summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk531
-rw-r--r--COPYING108
-rw-r--r--Makefile.am43
-rw-r--r--README61
-rwxr-xr-xautogen.sh12
-rw-r--r--benchmarks/.gitignore5
-rw-r--r--benchmarks/Makefile.am10
-rw-r--r--benchmarks/intel_upload_blit_large.c161
-rw-r--r--benchmarks/intel_upload_blit_large_gtt.c161
-rw-r--r--benchmarks/intel_upload_blit_large_map.c164
-rw-r--r--benchmarks/intel_upload_blit_small.c174
-rw-r--r--configure.ac139
-rw-r--r--debugger/.gitignore2
-rw-r--r--debugger/Makefile.am16
-rw-r--r--debugger/debug_rdata.c141
-rw-r--r--debugger/eudb.c606
-rw-r--r--debugger/system_routine/.gitignore10
-rw-r--r--debugger/system_routine/Makefile.am42
-rw-r--r--debugger/system_routine/eviction_macro.c48
-rwxr-xr-xdebugger/system_routine/pre_cpp.py123
-rw-r--r--debugger/system_routine/sr.g4a277
-rw-r--r--debugger/system_routine/test.g4a64
-rw-r--r--demos/.gitignore1
-rw-r--r--demos/Makefile.am7
-rw-r--r--demos/intel_sprite_on.c1068
-rw-r--r--lib/Makefile.am36
-rw-r--r--lib/debug.h92
-rw-r--r--lib/drmtest.c779
-rw-r--r--lib/drmtest.h114
-rw-r--r--lib/gen6_render.h1553
-rw-r--r--lib/gen7_render.h222
-rw-r--r--lib/i830_reg.h805
-rw-r--r--lib/i915_3d.h619
-rw-r--r--lib/i915_reg.h844
-rw-r--r--lib/instdone.c358
-rw-r--r--lib/instdone.h41
-rw-r--r--lib/intel_batchbuffer.c241
-rw-r--r--lib/intel_batchbuffer.h112
-rwxr-xr-xlib/intel_chipset.h270
-rw-r--r--lib/intel_dpio.c94
-rw-r--r--lib/intel_drm.c190
-rw-r--r--lib/intel_gpu_tools.h104
-rw-r--r--lib/intel_mmio.c264
-rw-r--r--lib/intel_pci.c89
-rw-r--r--lib/intel_reg.h3758
-rw-r--r--lib/intel_reg_map.c179
-rw-r--r--lib/rendercopy.h81
-rw-r--r--lib/rendercopy_gen6.c599
-rw-r--r--lib/rendercopy_gen7.c801
-rw-r--r--lib/rendercopy_i830.c229
-rw-r--r--lib/rendercopy_i915.c180
-rw-r--r--man/Makefile.am30
-rw-r--r--man/intel_audio_dump.man11
-rw-r--r--man/intel_bios_dumper.man14
-rw-r--r--man/intel_bios_reader.man15
-rw-r--r--man/intel_error_decode.man20
-rw-r--r--man/intel_gpu_top.man41
-rw-r--r--man/intel_gtt.man14
-rw-r--r--man/intel_infoframes.man26
-rw-r--r--man/intel_lid.man12
-rw-r--r--man/intel_panel_fitter.man50
-rw-r--r--man/intel_reg_dumper.man33
-rw-r--r--man/intel_reg_read.man15
-rw-r--r--man/intel_reg_snapshot.man15
-rw-r--r--man/intel_reg_write.man16
-rw-r--r--man/intel_stepping.man15
-rw-r--r--man/intel_upload_blit_large.man18
-rw-r--r--man/intel_upload_blit_large_gtt.man18
-rw-r--r--man/intel_upload_blit_large_map.man18
-rw-r--r--man/intel_upload_blit_small.man18
-rw-r--r--packaging/intel-gpu-tools.changes5
-rw-r--r--packaging/intel-gpu-tools.spec36
-rw-r--r--scripts/Makefile.am3
-rwxr-xr-xscripts/convert_itp.py17
-rwxr-xr-xscripts/display_debug.sh172
-rwxr-xr-xscripts/throttle.py67
-rwxr-xr-xscripts/who.sh13
-rw-r--r--shaders/ps/README1
-rw-r--r--shaders/ps/blit.g7a66
-rw-r--r--shaders/ps/neg1_test.g7a9
-rw-r--r--tests/.gitignore78
-rw-r--r--tests/Makefile.am148
-rwxr-xr-xtests/ZZ_check_dmesg11
-rwxr-xr-xtests/ZZ_hangman42
-rwxr-xr-xtests/check_drm_clients6
-rwxr-xr-xtests/debugfs_emon_crash16
-rwxr-xr-xtests/debugfs_reader9
-rwxr-xr-xtests/debugfs_wedged10
-rwxr-xr-xtests/drm_lib.sh32
-rw-r--r--tests/drm_vma_limiter.c110
-rw-r--r--tests/drm_vma_limiter_cached.c138
-rw-r--r--tests/drm_vma_limiter_cpu.c100
-rw-r--r--tests/drm_vma_limiter_gtt.c101
-rw-r--r--tests/flip_test.c317
-rw-r--r--tests/gem_bad_address.c81
-rw-r--r--tests/gem_bad_batch.c77
-rw-r--r--tests/gem_bad_blit.c121
-rw-r--r--tests/gem_bad_length.c132
-rw-r--r--tests/gem_basic.c90
-rw-r--r--tests/gem_cpu_concurrent_blit.c142
-rw-r--r--tests/gem_cs_prefetch.c169
-rw-r--r--tests/gem_ctx_bad_destroy.c109
-rw-r--r--tests/gem_ctx_bad_exec.c125
-rw-r--r--tests/gem_ctx_basic.c166
-rw-r--r--tests/gem_ctx_create.c64
-rw-r--r--tests/gem_ctx_exec.c139
-rw-r--r--tests/gem_double_irq_loop.c147
-rw-r--r--tests/gem_dummy_reloc_loop.c194
-rw-r--r--tests/gem_exec_bad_domains.c145
-rw-r--r--tests/gem_exec_blt.c263
-rw-r--r--tests/gem_exec_faulting_reloc.c226
-rw-r--r--tests/gem_exec_nop.c119
-rw-r--r--tests/gem_fence_thrash.c119
-rw-r--r--tests/gem_fenced_exec_thrash.c166
-rw-r--r--tests/gem_flink.c130
-rw-r--r--tests/gem_gtt_concurrent_blit.c145
-rw-r--r--tests/gem_gtt_cpu_tlb.c108
-rw-r--r--tests/gem_gtt_speed.c292
-rw-r--r--tests/gem_hang.c97
-rw-r--r--tests/gem_hangcheck_forcewake.c127
-rw-r--r--tests/gem_largeobject.c95
-rw-r--r--tests/gem_linear_blits.c250
-rw-r--r--tests/gem_mmap.c96
-rw-r--r--tests/gem_mmap_gtt.c161
-rw-r--r--tests/gem_mmap_offset_exhaustion.c96
-rw-r--r--tests/gem_partial_pwrite_pread.c263
-rw-r--r--tests/gem_pipe_control_store_loop.c184
-rw-r--r--tests/gem_pread_after_blit.c175
-rw-r--r--tests/gem_pwrite.c122
-rw-r--r--tests/gem_readwrite.c134
-rw-r--r--tests/gem_reg_read.c98
-rw-r--r--tests/gem_reloc_vs_gpu.c206
-rw-r--r--tests/gem_ring_sync_loop.c139
-rw-r--r--tests/gem_ringfill.c233
-rw-r--r--tests/gem_set_tiling_vs_blt.c269
-rw-r--r--tests/gem_set_tiling_vs_gtt.c137
-rw-r--r--tests/gem_set_tiling_vs_pwrite.c99
-rw-r--r--tests/gem_storedw_batches_loop.c173
-rw-r--r--tests/gem_storedw_loop_blt.c154
-rw-r--r--tests/gem_storedw_loop_bsd.c160
-rw-r--r--tests/gem_storedw_loop_render.c148
-rw-r--r--tests/gem_stress.c945
-rw-r--r--tests/gem_tiled_blits.c214
-rw-r--r--tests/gem_tiled_fence_blits.c174
-rw-r--r--tests/gem_tiled_partial_pwrite_pread.c294
-rw-r--r--tests/gem_tiled_pread.c237
-rw-r--r--tests/gem_tiled_pread_pwrite.c159
-rw-r--r--tests/gem_tiled_swapping.c145
-rw-r--r--tests/gem_unfence_active_buffers.c171
-rw-r--r--tests/gem_unref_active_buffers.c107
-rw-r--r--tests/gem_vmap_blits.c355
-rw-r--r--tests/gem_wait_render_timeout.c230
-rw-r--r--tests/gen3_mixed_blits.c541
-rw-r--r--tests/gen3_render_linear_blits.c400
-rw-r--r--tests/gen3_render_mixed_blits.c429
-rw-r--r--tests/gen3_render_tiledx_blits.c408
-rw-r--r--tests/gen3_render_tiledy_blits.c415
-rw-r--r--tests/getclient.c61
-rw-r--r--tests/getstats.c50
-rw-r--r--tests/getversion.c49
-rwxr-xr-xtests/module_reload41
-rw-r--r--tests/pass.pngbin0 -> 569 bytes
-rw-r--r--tests/prime_nv_api.c408
-rw-r--r--tests/prime_nv_pcopy.c1329
-rw-r--r--tests/prime_nv_test.c582
-rw-r--r--tests/prime_self_import.c123
-rwxr-xr-xtests/sysfs_edid_timing20
-rwxr-xr-xtests/sysfs_l3_parity27
-rw-r--r--tests/sysfs_rc6_residency.c119
-rw-r--r--tests/testdisplay.c765
-rw-r--r--tests/testdisplay.h35
-rw-r--r--tests/testdisplay_hotplug.c136
-rw-r--r--tools/.gitignore24
-rw-r--r--tools/Makefile.am42
-rw-r--r--tools/intel_audio_dump.c1969
-rw-r--r--tools/intel_backlight.c69
-rw-r--r--tools/intel_bios.h731
-rw-r--r--tools/intel_bios_dumper.c112
-rw-r--r--tools/intel_bios_reader.c947
-rw-r--r--tools/intel_disable_clock_gating.c71
-rw-r--r--tools/intel_dpio_read.c68
-rw-r--r--tools/intel_dpio_write.c67
-rw-r--r--tools/intel_dump_decode.c211
-rw-r--r--tools/intel_error_decode.c515
-rw-r--r--tools/intel_forcewaked.c106
-rwxr-xr-xtools/intel_gpu_abrt45
-rw-r--r--tools/intel_gpu_time.c110
-rw-r--r--tools/intel_gpu_top.c716
-rw-r--r--tools/intel_gtt.c134
-rw-r--r--tools/intel_infoframes.c1142
-rw-r--r--tools/intel_l3_parity.c159
-rw-r--r--tools/intel_lid.c144
-rw-r--r--tools/intel_panel_fitter.c344
-rw-r--r--tools/intel_reg_checker.c399
-rw-r--r--tools/intel_reg_dumper.c2246
-rw-r--r--tools/intel_reg_read.c142
-rw-r--r--tools/intel_reg_snapshot.c48
-rw-r--r--tools/intel_reg_write.c58
-rw-r--r--tools/intel_stepping.c294
199 files changed, 45501 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 00000000..3be34625
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,531 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_reg_write.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_reg_map.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+LOCAL_MODULE := intel_reg_write
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_reg_read.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_reg_map.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_reg_read
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_disable_clock_gating.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_disable_clock_gating
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_audio_dump.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_audio_dump
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_backlight.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_backlight
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_bios_dumper.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_bios_dumper
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_bios_reader.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_bios_reader
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+# Disabling intel_error_decode tool, since Android still does not have libdrm2.4.30
+#================
+#include $(CLEAR_VARS)
+#
+#LOCAL_SRC_FILES := \
+# tools/intel_error_decode.c \
+# lib/intel_pci.c \
+# lib/intel_gpu_tools.h \
+# tools/intel_reg.h \
+# lib/intel_batchbuffer.h \
+# lib/intel_batchbuffer.c \
+# lib/intel_mmio.c \
+# tools/intel_chipset.h \
+# lib/instdone.h \
+# lib/instdone.c \
+# tools/intel_decode.h \
+# lib/intel_drm.c
+#
+#
+#LOCAL_C_INCLUDES += \
+# $(LOCAL_PATH)/lib \
+# $(TOPDIR)hardware/intel/libdrm/include/drm \
+# $(TOPDIR)hardware/intel/libdrm/intel \
+# $(LOCAL_PATH)/../libpciaccess/include/
+#
+#LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+#LOCAL_CFLAGS += -DANDROID
+#LOCAL_CFLAGS += -std=c99
+#
+#
+#LOCAL_MODULE := intel_error_decode
+#LOCAL_MODULE_TAGS := optional
+#
+#LOCAL_SHARED_LIBRARIES := libpciaccess \
+# libdrm \
+# libdrm_intel
+#
+#include $(BUILD_EXECUTABLE)
+#
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_gpu_top.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h \
+ lib/instdone.h \
+ lib/instdone.c \
+ lib/intel_reg_map.c
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_gpu_top
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_gpu_time.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_gpu_time
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_gtt.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+
+LOCAL_MODULE := intel_gtt
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_stepping.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_stepping
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_reg_dumper.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_reg_dumper
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/intel_reg_snapshot.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+
+LOCAL_MODULE := intel_reg_snapshot
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ tools/forcewaked.c \
+ lib/intel_pci.c \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg.h \
+ lib/intel_batchbuffer.h \
+ lib/intel_batchbuffer.c \
+ lib/intel_mmio.c \
+ tools/intel_chipset.h \
+ lib/intel_reg_map.c \
+ lib/intel_drm.c
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := forcewaked
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess \
+ libdrm \
+ libdrm_intel
+
+include $(BUILD_EXECUTABLE)
+
+#================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ lib/intel_gpu_tools.h \
+ tools/intel_reg_checker.c \
+ lib/intel_pci.c \
+ lib/intel_mmio.c
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/lib \
+ $(TOPDIR)hardware/intel/libdrm/include/drm \
+ $(TOPDIR)hardware/intel/libdrm/intel \
+ $(LOCAL_PATH)/../libpciaccess/include/
+
+LOCAL_CFLAGS += -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
+LOCAL_CFLAGS += -DANDROID
+
+
+LOCAL_MODULE := intel_reg_checker
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SHARED_LIBRARIES := libpciaccess
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..b8f67535
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,108 @@
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Copyright 2003,2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Copyright © 2006-2011 Intel Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+
+Copyright © 2010 Red Hat, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Copyright © 2011 Daniel Vetter
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 00000000..5ea0fd87
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,43 @@
+# Copyright © 2005 Adam Jackson.
+# Copyright © 2009 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
+
+SUBDIRS = lib man tools scripts tests benchmarks demos
+
+if BUILD_SHADER_DEBUGGER
+SUBDIRS += debugger
+endif
+
+test:
+ ${MAKE} -C tests test
+
+MAINTAINERCLEANFILES = ChangeLog INSTALL
+
+.PHONY: ChangeLog INSTALL
+
+INSTALL:
+ $(INSTALL_CMD)
+
+ChangeLog:
+ $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog INSTALL
diff --git a/README b/README
new file mode 100644
index 00000000..92da60bb
--- /dev/null
+++ b/README
@@ -0,0 +1,61 @@
+This is a collection of tools for development and testing of the Intel DRM
+driver. There are many macro-level test suites that get used against our
+driver, including xtest, rendercheck, piglit, and oglconform, but failures
+from those can be difficult to track down to kernel changes, and many require
+complicated build procedures or specific testing environments to get useful
+results.
+
+Thus, intel-graphics-tools was a project I started to collect some low-level
+tools I intended to build.
+
+benchmarks/
+ This should be a collection of useful microbenchmarks. The hope is
+ that people can use these to tune some pieces of DRM code in relevant
+ ways.
+
+ The benchmarks require KMS to be enabled. When run with an X Server
+ running, they must be run as root to avoid the authentication
+ requirement.
+
+ Note that a few other microbenchmarks are in tests (like gem_gtt_speed).
+
+tests/
+ This is a set of automated tests to run against the DRM to validate
+ changes. Hopefully this can cover the relevant cases we need to
+ worry about, including backwards compatibility.
+
+ Run this tests with "make test" as root from this directory. Note that
+ no other drm clients (X server) may run.
+
+ "make test" only runs a default of test usefull for regression testing.
+ Other tests not run are:
+ - tests that might hang the gpu, see HANG in Makefile.am
+ - gem_stress, a stress test suite. Look at the source for all the
+ various options.
+ - testdisplay is only run in the default mode. testdisplay has tons of
+ options to test different kms functionality, again read the source of
+ the details.
+
+lib/
+ Common helper functions and headers used by the other tools.
+
+man/
+ Manpages, unfortunately rather incomplete.
+
+tools/
+ This is a collection of debugging tools that had previously been
+ built with the 2D driver but not shipped. Some distros were hacking
+ up the 2D build to ship them. Instead, here's a separate package for
+ people debugging the driver.
+
+ These tools generally must be run as root, safe for the ones that just
+ decode dumps.
+
+debugger/
+ This tool is to be used to do shader debugging. It acts like a
+ debug server accepting connections from debug clients such as
+ mesa. The connections is made with unix domain sockets, and at some
+ point it would be nice if this directory contained a library for
+ initiating connections with debug clients..
+
+ The debugger must be run as root: "sudo debugger/eudb"
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 00000000..904cd674
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore
new file mode 100644
index 00000000..ddea6f7e
--- /dev/null
+++ b/benchmarks/.gitignore
@@ -0,0 +1,5 @@
+intel_upload_blit_large
+intel_upload_blit_large_gtt
+intel_upload_blit_large_map
+intel_upload_blit_small
+# Please keep sorted alphabetically
diff --git a/benchmarks/Makefile.am b/benchmarks/Makefile.am
new file mode 100644
index 00000000..e2ad7845
--- /dev/null
+++ b/benchmarks/Makefile.am
@@ -0,0 +1,10 @@
+
+bin_PROGRAMS = \
+ intel_upload_blit_large \
+ intel_upload_blit_large_gtt \
+ intel_upload_blit_large_map \
+ intel_upload_blit_small
+
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib
+AM_CFLAGS = $(DRM_CFLAGS) $(CWARNFLAGS) $(CAIRO_CFLAGS)
+LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS)
diff --git a/benchmarks/intel_upload_blit_large.c b/benchmarks/intel_upload_blit_large.c
new file mode 100644
index 00000000..de0f6683
--- /dev/null
+++ b/benchmarks/intel_upload_blit_large.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/**
+ * Roughly simulates repeatedly uploading frames of images, by uploading
+ * the data all at once with pwrite, and then blitting it to another buffer.
+ *
+ * You might think of this like a movie player, but that wouldn't be entirely
+ * accurate, since the access patterns of the memory would be different
+ * (generally, smaller source image, upscaled, an thus different memory access
+ * pattern in both texel fetch for the stretching and the destination writes).
+ * However, some things like swfdec would be doing something like this since
+ * they compute their data in host memory and upload the full sw rendered
+ * frame.
+ *
+ * Additionally, those applications should be rendering at the screen refresh
+ * rate, while this test has no limits, and so can get itself into the
+ * working set larger than aperture size performance disaster.
+ *
+ * The current workload doing this path is pixmap upload for non-KMS.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+#define OBJECT_WIDTH 1280
+#define OBJECT_HEIGHT 720
+
+static double
+get_time_in_secs(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+static void
+do_render(drm_intel_bufmgr *bufmgr, struct intel_batchbuffer *batch,
+ drm_intel_bo *dst_bo, int width, int height)
+{
+ uint32_t data[width * height];
+ drm_intel_bo *src_bo;
+ int i;
+ static uint32_t seed = 1;
+
+ /* Generate some junk. Real workloads would be doing a lot more
+ * work to generate the junk.
+ */
+ for (i = 0; i < width * height; i++) {
+ data[i] = seed++;
+ }
+
+ /* Upload the junk. */
+ src_bo = drm_intel_bo_alloc(bufmgr, "src", sizeof(data), 4096);
+ drm_intel_bo_subdata(src_bo, 0, sizeof(data), data);
+
+ /* Render the junk to the dst. */
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ (width * 4) /* dst pitch */);
+ OUT_BATCH(0); /* dst x1,y1 */
+ OUT_BATCH((height << 16) | width); /* dst x2,y2 */
+ OUT_RELOC(dst_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0); /* src x1,y1 */
+ OUT_BATCH(width * 4); /* src pitch */
+ OUT_RELOC(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+
+ drm_intel_bo_unreference(src_bo);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int object_size = OBJECT_WIDTH * OBJECT_HEIGHT * 4;
+ double start_time, end_time;
+ drm_intel_bo *dst_bo;
+ drm_intel_bufmgr *bufmgr;
+ struct intel_batchbuffer *batch;
+ int i;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ dst_bo = drm_intel_bo_alloc(bufmgr, "dst", object_size, 4096);
+
+ /* Prep loop to get us warmed up. */
+ for (i = 0; i < 60; i++) {
+ do_render(bufmgr, batch, dst_bo, OBJECT_WIDTH, OBJECT_HEIGHT);
+ }
+ drm_intel_bo_wait_rendering(dst_bo);
+
+ /* Do the actual timing. */
+ start_time = get_time_in_secs();
+ for (i = 0; i < 200; i++) {
+ do_render(bufmgr, batch, dst_bo, OBJECT_WIDTH, OBJECT_HEIGHT);
+ }
+ drm_intel_bo_wait_rendering(dst_bo);
+ end_time = get_time_in_secs();
+
+ printf("%d iterations in %.03f secs: %.01f MB/sec\n", i,
+ end_time - start_time,
+ (double)i * OBJECT_WIDTH * OBJECT_HEIGHT * 4 / 1024.0 / 1024.0 /
+ (end_time - start_time));
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/benchmarks/intel_upload_blit_large_gtt.c b/benchmarks/intel_upload_blit_large_gtt.c
new file mode 100644
index 00000000..dc2733e2
--- /dev/null
+++ b/benchmarks/intel_upload_blit_large_gtt.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/**
+ * Roughly simulates repeatedly uploading frames of images, by uploading
+ * the data all at once with pwrite, and then blitting it to another buffer.
+ *
+ * You might think of this like a movie player, but that wouldn't be entirely
+ * accurate, since the access patterns of the memory would be different
+ * (generally, smaller source image, upscaled, an thus different memory access
+ * pattern in both texel fetch for the stretching and the destination writes).
+ * However, some things like swfdec would be doing something like this since
+ * they compute their data in host memory and upload the full sw rendered
+ * frame.
+ *
+ * Additionally, those applications should be rendering at the screen refresh
+ * rate, while this test has no limits, and so can get itself into the
+ * working set larger than aperture size performance disaster.
+ *
+ * The current workload doing this path is pixmap upload in 2D with KMS.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+#define OBJECT_WIDTH 1280
+#define OBJECT_HEIGHT 720
+
+static double
+get_time_in_secs(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+static void
+do_render(drm_intel_bufmgr *bufmgr, struct intel_batchbuffer *batch,
+ drm_intel_bo *dst_bo, int width, int height)
+{
+ uint32_t *data;
+ drm_intel_bo *src_bo;
+ int i;
+ static uint32_t seed = 1;
+
+ src_bo = drm_intel_bo_alloc(bufmgr, "src", width * height * 4, 4096);
+
+ drm_intel_gem_bo_map_gtt(src_bo);
+
+ data = src_bo->virtual;
+ for (i = 0; i < width * height; i++) {
+ data[i] = seed++;
+ }
+
+ drm_intel_gem_bo_unmap_gtt(src_bo);
+
+ /* Render the junk to the dst. */
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ (width * 4) /* dst pitch */);
+ OUT_BATCH(0); /* dst x1,y1 */
+ OUT_BATCH((height << 16) | width); /* dst x2,y2 */
+ OUT_RELOC(dst_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0); /* src x1,y1 */
+ OUT_BATCH(width * 4); /* src pitch */
+ OUT_RELOC(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+
+ drm_intel_bo_unreference(src_bo);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int object_size = OBJECT_WIDTH * OBJECT_HEIGHT * 4;
+ double start_time, end_time;
+ drm_intel_bo *dst_bo;
+ drm_intel_bufmgr *bufmgr;
+ struct intel_batchbuffer *batch;
+ int i;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ dst_bo = drm_intel_bo_alloc(bufmgr, "dst", object_size, 4096);
+
+ /* Prep loop to get us warmed up. */
+ for (i = 0; i < 60; i++) {
+ do_render(bufmgr, batch, dst_bo, OBJECT_WIDTH, OBJECT_HEIGHT);
+ }
+ drm_intel_bo_wait_rendering(dst_bo);
+
+ /* Do the actual timing. */
+ start_time = get_time_in_secs();
+ for (i = 0; i < 200; i++) {
+ do_render(bufmgr, batch, dst_bo, OBJECT_WIDTH, OBJECT_HEIGHT);
+ }
+ drm_intel_bo_wait_rendering(dst_bo);
+ end_time = get_time_in_secs();
+
+ printf("%d iterations in %.03f secs: %.01f MB/sec\n", i,
+ end_time - start_time,
+ (double)i * OBJECT_WIDTH * OBJECT_HEIGHT * 4 / 1024.0 / 1024.0 /
+ (end_time - start_time));
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/benchmarks/intel_upload_blit_large_map.c b/benchmarks/intel_upload_blit_large_map.c
new file mode 100644
index 00000000..0ca9e9de
--- /dev/null
+++ b/benchmarks/intel_upload_blit_large_map.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/**
+ * Roughly simulates repeatedly uploading frames of images, by uploading
+ * the data all at once with pwrite, and then blitting it to another buffer.
+ *
+ * You might think of this like a movie player, but that wouldn't be entirely
+ * accurate, since the access patterns of the memory would be different
+ * (generally, smaller source image, upscaled, an thus different memory access
+ * pattern in both texel fetch for the stretching and the destination writes).
+ * However, some things like swfdec would be doing something like this since
+ * they compute their data in host memory and upload the full sw rendered
+ * frame.
+ *
+ * Additionally, those applications should be rendering at the screen refresh
+ * rate, while this test has no limits, and so can get itself into the
+ * working set larger than aperture size performance disaster.
+ *
+ * The current workload we have that does large drm_intel_bo_map()
+ * uploads is texture upload for OpenGL (as it frequently is doing
+ * reformatting as it uploads the user's data, making bo_subdata less
+ * suitable)
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+#define OBJECT_WIDTH 1280
+#define OBJECT_HEIGHT 720
+
+static double
+get_time_in_secs(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+static void
+do_render(drm_intel_bufmgr *bufmgr, struct intel_batchbuffer *batch,
+ drm_intel_bo *dst_bo, int width, int height)
+{
+ uint32_t *data;
+ drm_intel_bo *src_bo;
+ int i;
+ static uint32_t seed = 1;
+
+ src_bo = drm_intel_bo_alloc(bufmgr, "src", width * height * 4, 4096);
+
+ drm_intel_bo_map(src_bo, 1);
+
+ data = src_bo->virtual;
+ for (i = 0; i < width * height; i++) {
+ data[i] = seed++;
+ }
+
+ drm_intel_bo_unmap(src_bo);
+
+ /* Render the junk to the dst. */
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ (width * 4) /* dst pitch */);
+ OUT_BATCH(0); /* dst x1,y1 */
+ OUT_BATCH((height << 16) | width); /* dst x2,y2 */
+ OUT_RELOC(dst_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0); /* src x1,y1 */
+ OUT_BATCH(width * 4); /* src pitch */
+ OUT_RELOC(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+
+ drm_intel_bo_unreference(src_bo);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int object_size = OBJECT_WIDTH * OBJECT_HEIGHT * 4;
+ double start_time, end_time;
+ drm_intel_bo *dst_bo;
+ drm_intel_bufmgr *bufmgr;
+ struct intel_batchbuffer *batch;
+ int i;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ dst_bo = drm_intel_bo_alloc(bufmgr, "dst", object_size, 4096);
+
+ /* Prep loop to get us warmed up. */
+ for (i = 0; i < 60; i++) {
+ do_render(bufmgr, batch, dst_bo, OBJECT_WIDTH, OBJECT_HEIGHT);
+ }
+ drm_intel_bo_wait_rendering(dst_bo);
+
+ /* Do the actual timing. */
+ start_time = get_time_in_secs();
+ for (i = 0; i < 200; i++) {
+ do_render(bufmgr, batch, dst_bo, OBJECT_WIDTH, OBJECT_HEIGHT);
+ }
+ drm_intel_bo_wait_rendering(dst_bo);
+ end_time = get_time_in_secs();
+
+ printf("%d iterations in %.03f secs: %.01f MB/sec\n", i,
+ end_time - start_time,
+ (double)i * OBJECT_WIDTH * OBJECT_HEIGHT * 4 / 1024.0 / 1024.0 /
+ (end_time - start_time));
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/benchmarks/intel_upload_blit_small.c b/benchmarks/intel_upload_blit_small.c
new file mode 100644
index 00000000..8ad25ad1
--- /dev/null
+++ b/benchmarks/intel_upload_blit_small.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/**
+ * Roughly simulates Mesa's current vertex buffer behavior: do a series of
+ * small pwrites on a moderately-sized buffer, then render using it.
+ *
+ * The vertex buffer uploads
+ *
+ * You might think of this like a movie player, but that wouldn't be entirely
+ * accurate, since the access patterns of the memory would be different
+ * (generally, smaller source image, upscaled, an thus different memory access
+ * pattern in both texel fetch for the stretching and the destination writes).
+ * However, some things like swfdec would be doing something like this since
+ * they compute their data in host memory and upload the full sw rendered
+ * frame.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+/* Happens to be 128k, the size of the VBOs used by i965's Mesa driver. */
+#define OBJECT_WIDTH 256
+#define OBJECT_HEIGHT 128
+
+static double
+get_time_in_secs(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
+}
+
+static void
+do_render(drm_intel_bufmgr *bufmgr, struct intel_batchbuffer *batch,
+ drm_intel_bo *dst_bo, int width, int height)
+{
+ uint32_t data[64];
+ drm_intel_bo *src_bo;
+ int i;
+ static uint32_t seed = 1;
+
+ src_bo = drm_intel_bo_alloc(bufmgr, "src", width * height * 4, 4096);
+
+ /* Upload some junk. Real workloads would be doing a lot more
+ * work to generate the junk.
+ */
+ for (i = 0; i < width * height;) {
+ int size, j;
+
+ /* Choose a size from 1 to 64 dwords to upload.
+ * Normal workloads have a distribution of sizes with a
+ * large tail (something in your scene's going to have a big
+ * pile of vertices, most likely), but I'm trying to get at
+ * the cost of the small uploads here.
+ */
+ size = random() % 64 + 1;
+ if (i + size > width * height)
+ size = width * height - i;
+
+ for (j = 0; j < size; j++)
+ data[j] = seed++;
+
+ /* Upload the junk. */
+ drm_intel_bo_subdata(src_bo, i * 4, size * 4, data);
+
+ i += size;
+ }
+
+ /* Render the junk to the dst. */
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ (width * 4) /* dst pitch */);
+ OUT_BATCH(0); /* dst x1,y1 */
+ OUT_BATCH((height << 16) | width); /* dst x2,y2 */
+ OUT_RELOC(dst_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0); /* src x1,y1 */
+ OUT_BATCH(width * 4); /* src pitch */
+ OUT_RELOC(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+
+ drm_intel_bo_unreference(src_bo);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int object_size = OBJECT_WIDTH * OBJECT_HEIGHT * 4;
+ double start_time, end_time;
+ drm_intel_bo *dst_bo;
+ drm_intel_bufmgr *bufmgr;
+ struct intel_batchbuffer *batch;
+ int i;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ dst_bo = drm_intel_bo_alloc(bufmgr, "dst", object_size, 4096);
+
+ /* Prep loop to get us warmed up. */
+ for (i = 0; i < 20; i++) {
+ do_render(bufmgr, batch, dst_bo, OBJECT_WIDTH, OBJECT_HEIGHT);
+ }
+ drm_intel_bo_wait_rendering(dst_bo);
+
+ /* Do the actual timing. */
+ start_time = get_time_in_secs();
+ for (i = 0; i < 1000; i++) {
+ do_render(bufmgr, batch, dst_bo, OBJECT_WIDTH, OBJECT_HEIGHT);
+ }
+ drm_intel_bo_wait_rendering(dst_bo);
+ end_time = get_time_in_secs();
+
+ printf("%d iterations in %.03f secs: %.01f MB/sec\n", i,
+ end_time - start_time,
+ (double)i * OBJECT_WIDTH * OBJECT_HEIGHT * 4 / 1024.0 / 1024.0 /
+ (end_time - start_time));
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 00000000..0ba7ce76
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,139 @@
+# Copyright 2005 Adam Jackson.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Process this file with autoconf to produce a configure script
+
+AC_PREREQ([2.60])
+AC_INIT([intel-gpu-tools],
+ [1.3],
+ [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
+ [intel-gpu-tools])
+
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+AC_USE_SYSTEM_EXTENSIONS
+AC_SYS_LARGEFILE
+AC_GNU_SOURCE
+
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
+AM_PATH_PYTHON([3],, [:])
+AM_MAINTAINER_MODE
+
+# Checks for functions, headers, structures, etc.
+AC_CHECK_HEADERS([termios.h])
+AC_CHECK_MEMBERS([struct sysinfo.totalram],[],[],[AC_INCLUDES_DEFAULT
+#include <sys/sysinfo.h>
+])
+AC_CHECK_FUNCS([swapctl])
+AC_CHECK_FUNCS([asprintf])
+
+# Initialize libtool
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+
+# Require X.Org macros 1.16 or later for XORG_TESTSET_CFLAG
+m4_ifndef([XORG_MACROS_VERSION],
+ [m4_fatal([must install xorg-macros 1.16 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.16)
+XORG_DEFAULT_OPTIONS
+
+PKG_CHECK_MODULES(DRM, [libdrm_intel >= 2.4.38 libdrm])
+PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10])
+
+# for dma-buf tests
+AC_ARG_ENABLE(nouveau,
+ AS_HELP_STRING([--disable-nouveau],
+ [Enable use of nouveau API for prime tests (default: enabled)]),
+ [NOUVEAU=$enableval], [NOUVEAU=yes])
+if test "x$NOUVEAU" = xyes; then
+ PKG_CHECK_MODULES(DRM_NOUVEAU, [libdrm_nouveau >= 2.4.33])
+ AC_DEFINE(HAVE_NOUVEAU, 1, [Have nouveau support])
+fi
+AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" = xyes])
+
+
+# for testdisplay
+PKG_CHECK_MODULES(CAIRO, cairo)
+PKG_CHECK_MODULES(LIBUDEV, [libudev], [udev=yes], [udev=no])
+if test x"$udev" = xyes; then
+ AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection])
+fi
+PKG_CHECK_MODULES(GLIB, glib-2.0)
+
+# -----------------------------------------------------------------------------
+# Configuration options
+# -----------------------------------------------------------------------------
+# Define a configure option for the shadder debugger
+AC_ARG_ENABLE(shader-debugger, AS_HELP_STRING([--enable-shader-debugger],
+ [Enable shader debugging support [autodetected]]),
+ [BUILD_SHADER_DEBUGGER="$enableval"], [BUILD_SHADER_DEBUGGER=auto])
+
+# Shadder debugger depends on python3, intel-genasm and objcopy
+if test "x$BUILD_SHADER_DEBUGGER" != xno; then
+ # Check Python 3 is installed
+ if test "$PYTHON" = ":" ; then
+ if test "x$BUILD_SHADER_DEBUGGER" = xyes; then
+ AC_MSG_ERROR([Shader debugger requested, python version 3 not found.])
+ else
+ BUILD_SHADER_DEBUGGER=no
+ fi
+ fi
+ # Check for the Intel Chipset assembler compiler
+ AC_PATH_PROGS([GEN4ASM], intel-gen4asm)
+ if test -z "$GEN4ASM" ; then
+ if test "x$BUILD_SHADER_DEBUGGER" = xyes; then
+ AC_MSG_ERROR([Shader debugger requested, but intel-gen4asm not found.])
+ else
+ BUILD_SHADER_DEBUGGER=no
+ fi
+ fi
+ # Check for the objcopy GNU binary utiliy command
+ AC_PATH_PROGS([OBJCOPY], objcopy)
+ if test -z "$OBJCOPY" ; then
+ if test "x$BUILD_SHADER_DEBUGGER" = xyes; then
+ AC_MSG_ERROR([Shader debugger requested, but objcopy command not found.])
+ else
+ BUILD_SHADER_DEBUGGER=no
+ fi
+ fi
+fi
+
+AM_CONDITIONAL(BUILD_SHADER_DEBUGGER, [test "x$BUILD_SHADER_DEBUGGER" != xno])
+# -----------------------------------------------------------------------------
+
+# To build multithread code, gcc uses -pthread, Solaris Studio cc uses -mt
+XORG_TESTSET_CFLAG([THREAD_CFLAGS], [-pthread], [-mt])
+AC_SUBST([THREAD_CFLAGS])
+
+AC_CONFIG_FILES([
+ Makefile
+ benchmarks/Makefile
+ demos/Makefile
+ lib/Makefile
+ man/Makefile
+ scripts/Makefile
+ tests/Makefile
+ tools/Makefile
+ debugger/Makefile
+ debugger/system_routine/Makefile
+])
+AC_OUTPUT
diff --git a/debugger/.gitignore b/debugger/.gitignore
new file mode 100644
index 00000000..873cd273
--- /dev/null
+++ b/debugger/.gitignore
@@ -0,0 +1,2 @@
+debug_rdata
+eudb
diff --git a/debugger/Makefile.am b/debugger/Makefile.am
new file mode 100644
index 00000000..d76e2ac6
--- /dev/null
+++ b/debugger/Makefile.am
@@ -0,0 +1,16 @@
+
+SUBDIRS = system_routine
+
+bin_PROGRAMS = eudb
+noinst_PROGRAMS = debug_rdata
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/lib
+
+AM_CFLAGS = \
+ $(DRM_CFLAGS) \
+ $(PCIACCESS_CFLAGS) \
+ $(CWARNFLAGS)
+
+LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS)
diff --git a/debugger/debug_rdata.c b/debugger/debug_rdata.c
new file mode 100644
index 00000000..f7dc4245
--- /dev/null
+++ b/debugger/debug_rdata.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "intel_gpu_tools.h"
+
+struct eu_rdata {
+ union {
+ struct {
+ uint8_t sendc_dep : 1;
+ uint8_t swh_dep : 1;
+ uint8_t pwc_dep : 1;
+ uint8_t n2_dep : 1;
+ uint8_t n1_dep : 1;
+ uint8_t n0_dep : 1;
+ uint8_t flag1_dep : 1;
+ uint8_t flag0_dep : 1;
+ uint8_t indx_dep : 1;
+ uint8_t mrf_dep : 1;
+ uint8_t dst_dep : 1;
+ uint8_t src2_dep : 1;
+ uint8_t src1_dep : 1;
+ uint8_t src0_dep : 1;
+ uint8_t mp_dep_pin : 1;
+ uint8_t sp_dep_pin : 1;
+ uint8_t fftid : 8;
+ uint8_t ffid : 4;
+ uint8_t instruction_valid : 1;
+ uint8_t thread_status : 3;
+ };
+ uint32_t dword;
+ } ud0;
+
+ union {
+ struct {
+ uint8_t mrf_addr : 4;
+ uint8_t dst_addr : 7;
+ uint8_t src2_addr : 7;
+ uint8_t src1_addr : 7;
+ uint8_t src0_addr : 7;
+ };
+ uint32_t dword;
+ } ud1;
+
+ union {
+ struct {
+ uint16_t exip : 12;
+ uint8_t opcode : 7;
+ uint8_t pwc : 8;
+ uint8_t instruction_valid : 1;
+ uint8_t mbz : 4;
+ };
+ uint32_t dword;
+ } ud2;
+};
+
+const char *thread_status[] =
+ {"INVALID", "invalid/no thread", "standby (dependency)", "INVALID", "Executing",
+ "INVALID" , "INVALID" , "INVALID"};
+
+static struct eu_rdata
+collect_rdata(int eu, int tid) {
+ struct eu_rdata rdata;
+
+ intel_register_write(0x7800, eu << 16 | (3 * tid) << 8);
+ rdata.ud0.dword = intel_register_read(0x7840);
+
+ intel_register_write(0x7800, eu << 16 | (3 * tid + 1) << 8);
+ rdata.ud1.dword = intel_register_read(0x7840);
+
+ intel_register_write(0x7800, eu << 16 | (3 * tid + 2) << 8);
+ rdata.ud2.dword = intel_register_read(0x7840);
+
+ return rdata;
+}
+static void
+print_rdata(struct eu_rdata rdata) {
+ printf("\t%s\n", thread_status[rdata.ud0.thread_status]);
+ printf("\tn1_dep: %d\n", rdata.ud0.n1_dep);
+ printf("\tpwc_dep: %d\n", rdata.ud0.pwc_dep);
+ printf("\tswh_dep: %d\n", rdata.ud0.swh_dep);
+ printf("\tsource 0 %x\n", rdata.ud1.src0_addr);
+ printf("\tsource 1 %x\n", rdata.ud1.src1_addr);
+ printf("\tsource 2 %x\n", rdata.ud1.src2_addr);
+ printf("\tdest %x\n", rdata.ud1.dst_addr);
+ printf("\tmrf %x\n", rdata.ud1.mrf_addr);
+ printf("\tIP: %x\n", rdata.ud2.exip);
+ printf("\topcode: %x\n", rdata.ud2.opcode);
+}
+
+static void
+find_stuck_threads(void)
+{
+ int i, j;
+ for (i = 0; i < 15; i++)
+ for (j = 0; j < 5; j++) {
+ struct eu_rdata rdata;
+ rdata = collect_rdata(i, j);
+ if (rdata.ud0.thread_status == 2 ||
+ rdata.ud0.thread_status == 4) {
+ printf("%d %d:\n", i, j);
+ print_rdata(rdata);
+ }
+ }
+}
+
+int main(int argc, char *argv[]) {
+ struct pci_device *pci_dev;
+ pci_dev = intel_get_pci_device();
+
+ intel_register_access_init(pci_dev, 1);
+ find_stuck_threads();
+// collect_rdata(atoi(argv[1]), atoi(argv[2]));
+ return 0;
+}
diff --git a/debugger/eudb.c b/debugger/eudb.c
new file mode 100644
index 00000000..228a143f
--- /dev/null
+++ b/debugger/eudb.c
@@ -0,0 +1,606 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ * Notes:
+ *
+ */
+
+#include <signal.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_chipset.h"
+#include "intel_bufmgr.h"
+#include "intel_gpu_tools.h"
+#include "intel_batchbuffer.h"
+#include "intel_debug.h"
+#include "debug.h"
+
+#define EU_ATT 0x7810
+#define EU_ATT_CLR 0x7830
+
+#define RSVD_EU -1
+#define RSVD_THREAD -1
+#define RSVD_ID EUID(-1, -1, -1)
+
+enum {
+ EBAD_SHMEM,
+ EBAD_PROTOCOL,
+ EBAD_MAGIC,
+ EBAD_WRITE
+};
+
+struct debuggee {
+ int euid;
+ int tid;
+ int fd;
+ int clr;
+ uint32_t reg;
+};
+
+struct debugger {
+ struct debuggee *debuggees;
+ int num_threads;
+ int real_num_threads;
+ int threads_per_eu;
+} *eu_info;
+
+drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+drm_intel_bo *scratch_bo;
+
+int handle;
+int drm_fd;
+int debug_fd = 0;
+const char *debug_file = "dump_debug.bin";
+int debug;
+int clear_waits;
+int shutting_down = 0;
+struct intel_debug_handshake dh;
+int force_clear = 0;
+uint32_t old_td_ctl;
+
+/*
+ * The docs are wrong about the attention clear bits. The clear bits are
+ * provided as part of the structure in case they change in future generations.
+ */
+#define EUID(eu, td, clear) \
+ { .euid = eu, .tid = td, .reg = EU_ATT, .fd = -1, .clr = clear }
+#define EUID2(eu, td, clear) \
+ { .euid = eu, .tid = td, .reg = EU_ATT + 4, .fd = -1, .clr = clear }
+struct debuggee gt1_debug_ids[] = {
+ RSVD_ID, RSVD_ID,
+ RSVD_ID, EUID(6, 3, 28), EUID(6, 2, 27), EUID(6, 1, 26), EUID(6, 0, 25),
+ RSVD_ID, EUID(5, 3, 23), EUID(5, 2, 22), EUID(5, 1, 21), EUID(5, 0, 20),
+ RSVD_ID, EUID(4, 3, 18), EUID(4, 2, 17), EUID(4, 1, 16), EUID(4, 0, 15),
+ RSVD_ID, EUID(2, 3, 13), EUID(2, 2, 12), EUID(2, 1, 11), EUID(2, 0, 10),
+ RSVD_ID, EUID(1, 3, 8), EUID(1, 2, 7), EUID(1, 1, 6), EUID(1, 0, 5),
+ RSVD_ID, EUID(0, 3, 3), EUID(0, 2, 2), EUID(0, 1, 1), EUID(0, 0, 0)
+};
+
+struct debuggee gt2_debug_ids[] = {
+ EUID(8, 1, 31), EUID(8, 0, 30),
+ EUID(6, 4, 29), EUID(6, 3, 28), EUID(6, 2, 27), EUID(6, 1, 26), EUID(6, 0, 25),
+ EUID(5, 4, 24), EUID(5, 3, 23), EUID(5, 2, 22), EUID(5, 1, 21), EUID(5, 0, 20),
+ EUID(4, 4, 19), EUID(4, 3, 18), EUID(4, 2, 17), EUID(4, 1, 16), EUID(4, 0, 15),
+ EUID(2, 4, 14), EUID(2, 3, 13), EUID(2, 2, 12), EUID(2, 1, 11), EUID(2, 0, 10),
+ EUID(1, 4, 9), EUID(1, 3, 8), EUID(1, 2, 7), EUID(1, 1, 6), EUID(1, 0, 5),
+ EUID(0, 4, 4), EUID(0, 3, 3), EUID(0, 2, 2), EUID(0, 1, 1), EUID(0, 0, 0),
+ RSVD_ID, RSVD_ID, RSVD_ID, RSVD_ID,
+ EUID2(14, 4, 27), EUID2(14, 3, 26), EUID2(14, 2, 25), EUID2(14, 1, 24), EUID2(14, 0, 23),
+ EUID2(13, 4, 22), EUID2(13, 3, 21), EUID2(13, 2, 20), EUID2(13, 1, 19), EUID2(13, 0, 18),
+ EUID2(12, 4, 17), EUID2(12, 3, 16), EUID2(12, 2, 15), EUID2(12, 1, 14), EUID2(12, 0, 13),
+ EUID2(10, 4, 12), EUID2(10, 3, 11), EUID2(10, 2, 10), EUID2(10, 1, 9), EUID2(10, 0, 8),
+ EUID2(9, 4, 7), EUID2(9, 3, 6), EUID2(9, 2, 5), EUID2(9, 1, 4), EUID2(9, 0, 3),
+ EUID2(8, 4, 2), EUID2(8, 3, 1), EUID2(8, 2, 0)
+};
+
+struct debugger gt1 = {
+ .debuggees = gt1_debug_ids,
+ .num_threads = 32,
+ .real_num_threads = 24,
+ .threads_per_eu = 4
+};
+
+struct debugger gt2 = {
+ .debuggees = gt2_debug_ids,
+ .num_threads = 64,
+ .real_num_threads = 60,
+ .threads_per_eu = 5
+};
+
+static void
+dump_debug(void *buf, size_t count) {
+ if (!debug_fd)
+ debug_fd = open(debug_file, O_CREAT | O_WRONLY | O_TRUNC, S_IRWXO);
+
+ write(debug_fd, buf, count);
+}
+
+static volatile void *
+map_debug_buffer(void) {
+ int ret;
+
+ ret = drm_intel_bo_map(scratch_bo, 0);
+ assert(ret == 0);
+ return scratch_bo->virtual;
+}
+
+static void
+unmap_debug_buffer(void) {
+ drm_intel_bo_unmap(scratch_bo);
+}
+
+static int
+wait_for_attn(int timeout, int *out_bits) {
+ int step = 1;
+ int eus_waiting = 0;
+ int i,j;
+
+ if (timeout <= 0) {
+ timeout = 1;
+ step = 0;
+ }
+
+ for (i = 0; i < timeout; i += step) {
+ for (j = 0; j < 8; j += 4) {
+ uint32_t attn = intel_register_read(EU_ATT + j);
+ if (attn) {
+ int bit = 0;
+ while( (bit = ffs(attn)) != 0) {
+ bit--; // ffs is 1 based
+ assert(bit >= 0);
+ out_bits[eus_waiting] = bit + (j * 8);
+ attn &= ~(1 << bit);
+ eus_waiting++;
+ }
+ }
+ }
+
+ if (intel_register_read(EU_ATT + 8) ||
+ intel_register_read(EU_ATT + 0xc)) {
+ fprintf(stderr, "Unknown attention bits\n");
+ }
+
+ if (eus_waiting || shutting_down)
+ break;
+ }
+
+ return eus_waiting;
+}
+
+#define eu_fd(bit) eu_info->debuggees[bit].fd
+#define eu_id(bit) eu_info->debuggees[bit].euid
+#define eu_tid(bit) eu_info->debuggees[bit].tid
+static struct eu_state *
+find_eu_shmem(int bit, volatile uint8_t *buf) {
+ struct per_thread_data {
+ uint8_t ____[dh.per_thread_scratch];
+ }__attribute__((packed)) *data;
+ struct eu_state *eu;
+ int mem_tid, mem_euid, i;
+
+ data = (struct per_thread_data *)buf;
+ for(i = 0; i < eu_info->num_threads; i++) {
+ eu = (struct eu_state *)&data[i];
+ mem_tid = eu->sr0 & 0x7;
+ mem_euid = (eu->sr0 >> 8) & 0xf;
+ if (mem_tid == eu_tid(bit) && mem_euid == eu_id(bit))
+ break;
+ eu = NULL;
+ }
+
+ return eu;
+}
+
+#define GRF_CMP(a, b) memcmp(a, b, sizeof(grf))
+#define GRF_CPY(a, b) memcpy(a, b, sizeof(grf))
+static int
+verify(struct eu_state *eu) {
+ if (GRF_CMP(eu->version, protocol_version)) {
+ if (debug) {
+ printf("Bad EU protocol version %x %x\n",
+ ((uint32_t *)&eu->version)[0],
+ DEBUG_PROTOCOL_VERSION);
+ dump_debug((void *)eu, sizeof(*eu));
+ }
+ return -EBAD_PROTOCOL;
+ }
+
+ if (GRF_CMP(eu->state_magic, eu_msg)) {
+ if (debug) {
+ printf("Bad EU state magic %x %x\n",
+ ((uint32_t *)&eu->state_magic)[0],
+ ((uint32_t *)&eu->state_magic)[1]);
+ dump_debug((void *)eu, sizeof(*eu));
+ }
+ return -EBAD_MAGIC;
+ } else {
+ GRF_CPY(eu->state_magic, cpu_ack);
+ }
+
+ eu->sr0 = RSVD_EU << 8 | RSVD_THREAD;
+ return 0;
+}
+
+static int
+collect_data(int bit, volatile uint8_t *buf) {
+ struct eu_state *eu;
+ ssize_t num;
+ int ret;
+
+ assert(eu_id(bit) != RSVD_EU);
+
+ if (eu_fd(bit) == -1) {
+ char name[128];
+ sprintf(name, "dump_eu_%02d_%d.bin", eu_id(bit), eu_tid(bit));
+ eu_fd(bit) = open(name, O_CREAT | O_WRONLY | O_TRUNC, S_IRWXO);
+ if (eu_fd(bit) == -1)
+ return -1;
+ }
+
+ eu = find_eu_shmem(bit, buf);
+
+ if (eu == NULL) {
+ if (debug)
+ printf("Bad offset %d %d\n", eu_id(bit), eu_tid(bit));
+ return -EBAD_SHMEM;
+ }
+
+ ret = verify(eu);
+ if (ret)
+ return ret;
+
+ num = write(eu_fd(bit), (void *)eu, sizeof(*eu));
+ if (num != sizeof(*eu)) {
+ perror("unhandled write failure");
+ return EBAD_WRITE;
+ }
+
+
+ return 0;
+}
+
+static void
+clear_attn(int bit) {
+#if 0
+/*
+ * This works but doesn't allow for easily changed clearing bits
+ */
+static void
+clear_attn_old(int bit) {
+ int bit_to_clear = bit % 32;
+ bit_to_clear = 31 - bit_to_clear;
+ intel_register_write(0x7830 + (bit/32) * 4, 0);
+ intel_register_write(0x7830 + (bit/32) * 4, 1 << bit_to_clear);
+}
+#else
+ if (!force_clear) {
+ int bit_to_clear;
+ bit_to_clear = eu_info->debuggees[bit].clr;
+ intel_register_write(EU_ATT_CLR + (bit/32) * 4, 0);
+ intel_register_write(EU_ATT_CLR + (bit/32) * 4, 1 << bit_to_clear);
+ } else {
+ intel_register_write(EU_ATT_CLR + 0, 0);
+ intel_register_write(EU_ATT_CLR + 4, 0);
+ intel_register_write(EU_ATT_CLR + 0, 0xffffffff);
+ intel_register_write(EU_ATT_CLR + 4, 0xffffffff);
+ }
+#endif
+}
+
+static void
+db_shutdown(int sig) {
+ shutting_down = 1;
+ printf("Shutting down...\n");
+}
+
+static void
+die(int reason) {
+ int i = 0;
+
+ intel_register_write(EU_ATT_CLR, 0);
+ intel_register_write(EU_ATT_CLR + 4, 0);
+
+ if (debug_fd)
+ close(debug_fd);
+
+ for (i = 0; i < eu_info->num_threads; i++) {
+ if (eu_info->debuggees[i].fd != -1)
+ close(eu_info->debuggees[i].fd);
+ }
+
+ unmap_debug_buffer();
+
+ if (old_td_ctl)
+ intel_register_write(TD_CTL, old_td_ctl);
+ intel_register_access_fini();
+ exit(reason);
+}
+
+static int
+identify_device(int devid) {
+ switch(devid) {
+ case PCI_CHIP_SANDYBRIDGE_GT1:
+ case PCI_CHIP_SANDYBRIDGE_M_GT1:
+ case PCI_CHIP_SANDYBRIDGE_S:
+ eu_info = &gt1;
+ break;
+ case PCI_CHIP_SANDYBRIDGE_GT2:
+ case PCI_CHIP_SANDYBRIDGE_GT2_PLUS:
+ case PCI_CHIP_SANDYBRIDGE_M_GT2:
+ case PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS:
+ eu_info = &gt2;
+ break;
+ default:
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+parse_data(const char *file_name) {
+ struct eu_state *eu_state = NULL;
+ struct stat st;
+ int fd = -1;
+ int ret, i, elements;
+
+ fd = open(file_name, O_RDONLY);
+ if (fd == -1) {
+ perror("open");
+ goto out;
+ }
+
+ ret = fstat(fd, &st);
+ if (ret == -1) {
+ perror("fstat");
+ goto out;
+ }
+
+ elements = st.st_size / sizeof(struct eu_state);
+ if (elements == 0) {
+ fprintf(stderr, "File not big enough for 1 entry\n");
+ goto out;
+ }
+
+ eu_state = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (eu_state == MAP_FAILED) {
+ perror("mmap");
+ goto out;
+ }
+
+ for(i = 0; i < elements; i++) {
+ printf("AIP: ");
+ printf("%x\n", ((uint32_t *)eu_state[i].cr0)[2]);
+ }
+out:
+ if (eu_state)
+ munmap(eu_state, st.st_size);
+ if (fd != -1)
+ close(fd);
+}
+
+static int
+wait_for_scratch_bo(void) {
+ struct sockaddr_un addr;
+ uint32_t version;
+ int fd, ret, handle = -1;
+
+ assert(sizeof(version) == sizeof(dh.version));
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1)
+ return -1;
+
+ /* Clean up previous runs */
+ remove(SHADER_DEBUG_SOCKET);
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, SHADER_DEBUG_SOCKET, sizeof(addr.sun_path) - 1);
+
+ ret = bind(fd, (const struct sockaddr *)&addr, sizeof(addr));
+ if (ret == -1) {
+ perror("listen");
+ return -1;
+ }
+
+ ret = listen(fd, 1);
+ if (ret == -1) {
+ perror("listen");
+ goto done;
+ }
+
+ while(1) {
+ int client_fd;
+ size_t count;
+ char ack[] = DEBUG_HANDSHAKE_ACK;
+
+ client_fd = accept(fd, NULL, NULL);
+ if (client_fd == -1) {
+ perror("accept");
+ goto done;
+ }
+
+ count = read(client_fd, &version, sizeof(version));
+ if (count != sizeof(version)) {
+ perror("read version");
+ goto loop_out;
+ }
+
+ if (version != DEBUG_HANDSHAKE_VERSION) {
+ fprintf(stderr, "Bad debug handshake\n");
+ goto loop_out;
+ }
+
+ count = read(client_fd, ((char *)&dh) + 1, sizeof(dh) - 1);
+ if (count != sizeof(dh) - 1) {
+ perror("read handshake");
+ goto loop_out;
+ }
+
+ count = write(client_fd, ack, sizeof(ack));
+ if (count != sizeof(ack)) {
+ perror("write ack");
+ goto loop_out;
+ }
+ handle = dh.flink_handle;
+ if (debug > 0) {
+ printf("Handshake completed successfully\n"
+ "\tprotocol version = %d\n"
+ "\tflink handle = %d\n"
+ "\tper thread scratch = %x\n", version,
+ dh.flink_handle, dh.per_thread_scratch);
+ }
+
+ loop_out:
+ close(client_fd);
+ break;
+ }
+
+done:
+ close(fd);
+ return handle;
+}
+
+static void
+setup_hw_bits(void)
+{
+ intel_register_write(INST_PM, GEN6_GLOBAL_DEBUG_ENABLE |
+ GEN6_GLOBAL_DEBUG_ENABLE << 16);
+ old_td_ctl = intel_register_read(GEN6_TD_CTL);
+ intel_register_write(GEN6_TD_CTL, GEN6_TD_CTL_FORCE_TD_BKPT);
+}
+
+int main(int argc, char* argv[]) {
+ struct pci_device *pci_dev;
+ volatile uint8_t *scratch = NULL;
+ int bits[64];
+ int devid = -1, opt;
+
+ while ((opt = getopt(argc, argv, "cdr:pf?h")) != -1) {
+ switch (opt) {
+ case 'c':
+ clear_waits = 1;
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case 'r':
+ parse_data(optarg);
+ exit(0);
+ break;
+ case 'p':
+ devid = atoi(optarg);
+ break;
+ case 'f':
+ force_clear = 1;
+ break;
+ case '?':
+ case 'h':
+ default:
+ exit(0);
+ }
+ }
+
+ pci_dev = intel_get_pci_device();
+ if (devid != -1);
+ devid = pci_dev->device_id;
+ if (identify_device(devid)) {
+ abort();
+ }
+
+ assert(intel_register_access_init(pci_dev, 1) == 0);
+
+ memset(bits, -1, sizeof(bits));
+ /*
+ * These events have to occur before the SR runs, or we need
+ * non-blocking versions of the functions.
+ */
+ if (!clear_waits) {
+ int handle;
+ drm_fd = drm_open_any();
+ bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
+
+ setup_hw_bits();
+
+ /* We are probably root, make files world friendly */
+ umask(0);
+ handle = wait_for_scratch_bo();
+ if (handle == -1) {
+ printf("No handle from mesa, please enter manually: ");
+ if (fscanf(stdin, "%1d", &handle) == 0)
+ exit(1);
+ }
+ scratch_bo = intel_bo_gem_create_from_name(bufmgr, "scratch", handle);
+ if (scratch_bo == NULL) {
+ fprintf(stderr, "Couldn't flink buffer\n");
+ abort();
+ }
+ signal(SIGINT, db_shutdown);
+ printf("Press Ctrl-C to stop\n");
+ } else {
+ int time = force_clear ? 0 : 20000;
+ while (wait_for_attn(time, bits)) {
+ clear_attn(bits[0]);
+ memset(bits, -1, sizeof(bits));
+ }
+ die(0);
+ }
+
+ scratch = map_debug_buffer();
+ while (shutting_down == 0) {
+ int num_events, i;
+
+ memset(bits, -1, sizeof(bits));
+ num_events = wait_for_attn(-1, bits);
+ if (num_events == 0)
+ break;
+
+ for (i = 0; i < num_events; i++) {
+ assert(bits[i] < 64 && bits[i] >= 0);
+ if (collect_data(bits[i], scratch)) {
+ bits[i] = -1;
+ continue;
+ }
+ clear_attn(bits[i]);
+ }
+ }
+
+ die(0);
+ return 0;
+}
diff --git a/debugger/system_routine/.gitignore b/debugger/system_routine/.gitignore
new file mode 100644
index 00000000..d19500cf
--- /dev/null
+++ b/debugger/system_routine/.gitignore
@@ -0,0 +1,10 @@
+evict.h
+eviction_macro
+sr
+sr.asm
+sr.c
+sr.cpp
+tiny
+tiny.asm
+tiny.c
+tiny.cpp
diff --git a/debugger/system_routine/Makefile.am b/debugger/system_routine/Makefile.am
new file mode 100644
index 00000000..2576e2aa
--- /dev/null
+++ b/debugger/system_routine/Makefile.am
@@ -0,0 +1,42 @@
+
+noinst_PROGRAMS = eviction_macro sr tiny
+nodist_sr_SOURCES = sr.c
+nodist_tiny_SOURCES = tiny.c
+
+GEN4ASM_FLAGS = -g6 -a -b
+ASM_CPPFLAGS = \
+ -x assembler-with-cpp \
+ -P -DGEN_ASM -DSANDYBRIDGE \
+ -I$(top_srcdir)/lib \
+ -I$(builddir)
+
+evict.h : eviction_macro
+ $(builddir)/eviction_macro > evict.h
+
+sr.cpp : sr.g4a
+ $(srcdir)/pre_cpp.py $(srcdir)/sr.g4a > $@.tmp && mv $@.tmp $@
+sr.asm : sr.cpp evict.h
+ $(CPP) $(ASM_CPPFLAGS) -o $@ sr.cpp
+sr.c: sr.asm
+ $(GEN4ASM) $(GEN4ASM_FLAGS) sr.asm -o $@
+sr.o : sr.c
+ $(CC) -c -o $@ sr.c
+sr : sr.o
+ $(OBJCOPY) -O binary -K gen_eu_bytes sr.o $@
+
+# Test.g4a is the simplest possible system routine we can run on the GPU
+# without actually hanging the system. The system routine kernel is very
+# simple and doesn't depend on any external communication to run.
+tiny.cpp : test.g4a
+ $(srcdir)/pre_cpp.py $(srcdir)/test.g4a > $@.tmp && mv $@.tmp $@
+tiny.asm : tiny.cpp
+ $(CPP) $(ASM_CPPFLAGS) -o $@ tiny.cpp
+tiny.c: tiny.asm
+ $(GEN4ASM) $(GEN4ASM_FLAGS) tiny.asm -o $@
+tiny.o : tiny.c
+ $(CC) -c -o $@ tiny.c
+tiny : tiny.o
+ $(OBJCOPY) -O binary -K gen_eu_bytes tiny.o $@
+
+CLEANFILES = evict.h sr.cpp sr.asm sr.c tiny.cpp tiny.asm tiny.c
+EXTRA_DIST = pre_cpp.py sr.g4a test.g4a
diff --git a/debugger/system_routine/eviction_macro.c b/debugger/system_routine/eviction_macro.c
new file mode 100644
index 00000000..1da22332
--- /dev/null
+++ b/debugger/system_routine/eviction_macro.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <stdio.h>
+
+#define START 0x100
+#define END ((128 << 10) / 4)
+
+int main(int argc, char *argv[]) {
+ int i;
+ printf("#ifdef SANDYBRIDGE\n");
+ printf("#define EVICT_CACHE \\\n");
+ printf("\tmov (1) m0.5:ud g0.5:ud FLAGS; \\\n");
+ for (i = START; i < END - 8; i+=0x8) {
+ printf("\tmov (1) m0.2:ud 0x%04x:ud FLAGS; \\\n", i);
+ printf("\tWRITE_SCRATCH4(m0); \\\n");
+ }
+
+ printf("\tmov (1) m0.2:ud 0x%04x:ud FLAGS; \\\n", i);
+ printf("\tWRITE_SCRATCH4(m0)\n");
+ printf("#else\n");
+ printf("#define EVICT_CACHE\n");
+ printf("#endif\n");
+}
diff --git a/debugger/system_routine/pre_cpp.py b/debugger/system_routine/pre_cpp.py
new file mode 100755
index 00000000..effea0e2
--- /dev/null
+++ b/debugger/system_routine/pre_cpp.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python3
+
+# Copyright © 2011 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# Authors:
+# Ben Widawsky <ben@bwidawsk.net>
+
+#very limited C-like preprocessor
+
+#limitations:
+# no macro substitutions
+# no multiline definitions
+# divide operator is //
+
+import sys,re
+
+file = open(sys.argv[1], "r")
+
+lines = file.readlines()
+len(lines)
+out = dict()
+defines = dict()
+
+count = 0
+#create a dict for our output
+for line in lines:
+ out[count] = line
+ count = count + 1
+
+#done is considered #define <name> <number>
+def is_done(string):
+ m = re.match("#define\s+(\w+?)\s+([a-fA-F0-9\-]+?)\s*$", string)
+ return m
+
+#skip macros, the real cpp will handle it
+def skip(string):
+ #macro
+ m = re.match("#define\s+\w+\(.+", string)
+ return m != None
+
+#put contants which are done being evaluated into the dictionary
+def easy_constants():
+ ret = 0
+ for lineno, string in out.items():
+ if skip(string):
+ continue
+ m = is_done(string)
+ if m != None:
+ key = m.group(1)
+ value = m.group(2)
+ if not key in defines:
+ defines[key] = int(eval(value))
+ ret = 1
+ return ret
+
+#replace names with dictionary values
+def simple_replace():
+ ret = 0
+ for lineno, string in out.items():
+ if skip(string):
+ continue
+ for key, value in defines.items():
+ if is_done(string):
+ continue
+ s = re.subn(key, repr(value), string)
+ if s[1] > 0:
+ out[lineno] = s[0]
+ ret = s[1]
+ return ret
+
+#evaluate expressions to try to simplify them
+def collapse_constants():
+ ret = 0
+ for lineno, string in out.items():
+ if skip(string):
+ continue
+ if is_done(string):
+ continue
+ m = re.match("#define\s+(.+?)\s+(.+)$", string)
+ if m != None:
+ try:
+ out[lineno] = "#define " + m.group(1) + " " + repr(eval(m.group(2)))
+ ret = 1
+ except NameError as ne:
+ #this happens before a variable is resolved in simple_replace
+ continue
+ except SyntaxError:
+ #this happens with something like #define foo bar, which the
+ #regular cpp can handle
+ continue
+ except:
+ raise KeyboardInterrupt
+ return ret;
+
+while True:
+ ret = 0
+ ret += easy_constants()
+ ret += simple_replace()
+ ret += collapse_constants()
+ if ret == 0:
+ break;
+
+for lineno, string in out.items():
+ print(string.rstrip())
diff --git a/debugger/system_routine/sr.g4a b/debugger/system_routine/sr.g4a
new file mode 100644
index 00000000..a70e7712
--- /dev/null
+++ b/debugger/system_routine/sr.g4a
@@ -0,0 +1,277 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include "debug.h"
+#include "evict.h"
+
+#define CR0_0_ME_STATE_CTRL (1 << 31)
+#define CR0_0_BP_SUPPRESS (1 << 15)
+#define CR0_0_SPF_EN (1 << 2)
+#define CR0_0_ACC_DIS (1 << 1)
+#define CR0_1_BES_CTRL (1 << 31)
+#define CR0_1_HALT_CTRL (1 << 30)
+#define CR0_1_SOFT_EXCEPTION_CTRL (1 << 29)
+#define CR0_1_ILLGL_OP_STS (1 << 28)
+#define CR0_1_STACK_OVRFLW_STS (1 << 27)
+
+#define CR0_0_ENTRY_UNMASK (CR0_0_SPF_EN | CR0_0_ACC_DIS)
+// TODO: Need to fix this for non breakpoint case
+#define CR0_1_ENTRY_UNMASK ~(CR0_1_BES_CTRL)
+#define CR0_0_RETURN_MASK ~(CR0_0_ME_STATE_CTRL | CR0_0_SPF_EN | CR0_0_ACC_DIS)
+
+// TODO: not sure how to make this not hardcoded
+#define PER_THREAD_SCRATCH_SIZE (1 << 20)
+#define PER_THREAD_QWORDS (PER_THREAD_SCRATCH_SIZE >> 4)
+
+/* Should get this from brw_defines.h */
+#define BRW_DATAPORT_OWORD_BLOCK_2_OWORDS 2
+#define BRW_DATAPORT_OWORD_BLOCK_4_OWORDS 3
+#define BRW_DATAPORT_OWORD_BLOCK_8_OWORDS 4
+#define GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE 8
+#define BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ 0
+
+/* desc field, ie. dword3 6.3.66.2 and 2.11.2.1.4 */
+#define SEND_MLEN_5 (5<<25)
+#define SEND_MLEN_3 (3<<25)
+#define SEND_MLEN_2 (2<<25)
+#define SEND_MLEN_1 (1<<25)
+#define SEND_RLEN_1 (1<<20)
+#define SEND_RLEN_0 (0<<20)
+#define SEND_HEADER_PRESENT (1<<19)
+#define SEND_WRITE_COMMIT (1<<17)
+#define SEND_TYPE_WRITE (GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE<<13)
+#define SEND_TYPE_READ (BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ<<13)
+#define SEND_BLOCK_SIZE1 (BRW_DATAPORT_OWORD_BLOCK_2_OWORDS<<8)
+#define SEND_BLOCK_SIZE2 (BRW_DATAPORT_OWORD_BLOCK_4_OWORDS<<8)
+#define SEND_BLOCK_SIZE4 (BRW_DATAPORT_OWORD_BLOCK_8_OWORDS<<8)
+#define SEND_BINDING_TABLE (255<<0)
+// No write commit
+#define WRITE_DESC1_XXX SEND_BINDING_TABLE | SEND_BLOCK_SIZE1 | SEND_TYPE_WRITE | SEND_HEADER_PRESENT | SEND_MLEN_2
+#define WRITE_DESC1_WC SEND_BINDING_TABLE | SEND_BLOCK_SIZE1 | SEND_TYPE_WRITE | SEND_HEADER_PRESENT | SEND_MLEN_2 | SEND_WRITE_COMMIT
+#define WRITE_DESC2 SEND_BINDING_TABLE | SEND_BLOCK_SIZE2 | SEND_TYPE_WRITE | SEND_HEADER_PRESENT | SEND_MLEN_3
+#define WRITE_DESC4 SEND_BINDING_TABLE | SEND_BLOCK_SIZE4 | SEND_TYPE_WRITE | SEND_HEADER_PRESENT | SEND_MLEN_5
+#define RECV_DESC1 SEND_BINDING_TABLE | SEND_BLOCK_SIZE1 | SEND_TYPE_READ | SEND_HEADER_PRESENT | SEND_MLEN_1 | SEND_RLEN_1
+//#define SEND_DESC1 0x40902FF
+#define SEND_DESC1_WC 0x40b02FF
+
+/* ex_desc field 6.3.66.2 */
+#define SEND_DP_RENDER_CACHE (5<<0)
+#define SEND_EOT (1<<5)
+#define SEND_EX_DESC SEND_DP_RENDER_CACHE
+
+/**
+ * WRITE_SCRATCH1 - Write 2 owords.
+ * cdst.2 - offset
+ * cdst.5 - per thread scratch base, relative to gsba??
+ * cdst+1 - data to be written.
+ */
+#define WRITE_SCRATCH1(cdst) \
+ send (16) null cdst SEND_EX_DESC WRITE_DESC1_XXX FLAGS
+#define WRITE_SCRATCH1_WC(cdst) \
+ send (16) g1 cdst SEND_EX_DESC WRITE_DESC1_WC FLAGS
+#define WRITE_SCRATCH2(cdst) \
+ send (16) null cdst SEND_EX_DESC WRITE_DESC2 FLAGS
+#define WRITE_SCRATCH4(cdst) \
+ send (16) null cdst SEND_EX_DESC WRITE_DESC4 FLAGS
+
+/**
+ * READ_SCRATCH1 - Read 2 owords.
+ * cdst.2 - offset
+ * cdst.5 - per thread scratch base, relative to gsba??
+ * grf - register where read data is populated.
+ */
+#define READ_SCRATCH1(grf, cdst) \
+ send (16) grf:ud cdst SEND_EX_DESC RECV_DESC1 FLAGS
+
+/**
+ * SET_OFFSET - setup mrf for the given offset prior to a send instruction.
+ * mrf - message register to be used as the header.
+ * offset - offset.
+ *
+ * If a WRITE_SCRATCH follows, mrf+1 -> mrf+1+n should contain the data to be
+ * written.
+ */
+#define SET_OFFSET(mrf, offset) \
+ mov (1) mrf.5:ud g0.5:ud FLAGS; \
+ mov (1) mrf.2:ud offset:ud FLAGS
+
+/**
+ * SAVE_CRF - save the control register
+ * clobbers: m0.2, m0.5
+ */
+#define CR_OFFSET 0x40
+#define SAVE_CRF \
+ SET_OFFSET(m0, CR_OFFSET); \
+ mov (8) m1:ud 0xdeadbeef:ud FLAGS; \
+ mov (1) m1.0:ud cr0.0 FLAGS; \
+ mov (1) m1.1:ud cr0.1 FLAGS; \
+ mov (1) m1.2:ud cr0.2 FLAGS; \
+ mov (1) m1.3:ud sr0:ud FLAGS; \
+ WRITE_SCRATCH1(m0)
+
+/*
+ * clobbers: m0.2, m0.5
+ */
+#define STORE_GRF(grf, offset) \
+ SET_OFFSET(m0, offset); \
+ mov (8) m1:ud grf:ud FLAGS; \
+ WRITE_SCRATCH1(m0)
+
+/*
+ * clobbers: m0.2, m0.5
+ */
+#define LOAD_GRF(grf, offset) \
+ SET_OFFSET(m0, offset); \
+ READ_SCRATCH1(grf, m0)
+
+/*
+ * clobbers: mrf.2 mrf.5
+ */
+#define STORE_MRF(mrf, offset) \
+ SET_OFFSET(mrf, offset); \
+ WRITE_SCRATCH1(mrf)
+
+/*
+ * non-quirky semantics, unlike STORE_MRF
+ * clobbers: g1
+ */
+#define LOAD_MRF(mrf, offset) \
+ LOAD_GRF(g1, offset); \
+ mov (8) mrf:ud g1:ud FLAGS
+
+#define SAVE_ALL_MRF \
+ /* m1 is saved already */ \
+ STORE_MRF(m1, 0x2); \
+ STORE_MRF(m2, 0x4); \
+ STORE_MRF(m3, 0x6); \
+ STORE_MRF(m4, 0x8); \
+ STORE_MRF(m5, 0xa); \
+ STORE_MRF(m6, 0xc); \
+ STORE_MRF(m7, 0xe); \
+ STORE_MRF(m8, 0x10); \
+ STORE_MRF(m9, 0x12); \
+ STORE_MRF(m10, 0x14); \
+ STORE_MRF(m11, 0x16); \
+ STORE_MRF(m12, 0x18); \
+ STORE_MRF(m13, 0x1a); \
+ STORE_MRF(m14, 0x1c)
+
+#define RESTORE_ALL_MRF \
+ LOAD_MRF(m15, 0x1c); \
+ LOAD_MRF(m14, 0x1a); \
+ LOAD_MRF(m13, 0x18); \
+ LOAD_MRF(m12, 0x16); \
+ LOAD_MRF(m11, 0x14); \
+ LOAD_MRF(m10, 0x12); \
+ LOAD_MRF(m9, 0x10); \
+ LOAD_MRF(m8, 0xe); \
+ LOAD_MRF(m7, 0xc); \
+ LOAD_MRF(m6, 0xa); \
+ LOAD_MRF(m5, 0x8); \
+ LOAD_MRF(m4, 0x6); \
+ LOAD_MRF(m3, 0x4); \
+ LOAD_MRF(m2, 0x2); \
+ LOAD_MRF(m1, 0x0)
+
+#ifndef SANDYBRIDGE
+ #error Only SandyBridge is supported
+#endif
+
+/* Default flags for an instruction */
+#define FLAGS { ALIGN1, SWITCH, MASK_DISABLE, ACCWRCTRL}
+
+/*
+ * We can clobber m0, and g0.4, everything else must be saved.
+ */
+Enter:
+ nop;
+
+ or (1) cr0.0 cr0.0 CR0_0_ENTRY_UNMASK:ud FLAGS;
+
+ /*
+ * g0.5 has the per thread scratch space when running in FS or VS.
+ * If we don't have a valid g0.5, we can calculate a per thread scratch offset
+ * using the system registers. The problem is we do not have a good way to know
+ * the offset from GSBA. The system routine will have to be hardcoded or
+ * dynamically patched with the correct offset.
+ * TID is in sr0.0[2:0]
+ * EUID is in sr0.0[11:8]
+ */
+
+#ifdef GPGPU
+ mov (1) g0.4:ud 0:ud FLAGS;
+#if 0
+ /* This should work according to the docs, the add blows up */
+ shr (1) g0.8:uw sr0.0:uw 5 FLAGS;
+ add (1) g0.16:ub gr0.16:ub sr0.0:ub FLAGS;
+#else
+ shr (1) g0.8:uw sr0.0:uw 5 FLAGS;
+ mov (1) g0.9:uw sr0.0:uw FLAGS;
+ and (1) g0.9:uw g0.9:uw 0x7:uw FLAGS;
+ add (1) g0.8:uw g0.8:uw g0.9:uw FLAGS;
+ mov (1) g0.9:uw 0:uw FLAGS;
+ mul (1) g0.4:ud g0.4:ud PER_THREAD_QWORDS FLAGS;
+#endif
+#endif
+
+ mov (8) m0:ud 0:ud FLAGS;
+
+ /* Saves must occur in order so as not to clobber the next register */
+ STORE_MRF(m0, 0);
+ STORE_GRF(g0, 0x20);
+ STORE_GRF(g1, 0x22);
+ SAVE_ALL_MRF;
+
+ mov (8) g1:ud STATE_EU_MSG:ud FLAGS;
+ STORE_GRF(g1, STATE_QWORD);
+
+ mov (8) g1:ud DEBUG_PROTOCOL_VERSION:ud FLAGS;
+ STORE_GRF(g1, COMMUNICATION_QWORD);
+
+ SAVE_CRF;
+
+ EVICT_CACHE;
+ wait n1:ud;
+ EVICT_CACHE;
+
+ /* Using this to try to keep coherency */
+ LOAD_GRF(g1, CR_OFFSET);
+ LOAD_GRF(g1, COMMUNICATION_QWORD);
+ LOAD_GRF(g1, STATE_QWORD);
+
+ RESTORE_ALL_MRF;
+ LOAD_GRF(g1, 0x22);
+ LOAD_GRF(g0, 0x20);
+
+ /* Clear breakpoint status */
+ and (1) cr0.1 cr0.1 CR0_1_ENTRY_UNMASK:ud FLAGS;
+
+ /* set breakpoint suppress this should be conditional on bes */
+ or (1) cr0.0 cr0.0 CR0_0_BP_SUPPRESS:ud FLAGS;
+
+ and (1) cr0.0 cr0.0 CR0_0_RETURN_MASK:ud FLAGS;
+ nop;
diff --git a/debugger/system_routine/test.g4a b/debugger/system_routine/test.g4a
new file mode 100644
index 00000000..e4296e01
--- /dev/null
+++ b/debugger/system_routine/test.g4a
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include "debug.h"
+
+#define CR0_0_ME_STATE_CTRL (1 << 31)
+#define CR0_0_BP_SUPPRESS (1 << 15)
+#define CR0_0_SPF_EN (1 << 2)
+#define CR0_0_ACC_DIS (1 << 1)
+#define CR0_1_BES_CTRL (1 << 31)
+#define CR0_1_HALT_CTRL (1 << 30)
+#define CR0_1_SOFT_EXCEPTION_CTRL (1 << 29)
+#define CR0_1_ILLGL_OP_STS (1 << 28)
+#define CR0_1_STACK_OVRFLW_STS (1 << 27)
+
+#define CR0_0_ENTRY_UNMASK (CR0_0_SPF_EN | CR0_0_ACC_DIS)
+// TODO: Need to fix this for non breakpoint case
+#define CR0_1_ENTRY_UNMASK ~(CR0_1_BES_CTRL)
+#define CR0_0_RETURN_MASK ~(CR0_0_ME_STATE_CTRL | CR0_0_SPF_EN | CR0_0_ACC_DIS)
+
+#ifndef SANDYBRIDGE
+ #error Only SandyBridge is supported
+#endif
+
+/* Default flags for an instruction */
+#define FLAGS { ALIGN1, SWITCH, MASK_DISABLE, ACCWRCTRL}
+
+Enter:
+ nop;
+
+ or (1) cr0.0 cr0.0 CR0_0_ENTRY_UNMASK:ud FLAGS;
+
+ /* Clear breakpoint status */
+ and (1) cr0.1 cr0.1 CR0_1_ENTRY_UNMASK:ud FLAGS;
+
+ /* set breakpoint suppress this should be conditional on bes */
+ or (1) cr0.0 cr0.0 CR0_0_BP_SUPPRESS:ud FLAGS;
+
+ and (1) cr0.0 cr0.0 CR0_0_RETURN_MASK:ud FLAGS;
+ nop;
diff --git a/demos/.gitignore b/demos/.gitignore
new file mode 100644
index 00000000..cd80b0b5
--- /dev/null
+++ b/demos/.gitignore
@@ -0,0 +1 @@
+intel_sprite_on
diff --git a/demos/Makefile.am b/demos/Makefile.am
new file mode 100644
index 00000000..49804d79
--- /dev/null
+++ b/demos/Makefile.am
@@ -0,0 +1,7 @@
+bin_PROGRAMS = \
+ intel_sprite_on \
+ $(NULL)
+
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib
+AM_CFLAGS = $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) $(CAIRO_CFLAGS)
+LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS)
diff --git a/demos/intel_sprite_on.c b/demos/intel_sprite_on.c
new file mode 100644
index 00000000..c1d02245
--- /dev/null
+++ b/demos/intel_sprite_on.c
@@ -0,0 +1,1068 @@
+/*
+ * Copyright 2012 Corporation
+ *
+ * Author:
+ * Armin Reese <armin.c.reese@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/*
+ * This program is intended for testing sprite functionality.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#if defined(DRM_IOCTL_MODE_ADDFB2) && defined(DRM_I915_SET_SPRITE_COLORKEY)
+#define TEST_PLANES 1
+#include "drm_fourcc.h"
+#endif
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct type_name
+{
+ int type;
+ const char *name;
+};
+
+#define type_name_fn(res) \
+static const char * res##_str(int type) { \
+ unsigned int i; \
+ for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
+ if (res##_names[i].type == type) \
+ return res##_names[i].name; \
+ } \
+ return "(invalid)"; \
+}
+
+struct type_name encoder_type_names[] = {
+ { DRM_MODE_ENCODER_NONE, "none" },
+ { DRM_MODE_ENCODER_DAC, "DAC" },
+ { DRM_MODE_ENCODER_TMDS, "TMDS" },
+ { DRM_MODE_ENCODER_LVDS, "LVDS" },
+ { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
+};
+
+type_name_fn(encoder_type)
+
+struct type_name connector_status_names[] = {
+ { DRM_MODE_CONNECTED, "connected" },
+ { DRM_MODE_DISCONNECTED, "disconnected" },
+ { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
+};
+
+type_name_fn(connector_status)
+
+struct type_name connector_type_names[] = {
+ { DRM_MODE_CONNECTOR_Unknown, "unknown" },
+ { DRM_MODE_CONNECTOR_VGA, "VGA" },
+ { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
+ { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
+ { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
+ { DRM_MODE_CONNECTOR_Composite, "composite" },
+ { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
+ { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
+ { DRM_MODE_CONNECTOR_Component, "component" },
+ { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
+ { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" },
+ { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
+ { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
+ { DRM_MODE_CONNECTOR_TV, "TV" },
+ { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort" },
+};
+
+type_name_fn(connector_type)
+
+/*
+ * Mode setting with the kernel interfaces is a bit of a chore.
+ * First you have to find the connector in question and make sure the
+ * requested mode is available.
+ * Then you need to find the encoder attached to that connector so you
+ * can bind it with a free crtc.
+ */
+struct connector
+{
+ uint32_t id;
+ int mode_valid;
+ drmModeModeInfo mode;
+ drmModeEncoder *encoder;
+ drmModeConnector *connector;
+ int crtc;
+ int pipe;
+};
+
+static void dump_mode(
+ drmModeModeInfo *mode)
+{
+ printf(" %s %d %d %d %d %d %d %d %d %d 0x%x 0x%x %d\n",
+ mode->name,
+ mode->vrefresh,
+ mode->hdisplay,
+ mode->hsync_start,
+ mode->hsync_end,
+ mode->htotal,
+ mode->vdisplay,
+ mode->vsync_start,
+ mode->vsync_end,
+ mode->vtotal,
+ mode->flags,
+ mode->type,
+ mode->clock);
+}
+
+static void dump_connectors(
+ int gfx_fd,
+ drmModeRes *resources)
+{
+ int i, j;
+
+ printf("Connectors:\n");
+ printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
+ for (i = 0; i < resources->count_connectors; i++) {
+ drmModeConnector *connector;
+
+ connector = drmModeGetConnector(gfx_fd, resources->connectors[i]);
+ if (!connector) {
+ printf("could not get connector %i: %s\n",
+ resources->connectors[i], strerror(errno));
+ continue;
+ }
+
+ printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
+ connector->connector_id,
+ connector->encoder_id,
+ connector_status_str(connector->connection),
+ connector_type_str(connector->connector_type),
+ connector->mmWidth, connector->mmHeight,
+ connector->count_modes);
+
+ if (!connector->count_modes)
+ continue;
+
+ printf(" modes:\n");
+ printf(" name refresh (Hz) hdisp hss hse htot vdisp "
+ "vss vse vtot flags type clock\n");
+ for (j = 0; j < connector->count_modes; j++)
+ dump_mode(&connector->modes[j]);
+
+ drmModeFreeConnector(connector);
+ }
+ printf("\n");
+}
+
+static void dump_crtcs(
+ int gfx_fd,
+ drmModeRes *resources)
+{
+ int i;
+
+ printf("CRTCs:\n");
+ printf("id\tfb\tpos\tsize\n");
+ for (i = 0; i < resources->count_crtcs; i++) {
+ drmModeCrtc *crtc;
+
+ crtc = drmModeGetCrtc(gfx_fd, resources->crtcs[i]);
+ if (!crtc) {
+ printf("could not get crtc %i: %s\n",
+ resources->crtcs[i],
+ strerror(errno));
+ continue;
+ }
+ printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
+ crtc->crtc_id,
+ crtc->buffer_id,
+ crtc->x, crtc->y,
+ crtc->width, crtc->height);
+ dump_mode(&crtc->mode);
+
+ drmModeFreeCrtc(crtc);
+ }
+ printf("\n");
+}
+
+static void dump_planes(
+ int gfx_fd,
+ drmModeRes *resources)
+{
+ drmModePlaneRes *plane_resources;
+ drmModePlane *ovr;
+ int i;
+
+ plane_resources = drmModeGetPlaneResources(gfx_fd);
+ if (!plane_resources) {
+ printf("drmModeGetPlaneResources failed: %s\n",
+ strerror(errno));
+ return;
+ }
+
+ printf("Planes:\n");
+ printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\n");
+ for (i = 0; i < plane_resources->count_planes; i++) {
+ ovr = drmModeGetPlane(gfx_fd, plane_resources->planes[i]);
+ if (!ovr) {
+ printf("drmModeGetPlane failed: %s\n",
+ strerror(errno));
+ continue;
+ }
+
+ printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%d\n",
+ ovr->plane_id, ovr->crtc_id, ovr->fb_id,
+ ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
+ ovr->gamma_size);
+
+ drmModeFreePlane(ovr);
+ }
+ printf("\n");
+
+ return;
+}
+
+static void connector_find_preferred_mode(
+ int gfx_fd,
+ drmModeRes *gfx_resources,
+ struct connector *c)
+{
+ drmModeConnector *connector;
+ drmModeEncoder *encoder = NULL;
+ int i, j;
+
+ /* First, find the connector & mode */
+ c->mode_valid = 0;
+ connector = drmModeGetConnector(gfx_fd, c->id);
+ if (!connector) {
+ printf("could not get connector %d: %s\n",
+ c->id,
+ strerror(errno));
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ if (connector->connection != DRM_MODE_CONNECTED) {
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ if (!connector->count_modes) {
+ printf("connector %d has no modes\n",
+ c->id);
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ if (connector->connector_id != c->id) {
+ printf("connector id doesn't match (%d != %d)\n",
+ connector->connector_id,
+ c->id);
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ for (j = 0; j < connector->count_modes; j++) {
+ c->mode = connector->modes[j];
+ if (c->mode.type & DRM_MODE_TYPE_PREFERRED) {
+ c->mode_valid = 1;
+ break;
+ }
+ }
+
+ if (!c->mode_valid) {
+ if (connector->count_modes > 0) {
+ /* use the first mode as test mode */
+ c->mode = connector->modes[0];
+ c->mode_valid = 1;
+ } else {
+ printf("failed to find any modes on connector %d\n",
+ c->id);
+ return;
+ }
+ }
+
+ /* Now get the encoder */
+ for (i = 0; i < connector->count_encoders; i++) {
+ encoder = drmModeGetEncoder(gfx_fd, connector->encoders[i]);
+
+ if (!encoder) {
+ printf("could not get encoder %i: %s\n",
+ gfx_resources->encoders[i],
+ strerror(errno));
+ drmModeFreeEncoder(encoder);
+ continue;
+ }
+
+ break;
+ }
+
+ c->encoder = encoder;
+
+ if (i == gfx_resources->count_encoders) {
+ printf("failed to find encoder\n");
+ c->mode_valid = 0;
+ return;
+ }
+
+ /* Find first CRTC not in use */
+ for (i = 0; i < gfx_resources->count_crtcs; i++) {
+ if (gfx_resources->crtcs[i] && (c->encoder->possible_crtcs & (1<<i)))
+ break;
+ }
+ c->crtc = gfx_resources->crtcs[i];
+ c->pipe = i;
+
+ gfx_resources->crtcs[i] = 0;
+
+ c->connector = connector;
+}
+
+static int connector_find_plane(int gfx_fd, struct connector *c)
+{
+ drmModePlaneRes *plane_resources;
+ drmModePlane *ovr;
+ uint32_t id = 0;
+ int i;
+
+ plane_resources = drmModeGetPlaneResources(gfx_fd);
+ if (!plane_resources) {
+ printf("drmModeGetPlaneResources failed: %s\n",
+ strerror(errno));
+ return 0;
+ }
+
+ for (i = 0; i < plane_resources->count_planes; i++) {
+ ovr = drmModeGetPlane(gfx_fd, plane_resources->planes[i]);
+ if (!ovr) {
+ printf("drmModeGetPlane failed: %s\n",
+ strerror(errno));
+ continue;
+ }
+
+ if (ovr->possible_crtcs & (1 << c->pipe)) {
+ id = ovr->plane_id;
+ drmModeFreePlane(ovr);
+ break;
+ }
+ drmModeFreePlane(ovr);
+ }
+
+ return id;
+}
+
+static int prepare_primary_surface(
+ int fd,
+ int prim_width,
+ int prim_height,
+ uint32_t *prim_handle,
+ uint32_t *prim_stride,
+ uint32_t *prim_size,
+ int tiled)
+{
+ uint32_t bytes_per_pixel = sizeof(uint32_t);
+ uint32_t *prim_fb_ptr;
+ struct drm_i915_gem_set_tiling set_tiling;
+
+ if (bytes_per_pixel != sizeof(uint32_t)) {
+ printf("Bad bytes_per_pixel for primary surface: %d\n",
+ bytes_per_pixel);
+ return -EINVAL;
+ }
+
+ if (tiled) {
+ int v;
+
+ /* Round the tiling up to the next power-of-two and the
+ * region up to the next pot fence size so that this works
+ * on all generations.
+ *
+ * This can still fail if the framebuffer is too large to
+ * be tiled. But then that failure is expected.
+ */
+
+ v = prim_width * bytes_per_pixel;
+ for (*prim_stride = 512; *prim_stride < v; *prim_stride *= 2)
+ ;
+
+ v = *prim_stride * prim_height;
+ for (*prim_size = 1024*1024; *prim_size < v; *prim_size *= 2)
+ ;
+ } else {
+ /* Scan-out has a 64 byte alignment restriction */
+ *prim_stride = (prim_width * bytes_per_pixel + 63) & ~63;
+ *prim_size = *prim_stride * prim_height;
+ }
+
+ *prim_handle = gem_create(fd, *prim_size);
+
+ if (tiled) {
+ set_tiling.handle = *prim_handle;
+ set_tiling.tiling_mode = I915_TILING_X;
+ set_tiling.stride = *prim_stride;
+ if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling)) {
+ printf("Set tiling failed: %s (stride=%d, size=%d)\n",
+ strerror(errno), *prim_stride, *prim_size);
+ return -1;
+ }
+ }
+
+ prim_fb_ptr = gem_mmap(fd,
+ *prim_handle, *prim_size,
+ PROT_READ | PROT_WRITE);
+
+ if (prim_fb_ptr != NULL) {
+ // Write primary surface with gray background
+ memset(prim_fb_ptr, 0x3f, *prim_size);
+ munmap(prim_fb_ptr, *prim_size);
+ }
+
+ return 0;
+}
+
+static void fill_sprite(
+ int sprite_width,
+ int sprite_height,
+ int sprite_stride,
+ int sprite_index,
+ void *sprite_fb_ptr)
+{
+ __u32 *pLinePat0,
+ *pLinePat1,
+ *pLinePtr;
+ int i,
+ line;
+ int stripe_width;
+
+ stripe_width = ((sprite_width > 64) &&
+ (sprite_height > 64)) ? (sprite_index + 1) * 8 :
+ (sprite_index + 1) * 2;
+
+ // Note: sprite_stride is in bytes. pLinePat0 and pLinePat1
+ // are both __u32 pointers
+ pLinePat0 = sprite_fb_ptr;
+ pLinePat1 = pLinePat0 + (stripe_width * (sprite_stride / sizeof(*pLinePat0)));
+
+ for (i = 0; i < sprite_width; i++) {
+ *(pLinePat0 + i) = ((i / stripe_width) & 0x1) ? 0 : ~0;
+ *(pLinePat1 + i) = ~(*(pLinePat0 + i));
+ }
+
+ for (line = 1; line < sprite_height; line++) {
+ if (line == stripe_width) {
+ continue;
+ }
+
+ pLinePtr = ((line / stripe_width) & 0x1) ? pLinePat1 : pLinePat0;
+ memcpy( pLinePat0 + ((sprite_stride / sizeof(*pLinePat0)) * line),
+ pLinePtr,
+ sprite_width * sizeof(*pLinePat0));
+ }
+
+ return;
+}
+
+static int prepare_sprite_surfaces(
+ int fd,
+ int sprite_width,
+ int sprite_height,
+ uint32_t num_surfaces,
+ uint32_t *sprite_handles,
+ uint32_t *sprite_stride,
+ uint32_t *sprite_size,
+ int tiled)
+{
+ uint32_t bytes_per_pixel = sizeof(uint32_t);
+ uint32_t *sprite_fb_ptr;
+ struct drm_i915_gem_set_tiling set_tiling;
+ int i;
+
+ if (bytes_per_pixel != sizeof(uint32_t)) {
+ printf("Bad bytes_per_pixel for sprite: %d\n", bytes_per_pixel);
+ return -EINVAL;
+ }
+
+ if (tiled) {
+ int v;
+
+ /* Round the tiling up to the next power-of-two and the
+ * region up to the next pot fence size so that this works
+ * on all generations.
+ *
+ * This can still fail if the framebuffer is too large to
+ * be tiled. But then that failure is expected.
+ */
+
+ v = sprite_width * bytes_per_pixel;
+ for (*sprite_stride = 512; *sprite_stride < v; *sprite_stride *= 2)
+ ;
+
+ v = *sprite_stride * sprite_height;
+ for (*sprite_size = 1024*1024; *sprite_size < v; *sprite_size *= 2)
+ ;
+ } else {
+ /* Scan-out has a 64 byte alignment restriction */
+ *sprite_stride = (sprite_width * bytes_per_pixel + 63) & ~63;
+ *sprite_size = *sprite_stride * sprite_height;
+ }
+
+ for (i = 0; i < num_surfaces; i++) {
+ // Create the sprite surface
+ sprite_handles[i] = gem_create(fd, *sprite_size);
+
+ if (tiled) {
+ set_tiling.handle = sprite_handles[i];
+ set_tiling.tiling_mode = I915_TILING_X;
+ set_tiling.stride = *sprite_stride;
+ if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling)) {
+ printf("Set tiling failed: %s (stride=%d, size=%d)\n",
+ strerror(errno), *sprite_stride, *sprite_size);
+ return -1;
+ }
+ }
+
+ // Get pointer to the surface
+ sprite_fb_ptr = gem_mmap(fd,
+ sprite_handles[i], *sprite_size,
+ PROT_READ | PROT_WRITE);
+
+ if (sprite_fb_ptr != NULL) {
+ // Fill with checkerboard pattern
+ fill_sprite(
+ sprite_width,
+ sprite_height,
+ *sprite_stride,
+ i, sprite_fb_ptr);
+
+ munmap(sprite_fb_ptr, *sprite_size);
+ } else {
+ i--;
+ while (i >= 0) {
+ gem_close(fd, sprite_handles[i]);
+ i--;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void ricochet(
+ int tiled,
+ int sprite_w,
+ int sprite_h,
+ int out_w,
+ int out_h,
+ int dump_info)
+{
+ int ret;
+ int gfx_fd;
+ int keep_moving;
+ const int num_surfaces = 3;
+ uint32_t sprite_handles[num_surfaces];
+ uint32_t sprite_fb_id[num_surfaces];
+ int sprite_x;
+ int sprite_y;
+ uint32_t sprite_stride;
+ uint32_t sprite_size;
+ uint32_t handles[4],
+ pitches[4],
+ offsets[4]; /* we only use [0] */
+ uint32_t prim_width,
+ prim_height,
+ prim_handle,
+ prim_stride,
+ prim_size,
+ prim_fb_id;
+ struct drm_intel_sprite_colorkey set;
+ struct connector curr_connector;
+ drmModeRes *gfx_resources;
+ struct termios orig_term,
+ curr_term;
+ int c_index;
+ int sprite_index;
+ unsigned int sprite_plane_id;
+ uint32_t plane_flags = 0;
+ int delta_x,
+ delta_y;
+ struct timeval stTimeVal;
+ long long currTime,
+ prevFlipTime,
+ prevMoveTime,
+ deltaFlipTime,
+ deltaMoveTime,
+ SleepTime;
+ char key;
+
+ // Open up I915 graphics device
+ gfx_fd = drmOpen("i915", NULL);
+ if (gfx_fd < 0) {
+ printf("Failed to load i915 driver: %s\n", strerror(errno));
+ return;
+ }
+
+ // Obtain pointer to struct containing graphics resources
+ gfx_resources = drmModeGetResources(gfx_fd);
+ if (!gfx_resources) {
+ printf("drmModeGetResources failed: %s\n", strerror(errno));
+ return;
+ }
+
+ if (dump_info != 0) {
+ dump_connectors(gfx_fd, gfx_resources);
+ dump_crtcs(gfx_fd, gfx_resources);
+ dump_planes(gfx_fd, gfx_resources);
+ }
+
+ // Save previous terminal settings
+ if (tcgetattr( 0, &orig_term) != 0) {
+ printf("tcgetattr failure: %s\n",
+ strerror(errno));
+ return;
+ }
+
+ // Set up input to return characters immediately
+ curr_term = orig_term;
+ curr_term.c_lflag &= ~(ICANON | ECHO | ECHONL);
+ curr_term.c_cc[VMIN] = 0; // No minimum number of characters
+ curr_term.c_cc[VTIME] = 0 ; // Return immediately, even if
+ // nothing has been entered.
+ if (tcsetattr( 0, TCSANOW, &curr_term) != 0) {
+ printf("tcgetattr failure: %s\n",
+ strerror(errno));
+ return;
+ }
+
+ // Cycle through all connectors and display the flying sprite
+ // where there are displays attached and the hardware will support it.
+ for (c_index = 0; c_index < gfx_resources->count_connectors; c_index++) {
+ curr_connector.id = gfx_resources->connectors[c_index];
+
+ // Find the native (preferred) display mode
+ connector_find_preferred_mode(gfx_fd, gfx_resources, &curr_connector);
+ if (curr_connector.mode_valid == 0) {
+ printf("No valid preferred mode detected\n");
+ goto out;
+ }
+
+ // Determine if sprite hardware is available on pipe
+ // associated with this connector.
+ sprite_plane_id = connector_find_plane(gfx_fd, &curr_connector);
+ if (!sprite_plane_id) {
+ printf("Failed to find sprite plane on crtc\n");
+ goto out;
+ }
+
+ // Width and height of preferred mode
+ prim_width = curr_connector.mode.hdisplay;
+ prim_height = curr_connector.mode.vdisplay;
+
+ // Allocate and fill memory for primary surface
+ ret = prepare_primary_surface(
+ gfx_fd,
+ prim_width,
+ prim_height,
+ &prim_handle,
+ &prim_stride,
+ &prim_size,
+ tiled);
+ if (ret != 0) {
+ printf("Failed to add primary fb (%dx%d): %s\n",
+ prim_width, prim_height, strerror(errno));
+ goto out;
+ }
+
+ // Add the primary surface framebuffer
+ ret = drmModeAddFB(
+ gfx_fd,
+ prim_width,
+ prim_height,
+ 24, 32,
+ prim_stride,
+ prim_handle,
+ &prim_fb_id);
+ gem_close(gfx_fd, prim_handle);
+
+ if (ret != 0) {
+ printf("Failed to add primary fb (%dx%d): %s\n",
+ prim_width, prim_height, strerror(errno));
+ goto out;
+ }
+
+ // Allocate and fill sprite surfaces
+ ret = prepare_sprite_surfaces(
+ gfx_fd,
+ sprite_w,
+ sprite_h,
+ num_surfaces,
+ &sprite_handles[0],
+ &sprite_stride,
+ &sprite_size,
+ tiled);
+ if (ret != 0) {
+ printf("Preparation of sprite surfaces failed %dx%d\n",
+ sprite_w, sprite_h);
+ goto out;
+ }
+
+ // Add the sprite framebuffers
+ for (sprite_index = 0; sprite_index < num_surfaces; sprite_index++) {
+ handles[0] = sprite_handles[sprite_index];
+ handles[1] = handles[0];
+ handles[2] = handles[0];
+ handles[3] = handles[0];
+ pitches[0] = sprite_stride;
+ pitches[1] = sprite_stride;
+ pitches[2] = sprite_stride;
+ pitches[3] = sprite_stride;
+ memset(offsets, 0, sizeof(offsets));
+
+ ret = drmModeAddFB2(
+ gfx_fd,
+ sprite_w, sprite_h, DRM_FORMAT_XRGB8888,
+ handles, pitches, offsets, &sprite_fb_id[sprite_index],
+ plane_flags);
+ gem_close(gfx_fd, sprite_handles[sprite_index]);
+
+ if (ret) {
+ printf("Failed to add sprite fb (%dx%d): %s\n",
+ sprite_w, sprite_h, strerror(errno));
+
+ sprite_index--;
+ while (sprite_index >= 0) {
+ drmModeRmFB(gfx_fd, sprite_fb_id[sprite_index]);
+ sprite_index--;
+ }
+ goto out;
+ }
+ }
+
+ if (dump_info != 0) {
+ printf("Displayed Mode Connector struct:\n"
+ " .id = %d\n"
+ " .mode_valid = %d\n"
+ " .crtc = %d\n"
+ " .pipe = %d\n"
+ " drmModeModeInfo ...\n"
+ " .name = %s\n"
+ " .type = %d\n"
+ " .flags = %08x\n"
+ " drmModeEncoder ...\n"
+ " .encoder_id = %d\n"
+ " .encoder_type = %d (%s)\n"
+ " .crtc_id = %d\n"
+ " .possible_crtcs = %d\n"
+ " .possible_clones = %d\n"
+ " drmModeConnector ...\n"
+ " .connector_id = %d\n"
+ " .encoder_id = %d\n"
+ " .connector_type = %d (%s)\n"
+ " .connector_type_id = %d\n\n",
+ curr_connector.id,
+ curr_connector.mode_valid,
+ curr_connector.crtc,
+ curr_connector.pipe,
+ curr_connector.mode.name,
+ curr_connector.mode.type,
+ curr_connector.mode.flags,
+ curr_connector.encoder->encoder_id,
+ curr_connector.encoder->encoder_type,
+ encoder_type_str(curr_connector.encoder->encoder_type),
+ curr_connector.encoder->crtc_id,
+ curr_connector.encoder->possible_crtcs,
+ curr_connector.encoder->possible_clones,
+ curr_connector.connector->connector_id,
+ curr_connector.connector->encoder_id,
+ curr_connector.connector->connector_type,
+ connector_type_str(curr_connector.connector->connector_type),
+ curr_connector.connector->connector_type_id);
+
+ printf("Sprite surface dimensions = %dx%d\n"
+ "Sprite output dimensions = %dx%d\n"
+ "Press any key to continue >\n",
+ sprite_w,
+ sprite_h,
+ out_w,
+ out_h);
+
+ // Wait for a key-press
+ while( read(0, &key, 1) == 0);
+ // Purge unread characters
+ tcflush(0, TCIFLUSH);
+ }
+
+ // Set up the primary display mode
+ ret = drmModeSetCrtc(
+ gfx_fd,
+ curr_connector.crtc,
+ prim_fb_id,
+ 0, 0,
+ &curr_connector.id,
+ 1,
+ &curr_connector.mode);
+ if (ret != 0)
+ {
+ printf("Failed to set mode (%dx%d@%dHz): %s\n",
+ prim_width, prim_height, curr_connector.mode.vrefresh,
+ strerror(errno));
+ continue;
+ }
+
+ // Set the sprite colorkey state
+ set.plane_id = sprite_plane_id;
+ set.min_value = 0;
+ set.max_value = 0;
+ set.flags = I915_SET_COLORKEY_NONE;
+ ret = drmCommandWrite(gfx_fd, DRM_I915_SET_SPRITE_COLORKEY, &set,
+ sizeof(set));
+
+ // Set up sprite output dimensions, initial position, etc.
+ if (out_w > prim_width / 2)
+ out_w = prim_width / 2;
+ if (out_h > prim_height / 2)
+ out_h = prim_height / 2;
+
+ delta_x = 3;
+ delta_y = 4;
+ sprite_x = (prim_width / 2) - (out_w / 2);
+ sprite_y = (prim_height / 2) - (out_h / 2);
+
+ currTime = 0;
+ prevFlipTime = 0; // Will force immediate sprite flip
+ prevMoveTime = 0; // Will force immediate sprite move
+ deltaFlipTime = 500000; // Flip sprite surface every 1/2 second
+ deltaMoveTime = 100000; // Move sprite every 100 ms
+ sprite_index = num_surfaces - 1;
+ keep_moving = 1;
+
+ // Bounce sprite off the walls
+ while (keep_moving) {
+ // Obtain system time in usec.
+ if (gettimeofday( &stTimeVal, NULL ) != 0) {
+ printf("gettimeofday error: %s\n",
+ strerror(errno));
+ } else {
+ currTime = ((long long)stTimeVal.tv_sec * 1000000) + stTimeVal.tv_usec;
+ }
+
+ // Check if it's time to flip the sprite surface
+ if (currTime - prevFlipTime > deltaFlipTime) {
+ sprite_index = (sprite_index + 1) % num_surfaces;
+
+ prevFlipTime = currTime;
+ }
+
+ // Move the sprite on the screen and flip
+ // the surface if the index has changed
+ if (drmModeSetPlane(
+ gfx_fd,
+ sprite_plane_id,
+ curr_connector.crtc,
+ sprite_fb_id[sprite_index],
+ plane_flags,
+ sprite_x, sprite_y,
+ out_w, out_h,
+ 0, 0,
+ sprite_w, sprite_h)) {
+ printf("Failed to enable sprite plane: %s\n",
+ strerror(errno));
+ }
+
+ // Check if it's time to move the sprite surface
+ if (currTime - prevMoveTime > deltaMoveTime) {
+
+ // Compute the next position for sprite
+ sprite_x += delta_x;
+ sprite_y += delta_y;
+ if (sprite_x < 0) {
+ sprite_x = 0;
+ delta_x = -delta_x;
+ }
+ else if (sprite_x > prim_width - out_w) {
+ sprite_x = prim_width - out_w;
+ delta_x = -delta_x;
+ }
+
+ if (sprite_y < 0) {
+ sprite_y = 0;
+ delta_y = -delta_y;
+ }
+ else if (sprite_y > prim_height - out_h) {
+ sprite_y = prim_height - out_h;
+ delta_y = -delta_y;
+ }
+
+ prevMoveTime = currTime;
+ }
+
+ // Fetch a key from input (non-blocking)
+ if (read(0, &key, 1) == 1) {
+ switch (key) {
+ case 'q': // Kill the program
+ case 'Q':
+ goto out;
+ break;
+ case 's': // Slow down sprite movement;
+ deltaMoveTime = (deltaMoveTime * 100) / 90;
+ if (deltaMoveTime > 800000) {
+ deltaMoveTime = 800000;
+ }
+ break;
+ case 'S': // Speed up sprite movement;
+ deltaMoveTime = (deltaMoveTime * 100) / 110;
+ if (deltaMoveTime < 2000) {
+ deltaMoveTime = 2000;
+ }
+ break;
+ case 'f': // Slow down sprite flipping;
+ deltaFlipTime = (deltaFlipTime * 100) / 90;
+ if (deltaFlipTime > 1000000) {
+ deltaFlipTime = 1000000;
+ }
+ break;
+ case 'F': // Speed up sprite flipping;
+ deltaFlipTime = (deltaFlipTime * 100) / 110;
+ if (deltaFlipTime < 20000) {
+ deltaFlipTime = 20000;
+ }
+ break;
+ case 'n': // Next connector
+ case 'N':
+ keep_moving = 0;
+ break;
+ default:
+ break;
+ }
+
+ // Purge unread characters
+ tcflush(0, TCIFLUSH);
+ }
+
+ // Wait for min of flip or move deltas
+ SleepTime = (deltaFlipTime < deltaMoveTime) ?
+ deltaFlipTime : deltaMoveTime;
+ usleep(SleepTime);
+ }
+ }
+
+out:
+ // Purge unread characters
+ tcflush(0, TCIFLUSH);
+ // Restore previous terminal settings
+ if (tcsetattr( 0, TCSANOW, &orig_term) != 0) {
+ printf("tcgetattr failure: %s\n",
+ strerror(errno));
+ return;
+ }
+
+ drmModeFreeResources(gfx_resources);
+}
+
+static void usage(char *name)
+{
+ printf("usage: %s -s <plane width>x<plane height> [-dhto]\n"
+ "\t-d\t[optional] dump mode information\n"
+ "\t-h\t[optional] output help message\n"
+ "\t-t\t[optional] enable tiling\n"
+ "\t-o\t[optional] <output rect width>x<output rect height>\n\n"
+ "Keyboard control for sprite movement and flip rate ...\n"
+ "\t'q' or 'Q' - Quit the program\n"
+ "\t'n' or 'N' - Switch to next display\n"
+ "\t's' - Slow sprite movement\n"
+ "\t'S' - Speed up sprite movement\n"
+ "\t'f' - Slow sprite surface flipping\n"
+ "\t'F' - Speed up sprite surface flipping\n",
+ name);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ int test_overlay = 0,
+ enable_tiling = 0,
+ dump_info = 0;
+ int plane_width = 0,
+ plane_height = 0,
+ out_width = 0,
+ out_height = 0;
+ static char optstr[] = "ds:o:th";
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ switch (c) {
+ case 'd': // Dump information
+ dump_info = 1;
+ break;
+ case 't': // Tiling enable
+ enable_tiling = 1;
+ break;
+ case 's': // Surface dimensions
+ if (sscanf(optarg, "%dx%d",
+ &plane_width, &plane_height) != 2)
+ usage(argv[0]);
+ test_overlay = 1;
+ break;
+ case 'o': // Output dimensions
+ if (sscanf(optarg, "%dx%d",
+ &out_width, &out_height) != 2)
+ usage(argv[0]);
+ break;
+ default:
+ printf("unknown option %c\n", c);
+ /* fall through */
+ case 'h': // Help!
+ usage(argv[0]);
+ goto out;
+ }
+ }
+
+ if (test_overlay) {
+ if (out_width < (plane_width / 2)) {
+ out_width = plane_width;
+ }
+
+ if (out_height < (plane_height / 2)) {
+ out_height = plane_height;
+ }
+
+ ricochet(enable_tiling,
+ plane_width,
+ plane_height,
+ out_width,
+ out_height,
+ dump_info);
+ } else {
+ printf("Sprite dimensions are required:\n");
+ usage(argv[0]);
+ }
+
+out:
+ exit(0);
+}
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 00000000..d8f081fe
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,36 @@
+
+noinst_LTLIBRARIES = libintel_tools.la
+
+AM_CPPFLAGS = -I$(top_srcdir)
+AM_CFLAGS = $(DRM_CFLAGS) $(CWARNFLAGS)
+
+libintel_tools_la_SOURCES = \
+ debug.h \
+ drmtest.c \
+ drmtest.h \
+ i830_reg.h \
+ i915_3d.h \
+ i915_reg.h \
+ instdone.c \
+ instdone.h \
+ intel_batchbuffer.c \
+ intel_batchbuffer.h \
+ intel_chipset.h \
+ intel_drm.c \
+ intel_gpu_tools.h \
+ intel_mmio.c \
+ intel_pci.c \
+ intel_reg.h \
+ rendercopy_i915.c \
+ rendercopy_i830.c \
+ gen6_render.h \
+ gen7_render.h \
+ rendercopy_gen6.c \
+ rendercopy_gen7.c \
+ rendercopy.h \
+ intel_reg_map.c \
+ intel_dpio.c \
+ $(NULL)
+
+LDADD = $(CAIRO_LIBS)
+AM_CFLAGS += $(CAIRO_CFLAGS)
diff --git a/lib/debug.h b/lib/debug.h
new file mode 100644
index 00000000..af9cf391
--- /dev/null
+++ b/lib/debug.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+#define DEBUG_PROTOCOL_VERSION 1
+#define COMMUNICATION_OFFSET 0xc00
+#define COMMUNICATION_QWORD 0xc0
+
+#define STATE_EU_MSG 0x47534d65 /* eMSG */
+#define STATE_CPU_ACK 0x4b434163 /* cACK */
+#define STATE_OFFSET 0xc20
+#define STATE_QWORD 0xc2
+
+#define TX_OFFSET 0xc40
+#define TX_QWORD 0xc4
+#define RX_OFFSET 0xc60
+#define RX_QWORD 0xc6
+
+#ifndef GEN_ASM
+typedef uint32_t grf[8];
+typedef uint32_t mrf[8];
+typedef uint8_t cr[12];
+typedef uint32_t sr;
+
+#define DWORD8(x) {x, x, x, x, x, x, x, x}
+
+const static grf protocol_version = DWORD8(DEBUG_PROTOCOL_VERSION);
+const static grf eu_msg = DWORD8(STATE_EU_MSG);
+const static grf cpu_ack = DWORD8(STATE_CPU_ACK);
+
+struct eu_state {
+ mrf m_regs[15];
+ grf g_regs[16];
+ grf pad;
+
+/* 0x400 */
+ cr cr0;
+ sr sr0;
+ uint32_t beef_pad[4];
+ uint8_t pad2[992 + 1024];
+
+/* 0xc00 COMMUNICATION_OFFSET */
+ grf version;
+ grf state_magic;
+ grf eu_tx;
+ grf eu_rx;
+
+ uint8_t pad3[896];
+} __attribute__((packed));
+
+static inline void
+print_reg(uint8_t reg[32]) {
+ uint32_t *dwords = (uint32_t *)reg;
+ printf("%08x %08x %08x %08x %08x %08x %08x %08x",
+ dwords[7], dwords[6], dwords[5], dwords[4],
+ dwords[3], dwords[2], dwords[1], dwords[0]);
+}
+
+static inline void
+print_creg(uint8_t reg[12]) {
+ uint32_t *dwords = (uint32_t *)reg;
+ printf("%08x %08x %08x", dwords[2], dwords[1], dwords[0]);
+}
+#endif
+
+#endif
diff --git a/lib/drmtest.c b/lib/drmtest.c
new file mode 100644
index 00000000..2101f6a9
--- /dev/null
+++ b/lib/drmtest.c
@@ -0,0 +1,779 @@
+/*
+ * Copyright © 2007, 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <pciaccess.h>
+#include <math.h>
+
+#include "drmtest.h"
+#include "i915_drm.h"
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+
+/* This file contains a bunch of wrapper functions to directly use gem ioctls.
+ * Mostly useful to write kernel tests. */
+
+static int
+is_intel(int fd)
+{
+ struct drm_i915_getparam gp;
+ int devid;
+
+ gp.param = I915_PARAM_CHIPSET_ID;
+ gp.value = &devid;
+
+ if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp)))
+ return 0;
+
+ return IS_INTEL(devid);
+}
+
+bool gem_uses_aliasing_ppgtt(int fd)
+{
+ struct drm_i915_getparam gp;
+ int val;
+
+ gp.param = 18; /* HAS_ALIASING_PPGTT */
+ gp.value = &val;
+
+ if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp)))
+ return 0;
+
+ return val;
+}
+
+int gem_available_fences(int fd)
+{
+ struct drm_i915_getparam gp;
+ int val;
+
+ gp.param = I915_PARAM_NUM_FENCES_AVAIL;
+ gp.value = &val;
+
+ if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp)))
+ return 0;
+
+ return val;
+}
+
+
+/* Ensure the gpu is idle by launching a nop execbuf and stalling for it. */
+void gem_quiescent_gpu(int fd)
+{
+ uint32_t batch[2] = {MI_BATCH_BUFFER_END, 0};
+ uint32_t handle;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 gem_exec[1];
+
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, sizeof(batch));
+
+ gem_exec[0].handle = handle;
+ gem_exec[0].relocation_count = 0;
+ gem_exec[0].relocs_ptr = 0;
+ gem_exec[0].alignment = 0;
+ gem_exec[0].offset = 0;
+ gem_exec[0].flags = 0;
+ gem_exec[0].rsvd1 = 0;
+ gem_exec[0].rsvd2 = 0;
+
+ execbuf.buffers_ptr = (uintptr_t)gem_exec;
+ execbuf.buffer_count = 1;
+ execbuf.batch_start_offset = 0;
+ execbuf.batch_len = 8;
+ execbuf.cliprects_ptr = 0;
+ execbuf.num_cliprects = 0;
+ execbuf.DR1 = 0;
+ execbuf.DR4 = 0;
+ execbuf.flags = 0;
+ i915_execbuffer2_set_context_id(execbuf, 0);
+ execbuf.rsvd2 = 0;
+
+ do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
+
+ gem_sync(fd, handle);
+}
+
+static bool is_master(int fd)
+{
+ drm_client_t client;
+ int ret;
+
+ /* Check that we're the only opener and authed. */
+ client.idx = 0;
+ ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client);
+ assert (ret == 0);
+ if (!client.auth) {
+ return 0;
+ }
+ client.idx = 1;
+ ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client);
+ if (ret != -1 || errno != EINVAL) {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * drm_get_card() - get an intel card number for use in /dev or /sys
+ *
+ * @master: -1 not a master, 0 don't care, 1 is the master
+ *
+ * returns -1 on error
+ */
+int drm_get_card(int master)
+{
+ char *name;
+ int i, fd;
+
+ for (i = 0; i < 16; i++) {
+ int ret;
+
+ ret = asprintf(&name, "/dev/dri/card%u", i);
+ if (ret == -1)
+ return -1;
+ fd = open(name, O_RDWR);
+ free(name);
+
+ if (fd == -1)
+ continue;
+
+ if (is_intel(fd) && master == 0) {
+ gem_quiescent_gpu(fd);
+ close(fd);
+ break;
+ }
+
+ if (master == 1 && is_master(fd)) {
+ close(fd);
+ break;
+ }
+
+ if (master == -1 && !is_master(fd)) {
+ close(fd);
+ break;
+ }
+
+ close(fd);
+ }
+
+ return i;
+}
+
+/** Open the first DRM device we can find, searching up to 16 device nodes */
+int drm_open_any(void)
+{
+ char *name;
+ int ret, fd;
+
+ ret = asprintf(&name, "/dev/dri/card%d", drm_get_card(0));
+ if (ret == -1)
+ return -1;
+
+ fd = open(name, O_RDWR);
+ free(name);
+
+ if (fd == -1)
+ fprintf(stderr, "failed to open any drm device. retry as root?\n");
+
+ assert(is_intel(fd));
+
+ return fd;
+}
+
+/**
+ * Open the first DRM device we can find where we end up being the master.
+ */
+int drm_open_any_master(void)
+{
+ char *name;
+ int ret, fd;
+
+ ret = asprintf(&name, "/dev/dri/card%d", drm_get_card(1));
+ if (ret == -1)
+ return -1;
+
+ fd = open(name, O_RDWR);
+ free(name);
+ if (fd == -1)
+ fprintf(stderr, "Couldn't find an un-controlled DRM device\n");
+
+ assert(is_intel(fd));
+
+ return fd;
+}
+
+void gem_set_tiling(int fd, uint32_t handle, int tiling, int stride)
+{
+ struct drm_i915_gem_set_tiling st;
+ int ret;
+
+ memset(&st, 0, sizeof(st));
+ do {
+ st.handle = handle;
+ st.tiling_mode = tiling;
+ st.stride = tiling ? stride : 0;
+
+ ret = ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &st);
+ } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+ assert(ret == 0);
+ assert(st.tiling_mode == tiling);
+}
+
+void gem_close(int fd, uint32_t handle)
+{
+ struct drm_gem_close close_bo;
+
+ close_bo.handle = handle;
+ do_ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
+}
+
+void gem_write(int fd, uint32_t handle, uint32_t offset, const void *buf, uint32_t size)
+{
+ struct drm_i915_gem_pwrite gem_pwrite;
+
+ gem_pwrite.handle = handle;
+ gem_pwrite.offset = offset;
+ gem_pwrite.size = size;
+ gem_pwrite.data_ptr = (uintptr_t)buf;
+ do_ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite);
+}
+
+void gem_read(int fd, uint32_t handle, uint32_t offset, void *buf, uint32_t length)
+{
+ struct drm_i915_gem_pread gem_pread;
+
+ gem_pread.handle = handle;
+ gem_pread.offset = offset;
+ gem_pread.size = length;
+ gem_pread.data_ptr = (uintptr_t)buf;
+ do_ioctl(fd, DRM_IOCTL_I915_GEM_PREAD, &gem_pread);
+}
+
+void gem_set_domain(int fd, uint32_t handle,
+ uint32_t read_domains, uint32_t write_domain)
+{
+ struct drm_i915_gem_set_domain set_domain;
+
+ set_domain.handle = handle;
+ set_domain.read_domains = read_domains;
+ set_domain.write_domain = write_domain;
+
+ do_ioctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
+}
+
+void gem_sync(int fd, uint32_t handle)
+{
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+}
+
+uint32_t gem_create(int fd, int size)
+{
+ struct drm_i915_gem_create create;
+
+ create.handle = 0;
+ create.size = size;
+ do_ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create);
+ assert(create.handle);
+
+ return create.handle;
+}
+
+void *gem_mmap__gtt(int fd, uint32_t handle, int size, int prot)
+{
+ struct drm_i915_gem_mmap_gtt mmap_arg;
+ void *ptr;
+
+ mmap_arg.handle = handle;
+ if (drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg))
+ return NULL;
+
+ ptr = mmap64(0, size, prot, MAP_SHARED, fd, mmap_arg.offset);
+ if (ptr == MAP_FAILED)
+ ptr = NULL;
+
+ return ptr;
+}
+
+void *gem_mmap__cpu(int fd, uint32_t handle, int size, int prot)
+{
+ struct drm_i915_gem_mmap mmap_arg;
+
+ mmap_arg.handle = handle;
+ mmap_arg.offset = 0;
+ mmap_arg.size = size;
+ if (drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))
+ return NULL;
+
+ return (void *)(uintptr_t)mmap_arg.addr_ptr;
+}
+
+uint64_t gem_aperture_size(int fd)
+{
+ struct drm_i915_gem_get_aperture aperture;
+
+ aperture.aper_size = 256*1024*1024;
+ do_ioctl(fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
+ return aperture.aper_size;
+}
+
+uint64_t gem_mappable_aperture_size(void)
+{
+ struct pci_device *pci_dev;
+ int bar;
+ pci_dev = intel_get_pci_device();
+
+ if (intel_gen(pci_dev->device_id) < 3)
+ bar = 0;
+ else
+ bar = 2;
+
+ return pci_dev->regions[bar].size;
+}
+
+int gem_madvise(int fd, uint32_t handle, int state)
+{
+ struct drm_i915_gem_madvise madv;
+
+ madv.handle = handle;
+ madv.madv = state;
+ madv.retained = 1;
+ do_ioctl(fd, DRM_IOCTL_I915_GEM_MADVISE, &madv);
+
+ return madv.retained;
+}
+
+/* prime */
+int prime_handle_to_fd(int fd, uint32_t handle)
+{
+ struct drm_prime_handle args;
+
+ args.handle = handle;
+ args.flags = DRM_CLOEXEC;
+ args.fd = -1;
+
+ do_ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
+
+ return args.fd;
+}
+
+uint32_t prime_fd_to_handle(int fd, int dma_buf_fd)
+{
+ struct drm_prime_handle args;
+
+ args.fd = dma_buf_fd;
+ args.flags = 0;
+ args.handle = 0;
+
+ do_ioctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
+
+ return args.handle;
+}
+
+/* signal interrupt helpers */
+static pid_t signal_helper = -1;
+long long int sig_stat;
+static void signal_helper_process(pid_t pid)
+{
+ /* Interrupt the parent process at 500Hz, just to be annoying */
+ while (1) {
+ usleep(1000 * 1000 / 500);
+ if (kill(pid, SIGUSR1)) /* Parent has died, so must we. */
+ exit(0);
+ }
+}
+
+static void sig_handler(int i)
+{
+ sig_stat++;
+}
+
+void drmtest_fork_signal_helper(void)
+{
+ pid_t pid;
+
+ signal(SIGUSR1, sig_handler);
+ pid = fork();
+ if (pid == 0) {
+ signal_helper_process(getppid());
+ return;
+ }
+
+ signal_helper = pid;
+}
+
+void drmtest_stop_signal_helper(void)
+{
+ if (signal_helper != -1)
+ kill(signal_helper, SIGQUIT);
+
+ if (sig_stat)
+ fprintf(stderr, "signal handler called %llu times\n", sig_stat);
+
+ signal_helper = -1;
+}
+
+/* other helpers */
+void drmtest_exchange_int(void *array, unsigned i, unsigned j)
+{
+ int *int_arr, tmp;
+ int_arr = array;
+
+ tmp = int_arr[i];
+ int_arr[i] = int_arr[j];
+ int_arr[j] = tmp;
+}
+
+void drmtest_permute_array(void *array, unsigned size,
+ void (*exchange_func)(void *array,
+ unsigned i,
+ unsigned j))
+{
+ int i;
+
+ for (i = size - 1; i > 1; i--) {
+ /* yes, not perfectly uniform, who cares */
+ long l = random() % (i +1);
+ if (i != l)
+ exchange_func(array, i, l);
+ }
+}
+
+void drmtest_progress(const char *header, uint64_t i, uint64_t total)
+{
+ if (i+1 >= total) {
+ fprintf(stderr, "\r%s100%%\n", header);
+ return;
+ }
+
+ /* only bother updating about every 0.5% */
+ if (i % (total / 200) == 0 || i+1 >= total) {
+ fprintf(stderr, "\r%s%3llu%%", header,
+ (long long unsigned) i * 100 / total);
+ }
+}
+
+/* mappable aperture trasher helper */
+drm_intel_bo **trash_bos;
+int num_trash_bos;
+
+void drmtest_init_aperture_trashers(drm_intel_bufmgr *bufmgr)
+{
+ int i;
+
+ num_trash_bos = gem_mappable_aperture_size() / (1024*1024);
+
+ trash_bos = malloc(num_trash_bos * sizeof(drm_intel_bo *));
+ assert(trash_bos);
+
+ for (i = 0; i < num_trash_bos; i++)
+ trash_bos[i] = drm_intel_bo_alloc(bufmgr, "trash bo", 1024*1024, 4096);
+}
+
+void drmtest_trash_aperture(void)
+{
+ int i;
+ uint8_t *gtt_ptr;
+
+ for (i = 0; i < num_trash_bos; i++) {
+ drm_intel_gem_bo_map_gtt(trash_bos[i]);
+ gtt_ptr = trash_bos[i]->virtual;
+ *gtt_ptr = 0;
+ drm_intel_gem_bo_unmap_gtt(trash_bos[i]);
+ }
+}
+
+void drmtest_cleanup_aperture_trashers(void)
+{
+ int i;
+
+ for (i = 0; i < num_trash_bos; i++)
+ drm_intel_bo_unreference(trash_bos[i]);
+
+ free(trash_bos);
+}
+
+/* helpers to create nice-looking framebuffers */
+static cairo_surface_t *
+paint_allocate_surface(int fd, int width, int height, int depth, int bpp,
+ bool tiled,
+ struct kmstest_fb *fb_info)
+{
+ cairo_format_t format;
+ struct drm_i915_gem_set_tiling set_tiling;
+ int size;
+ unsigned stride;
+ uint32_t *fb_ptr;
+
+ if (tiled) {
+ int v;
+
+ /* Round the tiling up to the next power-of-two and the
+ * region up to the next pot fence size so that this works
+ * on all generations.
+ *
+ * This can still fail if the framebuffer is too large to
+ * be tiled. But then that failure is expected.
+ */
+
+ v = width * bpp / 8;
+ for (stride = 512; stride < v; stride *= 2)
+ ;
+
+ v = stride * height;
+ for (size = 1024*1024; size < v; size *= 2)
+ ;
+ } else {
+ /* Scan-out has a 64 byte alignment restriction */
+ stride = (width * (bpp / 8) + 63) & ~63;
+ size = stride * height;
+ }
+
+ switch (depth) {
+ case 16:
+ format = CAIRO_FORMAT_RGB16_565;
+ break;
+ case 24:
+ format = CAIRO_FORMAT_RGB24;
+ break;
+#if 0
+ case 30:
+ format = CAIRO_FORMAT_RGB30;
+ break;
+#endif
+ case 32:
+ format = CAIRO_FORMAT_ARGB32;
+ break;
+ default:
+ fprintf(stderr, "bad depth %d\n", depth);
+ return NULL;
+ }
+
+ assert (bpp >= depth);
+
+ fb_info->gem_handle = gem_create(fd, size);
+
+ if (tiled) {
+ set_tiling.handle = fb_info->gem_handle;
+ set_tiling.tiling_mode = I915_TILING_X;
+ set_tiling.stride = stride;
+ if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling)) {
+ fprintf(stderr, "set tiling failed: %s (stride=%d, size=%d)\n",
+ strerror(errno), stride, size);
+ return NULL;
+ }
+ }
+
+ fb_ptr = gem_mmap(fd, fb_info->gem_handle, size, PROT_READ | PROT_WRITE);
+
+ fb_info->stride = stride;
+ fb_info->size = size;
+
+ return cairo_image_surface_create_for_data((unsigned char *)fb_ptr,
+ format, width, height,
+ stride);
+}
+
+static void
+paint_color_gradient(cairo_t *cr, int x, int y, int w, int h,
+ int r, int g, int b)
+{
+ cairo_pattern_t *pat;
+
+ pat = cairo_pattern_create_linear(x, y, x + w, y + h);
+ cairo_pattern_add_color_stop_rgba(pat, 1, 0, 0, 0, 1);
+ cairo_pattern_add_color_stop_rgba(pat, 0, r, g, b, 1);
+
+ cairo_rectangle(cr, x, y, w, h);
+ cairo_set_source(cr, pat);
+ cairo_fill(cr);
+ cairo_pattern_destroy(pat);
+}
+
+static void
+paint_test_patterns(cairo_t *cr, int width, int height)
+{
+ double gr_height, gr_width;
+ int x, y;
+
+ y = height * 0.10;
+ gr_width = width * 0.75;
+ gr_height = height * 0.08;
+ x = (width / 2) - (gr_width / 2);
+
+ paint_color_gradient(cr, x, y, gr_width, gr_height, 1, 0, 0);
+
+ y += gr_height;
+ paint_color_gradient(cr, x, y, gr_width, gr_height, 0, 1, 0);
+
+ y += gr_height;
+ paint_color_gradient(cr, x, y, gr_width, gr_height, 0, 0, 1);
+
+ y += gr_height;
+ paint_color_gradient(cr, x, y, gr_width, gr_height, 1, 1, 1);
+}
+
+enum corner {
+ topleft,
+ topright,
+ bottomleft,
+ bottomright,
+};
+
+static void
+paint_marker(cairo_t *cr, int x, int y, char *str, enum corner text_location)
+{
+ cairo_text_extents_t extents;
+ int xoff, yoff;
+
+ cairo_set_font_size(cr, 18);
+ cairo_text_extents(cr, str, &extents);
+
+ switch (text_location) {
+ case topleft:
+ xoff = -20;
+ xoff -= extents.width;
+ yoff = -20;
+ break;
+ case topright:
+ xoff = 20;
+ yoff = -20;
+ break;
+ case bottomleft:
+ xoff = -20;
+ xoff -= extents.width;
+ yoff = 20;
+ break;
+ case bottomright:
+ xoff = 20;
+ yoff = 20;
+ break;
+ default:
+ xoff = 0;
+ yoff = 0;
+ }
+
+ cairo_move_to(cr, x, y - 20);
+ cairo_line_to(cr, x, y + 20);
+ cairo_move_to(cr, x - 20, y);
+ cairo_line_to(cr, x + 20, y);
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, x, y, 10, 0, M_PI * 2);
+ cairo_set_line_width(cr, 4);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_stroke_preserve(cr);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_set_line_width(cr, 2);
+ cairo_stroke(cr);
+
+ cairo_move_to(cr, x + xoff, y + yoff);
+ cairo_text_path(cr, str);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_stroke_preserve(cr);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+}
+
+unsigned int kmstest_create_fb(int fd, int width, int height, int bpp,
+ int depth, bool tiled,
+ struct kmstest_fb *fb_info,
+ kmstest_paint_func paint_func,
+ void *func_arg)
+{
+ cairo_surface_t *surface;
+ cairo_status_t status;
+ cairo_t *cr;
+ char buf[128];
+ int ret;
+ unsigned int fb_id;
+
+ surface = paint_allocate_surface(fd, width, height, depth, bpp,
+ tiled, fb_info);
+ assert(surface);
+
+ cr = cairo_create(surface);
+
+ paint_test_patterns(cr, width, height);
+
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
+
+ /* Paint corner markers */
+ snprintf(buf, sizeof buf, "(%d, %d)", 0, 0);
+ paint_marker(cr, 0, 0, buf, bottomright);
+ snprintf(buf, sizeof buf, "(%d, %d)", width, 0);
+ paint_marker(cr, width, 0, buf, bottomleft);
+ snprintf(buf, sizeof buf, "(%d, %d)", 0, height);
+ paint_marker(cr, 0, height, buf, topright);
+ snprintf(buf, sizeof buf, "(%d, %d)", width, height);
+ paint_marker(cr, width, height, buf, topleft);
+
+ if (paint_func)
+ paint_func(cr, width, height, func_arg);
+
+ status = cairo_status(cr);
+ assert(!status);
+ cairo_destroy(cr);
+
+ ret = drmModeAddFB(fd, width, height, depth, bpp,
+ fb_info->stride,
+ fb_info->gem_handle, &fb_id);
+
+ assert(ret == 0);
+ cairo_surface_destroy(surface);
+
+ fb_info->fb_id = fb_id;
+
+ return fb_id;
+}
+
+void kmstest_dump_mode(drmModeModeInfo *mode)
+{
+ printf(" %s %d %d %d %d %d %d %d %d %d 0x%x 0x%x %d\n",
+ mode->name,
+ mode->vrefresh,
+ mode->hdisplay,
+ mode->hsync_start,
+ mode->hsync_end,
+ mode->htotal,
+ mode->vdisplay,
+ mode->vsync_start,
+ mode->vsync_end,
+ mode->vtotal,
+ mode->flags,
+ mode->type,
+ mode->clock);
+ fflush(stdout);
+}
+
diff --git a/lib/drmtest.h b/lib/drmtest.h
new file mode 100644
index 00000000..0cffa394
--- /dev/null
+++ b/lib/drmtest.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <cairo.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "intel_batchbuffer.h"
+
+int drm_get_card(int master);
+int drm_open_any(void);
+int drm_open_any_master(void);
+
+void gem_quiescent_gpu(int fd);
+
+/* ioctl wrappers and similar stuff for bare metal testing */
+void gem_set_tiling(int fd, uint32_t handle, int tiling, int stride);
+void gem_close(int fd, uint32_t handle);
+void gem_write(int fd, uint32_t handle, uint32_t offset, const void *buf, uint32_t size);
+void gem_read(int fd, uint32_t handle, uint32_t offset, void *buf, uint32_t size);
+void gem_set_domain(int fd, uint32_t handle,
+ uint32_t read_domains, uint32_t write_domain);
+void gem_sync(int fd, uint32_t handle);
+uint32_t gem_create(int fd, int size);
+
+void *gem_mmap__gtt(int fd, uint32_t handle, int size, int prot);
+void *gem_mmap__cpu(int fd, uint32_t handle, int size, int prot);
+#define gem_mmap gem_mmap__gtt
+
+uint64_t gem_aperture_size(int fd);
+uint64_t gem_mappable_aperture_size(void);
+int gem_madvise(int fd, uint32_t handle, int state);
+
+/* feature test helpers */
+bool gem_uses_aliasing_ppgtt(int fd);
+int gem_available_fences(int fd);
+
+/* prime */
+int prime_handle_to_fd(int fd, uint32_t handle);
+uint32_t prime_fd_to_handle(int fd, int dma_buf_fd);
+
+/* generally useful helpers */
+void drmtest_fork_signal_helper(void);
+void drmtest_stop_signal_helper(void);
+void drmtest_exchange_int(void *array, unsigned i, unsigned j);
+void drmtest_permute_array(void *array, unsigned size,
+ void (*exchange_func)(void *array,
+ unsigned i,
+ unsigned j));
+void drmtest_progress(const char *header, uint64_t i, uint64_t total);
+
+/* helpers based upon the libdrm buffer manager */
+void drmtest_init_aperture_trashers(drm_intel_bufmgr *bufmgr);
+void drmtest_trash_aperture(void);
+void drmtest_cleanup_aperture_trashers(void);
+
+/* helpers to create nice-looking framebuffers */
+struct kmstest_fb {
+ uint32_t fb_id;
+ uint32_t gem_handle;
+ unsigned stride;
+ unsigned size;
+};
+
+typedef void (*kmstest_paint_func)(cairo_t *cr, int width, int height, void *priv);
+
+unsigned int kmstest_create_fb(int fd, int width, int height, int bpp,
+ int depth, bool tiled,
+ struct kmstest_fb *fb_info,
+ kmstest_paint_func paint_func,
+ void *func_arg);
+void kmstest_dump_mode(drmModeModeInfo *mode);
+
+inline static void _do_or_die(const char *function, int line, int ret)
+{
+ if (ret == 0)
+ return;
+
+ fprintf(stderr, "%s:%d failed, ret=%d, errno=%d\n",
+ function, line, ret, errno);
+ abort();
+}
+#define do_or_die(x) _do_or_die(__FUNCTION__, __LINE__, x)
+#define do_ioctl(fd, ptr, sz) do_or_die(drmIoctl((fd), (ptr), (sz)))
diff --git a/lib/gen6_render.h b/lib/gen6_render.h
new file mode 100644
index 00000000..2c63c9e7
--- /dev/null
+++ b/lib/gen6_render.h
@@ -0,0 +1,1553 @@
+#ifndef GEN6_RENDER_H
+#define GEN6_RENDER_H
+
+#define GEN6_3D(Pipeline,Opcode,Subopcode) ((3 << 29) | \
+ ((Pipeline) << 27) | \
+ ((Opcode) << 24) | \
+ ((Subopcode) << 16))
+
+#define GEN6_STATE_BASE_ADDRESS GEN6_3D(0, 1, 1)
+#define GEN6_STATE_SIP GEN6_3D(0, 1, 2)
+
+#define GEN6_PIPELINE_SELECT GEN6_3D(1, 1, 4)
+
+#define GEN6_MEDIA_STATE_POINTERS GEN6_3D(2, 0, 0)
+#define GEN6_MEDIA_OBJECT GEN6_3D(2, 1, 0)
+
+#define GEN6_3DSTATE_BINDING_TABLE_POINTERS GEN6_3D(3, 0, 1)
+# define GEN6_3DSTATE_BINDING_TABLE_MODIFY_PS (1 << 12)/* for GEN6 */
+# define GEN6_3DSTATE_BINDING_TABLE_MODIFY_GS (1 << 9) /* for GEN6 */
+# define GEN6_3DSTATE_BINDING_TABLE_MODIFY_VS (1 << 8) /* for GEN6 */
+
+#define GEN6_3DSTATE_VERTEX_BUFFERS GEN6_3D(3, 0, 8)
+#define GEN6_3DSTATE_VERTEX_ELEMENTS GEN6_3D(3, 0, 9)
+#define GEN6_3DSTATE_INDEX_BUFFER GEN6_3D(3, 0, 0xa)
+#define GEN6_3DSTATE_VF_STATISTICS GEN6_3D(3, 0, 0xb)
+
+#define GEN6_3DSTATE_DRAWING_RECTANGLE GEN6_3D(3, 1, 0)
+#define GEN6_3DSTATE_CONSTANT_COLOR GEN6_3D(3, 1, 1)
+#define GEN6_3DSTATE_SAMPLER_PALETTE_LOAD GEN6_3D(3, 1, 2)
+#define GEN6_3DSTATE_CHROMA_KEY GEN6_3D(3, 1, 4)
+#define GEN6_3DSTATE_DEPTH_BUFFER GEN6_3D(3, 1, 5)
+# define GEN6_3DSTATE_DEPTH_BUFFER_TYPE_SHIFT 29
+# define GEN6_3DSTATE_DEPTH_BUFFER_FORMAT_SHIFT 18
+
+#define GEN6_3DSTATE_POLY_STIPPLE_OFFSET GEN6_3D(3, 1, 6)
+#define GEN6_3DSTATE_POLY_STIPPLE_PATTERN GEN6_3D(3, 1, 7)
+#define GEN6_3DSTATE_LINE_STIPPLE GEN6_3D(3, 1, 8)
+#define GEN6_3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP GEN6_3D(3, 1, 9)
+/* These two are BLC and CTG only, not BW or CL */
+#define GEN6_3DSTATE_AA_LINE_PARAMS GEN6_3D(3, 1, 0xa)
+#define GEN6_3DSTATE_GS_SVB_INDEX GEN6_3D(3, 1, 0xb)
+
+#define GEN6_3DPRIMITIVE GEN6_3D(3, 3, 0)
+
+#define GEN6_3DSTATE_CLEAR_PARAMS GEN6_3D(3, 1, 0x10)
+/* DW1 */
+# define GEN6_3DSTATE_DEPTH_CLEAR_VALID (1 << 15)
+
+#define GEN6_3DSTATE_SAMPLER_STATE_POINTERS GEN6_3D(3, 0, 0x02)
+# define GEN6_3DSTATE_SAMPLER_STATE_MODIFY_PS (1 << 12)
+# define GEN6_3DSTATE_SAMPLER_STATE_MODIFY_GS (1 << 9)
+# define GEN6_3DSTATE_SAMPLER_STATE_MODIFY_VS (1 << 8)
+
+#define GEN6_3DSTATE_URB GEN6_3D(3, 0, 0x05)
+/* DW1 */
+# define GEN6_3DSTATE_URB_VS_SIZE_SHIFT 16
+# define GEN6_3DSTATE_URB_VS_ENTRIES_SHIFT 0
+/* DW2 */
+# define GEN6_3DSTATE_URB_GS_ENTRIES_SHIFT 8
+# define GEN6_3DSTATE_URB_GS_SIZE_SHIFT 0
+
+#define GEN6_3DSTATE_VIEWPORT_STATE_POINTERS GEN6_3D(3, 0, 0x0d)
+# define GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_CC (1 << 12)
+# define GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_SF (1 << 11)
+# define GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_CLIP (1 << 10)
+
+#define GEN6_3DSTATE_CC_STATE_POINTERS GEN6_3D(3, 0, 0x0e)
+
+#define GEN6_3DSTATE_VS GEN6_3D(3, 0, 0x10)
+
+#define GEN6_3DSTATE_GS GEN6_3D(3, 0, 0x11)
+/* DW4 */
+# define GEN6_3DSTATE_GS_DISPATCH_START_GRF_SHIFT 0
+
+#define GEN6_3DSTATE_CLIP GEN6_3D(3, 0, 0x12)
+
+#define GEN6_3DSTATE_SF GEN6_3D(3, 0, 0x13)
+/* DW1 */
+# define GEN6_3DSTATE_SF_NUM_OUTPUTS_SHIFT 22
+# define GEN6_3DSTATE_SF_URB_ENTRY_READ_LENGTH_SHIFT 11
+# define GEN6_3DSTATE_SF_URB_ENTRY_READ_OFFSET_SHIFT 4
+/* DW2 */
+/* DW3 */
+# define GEN6_3DSTATE_SF_CULL_BOTH (0 << 29)
+# define GEN6_3DSTATE_SF_CULL_NONE (1 << 29)
+# define GEN6_3DSTATE_SF_CULL_FRONT (2 << 29)
+# define GEN6_3DSTATE_SF_CULL_BACK (3 << 29)
+/* DW4 */
+# define GEN6_3DSTATE_SF_TRI_PROVOKE_SHIFT 29
+# define GEN6_3DSTATE_SF_LINE_PROVOKE_SHIFT 27
+# define GEN6_3DSTATE_SF_TRIFAN_PROVOKE_SHIFT 25
+
+#define GEN6_3DSTATE_WM GEN6_3D(3, 0, 0x14)
+/* DW2 */
+# define GEN6_3DSTATE_WM_SAMPLER_COUNT_SHIFT 27
+# define GEN6_3DSTATE_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT 18
+/* DW4 */
+# define GEN6_3DSTATE_WM_DISPATCH_START_GRF_0_SHIFT 16
+/* DW5 */
+# define GEN6_3DSTATE_WM_MAX_THREADS_SHIFT 25
+# define GEN6_3DSTATE_WM_DISPATCH_ENABLE (1 << 19)
+# define GEN6_3DSTATE_WM_16_DISPATCH_ENABLE (1 << 1)
+# define GEN6_3DSTATE_WM_8_DISPATCH_ENABLE (1 << 0)
+/* DW6 */
+# define GEN6_3DSTATE_WM_NUM_SF_OUTPUTS_SHIFT 20
+# define GEN6_3DSTATE_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC (1 << 15)
+# define GEN6_3DSTATE_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC (1 << 14)
+# define GEN6_3DSTATE_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC (1 << 13)
+# define GEN6_3DSTATE_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC (1 << 12)
+# define GEN6_3DSTATE_WM_PERSPECTIVE_CENTROID_BARYCENTRIC (1 << 11)
+# define GEN6_3DSTATE_WM_PERSPECTIVE_PIXEL_BARYCENTRIC (1 << 10)
+
+
+#define GEN6_3DSTATE_CONSTANT_VS GEN6_3D(3, 0, 0x15)
+#define GEN6_3DSTATE_CONSTANT_GS GEN6_3D(3, 0, 0x16)
+#define GEN6_3DSTATE_CONSTANT_PS GEN6_3D(3, 0, 0x17)
+
+#define GEN6_3DSTATE_SAMPLE_MASK GEN6_3D(3, 0, 0x18)
+
+#define GEN6_3DSTATE_MULTISAMPLE GEN6_3D(3, 1, 0x0d)
+/* DW1 */
+# define GEN6_3DSTATE_MULTISAMPLE_PIXEL_LOCATION_CENTER (0 << 4)
+# define GEN6_3DSTATE_MULTISAMPLE_PIXEL_LOCATION_UPPER_LEFT (1 << 4)
+# define GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_1 (0 << 1)
+# define GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_4 (2 << 1)
+# define GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_8 (3 << 1)
+
+#define PIPELINE_SELECT_3D 0
+#define PIPELINE_SELECT_MEDIA 1
+
+/* for GEN6_STATE_BASE_ADDRESS */
+#define BASE_ADDRESS_MODIFY (1 << 0)
+
+/* for GEN6_PIPE_CONTROL */
+#define GEN6_PIPE_CONTROL_NOWRITE (0 << 14)
+#define GEN6_PIPE_CONTROL_WRITE_QWORD (1 << 14)
+#define GEN6_PIPE_CONTROL_WRITE_DEPTH (2 << 14)
+#define GEN6_PIPE_CONTROL_WRITE_TIME (3 << 14)
+#define GEN6_PIPE_CONTROL_DEPTH_STALL (1 << 13)
+#define GEN6_PIPE_CONTROL_WC_FLUSH (1 << 12)
+#define GEN6_PIPE_CONTROL_IS_FLUSH (1 << 11)
+#define GEN6_PIPE_CONTROL_TC_FLUSH (1 << 10)
+#define GEN6_PIPE_CONTROL_NOTIFY_ENABLE (1 << 8)
+#define GEN6_PIPE_CONTROL_GLOBAL_GTT (1 << 2)
+#define GEN6_PIPE_CONTROL_LOCAL_PGTT (0 << 2)
+#define GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH (1 << 0)
+
+/* VERTEX_BUFFER_STATE Structure */
+#define VB0_BUFFER_INDEX_SHIFT 26
+#define VB0_VERTEXDATA (0 << 20)
+#define VB0_INSTANCEDATA (1 << 20)
+#define VB0_BUFFER_PITCH_SHIFT 0
+
+/* VERTEX_ELEMENT_STATE Structure */
+#define VE0_VERTEX_BUFFER_INDEX_SHIFT 26 /* for GEN6 */
+#define VE0_VALID (1 << 25) /* for GEN6 */
+#define VE0_FORMAT_SHIFT 16
+#define VE0_OFFSET_SHIFT 0
+#define VE1_VFCOMPONENT_0_SHIFT 28
+#define VE1_VFCOMPONENT_1_SHIFT 24
+#define VE1_VFCOMPONENT_2_SHIFT 20
+#define VE1_VFCOMPONENT_3_SHIFT 16
+#define VE1_DESTINATION_ELEMENT_OFFSET_SHIFT 0
+
+/* 3DPRIMITIVE bits */
+#define GEN6_3DPRIMITIVE_VERTEX_SEQUENTIAL (0 << 15)
+#define GEN6_3DPRIMITIVE_VERTEX_RANDOM (1 << 15)
+/* Primitive types are in gen6_defines.h */
+#define GEN6_3DPRIMITIVE_TOPOLOGY_SHIFT 10
+
+#define GEN6_SVG_CTL 0x7400
+
+#define GEN6_SVG_CTL_GS_BA (0 << 8)
+#define GEN6_SVG_CTL_SS_BA (1 << 8)
+#define GEN6_SVG_CTL_IO_BA (2 << 8)
+#define GEN6_SVG_CTL_GS_AUB (3 << 8)
+#define GEN6_SVG_CTL_IO_AUB (4 << 8)
+#define GEN6_SVG_CTL_SIP (5 << 8)
+
+#define GEN6_SVG_RDATA 0x7404
+#define GEN6_SVG_WORK_CTL 0x7408
+
+#define GEN6_VF_CTL 0x7500
+
+#define GEN6_VF_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID (0 << 8)
+#define GEN6_VF_CTL_SNAPSHOT_MUX_SELECT_VF_DEBUG (1 << 8)
+#define GEN6_VF_CTL_SNAPSHOT_TYPE_VERTEX_SEQUENCE (0 << 4)
+#define GEN6_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX (1 << 4)
+#define GEN6_VF_CTL_SKIP_INITIAL_PRIMITIVES (1 << 3)
+#define GEN6_VF_CTL_MAX_PRIMITIVES_LIMIT_ENABLE (1 << 2)
+#define GEN6_VF_CTL_VERTEX_RANGE_LIMIT_ENABLE (1 << 1)
+#define GEN6_VF_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_VF_STRG_VAL 0x7504
+#define GEN6_VF_STR_VL_OVR 0x7508
+#define GEN6_VF_VC_OVR 0x750c
+#define GEN6_VF_STR_PSKIP 0x7510
+#define GEN6_VF_MAX_PRIM 0x7514
+#define GEN6_VF_RDATA 0x7518
+
+#define GEN6_VS_CTL 0x7600
+#define GEN6_VS_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_VS_CTL_SNAPSHOT_MUX_VERTEX_0 (0 << 8)
+#define GEN6_VS_CTL_SNAPSHOT_MUX_VERTEX_1 (1 << 8)
+#define GEN6_VS_CTL_SNAPSHOT_MUX_VALID_COUNT (2 << 8)
+#define GEN6_VS_CTL_SNAPSHOT_MUX_VS_KERNEL_POINTER (3 << 8)
+#define GEN6_VS_CTL_SNAPSHOT_ALL_THREADS (1 << 2)
+#define GEN6_VS_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1)
+#define GEN6_VS_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_VS_STRG_VAL 0x7604
+#define GEN6_VS_RDATA 0x7608
+
+#define GEN6_SF_CTL 0x7b00
+#define GEN6_SF_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_0_FF_ID (0 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_0_REL_COUNT (1 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_1_FF_ID (2 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_1_REL_COUNT (3 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_2_FF_ID (4 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_2_REL_COUNT (5 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT (6 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_SF_KERNEL_POINTER (7 << 8)
+#define GEN6_SF_CTL_MIN_MAX_PRIMITIVE_RANGE_ENABLE (1 << 4)
+#define GEN6_SF_CTL_DEBUG_CLIP_RECTANGLE_ENABLE (1 << 3)
+#define GEN6_SF_CTL_SNAPSHOT_ALL_THREADS (1 << 2)
+#define GEN6_SF_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1)
+#define GEN6_SF_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_SF_STRG_VAL 0x7b04
+#define GEN6_SF_RDATA 0x7b18
+
+#define GEN6_WIZ_CTL 0x7c00
+#define GEN6_WIZ_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_WIZ_CTL_SUBSPAN_INSTANCE_SHIFT 16
+#define GEN6_WIZ_CTL_SNAPSHOT_MUX_WIZ_KERNEL_POINTER (0 << 8)
+#define GEN6_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE (1 << 8)
+#define GEN6_WIZ_CTL_SNAPSHOT_MUX_PRIMITIVE_SEQUENCE (2 << 8)
+#define GEN6_WIZ_CTL_SINGLE_SUBSPAN_DISPATCH (1 << 6)
+#define GEN6_WIZ_CTL_IGNORE_COLOR_SCOREBOARD_STALLS (1 << 5)
+#define GEN6_WIZ_CTL_ENABLE_SUBSPAN_INSTANCE_COMPARE (1 << 4)
+#define GEN6_WIZ_CTL_USE_UPSTREAM_SNAPSHOT_FLAG (1 << 3)
+#define GEN6_WIZ_CTL_SNAPSHOT_ALL_THREADS (1 << 2)
+#define GEN6_WIZ_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1)
+#define GEN6_WIZ_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_WIZ_STRG_VAL 0x7c04
+#define GEN6_WIZ_RDATA 0x7c18
+
+#define GEN6_TS_CTL 0x7e00
+#define GEN6_TS_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_TS_CTL_SNAPSHOT_MESSAGE_ERROR (0 << 8)
+#define GEN6_TS_CTL_SNAPSHOT_INTERFACE_DESCRIPTOR (3 << 8)
+#define GEN6_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS (1 << 2)
+#define GEN6_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS (1 << 1)
+#define GEN6_TS_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_TS_STRG_VAL 0x7e04
+#define GEN6_TS_RDATA 0x7e08
+
+/* TD_CTL on gen6 is 0x7000, to not break stuff which depends on this... */
+#ifndef GEN6_TD_CTL
+#define GEN6_TD_CTL 0x8000
+#endif
+#define GEN6_TD_CTL_MUX_SHIFT 8
+#define GEN6_TD_CTL_EXTERNAL_HALT_R0_DEBUG_MATCH (1 << 7)
+#define GEN6_TD_CTL_FORCE_EXTERNAL_HALT (1 << 6)
+#define GEN6_TD_CTL_EXCEPTION_MASK_OVERRIDE (1 << 5)
+#define GEN6_TD_CTL_FORCE_THREAD_BREAKPOINT_ENABLE (1 << 4)
+#define GEN6_TD_CTL_BREAKPOINT_ENABLE (1 << 2)
+#define GEN6_TD_CTL2 0x8004
+#define GEN6_TD_CTL2_ILLEGAL_OPCODE_EXCEPTION_OVERRIDE (1 << 28)
+#define GEN6_TD_CTL2_MASKSTACK_EXCEPTION_OVERRIDE (1 << 26)
+#define GEN6_TD_CTL2_SOFTWARE_EXCEPTION_OVERRIDE (1 << 25)
+#define GEN6_TD_CTL2_ACTIVE_THREAD_LIMIT_SHIFT 16
+#define GEN6_TD_CTL2_ACTIVE_THREAD_LIMIT_ENABLE (1 << 8)
+#define GEN6_TD_CTL2_THREAD_SPAWNER_EXECUTION_MASK_ENABLE (1 << 7)
+#define GEN6_TD_CTL2_WIZ_EXECUTION_MASK_ENABLE (1 << 6)
+#define GEN6_TD_CTL2_SF_EXECUTION_MASK_ENABLE (1 << 5)
+#define GEN6_TD_CTL2_CLIPPER_EXECUTION_MASK_ENABLE (1 << 4)
+#define GEN6_TD_CTL2_GS_EXECUTION_MASK_ENABLE (1 << 3)
+#define GEN6_TD_CTL2_VS_EXECUTION_MASK_ENABLE (1 << 0)
+#define GEN6_TD_VF_VS_EMSK 0x8008
+#define GEN6_TD_GS_EMSK 0x800c
+#define GEN6_TD_CLIP_EMSK 0x8010
+#define GEN6_TD_SF_EMSK 0x8014
+#define GEN6_TD_WIZ_EMSK 0x8018
+#define GEN6_TD_0_6_EHTRG_VAL 0x801c
+#define GEN6_TD_0_7_EHTRG_VAL 0x8020
+#define GEN6_TD_0_6_EHTRG_MSK 0x8024
+#define GEN6_TD_0_7_EHTRG_MSK 0x8028
+#define GEN6_TD_RDATA 0x802c
+#define GEN6_TD_TS_EMSK 0x8030
+
+#define GEN6_EU_CTL 0x8800
+#define GEN6_EU_CTL_SELECT_SHIFT 16
+#define GEN6_EU_CTL_DATA_MUX_SHIFT 8
+#define GEN6_EU_ATT_0 0x8810
+#define GEN6_EU_ATT_1 0x8814
+#define GEN6_EU_ATT_DATA_0 0x8820
+#define GEN6_EU_ATT_DATA_1 0x8824
+#define GEN6_EU_ATT_CLR_0 0x8830
+#define GEN6_EU_ATT_CLR_1 0x8834
+#define GEN6_EU_RDATA 0x8840
+
+#define GEN6_3D(Pipeline,Opcode,Subopcode) ((3 << 29) | \
+ ((Pipeline) << 27) | \
+ ((Opcode) << 24) | \
+ ((Subopcode) << 16))
+
+#define GEN6_STATE_BASE_ADDRESS GEN6_3D(0, 1, 1)
+#define GEN6_STATE_SIP GEN6_3D(0, 1, 2)
+
+#define GEN6_PIPELINE_SELECT GEN6_3D(1, 1, 4)
+
+#define GEN6_MEDIA_STATE_POINTERS GEN6_3D(2, 0, 0)
+#define GEN6_MEDIA_OBJECT GEN6_3D(2, 1, 0)
+
+#define GEN6_3DSTATE_BINDING_TABLE_POINTERS GEN6_3D(3, 0, 1)
+# define GEN6_3DSTATE_BINDING_TABLE_MODIFY_PS (1 << 12)/* for GEN6 */
+# define GEN6_3DSTATE_BINDING_TABLE_MODIFY_GS (1 << 9) /* for GEN6 */
+# define GEN6_3DSTATE_BINDING_TABLE_MODIFY_VS (1 << 8) /* for GEN6 */
+
+#define GEN6_3DSTATE_VERTEX_BUFFERS GEN6_3D(3, 0, 8)
+#define GEN6_3DSTATE_VERTEX_ELEMENTS GEN6_3D(3, 0, 9)
+#define GEN6_3DSTATE_INDEX_BUFFER GEN6_3D(3, 0, 0xa)
+#define GEN6_3DSTATE_VF_STATISTICS GEN6_3D(3, 0, 0xb)
+
+#define GEN6_3DSTATE_DRAWING_RECTANGLE GEN6_3D(3, 1, 0)
+#define GEN6_3DSTATE_CONSTANT_COLOR GEN6_3D(3, 1, 1)
+#define GEN6_3DSTATE_SAMPLER_PALETTE_LOAD GEN6_3D(3, 1, 2)
+#define GEN6_3DSTATE_CHROMA_KEY GEN6_3D(3, 1, 4)
+#define GEN6_3DSTATE_DEPTH_BUFFER GEN6_3D(3, 1, 5)
+# define GEN6_3DSTATE_DEPTH_BUFFER_TYPE_SHIFT 29
+# define GEN6_3DSTATE_DEPTH_BUFFER_FORMAT_SHIFT 18
+
+#define GEN6_3DSTATE_POLY_STIPPLE_OFFSET GEN6_3D(3, 1, 6)
+#define GEN6_3DSTATE_POLY_STIPPLE_PATTERN GEN6_3D(3, 1, 7)
+#define GEN6_3DSTATE_LINE_STIPPLE GEN6_3D(3, 1, 8)
+#define GEN6_3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP GEN6_3D(3, 1, 9)
+/* These two are BLC and CTG only, not BW or CL */
+#define GEN6_3DSTATE_AA_LINE_PARAMS GEN6_3D(3, 1, 0xa)
+#define GEN6_3DSTATE_GS_SVB_INDEX GEN6_3D(3, 1, 0xb)
+
+#define GEN6_PIPE_CONTROL GEN6_3D(3, 2, 0)
+
+#define GEN6_3DPRIMITIVE GEN6_3D(3, 3, 0)
+
+#define GEN6_3DSTATE_CLEAR_PARAMS GEN6_3D(3, 1, 0x10)
+/* DW1 */
+# define GEN6_3DSTATE_DEPTH_CLEAR_VALID (1 << 15)
+
+/* for GEN6+ */
+#define GEN6_3DSTATE_SAMPLER_STATE_POINTERS GEN6_3D(3, 0, 0x02)
+# define GEN6_3DSTATE_SAMPLER_STATE_MODIFY_PS (1 << 12)
+# define GEN6_3DSTATE_SAMPLER_STATE_MODIFY_GS (1 << 9)
+# define GEN6_3DSTATE_SAMPLER_STATE_MODIFY_VS (1 << 8)
+
+#define GEN6_3DSTATE_URB GEN6_3D(3, 0, 0x05)
+/* DW1 */
+# define GEN6_3DSTATE_URB_VS_SIZE_SHIFT 16
+# define GEN6_3DSTATE_URB_VS_ENTRIES_SHIFT 0
+/* DW2 */
+# define GEN6_3DSTATE_URB_GS_ENTRIES_SHIFT 8
+# define GEN6_3DSTATE_URB_GS_SIZE_SHIFT 0
+
+#define GEN6_3DSTATE_VIEWPORT_STATE_POINTERS GEN6_3D(3, 0, 0x0d)
+# define GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_CC (1 << 12)
+# define GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_SF (1 << 11)
+# define GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_CLIP (1 << 10)
+
+#define GEN6_3DSTATE_CC_STATE_POINTERS GEN6_3D(3, 0, 0x0e)
+
+#define GEN6_3DSTATE_VS GEN6_3D(3, 0, 0x10)
+
+#define GEN6_3DSTATE_GS GEN6_3D(3, 0, 0x11)
+/* DW4 */
+# define GEN6_3DSTATE_GS_DISPATCH_START_GRF_SHIFT 0
+
+#define GEN6_3DSTATE_CLIP GEN6_3D(3, 0, 0x12)
+
+#define GEN6_3DSTATE_SF GEN6_3D(3, 0, 0x13)
+/* DW1 */
+# define GEN6_3DSTATE_SF_NUM_OUTPUTS_SHIFT 22
+# define GEN6_3DSTATE_SF_URB_ENTRY_READ_LENGTH_SHIFT 11
+# define GEN6_3DSTATE_SF_URB_ENTRY_READ_OFFSET_SHIFT 4
+/* DW2 */
+/* DW3 */
+# define GEN6_3DSTATE_SF_CULL_BOTH (0 << 29)
+# define GEN6_3DSTATE_SF_CULL_NONE (1 << 29)
+# define GEN6_3DSTATE_SF_CULL_FRONT (2 << 29)
+# define GEN6_3DSTATE_SF_CULL_BACK (3 << 29)
+/* DW4 */
+# define GEN6_3DSTATE_SF_TRI_PROVOKE_SHIFT 29
+# define GEN6_3DSTATE_SF_LINE_PROVOKE_SHIFT 27
+# define GEN6_3DSTATE_SF_TRIFAN_PROVOKE_SHIFT 25
+
+
+#define GEN6_3DSTATE_WM GEN6_3D(3, 0, 0x14)
+/* DW2 */
+# define GEN6_3DSTATE_WM_SAMPLER_COUNT_SHITF 27
+# define GEN6_3DSTATE_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT 18
+/* DW4 */
+# define GEN6_3DSTATE_WM_DISPATCH_START_GRF_0_SHIFT 16
+/* DW5 */
+# define GEN6_3DSTATE_WM_MAX_THREADS_SHIFT 25
+# define GEN6_3DSTATE_WM_DISPATCH_ENABLE (1 << 19)
+# define GEN6_3DSTATE_WM_16_DISPATCH_ENABLE (1 << 1)
+# define GEN6_3DSTATE_WM_8_DISPATCH_ENABLE (1 << 0)
+/* DW6 */
+# define GEN6_3DSTATE_WM_NUM_SF_OUTPUTS_SHIFT 20
+# define GEN6_3DSTATE_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC (1 << 15)
+# define GEN6_3DSTATE_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC (1 << 14)
+# define GEN6_3DSTATE_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC (1 << 13)
+# define GEN6_3DSTATE_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC (1 << 12)
+# define GEN6_3DSTATE_WM_PERSPECTIVE_CENTROID_BARYCENTRIC (1 << 11)
+# define GEN6_3DSTATE_WM_PERSPECTIVE_PIXEL_BARYCENTRIC (1 << 10)
+
+
+#define GEN6_3DSTATE_CONSTANT_VS GEN6_3D(3, 0, 0x15)
+#define GEN6_3DSTATE_CONSTANT_GS GEN6_3D(3, 0, 0x16)
+#define GEN6_3DSTATE_CONSTANT_PS GEN6_3D(3, 0, 0x17)
+
+#define GEN6_3DSTATE_SAMPLE_MASK GEN6_3D(3, 0, 0x18)
+
+#define GEN6_3DSTATE_MULTISAMPLE GEN6_3D(3, 1, 0x0d)
+/* DW1 */
+# define GEN6_3DSTATE_MULTISAMPLE_PIXEL_LOCATION_CENTER (0 << 4)
+# define GEN6_3DSTATE_MULTISAMPLE_PIXEL_LOCATION_UPPER_LEFT (1 << 4)
+# define GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_1 (0 << 1)
+# define GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_4 (2 << 1)
+# define GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_8 (3 << 1)
+
+#define PIPELINE_SELECT_3D 0
+#define PIPELINE_SELECT_MEDIA 1
+
+#define UF0_CS_REALLOC (1 << 13)
+#define UF0_VFE_REALLOC (1 << 12)
+#define UF0_SF_REALLOC (1 << 11)
+#define UF0_CLIP_REALLOC (1 << 10)
+#define UF0_GS_REALLOC (1 << 9)
+#define UF0_VS_REALLOC (1 << 8)
+#define UF1_CLIP_FENCE_SHIFT 20
+#define UF1_GS_FENCE_SHIFT 10
+#define UF1_VS_FENCE_SHIFT 0
+#define UF2_CS_FENCE_SHIFT 20
+#define UF2_VFE_FENCE_SHIFT 10
+#define UF2_SF_FENCE_SHIFT 0
+
+/* for GEN6_STATE_BASE_ADDRESS */
+#define BASE_ADDRESS_MODIFY (1 << 0)
+
+/* for GEN6_3DSTATE_PIPELINED_POINTERS */
+#define GEN6_GS_DISABLE 0
+#define GEN6_GS_ENABLE 1
+#define GEN6_CLIP_DISABLE 0
+#define GEN6_CLIP_ENABLE 1
+
+/* for GEN6_PIPE_CONTROL */
+#define GEN6_PIPE_CONTROL_NOWRITE (0 << 14)
+#define GEN6_PIPE_CONTROL_WRITE_QWORD (1 << 14)
+#define GEN6_PIPE_CONTROL_WRITE_DEPTH (2 << 14)
+#define GEN6_PIPE_CONTROL_WRITE_TIME (3 << 14)
+#define GEN6_PIPE_CONTROL_DEPTH_STALL (1 << 13)
+#define GEN6_PIPE_CONTROL_WC_FLUSH (1 << 12)
+#define GEN6_PIPE_CONTROL_IS_FLUSH (1 << 11)
+#define GEN6_PIPE_CONTROL_TC_FLUSH (1 << 10)
+#define GEN6_PIPE_CONTROL_NOTIFY_ENABLE (1 << 8)
+#define GEN6_PIPE_CONTROL_GLOBAL_GTT (1 << 2)
+#define GEN6_PIPE_CONTROL_LOCAL_PGTT (0 << 2)
+#define GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH (1 << 0)
+
+/* 3DPRIMITIVE bits */
+#define GEN6_3DPRIMITIVE_VERTEX_SEQUENTIAL (0 << 15)
+#define GEN6_3DPRIMITIVE_VERTEX_RANDOM (1 << 15)
+/* Primitive types are in gen6_defines.h */
+#define GEN6_3DPRIMITIVE_TOPOLOGY_SHIFT 10
+
+#define GEN6_SVG_CTL 0x7400
+
+#define GEN6_SVG_CTL_GS_BA (0 << 8)
+#define GEN6_SVG_CTL_SS_BA (1 << 8)
+#define GEN6_SVG_CTL_IO_BA (2 << 8)
+#define GEN6_SVG_CTL_GS_AUB (3 << 8)
+#define GEN6_SVG_CTL_IO_AUB (4 << 8)
+#define GEN6_SVG_CTL_SIP (5 << 8)
+
+#define GEN6_SVG_RDATA 0x7404
+#define GEN6_SVG_WORK_CTL 0x7408
+
+#define GEN6_VF_CTL 0x7500
+
+#define GEN6_VF_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID (0 << 8)
+#define GEN6_VF_CTL_SNAPSHOT_MUX_SELECT_VF_DEBUG (1 << 8)
+#define GEN6_VF_CTL_SNAPSHOT_TYPE_VERTEX_SEQUENCE (0 << 4)
+#define GEN6_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX (1 << 4)
+#define GEN6_VF_CTL_SKIP_INITIAL_PRIMITIVES (1 << 3)
+#define GEN6_VF_CTL_MAX_PRIMITIVES_LIMIT_ENABLE (1 << 2)
+#define GEN6_VF_CTL_VERTEX_RANGE_LIMIT_ENABLE (1 << 1)
+#define GEN6_VF_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_VF_STRG_VAL 0x7504
+#define GEN6_VF_STR_VL_OVR 0x7508
+#define GEN6_VF_VC_OVR 0x750c
+#define GEN6_VF_STR_PSKIP 0x7510
+#define GEN6_VF_MAX_PRIM 0x7514
+#define GEN6_VF_RDATA 0x7518
+
+#define GEN6_VS_CTL 0x7600
+#define GEN6_VS_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_VS_CTL_SNAPSHOT_MUX_VERTEX_0 (0 << 8)
+#define GEN6_VS_CTL_SNAPSHOT_MUX_VERTEX_1 (1 << 8)
+#define GEN6_VS_CTL_SNAPSHOT_MUX_VALID_COUNT (2 << 8)
+#define GEN6_VS_CTL_SNAPSHOT_MUX_VS_KERNEL_POINTER (3 << 8)
+#define GEN6_VS_CTL_SNAPSHOT_ALL_THREADS (1 << 2)
+#define GEN6_VS_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1)
+#define GEN6_VS_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_VS_STRG_VAL 0x7604
+#define GEN6_VS_RDATA 0x7608
+
+#define GEN6_SF_CTL 0x7b00
+#define GEN6_SF_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_0_FF_ID (0 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_0_REL_COUNT (1 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_1_FF_ID (2 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_1_REL_COUNT (3 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_2_FF_ID (4 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_2_REL_COUNT (5 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT (6 << 8)
+#define GEN6_SF_CTL_SNAPSHOT_MUX_SF_KERNEL_POINTER (7 << 8)
+#define GEN6_SF_CTL_MIN_MAX_PRIMITIVE_RANGE_ENABLE (1 << 4)
+#define GEN6_SF_CTL_DEBUG_CLIP_RECTANGLE_ENABLE (1 << 3)
+#define GEN6_SF_CTL_SNAPSHOT_ALL_THREADS (1 << 2)
+#define GEN6_SF_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1)
+#define GEN6_SF_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_SF_STRG_VAL 0x7b04
+#define GEN6_SF_RDATA 0x7b18
+
+#define GEN6_WIZ_CTL 0x7c00
+#define GEN6_WIZ_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_WIZ_CTL_SUBSPAN_INSTANCE_SHIFT 16
+#define GEN6_WIZ_CTL_SNAPSHOT_MUX_WIZ_KERNEL_POINTER (0 << 8)
+#define GEN6_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE (1 << 8)
+#define GEN6_WIZ_CTL_SNAPSHOT_MUX_PRIMITIVE_SEQUENCE (2 << 8)
+#define GEN6_WIZ_CTL_SINGLE_SUBSPAN_DISPATCH (1 << 6)
+#define GEN6_WIZ_CTL_IGNORE_COLOR_SCOREBOARD_STALLS (1 << 5)
+#define GEN6_WIZ_CTL_ENABLE_SUBSPAN_INSTANCE_COMPARE (1 << 4)
+#define GEN6_WIZ_CTL_USE_UPSTREAM_SNAPSHOT_FLAG (1 << 3)
+#define GEN6_WIZ_CTL_SNAPSHOT_ALL_THREADS (1 << 2)
+#define GEN6_WIZ_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1)
+#define GEN6_WIZ_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_WIZ_STRG_VAL 0x7c04
+#define GEN6_WIZ_RDATA 0x7c18
+
+#define GEN6_TS_CTL 0x7e00
+#define GEN6_TS_CTL_SNAPSHOT_COMPLETE (1 << 31)
+#define GEN6_TS_CTL_SNAPSHOT_MESSAGE_ERROR (0 << 8)
+#define GEN6_TS_CTL_SNAPSHOT_INTERFACE_DESCRIPTOR (3 << 8)
+#define GEN6_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS (1 << 2)
+#define GEN6_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS (1 << 1)
+#define GEN6_TS_CTL_SNAPSHOT_ENABLE (1 << 0)
+
+#define GEN6_TS_STRG_VAL 0x7e04
+#define GEN6_TS_RDATA 0x7e08
+
+/* TD_CTL on gen6 is 0x7000, to not break stuff which depends on this... */
+#ifndef GEN6_TD_CTL
+#define GEN6_TD_CTL 0x8000
+#endif
+#define GEN6_TD_CTL_MUX_SHIFT 8
+#define GEN6_TD_CTL_EXTERNAL_HALT_R0_DEBUG_MATCH (1 << 7)
+#define GEN6_TD_CTL_FORCE_EXTERNAL_HALT (1 << 6)
+#define GEN6_TD_CTL_EXCEPTION_MASK_OVERRIDE (1 << 5)
+#define GEN6_TD_CTL_FORCE_THREAD_BREAKPOINT_ENABLE (1 << 4)
+#define GEN6_TD_CTL_BREAKPOINT_ENABLE (1 << 2)
+#define GEN6_TD_CTL2 0x8004
+#define GEN6_TD_CTL2_ILLEGAL_OPCODE_EXCEPTION_OVERRIDE (1 << 28)
+#define GEN6_TD_CTL2_MASKSTACK_EXCEPTION_OVERRIDE (1 << 26)
+#define GEN6_TD_CTL2_SOFTWARE_EXCEPTION_OVERRIDE (1 << 25)
+#define GEN6_TD_CTL2_ACTIVE_THREAD_LIMIT_SHIFT 16
+#define GEN6_TD_CTL2_ACTIVE_THREAD_LIMIT_ENABLE (1 << 8)
+#define GEN6_TD_CTL2_THREAD_SPAWNER_EXECUTION_MASK_ENABLE (1 << 7)
+#define GEN6_TD_CTL2_WIZ_EXECUTION_MASK_ENABLE (1 << 6)
+#define GEN6_TD_CTL2_SF_EXECUTION_MASK_ENABLE (1 << 5)
+#define GEN6_TD_CTL2_CLIPPER_EXECUTION_MASK_ENABLE (1 << 4)
+#define GEN6_TD_CTL2_GS_EXECUTION_MASK_ENABLE (1 << 3)
+#define GEN6_TD_CTL2_VS_EXECUTION_MASK_ENABLE (1 << 0)
+#define GEN6_TD_VF_VS_EMSK 0x8008
+#define GEN6_TD_GS_EMSK 0x800c
+#define GEN6_TD_CLIP_EMSK 0x8010
+#define GEN6_TD_SF_EMSK 0x8014
+#define GEN6_TD_WIZ_EMSK 0x8018
+#define GEN6_TD_0_6_EHTRG_VAL 0x801c
+#define GEN6_TD_0_7_EHTRG_VAL 0x8020
+#define GEN6_TD_0_6_EHTRG_MSK 0x8024
+#define GEN6_TD_0_7_EHTRG_MSK 0x8028
+#define GEN6_TD_RDATA 0x802c
+#define GEN6_TD_TS_EMSK 0x8030
+
+#define GEN6_EU_CTL 0x8800
+#define GEN6_EU_CTL_SELECT_SHIFT 16
+#define GEN6_EU_CTL_DATA_MUX_SHIFT 8
+#define GEN6_EU_ATT_0 0x8810
+#define GEN6_EU_ATT_1 0x8814
+#define GEN6_EU_ATT_DATA_0 0x8820
+#define GEN6_EU_ATT_DATA_1 0x8824
+#define GEN6_EU_ATT_CLR_0 0x8830
+#define GEN6_EU_ATT_CLR_1 0x8834
+#define GEN6_EU_RDATA 0x8840
+
+/* 3D state:
+ */
+#define _3DOP_3DSTATE_PIPELINED 0x0
+#define _3DOP_3DSTATE_NONPIPELINED 0x1
+#define _3DOP_3DCONTROL 0x2
+#define _3DOP_3DPRIMITIVE 0x3
+
+#define _3DSTATE_PIPELINED_POINTERS 0x00
+#define _3DSTATE_BINDING_TABLE_POINTERS 0x01
+#define _3DSTATE_VERTEX_BUFFERS 0x08
+#define _3DSTATE_VERTEX_ELEMENTS 0x09
+#define _3DSTATE_INDEX_BUFFER 0x0A
+#define _3DSTATE_VF_STATISTICS 0x0B
+#define _3DSTATE_DRAWING_RECTANGLE 0x00
+#define _3DSTATE_CONSTANT_COLOR 0x01
+#define _3DSTATE_SAMPLER_PALETTE_LOAD 0x02
+#define _3DSTATE_CHROMA_KEY 0x04
+#define _3DSTATE_DEPTH_BUFFER 0x05
+#define _3DSTATE_POLY_STIPPLE_OFFSET 0x06
+#define _3DSTATE_POLY_STIPPLE_PATTERN 0x07
+#define _3DSTATE_LINE_STIPPLE 0x08
+#define _3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP 0x09
+#define _3DCONTROL 0x00
+#define _3DPRIMITIVE 0x00
+
+#define _3DPRIM_POINTLIST 0x01
+#define _3DPRIM_LINELIST 0x02
+#define _3DPRIM_LINESTRIP 0x03
+#define _3DPRIM_TRILIST 0x04
+#define _3DPRIM_TRISTRIP 0x05
+#define _3DPRIM_TRIFAN 0x06
+#define _3DPRIM_QUADLIST 0x07
+#define _3DPRIM_QUADSTRIP 0x08
+#define _3DPRIM_LINELIST_ADJ 0x09
+#define _3DPRIM_LINESTRIP_ADJ 0x0A
+#define _3DPRIM_TRILIST_ADJ 0x0B
+#define _3DPRIM_TRISTRIP_ADJ 0x0C
+#define _3DPRIM_TRISTRIP_REVERSE 0x0D
+#define _3DPRIM_POLYGON 0x0E
+#define _3DPRIM_RECTLIST 0x0F
+#define _3DPRIM_LINELOOP 0x10
+#define _3DPRIM_POINTLIST_BF 0x11
+#define _3DPRIM_LINESTRIP_CONT 0x12
+#define _3DPRIM_LINESTRIP_BF 0x13
+#define _3DPRIM_LINESTRIP_CONT_BF 0x14
+#define _3DPRIM_TRIFAN_NOSTIPPLE 0x15
+
+#define _3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL 0
+#define _3DPRIM_VERTEXBUFFER_ACCESS_RANDOM 1
+
+#define GEN6_ANISORATIO_2 0
+#define GEN6_ANISORATIO_4 1
+#define GEN6_ANISORATIO_6 2
+#define GEN6_ANISORATIO_8 3
+#define GEN6_ANISORATIO_10 4
+#define GEN6_ANISORATIO_12 5
+#define GEN6_ANISORATIO_14 6
+#define GEN6_ANISORATIO_16 7
+
+#define GEN6_BLENDFACTOR_ONE 0x1
+#define GEN6_BLENDFACTOR_SRC_COLOR 0x2
+#define GEN6_BLENDFACTOR_SRC_ALPHA 0x3
+#define GEN6_BLENDFACTOR_DST_ALPHA 0x4
+#define GEN6_BLENDFACTOR_DST_COLOR 0x5
+#define GEN6_BLENDFACTOR_SRC_ALPHA_SATURATE 0x6
+#define GEN6_BLENDFACTOR_CONST_COLOR 0x7
+#define GEN6_BLENDFACTOR_CONST_ALPHA 0x8
+#define GEN6_BLENDFACTOR_SRC1_COLOR 0x9
+#define GEN6_BLENDFACTOR_SRC1_ALPHA 0x0A
+#define GEN6_BLENDFACTOR_ZERO 0x11
+#define GEN6_BLENDFACTOR_INV_SRC_COLOR 0x12
+#define GEN6_BLENDFACTOR_INV_SRC_ALPHA 0x13
+#define GEN6_BLENDFACTOR_INV_DST_ALPHA 0x14
+#define GEN6_BLENDFACTOR_INV_DST_COLOR 0x15
+#define GEN6_BLENDFACTOR_INV_CONST_COLOR 0x17
+#define GEN6_BLENDFACTOR_INV_CONST_ALPHA 0x18
+#define GEN6_BLENDFACTOR_INV_SRC1_COLOR 0x19
+#define GEN6_BLENDFACTOR_INV_SRC1_ALPHA 0x1A
+
+#define GEN6_BLENDFUNCTION_ADD 0
+#define GEN6_BLENDFUNCTION_SUBTRACT 1
+#define GEN6_BLENDFUNCTION_REVERSE_SUBTRACT 2
+#define GEN6_BLENDFUNCTION_MIN 3
+#define GEN6_BLENDFUNCTION_MAX 4
+
+#define GEN6_ALPHATEST_FORMAT_UNORM8 0
+#define GEN6_ALPHATEST_FORMAT_FLOAT32 1
+
+#define GEN6_CHROMAKEY_KILL_ON_ANY_MATCH 0
+#define GEN6_CHROMAKEY_REPLACE_BLACK 1
+
+#define GEN6_CLIP_API_OGL 0
+#define GEN6_CLIP_API_DX 1
+
+#define GEN6_CLIPMODE_NORMAL 0
+#define GEN6_CLIPMODE_CLIP_ALL 1
+#define GEN6_CLIPMODE_CLIP_NON_REJECTED 2
+#define GEN6_CLIPMODE_REJECT_ALL 3
+#define GEN6_CLIPMODE_ACCEPT_ALL 4
+
+#define GEN6_CLIP_NDCSPACE 0
+#define GEN6_CLIP_SCREENSPACE 1
+
+#define GEN6_COMPAREFUNCTION_ALWAYS 0
+#define GEN6_COMPAREFUNCTION_NEVER 1
+#define GEN6_COMPAREFUNCTION_LESS 2
+#define GEN6_COMPAREFUNCTION_EQUAL 3
+#define GEN6_COMPAREFUNCTION_LEQUAL 4
+#define GEN6_COMPAREFUNCTION_GREATER 5
+#define GEN6_COMPAREFUNCTION_NOTEQUAL 6
+#define GEN6_COMPAREFUNCTION_GEQUAL 7
+
+#define GEN6_COVERAGE_PIXELS_HALF 0
+#define GEN6_COVERAGE_PIXELS_1 1
+#define GEN6_COVERAGE_PIXELS_2 2
+#define GEN6_COVERAGE_PIXELS_4 3
+
+#define GEN6_CULLMODE_BOTH 0
+#define GEN6_CULLMODE_NONE 1
+#define GEN6_CULLMODE_FRONT 2
+#define GEN6_CULLMODE_BACK 3
+
+#define GEN6_DEFAULTCOLOR_R8G8B8A8_UNORM 0
+#define GEN6_DEFAULTCOLOR_R32G32B32A32_FLOAT 1
+
+#define GEN6_DEPTHFORMAT_D32_FLOAT_S8X24_UINT 0
+#define GEN6_DEPTHFORMAT_D32_FLOAT 1
+#define GEN6_DEPTHFORMAT_D24_UNORM_S8_UINT 2
+#define GEN6_DEPTHFORMAT_D16_UNORM 5
+
+#define GEN6_FLOATING_POINT_IEEE_754 0
+#define GEN6_FLOATING_POINT_NON_IEEE_754 1
+
+#define GEN6_FRONTWINDING_CW 0
+#define GEN6_FRONTWINDING_CCW 1
+
+#define GEN6_INDEX_BYTE 0
+#define GEN6_INDEX_WORD 1
+#define GEN6_INDEX_DWORD 2
+
+#define GEN6_LOGICOPFUNCTION_CLEAR 0
+#define GEN6_LOGICOPFUNCTION_NOR 1
+#define GEN6_LOGICOPFUNCTION_AND_INVERTED 2
+#define GEN6_LOGICOPFUNCTION_COPY_INVERTED 3
+#define GEN6_LOGICOPFUNCTION_AND_REVERSE 4
+#define GEN6_LOGICOPFUNCTION_INVERT 5
+#define GEN6_LOGICOPFUNCTION_XOR 6
+#define GEN6_LOGICOPFUNCTION_NAND 7
+#define GEN6_LOGICOPFUNCTION_AND 8
+#define GEN6_LOGICOPFUNCTION_EQUIV 9
+#define GEN6_LOGICOPFUNCTION_NOOP 10
+#define GEN6_LOGICOPFUNCTION_OR_INVERTED 11
+#define GEN6_LOGICOPFUNCTION_COPY 12
+#define GEN6_LOGICOPFUNCTION_OR_REVERSE 13
+#define GEN6_LOGICOPFUNCTION_OR 14
+#define GEN6_LOGICOPFUNCTION_SET 15
+
+#define GEN6_MAPFILTER_NEAREST 0x0
+#define GEN6_MAPFILTER_LINEAR 0x1
+#define GEN6_MAPFILTER_ANISOTROPIC 0x2
+
+#define GEN6_MIPFILTER_NONE 0
+#define GEN6_MIPFILTER_NEAREST 1
+#define GEN6_MIPFILTER_LINEAR 3
+
+#define GEN6_POLYGON_FRONT_FACING 0
+#define GEN6_POLYGON_BACK_FACING 1
+
+#define GEN6_PREFILTER_ALWAYS 0x0
+#define GEN6_PREFILTER_NEVER 0x1
+#define GEN6_PREFILTER_LESS 0x2
+#define GEN6_PREFILTER_EQUAL 0x3
+#define GEN6_PREFILTER_LEQUAL 0x4
+#define GEN6_PREFILTER_GREATER 0x5
+#define GEN6_PREFILTER_NOTEQUAL 0x6
+#define GEN6_PREFILTER_GEQUAL 0x7
+
+#define GEN6_PROVOKING_VERTEX_0 0
+#define GEN6_PROVOKING_VERTEX_1 1
+#define GEN6_PROVOKING_VERTEX_2 2
+
+#define GEN6_RASTRULE_UPPER_LEFT 0
+#define GEN6_RASTRULE_UPPER_RIGHT 1
+
+#define GEN6_RENDERTARGET_CLAMPRANGE_UNORM 0
+#define GEN6_RENDERTARGET_CLAMPRANGE_SNORM 1
+#define GEN6_RENDERTARGET_CLAMPRANGE_FORMAT 2
+
+#define GEN6_STENCILOP_KEEP 0
+#define GEN6_STENCILOP_ZERO 1
+#define GEN6_STENCILOP_REPLACE 2
+#define GEN6_STENCILOP_INCRSAT 3
+#define GEN6_STENCILOP_DECRSAT 4
+#define GEN6_STENCILOP_INCR 5
+#define GEN6_STENCILOP_DECR 6
+#define GEN6_STENCILOP_INVERT 7
+
+#define GEN6_SURFACE_MIPMAPLAYOUT_BELOW 0
+#define GEN6_SURFACE_MIPMAPLAYOUT_RIGHT 1
+
+#define GEN6_SURFACEFORMAT_R32G32B32A32_FLOAT 0x000
+#define GEN6_SURFACEFORMAT_R32G32B32A32_SINT 0x001
+#define GEN6_SURFACEFORMAT_R32G32B32A32_UINT 0x002
+#define GEN6_SURFACEFORMAT_R32G32B32A32_UNORM 0x003
+#define GEN6_SURFACEFORMAT_R32G32B32A32_SNORM 0x004
+#define GEN6_SURFACEFORMAT_R64G64_FLOAT 0x005
+#define GEN6_SURFACEFORMAT_R32G32B32X32_FLOAT 0x006
+#define GEN6_SURFACEFORMAT_R32G32B32A32_SSCALED 0x007
+#define GEN6_SURFACEFORMAT_R32G32B32A32_USCALED 0x008
+#define GEN6_SURFACEFORMAT_R32G32B32_FLOAT 0x040
+#define GEN6_SURFACEFORMAT_R32G32B32_SINT 0x041
+#define GEN6_SURFACEFORMAT_R32G32B32_UINT 0x042
+#define GEN6_SURFACEFORMAT_R32G32B32_UNORM 0x043
+#define GEN6_SURFACEFORMAT_R32G32B32_SNORM 0x044
+#define GEN6_SURFACEFORMAT_R32G32B32_SSCALED 0x045
+#define GEN6_SURFACEFORMAT_R32G32B32_USCALED 0x046
+#define GEN6_SURFACEFORMAT_R16G16B16A16_UNORM 0x080
+#define GEN6_SURFACEFORMAT_R16G16B16A16_SNORM 0x081
+#define GEN6_SURFACEFORMAT_R16G16B16A16_SINT 0x082
+#define GEN6_SURFACEFORMAT_R16G16B16A16_UINT 0x083
+#define GEN6_SURFACEFORMAT_R16G16B16A16_FLOAT 0x084
+#define GEN6_SURFACEFORMAT_R32G32_FLOAT 0x085
+#define GEN6_SURFACEFORMAT_R32G32_SINT 0x086
+#define GEN6_SURFACEFORMAT_R32G32_UINT 0x087
+#define GEN6_SURFACEFORMAT_R32_FLOAT_X8X24_TYPELESS 0x088
+#define GEN6_SURFACEFORMAT_X32_TYPELESS_G8X24_UINT 0x089
+#define GEN6_SURFACEFORMAT_L32A32_FLOAT 0x08A
+#define GEN6_SURFACEFORMAT_R32G32_UNORM 0x08B
+#define GEN6_SURFACEFORMAT_R32G32_SNORM 0x08C
+#define GEN6_SURFACEFORMAT_R64_FLOAT 0x08D
+#define GEN6_SURFACEFORMAT_R16G16B16X16_UNORM 0x08E
+#define GEN6_SURFACEFORMAT_R16G16B16X16_FLOAT 0x08F
+#define GEN6_SURFACEFORMAT_A32X32_FLOAT 0x090
+#define GEN6_SURFACEFORMAT_L32X32_FLOAT 0x091
+#define GEN6_SURFACEFORMAT_I32X32_FLOAT 0x092
+#define GEN6_SURFACEFORMAT_R16G16B16A16_SSCALED 0x093
+#define GEN6_SURFACEFORMAT_R16G16B16A16_USCALED 0x094
+#define GEN6_SURFACEFORMAT_R32G32_SSCALED 0x095
+#define GEN6_SURFACEFORMAT_R32G32_USCALED 0x096
+#define GEN6_SURFACEFORMAT_B8G8R8A8_UNORM 0x0C0
+#define GEN6_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB 0x0C1
+#define GEN6_SURFACEFORMAT_R10G10B10A2_UNORM 0x0C2
+#define GEN6_SURFACEFORMAT_R10G10B10A2_UNORM_SRGB 0x0C3
+#define GEN6_SURFACEFORMAT_R10G10B10A2_UINT 0x0C4
+#define GEN6_SURFACEFORMAT_R10G10B10_SNORM_A2_UNORM 0x0C5
+#define GEN6_SURFACEFORMAT_R8G8B8A8_UNORM 0x0C7
+#define GEN6_SURFACEFORMAT_R8G8B8A8_UNORM_SRGB 0x0C8
+#define GEN6_SURFACEFORMAT_R8G8B8A8_SNORM 0x0C9
+#define GEN6_SURFACEFORMAT_R8G8B8A8_SINT 0x0CA
+#define GEN6_SURFACEFORMAT_R8G8B8A8_UINT 0x0CB
+#define GEN6_SURFACEFORMAT_R16G16_UNORM 0x0CC
+#define GEN6_SURFACEFORMAT_R16G16_SNORM 0x0CD
+#define GEN6_SURFACEFORMAT_R16G16_SINT 0x0CE
+#define GEN6_SURFACEFORMAT_R16G16_UINT 0x0CF
+#define GEN6_SURFACEFORMAT_R16G16_FLOAT 0x0D0
+#define GEN6_SURFACEFORMAT_B10G10R10A2_UNORM 0x0D1
+#define GEN6_SURFACEFORMAT_B10G10R10A2_UNORM_SRGB 0x0D2
+#define GEN6_SURFACEFORMAT_R11G11B10_FLOAT 0x0D3
+#define GEN6_SURFACEFORMAT_R32_SINT 0x0D6
+#define GEN6_SURFACEFORMAT_R32_UINT 0x0D7
+#define GEN6_SURFACEFORMAT_R32_FLOAT 0x0D8
+#define GEN6_SURFACEFORMAT_R24_UNORM_X8_TYPELESS 0x0D9
+#define GEN6_SURFACEFORMAT_X24_TYPELESS_G8_UINT 0x0DA
+#define GEN6_SURFACEFORMAT_L16A16_UNORM 0x0DF
+#define GEN6_SURFACEFORMAT_I24X8_UNORM 0x0E0
+#define GEN6_SURFACEFORMAT_L24X8_UNORM 0x0E1
+#define GEN6_SURFACEFORMAT_A24X8_UNORM 0x0E2
+#define GEN6_SURFACEFORMAT_I32_FLOAT 0x0E3
+#define GEN6_SURFACEFORMAT_L32_FLOAT 0x0E4
+#define GEN6_SURFACEFORMAT_A32_FLOAT 0x0E5
+#define GEN6_SURFACEFORMAT_B8G8R8X8_UNORM 0x0E9
+#define GEN6_SURFACEFORMAT_B8G8R8X8_UNORM_SRGB 0x0EA
+#define GEN6_SURFACEFORMAT_R8G8B8X8_UNORM 0x0EB
+#define GEN6_SURFACEFORMAT_R8G8B8X8_UNORM_SRGB 0x0EC
+#define GEN6_SURFACEFORMAT_R9G9B9E5_SHAREDEXP 0x0ED
+#define GEN6_SURFACEFORMAT_B10G10R10X2_UNORM 0x0EE
+#define GEN6_SURFACEFORMAT_L16A16_FLOAT 0x0F0
+#define GEN6_SURFACEFORMAT_R32_UNORM 0x0F1
+#define GEN6_SURFACEFORMAT_R32_SNORM 0x0F2
+#define GEN6_SURFACEFORMAT_R10G10B10X2_USCALED 0x0F3
+#define GEN6_SURFACEFORMAT_R8G8B8A8_SSCALED 0x0F4
+#define GEN6_SURFACEFORMAT_R8G8B8A8_USCALED 0x0F5
+#define GEN6_SURFACEFORMAT_R16G16_SSCALED 0x0F6
+#define GEN6_SURFACEFORMAT_R16G16_USCALED 0x0F7
+#define GEN6_SURFACEFORMAT_R32_SSCALED 0x0F8
+#define GEN6_SURFACEFORMAT_R32_USCALED 0x0F9
+#define GEN6_SURFACEFORMAT_B5G6R5_UNORM 0x100
+#define GEN6_SURFACEFORMAT_B5G6R5_UNORM_SRGB 0x101
+#define GEN6_SURFACEFORMAT_B5G5R5A1_UNORM 0x102
+#define GEN6_SURFACEFORMAT_B5G5R5A1_UNORM_SRGB 0x103
+#define GEN6_SURFACEFORMAT_B4G4R4A4_UNORM 0x104
+#define GEN6_SURFACEFORMAT_B4G4R4A4_UNORM_SRGB 0x105
+#define GEN6_SURFACEFORMAT_R8G8_UNORM 0x106
+#define GEN6_SURFACEFORMAT_R8G8_SNORM 0x107
+#define GEN6_SURFACEFORMAT_R8G8_SINT 0x108
+#define GEN6_SURFACEFORMAT_R8G8_UINT 0x109
+#define GEN6_SURFACEFORMAT_R16_UNORM 0x10A
+#define GEN6_SURFACEFORMAT_R16_SNORM 0x10B
+#define GEN6_SURFACEFORMAT_R16_SINT 0x10C
+#define GEN6_SURFACEFORMAT_R16_UINT 0x10D
+#define GEN6_SURFACEFORMAT_R16_FLOAT 0x10E
+#define GEN6_SURFACEFORMAT_I16_UNORM 0x111
+#define GEN6_SURFACEFORMAT_L16_UNORM 0x112
+#define GEN6_SURFACEFORMAT_A16_UNORM 0x113
+#define GEN6_SURFACEFORMAT_L8A8_UNORM 0x114
+#define GEN6_SURFACEFORMAT_I16_FLOAT 0x115
+#define GEN6_SURFACEFORMAT_L16_FLOAT 0x116
+#define GEN6_SURFACEFORMAT_A16_FLOAT 0x117
+#define GEN6_SURFACEFORMAT_R5G5_SNORM_B6_UNORM 0x119
+#define GEN6_SURFACEFORMAT_B5G5R5X1_UNORM 0x11A
+#define GEN6_SURFACEFORMAT_B5G5R5X1_UNORM_SRGB 0x11B
+#define GEN6_SURFACEFORMAT_R8G8_SSCALED 0x11C
+#define GEN6_SURFACEFORMAT_R8G8_USCALED 0x11D
+#define GEN6_SURFACEFORMAT_R16_SSCALED 0x11E
+#define GEN6_SURFACEFORMAT_R16_USCALED 0x11F
+#define GEN6_SURFACEFORMAT_R8_UNORM 0x140
+#define GEN6_SURFACEFORMAT_R8_SNORM 0x141
+#define GEN6_SURFACEFORMAT_R8_SINT 0x142
+#define GEN6_SURFACEFORMAT_R8_UINT 0x143
+#define GEN6_SURFACEFORMAT_A8_UNORM 0x144
+#define GEN6_SURFACEFORMAT_I8_UNORM 0x145
+#define GEN6_SURFACEFORMAT_L8_UNORM 0x146
+#define GEN6_SURFACEFORMAT_P4A4_UNORM 0x147
+#define GEN6_SURFACEFORMAT_A4P4_UNORM 0x148
+#define GEN6_SURFACEFORMAT_R8_SSCALED 0x149
+#define GEN6_SURFACEFORMAT_R8_USCALED 0x14A
+#define GEN6_SURFACEFORMAT_R1_UINT 0x181
+#define GEN6_SURFACEFORMAT_YCRCB_NORMAL 0x182
+#define GEN6_SURFACEFORMAT_YCRCB_SWAPUVY 0x183
+#define GEN6_SURFACEFORMAT_BC1_UNORM 0x186
+#define GEN6_SURFACEFORMAT_BC2_UNORM 0x187
+#define GEN6_SURFACEFORMAT_BC3_UNORM 0x188
+#define GEN6_SURFACEFORMAT_BC4_UNORM 0x189
+#define GEN6_SURFACEFORMAT_BC5_UNORM 0x18A
+#define GEN6_SURFACEFORMAT_BC1_UNORM_SRGB 0x18B
+#define GEN6_SURFACEFORMAT_BC2_UNORM_SRGB 0x18C
+#define GEN6_SURFACEFORMAT_BC3_UNORM_SRGB 0x18D
+#define GEN6_SURFACEFORMAT_MONO8 0x18E
+#define GEN6_SURFACEFORMAT_YCRCB_SWAPUV 0x18F
+#define GEN6_SURFACEFORMAT_YCRCB_SWAPY 0x190
+#define GEN6_SURFACEFORMAT_DXT1_RGB 0x191
+#define GEN6_SURFACEFORMAT_FXT1 0x192
+#define GEN6_SURFACEFORMAT_R8G8B8_UNORM 0x193
+#define GEN6_SURFACEFORMAT_R8G8B8_SNORM 0x194
+#define GEN6_SURFACEFORMAT_R8G8B8_SSCALED 0x195
+#define GEN6_SURFACEFORMAT_R8G8B8_USCALED 0x196
+#define GEN6_SURFACEFORMAT_R64G64B64A64_FLOAT 0x197
+#define GEN6_SURFACEFORMAT_R64G64B64_FLOAT 0x198
+#define GEN6_SURFACEFORMAT_BC4_SNORM 0x199
+#define GEN6_SURFACEFORMAT_BC5_SNORM 0x19A
+#define GEN6_SURFACEFORMAT_R16G16B16_UNORM 0x19C
+#define GEN6_SURFACEFORMAT_R16G16B16_SNORM 0x19D
+#define GEN6_SURFACEFORMAT_R16G16B16_SSCALED 0x19E
+#define GEN6_SURFACEFORMAT_R16G16B16_USCALED 0x19F
+
+#define GEN6_SURFACERETURNFORMAT_FLOAT32 0
+#define GEN6_SURFACERETURNFORMAT_S1 1
+
+#define GEN6_SURFACE_1D 0
+#define GEN6_SURFACE_2D 1
+#define GEN6_SURFACE_3D 2
+#define GEN6_SURFACE_CUBE 3
+#define GEN6_SURFACE_BUFFER 4
+#define GEN6_SURFACE_NULL 7
+
+#define GEN6_BORDER_COLOR_MODE_DEFAULT 0
+#define GEN6_BORDER_COLOR_MODE_LEGACY 1
+
+#define GEN6_TEXCOORDMODE_WRAP 0
+#define GEN6_TEXCOORDMODE_MIRROR 1
+#define GEN6_TEXCOORDMODE_CLAMP 2
+#define GEN6_TEXCOORDMODE_CUBE 3
+#define GEN6_TEXCOORDMODE_CLAMP_BORDER 4
+#define GEN6_TEXCOORDMODE_MIRROR_ONCE 5
+
+#define GEN6_THREAD_PRIORITY_NORMAL 0
+#define GEN6_THREAD_PRIORITY_HIGH 1
+
+#define GEN6_TILEWALK_XMAJOR 0
+#define GEN6_TILEWALK_YMAJOR 1
+
+#define GEN6_VERTEX_SUBPIXEL_PRECISION_8BITS 0
+#define GEN6_VERTEX_SUBPIXEL_PRECISION_4BITS 1
+
+#define GEN6_VERTEXBUFFER_ACCESS_VERTEXDATA 0
+#define GEN6_VERTEXBUFFER_ACCESS_INSTANCEDATA 1
+
+#define GEN6_VFCOMPONENT_NOSTORE 0
+#define GEN6_VFCOMPONENT_STORE_SRC 1
+#define GEN6_VFCOMPONENT_STORE_0 2
+#define GEN6_VFCOMPONENT_STORE_1_FLT 3
+#define GEN6_VFCOMPONENT_STORE_1_INT 4
+#define GEN6_VFCOMPONENT_STORE_VID 5
+#define GEN6_VFCOMPONENT_STORE_IID 6
+#define GEN6_VFCOMPONENT_STORE_PID 7
+
+
+
+/* Execution Unit (EU) defines
+ */
+
+#define GEN6_ALIGN_1 0
+#define GEN6_ALIGN_16 1
+
+#define GEN6_ADDRESS_DIRECT 0
+#define GEN6_ADDRESS_REGISTER_INDIRECT_REGISTER 1
+
+#define GEN6_CHANNEL_X 0
+#define GEN6_CHANNEL_Y 1
+#define GEN6_CHANNEL_Z 2
+#define GEN6_CHANNEL_W 3
+
+#define GEN6_COMPRESSION_NONE 0
+#define GEN6_COMPRESSION_2NDHALF 1
+#define GEN6_COMPRESSION_COMPRESSED 2
+
+#define GEN6_CONDITIONAL_NONE 0
+#define GEN6_CONDITIONAL_Z 1
+#define GEN6_CONDITIONAL_NZ 2
+#define GEN6_CONDITIONAL_EQ 1 /* Z */
+#define GEN6_CONDITIONAL_NEQ 2 /* NZ */
+#define GEN6_CONDITIONAL_G 3
+#define GEN6_CONDITIONAL_GE 4
+#define GEN6_CONDITIONAL_L 5
+#define GEN6_CONDITIONAL_LE 6
+#define GEN6_CONDITIONAL_C 7
+#define GEN6_CONDITIONAL_O 8
+
+#define GEN6_DEBUG_NONE 0
+#define GEN6_DEBUG_BREAKPOINT 1
+
+#define GEN6_DEPENDENCY_NORMAL 0
+#define GEN6_DEPENDENCY_NOTCLEARED 1
+#define GEN6_DEPENDENCY_NOTCHECKED 2
+#define GEN6_DEPENDENCY_DISABLE 3
+
+#define GEN6_EXECUTE_1 0
+#define GEN6_EXECUTE_2 1
+#define GEN6_EXECUTE_4 2
+#define GEN6_EXECUTE_8 3
+#define GEN6_EXECUTE_16 4
+#define GEN6_EXECUTE_32 5
+
+#define GEN6_HORIZONTAL_STRIDE_0 0
+#define GEN6_HORIZONTAL_STRIDE_1 1
+#define GEN6_HORIZONTAL_STRIDE_2 2
+#define GEN6_HORIZONTAL_STRIDE_4 3
+
+#define GEN6_INSTRUCTION_NORMAL 0
+#define GEN6_INSTRUCTION_SATURATE 1
+
+#define GEN6_MASK_ENABLE 0
+#define GEN6_MASK_DISABLE 1
+
+#define GEN6_OPCODE_MOV 1
+#define GEN6_OPCODE_SEL 2
+#define GEN6_OPCODE_NOT 4
+#define GEN6_OPCODE_AND 5
+#define GEN6_OPCODE_OR 6
+#define GEN6_OPCODE_XOR 7
+#define GEN6_OPCODE_SHR 8
+#define GEN6_OPCODE_SHL 9
+#define GEN6_OPCODE_RSR 10
+#define GEN6_OPCODE_RSL 11
+#define GEN6_OPCODE_ASR 12
+#define GEN6_OPCODE_CMP 16
+#define GEN6_OPCODE_JMPI 32
+#define GEN6_OPCODE_IF 34
+#define GEN6_OPCODE_IFF 35
+#define GEN6_OPCODE_ELSE 36
+#define GEN6_OPCODE_ENDIF 37
+#define GEN6_OPCODE_DO 38
+#define GEN6_OPCODE_WHILE 39
+#define GEN6_OPCODE_BREAK 40
+#define GEN6_OPCODE_CONTINUE 41
+#define GEN6_OPCODE_HALT 42
+#define GEN6_OPCODE_MSAVE 44
+#define GEN6_OPCODE_MRESTORE 45
+#define GEN6_OPCODE_PUSH 46
+#define GEN6_OPCODE_POP 47
+#define GEN6_OPCODE_WAIT 48
+#define GEN6_OPCODE_SEND 49
+#define GEN6_OPCODE_ADD 64
+#define GEN6_OPCODE_MUL 65
+#define GEN6_OPCODE_AVG 66
+#define GEN6_OPCODE_FRC 67
+#define GEN6_OPCODE_RNDU 68
+#define GEN6_OPCODE_RNDD 69
+#define GEN6_OPCODE_RNDE 70
+#define GEN6_OPCODE_RNDZ 71
+#define GEN6_OPCODE_MAC 72
+#define GEN6_OPCODE_MACH 73
+#define GEN6_OPCODE_LZD 74
+#define GEN6_OPCODE_SAD2 80
+#define GEN6_OPCODE_SADA2 81
+#define GEN6_OPCODE_DP4 84
+#define GEN6_OPCODE_DPH 85
+#define GEN6_OPCODE_DP3 86
+#define GEN6_OPCODE_DP2 87
+#define GEN6_OPCODE_DPA2 88
+#define GEN6_OPCODE_LINE 89
+#define GEN6_OPCODE_NOP 126
+
+#define GEN6_PREDICATE_NONE 0
+#define GEN6_PREDICATE_NORMAL 1
+#define GEN6_PREDICATE_ALIGN1_ANYV 2
+#define GEN6_PREDICATE_ALIGN1_ALLV 3
+#define GEN6_PREDICATE_ALIGN1_ANY2H 4
+#define GEN6_PREDICATE_ALIGN1_ALL2H 5
+#define GEN6_PREDICATE_ALIGN1_ANY4H 6
+#define GEN6_PREDICATE_ALIGN1_ALL4H 7
+#define GEN6_PREDICATE_ALIGN1_ANY8H 8
+#define GEN6_PREDICATE_ALIGN1_ALL8H 9
+#define GEN6_PREDICATE_ALIGN1_ANY16H 10
+#define GEN6_PREDICATE_ALIGN1_ALL16H 11
+#define GEN6_PREDICATE_ALIGN16_REPLICATE_X 2
+#define GEN6_PREDICATE_ALIGN16_REPLICATE_Y 3
+#define GEN6_PREDICATE_ALIGN16_REPLICATE_Z 4
+#define GEN6_PREDICATE_ALIGN16_REPLICATE_W 5
+#define GEN6_PREDICATE_ALIGN16_ANY4H 6
+#define GEN6_PREDICATE_ALIGN16_ALL4H 7
+
+#define GEN6_ARCHITECTURE_REGISTER_FILE 0
+#define GEN6_GENERAL_REGISTER_FILE 1
+#define GEN6_MESSAGE_REGISTER_FILE 2
+#define GEN6_IMMEDIATE_VALUE 3
+
+#define GEN6_REGISTER_TYPE_UD 0
+#define GEN6_REGISTER_TYPE_D 1
+#define GEN6_REGISTER_TYPE_UW 2
+#define GEN6_REGISTER_TYPE_W 3
+#define GEN6_REGISTER_TYPE_UB 4
+#define GEN6_REGISTER_TYPE_B 5
+#define GEN6_REGISTER_TYPE_VF 5 /* packed float vector, immediates only? */
+#define GEN6_REGISTER_TYPE_HF 6
+#define GEN6_REGISTER_TYPE_V 6 /* packed int vector, immediates only, uword dest only */
+#define GEN6_REGISTER_TYPE_F 7
+
+#define GEN6_ARF_NULL 0x00
+#define GEN6_ARF_ADDRESS 0x10
+#define GEN6_ARF_ACCUMULATOR 0x20
+#define GEN6_ARF_FLAG 0x30
+#define GEN6_ARF_MASK 0x40
+#define GEN6_ARF_MASK_STACK 0x50
+#define GEN6_ARF_MASK_STACK_DEPTH 0x60
+#define GEN6_ARF_STATE 0x70
+#define GEN6_ARF_CONTROL 0x80
+#define GEN6_ARF_NOTIFICATION_COUNT 0x90
+#define GEN6_ARF_IP 0xA0
+
+#define GEN6_AMASK 0
+#define GEN6_IMASK 1
+#define GEN6_LMASK 2
+#define GEN6_CMASK 3
+
+
+
+#define GEN6_THREAD_NORMAL 0
+#define GEN6_THREAD_ATOMIC 1
+#define GEN6_THREAD_SWITCH 2
+
+#define GEN6_VERTICAL_STRIDE_0 0
+#define GEN6_VERTICAL_STRIDE_1 1
+#define GEN6_VERTICAL_STRIDE_2 2
+#define GEN6_VERTICAL_STRIDE_4 3
+#define GEN6_VERTICAL_STRIDE_8 4
+#define GEN6_VERTICAL_STRIDE_16 5
+#define GEN6_VERTICAL_STRIDE_32 6
+#define GEN6_VERTICAL_STRIDE_64 7
+#define GEN6_VERTICAL_STRIDE_128 8
+#define GEN6_VERTICAL_STRIDE_256 9
+#define GEN6_VERTICAL_STRIDE_ONE_DIMENSIONAL 0xF
+
+#define GEN6_WIDTH_1 0
+#define GEN6_WIDTH_2 1
+#define GEN6_WIDTH_4 2
+#define GEN6_WIDTH_8 3
+#define GEN6_WIDTH_16 4
+
+#define GEN6_STATELESS_BUFFER_BOUNDARY_1K 0
+#define GEN6_STATELESS_BUFFER_BOUNDARY_2K 1
+#define GEN6_STATELESS_BUFFER_BOUNDARY_4K 2
+#define GEN6_STATELESS_BUFFER_BOUNDARY_8K 3
+#define GEN6_STATELESS_BUFFER_BOUNDARY_16K 4
+#define GEN6_STATELESS_BUFFER_BOUNDARY_32K 5
+#define GEN6_STATELESS_BUFFER_BOUNDARY_64K 6
+#define GEN6_STATELESS_BUFFER_BOUNDARY_128K 7
+#define GEN6_STATELESS_BUFFER_BOUNDARY_256K 8
+#define GEN6_STATELESS_BUFFER_BOUNDARY_512K 9
+#define GEN6_STATELESS_BUFFER_BOUNDARY_1M 10
+#define GEN6_STATELESS_BUFFER_BOUNDARY_2M 11
+
+#define GEN6_POLYGON_FACING_FRONT 0
+#define GEN6_POLYGON_FACING_BACK 1
+
+#define GEN6_MESSAGE_TARGET_NULL 0
+#define GEN6_MESSAGE_TARGET_MATH 1
+#define GEN6_MESSAGE_TARGET_SAMPLER 2
+#define GEN6_MESSAGE_TARGET_GATEWAY 3
+#define GEN6_MESSAGE_TARGET_DATAPORT_READ 4
+#define GEN6_MESSAGE_TARGET_DATAPORT_WRITE 5
+#define GEN6_MESSAGE_TARGET_URB 6
+#define GEN6_MESSAGE_TARGET_THREAD_SPAWNER 7
+
+#define GEN6_SAMPLER_RETURN_FORMAT_FLOAT32 0
+#define GEN6_SAMPLER_RETURN_FORMAT_UINT32 2
+#define GEN6_SAMPLER_RETURN_FORMAT_SINT32 3
+
+#define GEN6_SAMPLER_MESSAGE_SIMD8_SAMPLE 0
+#define GEN6_SAMPLER_MESSAGE_SIMD16_SAMPLE 0
+#define GEN6_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS 0
+#define GEN6_SAMPLER_MESSAGE_SIMD8_KILLPIX 1
+#define GEN6_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD 1
+#define GEN6_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD 1
+#define GEN6_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_GRADIENTS 2
+#define GEN6_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS 2
+#define GEN6_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE 0
+#define GEN6_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE 2
+#define GEN6_SAMPLER_MESSAGE_SIMD4X2_RESINFO 2
+#define GEN6_SAMPLER_MESSAGE_SIMD8_RESINFO 2
+#define GEN6_SAMPLER_MESSAGE_SIMD16_RESINFO 2
+#define GEN6_SAMPLER_MESSAGE_SIMD4X2_LD 3
+#define GEN6_SAMPLER_MESSAGE_SIMD8_LD 3
+#define GEN6_SAMPLER_MESSAGE_SIMD16_LD 3
+
+#define GEN6_DATAPORT_OWORD_BLOCK_1_OWORDLOW 0
+#define GEN6_DATAPORT_OWORD_BLOCK_1_OWORDHIGH 1
+#define GEN6_DATAPORT_OWORD_BLOCK_2_OWORDS 2
+#define GEN6_DATAPORT_OWORD_BLOCK_4_OWORDS 3
+#define GEN6_DATAPORT_OWORD_BLOCK_8_OWORDS 4
+
+#define GEN6_DATAPORT_OWORD_DUAL_BLOCK_1OWORD 0
+#define GEN6_DATAPORT_OWORD_DUAL_BLOCK_4OWORDS 2
+
+#define GEN6_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS 2
+#define GEN6_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS 3
+
+#define GEN6_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ 0
+#define GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ 1
+#define GEN6_DATAPORT_READ_MESSAGE_DWORD_BLOCK_READ 2
+#define GEN6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ 3
+
+#define GEN6_DATAPORT_READ_TARGET_DATA_CACHE 0
+#define GEN6_DATAPORT_READ_TARGET_RENDER_CACHE 1
+#define GEN6_DATAPORT_READ_TARGET_SAMPLER_CACHE 2
+
+#define GEN6_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE 0
+#define GEN6_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED 1
+#define GEN6_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01 2
+#define GEN6_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23 3
+#define GEN6_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01 4
+
+#define GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE 0
+#define GEN6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE 1
+#define GEN6_DATAPORT_WRITE_MESSAGE_DWORD_BLOCK_WRITE 2
+#define GEN6_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE 3
+#define GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE 4
+#define GEN6_DATAPORT_WRITE_MESSAGE_STREAMED_VERTEX_BUFFER_WRITE 5
+#define GEN6_DATAPORT_WRITE_MESSAGE_FLUSH_RENDER_CACHE 7
+
+#define GEN6_MATH_FUNCTION_INV 1
+#define GEN6_MATH_FUNCTION_LOG 2
+#define GEN6_MATH_FUNCTION_EXP 3
+#define GEN6_MATH_FUNCTION_SQRT 4
+#define GEN6_MATH_FUNCTION_RSQ 5
+#define GEN6_MATH_FUNCTION_SIN 6 /* was 7 */
+#define GEN6_MATH_FUNCTION_COS 7 /* was 8 */
+#define GEN6_MATH_FUNCTION_SINCOS 8 /* was 6 */
+#define GEN6_MATH_FUNCTION_TAN 9
+#define GEN6_MATH_FUNCTION_POW 10
+#define GEN6_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER 11
+#define GEN6_MATH_FUNCTION_INT_DIV_QUOTIENT 12
+#define GEN6_MATH_FUNCTION_INT_DIV_REMAINDER 13
+
+#define GEN6_MATH_INTEGER_UNSIGNED 0
+#define GEN6_MATH_INTEGER_SIGNED 1
+
+#define GEN6_MATH_PRECISION_FULL 0
+#define GEN6_MATH_PRECISION_PARTIAL 1
+
+#define GEN6_MATH_SATURATE_NONE 0
+#define GEN6_MATH_SATURATE_SATURATE 1
+
+#define GEN6_MATH_DATA_VECTOR 0
+#define GEN6_MATH_DATA_SCALAR 1
+
+#define GEN6_URB_OPCODE_WRITE 0
+
+#define GEN6_URB_SWIZZLE_NONE 0
+#define GEN6_URB_SWIZZLE_INTERLEAVE 1
+#define GEN6_URB_SWIZZLE_TRANSPOSE 2
+
+#define GEN6_SCRATCH_SPACE_SIZE_1K 0
+#define GEN6_SCRATCH_SPACE_SIZE_2K 1
+#define GEN6_SCRATCH_SPACE_SIZE_4K 2
+#define GEN6_SCRATCH_SPACE_SIZE_8K 3
+#define GEN6_SCRATCH_SPACE_SIZE_16K 4
+#define GEN6_SCRATCH_SPACE_SIZE_32K 5
+#define GEN6_SCRATCH_SPACE_SIZE_64K 6
+#define GEN6_SCRATCH_SPACE_SIZE_128K 7
+#define GEN6_SCRATCH_SPACE_SIZE_256K 8
+#define GEN6_SCRATCH_SPACE_SIZE_512K 9
+#define GEN6_SCRATCH_SPACE_SIZE_1M 10
+#define GEN6_SCRATCH_SPACE_SIZE_2M 11
+
+/* The hardware supports two different modes for border color. The
+ * default (OpenGL) mode uses floating-point color channels, while the
+ * legacy mode uses 4 bytes.
+ *
+ * More significantly, the legacy mode respects the components of the
+ * border color for channels not present in the source, (whereas the
+ * default mode will ignore the border color's alpha channel and use
+ * alpha==1 for an RGB source, for example).
+ *
+ * The legacy mode matches the semantics specified by the Render
+ * extension.
+ */
+struct gen6_sampler_default_border_color {
+ float color[4];
+};
+
+struct gen6_sampler_legacy_border_color {
+ uint8_t color[4];
+};
+
+struct gen6_sampler_state {
+ struct {
+ uint32_t shadow_function:3;
+ uint32_t lod_bias:11;
+ uint32_t min_filter:3;
+ uint32_t mag_filter:3;
+ uint32_t mip_filter:2;
+ uint32_t base_level:5;
+ uint32_t pad:1;
+ uint32_t lod_preclamp:1;
+ uint32_t border_color_mode:1;
+ uint32_t pad0:1;
+ uint32_t disable:1;
+ } ss0;
+
+ struct {
+ uint32_t r_wrap_mode:3;
+ uint32_t t_wrap_mode:3;
+ uint32_t s_wrap_mode:3;
+ uint32_t pad:3;
+ uint32_t max_lod:10;
+ uint32_t min_lod:10;
+ } ss1;
+
+ struct {
+ uint32_t border_color;
+ } ss2;
+
+ struct {
+ uint32_t pad:19;
+ uint32_t max_aniso:3;
+ uint32_t chroma_key_mode:1;
+ uint32_t chroma_key_index:2;
+ uint32_t chroma_key_enable:1;
+ uint32_t monochrome_filter_width:3;
+ uint32_t monochrome_filter_height:3;
+ } ss3;
+};
+
+struct gen6_blend_state {
+ struct {
+ uint32_t dest_blend_factor:5;
+ uint32_t source_blend_factor:5;
+ uint32_t pad3:1;
+ uint32_t blend_func:3;
+ uint32_t pad2:1;
+ uint32_t ia_dest_blend_factor:5;
+ uint32_t ia_source_blend_factor:5;
+ uint32_t pad1:1;
+ uint32_t ia_blend_func:3;
+ uint32_t pad0:1;
+ uint32_t ia_blend_enable:1;
+ uint32_t blend_enable:1;
+ } blend0;
+
+ struct {
+ uint32_t post_blend_clamp_enable:1;
+ uint32_t pre_blend_clamp_enable:1;
+ uint32_t clamp_range:2;
+ uint32_t pad0:4;
+ uint32_t x_dither_offset:2;
+ uint32_t y_dither_offset:2;
+ uint32_t dither_enable:1;
+ uint32_t alpha_test_func:3;
+ uint32_t alpha_test_enable:1;
+ uint32_t pad1:1;
+ uint32_t logic_op_func:4;
+ uint32_t logic_op_enable:1;
+ uint32_t pad2:1;
+ uint32_t write_disable_b:1;
+ uint32_t write_disable_g:1;
+ uint32_t write_disable_r:1;
+ uint32_t write_disable_a:1;
+ uint32_t pad3:1;
+ uint32_t alpha_to_coverage_dither:1;
+ uint32_t alpha_to_one:1;
+ uint32_t alpha_to_coverage:1;
+ } blend1;
+};
+
+struct gen6_color_calc_state {
+ struct {
+ uint32_t alpha_test_format:1;
+ uint32_t pad0:14;
+ uint32_t round_disable:1;
+ uint32_t bf_stencil_ref:8;
+ uint32_t stencil_ref:8;
+ } cc0;
+
+ union {
+ float alpha_ref_f;
+ struct {
+ uint32_t ui:8;
+ uint32_t pad0:24;
+ } alpha_ref_fi;
+ } cc1;
+
+ float constant_r;
+ float constant_g;
+ float constant_b;
+ float constant_a;
+};
+
+struct gen6_depth_stencil_state {
+ struct {
+ uint32_t pad0:3;
+ uint32_t bf_stencil_pass_depth_pass_op:3;
+ uint32_t bf_stencil_pass_depth_fail_op:3;
+ uint32_t bf_stencil_fail_op:3;
+ uint32_t bf_stencil_func:3;
+ uint32_t bf_stencil_enable:1;
+ uint32_t pad1:2;
+ uint32_t stencil_write_enable:1;
+ uint32_t stencil_pass_depth_pass_op:3;
+ uint32_t stencil_pass_depth_fail_op:3;
+ uint32_t stencil_fail_op:3;
+ uint32_t stencil_func:3;
+ uint32_t stencil_enable:1;
+ } ds0;
+
+ struct {
+ uint32_t bf_stencil_write_mask:8;
+ uint32_t bf_stencil_test_mask:8;
+ uint32_t stencil_write_mask:8;
+ uint32_t stencil_test_mask:8;
+ } ds1;
+
+ struct {
+ uint32_t pad0:26;
+ uint32_t depth_write_enable:1;
+ uint32_t depth_test_func:3;
+ uint32_t pad1:1;
+ uint32_t depth_test_enable:1;
+ } ds2;
+};
+
+struct gen6_surface_state {
+ struct {
+ uint32_t cube_pos_z:1;
+ uint32_t cube_neg_z:1;
+ uint32_t cube_pos_y:1;
+ uint32_t cube_neg_y:1;
+ uint32_t cube_pos_x:1;
+ uint32_t cube_neg_x:1;
+ uint32_t pad:3;
+ uint32_t render_cache_read_mode:1;
+ uint32_t mipmap_layout_mode:1;
+ uint32_t vert_line_stride_ofs:1;
+ uint32_t vert_line_stride:1;
+ uint32_t color_blend:1;
+ uint32_t writedisable_blue:1;
+ uint32_t writedisable_green:1;
+ uint32_t writedisable_red:1;
+ uint32_t writedisable_alpha:1;
+ uint32_t surface_format:9;
+ uint32_t data_return_format:1;
+ uint32_t pad0:1;
+ uint32_t surface_type:3;
+ } ss0;
+
+ struct {
+ uint32_t base_addr;
+ } ss1;
+
+ struct {
+ uint32_t render_target_rotation:2;
+ uint32_t mip_count:4;
+ uint32_t width:13;
+ uint32_t height:13;
+ } ss2;
+
+ struct {
+ uint32_t tile_walk:1;
+ uint32_t tiled_surface:1;
+ uint32_t pad:1;
+ uint32_t pitch:18;
+ uint32_t depth:11;
+ } ss3;
+
+ struct {
+ uint32_t pad:19;
+ uint32_t min_array_elt:9;
+ uint32_t min_lod:4;
+ } ss4;
+
+ struct {
+ uint32_t pad:20;
+ uint32_t y_offset:4;
+ uint32_t pad2:1;
+ uint32_t x_offset:7;
+ } ss5;
+};
+
+struct gen6_cc_viewport {
+ float min_depth;
+ float max_depth;
+};
+
+typedef enum {
+ SAMPLER_FILTER_NEAREST = 0,
+ SAMPLER_FILTER_BILINEAR,
+ FILTER_COUNT
+} sampler_filter_t;
+
+typedef enum {
+ SAMPLER_EXTEND_NONE = 0,
+ SAMPLER_EXTEND_REPEAT,
+ SAMPLER_EXTEND_PAD,
+ SAMPLER_EXTEND_REFLECT,
+ EXTEND_COUNT
+} sampler_extend_t;
+
+#endif
diff --git a/lib/gen7_render.h b/lib/gen7_render.h
new file mode 100644
index 00000000..6cd94753
--- /dev/null
+++ b/lib/gen7_render.h
@@ -0,0 +1,222 @@
+#ifndef GEN7_RENDER_H
+#define GEN7_RENDER_H
+
+#include "gen6_render.h"
+
+#define GEN7_3DSTATE_URB_VS (0x7830 << 16)
+#define GEN7_3DSTATE_URB_HS (0x7831 << 16)
+#define GEN7_3DSTATE_URB_DS (0x7832 << 16)
+#define GEN7_3DSTATE_URB_GS (0x7833 << 16)
+
+#define GEN6_3DSTATE_SCISSOR_STATE_POINTERS GEN6_3D(3, 0, 0xf)
+#define GEN7_3DSTATE_CLEAR_PARAMS GEN6_3D(3, 0, 0x04)
+#define GEN7_3DSTATE_DEPTH_BUFFER GEN6_3D(3, 0, 0x05)
+#define GEN7_3DSTATE_STENCIL_BUFFER GEN6_3D(3, 0, 0x06)
+#define GEN7_3DSTATE_HIER_DEPTH_BUFFER GEN6_3D(3, 0, 0x07)
+
+#define GEN7_3DSTATE_GS GEN6_3D(3, 0, 0x11)
+#define GEN7_3DSTATE_CONSTANT_GS GEN6_3D(3, 0, 0x16)
+#define GEN7_3DSTATE_CONSTANT_HS GEN6_3D(3, 0, 0x19)
+#define GEN7_3DSTATE_CONSTANT_DS GEN6_3D(3, 0, 0x1a)
+#define GEN7_3DSTATE_HS GEN6_3D(3, 0, 0x1b)
+#define GEN7_3DSTATE_TE GEN6_3D(3, 0, 0x1c)
+#define GEN7_3DSTATE_DS GEN6_3D(3, 0, 0x1d)
+#define GEN7_3DSTATE_STREAMOUT GEN6_3D(3, 0, 0x1e)
+#define GEN7_3DSTATE_SBE GEN6_3D(3, 0, 0x1f)
+#define GEN7_3DSTATE_PS GEN6_3D(3, 0, 0x20)
+#define GEN7_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP \
+ GEN6_3D(3, 0, 0x21)
+#define GEN7_3DSTATE_VIEWPORT_STATE_POINTERS_CC GEN6_3D(3, 0, 0x23)
+#define GEN7_3DSTATE_BLEND_STATE_POINTERS GEN6_3D(3, 0, 0x24)
+#define GEN7_3DSTATE_DS_STATE_POINTERS GEN6_3D(3, 0, 0x25)
+#define GEN7_3DSTATE_BINDING_TABLE_POINTERS_VS GEN6_3D(3, 0, 0x26)
+#define GEN7_3DSTATE_BINDING_TABLE_POINTERS_HS GEN6_3D(3, 0, 0x27)
+#define GEN7_3DSTATE_BINDING_TABLE_POINTERS_DS GEN6_3D(3, 0, 0x28)
+#define GEN7_3DSTATE_BINDING_TABLE_POINTERS_GS GEN6_3D(3, 0, 0x29)
+#define GEN7_3DSTATE_BINDING_TABLE_POINTERS_PS GEN6_3D(3, 0, 0x2a)
+
+#define GEN7_3DSTATE_SAMPLER_STATE_POINTERS_VS GEN6_3D(3, 0, 0x2b)
+#define GEN7_3DSTATE_SAMPLER_STATE_POINTERS_HS GEN6_3D(3, 0, 0x2c)
+#define GEN7_3DSTATE_SAMPLER_STATE_POINTERS_DS GEN6_3D(3, 0, 0x2d)
+#define GEN7_3DSTATE_SAMPLER_STATE_POINTERS_GS GEN6_3D(3, 0, 0x2e)
+#define GEN7_3DSTATE_SAMPLER_STATE_POINTERS_PS GEN6_3D(3, 0, 0x2f)
+
+#define GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_VS GEN6_3D(3, 1, 0x12)
+#define GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_HS GEN6_3D(3, 1, 0x13)
+#define GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_DS GEN6_3D(3, 1, 0x14)
+#define GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_GS GEN6_3D(3, 1, 0x15)
+#define GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_PS GEN6_3D(3, 1, 0x16)
+
+/* Some random bits that we care about */
+#define GEN7_VB0_BUFFER_ADDR_MOD_EN (1 << 14)
+#define GEN7_WM_DISPATCH_ENABLE (1 << 29)
+#define GEN7_3DSTATE_PS_PERSPECTIVE_PIXEL_BARYCENTRIC (1 << 11)
+#define GEN7_3DSTATE_PS_ATTRIBUTE_ENABLED (1 << 10)
+
+/* Random shifts */
+#define GEN7_3DSTATE_WM_MAX_THREADS_SHIFT 24
+#define HSW_3DSTATE_WM_MAX_THREADS_SHIFT 23
+
+/* Shamelessly ripped from mesa */
+struct gen7_surface_state
+{
+ struct {
+ uint32_t cube_pos_z:1;
+ uint32_t cube_neg_z:1;
+ uint32_t cube_pos_y:1;
+ uint32_t cube_neg_y:1;
+ uint32_t cube_pos_x:1;
+ uint32_t cube_neg_x:1;
+ uint32_t pad2:2;
+ uint32_t render_cache_read_write:1;
+ uint32_t pad1:1;
+ uint32_t surface_array_spacing:1;
+ uint32_t vert_line_stride_ofs:1;
+ uint32_t vert_line_stride:1;
+ uint32_t tile_walk:1;
+ uint32_t tiled_surface:1;
+ uint32_t horizontal_alignment:1;
+ uint32_t vertical_alignment:2;
+ uint32_t surface_format:9; /**< BRW_SURFACEFORMAT_x */
+ uint32_t pad0:1;
+ uint32_t is_array:1;
+ uint32_t surface_type:3; /**< BRW_SURFACE_1D/2D/3D/CUBE */
+ } ss0;
+
+ struct {
+ uint32_t base_addr;
+ } ss1;
+
+ struct {
+ uint32_t width:14;
+ uint32_t pad1:2;
+ uint32_t height:14;
+ uint32_t pad0:2;
+ } ss2;
+
+ struct {
+ uint32_t pitch:18;
+ uint32_t pad:3;
+ uint32_t depth:11;
+ } ss3;
+
+ struct {
+ uint32_t multisample_position_palette_index:3;
+ uint32_t num_multisamples:3;
+ uint32_t multisampled_surface_storage_format:1;
+ uint32_t render_target_view_extent:11;
+ uint32_t min_array_elt:11;
+ uint32_t rotation:2;
+ uint32_t pad0:1;
+ } ss4;
+
+ struct {
+ uint32_t mip_count:4;
+ uint32_t min_lod:4;
+ uint32_t pad1:12;
+ uint32_t y_offset:4;
+ uint32_t pad0:1;
+ uint32_t x_offset:7;
+ } ss5;
+
+ struct {
+ uint32_t pad; /* Multisample Control Surface stuff */
+ } ss6;
+
+ struct {
+ uint32_t resource_min_lod:12;
+
+ /* Only on Haswell */
+ uint32_t pad0:4;
+ uint32_t shader_chanel_select_a:3;
+ uint32_t shader_chanel_select_b:3;
+ uint32_t shader_chanel_select_g:3;
+ uint32_t shader_chanel_select_r:3;
+
+ uint32_t alpha_clear_color:1;
+ uint32_t blue_clear_color:1;
+ uint32_t green_clear_color:1;
+ uint32_t red_clear_color:1;
+ } ss7;
+};
+
+struct gen7_sampler_state
+{
+ struct
+ {
+ uint32_t aniso_algorithm:1;
+ uint32_t lod_bias:13;
+ uint32_t min_filter:3;
+ uint32_t mag_filter:3;
+ uint32_t mip_filter:2;
+ uint32_t base_level:5;
+ uint32_t pad1:1;
+ uint32_t lod_preclamp:1;
+ uint32_t default_color_mode:1;
+ uint32_t pad0:1;
+ uint32_t disable:1;
+ } ss0;
+
+ struct
+ {
+ uint32_t cube_control_mode:1;
+ uint32_t shadow_function:3;
+ uint32_t pad:4;
+ uint32_t max_lod:12;
+ uint32_t min_lod:12;
+ } ss1;
+
+ struct
+ {
+ uint32_t pad:5;
+ uint32_t default_color_pointer:27;
+ } ss2;
+
+ struct
+ {
+ uint32_t r_wrap_mode:3;
+ uint32_t t_wrap_mode:3;
+ uint32_t s_wrap_mode:3;
+ uint32_t pad:1;
+ uint32_t non_normalized_coord:1;
+ uint32_t trilinear_quality:2;
+ uint32_t address_round:6;
+ uint32_t max_aniso:3;
+ uint32_t chroma_key_mode:1;
+ uint32_t chroma_key_index:2;
+ uint32_t chroma_key_enable:1;
+ uint32_t pad0:6;
+ } ss3;
+};
+
+struct gen7_sf_clip_viewport {
+ struct {
+ float m00;
+ float m11;
+ float m22;
+ float m30;
+ float m31;
+ float m32;
+ } viewport;
+
+ uint32_t pad0[2];
+
+ struct {
+ float xmin;
+ float xmax;
+ float ymin;
+ float ymax;
+ } guardband;
+
+ float pad1[4];
+};
+
+struct gen6_scissor_rect
+{
+ uint32_t xmin:16;
+ uint32_t ymin:16;
+ uint32_t xmax:16;
+ uint32_t ymax:16;
+};
+
+#endif
diff --git a/lib/i830_reg.h b/lib/i830_reg.h
new file mode 100644
index 00000000..93d03cf3
--- /dev/null
+++ b/lib/i830_reg.h
@@ -0,0 +1,805 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _I830_REG_H_
+#define _I830_REG_H_
+
+#define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
+
+/* Flush */
+#define MI_FLUSH (0x04<<23)
+#define MI_FLUSH_DW (0x26<<23)
+
+#define MI_WRITE_DIRTY_STATE (1<<4)
+#define MI_END_SCENE (1<<3)
+#define MI_GLOBAL_SNAPSHOT_COUNT_RESET (1<<3)
+#define MI_INHIBIT_RENDER_CACHE_FLUSH (1<<2)
+#define MI_STATE_INSTRUCTION_CACHE_FLUSH (1<<1)
+#define MI_INVALIDATE_MAP_CACHE (1<<0)
+/* broadwater flush bits */
+#define BRW_MI_GLOBAL_SNAPSHOT_RESET (1 << 3)
+
+#define MI_BATCH_BUFFER_END (0xA << 23)
+
+/* Noop */
+#define MI_NOOP 0x00
+#define MI_NOOP_WRITE_ID (1<<22)
+#define MI_NOOP_ID_MASK (1<<22 - 1)
+
+/* Wait for Events */
+#define MI_WAIT_FOR_EVENT (0x03<<23)
+#define MI_WAIT_FOR_PIPEB_SVBLANK (1<<18)
+#define MI_WAIT_FOR_PIPEA_SVBLANK (1<<17)
+#define MI_WAIT_FOR_OVERLAY_FLIP (1<<16)
+#define MI_WAIT_FOR_PIPEB_VBLANK (1<<7)
+#define MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW (1<<5)
+#define MI_WAIT_FOR_PIPEA_VBLANK (1<<3)
+#define MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW (1<<1)
+
+/* Set the scan line for MI_WAIT_FOR_PIPE?_SCAN_LINE_WINDOW */
+#define MI_LOAD_SCAN_LINES_INCL (0x12<<23)
+#define MI_LOAD_SCAN_LINES_DISPLAY_PIPEA (0)
+#define MI_LOAD_SCAN_LINES_DISPLAY_PIPEB (0x1<<20)
+
+/* BLT commands */
+#define COLOR_BLT_CMD ((2<<29)|(0x40<<22)|(0x3))
+#define COLOR_BLT_WRITE_ALPHA (1<<21)
+#define COLOR_BLT_WRITE_RGB (1<<20)
+
+#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|(0x4))
+#define XY_COLOR_BLT_WRITE_ALPHA (1<<21)
+#define XY_COLOR_BLT_WRITE_RGB (1<<20)
+#define XY_COLOR_BLT_TILED (1<<11)
+
+#define XY_SETUP_CLIP_BLT_CMD ((2<<29)|(3<<22)|1)
+
+#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
+#define XY_SRC_COPY_BLT_SRC_TILED (1<<15)
+#define XY_SRC_COPY_BLT_DST_TILED (1<<11)
+
+#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|0x4)
+#define SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define SRC_COPY_BLT_WRITE_RGB (1<<20)
+
+#define XY_PAT_BLT_IMMEDIATE ((2<<29)|(0x72<<22))
+
+#define XY_MONO_PAT_BLT_CMD ((0x2<<29)|(0x52<<22)|0x7)
+#define XY_MONO_PAT_VERT_SEED ((1<<10)|(1<<9)|(1<<8))
+#define XY_MONO_PAT_HORT_SEED ((1<<14)|(1<<13)|(1<<12))
+#define XY_MONO_PAT_BLT_WRITE_ALPHA (1<<21)
+#define XY_MONO_PAT_BLT_WRITE_RGB (1<<20)
+
+#define XY_MONO_SRC_BLT_CMD ((0x2<<29)|(0x54<<22)|(0x6))
+#define XY_MONO_SRC_BLT_WRITE_ALPHA (1<<21)
+#define XY_MONO_SRC_BLT_WRITE_RGB (1<<20)
+
+#define CMD_3D (0x3<<29)
+
+#define PRIM3D_INLINE (CMD_3D | (0x1f<<24))
+#define PRIM3D_TRILIST (0x0<<18)
+#define PRIM3D_TRISTRIP (0x1<<18)
+#define PRIM3D_TRISTRIP_RVRSE (0x2<<18)
+#define PRIM3D_TRIFAN (0x3<<18)
+#define PRIM3D_POLY (0x4<<18)
+#define PRIM3D_LINELIST (0x5<<18)
+#define PRIM3D_LINESTRIP (0x6<<18)
+#define PRIM3D_RECTLIST (0x7<<18)
+#define PRIM3D_POINTLIST (0x8<<18)
+#define PRIM3D_DIB (0x9<<18)
+#define PRIM3D_CLEAR_RECT (0xa<<18)
+#define PRIM3D_ZONE_INIT (0xd<<18)
+#define PRIM3D_MASK (0x1f<<18)
+
+#define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24))
+#define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16)
+#define AA_LINE_ECAAR_WIDTH_0_5 0
+#define AA_LINE_ECAAR_WIDTH_1_0 (1<<14)
+#define AA_LINE_ECAAR_WIDTH_2_0 (2<<14)
+#define AA_LINE_ECAAR_WIDTH_4_0 (3<<14)
+#define AA_LINE_REGION_WIDTH_ENABLE (1<<8)
+#define AA_LINE_REGION_WIDTH_0_5 0
+#define AA_LINE_REGION_WIDTH_1_0 (1<<6)
+#define AA_LINE_REGION_WIDTH_2_0 (2<<6)
+#define AA_LINE_REGION_WIDTH_4_0 (3<<6)
+#define AA_LINE_ENABLE ((1<<1) | 1)
+#define AA_LINE_DISABLE (1<<1)
+
+#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
+/* Dword 1 */
+#define BUF_3D_ID_COLOR_BACK (0x3<<24)
+#define BUF_3D_ID_DEPTH (0x7<<24)
+#define BUF_3D_USE_FENCE (1<<23)
+#define BUF_3D_TILED_SURFACE (1<<22)
+#define BUF_3D_TILE_WALK_X 0
+#define BUF_3D_TILE_WALK_Y (1<<21)
+#define BUF_3D_PITCH(x) (((x)/4)<<2)
+/* Dword 2 */
+#define BUF_3D_ADDR(x) ((x) & ~0x3)
+
+#define _3DSTATE_COLOR_FACTOR_CMD (CMD_3D | (0x1d<<24) | (0x1<<16))
+
+#define _3DSTATE_COLOR_FACTOR_N_CMD(stage) (CMD_3D | (0x1d<<24) | \
+ ((0x90+(stage))<<16))
+
+#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16))
+
+#define _3DSTATE_DFLT_DIFFUSE_CMD (CMD_3D | (0x1d<<24) | (0x99<<16))
+
+#define _3DSTATE_DFLT_SPEC_CMD (CMD_3D | (0x1d<<24) | (0x9a<<16))
+
+#define _3DSTATE_DFLT_Z_CMD (CMD_3D | (0x1d<<24) | (0x98<<16))
+
+#define _3DSTATE_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16))
+/* Dword 1 */
+#define DSTORG_HORT_BIAS(x) ((x)<<20)
+#define DSTORG_VERT_BIAS(x) ((x)<<16)
+#define COLOR_4_2_2_CHNL_WRT_ALL 0
+#define COLOR_4_2_2_CHNL_WRT_Y (1<<12)
+#define COLOR_4_2_2_CHNL_WRT_CR (2<<12)
+#define COLOR_4_2_2_CHNL_WRT_CB (3<<12)
+#define COLOR_4_2_2_CHNL_WRT_CRCB (4<<12)
+#define COLR_BUF_8BIT 0
+#define COLR_BUF_RGB555 (1<<8)
+#define COLR_BUF_RGB565 (2<<8)
+#define COLR_BUF_ARGB8888 (3<<8)
+#define COLR_BUF_ARGB4444 (8<<8)
+#define COLR_BUF_ARGB1555 (9<<8)
+#define DEPTH_IS_Z 0
+#define DEPTH_IS_W (1<<6)
+#define DEPTH_FRMT_16_FIXED 0
+#define DEPTH_FRMT_16_FLOAT (1<<2)
+#define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2)
+#define DEPTH_FRMT_24_FLOAT_8_OTHER (3<<2)
+#define VERT_LINE_STRIDE_1 (1<<1)
+#define VERT_LINE_STRIDE_0 0
+#define VERT_LINE_STRIDE_OFS_1 1
+#define VERT_LINE_STRIDE_OFS_0 0
+
+#define _3DSTATE_DRAW_RECT_CMD (CMD_3D|(0x1d<<24)|(0x80<<16)|3)
+/* Dword 1 */
+#define DRAW_RECT_DIS_DEPTH_OFS (1<<30)
+#define DRAW_DITHER_OFS_X(x) ((x)<<26)
+#define DRAW_DITHER_OFS_Y(x) ((x)<<24)
+/* Dword 2 */
+#define DRAW_YMIN(x) ((x)<<16)
+#define DRAW_XMIN(x) (x)
+/* Dword 3 */
+#define DRAW_YMAX(x) ((x)<<16)
+#define DRAW_XMAX(x) (x)
+/* Dword 4 */
+#define DRAW_YORG(x) ((x)<<16)
+#define DRAW_XORG(x) (x)
+
+#define _3DSTATE_ENABLES_1_CMD (CMD_3D|(0x3<<24))
+#define ENABLE_LOGIC_OP_MASK ((1<<23)|(1<<22))
+#define ENABLE_LOGIC_OP ((1<<23)|(1<<22))
+#define DISABLE_LOGIC_OP (1<<23)
+#define ENABLE_STENCIL_TEST ((1<<21)|(1<<20))
+#define DISABLE_STENCIL_TEST (1<<21)
+#define ENABLE_DEPTH_BIAS ((1<<11)|(1<<10))
+#define DISABLE_DEPTH_BIAS (1<<11)
+#define ENABLE_SPEC_ADD_MASK ((1<<9)|(1<<8))
+#define ENABLE_SPEC_ADD ((1<<9)|(1<<8))
+#define DISABLE_SPEC_ADD (1<<9)
+#define ENABLE_DIS_FOG_MASK ((1<<7)|(1<<6))
+#define ENABLE_FOG ((1<<7)|(1<<6))
+#define DISABLE_FOG (1<<7)
+#define ENABLE_DIS_ALPHA_TEST_MASK ((1<<5)|(1<<4))
+#define ENABLE_ALPHA_TEST ((1<<5)|(1<<4))
+#define DISABLE_ALPHA_TEST (1<<5)
+#define ENABLE_DIS_CBLEND_MASK ((1<<3)|(1<<2))
+#define ENABLE_COLOR_BLEND ((1<<3)|(1<<2))
+#define DISABLE_COLOR_BLEND (1<<3)
+#define ENABLE_DIS_DEPTH_TEST_MASK ((1<<1)|1)
+#define ENABLE_DEPTH_TEST ((1<<1)|1)
+#define DISABLE_DEPTH_TEST (1<<1)
+
+/* _3DSTATE_ENABLES_2, p138 */
+#define _3DSTATE_ENABLES_2_CMD (CMD_3D|(0x4<<24))
+#define ENABLE_STENCIL_WRITE ((1<<21)|(1<<20))
+#define DISABLE_STENCIL_WRITE (1<<21)
+#define ENABLE_TEX_CACHE ((1<<17)|(1<<16))
+#define DISABLE_TEX_CACHE (1<<17)
+#define ENABLE_DITHER ((1<<9)|(1<<8))
+#define DISABLE_DITHER (1<<9)
+#define ENABLE_COLOR_MASK (1<<10)
+#define WRITEMASK_ALPHA (1<<7)
+#define WRITEMASK_ALPHA_SHIFT 7
+#define WRITEMASK_RED (1<<6)
+#define WRITEMASK_RED_SHIFT 6
+#define WRITEMASK_GREEN (1<<5)
+#define WRITEMASK_GREEN_SHIFT 5
+#define WRITEMASK_BLUE (1<<4)
+#define WRITEMASK_BLUE_SHIFT 4
+#define WRITEMASK_MASK ((1<<4)|(1<<5)|(1<<6)|(1<<7))
+#define ENABLE_COLOR_WRITE ((1<<3)|(1<<2))
+#define DISABLE_COLOR_WRITE (1<<3)
+#define ENABLE_DIS_DEPTH_WRITE_MASK 0x3
+#define ENABLE_DEPTH_WRITE ((1<<1)|1)
+#define DISABLE_DEPTH_WRITE (1<<1)
+
+/* _3DSTATE_FOG_COLOR, p139 */
+#define _3DSTATE_FOG_COLOR_CMD (CMD_3D|(0x15<<24))
+#define FOG_COLOR_RED(x) ((x)<<16)
+#define FOG_COLOR_GREEN(x) ((x)<<8)
+#define FOG_COLOR_BLUE(x) (x)
+
+/* _3DSTATE_FOG_MODE, p140 */
+#define _3DSTATE_FOG_MODE_CMD (CMD_3D|(0x1d<<24)|(0x89<<16)|2)
+/* Dword 1 */
+#define FOGFUNC_ENABLE (1<<31)
+#define FOGFUNC_VERTEX 0
+#define FOGFUNC_PIXEL_EXP (1<<28)
+#define FOGFUNC_PIXEL_EXP2 (2<<28)
+#define FOGFUNC_PIXEL_LINEAR (3<<28)
+#define FOGSRC_INDEX_Z (1<<27)
+#define FOGSRC_INDEX_W ((1<<27)|(1<<25))
+#define FOG_LINEAR_CONST (1<<24)
+#define FOG_CONST_1(x) ((x)<<4)
+#define ENABLE_FOG_DENSITY (1<<23)
+/* Dword 2 */
+#define FOG_CONST_2(x) (x)
+/* Dword 3 */
+#define FOG_DENSITY(x) (x)
+
+/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p142 */
+#define _3DSTATE_INDPT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24))
+#define ENABLE_INDPT_ALPHA_BLEND ((1<<23)|(1<<22))
+#define DISABLE_INDPT_ALPHA_BLEND (1<<23)
+#define ALPHA_BLENDFUNC_MASK 0x3f0000
+#define ENABLE_ALPHA_BLENDFUNC (1<<21)
+#define ABLENDFUNC_ADD 0
+#define ABLENDFUNC_SUB (1<<16)
+#define ABLENDFUNC_RVSE_SUB (2<<16)
+#define ABLENDFUNC_MIN (3<<16)
+#define ABLENDFUNC_MAX (4<<16)
+#define SRC_DST_ABLEND_MASK 0xfff
+#define ENABLE_SRC_ABLEND_FACTOR (1<<11)
+#define SRC_ABLEND_FACT(x) ((x)<<6)
+#define ENABLE_DST_ABLEND_FACTOR (1<<5)
+#define DST_ABLEND_FACT(x) (x)
+
+#define BLENDFACTOR_ZERO 0x01
+#define BLENDFACTOR_ONE 0x02
+#define BLENDFACTOR_SRC_COLR 0x03
+#define BLENDFACTOR_INV_SRC_COLR 0x04
+#define BLENDFACTOR_SRC_ALPHA 0x05
+#define BLENDFACTOR_INV_SRC_ALPHA 0x06
+#define BLENDFACTOR_DST_ALPHA 0x07
+#define BLENDFACTOR_INV_DST_ALPHA 0x08
+#define BLENDFACTOR_DST_COLR 0x09
+#define BLENDFACTOR_INV_DST_COLR 0x0a
+#define BLENDFACTOR_SRC_ALPHA_SATURATE 0x0b
+#define BLENDFACTOR_CONST_COLOR 0x0c
+#define BLENDFACTOR_INV_CONST_COLOR 0x0d
+#define BLENDFACTOR_CONST_ALPHA 0x0e
+#define BLENDFACTOR_INV_CONST_ALPHA 0x0f
+#define BLENDFACTOR_MASK 0x0f
+
+/* _3DSTATE_MAP_BLEND_ARG, p152 */
+#define _3DSTATE_MAP_BLEND_ARG_CMD(stage) (CMD_3D|(0x0e<<24)|((stage)<<20))
+
+#define TEXPIPE_COLOR 0
+#define TEXPIPE_ALPHA (1<<18)
+#define TEXPIPE_KILL (2<<18)
+#define TEXBLEND_ARG0 0
+#define TEXBLEND_ARG1 (1<<15)
+#define TEXBLEND_ARG2 (2<<15)
+#define TEXBLEND_ARG3 (3<<15)
+#define TEXBLENDARG_MODIFY_PARMS (1<<6)
+#define TEXBLENDARG_REPLICATE_ALPHA (1<<5)
+#define TEXBLENDARG_INV_ARG (1<<4)
+#define TEXBLENDARG_ONE 0
+#define TEXBLENDARG_FACTOR 0x01
+#define TEXBLENDARG_ACCUM 0x02
+#define TEXBLENDARG_DIFFUSE 0x03
+#define TEXBLENDARG_SPEC 0x04
+#define TEXBLENDARG_CURRENT 0x05
+#define TEXBLENDARG_TEXEL0 0x06
+#define TEXBLENDARG_TEXEL1 0x07
+#define TEXBLENDARG_TEXEL2 0x08
+#define TEXBLENDARG_TEXEL3 0x09
+#define TEXBLENDARG_FACTOR_N 0x0e
+
+/* _3DSTATE_MAP_BLEND_OP, p155 */
+#define _3DSTATE_MAP_BLEND_OP_CMD(stage) (CMD_3D|(0x0d<<24)|((stage)<<20))
+#if 0
+# define TEXPIPE_COLOR 0
+# define TEXPIPE_ALPHA (1<<18)
+# define TEXPIPE_KILL (2<<18)
+#endif
+#define ENABLE_TEXOUTPUT_WRT_SEL (1<<17)
+#define TEXOP_OUTPUT_CURRENT 0
+#define TEXOP_OUTPUT_ACCUM (1<<15)
+#define ENABLE_TEX_CNTRL_STAGE ((1<<12)|(1<<11))
+#define DISABLE_TEX_CNTRL_STAGE (1<<12)
+#define TEXOP_SCALE_SHIFT 9
+#define TEXOP_SCALE_1X (0 << TEXOP_SCALE_SHIFT)
+#define TEXOP_SCALE_2X (1 << TEXOP_SCALE_SHIFT)
+#define TEXOP_SCALE_4X (2 << TEXOP_SCALE_SHIFT)
+#define TEXOP_MODIFY_PARMS (1<<8)
+#define TEXOP_LAST_STAGE (1<<7)
+#define TEXBLENDOP_KILLPIXEL 0x02
+#define TEXBLENDOP_ARG1 0x01
+#define TEXBLENDOP_ARG2 0x02
+#define TEXBLENDOP_MODULATE 0x03
+#define TEXBLENDOP_ADD 0x06
+#define TEXBLENDOP_ADDSIGNED 0x07
+#define TEXBLENDOP_BLEND 0x08
+#define TEXBLENDOP_BLEND_AND_ADD 0x09
+#define TEXBLENDOP_SUBTRACT 0x0a
+#define TEXBLENDOP_DOT3 0x0b
+#define TEXBLENDOP_DOT4 0x0c
+#define TEXBLENDOP_MODULATE_AND_ADD 0x0d
+#define TEXBLENDOP_MODULATE_2X_AND_ADD 0x0e
+#define TEXBLENDOP_MODULATE_4X_AND_ADD 0x0f
+
+/* _3DSTATE_MAP_BUMP_TABLE, p160 TODO */
+/* _3DSTATE_MAP_COLOR_CHROMA_KEY, p161 TODO */
+
+#define _3DSTATE_MAP_COORD_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8c<<16))
+#define DISABLE_TEX_TRANSFORM (1<<28)
+#define TEXTURE_SET(x) (x<<29)
+
+#define _3DSTATE_VERTEX_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8b<<16))
+#define DISABLE_VIEWPORT_TRANSFORM (1<<31)
+#define DISABLE_PERSPECTIVE_DIVIDE (1<<29)
+
+/* _3DSTATE_MAP_COORD_SET_BINDINGS, p162 */
+#define _3DSTATE_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16))
+#define TEXBIND_MASK3 ((1<<15)|(1<<14)|(1<<13)|(1<<12))
+#define TEXBIND_MASK2 ((1<<11)|(1<<10)|(1<<9)|(1<<8))
+#define TEXBIND_MASK1 ((1<<7)|(1<<6)|(1<<5)|(1<<4))
+#define TEXBIND_MASK0 ((1<<3)|(1<<2)|(1<<1)|1)
+
+#define TEXBIND_SET3(x) ((x)<<12)
+#define TEXBIND_SET2(x) ((x)<<8)
+#define TEXBIND_SET1(x) ((x)<<4)
+#define TEXBIND_SET0(x) (x)
+
+#define TEXCOORDSRC_KEEP 0
+#define TEXCOORDSRC_DEFAULT 0x01
+#define TEXCOORDSRC_VTXSET_0 0x08
+#define TEXCOORDSRC_VTXSET_1 0x09
+#define TEXCOORDSRC_VTXSET_2 0x0a
+#define TEXCOORDSRC_VTXSET_3 0x0b
+#define TEXCOORDSRC_VTXSET_4 0x0c
+#define TEXCOORDSRC_VTXSET_5 0x0d
+#define TEXCOORDSRC_VTXSET_6 0x0e
+#define TEXCOORDSRC_VTXSET_7 0x0f
+
+#define MAP_UNIT(unit) ((unit)<<16)
+#define MAP_UNIT_MASK (0x7<<16)
+
+/* _3DSTATE_MAP_COORD_SETS, p164 */
+#define _3DSTATE_MAP_COORD_SET_CMD (CMD_3D|(0x1c<<24)|(0x01<<19))
+#define TEXCOORD_SET(n) ((n)<<16)
+#define ENABLE_TEXCOORD_PARAMS (1<<15)
+#define TEXCOORDS_ARE_NORMAL (1<<14)
+#define TEXCOORDS_ARE_IN_TEXELUNITS 0
+#define TEXCOORDTYPE_CARTESIAN 0
+#define TEXCOORDTYPE_HOMOGENEOUS (1<<11)
+#define TEXCOORDTYPE_VECTOR (2<<11)
+#define TEXCOORDTYPE_MASK (0x7<<11)
+#define ENABLE_ADDR_V_CNTL (1<<7)
+#define ENABLE_ADDR_U_CNTL (1<<3)
+#define TEXCOORD_ADDR_V_MODE(x) ((x)<<4)
+#define TEXCOORD_ADDR_U_MODE(x) (x)
+#define TEXCOORDMODE_WRAP 0
+#define TEXCOORDMODE_MIRROR 1
+#define TEXCOORDMODE_CLAMP 2
+#define TEXCOORDMODE_WRAP_SHORTEST 3
+#define TEXCOORDMODE_CLAMP_BORDER 4
+#define TEXCOORD_ADDR_V_MASK 0x70
+#define TEXCOORD_ADDR_U_MASK 0x7
+
+/* _3DSTATE_MAP_CUBE, p168 TODO */
+#define _3DSTATE_MAP_CUBE (CMD_3D|(0x1c<<24)|(0x0a<<19))
+#define CUBE_NEGX_ENABLE (1<<5)
+#define CUBE_POSX_ENABLE (1<<4)
+#define CUBE_NEGY_ENABLE (1<<3)
+#define CUBE_POSY_ENABLE (1<<2)
+#define CUBE_NEGZ_ENABLE (1<<1)
+#define CUBE_POSZ_ENABLE (1<<0)
+
+#define _3DSTATE_MAP_INFO_CMD (CMD_3D|(0x1d<<24)|(0x0<<16)|3)
+#define TEXMAP_INDEX(x) ((x)<<28)
+#define MAP_SURFACE_8BIT (1<<24)
+#define MAP_SURFACE_16BIT (2<<24)
+#define MAP_SURFACE_32BIT (3<<24)
+#define MAP_FORMAT_2D (0)
+#define MAP_FORMAT_3D_CUBE (1<<11)
+
+/* _3DSTATE_MODES_1, p190 */
+#define _3DSTATE_MODES_1_CMD (CMD_3D|(0x08<<24))
+#define BLENDFUNC_MASK 0x3f0000
+#define ENABLE_COLR_BLND_FUNC (1<<21)
+#define BLENDFUNC_ADD 0
+#define BLENDFUNC_SUB (1<<16)
+#define BLENDFUNC_RVRSE_SUB (2<<16)
+#define BLENDFUNC_MIN (3<<16)
+#define BLENDFUNC_MAX (4<<16)
+#define SRC_DST_BLND_MASK 0xfff
+#define ENABLE_SRC_BLND_FACTOR (1<<11)
+#define ENABLE_DST_BLND_FACTOR (1<<5)
+#define SRC_BLND_FACT(x) ((x)<<6)
+#define DST_BLND_FACT(x) (x)
+
+/* _3DSTATE_MODES_2, p192 */
+#define _3DSTATE_MODES_2_CMD (CMD_3D|(0x0f<<24))
+#define ENABLE_GLOBAL_DEPTH_BIAS (1<<22)
+#define GLOBAL_DEPTH_BIAS(x) ((x)<<14)
+#define ENABLE_ALPHA_TEST_FUNC (1<<13)
+#define ENABLE_ALPHA_REF_VALUE (1<<8)
+#define ALPHA_TEST_FUNC(x) ((x)<<9)
+#define ALPHA_REF_VALUE(x) (x)
+
+#define ALPHA_TEST_REF_MASK 0x3fff
+
+/* _3DSTATE_MODES_3, p193 */
+#define _3DSTATE_MODES_3_CMD (CMD_3D|(0x02<<24))
+#define DEPTH_TEST_FUNC_MASK 0x1f0000
+#define ENABLE_DEPTH_TEST_FUNC (1<<20)
+/* Uses COMPAREFUNC */
+#define DEPTH_TEST_FUNC(x) ((x)<<16)
+#define ENABLE_ALPHA_SHADE_MODE (1<<11)
+#define ENABLE_FOG_SHADE_MODE (1<<9)
+#define ENABLE_SPEC_SHADE_MODE (1<<7)
+#define ENABLE_COLOR_SHADE_MODE (1<<5)
+#define ALPHA_SHADE_MODE(x) ((x)<<10)
+#define FOG_SHADE_MODE(x) ((x)<<8)
+#define SPEC_SHADE_MODE(x) ((x)<<6)
+#define COLOR_SHADE_MODE(x) ((x)<<4)
+#define CULLMODE_MASK 0xf
+#define ENABLE_CULL_MODE (1<<3)
+#define CULLMODE_BOTH 0
+#define CULLMODE_NONE 1
+#define CULLMODE_CW 2
+#define CULLMODE_CCW 3
+
+#define SHADE_MODE_LINEAR 0
+#define SHADE_MODE_FLAT 0x1
+
+/* _3DSTATE_MODES_4, p195 */
+#define _3DSTATE_MODES_4_CMD (CMD_3D|(0x16<<24))
+#define ENABLE_LOGIC_OP_FUNC (1<<23)
+#define LOGIC_OP_FUNC(x) ((x)<<18)
+#define LOGICOP_MASK ((1<<18)|(1<<19)|(1<<20)|(1<<21))
+#define LOGICOP_CLEAR 0
+#define LOGICOP_NOR 0x1
+#define LOGICOP_AND_INV 0x2
+#define LOGICOP_COPY_INV 0x3
+#define LOGICOP_AND_RVRSE 0x4
+#define LOGICOP_INV 0x5
+#define LOGICOP_XOR 0x6
+#define LOGICOP_NAND 0x7
+#define LOGICOP_AND 0x8
+#define LOGICOP_EQUIV 0x9
+#define LOGICOP_NOOP 0xa
+#define LOGICOP_OR_INV 0xb
+#define LOGICOP_COPY 0xc
+#define LOGICOP_OR_RVRSE 0xd
+#define LOGICOP_OR 0xe
+#define LOGICOP_SET 0xf
+#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
+#define ENABLE_STENCIL_TEST_MASK (1<<17)
+#define STENCIL_TEST_MASK(x) ((x)<<8)
+#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
+#define ENABLE_STENCIL_WRITE_MASK (1<<16)
+#define STENCIL_WRITE_MASK(x) ((x)&0xff)
+
+/* _3DSTATE_MODES_5, p196 */
+#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))
+#define ENABLE_SPRITE_POINT_TEX (1<<23)
+#define SPRITE_POINT_TEX_ON (1<<22)
+#define SPRITE_POINT_TEX_OFF 0
+#define FLUSH_RENDER_CACHE (1<<18)
+#define FLUSH_TEXTURE_CACHE (1<<16)
+#define FIXED_LINE_WIDTH_MASK 0xfc00
+#define ENABLE_FIXED_LINE_WIDTH (1<<15)
+#define FIXED_LINE_WIDTH(x) ((x)<<10)
+#define FIXED_POINT_WIDTH_MASK 0x3ff
+#define ENABLE_FIXED_POINT_WIDTH (1<<9)
+#define FIXED_POINT_WIDTH(x) (x)
+
+/* _3DSTATE_RASTERIZATION_RULES, p198 */
+#define _3DSTATE_RASTER_RULES_CMD (CMD_3D|(0x07<<24))
+#define ENABLE_POINT_RASTER_RULE (1<<15)
+#define OGL_POINT_RASTER_RULE (1<<13)
+#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8)
+#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5)
+#define ENABLE_TRI_STRIP_PROVOKE_VRTX (1<<2)
+#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6)
+#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3)
+#define TRI_STRIP_PROVOKE_VRTX(x) (x)
+
+/* _3DSTATE_SCISSOR_ENABLE, p200 */
+#define _3DSTATE_SCISSOR_ENABLE_CMD (CMD_3D|(0x1c<<24)|(0x10<<19))
+#define ENABLE_SCISSOR_RECT ((1<<1) | 1)
+#define DISABLE_SCISSOR_RECT (1<<1)
+
+/* _3DSTATE_SCISSOR_RECTANGLE_0, p201 */
+#define _3DSTATE_SCISSOR_RECT_0_CMD (CMD_3D|(0x1d<<24)|(0x81<<16)|1)
+/* Dword 1 */
+#define SCISSOR_RECT_0_YMIN(x) ((x)<<16)
+#define SCISSOR_RECT_0_XMIN(x) (x)
+/* Dword 2 */
+#define SCISSOR_RECT_0_YMAX(x) ((x)<<16)
+#define SCISSOR_RECT_0_XMAX(x) (x)
+
+/* _3DSTATE_STENCIL_TEST, p202 */
+#define _3DSTATE_STENCIL_TEST_CMD (CMD_3D|(0x09<<24))
+#define ENABLE_STENCIL_PARMS (1<<23)
+#define STENCIL_OPS_MASK (0xffc000)
+#define STENCIL_FAIL_OP(x) ((x)<<20)
+#define STENCIL_PASS_DEPTH_FAIL_OP(x) ((x)<<17)
+#define STENCIL_PASS_DEPTH_PASS_OP(x) ((x)<<14)
+
+#define ENABLE_STENCIL_TEST_FUNC_MASK ((1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9))
+#define ENABLE_STENCIL_TEST_FUNC (1<<13)
+/* Uses COMPAREFUNC */
+#define STENCIL_TEST_FUNC(x) ((x)<<9)
+#define STENCIL_REF_VALUE_MASK ((1<<8)|0xff)
+#define ENABLE_STENCIL_REF_VALUE (1<<8)
+#define STENCIL_REF_VALUE(x) (x)
+
+/* _3DSTATE_VERTEX_FORMAT, p204 */
+#define _3DSTATE_VFT0_CMD (CMD_3D|(0x05<<24))
+#define VFT0_POINT_WIDTH (1<<12)
+#define VFT0_TEX_COUNT_MASK (7<<8)
+#define VFT0_TEX_COUNT_SHIFT 8
+#define VFT0_TEX_COUNT(x) ((x)<<8)
+#define VFT0_SPEC (1<<7)
+#define VFT0_DIFFUSE (1<<6)
+#define VFT0_DEPTH_OFFSET (1<<5)
+#define VFT0_XYZ (1<<1)
+#define VFT0_XYZW (2<<1)
+#define VFT0_XY (3<<1)
+#define VFT0_XYW (4<<1)
+#define VFT0_XYZW_MASK (7<<1)
+
+/* _3DSTATE_VERTEX_FORMAT_2, p206 */
+#define _3DSTATE_VERTEX_FORMAT_2_CMD (CMD_3D|(0x0a<<24))
+#define VFT1_TEX7_FMT(x) ((x)<<14)
+#define VFT1_TEX6_FMT(x) ((x)<<12)
+#define VFT1_TEX5_FMT(x) ((x)<<10)
+#define VFT1_TEX4_FMT(x) ((x)<<8)
+#define VFT1_TEX3_FMT(x) ((x)<<6)
+#define VFT1_TEX2_FMT(x) ((x)<<4)
+#define VFT1_TEX1_FMT(x) ((x)<<2)
+#define VFT1_TEX0_FMT(x) (x)
+#define VFT1_TEX0_MASK 3
+#define VFT1_TEX1_SHIFT 2
+#define TEXCOORDFMT_2D 0
+#define TEXCOORDFMT_3D 1
+#define TEXCOORDFMT_4D 2
+#define TEXCOORDFMT_1D 3
+
+/*New stuff picked up along the way */
+
+#define MLC_LOD_BIAS_MASK ((1<<7)-1)
+
+/* _3DSTATE_VERTEX_TRANSFORM, p207 */
+#define _3DSTATE_VERTEX_TRANS_CMD (CMD_3D|(0x1d<<24)|(0x8b<<16)|0)
+#define _3DSTATE_VERTEX_TRANS_MTX_CMD (CMD_3D|(0x1d<<24)|(0x8b<<16)|6)
+/* Dword 1 */
+#define ENABLE_VIEWPORT_TRANSFORM ((1<<31)|(1<<30))
+#define DISABLE_VIEWPORT_TRANSFORM (1<<31)
+#define ENABLE_PERSP_DIVIDE ((1<<29)|(1<<28))
+#define DISABLE_PERSP_DIVIDE (1<<29)
+#define VRTX_TRANS_LOAD_MATRICES 0x7421
+#define VRTX_TRANS_NO_LOAD_MATRICES 0x0000
+/* Dword 2 -> 7 are matrix elements */
+
+/* _3DSTATE_W_STATE, p209 */
+#define _3DSTATE_W_STATE_CMD (CMD_3D|(0x1d<<24)|(0x8d<<16)|1)
+/* Dword 1 */
+#define MAGIC_W_STATE_DWORD1 0x00000008
+/* Dword 2 */
+#define WFAR_VALUE(x) (x)
+
+/* Stipple command, carried over from the i810, apparently:
+ */
+#define _3DSTATE_STIPPLE (CMD_3D|(0x1d<<24)|(0x83<<16))
+#define ST1_ENABLE (1<<16)
+#define ST1_MASK (0xffff)
+
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_1 (CMD_3D|(0x1d<<24)|(0x04<<16))
+#define I1_LOAD_S(n) (1<<((n)+4))
+#define S3_POINT_WIDTH_SHIFT 23
+#define S3_LINE_WIDTH_SHIFT 19
+#define S3_ALPHA_SHADE_MODE_SHIFT 18
+#define S3_FOG_SHADE_MODE_SHIFT 17
+#define S3_SPEC_SHADE_MODE_SHIFT 16
+#define S3_COLOR_SHADE_MODE_SHIFT 15
+#define S3_CULL_MODE_SHIFT 13
+#define S3_CULLMODE_BOTH (0)
+#define S3_CULLMODE_NONE (1<<13)
+#define S3_CULLMODE_CW (2<<13)
+#define S3_CULLMODE_CCW (3<<13)
+#define S3_POINT_WIDTH_PRESENT (1<<12)
+#define S3_SPEC_FOG_PRESENT (1<<11)
+#define S3_DIFFUSE_PRESENT (1<<10)
+#define S3_DEPTH_OFFSET_PRESENT (1<<9)
+#define S3_POSITION_SHIFT 6
+#define S3_VERTEXHAS_XYZ (1<<6)
+#define S3_VERTEXHAS_XYZW (2<<6)
+#define S3_VERTEXHAS_XY (3<<6)
+#define S3_VERTEXHAS_XYW (4<<6)
+#define S3_ENABLE_SPEC_ADD (1<<5)
+#define S3_ENABLE_FOG (1<<4)
+#define S3_ENABLE_LOCAL_DEPTH_BIAS (1<<3)
+#define S3_ENABLE_SPRITE_POINT (1<<1)
+#define S3_ENABLE_ANTIALIASING 1
+#define S8_ENABLE_ALPHA_TEST (1<<31)
+#define S8_ALPHA_TEST_FUNC_SHIFT 28
+#define S8_ALPHA_REFVALUE_SHIFT 20
+#define S8_ENABLE_DEPTH_TEST (1<<19)
+#define S8_DEPTH_TEST_FUNC_SHIFT 16
+#define S8_ENABLE_COLOR_BLEND (1<<15)
+#define S8_COLOR_BLEND_FUNC_SHIFT 12
+#define S8_BLENDFUNC_ADD (0)
+#define S8_BLENDFUNC_SUB (1<<12)
+#define S8_BLENDFUNC_RVRSE_SUB (2<<12)
+#define S8_BLENDFUNC_MIN (3<<12)
+#define S8_BLENDFUNC_MAX (4<<12)
+#define S8_SRC_BLEND_FACTOR_SHIFT 8
+#define S8_DST_BLEND_FACTOR_SHIFT 4
+#define S8_ENABLE_DEPTH_BUFFER_WRITE (1<<3)
+#define S8_ENABLE_COLOR_BUFFER_WRITE (1<<2)
+
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_2 (CMD_3D|(0x1d<<24)|(0x03<<16))
+#define LOAD_TEXTURE_MAP(x) (1<<((x)+11))
+#define LOAD_TEXTURE_BLEND_STAGE(x) (1<<((x)+7))
+#define LOAD_GLOBAL_COLOR_FACTOR (1<<6)
+
+#define TM0S0_ADDRESS_MASK 0xfffffffc
+#define TM0S0_USE_FENCE (1<<1)
+
+#define TM0S1_HEIGHT_SHIFT 21
+#define TM0S1_WIDTH_SHIFT 10
+#define TM0S1_PALETTE_SELECT (1<<9)
+#define TM0S1_MAPSURF_FORMAT_MASK (0x7 << 6)
+#define TM0S1_MAPSURF_FORMAT_SHIFT 6
+#define MAPSURF_8BIT_INDEXED (0<<6)
+#define MAPSURF_8BIT (1<<6)
+#define MAPSURF_16BIT (2<<6)
+#define MAPSURF_32BIT (3<<6)
+#define MAPSURF_411 (4<<6)
+#define MAPSURF_422 (5<<6)
+#define MAPSURF_COMPRESSED (6<<6)
+#define MAPSURF_4BIT_INDEXED (7<<6)
+#define TM0S1_MT_FORMAT_MASK (0x7 << 3)
+#define TM0S1_MT_FORMAT_SHIFT 3
+#define MT_4BIT_IDX_ARGB8888 (7<<3) /* SURFACE_4BIT_INDEXED */
+#define MT_8BIT_IDX_RGB565 (0<<3) /* SURFACE_8BIT_INDEXED */
+#define MT_8BIT_IDX_ARGB1555 (1<<3)
+#define MT_8BIT_IDX_ARGB4444 (2<<3)
+#define MT_8BIT_IDX_AY88 (3<<3)
+#define MT_8BIT_IDX_ABGR8888 (4<<3)
+#define MT_8BIT_IDX_BUMP_88DVDU (5<<3)
+#define MT_8BIT_IDX_BUMP_655LDVDU (6<<3)
+#define MT_8BIT_IDX_ARGB8888 (7<<3)
+#define MT_8BIT_I8 (0<<3) /* SURFACE_8BIT */
+#define MT_8BIT_L8 (1<<3)
+#define MT_8BIT_A8 (4<<3)
+#define MT_16BIT_RGB565 (0<<3) /* SURFACE_16BIT */
+#define MT_16BIT_ARGB1555 (1<<3)
+#define MT_16BIT_ARGB4444 (2<<3)
+#define MT_16BIT_AY88 (3<<3)
+#define MT_16BIT_DIB_ARGB1555_8888 (4<<3)
+#define MT_16BIT_BUMP_88DVDU (5<<3)
+#define MT_16BIT_BUMP_655LDVDU (6<<3)
+#define MT_16BIT_DIB_RGB565_8888 (7<<3)
+#define MT_32BIT_ARGB8888 (0<<3) /* SURFACE_32BIT */
+#define MT_32BIT_ABGR8888 (1<<3)
+#define MT_32BIT_XRGB8888 (2<<3)
+#define MT_32BIT_XBGR8888 (3<<3)
+#define MT_32BIT_BUMP_XLDVDU_8888 (6<<3)
+#define MT_32BIT_DIB_8888 (7<<3)
+#define MT_411_YUV411 (0<<3) /* SURFACE_411 */
+#define MT_422_YCRCB_SWAPY (0<<3) /* SURFACE_422 */
+#define MT_422_YCRCB_NORMAL (1<<3)
+#define MT_422_YCRCB_SWAPUV (2<<3)
+#define MT_422_YCRCB_SWAPUVY (3<<3)
+#define MT_COMPRESS_DXT1 (0<<3) /* SURFACE_COMPRESSED */
+#define MT_COMPRESS_DXT2_3 (1<<3)
+#define MT_COMPRESS_DXT4_5 (2<<3)
+#define MT_COMPRESS_FXT1 (3<<3)
+#define TM0S1_COLORSPACE_CONVERSION (1 << 2)
+#define TM0S1_TILED_SURFACE (1 << 1)
+#define TM0S1_TILE_WALK (1 << 0)
+
+#define TM0S2_PITCH_SHIFT 21
+#define TM0S2_CUBE_FACE_ENA_SHIFT 15
+#define TM0S2_CUBE_FACE_ENA_MASK (1<<15)
+#define TM0S2_MAP_FORMAT (1<<14)
+#define TM0S2_MAP_2D (0<<14)
+#define TM0S2_MAP_3D_CUBE (1<<14)
+#define TM0S2_VERTICAL_LINE_STRIDE (1<<13)
+#define TM0S2_VERITCAL_LINE_STRIDE_OFF (1<<12)
+#define TM0S2_OUTPUT_CHAN_SHIFT 10
+#define TM0S2_OUTPUT_CHAN_MASK (3<<10)
+
+#define TM0S3_MIP_FILTER_MASK (0x3<<30)
+#define TM0S3_MIP_FILTER_SHIFT 30
+#define MIPFILTER_NONE 0
+#define MIPFILTER_NEAREST 1
+#define MIPFILTER_LINEAR 3
+#define TM0S3_MAG_FILTER_MASK (0x3<<28)
+#define TM0S3_MAG_FILTER_SHIFT 28
+#define TM0S3_MIN_FILTER_MASK (0x3<<26)
+#define TM0S3_MIN_FILTER_SHIFT 26
+#define FILTER_NEAREST 0
+#define FILTER_LINEAR 1
+#define FILTER_ANISOTROPIC 2
+
+#define TM0S3_LOD_BIAS_SHIFT 17
+#define TM0S3_LOD_BIAS_MASK (0x1ff<<17)
+#define TM0S3_MAX_MIP_SHIFT 9
+#define TM0S3_MAX_MIP_MASK (0xff<<9)
+#define TM0S3_MIN_MIP_SHIFT 3
+#define TM0S3_MIN_MIP_MASK (0x3f<<3)
+#define TM0S3_KILL_PIXEL (1<<2)
+#define TM0S3_KEYED_FILTER (1<<1)
+#define TM0S3_CHROMA_KEY (1<<0)
+
+/* _3DSTATE_MAP_TEXEL_STREAM, p188 */
+#define _3DSTATE_MAP_TEX_STREAM_CMD (CMD_3D|(0x1c<<24)|(0x05<<19))
+#define DISABLE_TEX_STREAM_BUMP (1<<12)
+#define ENABLE_TEX_STREAM_BUMP ((1<<12)|(1<<11))
+#define TEX_MODIFY_UNIT_0 0
+#define TEX_MODIFY_UNIT_1 (1<<8)
+#define ENABLE_TEX_STREAM_COORD_SET (1<<7)
+#define TEX_STREAM_COORD_SET(x) ((x)<<4)
+#define ENABLE_TEX_STREAM_MAP_IDX (1<<3)
+#define TEX_STREAM_MAP_IDX(x) (x)
+
+#define FLUSH_MAP_CACHE (1<<0)
+
+#define _3DSTATE_MAP_FILTER_CMD (CMD_3D|(0x1c<<24)|(0x02<<19))
+#define FILTER_TEXMAP_INDEX(x) ((x) << 16)
+#define MAG_MODE_FILTER_ENABLE (1 << 5)
+#define MIN_MODE_FILTER_ENABLE (1 << 2)
+#define MAG_MAPFILTER_NEAREST (0 << 3)
+#define MAG_MAPFILTER_LINEAR (1 << 3)
+#define MAG_MAPFILTER_ANISOTROPIC (2 << 3)
+#define MIN_MAPFILTER_NEAREST (0)
+#define MIN_MAPFILTER_LINEAR (1)
+#define MIN_MAPFILTER_ANISOTROPIC (2)
+#define ENABLE_KEYS (1<<15)
+#define DISABLE_COLOR_KEY 0
+#define DISABLE_CHROMA_KEY 0
+#define DISABLE_KILL_PIXEL 0
+#define ENABLE_MIP_MODE_FILTER (1 << 9)
+#define MIPFILTER_NONE 0
+#define MIPFILTER_NEAREST 1
+#define MIPFILTER_LINEAR 3
+
+#endif
diff --git a/lib/i915_3d.h b/lib/i915_3d.h
new file mode 100644
index 00000000..04531f33
--- /dev/null
+++ b/lib/i915_3d.h
@@ -0,0 +1,619 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006,2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/* Each instruction is 3 dwords long, though most don't require all
+ * this space. Maximum of 123 instructions. Smaller maxes per insn
+ * type.
+ */
+#define _3DSTATE_PIXEL_SHADER_PROGRAM (CMD_3D|(0x1d<<24)|(0x5<<16))
+
+#define REG_TYPE_R 0 /* temporary regs, no need to
+ * dcl, must be written before
+ * read -- Preserved between
+ * phases.
+ */
+#define REG_TYPE_T 1 /* Interpolated values, must be
+ * dcl'ed before use.
+ *
+ * 0..7: texture coord,
+ * 8: diffuse spec,
+ * 9: specular color,
+ * 10: fog parameter in w.
+ */
+#define REG_TYPE_CONST 2 /* Restriction: only one const
+ * can be referenced per
+ * instruction, though it may be
+ * selected for multiple inputs.
+ * Constants not initialized
+ * default to zero.
+ */
+#define REG_TYPE_S 3 /* sampler */
+#define REG_TYPE_OC 4 /* output color (rgba) */
+#define REG_TYPE_OD 5 /* output depth (w), xyz are
+ * temporaries. If not written,
+ * interpolated depth is used?
+ */
+#define REG_TYPE_U 6 /* unpreserved temporaries */
+#define REG_TYPE_MASK 0x7
+#define REG_TYPE_SHIFT 4
+#define REG_NR_MASK 0xf
+
+/* REG_TYPE_T:
+*/
+#define T_TEX0 0
+#define T_TEX1 1
+#define T_TEX2 2
+#define T_TEX3 3
+#define T_TEX4 4
+#define T_TEX5 5
+#define T_TEX6 6
+#define T_TEX7 7
+#define T_DIFFUSE 8
+#define T_SPECULAR 9
+#define T_FOG_W 10 /* interpolated fog is in W coord */
+
+/* Arithmetic instructions */
+
+/* .replicate_swizzle == selection and replication of a particular
+ * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww
+ */
+#define A0_NOP (0x0<<24) /* no operation */
+#define A0_ADD (0x1<<24) /* dst = src0 + src1 */
+#define A0_MOV (0x2<<24) /* dst = src0 */
+#define A0_MUL (0x3<<24) /* dst = src0 * src1 */
+#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */
+#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */
+#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */
+#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */
+#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */
+#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */
+#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */
+#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */
+#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */
+#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */
+#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */
+#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */
+#define A0_FLR (0x10<<24) /* dst = floor(src0) */
+#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */
+#define A0_TRC (0x12<<24) /* dst = int(src0) */
+#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */
+#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */
+#define A0_DEST_SATURATE (1<<22)
+#define A0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+#define A0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define A0_DEST_CHANNEL_X (1<<10)
+#define A0_DEST_CHANNEL_Y (2<<10)
+#define A0_DEST_CHANNEL_Z (4<<10)
+#define A0_DEST_CHANNEL_W (8<<10)
+#define A0_DEST_CHANNEL_ALL (0xf<<10)
+#define A0_DEST_CHANNEL_SHIFT 10
+#define A0_SRC0_TYPE_SHIFT 7
+#define A0_SRC0_NR_SHIFT 2
+
+#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y)
+#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z)
+
+#define SRC_X 0
+#define SRC_Y 1
+#define SRC_Z 2
+#define SRC_W 3
+#define SRC_ZERO 4
+#define SRC_ONE 5
+
+#define A1_SRC0_CHANNEL_X_NEGATE (1<<31)
+#define A1_SRC0_CHANNEL_X_SHIFT 28
+#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27)
+#define A1_SRC0_CHANNEL_Y_SHIFT 24
+#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23)
+#define A1_SRC0_CHANNEL_Z_SHIFT 20
+#define A1_SRC0_CHANNEL_W_NEGATE (1<<19)
+#define A1_SRC0_CHANNEL_W_SHIFT 16
+#define A1_SRC1_TYPE_SHIFT 13
+#define A1_SRC1_NR_SHIFT 8
+#define A1_SRC1_CHANNEL_X_NEGATE (1<<7)
+#define A1_SRC1_CHANNEL_X_SHIFT 4
+#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3)
+#define A1_SRC1_CHANNEL_Y_SHIFT 0
+
+#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31)
+#define A2_SRC1_CHANNEL_Z_SHIFT 28
+#define A2_SRC1_CHANNEL_W_NEGATE (1<<27)
+#define A2_SRC1_CHANNEL_W_SHIFT 24
+#define A2_SRC2_TYPE_SHIFT 21
+#define A2_SRC2_NR_SHIFT 16
+#define A2_SRC2_CHANNEL_X_NEGATE (1<<15)
+#define A2_SRC2_CHANNEL_X_SHIFT 12
+#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11)
+#define A2_SRC2_CHANNEL_Y_SHIFT 8
+#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7)
+#define A2_SRC2_CHANNEL_Z_SHIFT 4
+#define A2_SRC2_CHANNEL_W_NEGATE (1<<3)
+#define A2_SRC2_CHANNEL_W_SHIFT 0
+
+/* Texture instructions */
+#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared
+ * sampler and address, and output
+ * filtered texel data to destination
+ * register */
+#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a
+ * perspective divide of the texture
+ * coordinate .xyz values by .w before
+ * sampling. */
+#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the
+ * computed LOD by w. Only S4.6 two's
+ * comp is used. This implies that a
+ * float to fixed conversion is
+ * done. */
+#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling
+ * operation. Simply kills the pixel
+ * if any channel of the address
+ * register is < 0.0. */
+#define T0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+/* Note: U (unpreserved) regs do not retain their values between
+ * phases (cannot be used for feedback)
+ *
+ * Note: oC and OD registers can only be used as the destination of a
+ * texture instruction once per phase (this is an implementation
+ * restriction).
+ */
+#define T0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */
+#define T0_SAMPLER_NR_MASK (0xf<<0)
+
+#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */
+/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */
+#define T1_ADDRESS_REG_NR_SHIFT 17
+#define T2_MBZ 0
+
+/* Declaration instructions */
+#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib)
+ * register or an s (sampler)
+ * register. */
+#define D0_SAMPLE_TYPE_SHIFT 22
+#define D0_SAMPLE_TYPE_2D (0x0<<22)
+#define D0_SAMPLE_TYPE_CUBE (0x1<<22)
+#define D0_SAMPLE_TYPE_VOLUME (0x2<<22)
+#define D0_SAMPLE_TYPE_MASK (0x3<<22)
+
+#define D0_TYPE_SHIFT 19
+/* Allow: T, S */
+#define D0_NR_SHIFT 14
+/* Allow T: 0..10, S: 0..15 */
+#define D0_CHANNEL_X (1<<10)
+#define D0_CHANNEL_Y (2<<10)
+#define D0_CHANNEL_Z (4<<10)
+#define D0_CHANNEL_W (8<<10)
+#define D0_CHANNEL_ALL (0xf<<10)
+#define D0_CHANNEL_NONE (0<<10)
+
+#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y)
+#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z)
+
+/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse
+ * or specular declarations.
+ *
+ * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw)
+ *
+ * Must be zero for S (sampler) dcls
+ */
+#define D1_MBZ 0
+#define D2_MBZ 0
+
+
+/* MASK_* are the unshifted bitmasks of the destination mask in arithmetic
+ * operations
+ */
+#define MASK_X 0x1
+#define MASK_Y 0x2
+#define MASK_Z 0x4
+#define MASK_W 0x8
+#define MASK_XYZ (MASK_X | MASK_Y | MASK_Z)
+#define MASK_XYZW (MASK_XYZ | MASK_W)
+#define MASK_SATURATE 0x10
+
+/* Temporary, undeclared regs. Preserved between phases */
+#define FS_R0 ((REG_TYPE_R << REG_TYPE_SHIFT) | 0)
+#define FS_R1 ((REG_TYPE_R << REG_TYPE_SHIFT) | 1)
+#define FS_R2 ((REG_TYPE_R << REG_TYPE_SHIFT) | 2)
+#define FS_R3 ((REG_TYPE_R << REG_TYPE_SHIFT) | 3)
+
+/* Texture coordinate regs. Must be declared. */
+#define FS_T0 ((REG_TYPE_T << REG_TYPE_SHIFT) | 0)
+#define FS_T1 ((REG_TYPE_T << REG_TYPE_SHIFT) | 1)
+#define FS_T2 ((REG_TYPE_T << REG_TYPE_SHIFT) | 2)
+#define FS_T3 ((REG_TYPE_T << REG_TYPE_SHIFT) | 3)
+#define FS_T4 ((REG_TYPE_T << REG_TYPE_SHIFT) | 4)
+#define FS_T5 ((REG_TYPE_T << REG_TYPE_SHIFT) | 5)
+#define FS_T6 ((REG_TYPE_T << REG_TYPE_SHIFT) | 6)
+#define FS_T7 ((REG_TYPE_T << REG_TYPE_SHIFT) | 7)
+#define FS_T8 ((REG_TYPE_T << REG_TYPE_SHIFT) | 8)
+#define FS_T9 ((REG_TYPE_T << REG_TYPE_SHIFT) | 9)
+#define FS_T10 ((REG_TYPE_T << REG_TYPE_SHIFT) | 10)
+
+/* Constant values */
+#define FS_C0 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 0)
+#define FS_C1 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 1)
+#define FS_C2 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 2)
+#define FS_C3 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 3)
+#define FS_C4 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 4)
+#define FS_C5 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 5)
+#define FS_C6 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 6)
+#define FS_C7 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 7)
+
+/* Sampler regs */
+#define FS_S0 ((REG_TYPE_S << REG_TYPE_SHIFT) | 0)
+#define FS_S1 ((REG_TYPE_S << REG_TYPE_SHIFT) | 1)
+#define FS_S2 ((REG_TYPE_S << REG_TYPE_SHIFT) | 2)
+#define FS_S3 ((REG_TYPE_S << REG_TYPE_SHIFT) | 3)
+
+/* Output color */
+#define FS_OC ((REG_TYPE_OC << REG_TYPE_SHIFT) | 0)
+
+/* Output depth */
+#define FS_OD ((REG_TYPE_OD << REG_TYPE_SHIFT) | 0)
+
+/* Unpreserved temporary regs */
+#define FS_U0 ((REG_TYPE_U << REG_TYPE_SHIFT) | 0)
+#define FS_U1 ((REG_TYPE_U << REG_TYPE_SHIFT) | 1)
+#define FS_U2 ((REG_TYPE_U << REG_TYPE_SHIFT) | 2)
+#define FS_U3 ((REG_TYPE_U << REG_TYPE_SHIFT) | 3)
+
+#define X_CHANNEL_SHIFT (REG_TYPE_SHIFT + 3)
+#define Y_CHANNEL_SHIFT (X_CHANNEL_SHIFT + 4)
+#define Z_CHANNEL_SHIFT (Y_CHANNEL_SHIFT + 4)
+#define W_CHANNEL_SHIFT (Z_CHANNEL_SHIFT + 4)
+
+#define REG_CHANNEL_MASK 0xf
+
+#define REG_NR(reg) ((reg) & REG_NR_MASK)
+#define REG_TYPE(reg) (((reg) >> REG_TYPE_SHIFT) & REG_TYPE_MASK)
+#define REG_X(reg) (((reg) >> X_CHANNEL_SHIFT) & REG_CHANNEL_MASK)
+#define REG_Y(reg) (((reg) >> Y_CHANNEL_SHIFT) & REG_CHANNEL_MASK)
+#define REG_Z(reg) (((reg) >> Z_CHANNEL_SHIFT) & REG_CHANNEL_MASK)
+#define REG_W(reg) (((reg) >> W_CHANNEL_SHIFT) & REG_CHANNEL_MASK)
+
+enum i915_fs_channel {
+ X_CHANNEL_VAL = 0,
+ Y_CHANNEL_VAL,
+ Z_CHANNEL_VAL,
+ W_CHANNEL_VAL,
+ ZERO_CHANNEL_VAL,
+ ONE_CHANNEL_VAL,
+
+ NEG_X_CHANNEL_VAL = X_CHANNEL_VAL | 0x8,
+ NEG_Y_CHANNEL_VAL = Y_CHANNEL_VAL | 0x8,
+ NEG_Z_CHANNEL_VAL = Z_CHANNEL_VAL | 0x8,
+ NEG_W_CHANNEL_VAL = W_CHANNEL_VAL | 0x8,
+ NEG_ONE_CHANNEL_VAL = ONE_CHANNEL_VAL | 0x8
+};
+
+#define i915_fs_operand(reg, x, y, z, w) \
+ (reg) | \
+(x##_CHANNEL_VAL << X_CHANNEL_SHIFT) | \
+(y##_CHANNEL_VAL << Y_CHANNEL_SHIFT) | \
+(z##_CHANNEL_VAL << Z_CHANNEL_SHIFT) | \
+(w##_CHANNEL_VAL << W_CHANNEL_SHIFT)
+
+/**
+ * Construct an operand description for using a register with no swizzling
+ */
+#define i915_fs_operand_reg(reg) \
+ i915_fs_operand(reg, X, Y, Z, W)
+
+#define i915_fs_operand_reg_negate(reg) \
+ i915_fs_operand(reg, NEG_X, NEG_Y, NEG_Z, NEG_W)
+
+/**
+ * Returns an operand containing (0.0, 0.0, 0.0, 0.0).
+ */
+#define i915_fs_operand_zero() i915_fs_operand(FS_R0, ZERO, ZERO, ZERO, ZERO)
+
+/**
+ * Returns an unused operand
+ */
+#define i915_fs_operand_none() i915_fs_operand_zero()
+
+/**
+ * Returns an operand containing (1.0, 1.0, 1.0, 1.0).
+ */
+#define i915_fs_operand_one() i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE)
+
+#define i915_get_hardware_channel_val(val, shift, negate) \
+ (((val & 0x7) << shift) | ((val & 0x8) ? negate : 0))
+
+/**
+ * Outputs a fragment shader command to declare a sampler or texture register.
+ */
+#define i915_fs_dcl(reg) \
+ do { \
+ OUT_BATCH(D0_DCL | \
+ (REG_TYPE(reg) << D0_TYPE_SHIFT) | \
+ (REG_NR(reg) << D0_NR_SHIFT) | \
+ ((REG_TYPE(reg) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0)); \
+ OUT_BATCH(0); \
+ OUT_BATCH(0); \
+ } while (0)
+
+#define i915_fs_texld(dest_reg, sampler_reg, address_reg) \
+ do { \
+ OUT_BATCH(T0_TEXLD | \
+ (REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT) | \
+ (REG_NR(dest_reg) << T0_DEST_NR_SHIFT) | \
+ (REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT)); \
+ OUT_BATCH((REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT) | \
+ (REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT)); \
+ OUT_BATCH(0); \
+ } while (0)
+
+#define i915_fs_texldp(dest_reg, sampler_reg, address_reg) \
+ do { \
+ OUT_BATCH(T0_TEXLDP | \
+ (REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT) | \
+ (REG_NR(dest_reg) << T0_DEST_NR_SHIFT) | \
+ (REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT)); \
+ OUT_BATCH((REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT) | \
+ (REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT)); \
+ OUT_BATCH(0); \
+ } while (0)
+
+#define i915_fs_arith_masked(op, dest_reg, dest_mask, operand0, operand1, operand2) \
+ _i915_fs_arith_masked(A0_##op, dest_reg, dest_mask, operand0, operand1, operand2)
+
+#define i915_fs_arith(op, dest_reg, operand0, operand1, operand2) \
+ _i915_fs_arith(A0_##op, dest_reg, operand0, operand1, operand2)
+
+#define _i915_fs_arith_masked(cmd, dest_reg, dest_mask, operand0, operand1, operand2) \
+ do { \
+ /* Set up destination register and write mask */ \
+ OUT_BATCH(cmd | \
+ (REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT) | \
+ (REG_NR(dest_reg) << A0_DEST_NR_SHIFT) | \
+ (((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT) | \
+ (((dest_mask) & MASK_SATURATE) ? A0_DEST_SATURATE : 0) | \
+ /* Set up operand 0 */ \
+ (REG_TYPE(operand0) << A0_SRC0_TYPE_SHIFT) | \
+ (REG_NR(operand0) << A0_SRC0_NR_SHIFT)); \
+ OUT_BATCH(i915_get_hardware_channel_val(REG_X(operand0), \
+ A1_SRC0_CHANNEL_X_SHIFT, \
+ A1_SRC0_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand0), \
+ A1_SRC0_CHANNEL_Y_SHIFT, \
+ A1_SRC0_CHANNEL_Y_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Z(operand0), \
+ A1_SRC0_CHANNEL_Z_SHIFT, \
+ A1_SRC0_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand0), \
+ A1_SRC0_CHANNEL_W_SHIFT, \
+ A1_SRC0_CHANNEL_W_NEGATE) | \
+ /* Set up operand 1 */ \
+ (REG_TYPE(operand1) << A1_SRC1_TYPE_SHIFT) | \
+ (REG_NR(operand1) << A1_SRC1_NR_SHIFT) | \
+ i915_get_hardware_channel_val(REG_X(operand1), \
+ A1_SRC1_CHANNEL_X_SHIFT, \
+ A1_SRC1_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand1), \
+ A1_SRC1_CHANNEL_Y_SHIFT, \
+ A1_SRC1_CHANNEL_Y_NEGATE)); \
+ OUT_BATCH(i915_get_hardware_channel_val(REG_Z(operand1), \
+ A2_SRC1_CHANNEL_Z_SHIFT, \
+ A2_SRC1_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand1), \
+ A2_SRC1_CHANNEL_W_SHIFT, \
+ A2_SRC1_CHANNEL_W_NEGATE) | \
+ /* Set up operand 2 */ \
+ (REG_TYPE(operand2) << A2_SRC2_TYPE_SHIFT) | \
+ (REG_NR(operand2) << A2_SRC2_NR_SHIFT) | \
+ i915_get_hardware_channel_val(REG_X(operand2), \
+ A2_SRC2_CHANNEL_X_SHIFT, \
+ A2_SRC2_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand2), \
+ A2_SRC2_CHANNEL_Y_SHIFT, \
+ A2_SRC2_CHANNEL_Y_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Z(operand2), \
+ A2_SRC2_CHANNEL_Z_SHIFT, \
+ A2_SRC2_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand2), \
+ A2_SRC2_CHANNEL_W_SHIFT, \
+ A2_SRC2_CHANNEL_W_NEGATE)); \
+ } while (0)
+
+#define _i915_fs_arith(cmd, dest_reg, operand0, operand1, operand2) do {\
+ /* Set up destination register and write mask */ \
+ OUT_BATCH(cmd | \
+ (REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT) | \
+ (REG_NR(dest_reg) << A0_DEST_NR_SHIFT) | \
+ (A0_DEST_CHANNEL_ALL) | \
+ /* Set up operand 0 */ \
+ (REG_TYPE(operand0) << A0_SRC0_TYPE_SHIFT) | \
+ (REG_NR(operand0) << A0_SRC0_NR_SHIFT)); \
+ OUT_BATCH(i915_get_hardware_channel_val(REG_X(operand0), \
+ A1_SRC0_CHANNEL_X_SHIFT, \
+ A1_SRC0_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand0), \
+ A1_SRC0_CHANNEL_Y_SHIFT, \
+ A1_SRC0_CHANNEL_Y_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Z(operand0), \
+ A1_SRC0_CHANNEL_Z_SHIFT, \
+ A1_SRC0_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand0), \
+ A1_SRC0_CHANNEL_W_SHIFT, \
+ A1_SRC0_CHANNEL_W_NEGATE) | \
+ /* Set up operand 1 */ \
+ (REG_TYPE(operand1) << A1_SRC1_TYPE_SHIFT) | \
+ (REG_NR(operand1) << A1_SRC1_NR_SHIFT) | \
+ i915_get_hardware_channel_val(REG_X(operand1), \
+ A1_SRC1_CHANNEL_X_SHIFT, \
+ A1_SRC1_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand1), \
+ A1_SRC1_CHANNEL_Y_SHIFT, \
+ A1_SRC1_CHANNEL_Y_NEGATE)); \
+ OUT_BATCH(i915_get_hardware_channel_val(REG_Z(operand1), \
+ A2_SRC1_CHANNEL_Z_SHIFT, \
+ A2_SRC1_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand1), \
+ A2_SRC1_CHANNEL_W_SHIFT, \
+ A2_SRC1_CHANNEL_W_NEGATE) | \
+ /* Set up operand 2 */ \
+ (REG_TYPE(operand2) << A2_SRC2_TYPE_SHIFT) | \
+ (REG_NR(operand2) << A2_SRC2_NR_SHIFT) | \
+ i915_get_hardware_channel_val(REG_X(operand2), \
+ A2_SRC2_CHANNEL_X_SHIFT, \
+ A2_SRC2_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand2), \
+ A2_SRC2_CHANNEL_Y_SHIFT, \
+ A2_SRC2_CHANNEL_Y_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Z(operand2), \
+ A2_SRC2_CHANNEL_Z_SHIFT, \
+ A2_SRC2_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand2), \
+ A2_SRC2_CHANNEL_W_SHIFT, \
+ A2_SRC2_CHANNEL_W_NEGATE)); \
+} while (0)
+
+#define i915_fs_mov(dest_reg, operand0) \
+ i915_fs_arith(MOV, dest_reg, \
+ operand0, \
+ i915_fs_operand_none(), \
+ i915_fs_operand_none())
+
+#define i915_fs_mov_masked(dest_reg, dest_mask, operand0) \
+ i915_fs_arith_masked (MOV, dest_reg, dest_mask, \
+ operand0, \
+ i915_fs_operand_none(), \
+ i915_fs_operand_none())
+
+
+#define i915_fs_frc(dest_reg, operand0) \
+ i915_fs_arith (FRC, dest_reg, \
+ operand0, \
+ i915_fs_operand_none(), \
+ i915_fs_operand_none())
+
+/** Add operand0 and operand1 and put the result in dest_reg */
+#define i915_fs_add(dest_reg, operand0, operand1) \
+ i915_fs_arith (ADD, dest_reg, \
+ operand0, operand1, \
+ i915_fs_operand_none())
+
+/** Multiply operand0 and operand1 and put the result in dest_reg */
+#define i915_fs_mul(dest_reg, operand0, operand1) \
+ i915_fs_arith (MUL, dest_reg, \
+ operand0, operand1, \
+ i915_fs_operand_none())
+
+/** Computes 1/sqrt(operand0.replicate_swizzle) puts the result in dest_reg */
+#define i915_fs_rsq(dest_reg, dest_mask, operand0) \
+ do { \
+ if (dest_mask) { \
+ i915_fs_arith_masked (RSQ, dest_reg, dest_mask, \
+ operand0, \
+ i915_fs_operand_none (), \
+ i915_fs_operand_none ()); \
+ } else { \
+ i915_fs_arith (RSQ, dest_reg, \
+ operand0, \
+ i915_fs_operand_none (), \
+ i915_fs_operand_none ()); \
+ } \
+ } while (0)
+
+/** Puts the minimum of operand0 and operand1 in dest_reg */
+#define i915_fs_min(dest_reg, operand0, operand1) \
+ i915_fs_arith (MIN, dest_reg, \
+ operand0, operand1, \
+ i915_fs_operand_none())
+
+/** Puts the maximum of operand0 and operand1 in dest_reg */
+#define i915_fs_max(dest_reg, operand0, operand1) \
+ i915_fs_arith (MAX, dest_reg, \
+ operand0, operand1, \
+ i915_fs_operand_none())
+
+#define i915_fs_cmp(dest_reg, operand0, operand1, operand2) \
+ i915_fs_arith (CMP, dest_reg, operand0, operand1, operand2)
+
+/** Perform operand0 * operand1 + operand2 and put the result in dest_reg */
+#define i915_fs_mad(dest_reg, dest_mask, op0, op1, op2) \
+ do { \
+ if (dest_mask) { \
+ i915_fs_arith_masked (MAD, dest_reg, dest_mask, op0, op1, op2); \
+ } else { \
+ i915_fs_arith (MAD, dest_reg, op0, op1, op2); \
+ } \
+ } while (0)
+
+#define i915_fs_dp2add(dest_reg, dest_mask, op0, op1, op2) \
+ do { \
+ if (dest_mask) { \
+ i915_fs_arith_masked (DP2ADD, dest_reg, dest_mask, op0, op1, op2); \
+ } else { \
+ i915_fs_arith (DP2ADD, dest_reg, op0, op1, op2); \
+ } \
+ } while (0)
+
+/**
+ * Perform a 3-component dot-product of operand0 and operand1 and put the
+ * resulting scalar in the channels of dest_reg specified by the dest_mask.
+ */
+#define i915_fs_dp3(dest_reg, dest_mask, op0, op1) \
+ do { \
+ if (dest_mask) { \
+ i915_fs_arith_masked (DP3, dest_reg, dest_mask, \
+ op0, op1,\
+ i915_fs_operand_none()); \
+ } else { \
+ i915_fs_arith (DP3, dest_reg, op0, op1,\
+ i915_fs_operand_none()); \
+ } \
+ } while (0)
+
+/**
+ * Sets up local state for accumulating a fragment shader buffer.
+ *
+ * \param x maximum number of shader commands that may be used between
+ * a FS_START and FS_END
+ */
+#define FS_LOCALS() \
+ uint32_t _shader_offset
+
+#define FS_BEGIN() \
+ do { \
+ _shader_offset = intel->batch_used++; \
+ } while (0)
+
+#define FS_END() \
+ do { \
+ intel->batch_ptr[_shader_offset] = \
+ _3DSTATE_PIXEL_SHADER_PROGRAM | \
+ (intel->batch_used - _shader_offset - 2); \
+ } while (0);
diff --git a/lib/i915_reg.h b/lib/i915_reg.h
new file mode 100644
index 00000000..746a4131
--- /dev/null
+++ b/lib/i915_reg.h
@@ -0,0 +1,844 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _I915_REG_H_
+#define _I915_REG_H_
+
+#define I915_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
+
+#define CMD_3D (0x3<<29)
+
+#define PRIM3D (CMD_3D | (0x1f<<24))
+#define PRIM3D_INDIRECT_SEQUENTIAL ((1<<23) | (0<<17))
+#define PRIM3D_TRILIST (PRIM3D | (0x0<<18))
+#define PRIM3D_TRISTRIP (PRIM3D | (0x1<<18))
+#define PRIM3D_TRISTRIP_RVRSE (PRIM3D | (0x2<<18))
+#define PRIM3D_TRIFAN (PRIM3D | (0x3<<18))
+#define PRIM3D_POLY (PRIM3D | (0x4<<18))
+#define PRIM3D_LINELIST (PRIM3D | (0x5<<18))
+#define PRIM3D_LINESTRIP (PRIM3D | (0x6<<18))
+#define PRIM3D_RECTLIST (PRIM3D | (0x7<<18))
+#define PRIM3D_POINTLIST (PRIM3D | (0x8<<18))
+#define PRIM3D_DIB (PRIM3D | (0x9<<18))
+#define PRIM3D_CLEAR_RECT (PRIM3D | (0xa<<18))
+#define PRIM3D_ZONE_INIT (PRIM3D | (0xd<<18))
+#define PRIM3D_MASK (0x1f<<18)
+
+/* p137 */
+#define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24))
+#define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16)
+#define AA_LINE_ECAAR_WIDTH_0_5 0
+#define AA_LINE_ECAAR_WIDTH_1_0 (1<<14)
+#define AA_LINE_ECAAR_WIDTH_2_0 (2<<14)
+#define AA_LINE_ECAAR_WIDTH_4_0 (3<<14)
+#define AA_LINE_REGION_WIDTH_ENABLE (1<<8)
+#define AA_LINE_REGION_WIDTH_0_5 0
+#define AA_LINE_REGION_WIDTH_1_0 (1<<6)
+#define AA_LINE_REGION_WIDTH_2_0 (2<<6)
+#define AA_LINE_REGION_WIDTH_4_0 (3<<6)
+
+/* 3DSTATE_BACKFACE_STENCIL_OPS, p138*/
+#define _3DSTATE_BACKFACE_STENCIL_OPS (CMD_3D | (0x8<<24))
+#define BFO_ENABLE_STENCIL_REF (1<<23)
+#define BFO_STENCIL_REF_SHIFT 15
+#define BFO_STENCIL_REF_MASK (0xff<<15)
+#define BFO_ENABLE_STENCIL_FUNCS (1<<14)
+#define BFO_STENCIL_TEST_SHIFT 11
+#define BFO_STENCIL_TEST_MASK (0x7<<11)
+#define BFO_STENCIL_FAIL_SHIFT 8
+#define BFO_STENCIL_FAIL_MASK (0x7<<8)
+#define BFO_STENCIL_PASS_Z_FAIL_SHIFT 5
+#define BFO_STENCIL_PASS_Z_FAIL_MASK (0x7<<5)
+#define BFO_STENCIL_PASS_Z_PASS_SHIFT 2
+#define BFO_STENCIL_PASS_Z_PASS_MASK (0x7<<2)
+#define BFO_ENABLE_STENCIL_TWO_SIDE (1<<1)
+#define BFO_STENCIL_TWO_SIDE (1<<0)
+
+/* 3DSTATE_BACKFACE_STENCIL_MASKS, p140 */
+#define _3DSTATE_BACKFACE_STENCIL_MASKS (CMD_3D | (0x9<<24))
+#define BFM_ENABLE_STENCIL_TEST_MASK (1<<17)
+#define BFM_ENABLE_STENCIL_WRITE_MASK (1<<16)
+#define BFM_STENCIL_TEST_MASK_SHIFT 8
+#define BFM_STENCIL_TEST_MASK_MASK (0xff<<8)
+#define BFM_STENCIL_WRITE_MASK_SHIFT 0
+#define BFM_STENCIL_WRITE_MASK_MASK (0xff<<0)
+
+/* 3DSTATE_BIN_CONTROL p141 */
+
+/* p143 */
+#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
+/* Dword 1 */
+#define BUF_3D_ID_COLOR_BACK (0x3<<24)
+#define BUF_3D_ID_DEPTH (0x7<<24)
+#define BUF_3D_USE_FENCE (1<<23)
+#define BUF_3D_TILED_SURFACE (1<<22)
+#define BUF_3D_TILE_WALK_X 0
+#define BUF_3D_TILE_WALK_Y (1<<21)
+#define BUF_3D_PITCH(x) (((x)/4)<<2)
+/* Dword 2 */
+#define BUF_3D_ADDR(x) ((x) & ~0x3)
+
+/* 3DSTATE_CHROMA_KEY */
+
+/* 3DSTATE_CLEAR_PARAMETERS, p150 */
+#define _3DSTATE_CLEAR_PARAMETERS (CMD_3D | (0x1d<<24) | (0x9c<<16) | 5)
+/* Dword 1 */
+#define CLEARPARAM_CLEAR_RECT (1 << 16)
+#define CLEARPARAM_ZONE_INIT (0 << 16)
+#define CLEARPARAM_WRITE_COLOR (1 << 2)
+#define CLEARPARAM_WRITE_DEPTH (1 << 1)
+#define CLEARPARAM_WRITE_STENCIL (1 << 0)
+
+/* 3DSTATE_CONSTANT_BLEND_COLOR, p153 */
+#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16))
+
+/* 3DSTATE_COORD_SET_BINDINGS, p154 */
+#define _3DSTATE_COORD_SET_BINDINGS (CMD_3D | (0x16<<24))
+#define CSB_TCB(iunit, eunit) ((eunit)<<(iunit*3))
+
+/* p156 */
+#define _3DSTATE_DFLT_DIFFUSE_CMD (CMD_3D | (0x1d<<24) | (0x99<<16))
+
+/* p157 */
+#define _3DSTATE_DFLT_SPEC_CMD (CMD_3D | (0x1d<<24) | (0x9a<<16))
+
+/* p158 */
+#define _3DSTATE_DFLT_Z_CMD (CMD_3D | (0x1d<<24) | (0x98<<16))
+
+/* 3DSTATE_DEPTH_OFFSET_SCALE, p159 */
+#define _3DSTATE_DEPTH_OFFSET_SCALE (CMD_3D | (0x1d<<24) | (0x97<<16))
+/* scale in dword 1 */
+
+/* The depth subrectangle is not supported, but must be disabled. */
+/* 3DSTATE_DEPTH_SUBRECT_DISABLE, p160 */
+#define _3DSTATE_DEPTH_SUBRECT_DISABLE (CMD_3D | (0x1c<<24) | (0x11<<19) | (1 << 1) | (0 << 0))
+
+/* p161 */
+#define _3DSTATE_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16))
+/* Dword 1 */
+#define TEX_DEFAULT_COLOR_OGL (0<<30)
+#define TEX_DEFAULT_COLOR_D3D (1<<30)
+#define ZR_EARLY_DEPTH (1<<29)
+#define LOD_PRECLAMP_OGL (1<<28)
+#define LOD_PRECLAMP_D3D (0<<28)
+#define DITHER_FULL_ALWAYS (0<<26)
+#define DITHER_FULL_ON_FB_BLEND (1<<26)
+#define DITHER_CLAMPED_ALWAYS (2<<26)
+#define LINEAR_GAMMA_BLEND_32BPP (1<<25)
+#define DEBUG_DISABLE_ENH_DITHER (1<<24)
+#define DSTORG_HORT_BIAS(x) ((x)<<20)
+#define DSTORG_VERT_BIAS(x) ((x)<<16)
+#define COLOR_4_2_2_CHNL_WRT_ALL 0
+#define COLOR_4_2_2_CHNL_WRT_Y (1<<12)
+#define COLOR_4_2_2_CHNL_WRT_CR (2<<12)
+#define COLOR_4_2_2_CHNL_WRT_CB (3<<12)
+#define COLOR_4_2_2_CHNL_WRT_CRCB (4<<12)
+#define COLR_BUF_8BIT 0
+#define COLR_BUF_RGB555 (1<<8)
+#define COLR_BUF_RGB565 (2<<8)
+#define COLR_BUF_ARGB8888 (3<<8)
+#define COLR_BUF_ARGB4444 (8<<8)
+#define COLR_BUF_ARGB1555 (9<<8)
+#define COLR_BUF_ARGB2AAA (0xa<<8)
+#define DEPTH_FRMT_16_FIXED 0
+#define DEPTH_FRMT_16_FLOAT (1<<2)
+#define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2)
+#define VERT_LINE_STRIDE_1 (1<<1)
+#define VERT_LINE_STRIDE_0 (0<<1)
+#define VERT_LINE_STRIDE_OFS_1 1
+#define VERT_LINE_STRIDE_OFS_0 0
+
+/* p166 */
+#define _3DSTATE_DRAW_RECT_CMD (CMD_3D|(0x1d<<24)|(0x80<<16)|3)
+/* Dword 1 */
+#define DRAW_RECT_DIS_DEPTH_OFS (1<<30)
+#define DRAW_DITHER_OFS_X(x) ((x)<<26)
+#define DRAW_DITHER_OFS_Y(x) ((x)<<24)
+/* Dword 2 */
+#define DRAW_YMIN(x) ((x)<<16)
+#define DRAW_XMIN(x) (x)
+/* Dword 3 */
+#define DRAW_YMAX(x) ((x)<<16)
+#define DRAW_XMAX(x) (x)
+/* Dword 4 */
+#define DRAW_YORG(x) ((x)<<16)
+#define DRAW_XORG(x) (x)
+
+/* 3DSTATE_FILTER_COEFFICIENTS_4X4, p170 */
+
+/* 3DSTATE_FILTER_COEFFICIENTS_6X5, p172 */
+
+/* _3DSTATE_FOG_COLOR, p173 */
+#define _3DSTATE_FOG_COLOR_CMD (CMD_3D|(0x15<<24))
+#define FOG_COLOR_RED(x) ((x)<<16)
+#define FOG_COLOR_GREEN(x) ((x)<<8)
+#define FOG_COLOR_BLUE(x) (x)
+
+/* _3DSTATE_FOG_MODE, p174 */
+#define _3DSTATE_FOG_MODE_CMD (CMD_3D|(0x1d<<24)|(0x89<<16)|2)
+/* Dword 1 */
+#define FMC1_FOGFUNC_MODIFY_ENABLE (1<<31)
+#define FMC1_FOGFUNC_VERTEX (0<<28)
+#define FMC1_FOGFUNC_PIXEL_EXP (1<<28)
+#define FMC1_FOGFUNC_PIXEL_EXP2 (2<<28)
+#define FMC1_FOGFUNC_PIXEL_LINEAR (3<<28)
+#define FMC1_FOGFUNC_MASK (3<<28)
+#define FMC1_FOGINDEX_MODIFY_ENABLE (1<<27)
+#define FMC1_FOGINDEX_Z (0<<25)
+#define FMC1_FOGINDEX_W (1<<25)
+#define FMC1_C1_C2_MODIFY_ENABLE (1<<24)
+#define FMC1_DENSITY_MODIFY_ENABLE (1<<23)
+#define FMC1_C1_ONE (1<<13)
+#define FMC1_C1_MASK (0xffff<<4)
+/* Dword 2 */
+#define FMC2_C2_ONE (1<<16)
+/* Dword 3 */
+#define FMC3_D_ONE (1<<16)
+
+/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p177 */
+#define _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24))
+#define IAB_MODIFY_ENABLE (1<<23)
+#define IAB_ENABLE (1<<22)
+#define IAB_MODIFY_FUNC (1<<21)
+#define IAB_FUNC_SHIFT 16
+#define IAB_MODIFY_SRC_FACTOR (1<<11)
+#define IAB_SRC_FACTOR_SHIFT 6
+#define IAB_SRC_FACTOR_MASK (BLENDFACT_MASK<<6)
+#define IAB_MODIFY_DST_FACTOR (1<<5)
+#define IAB_DST_FACTOR_SHIFT 0
+#define IAB_DST_FACTOR_MASK (BLENDFACT_MASK<<0)
+
+#define BLENDFACT_ZERO 0x01
+#define BLENDFACT_ONE 0x02
+#define BLENDFACT_SRC_COLR 0x03
+#define BLENDFACT_INV_SRC_COLR 0x04
+#define BLENDFACT_SRC_ALPHA 0x05
+#define BLENDFACT_INV_SRC_ALPHA 0x06
+#define BLENDFACT_DST_ALPHA 0x07
+#define BLENDFACT_INV_DST_ALPHA 0x08
+#define BLENDFACT_DST_COLR 0x09
+#define BLENDFACT_INV_DST_COLR 0x0a
+#define BLENDFACT_SRC_ALPHA_SATURATE 0x0b
+#define BLENDFACT_CONST_COLOR 0x0c
+#define BLENDFACT_INV_CONST_COLOR 0x0d
+#define BLENDFACT_CONST_ALPHA 0x0e
+#define BLENDFACT_INV_CONST_ALPHA 0x0f
+#define BLENDFACT_MASK 0x0f
+
+#define BLENDFUNC_ADD 0x0
+#define BLENDFUNC_SUBTRACT 0x1
+#define BLENDFUNC_REVERSE_SUBTRACT 0x2
+#define BLENDFUNC_MIN 0x3
+#define BLENDFUNC_MAX 0x4
+#define BLENDFUNC_MASK 0x7
+
+/* 3DSTATE_LOAD_INDIRECT, p180 */
+
+#define _3DSTATE_LOAD_INDIRECT (CMD_3D|(0x1d<<24)|(0x7<<16))
+#define LI0_STATE_STATIC_INDIRECT (0x01<<8)
+#define LI0_STATE_DYNAMIC_INDIRECT (0x02<<8)
+#define LI0_STATE_SAMPLER (0x04<<8)
+#define LI0_STATE_MAP (0x08<<8)
+#define LI0_STATE_PROGRAM (0x10<<8)
+#define LI0_STATE_CONSTANTS (0x20<<8)
+
+#define SIS0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define SIS0_FORCE_LOAD (1<<1)
+#define SIS0_BUFFER_VALID (1<<0)
+#define SIS1_BUFFER_LENGTH(x) ((x)&0xff)
+
+#define DIS0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define DIS0_BUFFER_RESET (1<<1)
+#define DIS0_BUFFER_VALID (1<<0)
+
+#define SSB0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define SSB0_FORCE_LOAD (1<<1)
+#define SSB0_BUFFER_VALID (1<<0)
+#define SSB1_BUFFER_LENGTH(x) ((x)&0xff)
+
+#define MSB0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define MSB0_FORCE_LOAD (1<<1)
+#define MSB0_BUFFER_VALID (1<<0)
+#define MSB1_BUFFER_LENGTH(x) ((x)&0xff)
+
+#define PSP0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define PSP0_FORCE_LOAD (1<<1)
+#define PSP0_BUFFER_VALID (1<<0)
+#define PSP1_BUFFER_LENGTH(x) ((x)&0xff)
+
+#define PSC0_BUFFER_ADDRESS(x) ((x)&~0x3)
+#define PSC0_FORCE_LOAD (1<<1)
+#define PSC0_BUFFER_VALID (1<<0)
+#define PSC1_BUFFER_LENGTH(x) ((x)&0xff)
+
+/* _3DSTATE_RASTERIZATION_RULES */
+#define _3DSTATE_RASTER_RULES_CMD (CMD_3D|(0x07<<24))
+#define ENABLE_POINT_RASTER_RULE (1<<15)
+#define OGL_POINT_RASTER_RULE (1<<13)
+#define ENABLE_TEXKILL_3D_4D (1<<10)
+#define TEXKILL_3D (0<<9)
+#define TEXKILL_4D (1<<9)
+#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8)
+#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5)
+#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6)
+#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3)
+
+/* _3DSTATE_SCISSOR_ENABLE, p256 */
+#define _3DSTATE_SCISSOR_ENABLE_CMD (CMD_3D|(0x1c<<24)|(0x10<<19))
+#define ENABLE_SCISSOR_RECT ((1<<1) | 1)
+#define DISABLE_SCISSOR_RECT (1<<1)
+
+/* _3DSTATE_SCISSOR_RECTANGLE_0, p257 */
+#define _3DSTATE_SCISSOR_RECT_0_CMD (CMD_3D|(0x1d<<24)|(0x81<<16)|1)
+/* Dword 1 */
+#define SCISSOR_RECT_0_YMIN(x) ((x)<<16)
+#define SCISSOR_RECT_0_XMIN(x) (x)
+/* Dword 2 */
+#define SCISSOR_RECT_0_YMAX(x) ((x)<<16)
+#define SCISSOR_RECT_0_XMAX(x) (x)
+
+/* p189 */
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_1 ((0x3<<29)|(0x1d<<24)|(0x04<<16))
+#define I1_LOAD_S(n) (1<<(4+n))
+
+#define S0_VB_OFFSET_MASK 0xffffffc
+#define S0_AUTO_CACHE_INV_DISABLE (1<<0)
+
+#define S1_VERTEX_WIDTH_SHIFT 24
+#define S1_VERTEX_WIDTH_MASK (0x3f<<24)
+#define S1_VERTEX_PITCH_SHIFT 16
+#define S1_VERTEX_PITCH_MASK (0x3f<<16)
+
+#define TEXCOORDFMT_2D 0x0
+#define TEXCOORDFMT_3D 0x1
+#define TEXCOORDFMT_4D 0x2
+#define TEXCOORDFMT_1D 0x3
+#define TEXCOORDFMT_2D_16 0x4
+#define TEXCOORDFMT_4D_16 0x5
+#define TEXCOORDFMT_NOT_PRESENT 0xf
+#define S2_TEXCOORD_FMT0_MASK 0xf
+#define S2_TEXCOORD_FMT1_SHIFT 4
+#define S2_TEXCOORD_FMT(unit, type) ((type)<<(unit*4))
+#define S2_TEXCOORD_NONE (~0)
+
+#define TEXCOORD_WRAP_SHORTEST_TCX 8
+#define TEXCOORD_WRAP_SHORTEST_TCY 4
+#define TEXCOORD_WRAP_SHORTEST_TCZ 2
+#define TEXCOORD_PERSPECTIVE_DISABLE 1
+
+#define S3_WRAP_SHORTEST_TCX(unit) (TEXCOORD_WRAP_SHORTEST_TCX << ((unit) * 4))
+#define S3_WRAP_SHORTEST_TCY(unit) (TEXCOORD_WRAP_SHORTEST_TCY << ((unit) * 4))
+#define S3_WRAP_SHORTEST_TCZ(unit) (TEXCOORD_WRAP_SHORTEST_TCZ << ((unit) * 4))
+#define S3_PERSPECTIVE_DISABLE(unit) (TEXCOORD_PERSPECTIVE_DISABLE << ((unit) * 4))
+
+/* S3 not interesting */
+
+#define S4_POINT_WIDTH_SHIFT 23
+#define S4_POINT_WIDTH_MASK (0x1ff<<23)
+#define S4_LINE_WIDTH_SHIFT 19
+#define S4_LINE_WIDTH_ONE (0x2<<19)
+#define S4_LINE_WIDTH_MASK (0xf<<19)
+#define S4_FLATSHADE_ALPHA (1<<18)
+#define S4_FLATSHADE_FOG (1<<17)
+#define S4_FLATSHADE_SPECULAR (1<<16)
+#define S4_FLATSHADE_COLOR (1<<15)
+#define S4_CULLMODE_BOTH (0<<13)
+#define S4_CULLMODE_NONE (1<<13)
+#define S4_CULLMODE_CW (2<<13)
+#define S4_CULLMODE_CCW (3<<13)
+#define S4_CULLMODE_MASK (3<<13)
+#define S4_VFMT_POINT_WIDTH (1<<12)
+#define S4_VFMT_SPEC_FOG (1<<11)
+#define S4_VFMT_COLOR (1<<10)
+#define S4_VFMT_DEPTH_OFFSET (1<<9)
+#define S4_VFMT_XYZ (1<<6)
+#define S4_VFMT_XYZW (2<<6)
+#define S4_VFMT_XY (3<<6)
+#define S4_VFMT_XYW (4<<6)
+#define S4_VFMT_XYZW_MASK (7<<6)
+#define S4_FORCE_DEFAULT_DIFFUSE (1<<5)
+#define S4_FORCE_DEFAULT_SPECULAR (1<<4)
+#define S4_LOCAL_DEPTH_OFFSET_ENABLE (1<<3)
+#define S4_VFMT_FOG_PARAM (1<<2)
+#define S4_SPRITE_POINT_ENABLE (1<<1)
+#define S4_LINE_ANTIALIAS_ENABLE (1<<0)
+
+#define S4_VFMT_MASK (S4_VFMT_POINT_WIDTH | \
+ S4_VFMT_SPEC_FOG | \
+ S4_VFMT_COLOR | \
+ S4_VFMT_DEPTH_OFFSET | \
+ S4_VFMT_XYZW_MASK | \
+ S4_VFMT_FOG_PARAM)
+
+#define S5_WRITEDISABLE_ALPHA (1<<31)
+#define S5_WRITEDISABLE_RED (1<<30)
+#define S5_WRITEDISABLE_GREEN (1<<29)
+#define S5_WRITEDISABLE_BLUE (1<<28)
+#define S5_WRITEDISABLE_MASK (0xf<<28)
+#define S5_FORCE_DEFAULT_POINT_SIZE (1<<27)
+#define S5_LAST_PIXEL_ENABLE (1<<26)
+#define S5_GLOBAL_DEPTH_OFFSET_ENABLE (1<<25)
+#define S5_FOG_ENABLE (1<<24)
+#define S5_STENCIL_REF_SHIFT 16
+#define S5_STENCIL_REF_MASK (0xff<<16)
+#define S5_STENCIL_TEST_FUNC_SHIFT 13
+#define S5_STENCIL_TEST_FUNC_MASK (0x7<<13)
+#define S5_STENCIL_FAIL_SHIFT 10
+#define S5_STENCIL_FAIL_MASK (0x7<<10)
+#define S5_STENCIL_PASS_Z_FAIL_SHIFT 7
+#define S5_STENCIL_PASS_Z_FAIL_MASK (0x7<<7)
+#define S5_STENCIL_PASS_Z_PASS_SHIFT 4
+#define S5_STENCIL_PASS_Z_PASS_MASK (0x7<<4)
+#define S5_STENCIL_WRITE_ENABLE (1<<3)
+#define S5_STENCIL_TEST_ENABLE (1<<2)
+#define S5_COLOR_DITHER_ENABLE (1<<1)
+#define S5_LOGICOP_ENABLE (1<<0)
+
+#define S6_ALPHA_TEST_ENABLE (1<<31)
+#define S6_ALPHA_TEST_FUNC_SHIFT 28
+#define S6_ALPHA_TEST_FUNC_MASK (0x7<<28)
+#define S6_ALPHA_REF_SHIFT 20
+#define S6_ALPHA_REF_MASK (0xff<<20)
+#define S6_DEPTH_TEST_ENABLE (1<<19)
+#define S6_DEPTH_TEST_FUNC_SHIFT 16
+#define S6_DEPTH_TEST_FUNC_MASK (0x7<<16)
+#define S6_CBUF_BLEND_ENABLE (1<<15)
+#define S6_CBUF_BLEND_FUNC_SHIFT 12
+#define S6_CBUF_BLEND_FUNC_MASK (0x7<<12)
+#define S6_CBUF_SRC_BLEND_FACT_SHIFT 8
+#define S6_CBUF_SRC_BLEND_FACT_MASK (0xf<<8)
+#define S6_CBUF_DST_BLEND_FACT_SHIFT 4
+#define S6_CBUF_DST_BLEND_FACT_MASK (0xf<<4)
+#define S6_DEPTH_WRITE_ENABLE (1<<3)
+#define S6_COLOR_WRITE_ENABLE (1<<2)
+#define S6_TRISTRIP_PV_SHIFT 0
+#define S6_TRISTRIP_PV_MASK (0x3<<0)
+
+#define S7_DEPTH_OFFSET_CONST_MASK ~0
+
+/* 3DSTATE_MAP_DEINTERLACER_PARAMETERS */
+/* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */
+
+/* _3DSTATE_MODES_4, p218 */
+#define _3DSTATE_MODES_4_CMD (CMD_3D|(0x0d<<24))
+#define ENABLE_LOGIC_OP_FUNC (1<<23)
+#define LOGIC_OP_FUNC(x) ((x)<<18)
+#define LOGICOP_MASK (0xf<<18)
+#define LOGICOP_COPY 0xc
+#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
+#define ENABLE_STENCIL_TEST_MASK (1<<17)
+#define STENCIL_TEST_MASK(x) ((x)<<8)
+#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
+#define ENABLE_STENCIL_WRITE_MASK (1<<16)
+#define STENCIL_WRITE_MASK(x) ((x)&0xff)
+
+/* _3DSTATE_MODES_5, p220 */
+#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))
+#define PIPELINE_FLUSH_RENDER_CACHE (1<<18)
+#define PIPELINE_FLUSH_TEXTURE_CACHE (1<<16)
+
+/* p221 */
+#define _3DSTATE_PIXEL_SHADER_CONSTANTS (CMD_3D|(0x1d<<24)|(0x6<<16))
+#define PS1_REG(n) (1<<(n))
+#define PS2_CONST_X(n) (n)
+#define PS3_CONST_Y(n) (n)
+#define PS4_CONST_Z(n) (n)
+#define PS5_CONST_W(n) (n)
+
+/* p222 */
+
+#define I915_MAX_TEX_INDIRECT 4
+#define I915_MAX_TEX_INSN 32
+#define I915_MAX_ALU_INSN 64
+#define I915_MAX_DECL_INSN 27
+#define I915_MAX_TEMPORARY 16
+
+/* Each instruction is 3 dwords long, though most don't require all
+ * this space. Maximum of 123 instructions. Smaller maxes per insn
+ * type.
+ */
+#define _3DSTATE_PIXEL_SHADER_PROGRAM (CMD_3D|(0x1d<<24)|(0x5<<16))
+
+#define REG_TYPE_R 0 /* temporary regs, no need to
+ * dcl, must be written before
+ * read -- Preserved between
+ * phases.
+ */
+#define REG_TYPE_T 1 /* Interpolated values, must be
+ * dcl'ed before use.
+ *
+ * 0..7: texture coord,
+ * 8: diffuse spec,
+ * 9: specular color,
+ * 10: fog parameter in w.
+ */
+#define REG_TYPE_CONST 2 /* Restriction: only one const
+ * can be referenced per
+ * instruction, though it may be
+ * selected for multiple inputs.
+ * Constants not initialized
+ * default to zero.
+ */
+#define REG_TYPE_S 3 /* sampler */
+#define REG_TYPE_OC 4 /* output color (rgba) */
+#define REG_TYPE_OD 5 /* output depth (w), xyz are
+ * temporaries. If not written,
+ * interpolated depth is used?
+ */
+#define REG_TYPE_U 6 /* unpreserved temporaries */
+#define REG_TYPE_MASK 0x7
+#define REG_NR_MASK 0xf
+
+/* REG_TYPE_T:
+ */
+#define T_TEX0 0
+#define T_TEX1 1
+#define T_TEX2 2
+#define T_TEX3 3
+#define T_TEX4 4
+#define T_TEX5 5
+#define T_TEX6 6
+#define T_TEX7 7
+#define T_DIFFUSE 8
+#define T_SPECULAR 9
+#define T_FOG_W 10 /* interpolated fog is in W coord */
+
+/* Arithmetic instructions */
+
+/* .replicate_swizzle == selection and replication of a particular
+ * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww
+ */
+#define A0_NOP (0x0<<24) /* no operation */
+#define A0_ADD (0x1<<24) /* dst = src0 + src1 */
+#define A0_MOV (0x2<<24) /* dst = src0 */
+#define A0_MUL (0x3<<24) /* dst = src0 * src1 */
+#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */
+#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */
+#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */
+#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */
+#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */
+#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */
+#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */
+#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */
+#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */
+#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */
+#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */
+#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */
+#define A0_FLR (0x10<<24) /* dst = floor(src0) */
+#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */
+#define A0_TRC (0x12<<24) /* dst = int(src0) */
+#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */
+#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */
+#define A0_DEST_SATURATE (1<<22)
+#define A0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+#define A0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define A0_DEST_CHANNEL_X (1<<10)
+#define A0_DEST_CHANNEL_Y (2<<10)
+#define A0_DEST_CHANNEL_Z (4<<10)
+#define A0_DEST_CHANNEL_W (8<<10)
+#define A0_DEST_CHANNEL_ALL (0xf<<10)
+#define A0_DEST_CHANNEL_SHIFT 10
+#define A0_SRC0_TYPE_SHIFT 7
+#define A0_SRC0_NR_SHIFT 2
+
+#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y)
+#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z)
+
+#define SRC_X 0
+#define SRC_Y 1
+#define SRC_Z 2
+#define SRC_W 3
+#define SRC_ZERO 4
+#define SRC_ONE 5
+
+#define A1_SRC0_CHANNEL_X_NEGATE (1<<31)
+#define A1_SRC0_CHANNEL_X_SHIFT 28
+#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27)
+#define A1_SRC0_CHANNEL_Y_SHIFT 24
+#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23)
+#define A1_SRC0_CHANNEL_Z_SHIFT 20
+#define A1_SRC0_CHANNEL_W_NEGATE (1<<19)
+#define A1_SRC0_CHANNEL_W_SHIFT 16
+#define A1_SRC1_TYPE_SHIFT 13
+#define A1_SRC1_NR_SHIFT 8
+#define A1_SRC1_CHANNEL_X_NEGATE (1<<7)
+#define A1_SRC1_CHANNEL_X_SHIFT 4
+#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3)
+#define A1_SRC1_CHANNEL_Y_SHIFT 0
+
+#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31)
+#define A2_SRC1_CHANNEL_Z_SHIFT 28
+#define A2_SRC1_CHANNEL_W_NEGATE (1<<27)
+#define A2_SRC1_CHANNEL_W_SHIFT 24
+#define A2_SRC2_TYPE_SHIFT 21
+#define A2_SRC2_NR_SHIFT 16
+#define A2_SRC2_CHANNEL_X_NEGATE (1<<15)
+#define A2_SRC2_CHANNEL_X_SHIFT 12
+#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11)
+#define A2_SRC2_CHANNEL_Y_SHIFT 8
+#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7)
+#define A2_SRC2_CHANNEL_Z_SHIFT 4
+#define A2_SRC2_CHANNEL_W_NEGATE (1<<3)
+#define A2_SRC2_CHANNEL_W_SHIFT 0
+
+/* Texture instructions */
+#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared
+ * sampler and address, and output
+ * filtered texel data to destination
+ * register */
+#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a
+ * perspective divide of the texture
+ * coordinate .xyz values by .w before
+ * sampling. */
+#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the
+ * computed LOD by w. Only S4.6 two's
+ * comp is used. This implies that a
+ * float to fixed conversion is
+ * done. */
+#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling
+ * operation. Simply kills the pixel
+ * if any channel of the address
+ * register is < 0.0. */
+#define T0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+/* Note: U (unpreserved) regs do not retain their values between
+ * phases (cannot be used for feedback)
+ *
+ * Note: oC and OD registers can only be used as the destination of a
+ * texture instruction once per phase (this is an implementation
+ * restriction).
+ */
+#define T0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */
+#define T0_SAMPLER_NR_MASK (0xf<<0)
+
+#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */
+/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */
+#define T1_ADDRESS_REG_NR_SHIFT 17
+#define T2_MBZ 0
+
+/* Declaration instructions */
+#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib)
+ * register or an s (sampler)
+ * register. */
+#define D0_SAMPLE_TYPE_SHIFT 22
+#define D0_SAMPLE_TYPE_2D (0x0<<22)
+#define D0_SAMPLE_TYPE_CUBE (0x1<<22)
+#define D0_SAMPLE_TYPE_VOLUME (0x2<<22)
+#define D0_SAMPLE_TYPE_MASK (0x3<<22)
+
+#define D0_TYPE_SHIFT 19
+/* Allow: T, S */
+#define D0_NR_SHIFT 14
+/* Allow T: 0..10, S: 0..15 */
+#define D0_CHANNEL_X (1<<10)
+#define D0_CHANNEL_Y (2<<10)
+#define D0_CHANNEL_Z (4<<10)
+#define D0_CHANNEL_W (8<<10)
+#define D0_CHANNEL_ALL (0xf<<10)
+#define D0_CHANNEL_NONE (0<<10)
+
+#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y)
+#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z)
+
+/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse
+ * or specular declarations.
+ *
+ * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw)
+ *
+ * Must be zero for S (sampler) dcls
+ */
+#define D1_MBZ 0
+#define D2_MBZ 0
+
+/* p207.
+ * The DWORD count is 3 times the number of bits set in MS1_MAPMASK_MASK
+ */
+#define _3DSTATE_MAP_STATE (CMD_3D|(0x1d<<24)|(0x0<<16))
+
+#define MS1_MAPMASK_SHIFT 0
+#define MS1_MAPMASK_MASK (0x8fff<<0)
+
+#define MS2_UNTRUSTED_SURFACE (1<<31)
+#define MS2_ADDRESS_MASK 0xfffffffc
+#define MS2_VERTICAL_LINE_STRIDE (1<<1)
+#define MS2_VERTICAL_OFFSET (1<<1)
+
+#define MS3_HEIGHT_SHIFT 21
+#define MS3_WIDTH_SHIFT 10
+#define MS3_PALETTE_SELECT (1<<9)
+#define MS3_MAPSURF_FORMAT_SHIFT 7
+#define MS3_MAPSURF_FORMAT_MASK (0x7<<7)
+#define MAPSURF_8BIT (1<<7)
+#define MAPSURF_16BIT (2<<7)
+#define MAPSURF_32BIT (3<<7)
+#define MAPSURF_422 (5<<7)
+#define MAPSURF_COMPRESSED (6<<7)
+#define MAPSURF_4BIT_INDEXED (7<<7)
+#define MS3_MT_FORMAT_MASK (0x7 << 3)
+#define MS3_MT_FORMAT_SHIFT 3
+#define MT_4BIT_IDX_ARGB8888 (7<<3) /* SURFACE_4BIT_INDEXED */
+#define MT_8BIT_I8 (0<<3) /* SURFACE_8BIT */
+#define MT_8BIT_L8 (1<<3)
+#define MT_8BIT_A8 (4<<3)
+#define MT_8BIT_MONO8 (5<<3)
+#define MT_16BIT_RGB565 (0<<3) /* SURFACE_16BIT */
+#define MT_16BIT_ARGB1555 (1<<3)
+#define MT_16BIT_ARGB4444 (2<<3)
+#define MT_16BIT_AY88 (3<<3)
+#define MT_16BIT_88DVDU (5<<3)
+#define MT_16BIT_BUMP_655LDVDU (6<<3)
+#define MT_16BIT_I16 (7<<3)
+#define MT_16BIT_L16 (8<<3)
+#define MT_16BIT_A16 (9<<3)
+#define MT_32BIT_ARGB8888 (0<<3) /* SURFACE_32BIT */
+#define MT_32BIT_ABGR8888 (1<<3)
+#define MT_32BIT_XRGB8888 (2<<3)
+#define MT_32BIT_XBGR8888 (3<<3)
+#define MT_32BIT_QWVU8888 (4<<3)
+#define MT_32BIT_AXVU8888 (5<<3)
+#define MT_32BIT_LXVU8888 (6<<3)
+#define MT_32BIT_XLVU8888 (7<<3)
+#define MT_32BIT_ARGB2101010 (8<<3)
+#define MT_32BIT_ABGR2101010 (9<<3)
+#define MT_32BIT_AWVU2101010 (0xA<<3)
+#define MT_32BIT_GR1616 (0xB<<3)
+#define MT_32BIT_VU1616 (0xC<<3)
+#define MT_32BIT_xI824 (0xD<<3)
+#define MT_32BIT_xA824 (0xE<<3)
+#define MT_32BIT_xL824 (0xF<<3)
+#define MT_422_YCRCB_SWAPY (0<<3) /* SURFACE_422 */
+#define MT_422_YCRCB_NORMAL (1<<3)
+#define MT_422_YCRCB_SWAPUV (2<<3)
+#define MT_422_YCRCB_SWAPUVY (3<<3)
+#define MT_COMPRESS_DXT1 (0<<3) /* SURFACE_COMPRESSED */
+#define MT_COMPRESS_DXT2_3 (1<<3)
+#define MT_COMPRESS_DXT4_5 (2<<3)
+#define MT_COMPRESS_FXT1 (3<<3)
+#define MT_COMPRESS_DXT1_RGB (4<<3)
+#define MS3_USE_FENCE_REGS (1<<2)
+#define MS3_TILED_SURFACE (1<<1)
+#define MS3_TILE_WALK (1<<0)
+
+/* The pitch is the pitch measured in DWORDS, minus 1 */
+#define MS4_PITCH_SHIFT 21
+#define MS4_CUBE_FACE_ENA_NEGX (1<<20)
+#define MS4_CUBE_FACE_ENA_POSX (1<<19)
+#define MS4_CUBE_FACE_ENA_NEGY (1<<18)
+#define MS4_CUBE_FACE_ENA_POSY (1<<17)
+#define MS4_CUBE_FACE_ENA_NEGZ (1<<16)
+#define MS4_CUBE_FACE_ENA_POSZ (1<<15)
+#define MS4_CUBE_FACE_ENA_MASK (0x3f<<15)
+#define MS4_MAX_LOD_SHIFT 9
+#define MS4_MAX_LOD_MASK (0x3f<<9)
+#define MS4_MIP_LAYOUT_LEGACY (0<<8)
+#define MS4_MIP_LAYOUT_BELOW_LPT (0<<8)
+#define MS4_MIP_LAYOUT_RIGHT_LPT (1<<8)
+#define MS4_VOLUME_DEPTH_SHIFT 0
+#define MS4_VOLUME_DEPTH_MASK (0xff<<0)
+
+/* p244.
+ * The DWORD count is 3 times the number of bits set in SS1_MAPMASK_MASK.
+ */
+#define _3DSTATE_SAMPLER_STATE (CMD_3D|(0x1d<<24)|(0x1<<16))
+
+#define SS1_MAPMASK_SHIFT 0
+#define SS1_MAPMASK_MASK (0x8fff<<0)
+
+#define SS2_REVERSE_GAMMA_ENABLE (1<<31)
+#define SS2_PACKED_TO_PLANAR_ENABLE (1<<30)
+#define SS2_COLORSPACE_CONVERSION (1<<29)
+#define SS2_CHROMAKEY_SHIFT 27
+#define SS2_BASE_MIP_LEVEL_SHIFT 22
+#define SS2_BASE_MIP_LEVEL_MASK (0x1f<<22)
+#define SS2_MIP_FILTER_SHIFT 20
+#define SS2_MIP_FILTER_MASK (0x3<<20)
+#define MIPFILTER_NONE 0
+#define MIPFILTER_NEAREST 1
+#define MIPFILTER_LINEAR 3
+#define SS2_MAG_FILTER_SHIFT 17
+#define SS2_MAG_FILTER_MASK (0x7<<17)
+#define FILTER_NEAREST 0
+#define FILTER_LINEAR 1
+#define FILTER_ANISOTROPIC 2
+#define FILTER_4X4_1 3
+#define FILTER_4X4_2 4
+#define FILTER_4X4_FLAT 5
+#define FILTER_6X5_MONO 6 /* XXX - check */
+#define SS2_MIN_FILTER_SHIFT 14
+#define SS2_MIN_FILTER_MASK (0x7<<14)
+#define SS2_LOD_BIAS_SHIFT 5
+#define SS2_LOD_BIAS_ONE (0x10<<5)
+#define SS2_LOD_BIAS_MASK (0x1ff<<5)
+/* Shadow requires:
+ * MT_X8{I,L,A}24 or MT_{I,L,A}16 texture format
+ * FILTER_4X4_x MIN and MAG filters
+ */
+#define SS2_SHADOW_ENABLE (1<<4)
+#define SS2_MAX_ANISO_MASK (1<<3)
+#define SS2_MAX_ANISO_2 (0<<3)
+#define SS2_MAX_ANISO_4 (1<<3)
+#define SS2_SHADOW_FUNC_SHIFT 0
+#define SS2_SHADOW_FUNC_MASK (0x7<<0)
+/* SS2_SHADOW_FUNC values: see COMPAREFUNC_* */
+
+#define SS3_MIN_LOD_SHIFT 24
+#define SS3_MIN_LOD_ONE (0x10<<24)
+#define SS3_MIN_LOD_MASK (0xff<<24)
+#define SS3_KILL_PIXEL_ENABLE (1<<17)
+#define SS3_TCX_ADDR_MODE_SHIFT 12
+#define SS3_TCX_ADDR_MODE_MASK (0x7<<12)
+#define TEXCOORDMODE_WRAP 0
+#define TEXCOORDMODE_MIRROR 1
+#define TEXCOORDMODE_CLAMP_EDGE 2
+#define TEXCOORDMODE_CUBE 3
+#define TEXCOORDMODE_CLAMP_BORDER 4
+#define TEXCOORDMODE_MIRROR_ONCE 5
+#define SS3_TCY_ADDR_MODE_SHIFT 9
+#define SS3_TCY_ADDR_MODE_MASK (0x7<<9)
+#define SS3_TCZ_ADDR_MODE_SHIFT 6
+#define SS3_TCZ_ADDR_MODE_MASK (0x7<<6)
+#define SS3_NORMALIZED_COORDS (1<<5)
+#define SS3_TEXTUREMAP_INDEX_SHIFT 1
+#define SS3_TEXTUREMAP_INDEX_MASK (0xf<<1)
+#define SS3_DEINTERLACER_ENABLE (1<<0)
+
+#define SS4_BORDER_COLOR_MASK (~0)
+
+/* 3DSTATE_SPAN_STIPPLE, p258
+ */
+#define _3DSTATE_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define ST1_ENABLE (1<<16)
+#define ST1_MASK (0xffff)
+
+#define FLUSH_MAP_CACHE (1<<0)
+#define FLUSH_RENDER_CACHE (1<<1)
+
+#endif
diff --git a/lib/instdone.c b/lib/instdone.c
new file mode 100644
index 00000000..4679a9c1
--- /dev/null
+++ b/lib/instdone.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright © 2007,2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <assert.h>
+#include "instdone.h"
+
+#include "intel_chipset.h"
+#include "intel_reg.h"
+
+struct instdone_bit instdone_bits[MAX_INSTDONE_BITS];
+int num_instdone_bits = 0;
+
+static void
+add_instdone_bit(uint32_t reg, uint32_t bit, const char *name)
+{
+ instdone_bits[num_instdone_bits].reg = reg;
+ instdone_bits[num_instdone_bits].bit = bit;
+ instdone_bits[num_instdone_bits].name = name;
+ num_instdone_bits++;
+}
+
+static void
+gen3_instdone_bit(uint32_t bit, const char *name)
+{
+ add_instdone_bit(INST_DONE, bit, name);
+}
+
+static void
+gen4_instdone_bit(uint32_t bit, const char *name)
+{
+ add_instdone_bit(INST_DONE_I965, bit, name);
+}
+
+static void
+gen4_instdone1_bit(uint32_t bit, const char *name)
+{
+ add_instdone_bit(INST_DONE_1, bit, name);
+}
+
+static void
+gen6_instdone1_bit(uint32_t bit, const char *name)
+{
+ add_instdone_bit(GEN6_INSTDONE_1, bit, name);
+}
+
+static void
+gen6_instdone2_bit(uint32_t bit, const char *name)
+{
+ add_instdone_bit(GEN6_INSTDONE_2, bit, name);
+}
+
+static void
+init_g965_instdone1(void)
+{
+ gen4_instdone1_bit(I965_GW_CS_DONE_CR, "GW CS CR");
+ gen4_instdone1_bit(I965_SVSM_CS_DONE_CR, "SVSM CS CR");
+ gen4_instdone1_bit(I965_SVDW_CS_DONE_CR, "SVDW CS CR");
+ gen4_instdone1_bit(I965_SVDR_CS_DONE_CR, "SVDR CS CR");
+ gen4_instdone1_bit(I965_SVRW_CS_DONE_CR, "SVRW CS CR");
+ gen4_instdone1_bit(I965_SVRR_CS_DONE_CR, "SVRR CS CR");
+ gen4_instdone1_bit(I965_SVTW_CS_DONE_CR, "SVTW CS CR");
+ gen4_instdone1_bit(I965_MASM_CS_DONE_CR, "MASM CS CR");
+ gen4_instdone1_bit(I965_MASF_CS_DONE_CR, "MASF CS CR");
+ gen4_instdone1_bit(I965_MAW_CS_DONE_CR, "MAW CS CR");
+ gen4_instdone1_bit(I965_EM1_CS_DONE_CR, "EM1 CS CR");
+ gen4_instdone1_bit(I965_EM0_CS_DONE_CR, "EM0 CS CR");
+ gen4_instdone1_bit(I965_UC1_CS_DONE, "UC1 CS");
+ gen4_instdone1_bit(I965_UC0_CS_DONE, "UC0 CS");
+ gen4_instdone1_bit(I965_URB_CS_DONE, "URB CS");
+ gen4_instdone1_bit(I965_ISC_CS_DONE, "ISC CS");
+ gen4_instdone1_bit(I965_CL_CS_DONE, "CL CS");
+ gen4_instdone1_bit(I965_GS_CS_DONE, "GS CS");
+ gen4_instdone1_bit(I965_VS0_CS_DONE, "VS0 CS");
+ gen4_instdone1_bit(I965_VF_CS_DONE, "VF CS");
+}
+
+static void
+init_g4x_instdone1(void)
+{
+ gen4_instdone1_bit(G4X_BCS_DONE, "BCS");
+ gen4_instdone1_bit(G4X_CS_DONE, "CS");
+ gen4_instdone1_bit(G4X_MASF_DONE, "MASF");
+ gen4_instdone1_bit(G4X_SVDW_DONE, "SVDW");
+ gen4_instdone1_bit(G4X_SVDR_DONE, "SVDR");
+ gen4_instdone1_bit(G4X_SVRW_DONE, "SVRW");
+ gen4_instdone1_bit(G4X_SVRR_DONE, "SVRR");
+ gen4_instdone1_bit(G4X_ISC_DONE, "ISC");
+ gen4_instdone1_bit(G4X_MT_DONE, "MT");
+ gen4_instdone1_bit(G4X_RC_DONE, "RC");
+ gen4_instdone1_bit(G4X_DAP_DONE, "DAP");
+ gen4_instdone1_bit(G4X_MAWB_DONE, "MAWB");
+ gen4_instdone1_bit(G4X_MT_IDLE, "MT idle");
+ //gen4_instdone1_bit(G4X_GBLT_BUSY, "GBLT");
+ gen4_instdone1_bit(G4X_SVSM_DONE, "SVSM");
+ gen4_instdone1_bit(G4X_MASM_DONE, "MASM");
+ gen4_instdone1_bit(G4X_QC_DONE, "QC");
+ gen4_instdone1_bit(G4X_FL_DONE, "FL");
+ gen4_instdone1_bit(G4X_SC_DONE, "SC");
+ gen4_instdone1_bit(G4X_DM_DONE, "DM");
+ gen4_instdone1_bit(G4X_FT_DONE, "FT");
+ gen4_instdone1_bit(G4X_DG_DONE, "DG");
+ gen4_instdone1_bit(G4X_SI_DONE, "SI");
+ gen4_instdone1_bit(G4X_SO_DONE, "SO");
+ gen4_instdone1_bit(G4X_PL_DONE, "PL");
+ gen4_instdone1_bit(G4X_WIZ_DONE, "WIZ");
+ gen4_instdone1_bit(G4X_URB_DONE, "URB");
+ gen4_instdone1_bit(G4X_SF_DONE, "SF");
+ gen4_instdone1_bit(G4X_CL_DONE, "CL");
+ gen4_instdone1_bit(G4X_GS_DONE, "GS");
+ gen4_instdone1_bit(G4X_VS0_DONE, "VS0");
+ gen4_instdone1_bit(G4X_VF_DONE, "VF");
+}
+
+static void
+init_gen7_instdone(void)
+{
+ gen6_instdone1_bit(1 << 19, "GAM");
+ gen6_instdone1_bit(1 << 18, "GAFM");
+ gen6_instdone1_bit(1 << 17, "TSG");
+ gen6_instdone1_bit(1 << 16, "VFE");
+ gen6_instdone1_bit(1 << 15, "GAFS");
+ gen6_instdone1_bit(1 << 14, "SVG");
+ gen6_instdone1_bit(1 << 13, "URBM");
+ gen6_instdone1_bit(1 << 12, "TDG");
+ gen6_instdone1_bit(1 << 9, "SF");
+ gen6_instdone1_bit(1 << 8, "CL");
+ gen6_instdone1_bit(1 << 7, "SOL");
+ gen6_instdone1_bit(1 << 6, "GS");
+ gen6_instdone1_bit(1 << 5, "DS");
+ gen6_instdone1_bit(1 << 4, "TE");
+ gen6_instdone1_bit(1 << 3, "HS");
+ gen6_instdone1_bit(1 << 2, "VS");
+ gen6_instdone1_bit(1 << 1, "VF");
+}
+
+void
+init_instdone_definitions(uint32_t devid)
+{
+ if (IS_GEN7(devid)) {
+ init_gen7_instdone();
+ } else if (IS_GEN6(devid)) {
+ /* Now called INSTDONE_1 in the docs. */
+ gen6_instdone1_bit(GEN6_MA_3_DONE, "Message Arbiter 3");
+ gen6_instdone1_bit(GEN6_EU_32_DONE, "EU 32");
+ gen6_instdone1_bit(GEN6_EU_31_DONE, "EU 31");
+ gen6_instdone1_bit(GEN6_EU_30_DONE, "EU 30");
+ gen6_instdone1_bit(GEN6_MA_3_DONE, "Message Arbiter 2");
+ gen6_instdone1_bit(GEN6_EU_22_DONE, "EU 22");
+ gen6_instdone1_bit(GEN6_EU_21_DONE, "EU 21");
+ gen6_instdone1_bit(GEN6_EU_20_DONE, "EU 20");
+ gen6_instdone1_bit(GEN6_MA_3_DONE, "Message Arbiter 1");
+ gen6_instdone1_bit(GEN6_EU_12_DONE, "EU 12");
+ gen6_instdone1_bit(GEN6_EU_11_DONE, "EU 11");
+ gen6_instdone1_bit(GEN6_EU_10_DONE, "EU 10");
+ gen6_instdone1_bit(GEN6_MA_3_DONE, "Message Arbiter 0");
+ gen6_instdone1_bit(GEN6_EU_02_DONE, "EU 02");
+ gen6_instdone1_bit(GEN6_EU_01_DONE, "EU 01");
+ gen6_instdone1_bit(GEN6_EU_00_DONE, "EU 00");
+
+ gen6_instdone1_bit(GEN6_IC_3_DONE, "IC 3");
+ gen6_instdone1_bit(GEN6_IC_2_DONE, "IC 2");
+ gen6_instdone1_bit(GEN6_IC_1_DONE, "IC 1");
+ gen6_instdone1_bit(GEN6_IC_0_DONE, "IC 0");
+ gen6_instdone1_bit(GEN6_ISC_10_DONE, "ISC 1/0");
+ gen6_instdone1_bit(GEN6_ISC_32_DONE, "ISC 3/2");
+
+ gen6_instdone1_bit(GEN6_VSC_DONE, "VSC");
+ gen6_instdone1_bit(GEN6_IEF_DONE, "IEF");
+ gen6_instdone1_bit(GEN6_VFE_DONE, "VFE");
+ gen6_instdone1_bit(GEN6_TD_DONE, "TD");
+ gen6_instdone1_bit(GEN6_TS_DONE, "TS");
+ gen6_instdone1_bit(GEN6_GW_DONE, "GW");
+ gen6_instdone1_bit(GEN6_HIZ_DONE, "HIZ");
+ gen6_instdone1_bit(GEN6_AVS_DONE, "AVS");
+
+ /* Now called INSTDONE_2 in the docs. */
+ gen6_instdone2_bit(GEN6_GAM_DONE, "GAM");
+ gen6_instdone2_bit(GEN6_CS_DONE, "CS");
+ gen6_instdone2_bit(GEN6_WMBE_DONE, "WMBE");
+ gen6_instdone2_bit(GEN6_SVRW_DONE, "SVRW");
+ gen6_instdone2_bit(GEN6_RCC_DONE, "RCC");
+ gen6_instdone2_bit(GEN6_SVG_DONE, "SVG");
+ gen6_instdone2_bit(GEN6_ISC_DONE, "ISC");
+ gen6_instdone2_bit(GEN6_MT_DONE, "MT");
+ gen6_instdone2_bit(GEN6_RCPFE_DONE, "RCPFE");
+ gen6_instdone2_bit(GEN6_RCPBE_DONE, "RCPBE");
+ gen6_instdone2_bit(GEN6_VDI_DONE, "VDI");
+ gen6_instdone2_bit(GEN6_RCZ_DONE, "RCZ");
+ gen6_instdone2_bit(GEN6_DAP_DONE, "DAP");
+ gen6_instdone2_bit(GEN6_PSD_DONE, "PSD");
+ gen6_instdone2_bit(GEN6_IZ_DONE, "IZ");
+ gen6_instdone2_bit(GEN6_WMFE_DONE, "WMFE");
+ gen6_instdone2_bit(GEN6_SVSM_DONE, "SVSM");
+ gen6_instdone2_bit(GEN6_QC_DONE, "QC");
+ gen6_instdone2_bit(GEN6_FL_DONE, "FL");
+ gen6_instdone2_bit(GEN6_SC_DONE, "SC");
+ gen6_instdone2_bit(GEN6_DM_DONE, "DM");
+ gen6_instdone2_bit(GEN6_FT_DONE, "FT");
+ gen6_instdone2_bit(GEN6_DG_DONE, "DG");
+ gen6_instdone2_bit(GEN6_SI_DONE, "SI");
+ gen6_instdone2_bit(GEN6_SO_DONE, "SO");
+ gen6_instdone2_bit(GEN6_PL_DONE, "PL");
+ gen6_instdone2_bit(GEN6_VME_DONE, "VME");
+ gen6_instdone2_bit(GEN6_SF_DONE, "SF");
+ gen6_instdone2_bit(GEN6_CL_DONE, "CL");
+ gen6_instdone2_bit(GEN6_GS_DONE, "GS");
+ gen6_instdone2_bit(GEN6_VS0_DONE, "VS0");
+ gen6_instdone2_bit(GEN6_VF_DONE, "VF");
+ } else if (IS_GEN5(devid)) {
+ gen4_instdone_bit(ILK_ROW_0_EU_0_DONE, "Row 0, EU 0");
+ gen4_instdone_bit(ILK_ROW_0_EU_1_DONE, "Row 0, EU 1");
+ gen4_instdone_bit(ILK_ROW_0_EU_2_DONE, "Row 0, EU 2");
+ gen4_instdone_bit(ILK_ROW_0_EU_3_DONE, "Row 0, EU 3");
+ gen4_instdone_bit(ILK_ROW_1_EU_0_DONE, "Row 1, EU 0");
+ gen4_instdone_bit(ILK_ROW_1_EU_1_DONE, "Row 1, EU 1");
+ gen4_instdone_bit(ILK_ROW_1_EU_2_DONE, "Row 1, EU 2");
+ gen4_instdone_bit(ILK_ROW_1_EU_3_DONE, "Row 1, EU 3");
+ gen4_instdone_bit(ILK_ROW_2_EU_0_DONE, "Row 2, EU 0");
+ gen4_instdone_bit(ILK_ROW_2_EU_1_DONE, "Row 2, EU 1");
+ gen4_instdone_bit(ILK_ROW_2_EU_2_DONE, "Row 2, EU 2");
+ gen4_instdone_bit(ILK_ROW_2_EU_3_DONE, "Row 2, EU 3");
+ gen4_instdone_bit(ILK_VCP_DONE, "VCP");
+ gen4_instdone_bit(ILK_ROW_0_MATH_DONE, "Row 0 math");
+ gen4_instdone_bit(ILK_ROW_1_MATH_DONE, "Row 1 math");
+ gen4_instdone_bit(ILK_ROW_2_MATH_DONE, "Row 2 math");
+ gen4_instdone_bit(ILK_VC1_DONE, "VC1");
+ gen4_instdone_bit(ILK_ROW_0_MA_DONE, "Row 0 MA");
+ gen4_instdone_bit(ILK_ROW_1_MA_DONE, "Row 1 MA");
+ gen4_instdone_bit(ILK_ROW_2_MA_DONE, "Row 2 MA");
+ gen4_instdone_bit(ILK_ROW_0_ISC_DONE, "Row 0 ISC");
+ gen4_instdone_bit(ILK_ROW_1_ISC_DONE, "Row 1 ISC");
+ gen4_instdone_bit(ILK_ROW_2_ISC_DONE, "Row 2 ISC");
+ gen4_instdone_bit(ILK_VFE_DONE, "VFE");
+ gen4_instdone_bit(ILK_TD_DONE, "TD");
+ gen4_instdone_bit(ILK_SVTS_DONE, "SVTS");
+ gen4_instdone_bit(ILK_TS_DONE, "TS");
+ gen4_instdone_bit(ILK_GW_DONE, "GW");
+ gen4_instdone_bit(ILK_AI_DONE, "AI");
+ gen4_instdone_bit(ILK_AC_DONE, "AC");
+ gen4_instdone_bit(ILK_AM_DONE, "AM");
+
+ init_g4x_instdone1();
+ } else if (IS_GEN4(devid)) {
+ gen4_instdone_bit(I965_ROW_0_EU_0_DONE, "Row 0, EU 0");
+ gen4_instdone_bit(I965_ROW_0_EU_1_DONE, "Row 0, EU 1");
+ gen4_instdone_bit(I965_ROW_0_EU_2_DONE, "Row 0, EU 2");
+ gen4_instdone_bit(I965_ROW_0_EU_3_DONE, "Row 0, EU 3");
+ gen4_instdone_bit(I965_ROW_1_EU_0_DONE, "Row 1, EU 0");
+ gen4_instdone_bit(I965_ROW_1_EU_1_DONE, "Row 1, EU 1");
+ gen4_instdone_bit(I965_ROW_1_EU_2_DONE, "Row 1, EU 2");
+ gen4_instdone_bit(I965_ROW_1_EU_3_DONE, "Row 1, EU 3");
+ gen4_instdone_bit(I965_SF_DONE, "Strips and Fans");
+ gen4_instdone_bit(I965_SE_DONE, "Setup Engine");
+ gen4_instdone_bit(I965_WM_DONE, "Windowizer");
+ gen4_instdone_bit(I965_DISPATCHER_DONE, "Dispatcher");
+ gen4_instdone_bit(I965_PROJECTION_DONE, "Projection and LOD");
+ gen4_instdone_bit(I965_DG_DONE, "Dependent address generator");
+ gen4_instdone_bit(I965_QUAD_CACHE_DONE, "Texture fetch");
+ gen4_instdone_bit(I965_TEXTURE_FETCH_DONE, "Texture fetch");
+ gen4_instdone_bit(I965_TEXTURE_DECOMPRESS_DONE, "Texture decompress");
+ gen4_instdone_bit(I965_SAMPLER_CACHE_DONE, "Sampler cache");
+ gen4_instdone_bit(I965_FILTER_DONE, "Filtering");
+ gen4_instdone_bit(I965_BYPASS_DONE, "Bypass FIFO");
+ gen4_instdone_bit(I965_PS_DONE, "Pixel shader");
+ gen4_instdone_bit(I965_CC_DONE, "Color calculator");
+ gen4_instdone_bit(I965_MAP_FILTER_DONE, "Map filter");
+ gen4_instdone_bit(I965_MAP_L2_IDLE, "Map L2");
+ gen4_instdone_bit(I965_MA_ROW_0_DONE, "Message Arbiter row 0");
+ gen4_instdone_bit(I965_MA_ROW_1_DONE, "Message Arbiter row 1");
+ gen4_instdone_bit(I965_IC_ROW_0_DONE, "Instruction cache row 0");
+ gen4_instdone_bit(I965_IC_ROW_1_DONE, "Instruction cache row 1");
+ gen4_instdone_bit(I965_CP_DONE, "Command Processor");
+
+ if (IS_G4X(devid)) {
+ init_g4x_instdone1();
+ } else {
+ init_g965_instdone1();
+ }
+ } else if (IS_GEN3(devid)) {
+ gen3_instdone_bit(IDCT_DONE, "IDCT");
+ gen3_instdone_bit(IQ_DONE, "IQ");
+ gen3_instdone_bit(PR_DONE, "PR");
+ gen3_instdone_bit(VLD_DONE, "VLD");
+ gen3_instdone_bit(IP_DONE, "Instruction parser");
+ gen3_instdone_bit(FBC_DONE, "Framebuffer Compression");
+ gen3_instdone_bit(BINNER_DONE, "Binner");
+ gen3_instdone_bit(SF_DONE, "Strips and fans");
+ gen3_instdone_bit(SE_DONE, "Setup engine");
+ gen3_instdone_bit(WM_DONE, "Windowizer");
+ gen3_instdone_bit(IZ_DONE, "Intermediate Z");
+ gen3_instdone_bit(PERSPECTIVE_INTERP_DONE, "Perspective interpolation");
+ gen3_instdone_bit(DISPATCHER_DONE, "Dispatcher");
+ gen3_instdone_bit(PROJECTION_DONE, "Projection and LOD");
+ gen3_instdone_bit(DEPENDENT_ADDRESS_DONE, "Dependent address calculation");
+ gen3_instdone_bit(TEXTURE_FETCH_DONE, "Texture fetch");
+ gen3_instdone_bit(TEXTURE_DECOMPRESS_DONE, "Texture decompression");
+ gen3_instdone_bit(SAMPLER_CACHE_DONE, "Sampler Cache");
+ gen3_instdone_bit(FILTER_DONE, "Filtering");
+ gen3_instdone_bit(BYPASS_FIFO_DONE, "Bypass FIFO");
+ gen3_instdone_bit(PS_DONE, "Pixel shader");
+ gen3_instdone_bit(CC_DONE, "Color calculator");
+ gen3_instdone_bit(MAP_FILTER_DONE, "Map filter");
+ gen3_instdone_bit(MAP_L2_IDLE, "Map L2");
+ } else {
+ assert(IS_GEN2(devid));
+ gen3_instdone_bit(I830_GMBUS_DONE, "GMBUS");
+ gen3_instdone_bit(I830_FBC_DONE, "FBC");
+ gen3_instdone_bit(I830_BINNER_DONE, "BINNER");
+ gen3_instdone_bit(I830_MPEG_DONE, "MPEG");
+ gen3_instdone_bit(I830_MECO_DONE, "MECO");
+ gen3_instdone_bit(I830_MCD_DONE, "MCD");
+ gen3_instdone_bit(I830_MCSTP_DONE, "MCSTP");
+ gen3_instdone_bit(I830_CC_DONE, "CC");
+ gen3_instdone_bit(I830_DG_DONE, "DG");
+ gen3_instdone_bit(I830_DCMP_DONE, "DCMP");
+ gen3_instdone_bit(I830_FTCH_DONE, "FTCH");
+ gen3_instdone_bit(I830_IT_DONE, "IT");
+ gen3_instdone_bit(I830_MG_DONE, "MG");
+ gen3_instdone_bit(I830_MEC_DONE, "MEC");
+ gen3_instdone_bit(I830_PC_DONE, "PC");
+ gen3_instdone_bit(I830_QCC_DONE, "QCC");
+ gen3_instdone_bit(I830_TB_DONE, "TB");
+ gen3_instdone_bit(I830_WM_DONE, "WM");
+ gen3_instdone_bit(I830_EF_DONE, "EF");
+ gen3_instdone_bit(I830_BLITTER_DONE, "Blitter");
+ gen3_instdone_bit(I830_MAP_L2_DONE, "Map L2 cache");
+ gen3_instdone_bit(I830_SECONDARY_RING_3_DONE, "Secondary ring 3");
+ gen3_instdone_bit(I830_SECONDARY_RING_2_DONE, "Secondary ring 2");
+ gen3_instdone_bit(I830_SECONDARY_RING_1_DONE, "Secondary ring 1");
+ gen3_instdone_bit(I830_SECONDARY_RING_0_DONE, "Secondary ring 0");
+ gen3_instdone_bit(I830_PRIMARY_RING_1_DONE, "Primary ring 1");
+ gen3_instdone_bit(I830_PRIMARY_RING_0_DONE, "Primary ring 0");
+ }
+}
diff --git a/lib/instdone.h b/lib/instdone.h
new file mode 100644
index 00000000..c86a54a7
--- /dev/null
+++ b/lib/instdone.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2007,2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdint.h>
+
+#define MAX_INSTDONE_BITS 100
+
+struct instdone_bit {
+ uint32_t reg;
+ uint32_t bit;
+ const char *name;
+};
+
+extern struct instdone_bit instdone_bits[MAX_INSTDONE_BITS];
+extern int num_instdone_bits;
+
+void init_instdone_definitions(uint32_t devid);
diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
new file mode 100644
index 00000000..724e23d9
--- /dev/null
+++ b/lib/intel_batchbuffer.c
@@ -0,0 +1,241 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "drm.h"
+#include "drmtest.h"
+#include "intel_batchbuffer.h"
+#include "intel_bufmgr.h"
+#include "intel_chipset.h"
+#include "intel_reg.h"
+#include <i915_drm.h>
+
+void
+intel_batchbuffer_reset(struct intel_batchbuffer *batch)
+{
+ if (batch->bo != NULL) {
+ drm_intel_bo_unreference(batch->bo);
+ batch->bo = NULL;
+ }
+
+ batch->bo = drm_intel_bo_alloc(batch->bufmgr, "batchbuffer",
+ BATCH_SZ, 4096);
+
+ batch->ptr = batch->buffer;
+}
+
+struct intel_batchbuffer *
+intel_batchbuffer_alloc(drm_intel_bufmgr *bufmgr, uint32_t devid)
+{
+ struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
+
+ batch->bufmgr = bufmgr;
+ batch->devid = devid;
+ intel_batchbuffer_reset(batch);
+
+ return batch;
+}
+
+void
+intel_batchbuffer_free(struct intel_batchbuffer *batch)
+{
+ drm_intel_bo_unreference(batch->bo);
+ batch->bo = NULL;
+ free(batch);
+}
+
+#define CMD_POLY_STIPPLE_OFFSET 0x7906
+
+static unsigned int
+flush_on_ring_common(struct intel_batchbuffer *batch, int ring)
+{
+ unsigned int used = batch->ptr - batch->buffer;
+
+ if (used == 0)
+ return 0;
+
+ if (IS_GEN5(batch->devid)) {
+ /* emit gen5 w/a without batch space checks - we reserve that
+ * already. */
+ *(uint32_t *) (batch->ptr) = CMD_POLY_STIPPLE_OFFSET << 16;
+ *(uint32_t *) (batch->ptr) = 0;
+ batch->ptr += 8;
+ }
+
+ /* Round batchbuffer usage to 2 DWORDs. */
+ if ((used & 4) == 0) {
+ *(uint32_t *) (batch->ptr) = 0; /* noop */
+ batch->ptr += 4;
+ }
+
+ /* Mark the end of the buffer. */
+ *(uint32_t *)(batch->ptr) = MI_BATCH_BUFFER_END; /* noop */
+ batch->ptr += 4;
+ return batch->ptr - batch->buffer;
+}
+
+void
+intel_batchbuffer_flush_on_ring(struct intel_batchbuffer *batch, int ring)
+{
+ unsigned int used = flush_on_ring_common(batch, ring);
+
+ if (used == 0)
+ return;
+
+ do_or_die(drm_intel_bo_subdata(batch->bo, 0, used, batch->buffer));
+
+ batch->ptr = NULL;
+
+ do_or_die(drm_intel_bo_mrb_exec(batch->bo, used, NULL, 0, 0, ring));
+
+ intel_batchbuffer_reset(batch);
+}
+
+void
+intel_batchbuffer_flush_with_context(struct intel_batchbuffer *batch,
+ drm_intel_context *context)
+{
+ int ret;
+ unsigned int used = flush_on_ring_common(batch, I915_EXEC_RENDER);
+
+ if (used == 0)
+ return;
+
+ ret = drm_intel_bo_subdata(batch->bo, 0, used, batch->buffer);
+ assert(ret == 0);
+
+ batch->ptr = NULL;
+
+ ret = drm_intel_gem_bo_context_exec(batch->bo, context, used,
+ I915_EXEC_RENDER);
+ assert(ret == 0);
+
+ intel_batchbuffer_reset(batch);
+}
+
+void
+intel_batchbuffer_flush(struct intel_batchbuffer *batch)
+{
+ int ring = 0;
+ if (HAS_BLT_RING(batch->devid))
+ ring = I915_EXEC_BLT;
+ intel_batchbuffer_flush_on_ring(batch, ring);
+}
+
+
+/* This is the only way buffers get added to the validate list.
+ */
+void
+intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+ drm_intel_bo *buffer, uint32_t delta,
+ uint32_t read_domains, uint32_t write_domain,
+ int fenced)
+{
+ int ret;
+
+ if (batch->ptr - batch->buffer > BATCH_SZ)
+ printf("bad relocation ptr %p map %p offset %d size %d\n",
+ batch->ptr, batch->buffer,
+ (int)(batch->ptr - batch->buffer),
+ BATCH_SZ);
+
+ if (fenced)
+ ret = drm_intel_bo_emit_reloc_fence(batch->bo, batch->ptr - batch->buffer,
+ buffer, delta,
+ read_domains, write_domain);
+ else
+ ret = drm_intel_bo_emit_reloc(batch->bo, batch->ptr - batch->buffer,
+ buffer, delta,
+ read_domains, write_domain);
+ intel_batchbuffer_emit_dword(batch, buffer->offset + delta);
+ assert(ret == 0);
+}
+
+void
+intel_batchbuffer_data(struct intel_batchbuffer *batch,
+ const void *data, unsigned int bytes)
+{
+ assert((bytes & 3) == 0);
+ intel_batchbuffer_require_space(batch, bytes);
+ memcpy(batch->ptr, data, bytes);
+ batch->ptr += bytes;
+}
+
+void
+intel_copy_bo(struct intel_batchbuffer *batch,
+ drm_intel_bo *dst_bo, drm_intel_bo *src_bo,
+ int width, int height)
+{
+ uint32_t src_tiling, dst_tiling, swizzle;
+ uint32_t src_pitch, dst_pitch;
+ uint32_t cmd_bits = 0;
+
+ drm_intel_bo_get_tiling(src_bo, &src_tiling, &swizzle);
+ drm_intel_bo_get_tiling(dst_bo, &dst_tiling, &swizzle);
+
+ src_pitch = width * 4;
+ if (IS_965(batch->devid) && src_tiling != I915_TILING_NONE) {
+ src_pitch /= 4;
+ cmd_bits |= XY_SRC_COPY_BLT_SRC_TILED;
+ }
+
+ dst_pitch = width * 4;
+ if (IS_965(batch->devid) && dst_tiling != I915_TILING_NONE) {
+ dst_pitch /= 4;
+ cmd_bits |= XY_SRC_COPY_BLT_DST_TILED;
+ }
+
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB |
+ cmd_bits);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ dst_pitch);
+ OUT_BATCH(0); /* dst x1,y1 */
+ OUT_BATCH((height << 16) | width); /* dst x2,y2 */
+ OUT_RELOC(dst_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0); /* src x1,y1 */
+ OUT_BATCH(src_pitch);
+ OUT_RELOC(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+}
+
+void
+intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch)
+{
+ intel_batchbuffer_require_space(batch, 4);
+ intel_batchbuffer_emit_dword(batch, MI_FLUSH);
+}
diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
new file mode 100644
index 00000000..ba0934cb
--- /dev/null
+++ b/lib/intel_batchbuffer.h
@@ -0,0 +1,112 @@
+#ifndef INTEL_BATCHBUFFER_H
+#define INTEL_BATCHBUFFER_H
+
+#include <assert.h>
+#include "intel_bufmgr.h"
+
+#define BATCH_SZ 4096
+#define BATCH_RESERVED 16
+
+struct intel_batchbuffer {
+ drm_intel_bufmgr *bufmgr;
+ uint32_t devid;
+
+ drm_intel_bo *bo;
+
+ uint8_t buffer[BATCH_SZ];
+ uint8_t *ptr;
+};
+
+struct intel_batchbuffer *intel_batchbuffer_alloc(drm_intel_bufmgr *bufmgr,
+ uint32_t devid);
+
+void intel_batchbuffer_free(struct intel_batchbuffer *batch);
+
+
+void intel_batchbuffer_flush(struct intel_batchbuffer *batch);
+void intel_batchbuffer_flush_on_ring(struct intel_batchbuffer *batch, int ring);
+void intel_batchbuffer_flush_with_context(struct intel_batchbuffer *batch,
+ drm_intel_context *context);
+
+void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
+
+void intel_batchbuffer_data(struct intel_batchbuffer *batch,
+ const void *data, unsigned int bytes);
+
+void intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+ drm_intel_bo *buffer,
+ uint32_t delta,
+ uint32_t read_domains,
+ uint32_t write_domain,
+ int fenced);
+
+/* Inline functions - might actually be better off with these
+ * non-inlined. Certainly better off switching all command packets to
+ * be passed as structs rather than dwords, but that's a little bit of
+ * work...
+ */
+#pragma GCC diagnostic ignored "-Winline"
+static inline int
+intel_batchbuffer_space(struct intel_batchbuffer *batch)
+{
+ return (BATCH_SZ - BATCH_RESERVED) - (batch->ptr - batch->buffer);
+}
+
+
+static inline void
+intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, uint32_t dword)
+{
+ assert(intel_batchbuffer_space(batch) >= 4);
+ *(uint32_t *) (batch->ptr) = dword;
+ batch->ptr += 4;
+}
+
+static inline void
+intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
+ unsigned int sz)
+{
+ assert(sz < BATCH_SZ - BATCH_RESERVED);
+ if (intel_batchbuffer_space(batch) < sz)
+ intel_batchbuffer_flush(batch);
+}
+
+/* Here are the crusty old macros, to be removed:
+ */
+#define BATCH_LOCALS
+
+#define BEGIN_BATCH(n) do { \
+ intel_batchbuffer_require_space(batch, (n)*4); \
+} while (0)
+
+#define OUT_BATCH(d) intel_batchbuffer_emit_dword(batch, d)
+
+#define OUT_RELOC_FENCED(buf, read_domains, write_domain, delta) do { \
+ assert((delta) >= 0); \
+ intel_batchbuffer_emit_reloc(batch, buf, delta, \
+ read_domains, write_domain, 1); \
+} while (0)
+
+#define OUT_RELOC(buf, read_domains, write_domain, delta) do { \
+ assert((delta) >= 0); \
+ intel_batchbuffer_emit_reloc(batch, buf, delta, \
+ read_domains, write_domain, 0); \
+} while (0)
+
+#define ADVANCE_BATCH() do { \
+} while(0)
+
+void
+intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch);
+
+void intel_copy_bo(struct intel_batchbuffer *batch,
+ drm_intel_bo *dst_bo, drm_intel_bo *src_bo,
+ int width, int height);
+
+#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
+#define i915_execbuffer2_set_context_id(eb2, context) \
+ (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
+#define i915_execbuffer2_get_context_id(eb2) \
+ ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK)
+
+
+#endif
diff --git a/lib/intel_chipset.h b/lib/intel_chipset.h
new file mode 100755
index 00000000..9dd4c94c
--- /dev/null
+++ b/lib/intel_chipset.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#define PCI_CHIP_I810 0x7121
+#define PCI_CHIP_I810_DC100 0x7123
+#define PCI_CHIP_I810_E 0x7125
+#define PCI_CHIP_I815 0x1132
+
+#define PCI_CHIP_I830_M 0x3577
+#define PCI_CHIP_845_G 0x2562
+#define PCI_CHIP_I855_GM 0x3582
+#define PCI_CHIP_I865_G 0x2572
+
+#define PCI_CHIP_I915_G 0x2582
+#define PCI_CHIP_E7221_G 0x258A
+#define PCI_CHIP_I915_GM 0x2592
+#define PCI_CHIP_I945_G 0x2772
+#define PCI_CHIP_I945_GM 0x27A2
+#define PCI_CHIP_I945_GME 0x27AE
+
+#define PCI_CHIP_Q35_G 0x29B2
+#define PCI_CHIP_G33_G 0x29C2
+#define PCI_CHIP_Q33_G 0x29D2
+
+#define PCI_CHIP_IGD_GM 0xA011
+#define PCI_CHIP_IGD_G 0xA001
+
+#define IS_IGDGM(devid) (devid == PCI_CHIP_IGD_GM)
+#define IS_IGDG(devid) (devid == PCI_CHIP_IGD_G)
+#define IS_IGD(devid) (IS_IGDG(devid) || IS_IGDGM(devid))
+
+#define PCI_CHIP_I965_G 0x29A2
+#define PCI_CHIP_I965_Q 0x2992
+#define PCI_CHIP_I965_G_1 0x2982
+#define PCI_CHIP_I946_GZ 0x2972
+#define PCI_CHIP_I965_GM 0x2A02
+#define PCI_CHIP_I965_GME 0x2A12
+
+#define PCI_CHIP_GM45_GM 0x2A42
+
+#define PCI_CHIP_IGD_E_G 0x2E02
+#define PCI_CHIP_Q45_G 0x2E12
+#define PCI_CHIP_G45_G 0x2E22
+#define PCI_CHIP_G41_G 0x2E32
+
+#define PCI_CHIP_ILD_G 0x0042
+#define PCI_CHIP_ILM_G 0x0046
+
+#define PCI_CHIP_SANDYBRIDGE_GT1 0x0102 /* desktop */
+#define PCI_CHIP_SANDYBRIDGE_GT2 0x0112
+#define PCI_CHIP_SANDYBRIDGE_GT2_PLUS 0x0122
+#define PCI_CHIP_SANDYBRIDGE_M_GT1 0x0106 /* mobile */
+#define PCI_CHIP_SANDYBRIDGE_M_GT2 0x0116
+#define PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS 0x0126
+#define PCI_CHIP_SANDYBRIDGE_S 0x010A /* server */
+
+#define PCI_CHIP_IVYBRIDGE_GT1 0x0152 /* desktop */
+#define PCI_CHIP_IVYBRIDGE_GT2 0x0162
+#define PCI_CHIP_IVYBRIDGE_M_GT1 0x0156 /* mobile */
+#define PCI_CHIP_IVYBRIDGE_M_GT2 0x0166
+#define PCI_CHIP_IVYBRIDGE_S 0x015a /* server */
+#define PCI_CHIP_IVYBRIDGE_S_GT2 0x016a /* server */
+
+#define PCI_CHIP_HASWELL_GT1 0x0402 /* Desktop */
+#define PCI_CHIP_HASWELL_GT2 0x0412
+#define PCI_CHIP_HASWELL_GT2_PLUS 0x0422
+#define PCI_CHIP_HASWELL_M_GT1 0x0406 /* Mobile */
+#define PCI_CHIP_HASWELL_M_GT2 0x0416
+#define PCI_CHIP_HASWELL_M_GT2_PLUS 0x0426
+#define PCI_CHIP_HASWELL_S_GT1 0x040A /* Server */
+#define PCI_CHIP_HASWELL_S_GT2 0x041A
+#define PCI_CHIP_HASWELL_S_GT2_PLUS 0x042A
+#define PCI_CHIP_HASWELL_SDV_GT1 0x0C02 /* Desktop */
+#define PCI_CHIP_HASWELL_SDV_GT2 0x0C12
+#define PCI_CHIP_HASWELL_SDV_GT2_PLUS 0x0C22
+#define PCI_CHIP_HASWELL_SDV_M_GT1 0x0C06 /* Mobile */
+#define PCI_CHIP_HASWELL_SDV_M_GT2 0x0C16
+#define PCI_CHIP_HASWELL_SDV_M_GT2_PLUS 0x0C26
+#define PCI_CHIP_HASWELL_SDV_S_GT1 0x0C0A /* Server */
+#define PCI_CHIP_HASWELL_SDV_S_GT2 0x0C1A
+#define PCI_CHIP_HASWELL_SDV_S_GT2_PLUS 0x0C2A
+#define PCI_CHIP_HASWELL_ULT_GT1 0x0A02 /* Desktop */
+#define PCI_CHIP_HASWELL_ULT_GT2 0x0A12
+#define PCI_CHIP_HASWELL_ULT_GT2_PLUS 0x0A22
+#define PCI_CHIP_HASWELL_ULT_M_GT1 0x0A06 /* Mobile */
+#define PCI_CHIP_HASWELL_ULT_M_GT2 0x0A16
+#define PCI_CHIP_HASWELL_ULT_M_GT2_PLUS 0x0A26
+#define PCI_CHIP_HASWELL_ULT_S_GT1 0x0A0A /* Server */
+#define PCI_CHIP_HASWELL_ULT_S_GT2 0x0A1A
+#define PCI_CHIP_HASWELL_ULT_S_GT2_PLUS 0x0A2A
+#define PCI_CHIP_HASWELL_CRW_GT1 0x0D12 /* Desktop */
+#define PCI_CHIP_HASWELL_CRW_GT2 0x0D22
+#define PCI_CHIP_HASWELL_CRW_GT2_PLUS 0x0D32
+#define PCI_CHIP_HASWELL_CRW_M_GT1 0x0D16 /* Mobile */
+#define PCI_CHIP_HASWELL_CRW_M_GT2 0x0D26
+#define PCI_CHIP_HASWELL_CRW_M_GT2_PLUS 0x0D36
+#define PCI_CHIP_HASWELL_CRW_S_GT1 0x0D1A /* Server */
+#define PCI_CHIP_HASWELL_CRW_S_GT2 0x0D2A
+#define PCI_CHIP_HASWELL_CRW_S_GT2_PLUS 0x0D3A
+
+#define PCI_CHIP_VALLEYVIEW_PO 0x0f30 /* VLV PO board */
+
+#define IS_MOBILE(devid) (devid == PCI_CHIP_I855_GM || \
+ devid == PCI_CHIP_I915_GM || \
+ devid == PCI_CHIP_I945_GM || \
+ devid == PCI_CHIP_I945_GME || \
+ devid == PCI_CHIP_I965_GM || \
+ devid == PCI_CHIP_I965_GME || \
+ devid == PCI_CHIP_GM45_GM || IS_IGD(devid) || \
+ devid == PCI_CHIP_IVYBRIDGE_M_GT1 || \
+ devid == PCI_CHIP_IVYBRIDGE_M_GT2)
+
+#define IS_G45(devid) (devid == PCI_CHIP_IGD_E_G || \
+ devid == PCI_CHIP_Q45_G || \
+ devid == PCI_CHIP_G45_G || \
+ devid == PCI_CHIP_G41_G)
+#define IS_GM45(devid) (devid == PCI_CHIP_GM45_GM)
+#define IS_G4X(devid) (IS_G45(devid) || IS_GM45(devid))
+
+#define IS_ILD(devid) (devid == PCI_CHIP_ILD_G)
+#define IS_ILM(devid) (devid == PCI_CHIP_ILM_G)
+
+#define IS_915(devid) (devid == PCI_CHIP_I915_G || \
+ devid == PCI_CHIP_E7221_G || \
+ devid == PCI_CHIP_I915_GM)
+
+#define IS_945GM(devid) (devid == PCI_CHIP_I945_GM || \
+ devid == PCI_CHIP_I945_GME)
+
+#define IS_945(devid) (devid == PCI_CHIP_I945_G || \
+ devid == PCI_CHIP_I945_GM || \
+ devid == PCI_CHIP_I945_GME || \
+ IS_G33(devid))
+
+#define IS_G33(devid) (devid == PCI_CHIP_G33_G || \
+ devid == PCI_CHIP_Q33_G || \
+ devid == PCI_CHIP_Q35_G || IS_IGD(devid))
+
+#define IS_GEN2(devid) (devid == PCI_CHIP_I830_M || \
+ devid == PCI_CHIP_845_G || \
+ devid == PCI_CHIP_I855_GM || \
+ devid == PCI_CHIP_I865_G)
+
+#define IS_GEN3(devid) (IS_945(devid) || IS_915(devid))
+
+#define IS_GEN4(devid) (devid == PCI_CHIP_I965_G || \
+ devid == PCI_CHIP_I965_Q || \
+ devid == PCI_CHIP_I965_G_1 || \
+ devid == PCI_CHIP_I965_GM || \
+ devid == PCI_CHIP_I965_GME || \
+ devid == PCI_CHIP_I946_GZ || \
+ IS_G4X(devid))
+
+#define IS_GEN5(devid) (IS_ILD(devid) || IS_ILM(devid))
+
+#define IS_GEN6(devid) (devid == PCI_CHIP_SANDYBRIDGE_GT1 || \
+ devid == PCI_CHIP_SANDYBRIDGE_GT2 || \
+ devid == PCI_CHIP_SANDYBRIDGE_GT2_PLUS || \
+ devid == PCI_CHIP_SANDYBRIDGE_M_GT1 || \
+ devid == PCI_CHIP_SANDYBRIDGE_M_GT2 || \
+ devid == PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS || \
+ devid == PCI_CHIP_SANDYBRIDGE_S)
+
+#define IS_GEN7(devid) (IS_IVYBRIDGE(devid) || \
+ IS_HASWELL(devid))
+
+#define IS_IVYBRIDGE(dev) (dev == PCI_CHIP_IVYBRIDGE_GT1 || \
+ dev == PCI_CHIP_IVYBRIDGE_GT2 || \
+ dev == PCI_CHIP_IVYBRIDGE_M_GT1 || \
+ dev == PCI_CHIP_IVYBRIDGE_M_GT2 || \
+ dev == PCI_CHIP_IVYBRIDGE_S || \
+ dev == PCI_CHIP_IVYBRIDGE_S_GT2 || \
+ dev == PCI_CHIP_VALLEYVIEW_PO)
+
+#define IS_VALLEYVIEW(devid) (devid == PCI_CHIP_VALLEYVIEW_PO)
+
+#define IS_HSW_GT1(devid) (devid == PCI_CHIP_HASWELL_GT1 || \
+ devid == PCI_CHIP_HASWELL_M_GT1 || \
+ devid == PCI_CHIP_HASWELL_S_GT1 || \
+ devid == PCI_CHIP_HASWELL_SDV_GT1 || \
+ devid == PCI_CHIP_HASWELL_SDV_M_GT1 || \
+ devid == PCI_CHIP_HASWELL_SDV_S_GT1 || \
+ devid == PCI_CHIP_HASWELL_ULT_GT1 || \
+ devid == PCI_CHIP_HASWELL_ULT_M_GT1 || \
+ devid == PCI_CHIP_HASWELL_ULT_S_GT1 || \
+ devid == PCI_CHIP_HASWELL_CRW_GT1 || \
+ devid == PCI_CHIP_HASWELL_CRW_M_GT1 || \
+ devid == PCI_CHIP_HASWELL_CRW_S_GT1)
+#define IS_HSW_GT2(devid) (devid == PCI_CHIP_HASWELL_GT2 || \
+ devid == PCI_CHIP_HASWELL_M_GT2 || \
+ devid == PCI_CHIP_HASWELL_S_GT2 || \
+ devid == PCI_CHIP_HASWELL_SDV_GT2 || \
+ devid == PCI_CHIP_HASWELL_SDV_M_GT2 || \
+ devid == PCI_CHIP_HASWELL_SDV_S_GT2 || \
+ devid == PCI_CHIP_HASWELL_ULT_GT2 || \
+ devid == PCI_CHIP_HASWELL_ULT_M_GT2 || \
+ devid == PCI_CHIP_HASWELL_ULT_S_GT2 || \
+ devid == PCI_CHIP_HASWELL_CRW_GT2 || \
+ devid == PCI_CHIP_HASWELL_CRW_M_GT2 || \
+ devid == PCI_CHIP_HASWELL_CRW_S_GT2 || \
+ devid == PCI_CHIP_HASWELL_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_M_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_S_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_SDV_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_SDV_M_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_SDV_S_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_ULT_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_ULT_M_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_ULT_S_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_CRW_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_CRW_M_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_CRW_S_GT2_PLUS)
+
+#define IS_HASWELL(devid) (IS_HSW_GT1(devid) || \
+ IS_HSW_GT2(devid))
+
+#define IS_965(devid) (IS_GEN4(devid) || \
+ IS_GEN5(devid) || \
+ IS_GEN6(devid) || \
+ IS_GEN7(devid))
+
+#define IS_INTEL(devid) (IS_GEN2(devid) || \
+ IS_GEN3(devid) || \
+ IS_GEN4(devid) || \
+ IS_GEN5(devid) || \
+ IS_GEN6(devid) || \
+ IS_GEN7(devid))
+
+#define HAS_PCH_SPLIT(devid) (IS_GEN5(devid) || \
+ IS_GEN6(devid) || \
+ IS_GEN7(devid))
+
+#define HAS_BLT_RING(devid) (IS_GEN6(devid) || \
+ IS_GEN7(devid))
+
+#define HAS_BSD_RING(devid) (IS_GEN5(devid) || \
+ IS_GEN6(devid) || \
+ IS_GEN7(devid))
+
+#define IS_BROADWATER(devid) (devid == PCI_CHIP_I946_GZ || \
+ devid == PCI_CHIP_I965_G_1 || \
+ devid == PCI_CHIP_I965_Q || \
+ devid == PCI_CHIP_I965_G)
+
+#define IS_CRESTLINE(devid) (devid == PCI_CHIP_I965_GM || \
+ devid == PCI_CHIP_I965_GME)
diff --git a/lib/intel_dpio.c b/lib/intel_dpio.c
new file mode 100644
index 00000000..acfd2018
--- /dev/null
+++ b/lib/intel_dpio.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Vijay Purushothaman <vijay.a.purushothaman@intel.com>
+ *
+ */
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include "intel_gpu_tools.h"
+
+static uint32_t intel_display_reg_read(uint32_t reg)
+{
+ struct pci_device *dev = intel_get_pci_device();
+
+ if (IS_VALLEYVIEW(dev->device_id))
+ reg += VLV_DISPLAY_BASE;
+ return (*(volatile uint32_t*)((volatile char*)mmio + reg));
+}
+
+static void intel_display_reg_write(uint32_t reg, uint32_t val)
+{
+ volatile uint32_t *ptr;
+ struct pci_device *dev = intel_get_pci_device();
+
+ if (IS_VALLEYVIEW(dev->device_id))
+ reg += VLV_DISPLAY_BASE;
+ ptr = (volatile uint32_t*)((volatile char*)mmio + reg);
+ *ptr = val;
+}
+
+/*
+ * In SoCs like Valleyview some of the PLL & Lane control registers
+ * can be accessed only through IO side band fabric called DPIO
+ */
+uint32_t
+intel_dpio_reg_read(uint32_t reg)
+{
+ /* Check whether the side band fabric is ready to accept commands */
+ do {
+ usleep(1);
+ } while (intel_display_reg_read(DPIO_PKT) & DPIO_BUSY);
+
+ intel_display_reg_write(DPIO_REG, reg);
+ intel_display_reg_write(DPIO_PKT, DPIO_RID |
+ DPIO_OP_READ | DPIO_PORTID | DPIO_BYTE);
+ do {
+ usleep(1);
+ } while (intel_display_reg_read(DPIO_PKT) & DPIO_BUSY);
+
+ return intel_display_reg_read(DPIO_DATA);
+}
+
+/*
+ * In SoCs like Valleyview some of the PLL & Lane control registers
+ * can be accessed only through IO side band fabric called DPIO
+ */
+void
+intel_dpio_reg_write(uint32_t reg, uint32_t val)
+{
+ /* Check whether the side band fabric is ready to accept commands */
+ do {
+ usleep(1);
+ } while (intel_display_reg_read(DPIO_PKT) & DPIO_BUSY);
+
+ intel_display_reg_write(DPIO_DATA, val);
+ intel_display_reg_write(DPIO_REG, reg);
+ intel_display_reg_write(DPIO_PKT, DPIO_RID |
+ DPIO_OP_WRITE | DPIO_PORTID | DPIO_BYTE);
+ do {
+ usleep(1);
+ } while (intel_display_reg_read(DPIO_PKT) & DPIO_BUSY);
+}
diff --git a/lib/intel_drm.c b/lib/intel_drm.c
new file mode 100644
index 00000000..8d89d24f
--- /dev/null
+++ b/lib/intel_drm.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+#include <assert.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#ifdef HAVE_STRUCT_SYSINFO_TOTALRAM
+#include <sys/sysinfo.h>
+#elif defined(HAVE_SWAPCTL) /* Solaris */
+#include <sys/swap.h>
+#endif
+
+#include "intel_gpu_tools.h"
+#include "i915_drm.h"
+
+uint32_t
+intel_get_drm_devid(int fd)
+{
+ int ret;
+ struct drm_i915_getparam gp;
+ uint32_t devid;
+
+ gp.param = I915_PARAM_CHIPSET_ID;
+ gp.value = (int *)&devid;
+
+ ret = ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp));
+ assert(ret == 0);
+
+ return devid;
+}
+
+int intel_gen(uint32_t devid)
+{
+ if (IS_GEN2(devid))
+ return 2;
+ if (IS_GEN3(devid))
+ return 3;
+ if (IS_GEN4(devid))
+ return 4;
+ if (IS_GEN5(devid))
+ return 5;
+ if (IS_GEN6(devid))
+ return 6;
+ if (IS_GEN7(devid))
+ return 7;
+
+ return -1;
+}
+
+uint64_t
+intel_get_total_ram_mb(void)
+{
+ uint64_t retval;
+
+#ifdef HAVE_STRUCT_SYSINFO_TOTALRAM /* Linux */
+ struct sysinfo sysinf;
+ int ret;
+
+ ret = sysinfo(&sysinf);
+ assert(ret == 0);
+
+ retval = sysinf.totalram;
+ retval *= sysinf.mem_unit;
+#elif defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES) /* Solaris */
+ long pagesize, npages;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+ npages = sysconf(_SC_PHYS_PAGES);
+
+ retval = (uint64_t) pagesize * npages;
+#else
+#error "Unknown how to get RAM size for this OS"
+#endif
+
+ return retval / (1024*1024);
+}
+
+uint64_t
+intel_get_total_swap_mb(void)
+{
+ uint64_t retval;
+
+#ifdef HAVE_STRUCT_SYSINFO_TOTALRAM /* Linux */
+ struct sysinfo sysinf;
+ int ret;
+
+ ret = sysinfo(&sysinf);
+ assert(ret == 0);
+
+ retval = sysinf.totalswap;
+ retval *= sysinf.mem_unit;
+#elif defined(HAVE_SWAPCTL) /* Solaris */
+ long pagesize = sysconf(_SC_PAGESIZE);
+ uint64_t totalpages = 0;
+ swaptbl_t *swt;
+ char *buf;
+ int n, i;
+
+ if ((n = swapctl(SC_GETNSWP, NULL)) == -1) {
+ perror("swapctl: GETNSWP");
+ return 0;
+ }
+ if (n == 0) {
+ /* no error, but no swap devices either */
+ return 0;
+ }
+
+ swt = malloc(sizeof(struct swaptable) + (n * sizeof(swapent_t)));
+ buf = malloc(n * MAXPATHLEN);
+ if (!swt || !buf) {
+ perror("malloc");
+ } else {
+ swt->swt_n = n;
+ for (i = 0 ; i < n; i++) {
+ swt->swt_ent[i].ste_path = buf + (i * MAXPATHLEN);
+ }
+
+ if ((n = swapctl(SC_LIST, swt)) == -1) {
+ perror("swapctl: LIST");
+ } else {
+ for (i = 0; i < swt->swt_n; i++) {
+ totalpages += swt->swt_ent[i].ste_pages;
+ }
+ }
+ }
+ free(swt);
+ free(buf);
+
+ retval = (uint64_t) pagesize * totalpages;
+#else
+#warning "Unknown how to get swap size for this OS"
+ return 0;
+#endif
+
+ return retval / (1024*1024);
+}
+
+
+/*
+ * When testing a port to a new platform, create a standalone test binary
+ * by running:
+ * cc -o porttest intel_drm.c -I.. -DSTANDALONE_TEST `pkg-config --cflags libdrm`
+ * and then running the resulting porttest program.
+ */
+#ifdef STANDALONE_TEST
+void *mmio;
+
+int main(int argc, char **argv)
+{
+ printf("Total RAM: %" PRIu64 " Mb\n", intel_get_total_ram_mb());
+ printf("Total Swap: %" PRIu64 " Mb\n", intel_get_total_swap_mb());
+
+ return 0;
+}
+#endif /* STANDALONE_TEST */
diff --git a/lib/intel_gpu_tools.h b/lib/intel_gpu_tools.h
new file mode 100644
index 00000000..245d1de8
--- /dev/null
+++ b/lib/intel_gpu_tools.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef INTEL_GPU_TOOLS_H
+#define INTEL_GPU_TOOLS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <pciaccess.h>
+
+#include "intel_chipset.h"
+#include "intel_reg.h"
+
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
+
+extern void *mmio;
+void intel_get_mmio(struct pci_device *pci_dev);
+
+/* New style register access API */
+int intel_register_access_init(struct pci_device *pci_dev, int safe);
+void intel_register_access_fini(void);
+uint32_t intel_register_read(uint32_t reg);
+void intel_register_write(uint32_t reg, uint32_t val);
+/* Following functions are relevant only for SoCs like Valleyview */
+uint32_t intel_dpio_reg_read(uint32_t reg);
+void intel_dpio_reg_write(uint32_t reg, uint32_t val);
+
+#define INTEL_RANGE_RSVD (0<<0) /* Shouldn't be read or written */
+#define INTEL_RANGE_READ (1<<0)
+#define INTEL_RANGE_WRITE (1<<1)
+#define INTEL_RANGE_RW (INTEL_RANGE_READ | INTEL_RANGE_WRITE)
+#define INTEL_RANGE_END (1<<31)
+
+struct intel_register_range {
+ uint32_t base;
+ uint32_t size;
+ uint32_t flags;
+};
+
+struct intel_register_map {
+ struct intel_register_range *map;
+ uint32_t top;
+ uint32_t alignment_mask;
+};
+struct intel_register_map intel_get_register_map(uint32_t devid);
+struct intel_register_range *intel_get_register_range(struct intel_register_map map, uint32_t offset, int mode);
+
+
+static inline uint32_t
+INREG(uint32_t reg)
+{
+ return *(volatile uint32_t *)((volatile char *)mmio + reg);
+}
+
+static inline void
+OUTREG(uint32_t reg, uint32_t val)
+{
+ *(volatile uint32_t *)((volatile char *)mmio + reg) = val;
+}
+
+struct pci_device *intel_get_pci_device(void);
+
+uint32_t intel_get_drm_devid(int fd);
+int intel_gen(uint32_t devid);
+uint64_t intel_get_total_ram_mb(void);
+uint64_t intel_get_total_swap_mb(void);
+
+void intel_map_file(char *);
+
+enum pch_type {
+ PCH_IBX,
+ PCH_CPT,
+};
+
+extern enum pch_type pch;
+void intel_check_pch(void);
+
+#define HAS_CPT (pch == PCH_CPT)
+
+#endif /* INTEL_GPU_TOOLS_H */
diff --git a/lib/intel_mmio.c b/lib/intel_mmio.c
new file mode 100644
index 00000000..ecb049b7
--- /dev/null
+++ b/lib/intel_mmio.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+#include <assert.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "intel_gpu_tools.h"
+
+void *mmio;
+
+static struct _mmio_data {
+ int inited;
+ bool safe;
+ char debugfs_path[FILENAME_MAX];
+ char debugfs_forcewake_path[FILENAME_MAX];
+ uint32_t i915_devid;
+ struct intel_register_map map;
+ int key;
+} mmio_data;
+
+void
+intel_map_file(char *file)
+{
+ int fd;
+ struct stat st;
+
+ fd = open(file, O_RDWR);
+ if (fd == -1) {
+ fprintf(stderr, "Couldn't open %s: %s\n", file,
+ strerror(errno));
+ exit(1);
+ }
+ fstat(fd, &st);
+ mmio = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (mmio == MAP_FAILED) {
+ fprintf(stderr, "Couldn't mmap %s: %s\n", file,
+ strerror(errno));
+ exit(1);
+ }
+ close(fd);
+}
+
+void
+intel_get_mmio(struct pci_device *pci_dev)
+{
+ uint32_t devid, gen;
+ int mmio_bar, mmio_size;
+ int error;
+
+ devid = pci_dev->device_id;
+ if (IS_GEN2(devid))
+ mmio_bar = 1;
+ else
+ mmio_bar = 0;
+
+ gen = intel_gen(devid);
+ if (gen < 3)
+ mmio_size = 64*1024;
+ else if (gen < 5)
+ mmio_size = 512*1024;
+ else
+ mmio_size = 2*1024*1024;
+
+ error = pci_device_map_range (pci_dev,
+ pci_dev->regions[mmio_bar].base_addr,
+ mmio_size,
+ PCI_DEV_MAP_FLAG_WRITABLE,
+ &mmio);
+
+ if (error != 0) {
+ fprintf(stderr, "Couldn't map MMIO region: %s\n",
+ strerror(error));
+ exit(1);
+ }
+}
+
+/*
+ * If successful, i915_debugfs_path and i915_debugfs_forcewake_path are both
+ * updated with the correct path.
+ */
+static int
+find_debugfs_path(const char *dri_base)
+{
+ char buf[FILENAME_MAX];
+ struct stat sb;
+ int i, ret;
+
+ for (i = 0; i < 16; i++) {
+ snprintf(buf, FILENAME_MAX, "%s/%i/name", dri_base, i);
+
+ snprintf(mmio_data.debugfs_path, FILENAME_MAX,
+ "%s/%i/", dri_base, i);
+ snprintf(mmio_data.debugfs_forcewake_path, FILENAME_MAX,
+ "%s/%i/i915_forcewake_user", dri_base, i);
+
+ ret = stat(mmio_data.debugfs_forcewake_path, &sb);
+ if (ret) {
+ mmio_data.debugfs_path[0] = 0;
+ mmio_data.debugfs_forcewake_path[0] = 0;
+ } else
+ return 0;
+ }
+
+ return -1;
+}
+
+static int
+get_forcewake_lock(void)
+{
+ return open(mmio_data.debugfs_forcewake_path, 0);
+}
+
+static void
+release_forcewake_lock(int fd)
+{
+ close(fd);
+}
+
+/*
+ * Initialize register access library.
+ *
+ * @pci_dev: pci device we're mucking with
+ * @safe: use safe register access tables
+ */
+int
+intel_register_access_init(struct pci_device *pci_dev, int safe)
+{
+ int ret;
+
+ /* after old API is deprecated, remove this */
+ if (mmio == NULL)
+ intel_get_mmio(pci_dev);
+
+ assert(mmio != NULL);
+
+ if (mmio_data.inited)
+ return -1;
+
+ mmio_data.safe = safe != 0 ? true : false;
+ mmio_data.i915_devid = pci_dev->device_id;
+ if (mmio_data.safe)
+ mmio_data.map = intel_get_register_map(mmio_data.i915_devid);
+
+ if (!(IS_GEN6(pci_dev->device_id) ||
+ IS_GEN7(pci_dev->device_id)))
+ goto done;
+
+ /* Find where the forcewake lock is */
+ ret = find_debugfs_path("/sys/kernel/debug/dri");
+ if (ret) {
+ ret = find_debugfs_path("/debug/dri");
+ if (ret) {
+ fprintf(stderr, "Couldn't find path to dri/debugfs entry\n");
+ return ret;
+ }
+ }
+ mmio_data.key = get_forcewake_lock();
+
+done:
+ mmio_data.inited++;
+ return 0;
+}
+
+void
+intel_register_access_fini(void)
+{
+ if (mmio_data.key)
+ release_forcewake_lock(mmio_data.key);
+ mmio_data.inited--;
+}
+
+uint32_t
+intel_register_read(uint32_t reg)
+{
+ struct intel_register_range *range;
+ uint32_t ret;
+
+ assert(mmio_data.inited);
+
+ if (intel_gen(mmio_data.i915_devid) >= 6)
+ assert(mmio_data.key != -1);
+
+ if (!mmio_data.safe)
+ goto read_out;
+
+ range = intel_get_register_range(mmio_data.map,
+ reg,
+ INTEL_RANGE_READ);
+
+ if(!range) {
+ fprintf(stderr, "Register read blocked for safety "
+ "(*0x%08x)\n", reg);
+ ret = 0xffffffff;
+ goto out;
+ }
+
+read_out:
+ ret = *(volatile uint32_t *)((volatile char *)mmio + reg);
+out:
+ return ret;
+}
+
+void
+intel_register_write(uint32_t reg, uint32_t val)
+{
+ struct intel_register_range *range;
+
+ assert(mmio_data.inited);
+
+ if (intel_gen(mmio_data.i915_devid) >= 6)
+ assert(mmio_data.key != -1);
+
+ if (!mmio_data.safe)
+ goto write_out;
+
+ range = intel_get_register_range(mmio_data.map,
+ reg,
+ INTEL_RANGE_WRITE);
+
+ if (!range) {
+ fprintf(stderr, "Register write blocked for safety "
+ "(*0x%08x = 0x%x)\n", reg, val);
+ }
+
+write_out:
+ *(volatile uint32_t *)((volatile char *)mmio + reg) = val;
+}
diff --git a/lib/intel_pci.c b/lib/intel_pci.c
new file mode 100644
index 00000000..7228daec
--- /dev/null
+++ b/lib/intel_pci.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+#include <assert.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "intel_gpu_tools.h"
+
+enum pch_type pch;
+
+struct pci_device *
+intel_get_pci_device(void)
+{
+ struct pci_device *pci_dev;
+ int error;
+
+ error = pci_system_init();
+ if (error != 0) {
+ fprintf(stderr, "Couldn't initialize PCI system: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ /* Grab the graphics card */
+ pci_dev = pci_device_find_by_slot(0, 0, 2, 0);
+ if (pci_dev == NULL)
+ errx(1, "Couldn't find graphics card");
+
+ error = pci_device_probe(pci_dev);
+ if (error != 0) {
+ fprintf(stderr, "Couldn't probe graphics card: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ if (pci_dev->vendor_id != 0x8086)
+ errx(1, "Graphics card is non-intel");
+
+ return pci_dev;
+}
+
+void
+intel_check_pch(void)
+{
+ struct pci_device *pch_dev;
+
+ pch_dev = pci_device_find_by_slot(0, 0, 31, 0);
+ if (pch_dev == NULL)
+ return;
+
+ if (pch_dev->vendor_id == 0x8086 &&
+ (((pch_dev->device_id & 0xff00) == 0x1c00) ||
+ (pch_dev->device_id & 0xff00) == 0x1e00))
+ pch = PCH_CPT;
+}
+
diff --git a/lib/intel_reg.h b/lib/intel_reg.h
new file mode 100644
index 00000000..ae220b83
--- /dev/null
+++ b/lib/intel_reg.h
@@ -0,0 +1,3758 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_reg.h,v 1.13 2003/02/06 04:18:04 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/** @file
+ * Register names and fields for Intel graphics.
+ */
+
+/*
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Eric Anholt <eric@anholt.net>
+ *
+ * based on the i740 driver by
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ *
+ *
+ */
+
+#ifndef _I810_REG_H
+#define _I810_REG_H
+
+/* I/O register offsets
+ */
+#define SRX 0x3C4 /* p208 */
+#define GRX 0x3CE /* p213 */
+#define ARX 0x3C0 /* p224 */
+
+/* VGA Color Palette Registers */
+#define DACMASK 0x3C6 /* p232 */
+#define DACSTATE 0x3C7 /* p232 */
+#define DACRX 0x3C7 /* p233 */
+#define DACWX 0x3C8 /* p233 */
+#define DACDATA 0x3C9 /* p233 */
+
+/* CRT Controller Registers (CRX) */
+#define START_ADDR_HI 0x0C /* p246 */
+#define START_ADDR_LO 0x0D /* p247 */
+#define VERT_SYNC_END 0x11 /* p249 */
+#define EXT_VERT_TOTAL 0x30 /* p257 */
+#define EXT_VERT_DISPLAY 0x31 /* p258 */
+#define EXT_VERT_SYNC_START 0x32 /* p259 */
+#define EXT_VERT_BLANK_START 0x33 /* p260 */
+#define EXT_HORIZ_TOTAL 0x35 /* p261 */
+#define EXT_HORIZ_BLANK 0x39 /* p261 */
+#define EXT_START_ADDR 0x40 /* p262 */
+#define EXT_START_ADDR_ENABLE 0x80
+#define EXT_OFFSET 0x41 /* p263 */
+#define EXT_START_ADDR_HI 0x42 /* p263 */
+#define INTERLACE_CNTL 0x70 /* p264 */
+#define INTERLACE_ENABLE 0x80
+#define INTERLACE_DISABLE 0x00
+
+/* Miscellaneous Output Register
+ */
+#define MSR_R 0x3CC /* p207 */
+#define MSR_W 0x3C2 /* p207 */
+#define IO_ADDR_SELECT 0x01
+
+#define MDA_BASE 0x3B0 /* p207 */
+#define CGA_BASE 0x3D0 /* p207 */
+
+/* CR80 - IO Control, p264
+ */
+#define IO_CTNL 0x80
+#define EXTENDED_ATTR_CNTL 0x02
+#define EXTENDED_CRTC_CNTL 0x01
+
+/* GR10 - Address mapping, p221
+ */
+#define ADDRESS_MAPPING 0x10
+#define PAGE_TO_LOCAL_MEM_ENABLE 0x10
+#define GTT_MEM_MAP_ENABLE 0x08
+#define PACKED_MODE_ENABLE 0x04
+#define LINEAR_MODE_ENABLE 0x02
+#define PAGE_MAPPING_ENABLE 0x01
+
+#define HOTKEY_VBIOS_SWITCH_BLOCK 0x80
+#define HOTKEY_SWITCH 0x20
+#define HOTKEY_TOGGLE 0x10
+
+/* Blitter control, p378
+ */
+#define BITBLT_CNTL 0x7000c
+#define COLEXP_MODE 0x30
+#define COLEXP_8BPP 0x00
+#define COLEXP_16BPP 0x10
+#define COLEXP_24BPP 0x20
+#define COLEXP_RESERVED 0x30
+#define BITBLT_STATUS 0x01
+
+#define CHDECMISC 0x10111
+#define DCC 0x10200
+#define C0DRB0 0x10200
+#define C0DRB1 0x10202
+#define C0DRB2 0x10204
+#define C0DRB3 0x10206
+#define C0DRA01 0x10208
+#define C0DRA23 0x1020a
+#define C1DRB0 0x10600
+#define C1DRB1 0x10602
+#define C1DRB2 0x10604
+#define C1DRB3 0x10606
+#define C1DRA01 0x10608
+#define C1DRA23 0x1060a
+
+/* p375.
+ */
+#define DISPLAY_CNTL 0x70008
+#define VGA_WRAP_MODE 0x02
+#define VGA_WRAP_AT_256KB 0x00
+#define VGA_NO_WRAP 0x02
+#define GUI_MODE 0x01
+#define STANDARD_VGA_MODE 0x00
+#define HIRES_MODE 0x01
+
+/* p375
+ */
+#define PIXPIPE_CONFIG_0 0x70009
+#define DAC_8_BIT 0x80
+#define DAC_6_BIT 0x00
+#define HW_CURSOR_ENABLE 0x10
+#define EXTENDED_PALETTE 0x01
+
+/* p375
+ */
+#define PIXPIPE_CONFIG_1 0x7000a
+#define DISPLAY_COLOR_MODE 0x0F
+#define DISPLAY_VGA_MODE 0x00
+#define DISPLAY_8BPP_MODE 0x02
+#define DISPLAY_15BPP_MODE 0x04
+#define DISPLAY_16BPP_MODE 0x05
+#define DISPLAY_24BPP_MODE 0x06
+#define DISPLAY_32BPP_MODE 0x07
+
+/* p375
+ */
+#define PIXPIPE_CONFIG_2 0x7000b
+#define DISPLAY_GAMMA_ENABLE 0x08
+#define DISPLAY_GAMMA_DISABLE 0x00
+#define OVERLAY_GAMMA_ENABLE 0x04
+#define OVERLAY_GAMMA_DISABLE 0x00
+
+
+/* p380
+ */
+#define DISPLAY_BASE 0x70020
+#define DISPLAY_BASE_MASK 0x03fffffc
+
+
+/* Cursor control registers, pp383-384
+ */
+/* Desktop (845G, 865G) */
+#define CURSOR_CONTROL 0x70080
+#define CURSOR_ENABLE 0x80000000
+#define CURSOR_GAMMA_ENABLE 0x40000000
+#define CURSOR_STRIDE_MASK 0x30000000
+#define CURSOR_FORMAT_SHIFT 24
+#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_3C (0x01 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_4C (0x02 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_ARGB (0x04 << CURSOR_FORMAT_SHIFT)
+#define CURSOR_FORMAT_XRGB (0x05 << CURSOR_FORMAT_SHIFT)
+
+/* Mobile and i810 */
+#define CURSOR_A_CONTROL CURSOR_CONTROL
+#define CURSOR_ORIGIN_SCREEN 0x00 /* i810 only */
+#define CURSOR_ORIGIN_DISPLAY 0x1 /* i810 only */
+#define CURSOR_MODE 0x27
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_32_4C_AX 0x01 /* i810 only */
+#define CURSOR_MODE_64_3C 0x04
+#define CURSOR_MODE_64_4C_AX 0x05
+#define CURSOR_MODE_64_4C 0x06
+#define CURSOR_MODE_64_32B_AX 0x07
+#define CURSOR_MODE_64_ARGB_AX (0x20 | CURSOR_MODE_64_32B_AX)
+#define MCURSOR_PIPE_SELECT (1 << 28)
+#define MCURSOR_PIPE_A 0x00
+#define MCURSOR_PIPE_B (1 << 28)
+#define MCURSOR_GAMMA_ENABLE (1 << 26)
+#define MCURSOR_MEM_TYPE_LOCAL (1 << 25)
+
+
+#define CURSOR_BASEADDR 0x70084
+#define CURSOR_A_BASE CURSOR_BASEADDR
+#define CURSOR_BASEADDR_MASK 0x1FFFFF00
+#define CURSOR_A_POSITION 0x70088
+#define CURSOR_POS_SIGN 0x8000
+#define CURSOR_POS_MASK 0x007FF
+#define CURSOR_X_SHIFT 0
+#define CURSOR_Y_SHIFT 16
+#define CURSOR_X_LO 0x70088
+#define CURSOR_X_HI 0x70089
+#define CURSOR_X_POS 0x00
+#define CURSOR_X_NEG 0x80
+#define CURSOR_Y_LO 0x7008A
+#define CURSOR_Y_HI 0x7008B
+#define CURSOR_Y_POS 0x00
+#define CURSOR_Y_NEG 0x80
+
+#define CURSOR_A_PALETTE0 0x70090
+#define CURSOR_A_PALETTE1 0x70094
+#define CURSOR_A_PALETTE2 0x70098
+#define CURSOR_A_PALETTE3 0x7009C
+
+#define CURSOR_SIZE 0x700A0
+#define CURSOR_SIZE_MASK 0x3FF
+#define CURSOR_SIZE_HSHIFT 0
+#define CURSOR_SIZE_VSHIFT 12
+
+#define CURSOR_B_CONTROL 0x700C0
+#define CURSOR_B_BASE 0x700C4
+#define CURSOR_B_POSITION 0x700C8
+#define CURSOR_B_PALETTE0 0x700D0
+#define CURSOR_B_PALETTE1 0x700D4
+#define CURSOR_B_PALETTE2 0x700D8
+#define CURSOR_B_PALETTE3 0x700DC
+
+
+/* Similar registers exist in Device 0 on the i810 (pp55-65), but I'm
+ * not sure they refer to local (graphics) memory.
+ *
+ * These details are for the local memory control registers,
+ * (pp301-310). The test machines are not equiped with local memory,
+ * so nothing is tested. Only a single row seems to be supported.
+ */
+#define DRAM_ROW_TYPE 0x3000
+#define DRAM_ROW_0 0x01
+#define DRAM_ROW_0_SDRAM 0x01
+#define DRAM_ROW_0_EMPTY 0x00
+#define DRAM_ROW_CNTL_LO 0x3001
+#define DRAM_PAGE_MODE_CTRL 0x10
+#define DRAM_RAS_TO_CAS_OVRIDE 0x08
+#define DRAM_CAS_LATENCY 0x04
+#define DRAM_RAS_TIMING 0x02
+#define DRAM_RAS_PRECHARGE 0x01
+#define DRAM_ROW_CNTL_HI 0x3002
+#define DRAM_REFRESH_RATE 0x18
+#define DRAM_REFRESH_DISABLE 0x00
+#define DRAM_REFRESH_60HZ 0x08
+#define DRAM_REFRESH_FAST_TEST 0x10
+#define DRAM_REFRESH_RESERVED 0x18
+#define DRAM_SMS 0x07
+#define DRAM_SMS_NORMAL 0x00
+#define DRAM_SMS_NOP_ENABLE 0x01
+#define DRAM_SMS_ABPCE 0x02
+#define DRAM_SMS_MRCE 0x03
+#define DRAM_SMS_CBRCE 0x04
+
+/* p307
+ */
+#define DPMS_SYNC_SELECT 0x5002
+#define VSYNC_CNTL 0x08
+#define VSYNC_ON 0x00
+#define VSYNC_OFF 0x08
+#define HSYNC_CNTL 0x02
+#define HSYNC_ON 0x00
+#define HSYNC_OFF 0x02
+
+#define GPIOA 0x5010
+#define GPIOB 0x5014
+#define GPIOC 0x5018
+#define GPIOD 0x501c
+#define GPIOE 0x5020
+#define GPIOF 0x5024
+#define GPIOG 0x5028
+#define GPIOH 0x502c
+# define GPIO_CLOCK_DIR_MASK (1 << 0)
+# define GPIO_CLOCK_DIR_IN (0 << 1)
+# define GPIO_CLOCK_DIR_OUT (1 << 1)
+# define GPIO_CLOCK_VAL_MASK (1 << 2)
+# define GPIO_CLOCK_VAL_OUT (1 << 3)
+# define GPIO_CLOCK_VAL_IN (1 << 4)
+# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5)
+# define GPIO_DATA_DIR_MASK (1 << 8)
+# define GPIO_DATA_DIR_IN (0 << 9)
+# define GPIO_DATA_DIR_OUT (1 << 9)
+# define GPIO_DATA_VAL_MASK (1 << 10)
+# define GPIO_DATA_VAL_OUT (1 << 11)
+# define GPIO_DATA_VAL_IN (1 << 12)
+# define GPIO_DATA_PULLUP_DISABLE (1 << 13)
+
+/* GMBus registers for hardware-assisted (non-bitbanging) I2C access */
+#define GMBUS0 0x5100
+#define GMBUS1 0x5104
+#define GMBUS2 0x5108
+#define GMBUS3 0x510c
+#define GMBUS4 0x5110
+#define GMBUS5 0x5120
+
+/* p317, 319
+ */
+#define VCLK2_VCO_M 0x6008 /* treat as 16 bit? (includes msbs) */
+#define VCLK2_VCO_N 0x600a
+#define VCLK2_VCO_DIV_SEL 0x6012
+
+#define VCLK_DIVISOR_VGA0 0x6000
+#define VCLK_DIVISOR_VGA1 0x6004
+#define VCLK_POST_DIV 0x6010
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA1_PD_P2_DIV_4 (1 << 15)
+/** Overrides the p2 post divisor field */
+# define VGA1_PD_P1_DIV_2 (1 << 13)
+# define VGA1_PD_P1_SHIFT 8
+/** P1 value is 2 greater than this field */
+# define VGA1_PD_P1_MASK (0x1f << 8)
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA0_PD_P2_DIV_4 (1 << 7)
+/** Overrides the p2 post divisor field */
+# define VGA0_PD_P1_DIV_2 (1 << 5)
+# define VGA0_PD_P1_SHIFT 0
+/** P1 value is 2 greater than this field */
+# define VGA0_PD_P1_MASK (0x1f << 0)
+
+#define POST_DIV_SELECT 0x70
+#define POST_DIV_1 0x00
+#define POST_DIV_2 0x10
+#define POST_DIV_4 0x20
+#define POST_DIV_8 0x30
+#define POST_DIV_16 0x40
+#define POST_DIV_32 0x50
+#define VCO_LOOP_DIV_BY_4M 0x00
+#define VCO_LOOP_DIV_BY_16M 0x04
+
+
+/* Instruction Parser Mode Register
+ * - p281
+ * - 2 new bits.
+ */
+#define INST_PM 0x20c0
+#define AGP_SYNC_PACKET_FLUSH_ENABLE 0x20 /* reserved */
+#define SYNC_PACKET_FLUSH_ENABLE 0x10
+#define TWO_D_INST_DISABLE 0x08
+#define THREE_D_INST_DISABLE 0x04
+#define STATE_VAR_UPDATE_DISABLE 0x02
+#define PAL_STIP_DISABLE 0x01
+#define GEN6_GLOBAL_DEBUG_ENABLE 0x10
+
+
+#define MEMMODE 0x20dc
+
+
+/* Instruction parser error register. p279
+ */
+#define IPEIR 0x2088
+#define IPEHR 0x208C
+
+#define INST_DONE 0x2090
+# define IDCT_DONE (1 << 30)
+# define IQ_DONE (1 << 29)
+# define PR_DONE (1 << 28)
+# define VLD_DONE (1 << 27)
+# define IP_DONE (1 << 26)
+# define FBC_DONE (1 << 25)
+# define BINNER_DONE (1 << 24)
+# define SF_DONE (1 << 23)
+# define SE_DONE (1 << 22)
+# define WM_DONE (1 << 21)
+# define IZ_DONE (1 << 20)
+# define PERSPECTIVE_INTERP_DONE (1 << 19)
+# define DISPATCHER_DONE (1 << 18)
+# define PROJECTION_DONE (1 << 17)
+# define DEPENDENT_ADDRESS_DONE (1 << 16)
+# define QUAD_CACHE_DONE (1 << 15)
+# define TEXTURE_FETCH_DONE (1 << 14)
+# define TEXTURE_DECOMPRESS_DONE (1 << 13)
+# define SAMPLER_CACHE_DONE (1 << 12)
+# define FILTER_DONE (1 << 11)
+# define BYPASS_FIFO_DONE (1 << 10)
+# define PS_DONE (1 << 9)
+# define CC_DONE (1 << 8)
+# define MAP_FILTER_DONE (1 << 7)
+# define MAP_L2_IDLE (1 << 6)
+# define RING_2_ENABLE (1 << 2)
+# define RING_1_ENABLE (1 << 1)
+# define RING_0_ENABLE (1 << 0)
+
+# define I830_GMBUS_DONE (1 << 26)
+# define I830_FBC_DONE (1 << 25)
+# define I830_BINNER_DONE (1 << 24)
+# define I830_MPEG_DONE (1 << 23)
+# define I830_MECO_DONE (1 << 22)
+# define I830_MCD_DONE (1 << 21)
+# define I830_MCSTP_DONE (1 << 20)
+# define I830_CC_DONE (1 << 19)
+# define I830_DG_DONE (1 << 18)
+# define I830_DCMP_DONE (1 << 17)
+# define I830_FTCH_DONE (1 << 16)
+# define I830_IT_DONE (1 << 15)
+# define I830_MG_DONE (1 << 14)
+# define I830_MEC_DONE (1 << 13)
+# define I830_PC_DONE (1 << 12)
+# define I830_QCC_DONE (1 << 11)
+# define I830_TB_DONE (1 << 10)
+# define I830_WM_DONE (1 << 9)
+# define I830_EF_DONE (1 << 8)
+# define I830_BLITTER_DONE (1 << 7)
+# define I830_MAP_L2_DONE (1 << 6)
+# define I830_SECONDARY_RING_3_DONE (1 << 5)
+# define I830_SECONDARY_RING_2_DONE (1 << 4)
+# define I830_SECONDARY_RING_1_DONE (1 << 3)
+# define I830_SECONDARY_RING_0_DONE (1 << 2)
+# define I830_PRIMARY_RING_1_DONE (1 << 1)
+# define I830_PRIMARY_RING_0_DONE (1 << 0)
+
+#define NOP_ID 0x2094
+
+#define SCPD0 0x209c /* debug */
+#define INST_PS 0x20c4
+#define IPEIR_I965 0x2064 /* i965 */
+#define IPEHR_I965 0x2068 /* i965 */
+#define INST_DONE_I965 0x206c
+# define I965_ROW_0_EU_0_DONE (1 << 31)
+# define I965_ROW_0_EU_1_DONE (1 << 30)
+# define I965_ROW_0_EU_2_DONE (1 << 29)
+# define I965_ROW_0_EU_3_DONE (1 << 28)
+# define I965_ROW_1_EU_0_DONE (1 << 27)
+# define I965_ROW_1_EU_1_DONE (1 << 26)
+# define I965_ROW_1_EU_2_DONE (1 << 25)
+# define I965_ROW_1_EU_3_DONE (1 << 24)
+# define I965_SF_DONE (1 << 23)
+# define I965_SE_DONE (1 << 22)
+# define I965_WM_DONE (1 << 21)
+# define I965_DISPATCHER_DONE (1 << 18)
+# define I965_PROJECTION_DONE (1 << 17)
+# define I965_DG_DONE (1 << 16)
+# define I965_QUAD_CACHE_DONE (1 << 15)
+# define I965_TEXTURE_FETCH_DONE (1 << 14)
+# define I965_TEXTURE_DECOMPRESS_DONE (1 << 13)
+# define I965_SAMPLER_CACHE_DONE (1 << 12)
+# define I965_FILTER_DONE (1 << 11)
+# define I965_BYPASS_DONE (1 << 10)
+# define I965_PS_DONE (1 << 9)
+# define I965_CC_DONE (1 << 8)
+# define I965_MAP_FILTER_DONE (1 << 7)
+# define I965_MAP_L2_IDLE (1 << 6)
+# define I965_MA_ROW_0_DONE (1 << 5)
+# define I965_MA_ROW_1_DONE (1 << 4)
+# define I965_IC_ROW_0_DONE (1 << 3)
+# define I965_IC_ROW_1_DONE (1 << 2)
+# define I965_CP_DONE (1 << 1)
+# define I965_RING_0_ENABLE (1 << 0)
+
+# define ILK_ROW_0_EU_0_DONE (1 << 31)
+# define ILK_ROW_0_EU_1_DONE (1 << 30)
+# define ILK_ROW_0_EU_2_DONE (1 << 29)
+# define ILK_ROW_0_EU_3_DONE (1 << 28)
+# define ILK_ROW_1_EU_0_DONE (1 << 27)
+# define ILK_ROW_1_EU_1_DONE (1 << 26)
+# define ILK_ROW_1_EU_2_DONE (1 << 25)
+# define ILK_ROW_1_EU_3_DONE (1 << 24)
+# define ILK_ROW_2_EU_0_DONE (1 << 23)
+# define ILK_ROW_2_EU_1_DONE (1 << 22)
+# define ILK_ROW_2_EU_2_DONE (1 << 21)
+# define ILK_ROW_2_EU_3_DONE (1 << 20)
+# define ILK_VCP_DONE (1 << 19)
+# define ILK_ROW_0_MATH_DONE (1 << 18)
+# define ILK_ROW_1_MATH_DONE (1 << 17)
+# define ILK_ROW_2_MATH_DONE (1 << 16)
+# define ILK_VC1_DONE (1 << 15)
+# define ILK_ROW_0_MA_DONE (1 << 14)
+# define ILK_ROW_1_MA_DONE (1 << 13)
+# define ILK_ROW_2_MA_DONE (1 << 12)
+# define ILK_ROW_0_ISC_DONE (1 << 11)
+# define ILK_ROW_1_ISC_DONE (1 << 10)
+# define ILK_ROW_2_ISC_DONE (1 << 9)
+# define ILK_VFE_DONE (1 << 8)
+# define ILK_TD_DONE (1 << 7)
+# define ILK_SVTS_DONE (1 << 6)
+# define ILK_TS_DONE (1 << 5)
+# define ILK_GW_DONE (1 << 4)
+# define ILK_AI_DONE (1 << 3)
+# define ILK_AC_DONE (1 << 2)
+# define ILK_AM_DONE (1 << 1)
+
+#define GEN6_INSTDONE_1 0x206c
+# define GEN6_MA_3_DONE (1 << 31)
+# define GEN6_EU_32_DONE (1 << 30)
+# define GEN6_EU_31_DONE (1 << 29)
+# define GEN6_EU_30_DONE (1 << 28)
+# define GEN6_MA_2_DONE (1 << 27)
+# define GEN6_EU_22_DONE (1 << 26)
+# define GEN6_EU_21_DONE (1 << 25)
+# define GEN6_EU_20_DONE (1 << 24)
+# define GEN6_MA_1_DONE (1 << 23)
+# define GEN6_EU_12_DONE (1 << 22)
+# define GEN6_EU_11_DONE (1 << 21)
+# define GEN6_EU_10_DONE (1 << 20)
+# define GEN6_MA_0_DONE (1 << 19)
+# define GEN6_EU_02_DONE (1 << 18)
+# define GEN6_EU_01_DONE (1 << 17)
+# define GEN6_EU_00_DONE (1 << 16)
+# define GEN6_IC_3_DONE (1 << 15)
+# define GEN6_IC_2_DONE (1 << 14)
+# define GEN6_IC_1_DONE (1 << 13)
+# define GEN6_IC_0_DONE (1 << 12)
+# define GEN6_ISC_10_DONE (1 << 11)
+# define GEN6_ISC_32_DONE (1 << 10)
+# define GEN6_VSC_DONE (1 << 9)
+# define GEN6_IEF_DONE (1 << 8)
+# define GEN6_VFE_DONE (1 << 7)
+# define GEN6_TD_DONE (1 << 6)
+# define GEN6_TS_DONE (1 << 4)
+# define GEN6_GW_DONE (1 << 3)
+# define GEN6_HIZ_DONE (1 << 2)
+# define GEN6_AVS_DONE (1 << 1)
+
+#define INST_PS_I965 0x2070
+
+/* Current active ring head address:
+ */
+#define ACTHD_I965 0x2074
+#define ACTHD 0x20C8
+
+/* Current primary/secondary DMA fetch addresses:
+ */
+#define DMA_FADD_P 0x2078
+#define DMA_FADD_S 0x20d4
+#define INST_DONE_1 0x207c
+# define I965_GW_CS_DONE_CR (1 << 19)
+# define I965_SVSM_CS_DONE_CR (1 << 18)
+# define I965_SVDW_CS_DONE_CR (1 << 17)
+# define I965_SVDR_CS_DONE_CR (1 << 16)
+# define I965_SVRW_CS_DONE_CR (1 << 15)
+# define I965_SVRR_CS_DONE_CR (1 << 14)
+# define I965_SVTW_CS_DONE_CR (1 << 13)
+# define I965_MASM_CS_DONE_CR (1 << 12)
+# define I965_MASF_CS_DONE_CR (1 << 11)
+# define I965_MAW_CS_DONE_CR (1 << 10)
+# define I965_EM1_CS_DONE_CR (1 << 9)
+# define I965_EM0_CS_DONE_CR (1 << 8)
+# define I965_UC1_CS_DONE (1 << 7)
+# define I965_UC0_CS_DONE (1 << 6)
+# define I965_URB_CS_DONE (1 << 5)
+# define I965_ISC_CS_DONE (1 << 4)
+# define I965_CL_CS_DONE (1 << 3)
+# define I965_GS_CS_DONE (1 << 2)
+# define I965_VS0_CS_DONE (1 << 1)
+# define I965_VF_CS_DONE (1 << 0)
+
+# define G4X_BCS_DONE (1 << 31)
+# define G4X_CS_DONE (1 << 30)
+# define G4X_MASF_DONE (1 << 29)
+# define G4X_SVDW_DONE (1 << 28)
+# define G4X_SVDR_DONE (1 << 27)
+# define G4X_SVRW_DONE (1 << 26)
+# define G4X_SVRR_DONE (1 << 25)
+# define G4X_ISC_DONE (1 << 24)
+# define G4X_MT_DONE (1 << 23)
+# define G4X_RC_DONE (1 << 22)
+# define G4X_DAP_DONE (1 << 21)
+# define G4X_MAWB_DONE (1 << 20)
+# define G4X_MT_IDLE (1 << 19)
+# define G4X_GBLT_BUSY (1 << 18)
+# define G4X_SVSM_DONE (1 << 17)
+# define G4X_MASM_DONE (1 << 16)
+# define G4X_QC_DONE (1 << 15)
+# define G4X_FL_DONE (1 << 14)
+# define G4X_SC_DONE (1 << 13)
+# define G4X_DM_DONE (1 << 12)
+# define G4X_FT_DONE (1 << 11)
+# define G4X_DG_DONE (1 << 10)
+# define G4X_SI_DONE (1 << 9)
+# define G4X_SO_DONE (1 << 8)
+# define G4X_PL_DONE (1 << 7)
+# define G4X_WIZ_DONE (1 << 6)
+# define G4X_URB_DONE (1 << 5)
+# define G4X_SF_DONE (1 << 4)
+# define G4X_CL_DONE (1 << 3)
+# define G4X_GS_DONE (1 << 2)
+# define G4X_VS0_DONE (1 << 1)
+# define G4X_VF_DONE (1 << 0)
+
+#define GEN6_INSTDONE_2 0x207c
+# define GEN6_GAM_DONE (1 << 31)
+# define GEN6_CS_DONE (1 << 30)
+# define GEN6_WMBE_DONE (1 << 29)
+# define GEN6_SVRW_DONE (1 << 28)
+# define GEN6_RCC_DONE (1 << 27)
+# define GEN6_SVG_DONE (1 << 26)
+# define GEN6_ISC_DONE (1 << 25)
+# define GEN6_MT_DONE (1 << 24)
+# define GEN6_RCPFE_DONE (1 << 23)
+# define GEN6_RCPBE_DONE (1 << 22)
+# define GEN6_VDI_DONE (1 << 21)
+# define GEN6_RCZ_DONE (1 << 20)
+# define GEN6_DAP_DONE (1 << 19)
+# define GEN6_PSD_DONE (1 << 18)
+# define GEN6_IZ_DONE (1 << 17)
+# define GEN6_WMFE_DONE (1 << 16)
+# define GEN6_SVSM_DONE (1 << 15)
+# define GEN6_QC_DONE (1 << 14)
+# define GEN6_FL_DONE (1 << 13)
+# define GEN6_SC_DONE (1 << 12)
+# define GEN6_DM_DONE (1 << 11)
+# define GEN6_FT_DONE (1 << 10)
+# define GEN6_DG_DONE (1 << 9)
+# define GEN6_SI_DONE (1 << 8)
+# define GEN6_SO_DONE (1 << 7)
+# define GEN6_PL_DONE (1 << 6)
+# define GEN6_VME_DONE (1 << 5)
+# define GEN6_SF_DONE (1 << 4)
+# define GEN6_CL_DONE (1 << 3)
+# define GEN6_GS_DONE (1 << 2)
+# define GEN6_VS0_DONE (1 << 1)
+# define GEN6_VF_DONE (1 << 0)
+
+#define CACHE_MODE_0 0x2120
+#define CACHE_MODE_1 0x2124
+#define MI_MODE 0x209c
+#define MI_DISPLAY_POWER_DOWN 0x20e0
+#define MI_ARB_STATE 0x20e4
+#define MI_RDRET_STATE 0x20fc
+
+/* Start addresses for each of the primary rings:
+ */
+#define PR0_STR 0x20f0
+#define PR1_STR 0x20f4
+#define PR2_STR 0x20f8
+
+#define WIZ_CTL 0x7c00
+#define WIZ_CTL_SINGLE_SUBSPAN (1<<6)
+#define WIZ_CTL_IGNORE_STALLS (1<<5)
+
+#define SVG_WORK_CTL 0x7408
+
+#define TS_CTL 0x7e00
+#define TS_MUX_ERR_CODE (0<<8)
+#define TS_MUX_URB_0 (1<<8)
+#define TS_MUX_DISPATCH_ID_0 (10<<8)
+#define TS_MUX_ERR_CODE_VALID (15<<8)
+#define TS_MUX_TID_0 (16<<8)
+#define TS_MUX_EUID_0 (18<<8)
+#define TS_MUX_FFID_0 (22<<8)
+#define TS_MUX_EOT (26<<8)
+#define TS_MUX_SIDEBAND_0 (27<<8)
+#define TS_SNAP_ALL_CHILD (1<<2)
+#define TS_SNAP_ALL_ROOT (1<<1)
+#define TS_SNAP_ENABLE (1<<0)
+
+#define TS_DEBUG_DATA 0x7e0c
+
+#define TD_CTL 0x8000
+#define TD_CTL2 0x8004
+
+
+#define ECOSKPD 0x21d0
+#define EXCC 0x2028
+
+/* I965 debug regs:
+ */
+#define IA_VERTICES_COUNT_QW 0x2310
+#define IA_PRIMITIVES_COUNT_QW 0x2318
+#define VS_INVOCATION_COUNT_QW 0x2320
+#define GS_INVOCATION_COUNT_QW 0x2328
+#define GS_PRIMITIVES_COUNT_QW 0x2330
+#define CL_INVOCATION_COUNT_QW 0x2338
+#define CL_PRIMITIVES_COUNT_QW 0x2340
+#define PS_INVOCATION_COUNT_QW 0x2348
+#define PS_DEPTH_COUNT_QW 0x2350
+#define TIMESTAMP_QW 0x2358
+#define CLKCMP_QW 0x2360
+
+
+
+
+
+
+/* General error reporting regs, p296
+ */
+#define EIR 0x20B0
+#define EMR 0x20B4
+#define ESR 0x20B8
+# define ERR_VERTEX_MAX (1 << 5) /* lpt/cst */
+# define ERR_PGTBL_ERROR (1 << 4)
+# define ERR_DISPLAY_OVERLAY_UNDERRUN (1 << 3)
+# define ERR_MAIN_MEMORY_REFRESH (1 << 1)
+# define ERR_INSTRUCTION_ERROR (1 << 0)
+
+
+/* Interrupt Control Registers
+ * - new bits for i810
+ * - new register hwstam (mask)
+ */
+#define HWS_PGA 0x2080
+#define PWRCTXA 0x2088 /* 965GM+ only */
+#define PWRCTX_EN (1<<0)
+#define HWSTAM 0x2098 /* p290 */
+#define IER 0x20a0 /* p291 */
+#define IIR 0x20a4 /* p292 */
+#define IMR 0x20a8 /* p293 */
+#define ISR 0x20ac /* p294 */
+#define HW_ERROR 0x8000
+#define SYNC_STATUS_TOGGLE 0x1000
+#define DPY_0_FLIP_PENDING 0x0800
+#define DPY_1_FLIP_PENDING 0x0400 /* not implemented on i810 */
+#define OVL_0_FLIP_PENDING 0x0200
+#define OVL_1_FLIP_PENDING 0x0100 /* not implemented on i810 */
+#define DPY_0_VBLANK 0x0080
+#define DPY_0_EVENT 0x0040
+#define DPY_1_VBLANK 0x0020 /* not implemented on i810 */
+#define DPY_1_EVENT 0x0010 /* not implemented on i810 */
+#define HOST_PORT_EVENT 0x0008 /* */
+#define CAPTURE_EVENT 0x0004 /* */
+#define USER_DEFINED 0x0002
+#define BREAKPOINT 0x0001
+
+
+#define INTR_RESERVED (0x6000 | \
+ DPY_1_FLIP_PENDING | \
+ OVL_1_FLIP_PENDING | \
+ DPY_1_VBLANK | \
+ DPY_1_EVENT | \
+ HOST_PORT_EVENT | \
+ CAPTURE_EVENT )
+
+/* FIFO Watermark and Burst Length Control Register
+ *
+ * - different offset and contents on i810 (p299) (fewer bits per field)
+ * - some overlay fields added
+ * - what does it all mean?
+ */
+#define FWATER_BLC 0x20d8
+#define FWATER_BLC2 0x20dc
+#define MM_BURST_LENGTH 0x00700000
+#define MM_FIFO_WATERMARK 0x0001F000
+#define LM_BURST_LENGTH 0x00000700
+#define LM_FIFO_WATERMARK 0x0000001F
+
+
+/* Fence/Tiling ranges [0..7]
+ */
+#define FENCE 0x2000
+#define FENCE_NR 8
+
+#define FENCE_NEW 0x3000
+#define FENCE_NEW_NR 16
+
+#define FENCE_LINEAR 0
+#define FENCE_XMAJOR 1
+#define FENCE_YMAJOR 2
+
+#define I915G_FENCE_START_MASK 0x0ff00000
+
+#define I830_FENCE_START_MASK 0x07f80000
+
+#define FENCE_START_MASK 0x03F80000
+#define FENCE_X_MAJOR 0x00000000
+#define FENCE_Y_MAJOR 0x00001000
+#define FENCE_SIZE_MASK 0x00000700
+#define FENCE_SIZE_512K 0x00000000
+#define FENCE_SIZE_1M 0x00000100
+#define FENCE_SIZE_2M 0x00000200
+#define FENCE_SIZE_4M 0x00000300
+#define FENCE_SIZE_8M 0x00000400
+#define FENCE_SIZE_16M 0x00000500
+#define FENCE_SIZE_32M 0x00000600
+#define FENCE_SIZE_64M 0x00000700
+#define I915G_FENCE_SIZE_1M 0x00000000
+#define I915G_FENCE_SIZE_2M 0x00000100
+#define I915G_FENCE_SIZE_4M 0x00000200
+#define I915G_FENCE_SIZE_8M 0x00000300
+#define I915G_FENCE_SIZE_16M 0x00000400
+#define I915G_FENCE_SIZE_32M 0x00000500
+#define I915G_FENCE_SIZE_64M 0x00000600
+#define I915G_FENCE_SIZE_128M 0x00000700
+#define I965_FENCE_X_MAJOR 0x00000000
+#define I965_FENCE_Y_MAJOR 0x00000002
+#define FENCE_PITCH_1 0x00000000
+#define FENCE_PITCH_2 0x00000010
+#define FENCE_PITCH_4 0x00000020
+#define FENCE_PITCH_8 0x00000030
+#define FENCE_PITCH_16 0x00000040
+#define FENCE_PITCH_32 0x00000050
+#define FENCE_PITCH_64 0x00000060
+#define FENCE_VALID 0x00000001
+
+
+/* Registers to control page table, p274
+ */
+#define PGETBL_CTL 0x2020
+#define PGETBL_ADDR_MASK 0xFFFFF000
+#define PGETBL_ENABLE_MASK 0x00000001
+#define PGETBL_ENABLED 0x00000001
+/** Added in 965G, this field has the actual size of the global GTT */
+#define PGETBL_SIZE_MASK 0x0000000e
+#define PGETBL_SIZE_512KB (0 << 1)
+#define PGETBL_SIZE_256KB (1 << 1)
+#define PGETBL_SIZE_128KB (2 << 1)
+#define PGETBL_SIZE_1MB (3 << 1)
+#define PGETBL_SIZE_2MB (4 << 1)
+#define PGETBL_SIZE_1_5MB (5 << 1)
+#define G33_PGETBL_SIZE_MASK (3 << 8)
+#define G33_PGETBL_SIZE_1M (1 << 8)
+#define G33_PGETBL_SIZE_2M (2 << 8)
+
+#define I830_PTE_BASE 0x10000
+#define PTE_ADDRESS_MASK 0xfffff000
+#define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */
+#define PTE_MAPPING_TYPE_UNCACHED (0 << 1)
+#define PTE_MAPPING_TYPE_DCACHE (1 << 1) /* i830 only */
+#define PTE_MAPPING_TYPE_CACHED (3 << 1)
+#define PTE_MAPPING_TYPE_MASK (3 << 1)
+#define PTE_VALID (1 << 0)
+
+/** @defgroup PGE_ERR
+ * @{
+ */
+/** Page table debug register for i845 */
+#define PGE_ERR 0x2024
+#define PGE_ERR_ADDR_MASK 0xFFFFF000
+#define PGE_ERR_ID_MASK 0x00000038
+#define PGE_ERR_CAPTURE 0x00000000
+#define PGE_ERR_OVERLAY 0x00000008
+#define PGE_ERR_DISPLAY 0x00000010
+#define PGE_ERR_HOST 0x00000018
+#define PGE_ERR_RENDER 0x00000020
+#define PGE_ERR_BLITTER 0x00000028
+#define PGE_ERR_MAPPING 0x00000030
+#define PGE_ERR_CMD_PARSER 0x00000038
+#define PGE_ERR_TYPE_MASK 0x00000007
+#define PGE_ERR_INV_TABLE 0x00000000
+#define PGE_ERR_INV_PTE 0x00000001
+#define PGE_ERR_MIXED_TYPES 0x00000002
+#define PGE_ERR_PAGE_MISS 0x00000003
+#define PGE_ERR_ILLEGAL_TRX 0x00000004
+#define PGE_ERR_LOCAL_MEM 0x00000005
+#define PGE_ERR_TILED 0x00000006
+/** @} */
+
+/** @defgroup PGTBL_ER
+ * @{
+ */
+/** Page table debug register for i945 */
+# define PGTBL_ER 0x2024
+# define PGTBL_ERR_MT_TILING (1 << 27)
+# define PGTBL_ERR_MT_GTT_PTE (1 << 26)
+# define PGTBL_ERR_LC_TILING (1 << 25)
+# define PGTBL_ERR_LC_GTT_PTE (1 << 24)
+# define PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE (1 << 23)
+# define PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE (1 << 22)
+# define PGTBL_ERR_CS_VERTEXDATA_GTT_PTE (1 << 21)
+# define PGTBL_ERR_CS_INSTRUCTION_GTT_PTE (1 << 20)
+# define PGTBL_ERR_CS_GTT (1 << 19)
+# define PGTBL_ERR_OVERLAY_TILING (1 << 18)
+# define PGTBL_ERR_OVERLAY_GTT_PTE (1 << 16)
+# define PGTBL_ERR_DISPC_TILING (1 << 14)
+# define PGTBL_ERR_DISPC_GTT_PTE (1 << 12)
+# define PGTBL_ERR_DISPB_TILING (1 << 10)
+# define PGTBL_ERR_DISPB_GTT_PTE (1 << 8)
+# define PGTBL_ERR_DISPA_TILING (1 << 6)
+# define PGTBL_ERR_DISPA_GTT_PTE (1 << 4)
+# define PGTBL_ERR_HOST_PTE_DATA (1 << 1)
+# define PGTBL_ERR_HOST_GTT_PTE (1 << 0)
+/** @} */
+
+/* Ring buffer registers, p277, overview p19
+ */
+#define LP_RING 0x2030
+#define HP_RING 0x2040
+
+#define RING_TAIL 0x00
+#define TAIL_ADDR 0x000FFFF8
+#define I830_TAIL_MASK 0x001FFFF8
+
+#define RING_HEAD 0x04
+#define HEAD_WRAP_COUNT 0xFFE00000
+#define HEAD_WRAP_ONE 0x00200000
+#define HEAD_ADDR 0x001FFFFC
+#define I830_HEAD_MASK 0x001FFFFC
+
+#define RING_START 0x08
+#define START_ADDR 0x03FFFFF8
+#define I830_RING_START_MASK 0xFFFFF000
+
+#define RING_LEN 0x0C
+#define RING_NR_PAGES 0x001FF000
+#define I830_RING_NR_PAGES 0x001FF000
+#define RING_REPORT_MASK 0x00000006
+#define RING_REPORT_64K 0x00000002
+#define RING_REPORT_128K 0x00000004
+#define RING_NO_REPORT 0x00000000
+#define RING_VALID_MASK 0x00000001
+#define RING_VALID 0x00000001
+#define RING_INVALID 0x00000000
+
+
+
+/* BitBlt Instructions
+ *
+ * There are many more masks & ranges yet to add.
+ */
+#define BR00_BITBLT_CLIENT 0x40000000
+#define BR00_OP_COLOR_BLT 0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR00_OP_FULL_BLT 0x11400000
+#define BR00_OP_MONO_SRC_BLT 0x11800000
+#define BR00_OP_MONO_SRC_COPY_BLT 0x11000000
+#define BR00_OP_MONO_PAT_BLT 0x11C00000
+#define BR00_OP_MONO_SRC_COPY_IMMEDIATE_BLT (0x61 << 22)
+#define BR00_OP_TEXT_IMMEDIATE_BLT 0xc000000
+
+
+#define BR00_TPCY_DISABLE 0x00000000
+#define BR00_TPCY_ENABLE 0x00000010
+
+#define BR00_TPCY_ROP 0x00000000
+#define BR00_TPCY_NO_ROP 0x00000020
+#define BR00_TPCY_EQ 0x00000000
+#define BR00_TPCY_NOT_EQ 0x00000040
+
+#define BR00_PAT_MSB_FIRST 0x00000000 /* ? */
+
+#define BR00_PAT_VERT_ALIGN 0x000000e0
+
+#define BR00_LENGTH 0x0000000F
+
+#define BR09_DEST_ADDR 0x03FFFFFF
+
+#define BR11_SOURCE_PITCH 0x00003FFF
+
+#define BR12_SOURCE_ADDR 0x03FFFFFF
+
+#define BR13_SOLID_PATTERN 0x80000000
+#define BR13_RIGHT_TO_LEFT 0x40000000
+#define BR13_LEFT_TO_RIGHT 0x00000000
+#define BR13_MONO_TRANSPCY 0x20000000
+#define BR13_MONO_PATN_TRANS 0x10000000
+#define BR13_USE_DYN_DEPTH 0x04000000
+#define BR13_DYN_8BPP 0x00000000
+#define BR13_DYN_16BPP 0x01000000
+#define BR13_DYN_24BPP 0x02000000
+#define BR13_ROP_MASK 0x00FF0000
+#define BR13_DEST_PITCH 0x0000FFFF
+#define BR13_PITCH_SIGN_BIT 0x00008000
+
+#define BR14_DEST_HEIGHT 0xFFFF0000
+#define BR14_DEST_WIDTH 0x0000FFFF
+
+#define BR15_PATTERN_ADDR 0x03FFFFFF
+
+#define BR16_SOLID_PAT_COLOR 0x00FFFFFF
+#define BR16_BACKGND_PAT_CLR 0x00FFFFFF
+
+#define BR17_FGND_PAT_CLR 0x00FFFFFF
+
+#define BR18_SRC_BGND_CLR 0x00FFFFFF
+#define BR19_SRC_FGND_CLR 0x00FFFFFF
+
+
+/* Instruction parser instructions
+ */
+
+#define INST_PARSER_CLIENT 0x00000000
+#define INST_OP_FLUSH 0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+
+#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
+
+
+/* Registers in the i810 host-pci bridge pci config space which affect
+ * the i810 graphics operations.
+ */
+#define SMRAM_MISCC 0x70
+#define GMS 0x000000c0
+#define GMS_DISABLE 0x00000000
+#define GMS_ENABLE_BARE 0x00000040
+#define GMS_ENABLE_512K 0x00000080
+#define GMS_ENABLE_1M 0x000000c0
+#define USMM 0x00000030
+#define USMM_DISABLE 0x00000000
+#define USMM_TSEG_ZERO 0x00000010
+#define USMM_TSEG_512K 0x00000020
+#define USMM_TSEG_1M 0x00000030
+#define GFX_MEM_WIN_SIZE 0x00010000
+#define GFX_MEM_WIN_32M 0x00010000
+#define GFX_MEM_WIN_64M 0x00000000
+
+/* Overkill? I don't know. Need to figure out top of mem to make the
+ * SMRAM calculations come out. Linux seems to have problems
+ * detecting it all on its own, so this seems a reasonable double
+ * check to any user supplied 'mem=...' boot param.
+ *
+ * ... unfortunately this reg doesn't work according to spec on the
+ * test hardware.
+ */
+#define WHTCFG_PAMR_DRP 0x50
+#define SYS_DRAM_ROW_0_SHIFT 16
+#define SYS_DRAM_ROW_1_SHIFT 20
+#define DRAM_MASK 0x0f
+#define DRAM_VALUE_0 0
+#define DRAM_VALUE_1 8
+/* No 2 value defined */
+#define DRAM_VALUE_3 16
+#define DRAM_VALUE_4 16
+#define DRAM_VALUE_5 24
+#define DRAM_VALUE_6 32
+#define DRAM_VALUE_7 32
+#define DRAM_VALUE_8 48
+#define DRAM_VALUE_9 64
+#define DRAM_VALUE_A 64
+#define DRAM_VALUE_B 96
+#define DRAM_VALUE_C 128
+#define DRAM_VALUE_D 128
+#define DRAM_VALUE_E 192
+#define DRAM_VALUE_F 256 /* nice one, geezer */
+#define LM_FREQ_MASK 0x10
+#define LM_FREQ_133 0x10
+#define LM_FREQ_100 0x00
+
+
+
+
+/* These are 3d state registers, but the state is invarient, so we let
+ * the X server handle it:
+ */
+
+
+
+/* GFXRENDERSTATE_COLOR_CHROMA_KEY, p135
+ */
+#define GFX_OP_COLOR_CHROMA_KEY ((0x3<<29)|(0x1d<<24)|(0x2<<16)|0x1)
+#define CC1_UPDATE_KILL_WRITE (1<<28)
+#define CC1_ENABLE_KILL_WRITE (1<<27)
+#define CC1_DISABLE_KILL_WRITE 0
+#define CC1_UPDATE_COLOR_IDX (1<<26)
+#define CC1_UPDATE_CHROMA_LOW (1<<25)
+#define CC1_UPDATE_CHROMA_HI (1<<24)
+#define CC1_CHROMA_LOW_MASK ((1<<24)-1)
+#define CC2_COLOR_IDX_SHIFT 24
+#define CC2_COLOR_IDX_MASK (0xff<<24)
+#define CC2_CHROMA_HI_MASK ((1<<24)-1)
+
+
+#define GFX_CMD_CONTEXT_SEL ((0<<29)|(0x5<<23))
+#define CS_UPDATE_LOAD (1<<17)
+#define CS_UPDATE_USE (1<<16)
+#define CS_UPDATE_LOAD (1<<17)
+#define CS_LOAD_CTX0 0
+#define CS_LOAD_CTX1 (1<<8)
+#define CS_USE_CTX0 0
+#define CS_USE_CTX1 (1<<0)
+
+/* I810 LCD/TV registers */
+#define LCD_TV_HTOTAL 0x60000
+#define LCD_TV_C 0x60018
+#define LCD_TV_OVRACT 0x6001C
+
+#define LCD_TV_ENABLE (1 << 31)
+#define LCD_TV_VGAMOD (1 << 28)
+
+/* I830 CRTC registers */
+#define HTOTAL_A 0x60000
+#define HBLANK_A 0x60004
+#define HSYNC_A 0x60008
+#define VTOTAL_A 0x6000c
+#define VBLANK_A 0x60010
+#define VSYNC_A 0x60014
+#define PIPEASRC 0x6001c
+#define BCLRPAT_A 0x60020
+#define VSYNCSHIFT_A 0x60028
+
+#define HTOTAL_B 0x61000
+#define HBLANK_B 0x61004
+#define HSYNC_B 0x61008
+#define VTOTAL_B 0x6100c
+#define VBLANK_B 0x61010
+#define VSYNC_B 0x61014
+#define PIPEBSRC 0x6101c
+#define BCLRPAT_B 0x61020
+#define VSYNCSHIFT_B 0x61028
+
+#define HTOTAL_C 0x62000
+#define HBLANK_C 0x62004
+#define HSYNC_C 0x62008
+#define VTOTAL_C 0x6200c
+#define VBLANK_C 0x62010
+#define VSYNC_C 0x62014
+#define PIPECSRC 0x6201c
+#define BCLRPAT_C 0x62020
+#define VSYNCSHIFT_C 0x62028
+
+#define PP_STATUS 0x61200
+# define PP_ON (1 << 31)
+/**
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+# define PP_READY (1 << 30)
+# define PP_SEQUENCE_NONE (0 << 28)
+# define PP_SEQUENCE_ON (1 << 28)
+# define PP_SEQUENCE_OFF (2 << 28)
+# define PP_SEQUENCE_MASK 0x30000000
+
+#define PP_CONTROL 0x61204
+# define POWER_DOWN_ON_RESET (1 << 1)
+# define POWER_TARGET_ON (1 << 0)
+
+#define PP_ON_DELAYS 0x61208
+#define PP_OFF_DELAYS 0x6120c
+#define PP_DIVISOR 0x61210
+
+#define PFIT_CONTROL 0x61230
+# define PFIT_ENABLE (1 << 31)
+/* Pre-965 */
+# define VERT_INTERP_DISABLE (0 << 10)
+# define VERT_INTERP_BILINEAR (1 << 10)
+# define VERT_INTERP_MASK (3 << 10)
+# define VERT_AUTO_SCALE (1 << 9)
+# define HORIZ_INTERP_DISABLE (0 << 6)
+# define HORIZ_INTERP_BILINEAR (1 << 6)
+# define HORIZ_INTERP_MASK (3 << 6)
+# define HORIZ_AUTO_SCALE (1 << 5)
+# define PANEL_8TO6_DITHER_ENABLE (1 << 3)
+/* 965+ */
+# define PFIT_PIPE_MASK (3 << 29)
+# define PFIT_PIPE_SHIFT 29
+# define PFIT_SCALING_MODE_MASK (7 << 26)
+# define PFIT_SCALING_AUTO (0 << 26)
+# define PFIT_SCALING_PROGRAMMED (1 << 26)
+# define PFIT_SCALING_PILLAR (2 << 26)
+# define PFIT_SCALING_LETTER (3 << 26)
+# define PFIT_FILTER_SELECT_MASK (3 << 24)
+# define PFIT_FILTER_FUZZY (0 << 24)
+# define PFIT_FILTER_CRISP (1 << 24)
+# define PFIT_FILTER_MEDIAN (2 << 24)
+
+#define PFIT_PGM_RATIOS 0x61234
+/* Pre-965 */
+# define PFIT_VERT_SCALE_SHIFT 20
+# define PFIT_VERT_SCALE_MASK 0xfff00000
+# define PFIT_HORIZ_SCALE_SHIFT 4
+# define PFIT_HORIZ_SCALE_MASK 0x0000fff0
+/* 965+ */
+# define PFIT_VERT_SCALE_SHIFT_965 16
+# define PFIT_VERT_SCALE_MASK_965 0x1fff0000
+# define PFIT_HORIZ_SCALE_SHIFT_965 0
+# define PFIT_HORIZ_SCALE_MASK_965 0x00001fff
+
+#define DPLL_A 0x06014
+#define DPLL_B 0x06018
+# define DPLL_VCO_ENABLE (1 << 31)
+# define DPLL_DVO_HIGH_SPEED (1 << 30)
+# define DPLL_SYNCLOCK_ENABLE (1 << 29)
+# define DPLL_VGA_MODE_DIS (1 << 28)
+# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
+# define DPLLB_MODE_LVDS (2 << 26) /* i915 */
+# define DPLL_MODE_MASK (3 << 26)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
+# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK_IGD 0x00ff8000 /* IGD */
+/**
+ * The i830 generation, in DAC/serial mode, defines p1 as two plus this
+ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
+/**
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
+# define DPLL_FPA01_P1_POST_DIV_SHIFT 16
+# define DPLL_FPA01_P1_POST_DIV_SHIFT_IGD 15
+# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */
+# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
+# define PLL_REF_INPUT_DREFCLK (0 << 13)
+# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */
+# define PLL_REF_INPUT_SUPER_SSC (1 << 13) /* Ironlake: 120M SSC */
+# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */
+# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
+# define PLL_REF_INPUT_MASK (3 << 13)
+# define PLL_REF_INPUT_DMICLK (5 << 13) /* Ironlake: DMI refclk */
+# define PLL_LOAD_PULSE_PHASE_SHIFT 9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+# define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
+/* Ironlake */
+# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9
+# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9)
+# define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x)-1)<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT)
+# define DPLL_FPA1_P1_POST_DIV_SHIFT 0
+# define DPLL_FPA1_P1_POST_DIV_MASK 0xff
+
+/**
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+# define SDVO_MULTIPLIER_MASK 0x000000ff
+# define SDVO_MULTIPLIER_SHIFT_HIRES 4
+# define SDVO_MULTIPLIER_SHIFT_VGA 0
+
+/** @defgroup DPLL_MD
+ * @{
+ */
+/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_A_MD 0x0601c
+/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_B_MD 0x06020
+/**
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1. Must be set to 1 pixel for SDVO.
+ */
+# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
+# define DPLL_MD_UDI_DIVIDER_SHIFT 24
+/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
+# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
+/**
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock. At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
+# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
+/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
+# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
+/** @} */
+
+#define DPLL_TEST 0x606c
+# define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
+# define DPLLB_TEST_SDVO_DIV_2 (1 << 22)
+# define DPLLB_TEST_SDVO_DIV_4 (2 << 22)
+# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22)
+# define DPLLB_TEST_N_BYPASS (1 << 19)
+# define DPLLB_TEST_M_BYPASS (1 << 18)
+# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16)
+# define DPLLA_TEST_N_BYPASS (1 << 3)
+# define DPLLA_TEST_M_BYPASS (1 << 2)
+# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
+
+#define D_STATE 0x6104
+#define DSPCLK_GATE_D 0x6200
+# define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */
+# define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */
+# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */
+# define VRDUNIT_CLOCK_GATE_DISABLE (1 << 27) /* 965 */
+# define AUDUNIT_CLOCK_GATE_DISABLE (1 << 26) /* 965 */
+# define DPUNIT_A_CLOCK_GATE_DISABLE (1 << 25) /* 965 */
+# define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24) /* 965 */
+# define TVRUNIT_CLOCK_GATE_DISABLE (1 << 23) /* 915-945 */
+# define TVCUNIT_CLOCK_GATE_DISABLE (1 << 22) /* 915-945 */
+# define TVFUNIT_CLOCK_GATE_DISABLE (1 << 21) /* 915-945 */
+# define TVEUNIT_CLOCK_GATE_DISABLE (1 << 20) /* 915-945 */
+# define DVSUNIT_CLOCK_GATE_DISABLE (1 << 19) /* 915-945 */
+# define DSSUNIT_CLOCK_GATE_DISABLE (1 << 18) /* 915-945 */
+# define DDBUNIT_CLOCK_GATE_DISABLE (1 << 17) /* 915-945 */
+# define DPRUNIT_CLOCK_GATE_DISABLE (1 << 16) /* 915-945 */
+# define DPFUNIT_CLOCK_GATE_DISABLE (1 << 15) /* 915-945 */
+# define DPBMUNIT_CLOCK_GATE_DISABLE (1 << 14) /* 915-945 */
+# define DPLSUNIT_CLOCK_GATE_DISABLE (1 << 13) /* 915-945 */
+# define DPLUNIT_CLOCK_GATE_DISABLE (1 << 12) /* 915-945 */
+# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11)
+# define DPBUNIT_CLOCK_GATE_DISABLE (1 << 10)
+# define DCUNIT_CLOCK_GATE_DISABLE (1 << 9)
+# define DPUNIT_CLOCK_GATE_DISABLE (1 << 8)
+# define VRUNIT_CLOCK_GATE_DISABLE (1 << 7) /* 915+: reserved */
+# define OVHUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 830-865 */
+# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */
+# define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5)
+# define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4)
+/**
+ * This bit must be set on the 830 to prevent hangs when turning off the
+ * overlay scaler.
+ */
+# define OVRUNIT_CLOCK_GATE_DISABLE (1 << 3)
+# define OVCUNIT_CLOCK_GATE_DISABLE (1 << 2)
+# define OVUUNIT_CLOCK_GATE_DISABLE (1 << 1)
+# define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */
+# define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */
+
+#define RENCLK_GATE_D1 0x6204
+# define BLITTER_CLOCK_GATE_DISABLE (1 << 13) /* 945GM only */
+# define MPEG_CLOCK_GATE_DISABLE (1 << 12) /* 945GM only */
+# define PC_FE_CLOCK_GATE_DISABLE (1 << 11)
+# define PC_BE_CLOCK_GATE_DISABLE (1 << 10)
+# define WINDOWER_CLOCK_GATE_DISABLE (1 << 9)
+# define INTERPOLATOR_CLOCK_GATE_DISABLE (1 << 8)
+# define COLOR_CALCULATOR_CLOCK_GATE_DISABLE (1 << 7)
+# define MOTION_COMP_CLOCK_GATE_DISABLE (1 << 6)
+# define MAG_CLOCK_GATE_DISABLE (1 << 5)
+/** This bit must be unset on 855,865 */
+# define MECI_CLOCK_GATE_DISABLE (1 << 4)
+# define DCMP_CLOCK_GATE_DISABLE (1 << 3)
+# define MEC_CLOCK_GATE_DISABLE (1 << 2)
+# define MECO_CLOCK_GATE_DISABLE (1 << 1)
+/** This bit must be set on 855,865. */
+# define SV_CLOCK_GATE_DISABLE (1 << 0)
+# define I915_MPEG_CLOCK_GATE_DISABLE (1 << 16)
+# define I915_VLD_IP_PR_CLOCK_GATE_DISABLE (1 << 15)
+# define I915_MOTION_COMP_CLOCK_GATE_DISABLE (1 << 14)
+# define I915_BD_BF_CLOCK_GATE_DISABLE (1 << 13)
+# define I915_SF_SE_CLOCK_GATE_DISABLE (1 << 12)
+# define I915_WM_CLOCK_GATE_DISABLE (1 << 11)
+# define I915_IZ_CLOCK_GATE_DISABLE (1 << 10)
+# define I915_PI_CLOCK_GATE_DISABLE (1 << 9)
+# define I915_DI_CLOCK_GATE_DISABLE (1 << 8)
+# define I915_SH_SV_CLOCK_GATE_DISABLE (1 << 7)
+# define I915_PL_DG_QC_FT_CLOCK_GATE_DISABLE (1 << 6)
+# define I915_SC_CLOCK_GATE_DISABLE (1 << 5)
+# define I915_FL_CLOCK_GATE_DISABLE (1 << 4)
+# define I915_DM_CLOCK_GATE_DISABLE (1 << 3)
+# define I915_PS_CLOCK_GATE_DISABLE (1 << 2)
+# define I915_CC_CLOCK_GATE_DISABLE (1 << 1)
+# define I915_BY_CLOCK_GATE_DISABLE (1 << 0)
+
+# define I965_RCZ_CLOCK_GATE_DISABLE (1 << 30)
+/** This bit must always be set on 965G/965GM */
+# define I965_RCC_CLOCK_GATE_DISABLE (1 << 29)
+# define I965_RCPB_CLOCK_GATE_DISABLE (1 << 28)
+# define I965_DAP_CLOCK_GATE_DISABLE (1 << 27)
+# define I965_ROC_CLOCK_GATE_DISABLE (1 << 26)
+# define I965_GW_CLOCK_GATE_DISABLE (1 << 25)
+# define I965_TD_CLOCK_GATE_DISABLE (1 << 24)
+/** This bit must always be set on 965G */
+# define I965_ISC_CLOCK_GATE_DISABLE (1 << 23)
+# define I965_IC_CLOCK_GATE_DISABLE (1 << 22)
+# define I965_EU_CLOCK_GATE_DISABLE (1 << 21)
+# define I965_IF_CLOCK_GATE_DISABLE (1 << 20)
+# define I965_TC_CLOCK_GATE_DISABLE (1 << 19)
+# define I965_SO_CLOCK_GATE_DISABLE (1 << 17)
+# define I965_FBC_CLOCK_GATE_DISABLE (1 << 16)
+# define I965_MARI_CLOCK_GATE_DISABLE (1 << 15)
+# define I965_MASF_CLOCK_GATE_DISABLE (1 << 14)
+# define I965_MAWB_CLOCK_GATE_DISABLE (1 << 13)
+# define I965_EM_CLOCK_GATE_DISABLE (1 << 12)
+# define I965_UC_CLOCK_GATE_DISABLE (1 << 11)
+# define I965_SI_CLOCK_GATE_DISABLE (1 << 6)
+# define I965_MT_CLOCK_GATE_DISABLE (1 << 5)
+# define I965_PL_CLOCK_GATE_DISABLE (1 << 4)
+# define I965_DG_CLOCK_GATE_DISABLE (1 << 3)
+# define I965_QC_CLOCK_GATE_DISABLE (1 << 2)
+# define I965_FT_CLOCK_GATE_DISABLE (1 << 1)
+# define I965_DM_CLOCK_GATE_DISABLE (1 << 0)
+
+#define RENCLK_GATE_D2 0x6208
+#define VF_UNIT_CLOCK_GATE_DISABLE (1 << 9)
+#define GS_UNIT_CLOCK_GATE_DISABLE (1 << 7)
+#define CL_UNIT_CLOCK_GATE_DISABLE (1 << 6)
+#define RAMCLK_GATE_D 0x6210 /* CRL only */
+#define DEUC 0x6214 /* CRL only */
+
+/*
+ * This is a PCI config space register to manipulate backlight brightness
+ * It is used when the BLM_LEGACY_MODE is turned on. When enabled, the first
+ * byte of this config register sets brightness within the range from
+ * 0 to 0xff
+ */
+#define LEGACY_BACKLIGHT_BRIGHTNESS 0xf4
+
+#define BLC_PWM_CTL 0x61254
+#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
+#define BACKLIGHT_MODULATION_FREQ_SHIFT2 (16)
+/**
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
+#define BACKLIGHT_MODULATION_FREQ_MASK2 (0xffff << 16)
+#define BLM_LEGACY_MODE (1 << 16)
+
+/**
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
+#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
+
+/* On 965+ backlight control is in another register */
+#define BLC_PWM_CTL2 0x61250
+#define BLM_LEGACY_MODE2 (1 << 30)
+
+#define BLM_CTL 0x61260
+#define BLM_THRESHOLD_0 0x61270
+#define BLM_THRESHOLD_1 0x61274
+#define BLM_THRESHOLD_2 0x61278
+#define BLM_THRESHOLD_3 0x6127c
+#define BLM_THRESHOLD_4 0x61280
+#define BLM_THRESHOLD_5 0x61284
+
+#define BLM_ACCUMULATOR_0 0x61290
+#define BLM_ACCUMULATOR_1 0x61294
+#define BLM_ACCUMULATOR_2 0x61298
+#define BLM_ACCUMULATOR_3 0x6129c
+#define BLM_ACCUMULATOR_4 0x612a0
+#define BLM_ACCUMULATOR_5 0x612a4
+
+#define FPA0 0x06040
+#define FPA1 0x06044
+#define FPB0 0x06048
+#define FPB1 0x0604c
+# define FP_N_DIV_MASK 0x003f0000
+# define FP_N_IGD_DIV_MASK 0x00ff0000
+# define FP_N_DIV_SHIFT 16
+# define FP_M1_DIV_MASK 0x00003f00
+# define FP_M1_DIV_SHIFT 8
+# define FP_M2_DIV_MASK 0x0000003f
+# define FP_M2_IGD_DIV_MASK 0x000000ff
+# define FP_M2_DIV_SHIFT 0
+
+#define PORT_HOTPLUG_EN 0x61110
+# define HDMIB_HOTPLUG_INT_EN (1 << 29)
+# define HDMIC_HOTPLUG_INT_EN (1 << 28)
+# define HDMID_HOTPLUG_INT_EN (1 << 27)
+# define SDVOB_HOTPLUG_INT_EN (1 << 26)
+# define SDVOC_HOTPLUG_INT_EN (1 << 25)
+# define TV_HOTPLUG_INT_EN (1 << 18)
+# define CRT_HOTPLUG_INT_EN (1 << 9)
+# define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
+/* must use period 64 on GM45 according to docs */
+# define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8)
+# define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7)
+# define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5)
+# define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5)
+# define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4)
+# define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4)
+# define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
+# define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
+# define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
+# define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
+
+#define PORT_HOTPLUG_STAT 0x61114
+# define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
+# define HDMIC_HOTPLUG_INT_STATUS (1 << 28)
+# define HDMID_HOTPLUG_INT_STATUS (1 << 27)
+# define CRT_HOTPLUG_INT_STATUS (1 << 11)
+# define TV_HOTPLUG_INT_STATUS (1 << 10)
+# define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
+# define CRT_HOTPLUG_MONITOR_COLOR (3 << 8)
+# define CRT_HOTPLUG_MONITOR_MONO (2 << 8)
+# define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
+# define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
+# define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
+
+#define SDVOB 0x61140
+#define SDVOC 0x61160
+#define SDVO_ENABLE (1 << 31)
+#define SDVO_PIPE_B_SELECT (1 << 30)
+#define SDVO_STALL_SELECT (1 << 29)
+#define SDVO_INTERRUPT_ENABLE (1 << 26)
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+#define SDVO_PORT_MULTIPLY_MASK (7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT 23
+#define SDVO_PHASE_SELECT_MASK (15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
+#define SDVOC_GANG_MODE (1 << 16)
+#define SDVO_ENCODING_SDVO (0x0 << 10)
+#define SDVO_ENCODING_HDMI (0x2 << 10)
+/** Requird for HDMI operation */
+#define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9)
+#define SDVO_BORDER_ENABLE (1 << 7)
+#define SDVO_AUDIO_ENABLE (1 << 6)
+/** New with 965, default is to be set */
+#define SDVO_VSYNC_ACTIVE_HIGH (1 << 4)
+/** New with 965, default is to be set */
+#define SDVO_HSYNC_ACTIVE_HIGH (1 << 3)
+/** 915/945 only, read-only bit */
+#define SDVOB_PCIE_CONCURRENCY (1 << 3)
+#define SDVO_DETECTED (1 << 2)
+/* Bits to be preserved when writing */
+#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14))
+#define SDVOC_PRESERVE_MASK (1 << 17)
+
+#define UDIB_SVB_SHB_CODES 0x61144
+#define UDIB_SHA_BLANK_CODES 0x61148
+#define UDIB_START_END_FILL_CODES 0x6114c
+
+
+#define SDVOUDI 0x61150
+
+#define I830_HTOTAL_MASK 0xfff0000
+#define I830_HACTIVE_MASK 0x7ff
+
+#define I830_HBLANKEND_MASK 0xfff0000
+#define I830_HBLANKSTART_MASK 0xfff
+
+#define I830_HSYNCEND_MASK 0xfff0000
+#define I830_HSYNCSTART_MASK 0xfff
+
+#define I830_VTOTAL_MASK 0xfff0000
+#define I830_VACTIVE_MASK 0x7ff
+
+#define I830_VBLANKEND_MASK 0xfff0000
+#define I830_VBLANKSTART_MASK 0xfff
+
+#define I830_VSYNCEND_MASK 0xfff0000
+#define I830_VSYNCSTART_MASK 0xfff
+
+#define I830_PIPEA_HORZ_MASK 0x7ff0000
+#define I830_PIPEA_VERT_MASK 0x7ff
+
+#define ADPA 0x61100
+#define ADPA_DAC_ENABLE (1<<31)
+#define ADPA_DAC_DISABLE 0
+#define ADPA_PIPE_SELECT_MASK (1<<30)
+#define ADPA_PIPE_A_SELECT 0
+#define ADPA_PIPE_B_SELECT (1<<30)
+#define ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define ADPA_SETS_HVPOLARITY 0
+#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define ADPA_VSYNC_CNTL_ENABLE 0
+#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define ADPA_HSYNC_CNTL_ENABLE 0
+#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
+#define ADPA_VSYNC_ACTIVE_LOW 0
+#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
+#define ADPA_HSYNC_ACTIVE_LOW 0
+
+#define PCH_DSPCLK_GATE_D 0x42020
+#define PCH_DSPRAMCLK_GATE_D 0x42024
+#define PCH_3DCGDIS0 0x46020
+#define PCH_3DCGDIS1 0x46024
+#define PCH_3DRAMCGDIS0 0x46028
+#define SOUTH_DSPCLK_GATE_D 0xc2020
+
+#define CPU_eDP_A 0x64000
+#define PCH_DP_B 0xe4100
+#define PCH_DP_C 0xe4200
+#define PCH_DP_D 0xe4300
+
+#define DVOA 0x61120
+#define DVOB 0x61140
+#define DVOC 0x61160
+#define DVO_ENABLE (1 << 31)
+#define DVO_PIPE_B_SELECT (1 << 30)
+#define DVO_PIPE_STALL_UNUSED (0 << 28)
+#define DVO_PIPE_STALL (1 << 28)
+#define DVO_PIPE_STALL_TV (2 << 28)
+#define DVO_PIPE_STALL_MASK (3 << 28)
+#define DVO_USE_VGA_SYNC (1 << 15)
+#define DVO_DATA_ORDER_I740 (0 << 14)
+#define DVO_DATA_ORDER_FP (1 << 14)
+#define DVO_VSYNC_DISABLE (1 << 11)
+#define DVO_HSYNC_DISABLE (1 << 10)
+#define DVO_VSYNC_TRISTATE (1 << 9)
+#define DVO_HSYNC_TRISTATE (1 << 8)
+#define DVO_BORDER_ENABLE (1 << 7)
+#define DVO_DATA_ORDER_GBRG (1 << 6)
+#define DVO_DATA_ORDER_RGGB (0 << 6)
+#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6)
+#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6)
+#define DVO_VSYNC_ACTIVE_HIGH (1 << 4)
+#define DVO_HSYNC_ACTIVE_HIGH (1 << 3)
+#define DVO_BLANK_ACTIVE_HIGH (1 << 2)
+#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */
+#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */
+#define DVO_PRESERVE_MASK (0x7<<24)
+
+#define DVOA_SRCDIM 0x61124
+#define DVOB_SRCDIM 0x61144
+#define DVOC_SRCDIM 0x61164
+#define DVO_SRCDIM_HORIZONTAL_SHIFT 12
+#define DVO_SRCDIM_VERTICAL_SHIFT 0
+
+/** @defgroup LVDS
+ * @{
+ */
+/**
+ * This register controls the LVDS output enable, pipe selection, and data
+ * format selection.
+ *
+ * All of the clock/data pairs are force powered down by power sequencing.
+ */
+#define LVDS 0x61180
+/**
+ * Enables the LVDS port. This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
+# define LVDS_PORT_EN (1 << 31)
+/** Selects pipe B for LVDS data. Must be set on pre-965. */
+# define LVDS_PIPEB_SELECT (1 << 30)
+
+/* on 965, dithering is enabled in this register, not PFIT_CONTROL */
+# define LVDS_DITHER_ENABLE (1 << 25)
+
+/*
+ * Selects between .0 and .1 formats:
+ *
+ * 0 = 1x18.0, 2x18.0, 1x24.0 or 2x24.0
+ * 1 = 1x24.1 or 2x24.1
+ */
+# define LVDS_DATA_FORMAT_DOT_ONE (1 << 24)
+
+/* Using LE instead of HS on second channel control signal */
+# define LVDS_LE_CONTROL_ENABLE (1 << 23)
+
+/* Using LF instead of VS on second channel control signal */
+# define LVDS_LF_CONTROL_ENABLE (1 << 22)
+
+/* invert vsync signal polarity */
+# define LVDS_VSYNC_POLARITY_INVERT (1 << 21)
+
+/* invert hsync signal polarity */
+# define LVDS_HSYNC_POLARITY_INVERT (1 << 20)
+
+/* invert display enable signal polarity */
+# define LVDS_DE_POLARITY_INVERT (1 << 19)
+
+/*
+ * Control signals for second channel, ignored in single channel modes
+ */
+
+/* send DE, HS, VS on second channel */
+# define LVDS_SECOND_CHANNEL_DE_HS_VS (0 << 17)
+
+# define LVDS_SECOND_CHANNEL_RESERVED (1 << 17)
+
+/* Send zeros instead of DE, HS, VS on second channel */
+# define LVDS_SECOND_CHANNEL_ZEROS (2 << 17)
+
+/* Set DE=0, HS=LE, VS=LF on second channel */
+# define LVDS_SECOND_CHANNEL_HS_VS (3 << 17)
+
+/*
+ * Send duplicate data for channel reserved bits, otherwise send zeros
+ */
+# define LVDS_CHANNEL_DUP_RESERVED (1 << 16)
+
+/*
+ * Enable border for unscaled (or aspect-scaled) display
+ */
+# define LVDS_BORDER_ENABLE (1 << 15)
+
+/*
+ * Tri-state the LVDS buffers when powered down, otherwise
+ * they are set to 0V
+ */
+# define LVDS_POWER_DOWN_TRI_STATE (1 << 10)
+
+/**
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+# define LVDS_A0A2_CLKA_POWER_MASK (3 << 8)
+# define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8)
+# define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
+/**
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+# define LVDS_A3_POWER_MASK (3 << 6)
+# define LVDS_A3_POWER_DOWN (0 << 6)
+# define LVDS_A3_POWER_UP (3 << 6)
+/**
+ * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+# define LVDS_CLKB_POWER_MASK (3 << 4)
+# define LVDS_CLKB_POWER_DOWN (0 << 4)
+# define LVDS_CLKB_POWER_UP (3 << 4)
+
+/**
+ * Controls the B0-B3 data pairs. This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode. The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+# define LVDS_B0B3_POWER_MASK (3 << 2)
+# define LVDS_B0B3_POWER_DOWN (0 << 2)
+# define LVDS_B0B3_POWER_UP (3 << 2)
+
+/** @} */
+
+#define DP_B 0x64100
+#define DPB_AUX_CH_CTL 0x64110
+#define DPB_AUX_CH_DATA1 0x64114
+#define DPB_AUX_CH_DATA2 0x64118
+#define DPB_AUX_CH_DATA3 0x6411c
+#define DPB_AUX_CH_DATA4 0x64120
+#define DPB_AUX_CH_DATA5 0x64124
+
+#define DP_C 0x64200
+#define DPC_AUX_CH_CTL 0x64210
+#define DPC_AUX_CH_DATA1 0x64214
+#define DPC_AUX_CH_DATA2 0x64218
+#define DPC_AUX_CH_DATA3 0x6421c
+#define DPC_AUX_CH_DATA4 0x64220
+#define DPC_AUX_CH_DATA5 0x64224
+
+#define DP_D 0x64300
+#define DPD_AUX_CH_CTL 0x64310
+#define DPD_AUX_CH_DATA1 0x64314
+#define DPD_AUX_CH_DATA2 0x64318
+#define DPD_AUX_CH_DATA3 0x6431c
+#define DPD_AUX_CH_DATA4 0x64320
+#define DPD_AUX_CH_DATA5 0x64324
+
+/*
+ * Two channel clock control. Turn this on if you need clkb for two channel mode
+ * Overridden by global LVDS power sequencing
+ */
+
+/* clkb off */
+# define LVDS_CLKB_POWER_DOWN (0 << 4)
+
+/* powered up, but clkb forced to 0 */
+# define LVDS_CLKB_POWER_PARTIAL (1 << 4)
+
+/* clock B running */
+# define LVDS_CLKB_POWER_UP (3 << 4)
+
+/*
+ * Two channel mode B0-B2 control. Sets state when power is on.
+ * Set to POWER_DOWN in single channel mode, other settings enable
+ * two channel mode. The CLKB power control controls whether that clock
+ * is enabled during two channel mode.
+ *
+ */
+/* Everything is off, including B3 and CLKB */
+# define LVDS_B_POWER_DOWN (0 << 2)
+
+/* B0, B1, B2 and data lines forced to 0. timing is active */
+# define LVDS_B_POWER_PARTIAL (1 << 2)
+
+/* data lines active (both timing and colour) */
+# define LVDS_B_POWER_UP (3 << 2)
+
+/** @defgroup TV_CTL
+ * @{
+ */
+#define TV_CTL 0x68000
+/** Enables the TV encoder */
+# define TV_ENC_ENABLE (1 << 31)
+/** Sources the TV encoder input from pipe B instead of A. */
+# define TV_ENC_PIPEB_SELECT (1 << 30)
+/** Outputs composite video (DAC A only) */
+# define TV_ENC_OUTPUT_COMPOSITE (0 << 28)
+/** Outputs SVideo video (DAC B/C) */
+# define TV_ENC_OUTPUT_SVIDEO (1 << 28)
+/** Outputs Component video (DAC A/B/C) */
+# define TV_ENC_OUTPUT_COMPONENT (2 << 28)
+/** Outputs Composite and SVideo (DAC A/B/C) */
+# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE (3 << 28)
+# define TV_TRILEVEL_SYNC (1 << 21)
+/** Enables slow sync generation (945GM only) */
+# define TV_SLOW_SYNC (1 << 20)
+/** Selects 4x oversampling for 480i and 576p */
+# define TV_OVERSAMPLE_4X (0 << 18)
+/** Selects 2x oversampling for 720p and 1080i */
+# define TV_OVERSAMPLE_2X (1 << 18)
+/** Selects no oversampling for 1080p */
+# define TV_OVERSAMPLE_NONE (2 << 18)
+/** Selects 8x oversampling */
+# define TV_OVERSAMPLE_8X (3 << 18)
+/** Selects progressive mode rather than interlaced */
+# define TV_PROGRESSIVE (1 << 17)
+/** Sets the colorburst to PAL mode. Required for non-M PAL modes. */
+# define TV_PAL_BURST (1 << 16)
+/** Field for setting delay of Y compared to C */
+# define TV_YC_SKEW_MASK (7 << 12)
+/** Enables a fix for 480p/576p standard definition modes on the 915GM only */
+# define TV_ENC_SDP_FIX (1 << 11)
+/**
+ * Enables a fix for the 915GM only.
+ *
+ * Not sure what it does.
+ */
+# define TV_ENC_C0_FIX (1 << 10)
+/** Bits that must be preserved by software */
+# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf)
+# define TV_FUSE_STATE_MASK (3 << 4)
+/** Read-only state that reports all features enabled */
+# define TV_FUSE_STATE_ENABLED (0 << 4)
+/** Read-only state that reports that Macrovision is disabled in hardware*/
+# define TV_FUSE_STATE_NO_MACROVISION (1 << 4)
+/** Read-only state that reports that TV-out is disabled in hardware. */
+# define TV_FUSE_STATE_DISABLED (2 << 4)
+/** Normal operation */
+# define TV_TEST_MODE_NORMAL (0 << 0)
+/** Encoder test pattern 1 - combo pattern */
+# define TV_TEST_MODE_PATTERN_1 (1 << 0)
+/** Encoder test pattern 2 - full screen vertical 75% color bars */
+# define TV_TEST_MODE_PATTERN_2 (2 << 0)
+/** Encoder test pattern 3 - full screen horizontal 75% color bars */
+# define TV_TEST_MODE_PATTERN_3 (3 << 0)
+/** Encoder test pattern 4 - random noise */
+# define TV_TEST_MODE_PATTERN_4 (4 << 0)
+/** Encoder test pattern 5 - linear color ramps */
+# define TV_TEST_MODE_PATTERN_5 (5 << 0)
+/**
+ * This test mode forces the DACs to 50% of full output.
+ *
+ * This is used for load detection in combination with TVDAC_SENSE_MASK
+ */
+# define TV_TEST_MODE_MONITOR_DETECT (7 << 0)
+# define TV_TEST_MODE_MASK (7 << 0)
+/** @} */
+
+/** @defgroup TV_DAC
+ * @{
+ */
+#define TV_DAC 0x68004
+/**
+ * Reports that DAC state change logic has reported change (RO).
+ *
+ * This gets cleared when TV_DAC_STATE_EN is cleared
+*/
+# define TVDAC_STATE_CHG (1 << 31)
+# define TVDAC_SENSE_MASK (7 << 28)
+/** Reports that DAC A voltage is above the detect threshold */
+# define TVDAC_A_SENSE (1 << 30)
+/** Reports that DAC B voltage is above the detect threshold */
+# define TVDAC_B_SENSE (1 << 29)
+/** Reports that DAC C voltage is above the detect threshold */
+# define TVDAC_C_SENSE (1 << 28)
+/**
+ * Enables DAC state detection logic, for load-based TV detection.
+ *
+ * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set
+ * to off, for load detection to work.
+ */
+# define TVDAC_STATE_CHG_EN (1 << 27)
+/** Sets the DAC A sense value to high */
+# define TVDAC_A_SENSE_CTL (1 << 26)
+/** Sets the DAC B sense value to high */
+# define TVDAC_B_SENSE_CTL (1 << 25)
+/** Sets the DAC C sense value to high */
+# define TVDAC_C_SENSE_CTL (1 << 24)
+/** Overrides the ENC_ENABLE and DAC voltage levels */
+# define DAC_CTL_OVERRIDE (1 << 7)
+/** Sets the slew rate. Must be preserved in software */
+# define ENC_TVDAC_SLEW_FAST (1 << 6)
+# define DAC_A_1_3_V (0 << 4)
+# define DAC_A_1_1_V (1 << 4)
+# define DAC_A_0_7_V (2 << 4)
+# define DAC_A_OFF (3 << 4)
+# define DAC_B_1_3_V (0 << 2)
+# define DAC_B_1_1_V (1 << 2)
+# define DAC_B_0_7_V (2 << 2)
+# define DAC_B_OFF (3 << 2)
+# define DAC_C_1_3_V (0 << 0)
+# define DAC_C_1_1_V (1 << 0)
+# define DAC_C_0_7_V (2 << 0)
+# define DAC_C_OFF (3 << 0)
+/** @} */
+
+/**
+ * CSC coefficients are stored in a floating point format with 9 bits of
+ * mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n,
+ * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
+ * -1 (0x3) being the only legal negative value.
+ */
+#define TV_CSC_Y 0x68010
+# define TV_RY_MASK 0x07ff0000
+# define TV_RY_SHIFT 16
+# define TV_GY_MASK 0x00000fff
+# define TV_GY_SHIFT 0
+
+#define TV_CSC_Y2 0x68014
+# define TV_BY_MASK 0x07ff0000
+# define TV_BY_SHIFT 16
+/**
+ * Y attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AY_MASK 0x000003ff
+# define TV_AY_SHIFT 0
+
+#define TV_CSC_U 0x68018
+# define TV_RU_MASK 0x07ff0000
+# define TV_RU_SHIFT 16
+# define TV_GU_MASK 0x000007ff
+# define TV_GU_SHIFT 0
+
+#define TV_CSC_U2 0x6801c
+# define TV_BU_MASK 0x07ff0000
+# define TV_BU_SHIFT 16
+/**
+ * U attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AU_MASK 0x000003ff
+# define TV_AU_SHIFT 0
+
+#define TV_CSC_V 0x68020
+# define TV_RV_MASK 0x0fff0000
+# define TV_RV_SHIFT 16
+# define TV_GV_MASK 0x000007ff
+# define TV_GV_SHIFT 0
+
+#define TV_CSC_V2 0x68024
+# define TV_BV_MASK 0x07ff0000
+# define TV_BV_SHIFT 16
+/**
+ * V attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AV_MASK 0x000007ff
+# define TV_AV_SHIFT 0
+
+/** @defgroup TV_CSC_KNOBS
+ * @{
+ */
+#define TV_CLR_KNOBS 0x68028
+/** 2s-complement brightness adjustment */
+# define TV_BRIGHTNESS_MASK 0xff000000
+# define TV_BRIGHTNESS_SHIFT 24
+/** Contrast adjustment, as a 2.6 unsigned floating point number */
+# define TV_CONTRAST_MASK 0x00ff0000
+# define TV_CONTRAST_SHIFT 16
+/** Saturation adjustment, as a 2.6 unsigned floating point number */
+# define TV_SATURATION_MASK 0x0000ff00
+# define TV_SATURATION_SHIFT 8
+/** Hue adjustment, as an integer phase angle in degrees */
+# define TV_HUE_MASK 0x000000ff
+# define TV_HUE_SHIFT 0
+/** @} */
+
+/** @defgroup TV_CLR_LEVEL
+ * @{
+ */
+#define TV_CLR_LEVEL 0x6802c
+/** Controls the DAC level for black */
+# define TV_BLACK_LEVEL_MASK 0x01ff0000
+# define TV_BLACK_LEVEL_SHIFT 16
+/** Controls the DAC level for blanking */
+# define TV_BLANK_LEVEL_MASK 0x000001ff
+# define TV_BLANK_LEVEL_SHIFT 0
+/* @} */
+
+/** @defgroup TV_H_CTL_1
+ * @{
+ */
+#define TV_H_CTL_1 0x68030
+/** Number of pixels in the hsync. */
+# define TV_HSYNC_END_MASK 0x1fff0000
+# define TV_HSYNC_END_SHIFT 16
+/** Total number of pixels minus one in the line (display and blanking). */
+# define TV_HTOTAL_MASK 0x00001fff
+# define TV_HTOTAL_SHIFT 0
+/** @} */
+
+/** @defgroup TV_H_CTL_2
+ * @{
+ */
+#define TV_H_CTL_2 0x68034
+/** Enables the colorburst (needed for non-component color) */
+# define TV_BURST_ENA (1 << 31)
+/** Offset of the colorburst from the start of hsync, in pixels minus one. */
+# define TV_HBURST_START_SHIFT 16
+# define TV_HBURST_START_MASK 0x1fff0000
+/** Length of the colorburst */
+# define TV_HBURST_LEN_SHIFT 0
+# define TV_HBURST_LEN_MASK 0x0001fff
+/** @} */
+
+/** @defgroup TV_H_CTL_3
+ * @{
+ */
+#define TV_H_CTL_3 0x68038
+/** End of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_END_SHIFT 16
+# define TV_HBLANK_END_MASK 0x1fff0000
+/** Start of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_START_SHIFT 0
+# define TV_HBLANK_START_MASK 0x0001fff
+/** @} */
+
+/** @defgroup TV_V_CTL_1
+ * @{
+ */
+#define TV_V_CTL_1 0x6803c
+/** XXX */
+# define TV_NBR_END_SHIFT 16
+# define TV_NBR_END_MASK 0x07ff0000
+/** XXX */
+# define TV_VI_END_F1_SHIFT 8
+# define TV_VI_END_F1_MASK 0x00003f00
+/** XXX */
+# define TV_VI_END_F2_SHIFT 0
+# define TV_VI_END_F2_MASK 0x0000003f
+/** @} */
+
+/** @defgroup TV_V_CTL_2
+ * @{
+ */
+#define TV_V_CTL_2 0x68040
+/** Length of vsync, in half lines */
+# define TV_VSYNC_LEN_MASK 0x07ff0000
+# define TV_VSYNC_LEN_SHIFT 16
+/** Offset of the start of vsync in field 1, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F1_MASK 0x00007f00
+# define TV_VSYNC_START_F1_SHIFT 8
+/**
+ * Offset of the start of vsync in field 2, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F2_MASK 0x0000007f
+# define TV_VSYNC_START_F2_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_3
+ * @{
+ */
+#define TV_V_CTL_3 0x68044
+/** Enables generation of the equalization signal */
+# define TV_EQUAL_ENA (1 << 31)
+/** Length of vsync, in half lines */
+# define TV_VEQ_LEN_MASK 0x007f0000
+# define TV_VEQ_LEN_SHIFT 16
+/** Offset of the start of equalization in field 1, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F1_MASK 0x0007f00
+# define TV_VEQ_START_F1_SHIFT 8
+/**
+ * Offset of the start of equalization in field 2, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F2_MASK 0x000007f
+# define TV_VEQ_START_F2_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_4
+ * @{
+ */
+#define TV_V_CTL_4 0x68048
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F1_MASK 0x003f0000
+# define TV_VBURST_START_F1_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F1_MASK 0x000000ff
+# define TV_VBURST_END_F1_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_5
+ * @{
+ */
+#define TV_V_CTL_5 0x6804c
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F2_MASK 0x003f0000
+# define TV_VBURST_START_F2_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F2_MASK 0x000000ff
+# define TV_VBURST_END_F2_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_6
+ * @{
+ */
+#define TV_V_CTL_6 0x68050
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F3_MASK 0x003f0000
+# define TV_VBURST_START_F3_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F3_MASK 0x000000ff
+# define TV_VBURST_END_F3_SHIFT 0
+/** @} */
+
+/** @defgroup TV_V_CTL_7
+ * @{
+ */
+#define TV_V_CTL_7 0x68054
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F4_MASK 0x003f0000
+# define TV_VBURST_START_F4_SHIFT 16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F4_MASK 0x000000ff
+# define TV_VBURST_END_F4_SHIFT 0
+/** @} */
+
+/** @defgroup TV_SC_CTL_1
+ * @{
+ */
+#define TV_SC_CTL_1 0x68060
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA1_EN (1 << 31)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA2_EN (1 << 30)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA3_EN (1 << 29)
+/** Sets the subcarrier DDA to reset frequency every other field */
+# define TV_SC_RESET_EVERY_2 (0 << 24)
+/** Sets the subcarrier DDA to reset frequency every fourth field */
+# define TV_SC_RESET_EVERY_4 (1 << 24)
+/** Sets the subcarrier DDA to reset frequency every eighth field */
+# define TV_SC_RESET_EVERY_8 (2 << 24)
+/** Sets the subcarrier DDA to never reset the frequency */
+# define TV_SC_RESET_NEVER (3 << 24)
+/** Sets the peak amplitude of the colorburst.*/
+# define TV_BURST_LEVEL_MASK 0x00ff0000
+# define TV_BURST_LEVEL_SHIFT 16
+/** Sets the increment of the first subcarrier phase generation DDA */
+# define TV_SCDDA1_INC_MASK 0x00000fff
+# define TV_SCDDA1_INC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_SC_CTL_2
+ * @{
+ */
+#define TV_SC_CTL_2 0x68064
+/** Sets the rollover for the second subcarrier phase generation DDA */
+# define TV_SCDDA2_SIZE_MASK 0x7fff0000
+# define TV_SCDDA2_SIZE_SHIFT 16
+/** Sets the increent of the second subcarrier phase generation DDA */
+# define TV_SCDDA2_INC_MASK 0x00007fff
+# define TV_SCDDA2_INC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_SC_CTL_3
+ * @{
+ */
+#define TV_SC_CTL_3 0x68068
+/** Sets the rollover for the third subcarrier phase generation DDA */
+# define TV_SCDDA3_SIZE_MASK 0x7fff0000
+# define TV_SCDDA3_SIZE_SHIFT 16
+/** Sets the increent of the third subcarrier phase generation DDA */
+# define TV_SCDDA3_INC_MASK 0x00007fff
+# define TV_SCDDA3_INC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_WIN_POS
+ * @{
+ */
+#define TV_WIN_POS 0x68070
+/** X coordinate of the display from the start of horizontal active */
+# define TV_XPOS_MASK 0x1fff0000
+# define TV_XPOS_SHIFT 16
+/** Y coordinate of the display from the start of vertical active (NBR) */
+# define TV_YPOS_MASK 0x00000fff
+# define TV_YPOS_SHIFT 0
+/** @} */
+
+/** @defgroup TV_WIN_SIZE
+ * @{
+ */
+#define TV_WIN_SIZE 0x68074
+/** Horizontal size of the display window, measured in pixels*/
+# define TV_XSIZE_MASK 0x1fff0000
+# define TV_XSIZE_SHIFT 16
+/**
+ * Vertical size of the display window, measured in pixels.
+ *
+ * Must be even for interlaced modes.
+ */
+# define TV_YSIZE_MASK 0x00000fff
+# define TV_YSIZE_SHIFT 0
+/** @} */
+
+/** @defgroup TV_FILTER_CTL_1
+ * @{
+ */
+#define TV_FILTER_CTL_1 0x68080
+/**
+ * Enables automatic scaling calculation.
+ *
+ * If set, the rest of the registers are ignored, and the calculated values can
+ * be read back from the register.
+ */
+# define TV_AUTO_SCALE (1 << 31)
+/**
+ * Disables the vertical filter.
+ *
+ * This is required on modes more than 1024 pixels wide */
+# define TV_V_FILTER_BYPASS (1 << 29)
+/** Enables adaptive vertical filtering */
+# define TV_VADAPT (1 << 28)
+# define TV_VADAPT_MODE_MASK (3 << 26)
+/** Selects the least adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_LEAST (0 << 26)
+/** Selects the moderately adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MODERATE (1 << 26)
+/** Selects the most adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MOST (3 << 26)
+/**
+ * Sets the horizontal scaling factor.
+ *
+ * This should be the fractional part of the horizontal scaling factor divided
+ * by the oversampling rate. TV_HSCALE should be less than 1, and set to:
+ *
+ * (src width - 1) / ((oversample * dest width) - 1)
+ */
+# define TV_HSCALE_FRAC_MASK 0x00003fff
+# define TV_HSCALE_FRAC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_FILTER_CTL_2
+ * @{
+ */
+#define TV_FILTER_CTL_2 0x68084
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1)
+ */
+# define TV_VSCALE_INT_MASK 0x00038000
+# define TV_VSCALE_INT_SHIFT 15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * \sa TV_VSCALE_INT_MASK
+ */
+# define TV_VSCALE_FRAC_MASK 0x00007fff
+# define TV_VSCALE_FRAC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_FILTER_CTL_3
+ * @{
+ */
+#define TV_FILTER_CTL_3 0x68088
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1))
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ */
+# define TV_VSCALE_IP_INT_MASK 0x00038000
+# define TV_VSCALE_IP_INT_SHIFT 15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ *
+ * \sa TV_VSCALE_IP_INT_MASK
+ */
+# define TV_VSCALE_IP_FRAC_MASK 0x00007fff
+# define TV_VSCALE_IP_FRAC_SHIFT 0
+/** @} */
+
+/** @defgroup TV_CC_CONTROL
+ * @{
+ */
+#define TV_CC_CONTROL 0x68090
+# define TV_CC_ENABLE (1 << 31)
+/**
+ * Specifies which field to send the CC data in.
+ *
+ * CC data is usually sent in field 0.
+ */
+# define TV_CC_FID_MASK (1 << 27)
+# define TV_CC_FID_SHIFT 27
+/** Sets the horizontal position of the CC data. Usually 135. */
+# define TV_CC_HOFF_MASK 0x03ff0000
+# define TV_CC_HOFF_SHIFT 16
+/** Sets the vertical position of the CC data. Usually 21 */
+# define TV_CC_LINE_MASK 0x0000003f
+# define TV_CC_LINE_SHIFT 0
+/** @} */
+
+/** @defgroup TV_CC_DATA
+ * @{
+ */
+#define TV_CC_DATA 0x68094
+# define TV_CC_RDY (1 << 31)
+/** Second word of CC data to be transmitted. */
+# define TV_CC_DATA_2_MASK 0x007f0000
+# define TV_CC_DATA_2_SHIFT 16
+/** First word of CC data to be transmitted. */
+# define TV_CC_DATA_1_MASK 0x0000007f
+# define TV_CC_DATA_1_SHIFT 0
+/** @}
+ */
+
+/** @{ */
+#define TV_H_LUMA_0 0x68100
+#define TV_H_LUMA_59 0x681ec
+#define TV_H_CHROMA_0 0x68200
+#define TV_H_CHROMA_59 0x682ec
+#define TV_V_LUMA_0 0x68300
+#define TV_V_LUMA_42 0x683a8
+#define TV_V_CHROMA_0 0x68400
+#define TV_V_CHROMA_42 0x684a8
+/** @} */
+
+#define PIPEA_DSL 0x70000
+
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE (1<<31)
+#define PIPEACONF_DISABLE 0
+#define PIPEACONF_DOUBLE_WIDE (1<<30)
+#define I965_PIPECONF_ACTIVE (1<<30)
+#define PIPEACONF_SINGLE_WIDE 0
+#define PIPEACONF_PIPE_UNLOCKED 0
+#define PIPEACONF_PIPE_LOCKED (1<<25)
+#define PIPEACONF_PALETTE 0
+#define PIPEACONF_GAMMA (1<<24)
+#define PIPECONF_FORCE_BORDER (1<<25)
+#define PIPECONF_PROGRESSIVE (0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
+/* ironlake: gamma */
+#define PIPECONF_PALETTE_8BIT (0<<24)
+#define PIPECONF_PALETTE_10BIT (1<<24)
+#define PIPECONF_PALETTE_12BIT (2<<24)
+#define PIPECONF_FORCE_BORDER (1<<25)
+#define PIPECONF_PROGRESSIVE (0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
+/* ironlake */
+#define PIPECONF_MSA_TIMING_DELAY (0<<18) /* for eDP */
+#define PIPECONF_NO_DYNAMIC_RATE_CHANGE (0 << 16)
+#define PIPECONF_NO_ROTATION (0<<14)
+#define PIPECONF_FULL_COLOR_RANGE (0<<13)
+#define PIPECONF_CE_COLOR_RANGE (1<<13)
+#define PIPECONF_COLOR_SPACE_RGB (0<<11)
+#define PIPECONF_COLOR_SPACE_YUV601 (1<<11)
+#define PIPECONF_COLOR_SPACE_YUV709 (2<<11)
+#define PIPECONF_CONNECT_DEFAULT (0<<9)
+#define PIPECONF_8BPP (0<<5)
+#define PIPECONF_10BPP (1<<5)
+#define PIPECONF_6BPP (2<<5)
+#define PIPECONF_12BPP (3<<5)
+#define PIPECONF_ENABLE_DITHER (1<<4)
+#define PIPECONF_DITHER_SPATIAL (0<<2)
+#define PIPECONF_DITHER_ST1 (1<<2)
+#define PIPECONF_DITHER_ST2 (2<<2)
+#define PIPECONF_DITHER_TEMPORAL (3<<2)
+
+#define PIPEAGCMAXRED 0x70010
+#define PIPEAGCMAXGREEN 0x70014
+#define PIPEAGCMAXBLUE 0x70018
+#define PIPEASTAT 0x70024
+# define FIFO_UNDERRUN (1 << 31)
+# define CRC_ERROR_ENABLE (1 << 29)
+# define CRC_DONE_ENABLE (1 << 28)
+# define GMBUS_EVENT_ENABLE (1 << 27)
+# define VSYNC_INT_ENABLE (1 << 25)
+# define DLINE_COMPARE_ENABLE (1 << 24)
+# define DPST_EVENT_ENABLE (1 << 23)
+# define LBLC_EVENT_ENABLE (1 << 22)
+# define OFIELD_INT_ENABLE (1 << 21)
+# define EFIELD_INT_ENABLE (1 << 20)
+# define SVBLANK_INT_ENABLE (1 << 18)
+# define VBLANK_INT_ENABLE (1 << 17)
+# define OREG_UPDATE_ENABLE (1 << 16)
+# define CRC_ERROR_INT_STATUS (1 << 13)
+# define CRC_DONE_INT_STATUS (1 << 12)
+# define GMBUS_INT_STATUS (1 << 11)
+# define VSYNC_INT_STATUS (1 << 9)
+# define DLINE_COMPARE_STATUS (1 << 8)
+# define DPST_EVENT_STATUS (1 << 7)
+# define LBLC_EVENT_STATUS (1 << 6)
+# define OFIELD_INT_STATUS (1 << 5)
+# define EFIELD_INT_STATUS (1 << 4)
+# define SVBLANK_INT_STATUS (1 << 2)
+# define VBLANK_INT_STATUS (1 << 1)
+# define OREG_UPDATE_STATUS (1 << 0)
+
+
+#define DSPARB 0x70030
+#define DSPARB_CSTART_SHIFT 7
+#define DSPARB_BSTART_SHIFT 0
+#define DSPARB_BEND_SHIFT 9 /* on 855 */
+#define DSPARB_AEND_SHIFT 0
+#define DSPFW1 0x70034
+#define DSPFW2 0x70038
+#define DSPFW3 0x7003c
+/*
+ * The two pipe frame counter registers are not synchronized, so
+ * reading a stable value is somewhat tricky. The following code
+ * should work:
+ *
+ * do {
+ * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> PIPE_FRAME_HIGH_SHIFT;
+ * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >> PIPE_FRAME_LOW_SHIFT);
+ * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> PIPE_FRAME_HIGH_SHIFT);
+ * } while (high1 != high2);
+ * frame = (high1 << 8) | low1;
+ */
+#define PIPEAFRAMEHIGH 0x70040
+#define PIPE_FRAME_HIGH_MASK 0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT 0
+#define PIPEAFRAMEPIXEL 0x70044
+#define PIPE_FRAME_LOW_MASK 0xff000000
+#define PIPE_FRAME_LOW_SHIFT 24
+/*
+ * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
+ * and is 24 bits wide.
+ */
+#define PIPE_PIXEL_MASK 0x00ffffff
+#define PIPE_PIXEL_SHIFT 0
+
+/*
+ * Computing GMCH M and N values.
+ *
+ * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes
+ *
+ * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz)
+ *
+ * The GMCH value is used internally
+ */
+#define PIPEA_GMCH_DATA_M 0x70050
+
+/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */
+#define PIPE_GMCH_DATA_M_TU_SIZE_MASK (0x3f << 25)
+#define PIPE_GMCH_DATA_M_TU_SIZE_SHIFT 25
+
+#define PIPE_GMCH_DATA_M_MASK (0xffffff)
+
+#define PIPEA_GMCH_DATA_N 0x70054
+#define PIPE_GMCH_DATA_N_MASK (0xffffff)
+
+/*
+ * Computing Link M and N values.
+ *
+ * Link M / N = pixel_clock / ls_clk
+ *
+ * (the DP spec calls pixel_clock the 'strm_clk')
+ *
+ * The Link value is transmitted in the Main Stream
+ * Attributes and VB-ID.
+ */
+
+#define PIPEA_DP_LINK_M 0x70060
+#define PIPEA_DP_LINK_M_MASK (0xffffff)
+
+#define PIPEA_DP_LINK_N 0x70064
+#define PIPEA_DP_LINK_N_MASK (0xffffff)
+
+#define PIPEB_DSL 0x71000
+
+#define PIPEBCONF 0x71008
+
+#define PIPEBGCMAXRED 0x71010
+#define PIPEBGCMAXGREEN 0x71014
+#define PIPEBGCMAXBLUE 0x71018
+#define PIPEBSTAT 0x71024
+#define PIPEBFRAMEHIGH 0x71040
+#define PIPEBFRAMEPIXEL 0x71044
+
+#define PIPEB_GMCH_DATA_M 0x71050
+#define PIPEB_GMCH_DATA_N 0x71054
+#define PIPEB_DP_LINK_M 0x71060
+#define PIPEB_DP_LINK_N 0x71064
+
+#define PIPECCONF 0x72008
+
+#define PIPECGCMAXRED 0x72010
+#define PIPECGCMAXGREEN 0x72014
+#define PIPECGCMAXBLUE 0x72018
+#define PIPECSTAT 0x72024
+#define PIPECFRAMEHIGH 0x72040
+#define PIPECFRAMEPIXEL 0x72044
+
+#define PIPEC_GMCH_DATA_M 0x72050
+#define PIPEC_GMCH_DATA_N 0x72054
+#define PIPEC_DP_LINK_M 0x72060
+#define PIPEC_DP_LINK_N 0x72064
+
+#define DSPACNTR 0x70180
+#define DSPBCNTR 0x71180
+#define DSPCCNTR 0x72180
+#define DISPLAY_PLANE_ENABLE (1<<31)
+#define DISPLAY_PLANE_DISABLE 0
+#define DISPLAY_PLANE_TILED (1<<10)
+#define DISPPLANE_GAMMA_ENABLE (1<<30)
+#define DISPPLANE_GAMMA_DISABLE 0
+#define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
+#define DISPPLANE_8BPP (0x2<<26)
+#define DISPPLANE_15_16BPP (0x4<<26)
+#define DISPPLANE_16BPP (0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
+#define DISPPLANE_32BPP (0x7<<26)
+#define DISPPLANE_STEREO_ENABLE (1<<25)
+#define DISPPLANE_STEREO_DISABLE 0
+#define DISPPLANE_SEL_PIPE_MASK (1<<24)
+#define DISPPLANE_SEL_PIPE_A 0
+#define DISPPLANE_SEL_PIPE_B (1<<24)
+#define DISPPLANE_SRC_KEY_ENABLE (1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE 0
+#define DISPPLANE_LINE_DOUBLE (1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE 0
+#define DISPPLANE_STEREO_POLARITY_FIRST 0
+#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE 0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1)
+
+#define DSPABASE 0x70184
+#define DSPASTRIDE 0x70188
+
+#define DSPBBASE 0x71184
+#define DSPBADDR DSPBBASE
+#define DSPBSTRIDE 0x71188
+
+#define DSPCBASE 0x72184
+#define DSPCADDR DSPCBASE
+#define DSPCSTRIDE 0x72188
+
+#define DSPAKEYVAL 0x70194
+#define DSPAKEYMASK 0x70198
+
+#define DSPAPOS 0x7018C /* reserved */
+#define DSPASIZE 0x70190
+#define DSPBPOS 0x7118C
+#define DSPBSIZE 0x71190
+
+#define DSPASURF 0x7019C
+#define DSPATILEOFF 0x701A4
+
+#define DSPBSURF 0x7119C
+#define DSPBTILEOFF 0x711A4
+
+#define DSPCSURF 0x7219C
+#define DSPCTILEOFF 0x721A4
+
+#define VGACNTRL 0x71400
+# define VGA_DISP_DISABLE (1 << 31)
+# define VGA_2X_MODE (1 << 30)
+# define VGA_PIPE_B_SELECT (1 << 29)
+
+/* Various masks for reserved bits, etc. */
+#define I830_FWATER1_MASK (~((1<<11)|(1<<10)|(1<<9)| \
+ (1<<8)|(1<<26)|(1<<25)|(1<<24)|(1<<5)|(1<<4)|(1<<3)| \
+ (1<<2)|(1<<1)|1|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)))
+#define I830_FWATER2_MASK ~(0)
+
+#define DV0A_RESERVED ((1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<16)|(1<<5)|(1<<1)|1)
+#define DV0B_RESERVED ((1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<16)|(1<<5)|(1<<1)|1)
+#define VGA0_N_DIVISOR_MASK ((1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16))
+#define VGA0_M1_DIVISOR_MASK ((1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8))
+#define VGA0_M2_DIVISOR_MASK ((1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1)
+#define VGA0_M1M2N_RESERVED ~(VGA0_N_DIVISOR_MASK|VGA0_M1_DIVISOR_MASK|VGA0_M2_DIVISOR_MASK)
+#define VGA0_POSTDIV_MASK ((1<<7)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1)
+#define VGA1_POSTDIV_MASK ((1<<15)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8))
+#define VGA_POSTDIV_RESERVED ~(VGA0_POSTDIV_MASK|VGA1_POSTDIV_MASK|(1<<7)|(1<<15))
+#define DPLLA_POSTDIV_MASK ((1<<23)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16))
+#define DPLLA_RESERVED ((1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<22)|(1<<15)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1)
+#define ADPA_RESERVED ((1<<2)|(1<<1)|1|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16))
+#define SUPER_WORD 32
+#define BURST_A_MASK ((1<<11)|(1<<10)|(1<<9)|(1<<8))
+#define BURST_B_MASK ((1<<26)|(1<<25)|(1<<24))
+#define WATER_A_MASK ((1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1)
+#define WATER_B_MASK ((1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16))
+#define WATER_RESERVED ((1<<31)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<23)|(1<<22)|(1<<21)|(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<7)|(1<<6))
+#define PIPEACONF_RESERVED ((1<<29)|(1<<28)|(1<<27)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)|0xffff)
+#define PIPEBCONF_RESERVED ((1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<26)|(1<<25)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)|0xffff)
+#define DSPACNTR_RESERVED ((1<<23)|(1<<19)|(1<<17)|(1<<16)|0xffff)
+#define DSPBCNTR_RESERVED ((1<<23)|(1<<19)|(1<<17)|(1<<16)|0x7ffe)
+
+#define I830_GMCH_CTRL 0x52
+
+#define I830_GMCH_ENABLED 0x4
+#define I830_GMCH_MEM_MASK 0x1
+#define I830_GMCH_MEM_64M 0x1
+#define I830_GMCH_MEM_128M 0
+
+#define I830_GMCH_GMS_MASK 0x70
+#define I830_GMCH_GMS_DISABLED 0x00
+#define I830_GMCH_GMS_LOCAL 0x10
+#define I830_GMCH_GMS_STOLEN_512 0x20
+#define I830_GMCH_GMS_STOLEN_1024 0x30
+#define I830_GMCH_GMS_STOLEN_8192 0x40
+
+#define I830_RDRAM_CHANNEL_TYPE 0x03010
+#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5)
+#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3)
+
+#define I855_GMCH_GMS_MASK (0xF << 4)
+#define I855_GMCH_GMS_DISABLED 0x00
+#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
+#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4)
+#define I855_GMCH_GMS_STOLEN_8M (0x3 << 4)
+#define I855_GMCH_GMS_STOLEN_16M (0x4 << 4)
+#define I855_GMCH_GMS_STOLEN_32M (0x5 << 4)
+#define I915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
+#define I915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
+#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
+#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
+#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
+#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
+#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
+#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
+
+
+#define I85X_CAPID 0x44
+#define I85X_VARIANT_MASK 0x7
+#define I85X_VARIANT_SHIFT 5
+#define I855_GME 0x0
+#define I855_GM 0x4
+#define I852_GME 0x2
+#define I852_GM 0x5
+
+#define I915_GCFGC 0xf0
+#define I915_LOW_FREQUENCY_ENABLE (1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4)
+#define I915_DISPLAY_CLOCK_MASK (7 << 4)
+
+#define I855_HPLLCC 0xc0
+#define I855_CLOCK_CONTROL_MASK (3 << 0)
+#define I855_CLOCK_133_200 (0 << 0)
+#define I855_CLOCK_100_200 (1 << 0)
+#define I855_CLOCK_100_133 (2 << 0)
+#define I855_CLOCK_166_250 (3 << 0)
+
+/* BLT commands */
+#define COLOR_BLT_CMD ((2<<29)|(0x40<<22)|(0x3))
+#define COLOR_BLT_WRITE_ALPHA (1<<21)
+#define COLOR_BLT_WRITE_RGB (1<<20)
+
+#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|(0x4))
+#define XY_COLOR_BLT_WRITE_ALPHA (1<<21)
+#define XY_COLOR_BLT_WRITE_RGB (1<<20)
+#define XY_COLOR_BLT_TILED (1<<11)
+
+#define XY_SETUP_CLIP_BLT_CMD ((2<<29)|(3<<22)|1)
+
+#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
+#define XY_SRC_COPY_BLT_SRC_TILED (1<<15)
+#define XY_SRC_COPY_BLT_DST_TILED (1<<11)
+
+#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|0x4)
+#define SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define SRC_COPY_BLT_WRITE_RGB (1<<20)
+
+#define XY_PAT_BLT_IMMEDIATE ((2<<29)|(0x72<<22))
+
+#define XY_MONO_PAT_BLT_CMD ((0x2<<29)|(0x52<<22)|0x7)
+#define XY_MONO_PAT_VERT_SEED ((1<<10)|(1<<9)|(1<<8))
+#define XY_MONO_PAT_HORT_SEED ((1<<14)|(1<<13)|(1<<12))
+#define XY_MONO_PAT_BLT_WRITE_ALPHA (1<<21)
+#define XY_MONO_PAT_BLT_WRITE_RGB (1<<20)
+
+#define XY_MONO_SRC_BLT_CMD ((0x2<<29)|(0x54<<22)|(0x6))
+#define XY_MONO_SRC_BLT_WRITE_ALPHA (1<<21)
+#define XY_MONO_SRC_BLT_WRITE_RGB (1<<20)
+
+#define MI_STORE_DWORD_IMM ((0x20<<23)|2)
+#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */
+
+#define MI_SET_CONTEXT (0x18<<23)
+#define CTXT_NO_RESTORE (1)
+#define CTXT_PALETTE_SAVE_DISABLE (1<<3)
+#define CTXT_PALETTE_RESTORE_DISABLE (1<<2)
+
+/* Dword 0 */
+#define MI_VERTEX_BUFFER (0x17<<23)
+#define MI_VERTEX_BUFFER_IDX(x) (x<<20)
+#define MI_VERTEX_BUFFER_PITCH(x) (x<<13)
+#define MI_VERTEX_BUFFER_WIDTH(x) (x<<6)
+/* Dword 1 */
+#define MI_VERTEX_BUFFER_DISABLE (1)
+
+/* Overlay Flip */
+#define MI_OVERLAY_FLIP (0x11<<23)
+#define MI_OVERLAY_FLIP_CONTINUE (0<<21)
+#define MI_OVERLAY_FLIP_ON (1<<21)
+#define MI_OVERLAY_FLIP_OFF (2<<21)
+
+/* Wait for Events */
+#define MI_WAIT_FOR_EVENT (0x03<<23)
+#define MI_WAIT_FOR_PIPEB_SVBLANK (1<<18)
+#define MI_WAIT_FOR_PIPEA_SVBLANK (1<<17)
+#define MI_WAIT_FOR_OVERLAY_FLIP (1<<16)
+#define MI_WAIT_FOR_PIPEB_VBLANK (1<<7)
+#define MI_WAIT_FOR_PIPEA_VBLANK (1<<3)
+#define MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW (1<<5)
+#define MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW (1<<1)
+
+#define MI_LOAD_SCAN_LINES_INCL (0x12<<23)
+
+/* Flush */
+#define MI_FLUSH (0x04<<23)
+#define MI_WRITE_DIRTY_STATE (1<<4)
+#define MI_END_SCENE (1<<3)
+#define MI_GLOBAL_SNAPSHOT_COUNT_RESET (1<<3)
+#define MI_INHIBIT_RENDER_CACHE_FLUSH (1<<2)
+#define MI_STATE_INSTRUCTION_CACHE_FLUSH (1<<1)
+#define MI_INVALIDATE_MAP_CACHE (1<<0)
+/* broadwater flush bits */
+#define BRW_MI_GLOBAL_SNAPSHOT_RESET (1 << 3)
+
+/* Noop */
+#define MI_NOOP 0x00
+#define MI_NOOP_WRITE_ID (1<<22)
+#define MI_NOOP_ID_MASK (1<<22 - 1)
+
+#define STATE3D_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x01<<16))
+
+/* Batch */
+#define MI_BATCH_BUFFER ((0x30 << 23) | 1)
+#define MI_BATCH_BUFFER_START (0x31 << 23)
+#define MI_BATCH_BUFFER_END (0xA << 23)
+#define MI_BATCH_NON_SECURE (1)
+#define MI_BATCH_NON_SECURE_I965 (1 << 8)
+
+#define MAX_DISPLAY_PIPES 2
+
+typedef enum {
+ CrtIndex = 0,
+ TvIndex,
+ DfpIndex,
+ LfpIndex,
+ Crt2Index,
+ Tv2Index,
+ Dfp2Index,
+ Lfp2Index,
+ NumDisplayTypes
+} DisplayType;
+
+/* What's connected to the pipes (as reported by the BIOS) */
+#define PIPE_ACTIVE_MASK 0xff
+#define PIPE_CRT_ACTIVE (1 << CrtIndex)
+#define PIPE_TV_ACTIVE (1 << TvIndex)
+#define PIPE_DFP_ACTIVE (1 << DfpIndex)
+#define PIPE_LCD_ACTIVE (1 << LfpIndex)
+#define PIPE_CRT2_ACTIVE (1 << Crt2Index)
+#define PIPE_TV2_ACTIVE (1 << Tv2Index)
+#define PIPE_DFP2_ACTIVE (1 << Dfp2Index)
+#define PIPE_LCD2_ACTIVE (1 << Lfp2Index)
+
+#define PIPE_SIZED_DISP_MASK (PIPE_DFP_ACTIVE | \
+ PIPE_LCD_ACTIVE | \
+ PIPE_DFP2_ACTIVE)
+
+#define PIPE_A_SHIFT 0
+#define PIPE_B_SHIFT 8
+#define PIPE_SHIFT(n) ((n) == 0 ? \
+ PIPE_A_SHIFT : PIPE_B_SHIFT)
+
+/*
+ * Some BIOS scratch area registers. The 845 (and 830?) store the amount
+ * of video memory available to the BIOS in SWF1.
+ */
+
+#define SWF0 0x71410
+#define SWF1 0x71414
+#define SWF2 0x71418
+#define SWF3 0x7141c
+#define SWF4 0x71420
+#define SWF5 0x71424
+#define SWF6 0x71428
+
+/*
+ * 855 scratch registers.
+ */
+#define SWF00 0x70410
+#define SWF01 0x70414
+#define SWF02 0x70418
+#define SWF03 0x7041c
+#define SWF04 0x70420
+#define SWF05 0x70424
+#define SWF06 0x70428
+
+#define SWF10 SWF0
+#define SWF11 SWF1
+#define SWF12 SWF2
+#define SWF13 SWF3
+#define SWF14 SWF4
+#define SWF15 SWF5
+#define SWF16 SWF6
+
+#define SWF30 0x72414
+#define SWF31 0x72418
+#define SWF32 0x7241c
+
+/*
+ * Overlay registers. These are overlay registers accessed via MMIO.
+ * Those loaded via the overlay register page are defined in i830_video.c.
+ */
+#define OVADD 0x30000
+
+#define DOVSTA 0x30008
+#define OC_BUF (0x3<<20)
+
+#define OGAMC5 0x30010
+#define OGAMC4 0x30014
+#define OGAMC3 0x30018
+#define OGAMC2 0x3001c
+#define OGAMC1 0x30020
+#define OGAMC0 0x30024
+
+
+/*
+ * Palette registers
+ */
+#define PALETTE_A 0x0a000
+#define PALETTE_B 0x0a800
+
+/* Framebuffer compression */
+#define FBC_CFB_BASE 0x03200 /* 4k page aligned */
+#define FBC_LL_BASE 0x03204 /* 4k page aligned */
+#define FBC_CONTROL 0x03208
+#define FBC_CTL_EN (1<<31)
+#define FBC_CTL_PERIODIC (1<<30)
+#define FBC_CTL_INTERVAL_SHIFT (16)
+#define FBC_CTL_UNCOMPRESSIBLE (1<<14)
+#define FBC_CTL_STRIDE_SHIFT (5)
+#define FBC_CTL_FENCENO (1<<0)
+#define FBC_COMMAND 0x0320c
+#define FBC_CMD_COMPRESS (1<<0)
+#define FBC_STATUS 0x03210
+#define FBC_STAT_COMPRESSING (1<<31)
+#define FBC_STAT_COMPRESSED (1<<30)
+#define FBC_STAT_MODIFIED (1<<29)
+#define FBC_STAT_CURRENT_LINE (1<<0)
+#define FBC_CONTROL2 0x03214
+#define FBC_CTL_FENCE_DBL (0<<4)
+#define FBC_CTL_IDLE_IMM (0<<2)
+#define FBC_CTL_IDLE_FULL (1<<2)
+#define FBC_CTL_IDLE_LINE (2<<2)
+#define FBC_CTL_IDLE_DEBUG (3<<2)
+#define FBC_CTL_CPU_FENCE (1<<1)
+#define FBC_CTL_PLANEA (0<<0)
+#define FBC_CTL_PLANEB (1<<0)
+#define FBC_FENCE_OFF 0x0321b
+#define FBC_MOD_NUM 0x03220
+#define FBC_TAG_DEBUG 0x03300
+
+#define FBC_LL_SIZE (1536)
+#define FBC_LL_PAD (32)
+
+/* Framebuffer compression version 2 */
+#define DPFC_CB_BASE 0x3200
+#define DPFC_CONTROL 0x3208
+#define DPFC_CTL_EN (1<<31)
+#define DPFC_CTL_PLANEA (0<<30)
+#define DPFC_CTL_PLANEB (1<<30)
+#define DPFC_CTL_FENCE_EN (1<<29)
+#define DPFC_CTL_LIMIT_1X (0<<6)
+#define DPFC_CTL_LIMIT_2X (1<<6)
+#define DPFC_CTL_LIMIT_4X (2<<6)
+#define DPFC_RECOMP_CTL 0x320c
+#define DPFC_RECOMP_STALL_EN (1<<27)
+#define DPFC_RECOMP_STALL_WM_SHIFT (16)
+#define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000)
+#define DPFC_RECOMP_TIMER_COUNT_SHIFT (0)
+#define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f)
+#define DPFC_STATUS 0x3210
+#define DPFC_INVAL_SEG_SHIFT (16)
+#define DPFC_INVAL_SEG_MASK (0x07ff0000)
+#define DPFC_COMP_SEG_SHIFT (0)
+#define DPFC_COMP_SEG_MASK (0x000003ff)
+#define DPFC_STATUS2 0x3214
+#define DPFC_FENCE_YOFF 0x3218
+
+#define PEG_BAND_GAP_DATA 0x14d68
+
+#define MCHBAR_RENDER_STANDBY 0x111B8
+#define RENDER_STANDBY_ENABLE (1 << 30)
+
+
+/* Ironlake */
+
+/* warmup time in us */
+#define WARMUP_PCH_REF_CLK_SSC_MOD 1
+#define WARMUP_PCH_FDI_RECEIVER_PLL 25
+#define WARMUP_PCH_DPLL 50
+#define WARMUP_CPU_DP_PLL 20
+#define WARMUP_CPU_FDI_TRANSMITTER_PLL 10
+#define WARMUP_DMI_LATENCY 20
+#define FDI_TRAIN_PATTERN_1_TIME 0.5
+#define FDI_TRAIN_PATTERN_2_TIME 1.5
+#define FDI_ONE_IDLE_PATTERN_TIME 31
+
+#define CPU_VGACNTRL 0x41000
+
+#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030
+#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4)
+#define DIGITAL_PORTA_SHORT_PULSE_2MS (0 << 2)
+#define DIGITAL_PORTA_SHORT_PULSE_4_5MS (1 << 2)
+#define DIGITAL_PORTA_SHORT_PULSE_6MS (2 << 2)
+#define DIGITAL_PORTA_SHORT_PULSE_100MS (3 << 2)
+#define DIGITAL_PORTA_NO_DETECT (0 << 0)
+#define DIGITAL_PORTA_LONG_PULSE_DETECT_MASK (1 << 1)
+#define DIGITAL_PORTA_SHORT_PULSE_DETECT_MASK (1 << 0)
+
+/* refresh rate hardware control */
+#define RR_HW_CTL 0x45300
+#define RR_HW_LOW_POWER_FRAMES_MASK 0xff
+#define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00
+
+#define FDI_PLL_BIOS_0 0x46000
+#define FDI_PLL_BIOS_1 0x46004
+#define FDI_PLL_BIOS_2 0x46008
+#define DISPLAY_PORT_PLL_BIOS_0 0x4600c
+#define DISPLAY_PORT_PLL_BIOS_1 0x46010
+#define DISPLAY_PORT_PLL_BIOS_2 0x46014
+
+#define FDI_PLL_FREQ_CTL 0x46030
+#define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24)
+#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00
+#define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff
+
+#define PIPEA_DATA_M1 0x60030
+#define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */
+#define TU_SIZE_MASK 0x7e000000
+#define PIPEA_DATA_M1_OFFSET 0
+#define PIPEA_DATA_N1 0x60034
+#define PIPEA_DATA_N1_OFFSET 0
+
+#define PIPEA_DATA_M2 0x60038
+#define PIPEA_DATA_M2_OFFSET 0
+#define PIPEA_DATA_N2 0x6003c
+#define PIPEA_DATA_N2_OFFSET 0
+
+#define PIPEA_LINK_M1 0x60040
+#define PIPEA_LINK_M1_OFFSET 0
+#define PIPEA_LINK_N1 0x60044
+#define PIPEA_LINK_N1_OFFSET 0
+
+#define PIPEA_LINK_M2 0x60048
+#define PIPEA_LINK_M2_OFFSET 0
+#define PIPEA_LINK_N2 0x6004c
+#define PIPEA_LINK_N2_OFFSET 0
+
+/* PIPEB timing regs are same start from 0x61000 */
+
+#define PIPEB_DATA_M1 0x61030
+#define PIPEB_DATA_N1 0x61034
+
+#define PIPEB_DATA_M2 0x61038
+#define PIPEB_DATA_N2 0x6103c
+
+#define PIPEB_LINK_M1 0x61040
+#define PIPEB_LINK_N1 0x61044
+
+#define PIPEB_LINK_M2 0x61048
+#define PIPEB_LINK_N2 0x6104c
+
+/* PIPEC timing regs */
+
+#define PIPEC_DATA_M1 0x62030
+#define PIPEC_DATA_N1 0x62034
+
+#define PIPEC_DATA_M2 0x62038
+#define PIPEC_DATA_N2 0x6203c
+
+#define PIPEC_LINK_M1 0x62040
+#define PIPEC_LINK_N1 0x62044
+
+#define PIPEC_LINK_M2 0x62048
+#define PIPEC_LINK_N2 0x6204c
+
+/* PIPECONF for pipe A/B addr is same */
+
+/* cusor A is only connected to pipe A,
+ cursor B is connected to pipe B. Otherwise no change. */
+
+/* Plane A/B, DSPACNTR/DSPBCNTR addr not changed */
+
+/* CPU panel fitter */
+#define PFA_CTL_1 0x68080
+#define PFB_CTL_1 0x68880
+#define PFC_CTL_1 0x69080
+#define PF_ENABLE (1<<31)
+#define PFA_CTL_2 0x68084
+#define PFB_CTL_2 0x68884
+#define PFC_CTL_2 0x69084
+#define PFA_CTL_3 0x68088
+#define PFB_CTL_3 0x68888
+#define PFC_CTL_3 0x69088
+#define PFA_CTL_4 0x68090
+#define PFB_CTL_4 0x68890
+#define PFC_CTL_4 0x69090
+
+#define PFA_WIN_POS 0x68070
+#define PFB_WIN_POS 0x68870
+#define PFC_WIN_POS 0x69070
+#define PFA_WIN_SIZE 0x68074
+#define PFB_WIN_SIZE 0x68874
+#define PFC_WIN_SIZE 0x69074
+
+/* legacy palette */
+#define LGC_PALETTE_A 0x4a000
+#define LGC_PALETTE_B 0x4a800
+
+/* interrupts */
+#define DE_MASTER_IRQ_CONTROL (1 << 31)
+#define DE_SPRITEB_FLIP_DONE (1 << 29)
+#define DE_SPRITEA_FLIP_DONE (1 << 28)
+#define DE_PLANEB_FLIP_DONE (1 << 27)
+#define DE_PLANEA_FLIP_DONE (1 << 26)
+#define DE_PCU_EVENT (1 << 25)
+#define DE_GTT_FAULT (1 << 24)
+#define DE_POISON (1 << 23)
+#define DE_PERFORM_COUNTER (1 << 22)
+#define DE_PCH_EVENT (1 << 21)
+#define DE_AUX_CHANNEL_A (1 << 20)
+#define DE_DP_A_HOTPLUG (1 << 19)
+#define DE_GSE (1 << 18)
+#define DE_PIPEB_VBLANK (1 << 15)
+#define DE_PIPEB_EVEN_FIELD (1 << 14)
+#define DE_PIPEB_ODD_FIELD (1 << 13)
+#define DE_PIPEB_LINE_COMPARE (1 << 12)
+#define DE_PIPEB_VSYNC (1 << 11)
+#define DE_PIPEB_FIFO_UNDERRUN (1 << 8)
+#define DE_PIPEA_VBLANK (1 << 7)
+#define DE_PIPEA_EVEN_FIELD (1 << 6)
+#define DE_PIPEA_ODD_FIELD (1 << 5)
+#define DE_PIPEA_LINE_COMPARE (1 << 4)
+#define DE_PIPEA_VSYNC (1 << 3)
+#define DE_PIPEA_FIFO_UNDERRUN (1 << 0)
+
+#define DEISR 0x44000
+#define DEIMR 0x44004
+#define DEIIR 0x44008
+#define DEIER 0x4400c
+
+/* GT interrupt */
+#define GT_SYNC_STATUS (1 << 2)
+#define GT_USER_INTERRUPT (1 << 0)
+
+#define GTISR 0x44010
+#define GTIMR 0x44014
+#define GTIIR 0x44018
+#define GTIER 0x4401c
+
+/* PCH */
+
+/* south display engine interrupt */
+#define SDE_CRT_HOTPLUG (1 << 11)
+#define SDE_PORTD_HOTPLUG (1 << 10)
+#define SDE_PORTC_HOTPLUG (1 << 9)
+#define SDE_PORTB_HOTPLUG (1 << 8)
+#define SDE_SDVOB_HOTPLUG (1 << 6)
+
+#define SDEISR 0xc4000
+#define SDEIMR 0xc4004
+#define SDEIIR 0xc4008
+#define SDEIER 0xc400c
+
+/* digital port hotplug */
+#define PCH_PORT_HOTPLUG 0xc4030
+#define PORTD_HOTPLUG_ENABLE (1 << 20)
+#define PORTD_PULSE_DURATION_2ms (0)
+#define PORTD_PULSE_DURATION_4_5ms (1 << 18)
+#define PORTD_PULSE_DURATION_6ms (2 << 18)
+#define PORTD_PULSE_DURATION_100ms (3 << 18)
+#define PORTD_HOTPLUG_NO_DETECT (0)
+#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
+#define PORTD_HOTPLUG_LONG_DETECT (1 << 17)
+#define PORTC_HOTPLUG_ENABLE (1 << 12)
+#define PORTC_PULSE_DURATION_2ms (0)
+#define PORTC_PULSE_DURATION_4_5ms (1 << 10)
+#define PORTC_PULSE_DURATION_6ms (2 << 10)
+#define PORTC_PULSE_DURATION_100ms (3 << 10)
+#define PORTC_HOTPLUG_NO_DETECT (0)
+#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
+#define PORTC_HOTPLUG_LONG_DETECT (1 << 9)
+#define PORTB_HOTPLUG_ENABLE (1 << 4)
+#define PORTB_PULSE_DURATION_2ms (0)
+#define PORTB_PULSE_DURATION_4_5ms (1 << 2)
+#define PORTB_PULSE_DURATION_6ms (2 << 2)
+#define PORTB_PULSE_DURATION_100ms (3 << 2)
+#define PORTB_HOTPLUG_NO_DETECT (0)
+#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
+#define PORTB_HOTPLUG_LONG_DETECT (1 << 1)
+
+#define PCH_GPIOA 0xc5010
+#define PCH_GPIOB 0xc5014
+#define PCH_GPIOC 0xc5018
+#define PCH_GPIOD 0xc501c
+#define PCH_GPIOE 0xc5020
+#define PCH_GPIOF 0xc5024
+#define PCH_GMBUS0 0xc5100
+#define PCH_GMBUS1 0xc5104
+#define PCH_GMBUS2 0xc5108
+#define PCH_GMBUS3 0xc510c
+#define PCH_GMBUS4 0xc5110
+#define PCH_GMBUS5 0xc5120
+
+#define PCH_DPLL_A 0xc6014
+#define PCH_DPLL_B 0xc6018
+
+#define PCH_FPA0 0xc6040
+#define PCH_FPA1 0xc6044
+#define PCH_FPB0 0xc6048
+#define PCH_FPB1 0xc604c
+
+#define PCH_DPLL_TEST 0xc606c
+
+#define PCH_DREF_CONTROL 0xC6200
+#define DREF_CONTROL_MASK 0x7fc3
+#define DREF_CPU_SOURCE_OUTPUT_DISABLE (0<<13)
+#define DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD (2<<13)
+#define DREF_CPU_SOURCE_OUTPUT_NONSPREAD (3<<13)
+#define DREF_SSC_SOURCE_DISABLE (0<<11)
+#define DREF_SSC_SOURCE_ENABLE (2<<11)
+#define DREF_NONSPREAD_SOURCE_DISABLE (0<<9)
+#define DREF_NONSPREAD_SOURCE_ENABLE (2<<9)
+#define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7)
+#define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7)
+#define DREF_SSC4_DOWNSPREAD (0<<6)
+#define DREF_SSC4_CENTERSPREAD (1<<6)
+#define DREF_SSC1_DISABLE (0<<1)
+#define DREF_SSC1_ENABLE (1<<1)
+#define DREF_SSC4_DISABLE (0)
+#define DREF_SSC4_ENABLE (1)
+
+#define PCH_RAWCLK_FREQ 0xc6204
+#define FDL_TP1_TIMER_SHIFT 12
+#define FDL_TP1_TIMER_MASK (3<<12)
+#define FDL_TP2_TIMER_SHIFT 10
+#define FDL_TP2_TIMER_MASK (3<<10)
+#define RAWCLK_FREQ_MASK 0x3ff
+
+#define PCH_DPLL_TMR_CFG 0xc6208
+
+#define PCH_SSC4_PARMS 0xc6210
+#define PCH_SSC4_AUX_PARMS 0xc6214
+
+/* CPT */
+#define PCH_DPLL_ANALOG_CTL 0xc6300
+
+#define PCH_DPLL_SEL 0xc7000
+#define TRANSA_DPLL_ENABLE (1<<3)
+#define TRANSA_DPLLA_SEL (0)
+#define TRANSA_DPLLB_SEL (1<<0)
+#define TRANSB_DPLL_ENABLE (1<<7)
+#define TRANSB_DPLLA_SEL (0<<4)
+#define TRANSB_DPLLB_SEL (1<<4)
+#define TRANSC_DPLL_ENABLE (1<<11)
+#define TRANSC_DPLLA_SEL (0<<8)
+#define TRANSC_DPLLB_SEL (1<<8)
+
+/* transcoder */
+
+#define TRANS_HTOTAL_A 0xe0000
+#define TRANS_HTOTAL_SHIFT 16
+#define TRANS_HACTIVE_SHIFT 0
+#define TRANS_HBLANK_A 0xe0004
+#define TRANS_HBLANK_END_SHIFT 16
+#define TRANS_HBLANK_START_SHIFT 0
+#define TRANS_HSYNC_A 0xe0008
+#define TRANS_HSYNC_END_SHIFT 16
+#define TRANS_HSYNC_START_SHIFT 0
+#define TRANS_VTOTAL_A 0xe000c
+#define TRANS_VTOTAL_SHIFT 16
+#define TRANS_VACTIVE_SHIFT 0
+#define TRANS_VBLANK_A 0xe0010
+#define TRANS_VBLANK_END_SHIFT 16
+#define TRANS_VBLANK_START_SHIFT 0
+#define TRANS_VSYNC_A 0xe0014
+#define TRANS_VSYNC_END_SHIFT 16
+#define TRANS_VSYNC_START_SHIFT 0
+#define TRANS_VSYNCSHIFT_A 0xe0028
+
+#define TRANSA_DATA_M1 0xe0030
+#define TRANSA_DATA_N1 0xe0034
+#define TRANSA_DATA_M2 0xe0038
+#define TRANSA_DATA_N2 0xe003c
+#define TRANSA_DP_LINK_M1 0xe0040
+#define TRANSA_DP_LINK_N1 0xe0044
+#define TRANSA_DP_LINK_M2 0xe0048
+#define TRANSA_DP_LINK_N2 0xe004c
+
+#define TRANS_HTOTAL_B 0xe1000
+#define TRANS_HBLANK_B 0xe1004
+#define TRANS_HSYNC_B 0xe1008
+#define TRANS_VTOTAL_B 0xe100c
+#define TRANS_VBLANK_B 0xe1010
+#define TRANS_VSYNC_B 0xe1014
+#define TRANS_VSYNCSHIFT_B 0xe1028
+
+#define TRANSB_DATA_M1 0xe1030
+#define TRANSB_DATA_N1 0xe1034
+#define TRANSB_DATA_M2 0xe1038
+#define TRANSB_DATA_N2 0xe103c
+#define TRANSB_DP_LINK_M1 0xe1040
+#define TRANSB_DP_LINK_N1 0xe1044
+#define TRANSB_DP_LINK_M2 0xe1048
+#define TRANSB_DP_LINK_N2 0xe104c
+
+#define TRANS_HTOTAL_C 0xe2000
+#define TRANS_HBLANK_C 0xe2004
+#define TRANS_HSYNC_C 0xe2008
+#define TRANS_VTOTAL_C 0xe200c
+#define TRANS_VBLANK_C 0xe2010
+#define TRANS_VSYNC_C 0xe2014
+#define TRANS_VSYNCSHIFT_C 0xe2028
+
+#define TRANSC_DATA_M1 0xe2030
+#define TRANSC_DATA_N1 0xe2034
+#define TRANSC_DATA_M2 0xe2038
+#define TRANSC_DATA_N2 0xe203c
+#define TRANSC_DP_LINK_M1 0xe2040
+#define TRANSC_DP_LINK_N1 0xe2044
+#define TRANSC_DP_LINK_M2 0xe2048
+#define TRANSC_DP_LINK_N2 0xe204c
+
+#define TRANSACONF 0xf0008
+#define TRANSBCONF 0xf1008
+#define TRANSCCONF 0xf2008
+#define TRANS_DISABLE (0<<31)
+#define TRANS_ENABLE (1<<31)
+#define TRANS_STATE_MASK (1<<30)
+#define TRANS_STATE_DISABLE (0<<30)
+#define TRANS_STATE_ENABLE (1<<30)
+#define TRANS_FSYNC_DELAY_HB1 (0<<27)
+#define TRANS_FSYNC_DELAY_HB2 (1<<27)
+#define TRANS_FSYNC_DELAY_HB3 (2<<27)
+#define TRANS_FSYNC_DELAY_HB4 (3<<27)
+#define TRANS_DP_AUDIO_ONLY (1<<26)
+#define TRANS_DP_VIDEO_AUDIO (0<<26)
+#define TRANS_PROGRESSIVE (0<<21)
+#define TRANS_8BPC (0<<5)
+#define TRANS_10BPC (1<<5)
+#define TRANS_6BPC (2<<5)
+#define TRANS_12BPC (3<<5)
+
+#define FDI_RXA_CHICKEN 0xc200c
+#define FDI_RXB_CHICKEN 0xc2010
+#define FDI_RX_PHASE_SYNC_POINTER_ENABLE (1)
+
+/* CPU: FDI_TX */
+#define FDI_TXA_CTL 0x60100
+#define FDI_TXB_CTL 0x61100
+#define FDI_TXC_CTL 0x62100
+#define FDI_TX_DISABLE (0<<31)
+#define FDI_TX_ENABLE (1<<31)
+#define FDI_LINK_TRAIN_PATTERN_1 (0<<28)
+#define FDI_LINK_TRAIN_PATTERN_2 (1<<28)
+#define FDI_LINK_TRAIN_PATTERN_IDLE (2<<28)
+#define FDI_LINK_TRAIN_NONE (3<<28)
+#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0<<25)
+#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1<<25)
+#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2<<25)
+#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3<<25)
+#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0<<22)
+#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1<<22)
+#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2<<22)
+#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3<<22)
+/* ILK always use 400mV 0dB for voltage swing and pre-emphasis level.
+ SNB has different settings. */
+/* SNB A-stepping */
+#define FDI_LINK_TRAIN_400MV_0DB_SNB_A (0x38<<22)
+#define FDI_LINK_TRAIN_400MV_6DB_SNB_A (0x02<<22)
+#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01<<22)
+#define FDI_LINK_TRAIN_800MV_0DB_SNB_A (0x0<<22)
+/* SNB B-stepping */
+#define FDI_LINK_TRAIN_400MV_0DB_SNB_B (0x0<<22)
+#define FDI_LINK_TRAIN_400MV_6DB_SNB_B (0x3a<<22)
+#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_B (0x39<<22)
+#define FDI_LINK_TRAIN_800MV_0DB_SNB_B (0x38<<22)
+#define FDI_LINK_TRAIN_VOL_EMP_MASK (0x3f<<22)
+#define FDI_DP_PORT_WIDTH_X1 (0<<19)
+#define FDI_DP_PORT_WIDTH_X2 (1<<19)
+#define FDI_DP_PORT_WIDTH_X3 (2<<19)
+#define FDI_DP_PORT_WIDTH_X4 (3<<19)
+#define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18)
+/* Ironlake: hardwired to 1 */
+#define FDI_TX_PLL_ENABLE (1<<14)
+/* both Tx and Rx */
+#define FDI_SCRAMBLING_ENABLE (0<<7)
+#define FDI_SCRAMBLING_DISABLE (1<<7)
+
+/* FDI_RX, FDI_X is hard-wired to Transcoder_X */
+#define FDI_RXA_CTL 0xf000c
+#define FDI_RXB_CTL 0xf100c
+#define FDI_RXC_CTL 0xf200c
+#define FDI_RX_ENABLE (1<<31)
+#define FDI_RX_DISABLE (0<<31)
+/* train, dp width same as FDI_TX */
+#define FDI_DP_PORT_WIDTH_X8 (7<<19)
+#define FDI_8BPC (0<<16)
+#define FDI_10BPC (1<<16)
+#define FDI_6BPC (2<<16)
+#define FDI_12BPC (3<<16)
+#define FDI_LINK_REVERSE_OVERWRITE (1<<15)
+#define FDI_DMI_LINK_REVERSE_MASK (1<<14)
+#define FDI_RX_PLL_ENABLE (1<<13)
+#define FDI_FS_ERR_CORRECT_ENABLE (1<<11)
+#define FDI_FE_ERR_CORRECT_ENABLE (1<<10)
+#define FDI_FS_ERR_REPORT_ENABLE (1<<9)
+#define FDI_FE_ERR_REPORT_ENABLE (1<<8)
+#define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6)
+#define FDI_SEL_RAWCLK (0<<4)
+#define FDI_SEL_PCDCLK (1<<4)
+/* CPT */
+#define FDI_AUTO_TRAINING (1<<10)
+#define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8)
+#define FDI_LINK_TRAIN_PATTERN_2_CPT (1<<8)
+#define FDI_LINK_TRAIN_PATTERN_IDLE_CPT (2<<8)
+#define FDI_LINK_TRAIN_NORMAL_CPT (3<<8)
+#define FDI_LINK_TRAIN_PATTERN_MASK_CPT (3<<8)
+
+#define FDI_RXA_MISC 0xf0010
+#define FDI_RXB_MISC 0xf1010
+#define FDI_RXC_MISC 0xf2010
+#define FDI_RXA_TUSIZE1 0xf0030
+#define FDI_RXA_TUSIZE2 0xf0038
+#define FDI_RXB_TUSIZE1 0xf1030
+#define FDI_RXB_TUSIZE2 0xf1038
+#define FDI_RXC_TUSIZE1 0xf2030
+#define FDI_RXC_TUSIZE2 0xf2038
+
+/* FDI_RX interrupt register format */
+#define FDI_RX_INTER_LANE_ALIGN (1<<10)
+#define FDI_RX_SYMBOL_LOCK (1<<9) /* train 2 */
+#define FDI_RX_BIT_LOCK (1<<8) /* train 1 */
+#define FDI_RX_TRAIN_PATTERN_2_FAIL (1<<7)
+#define FDI_RX_FS_CODE_ERR (1<<6)
+#define FDI_RX_FE_CODE_ERR (1<<5)
+#define FDI_RX_SYMBOL_ERR_RATE_ABOVE (1<<4)
+#define FDI_RX_HDCP_LINK_FAIL (1<<3)
+#define FDI_RX_PIXEL_FIFO_OVERFLOW (1<<2)
+#define FDI_RX_CROSS_CLOCK_OVERFLOW (1<<1)
+#define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1<<0)
+
+#define FDI_RXA_IIR 0xf0014
+#define FDI_RXA_IMR 0xf0018
+#define FDI_RXB_IIR 0xf1014
+#define FDI_RXB_IMR 0xf1018
+
+#define FDI_PLL_CTL_1 0xfe000
+#define FDI_PLL_CTL_2 0xfe004
+
+/* CRT */
+#define PCH_ADPA 0xe1100
+#define ADPA_TRANS_SELECT_MASK (1<<30)
+#define ADPA_TRANS_A_SELECT 0
+#define ADPA_TRANS_B_SELECT (1<<30)
+/* HPD is here */
+#define ADPA_CRT_HOTPLUG_MASK 0x03ff0000 /* bit 25-16 */
+#define ADPA_CRT_HOTPLUG_MONITOR_NONE (0<<24)
+#define ADPA_CRT_HOTPLUG_MONITOR_MASK (3<<24)
+#define ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
+#define ADPA_CRT_HOTPLUG_MONITOR_MONO (2<<24)
+#define ADPA_CRT_HOTPLUG_ENABLE (1<<23)
+#define ADPA_CRT_HOTPLUG_PERIOD_64 (0<<22)
+#define ADPA_CRT_HOTPLUG_PERIOD_128 (1<<22)
+#define ADPA_CRT_HOTPLUG_WARMUP_5MS (0<<21)
+#define ADPA_CRT_HOTPLUG_WARMUP_10MS (1<<21)
+#define ADPA_CRT_HOTPLUG_SAMPLE_2S (0<<20)
+#define ADPA_CRT_HOTPLUG_SAMPLE_4S (1<<20)
+#define ADPA_CRT_HOTPLUG_VOLTAGE_40 (0<<18)
+#define ADPA_CRT_HOTPLUG_VOLTAGE_50 (1<<18)
+#define ADPA_CRT_HOTPLUG_VOLTAGE_60 (2<<18)
+#define ADPA_CRT_HOTPLUG_VOLTAGE_70 (3<<18)
+#define ADPA_CRT_HOTPLUG_VOLREF_325MV (0<<17)
+#define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17)
+#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
+/* polarity control not changed */
+
+/* or SDVOB */
+#define HDMIB 0xe1140
+#define PORT_ENABLE (1 << 31)
+#define TRANSCODER_A (0)
+#define TRANSCODER_B (1 << 30)
+#define COLOR_FORMAT_8bpc (0)
+#define COLOR_FORMAT_12bpc (3 << 26)
+#define SDVOB_HOTPLUG_ENABLE (1 << 23)
+#define SDVO_ENCODING (0)
+#define TMDS_ENCODING (2 << 10)
+#define NULL_PACKET_VSYNC_ENABLE (1 << 9)
+#define SDVOB_BORDER_ENABLE (1 << 7)
+#define AUDIO_ENABLE (1 << 6)
+#define VSYNC_ACTIVE_HIGH (1 << 4)
+#define HSYNC_ACTIVE_HIGH (1 << 3)
+#define PORT_DETECTED (1 << 2)
+
+#define HDMIC 0xe1150
+#define HDMID 0xe1160
+#define PCH_LVDS 0xe1180
+
+#define BLC_PWM_CPU_CTL2 0x48250
+#define PWM_ENABLE (1 << 31)
+#define PWM_PIPE_A (0 << 29)
+#define PWM_PIPE_B (1 << 29)
+#define BLC_PWM_CPU_CTL 0x48254
+
+#define BLC_PWM_PCH_CTL1 0xc8250
+#define PWM_PCH_ENABLE (1 << 31)
+#define PWM_POLARITY_ACTIVE_LOW (1 << 29)
+#define PWM_POLARITY_ACTIVE_HIGH (0 << 29)
+#define PWM_POLARITY_ACTIVE_LOW2 (1 << 28)
+#define PWM_POLARITY_ACTIVE_HIGH2 (0 << 28)
+
+#define BLC_PWM_PCH_CTL2 0xc8254
+
+#define PCH_PP_STATUS 0xc7200
+#define PCH_PP_CONTROL 0xc7204
+#define EDP_FORCE_VDD (1 << 3)
+#define EDP_BLC_ENABLE (1 << 2)
+#define PANEL_POWER_RESET (1 << 1)
+#define PANEL_POWER_OFF (0 << 0)
+#define PANEL_POWER_ON (1 << 0)
+#define PCH_PP_ON_DELAYS 0xc7208
+#define EDP_PANEL (1 << 30)
+#define PCH_PP_OFF_DELAYS 0xc720c
+#define PCH_PP_DIVISOR 0xc7210
+
+#define AUD_CONFIG 0x62000
+#define AUD_DEBUG 0x62010
+#define AUD_VID_DID 0x62020
+#define AUD_RID 0x62024
+#define AUD_SUBN_CNT 0x62028
+#define AUD_FUNC_GRP 0x62040
+#define AUD_SUBN_CNT2 0x62044
+#define AUD_GRP_CAP 0x62048
+#define AUD_PWRST 0x6204c
+#define AUD_SUPPWR 0x62050
+#define AUD_SID 0x62054
+#define AUD_OUT_CWCAP 0x62070
+#define AUD_OUT_PCMSIZE 0x62074
+#define AUD_OUT_STR 0x62078
+#define AUD_OUT_DIG_CNVT 0x6207c
+#define AUD_OUT_CH_STR 0x62080
+#define AUD_OUT_STR_DESC 0x62084
+#define AUD_PINW_CAP 0x620a0
+#define AUD_PIN_CAP 0x620a4
+#define AUD_PINW_CONNLNG 0x620a8
+#define AUD_PINW_CONNLST 0x620ac
+#define AUD_PINW_CNTR 0x620b0
+#define AUD_PINW_UNSOLRESP 0x620b8
+#define AUD_CNTL_ST 0x620b4
+#define AUD_PINW_CONFIG 0x620bc
+#define AUD_HDMIW_STATUS 0x620d4
+#define AUD_HDMIW_HDMIEDID 0x6210c
+#define AUD_HDMIW_INFOFR 0x62118
+#define AUD_CONV_CHCNT 0x62120
+#define AUD_CTS_ENABLE 0x62128
+
+#define VIDEO_DIP_CTL 0x61170
+#define VIDEO_DIP_DATA 0x61178
+
+/* CPT */
+#define TRANS_DP_CTL_A 0xe0300
+#define TRANS_DP_CTL_B 0xe1300
+#define TRANS_DP_CTL_C 0xe2300
+#define TRANS_DP_OUTPUT_ENABLE (1<<31)
+#define TRANS_DP_PORT_SEL_B (0<<29)
+#define TRANS_DP_PORT_SEL_C (1<<29)
+#define TRANS_DP_PORT_SEL_D (2<<29)
+#define TRANS_DP_PORT_SEL_MASK (3<<29)
+#define TRANS_DP_AUDIO_ONLY (1<<26)
+#define TRANS_DP_ENH_FRAMING (1<<18)
+#define TRANS_DP_8BPC (0<<9)
+#define TRANS_DP_10BPC (1<<9)
+#define TRANS_DP_6BPC (2<<9)
+#define TRANS_DP_12BPC (3<<9)
+#define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4)
+#define TRANS_DP_VSYNC_ACTIVE_LOW 0
+#define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3)
+#define TRANS_DP_HSYNC_ACTIVE_LOW 0
+
+/* Debug regs */
+#define GEN6_TD_CTL 0x7000 /* <= GEN5 was at 0x8000 */
+#define GEN6_TD_CTL_FORCE_TD_BKPT (1<<4)
+
+/* Port debugging
+ */
+
+#define PORT_DBG 0x42308
+#define PORT_DBG_DRRS_HW_STATE_OFF (0<<30)
+#define PORT_DBG_DRRS_HW_STATE_LOW (1<<30)
+#define PORT_DBG_DRRS_HW_STATE_HIGH (2<<30)
+
+/* RC6 residence counters
+ */
+#define RC6_RESIDENCY_TIME 0x138108
+#define RC6p_RESIDENCY_TIME 0x13810C
+#define RC6pp_RESIDENCY_TIME 0x138110
+
+#define GEN6_RPNSWREQ 0xA008
+#define GEN6_RC_VIDEO_FREQ 0xA00C
+#define GEN6_RC_CONTROL 0xA090
+#define GEN6_RP_DOWN_TIMEOUT 0xA010
+#define GEN6_RP_INTERRUPT_LIMITS 0xA014
+#define GEN6_RPSTAT1 0xA01C
+#define GEN6_RP_CONTROL 0xA024
+#define GEN6_RP_UP_THRESHOLD 0xA02C
+#define GEN6_RP_DOWN_THRESHOLD 0xA030
+#define GEN6_RP_CUR_UP_EI 0xA050
+#define GEN6_RP_CUR_UP 0xA054
+#define GEN6_RP_PREV_UP 0xA058
+#define GEN6_RP_CUR_DOWN_EI 0xA05C
+#define GEN6_RP_CUR_DOWN 0xA060
+#define GEN6_RP_PREV_DOWN 0xA064
+#define GEN6_RP_UP_EI 0xA068
+#define GEN6_RP_DOWN_EI 0xA06C
+#define GEN6_RP_IDLE_HYSTERSIS 0xA070
+#define GEN6_RC_STATE 0xA094
+#define GEN6_RC1_WAKE_RATE_LIMIT 0xA098
+#define GEN6_RC6_WAKE_RATE_LIMIT 0xA09C
+#define GEN6_RC6pp_WAKE_RATE_LIMIT 0xA0A0
+#define GEN6_RC_EVALUATION_INTERVAL 0xA0A8
+#define GEN6_RC_IDLE_HYSTERSIS 0xA0AC
+#define GEN6_RC_SLEEP 0xA0B0
+#define GEN6_RC1e_THRESHOLD 0xA0B4
+#define GEN6_RC6_THRESHOLD 0xA0B8
+#define GEN6_RC6p_THRESHOLD 0xA0BC
+#define GEN6_RC6pp_THRESHOLD 0xA0C0
+#define GEN6_PMINTRMSK 0xA168
+#define GEN6_RC_EVALUATION_INTERVAL 0xA0A8
+#define GEN6_RC_IDLE_HYSTERSIS 0xA0AC
+#define GEN6_PMIER 0x4402C
+#define GEN6_PMIMR 0x44024 /* rps_lock */
+#define GEN6_PMINTRMSK 0xA168
+
+/* Haswell-related items */
+
+/* HSW Power Wells */
+#define HSW_PWR_WELL_CTL1 0x45400 /* BIOS */
+#define HSW_PWR_WELL_CTL2 0x45404 /* Driver */
+#define HSW_PWR_WELL_CTL3 0x45408 /* KVMR */
+#define HSW_PWR_WELL_CTL4 0x4540C /* Debug */
+#define HSW_PWR_WELL_ENABLE (1<<31)
+#define HSW_PWR_WELL_STATE (1<<30)
+#define HSW_PWR_WELL_CTL5 0x45410
+#define HSW_PWR_WELL_ENABLE_SINGLE_STEP (1<<31)
+#define HSW_PWR_WELL_PWR_GATE_OVERRIDE (1<<20)
+#define HSW_PWR_WELL_FORCE_ON (1<<19)
+#define HSW_PWR_WELL_CTL6 0x45414
+
+/* Per-pipe DDI Function Control */
+#define PIPE_DDI_FUNC_CTL_A 0x60400
+#define PIPE_DDI_FUNC_CTL_B 0x61400
+#define PIPE_DDI_FUNC_CTL_C 0x62400
+#define PIPE_DDI_FUNC_CTL_EDP 0x6F400
+#define DDI_FUNC_CTL(pipe) _PIPE(pipe, \
+ PIPE_DDI_FUNC_CTL_A, \
+ PIPE_DDI_FUNC_CTL_B)
+#define PIPE_DDI_FUNC_ENABLE (1<<31)
+/* Those bits are ignored by pipe EDP since it can only connect to DDI A */
+#define PIPE_DDI_PORT_MASK (0xf<<28)
+#define PIPE_DDI_SELECT_PORT(x) ((x)<<28)
+#define PIPE_DDI_MODE_SELECT_HDMI (0<<24)
+#define PIPE_DDI_MODE_SELECT_DVI (1<<24)
+#define PIPE_DDI_MODE_SELECT_DP_SST (2<<24)
+#define PIPE_DDI_MODE_SELECT_DP_MST (3<<24)
+#define PIPE_DDI_MODE_SELECT_FDI (4<<24)
+#define PIPE_DDI_BPC_8 (0<<20)
+#define PIPE_DDI_BPC_10 (1<<20)
+#define PIPE_DDI_BPC_6 (2<<20)
+#define PIPE_DDI_BPC_12 (3<<20)
+#define PIPE_DDI_BFI_ENABLE (1<<4)
+#define PIPE_DDI_PORT_WIDTH_X1 (0<<1)
+#define PIPE_DDI_PORT_WIDTH_X2 (1<<1)
+#define PIPE_DDI_PORT_WIDTH_X4 (3<<1)
+
+/* DisplayPort Transport Control */
+#define DP_TP_CTL_A 0x64040
+#define DP_TP_CTL_B 0x64140
+#define DP_TP_CTL_C 0x64240
+#define DP_TP_CTL_D 0x64340
+#define DP_TP_CTL_E 0x64440
+#define DP_TP_CTL_ENABLE (1<<31)
+#define DP_TP_CTL_MODE_SST (0<<27)
+#define DP_TP_CTL_MODE_MST (1<<27)
+#define DP_TP_CTL_ENHANCED_FRAME_ENABLE (1<<18)
+#define DP_TP_CTL_FDI_AUTOTRAIN (1<<15)
+#define DP_TP_CTL_LINK_TRAIN_MASK (7<<8)
+#define DP_TP_CTL_LINK_TRAIN_PAT1 (0<<8)
+#define DP_TP_CTL_LINK_TRAIN_PAT2 (1<<8)
+#define DP_TP_CTL_LINK_TRAIN_NORMAL (3<<8)
+
+/* DisplayPort Transport Status */
+#define DP_TP_STATUS_A 0x64044
+#define DP_TP_STATUS_B 0x64144
+#define DP_TP_STATUS_C 0x64244
+#define DP_TP_STATUS_D 0x64344
+#define DP_TP_STATUS_E 0x64444
+#define DP_TP_STATUS_AUTOTRAIN_DONE (1<<12)
+
+/* DDI Buffer Control */
+#define DDI_BUF_CTL_A 0x64000
+#define DDI_BUF_CTL_B 0x64100
+#define DDI_BUF_CTL_C 0x64200
+#define DDI_BUF_CTL_D 0x64300
+#define DDI_BUF_CTL_E 0x64400
+#define DDI_BUF_CTL_ENABLE (1<<31)
+#define DDI_BUF_EMP_400MV_0DB_HSW (0<<24) /* Sel0 */
+#define DDI_BUF_EMP_400MV_3_5DB_HSW (1<<24) /* Sel1 */
+#define DDI_BUF_EMP_400MV_6DB_HSW (2<<24) /* Sel2 */
+#define DDI_BUF_EMP_400MV_9_5DB_HSW (3<<24) /* Sel3 */
+#define DDI_BUF_EMP_600MV_0DB_HSW (4<<24) /* Sel4 */
+#define DDI_BUF_EMP_600MV_3_5DB_HSW (5<<24) /* Sel5 */
+#define DDI_BUF_EMP_600MV_6DB_HSW (6<<24) /* Sel6 */
+#define DDI_BUF_EMP_800MV_0DB_HSW (7<<24) /* Sel7 */
+#define DDI_BUF_EMP_800MV_3_5DB_HSW (8<<24) /* Sel8 */
+#define DDI_BUF_EMP_MASK (0xf<<24)
+#define DDI_BUF_IS_IDLE (1<<7)
+#define DDI_PORT_WIDTH_X1 (0<<1)
+#define DDI_PORT_WIDTH_X2 (1<<1)
+#define DDI_PORT_WIDTH_X4 (3<<1)
+#define DDI_INIT_DISPLAY_DETECTED (1<<0)
+
+/* LPT PIXCLK_GATE */
+#define PIXCLK_GATE 0xC6020
+#define PIXCLK_GATE_UNGATE 1<<0
+#define PIXCLK_GATE_GATE 0<<0
+
+/* SPLL */
+#define SPLL_CTL 0x46020
+#define SPLL_PLL_ENABLE (1<<31)
+#define SPLL_PLL_SCC (1<<28)
+#define SPLL_PLL_NON_SCC (2<<28)
+#define SPLL_PLL_FREQ_810MHz (0<<26)
+#define SPLL_PLL_FREQ_1350MHz (1<<26)
+
+/* WRPLL */
+#define WRPLL_CTL1 0x46040
+#define WRPLL_CTL2 0x46060
+#define WRPLL_PLL_ENABLE (1<<31)
+#define WRPLL_PLL_SELECT_SSC (0x01<<28)
+#define WRPLL_PLL_SELECT_NON_SCC (0x02<<28)
+#define WRPLL_PLL_SELECT_LCPLL_2700 (0x03<<28)
+/* WRPLL divider programming */
+#define WRPLL_DIVIDER_REFERENCE(x) ((x)<<0)
+#define WRPLL_DIVIDER_POST(x) ((x)<<8)
+#define WRPLL_DIVIDER_FEEDBACK(x) ((x)<<16)
+
+/* Port clock selection */
+#define PORT_CLK_SEL_A 0x46100
+#define PORT_CLK_SEL_B 0x46104
+#define PORT_CLK_SEL_C 0x46108
+#define PORT_CLK_SEL_D 0x4610C
+#define PORT_CLK_SEL_E 0x46110
+#define PORT_CLK_SEL_LCPLL_2700 (0<<29)
+#define PORT_CLK_SEL_LCPLL_1350 (1<<29)
+#define PORT_CLK_SEL_LCPLL_810 (2<<29)
+#define PORT_CLK_SEL_SPLL (3<<29)
+#define PORT_CLK_SEL_WRPLL1 (4<<29)
+#define PORT_CLK_SEL_WRPLL2 (5<<29)
+
+/* Pipe clock selection */
+#define PIPE_CLK_SEL_A 0x46140
+#define PIPE_CLK_SEL_B 0x46144
+#define PIPE_CLK_SEL_C 0x46148
+/* For each pipe, we need to select the corresponding port clock */
+#define PIPE_CLK_SEL_DISABLED (0x0<<29)
+#define PIPE_CLK_SEL_PORT(x) ((x+1)<<29)
+
+/* LCPLL Control */
+#define LCPLL_CTL 0x130040
+#define LCPLL_PLL_DISABLE (1<<31)
+#define LCPLL_PLL_LOCK (1<<30)
+#define LCPLL_CD_CLOCK_DISABLE (1<<25)
+#define LCPLL_CD2X_CLOCK_DISABLE (1<<23)
+
+/* Pipe WM_LINETIME - watermark line time */
+#define PIPE_WM_LINETIME_A 0x45270
+#define PIPE_WM_LINETIME_B 0x45274
+#define PIPE_WM_LINETIME_C 0x45278
+#define PIPE_WM_LINETIME_MASK (0x1ff)
+#define PIPE_WM_LINETIME_TIME(x) ((x))
+#define PIPE_WM_LINETIME_IPS_LINETIME_MASK (0x1ff<<16)
+#define PIPE_WM_LINETIME_IPS_LINETIME(x) ((x)<<16)
+
+/* SFUSE_STRAP */
+#define SFUSE_STRAP 0xc2014
+#define SFUSE_STRAP_DDIB_DETECTED (1<<2)
+#define SFUSE_STRAP_DDIC_DETECTED (1<<1)
+#define SFUSE_STRAP_DDID_DETECTED (1<<0)
+
+/* Valleyview related items */
+
+/* Valleyview DPIO registers */
+#define VLV_DISPLAY_BASE 0x180000
+#define DPIO_PKT 0x2100
+#define DPIO_RID (0 << 24)
+#define DPIO_OP_WRITE (1 << 16)
+#define DPIO_OP_READ (0 << 16)
+#define DPIO_PORTID (0x12 << 8)
+#define DPIO_BYTE (0xf << 4)
+#define DPIO_BUSY (1 << 0)
+#define DPIO_DATA 0x2104
+#define DPIO_REG 0x2108
+
+#endif /* _I810_REG_H */
diff --git a/lib/intel_reg_map.c b/lib/intel_reg_map.c
new file mode 100644
index 00000000..0c8d49c9
--- /dev/null
+++ b/lib/intel_reg_map.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include "intel_gpu_tools.h"
+
+static struct intel_register_range gen_bwcl_register_map[] = {
+ {0x00000000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00001000, 0x00000fff, INTEL_RANGE_RSVD},
+ {0x00002000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00003000, 0x000001ff, INTEL_RANGE_RW},
+ {0x00003200, 0x00000dff, INTEL_RANGE_RW},
+ {0x00004000, 0x000003ff, INTEL_RANGE_RSVD},
+ {0x00004400, 0x00000bff, INTEL_RANGE_RSVD},
+ {0x00005000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00006000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00007000, 0x000003ff, INTEL_RANGE_RW},
+ {0x00007400, 0x000014ff, INTEL_RANGE_RW},
+ {0x00008900, 0x000006ff, INTEL_RANGE_RSVD},
+ {0x00009000, 0x00000fff, INTEL_RANGE_RSVD},
+ {0x0000a000, 0x00000fff, INTEL_RANGE_RW},
+ {0x0000b000, 0x00004fff, INTEL_RANGE_RSVD},
+ {0x00010000, 0x00003fff, INTEL_RANGE_RW},
+ {0x00014000, 0x0001bfff, INTEL_RANGE_RSVD},
+ {0x00030000, 0x0000ffff, INTEL_RANGE_RW},
+ {0x00040000, 0x0001ffff, INTEL_RANGE_RSVD},
+ {0x00060000, 0x0000ffff, INTEL_RANGE_RW},
+ {0x00070000, 0x00002fff, INTEL_RANGE_RW},
+ {0x00073000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00074000, 0x0000bfff, INTEL_RANGE_RSVD},
+ {0x00000000, 0x00000000, INTEL_RANGE_END}
+};
+
+static struct intel_register_range gen4_register_map[] = {
+ {0x00000000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00001000, 0x00000fff, INTEL_RANGE_RSVD},
+ {0x00002000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00003000, 0x000001ff, INTEL_RANGE_RW},
+ {0x00003200, 0x00000dff, INTEL_RANGE_RW},
+ {0x00004000, 0x000003ff, INTEL_RANGE_RW},
+ {0x00004400, 0x00000bff, INTEL_RANGE_RW},
+ {0x00005000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00006000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00007000, 0x000003ff, INTEL_RANGE_RW},
+ {0x00007400, 0x000014ff, INTEL_RANGE_RW},
+ {0x00008900, 0x000006ff, INTEL_RANGE_RSVD},
+ {0x00009000, 0x00000fff, INTEL_RANGE_RSVD},
+ {0x0000a000, 0x00000fff, INTEL_RANGE_RW},
+ {0x0000b000, 0x00004fff, INTEL_RANGE_RSVD},
+ {0x00010000, 0x00003fff, INTEL_RANGE_RW},
+ {0x00014000, 0x0001bfff, INTEL_RANGE_RSVD},
+ {0x00030000, 0x0000ffff, INTEL_RANGE_RW},
+ {0x00040000, 0x0001ffff, INTEL_RANGE_RSVD},
+ {0x00060000, 0x0000ffff, INTEL_RANGE_RW},
+ {0x00070000, 0x00002fff, INTEL_RANGE_RW},
+ {0x00073000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00074000, 0x0000bfff, INTEL_RANGE_RSVD},
+ {0x00000000, 0x00000000, INTEL_RANGE_END}
+};
+
+/* The documentation is a little sketchy on these register ranges. */
+static struct intel_register_range gen6_gt_register_map[] = {
+ {0x00000000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00001000, 0x00000fff, INTEL_RANGE_RSVD},
+ {0x00002000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00003000, 0x000001ff, INTEL_RANGE_RW},
+ {0x00003200, 0x00000dff, INTEL_RANGE_RW},
+ {0x00004000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00005000, 0x0000017f, INTEL_RANGE_RW},
+ {0x00005180, 0x00000e7f, INTEL_RANGE_RW},
+ {0x00006000, 0x00001fff, INTEL_RANGE_RW},
+ {0x00008000, 0x000007ff, INTEL_RANGE_RW},
+ {0x00008800, 0x000000ff, INTEL_RANGE_RSVD},
+ {0x00008900, 0x000006ff, INTEL_RANGE_RW},
+ {0x00009000, 0x00000fff, INTEL_RANGE_RSVD},
+ {0x0000a000, 0x00000fff, INTEL_RANGE_RW},
+ {0x0000b000, 0x00004fff, INTEL_RANGE_RSVD},
+ {0x00010000, 0x00001fff, INTEL_RANGE_RW},
+ {0x00012000, 0x000003ff, INTEL_RANGE_RW},
+ {0x00012400, 0x00000bff, INTEL_RANGE_RW},
+ {0x00013000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00014000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00015000, 0x0000cfff, INTEL_RANGE_RW},
+ {0x00022000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00023000, 0x00000fff, INTEL_RANGE_RSVD},
+ {0x00024000, 0x00000fff, INTEL_RANGE_RW},
+ {0x00025000, 0x0000afff, INTEL_RANGE_RSVD},
+ {0x00030000, 0x0000ffff, INTEL_RANGE_RW},
+ {0x00040000, 0x0000ffff, INTEL_RANGE_RW},
+ {0x00050000, 0x0000ffff, INTEL_RANGE_RW},
+ {0x00060000, 0x0000ffff, INTEL_RANGE_RW},
+ {0x00070000, 0x00003fff, INTEL_RANGE_RW},
+ {0x00074000, 0x0008bfff, INTEL_RANGE_RSVD},
+ {0x00100000, 0x00007fff, INTEL_RANGE_RW},
+ {0x00108000, 0x00037fff, INTEL_RANGE_RSVD},
+ {0x00140000, 0x0003ffff, INTEL_RANGE_RW},
+ {0x00000000, 0x00000000, INTEL_RANGE_END}
+};
+
+struct intel_register_map
+intel_get_register_map(uint32_t devid)
+{
+ struct intel_register_map map;
+ const int gen = intel_gen(devid);
+
+ if (gen >= 6) {
+ map.map = gen6_gt_register_map;
+ map.top = 0x180000;
+ } else if (IS_BROADWATER(devid) || IS_CRESTLINE(devid)) {
+ map.map = gen_bwcl_register_map;
+ map.top = 0x80000;
+ } else if (gen >= 4) {
+ map.map = gen4_register_map;
+ map.top = 0x80000;
+ } else {
+ fprintf(stderr, "Gen2/3 Ranges are not supported. Please use "
+ "unsafe access.");
+ abort();
+ }
+
+ map.alignment_mask = 0x3;
+
+ return map;
+}
+
+struct intel_register_range *
+intel_get_register_range(struct intel_register_map map, uint32_t offset, int mode)
+{
+ struct intel_register_range *range = map.map;
+ uint32_t align = map.alignment_mask;
+
+ if (offset & map.alignment_mask)
+ return NULL;
+
+ if (offset >= map.top)
+ return NULL;
+
+ while (!(range->flags & INTEL_RANGE_END)) {
+ /* list is assumed to be in order */
+ if (offset < range->base)
+ break;
+
+ if ( (offset >= range->base) &&
+ (offset + align) <= (range->base + range->size)) {
+ if ((mode & range->flags) == mode)
+ return range;
+ }
+ range++;
+ }
+
+ return NULL;
+}
diff --git a/lib/rendercopy.h b/lib/rendercopy.h
new file mode 100644
index 00000000..5989d503
--- /dev/null
+++ b/lib/rendercopy.h
@@ -0,0 +1,81 @@
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <getopt.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+struct scratch_buf {
+ drm_intel_bo *bo;
+ uint32_t stride;
+ uint32_t tiling;
+ uint32_t *data;
+ uint32_t *cpu_mapping;
+ uint32_t size;
+ unsigned num_tiles;
+};
+
+static inline void emit_vertex_2s(struct intel_batchbuffer *batch,
+ int16_t x, int16_t y)
+{
+ OUT_BATCH((uint16_t)y << 16 | (uint16_t)x);
+}
+
+static inline void emit_vertex(struct intel_batchbuffer *batch,
+ float f)
+{
+ union { float f; uint32_t ui; } u;
+ u.f = f;
+ OUT_BATCH(u.ui);
+}
+
+static inline void emit_vertex_normalized(struct intel_batchbuffer *batch,
+ float f, float total)
+{
+ union { float f; uint32_t ui; } u;
+ u.f = f / total;
+ OUT_BATCH(u.ui);
+}
+
+static inline unsigned buf_width(struct scratch_buf *buf)
+{
+ return buf->stride/sizeof(uint32_t);
+}
+
+static inline unsigned buf_height(struct scratch_buf *buf)
+{
+ return buf->size/buf->stride;
+}
+
+typedef void (*render_copyfunc_t)(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned width, unsigned height,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y);
+
+void gen7_render_copyfunc(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned width, unsigned height,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y);
+void gen6_render_copyfunc(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned width, unsigned height,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y);
+void gen3_render_copyfunc(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned width, unsigned height,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y);
+void gen2_render_copyfunc(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned width, unsigned height,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y);
diff --git a/lib/rendercopy_gen6.c b/lib/rendercopy_gen6.c
new file mode 100644
index 00000000..dafee88a
--- /dev/null
+++ b/lib/rendercopy_gen6.c
@@ -0,0 +1,599 @@
+#include "rendercopy.h"
+#include "gen6_render.h"
+
+#include <assert.h>
+
+#define ALIGN(x, y) (((x) + (y)-1) & ~((y)-1))
+#define VERTEX_SIZE (3*4)
+
+static const uint32_t ps_kernel_nomask_affine[][4] = {
+ { 0x0060005a, 0x204077be, 0x000000c0, 0x008d0040 },
+ { 0x0060005a, 0x206077be, 0x000000c0, 0x008d0080 },
+ { 0x0060005a, 0x208077be, 0x000000d0, 0x008d0040 },
+ { 0x0060005a, 0x20a077be, 0x000000d0, 0x008d0080 },
+ { 0x00000201, 0x20080061, 0x00000000, 0x00000000 },
+ { 0x00600001, 0x20200022, 0x008d0000, 0x00000000 },
+ { 0x02800031, 0x21c01cc9, 0x00000020, 0x0a8a0001 },
+ { 0x00600001, 0x204003be, 0x008d01c0, 0x00000000 },
+ { 0x00600001, 0x206003be, 0x008d01e0, 0x00000000 },
+ { 0x00600001, 0x208003be, 0x008d0200, 0x00000000 },
+ { 0x00600001, 0x20a003be, 0x008d0220, 0x00000000 },
+ { 0x00600001, 0x20c003be, 0x008d0240, 0x00000000 },
+ { 0x00600001, 0x20e003be, 0x008d0260, 0x00000000 },
+ { 0x00600001, 0x210003be, 0x008d0280, 0x00000000 },
+ { 0x00600001, 0x212003be, 0x008d02a0, 0x00000000 },
+ { 0x05800031, 0x24001cc8, 0x00000040, 0x90019000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+static uint32_t
+batch_used(struct intel_batchbuffer *batch)
+{
+ return batch->ptr - batch->buffer;
+}
+
+static uint32_t
+batch_align(struct intel_batchbuffer *batch, uint32_t align)
+{
+ uint32_t offset = batch_used(batch);
+ offset = ALIGN(offset, align);
+ batch->ptr = batch->buffer + offset;
+ return offset;
+}
+
+static uint32_t
+batch_round_upto(struct intel_batchbuffer *batch, uint32_t divisor)
+{
+ uint32_t offset = batch_used(batch);
+ offset = (offset + divisor-1) / divisor * divisor;
+ batch->ptr = batch->buffer + offset;
+ return offset;
+}
+
+static void *
+batch_alloc(struct intel_batchbuffer *batch, uint32_t size, uint32_t align)
+{
+ uint32_t offset = batch_align(batch, align);
+ batch->ptr += size;
+ return memset(batch->buffer + offset, 0, size);
+}
+
+static uint32_t
+batch_offset(struct intel_batchbuffer *batch, void *ptr)
+{
+ return (uint8_t *)ptr - batch->buffer;
+}
+
+static uint32_t
+batch_copy(struct intel_batchbuffer *batch, const void *ptr, uint32_t size, uint32_t align)
+{
+ return batch_offset(batch, memcpy(batch_alloc(batch, size, align), ptr, size));
+}
+
+static void
+gen6_render_flush(struct intel_batchbuffer *batch, uint32_t batch_end)
+{
+ int ret;
+
+ ret = drm_intel_bo_subdata(batch->bo, 0, 4096, batch->buffer);
+ if (ret == 0)
+ ret = drm_intel_bo_mrb_exec(batch->bo, batch_end,
+ NULL, 0, 0, 0);
+ assert(ret == 0);
+}
+
+static uint32_t
+gen6_bind_buf(struct intel_batchbuffer *batch, struct scratch_buf *buf,
+ uint32_t format, int is_dst)
+{
+ struct gen6_surface_state *ss;
+ uint32_t write_domain, read_domain;
+ int ret;
+
+ if (is_dst) {
+ write_domain = read_domain = I915_GEM_DOMAIN_RENDER;
+ } else {
+ write_domain = 0;
+ read_domain = I915_GEM_DOMAIN_SAMPLER;
+ }
+
+ ss = batch_alloc(batch, sizeof(*ss), 32);
+ ss->ss0.surface_type = GEN6_SURFACE_2D;
+ ss->ss0.surface_format = format;
+
+ ss->ss0.data_return_format = GEN6_SURFACERETURNFORMAT_FLOAT32;
+ ss->ss0.color_blend = 1;
+ ss->ss1.base_addr = buf->bo->offset;
+
+ ret = drm_intel_bo_emit_reloc(batch->bo,
+ batch_offset(batch, ss) + 4,
+ buf->bo, 0,
+ read_domain, write_domain);
+ assert(ret == 0);
+
+ ss->ss2.height = buf_height(buf) - 1;
+ ss->ss2.width = buf_width(buf) - 1;
+ ss->ss3.pitch = buf->stride - 1;
+ ss->ss3.tiled_surface = buf->tiling != I915_TILING_NONE;
+ ss->ss3.tile_walk = buf->tiling == I915_TILING_Y;
+
+ return batch_offset(batch, ss);
+}
+
+static uint32_t
+gen6_bind_surfaces(struct intel_batchbuffer *batch,
+ struct scratch_buf *src,
+ struct scratch_buf *dst)
+{
+ uint32_t *binding_table;
+
+ binding_table = batch_alloc(batch, 32, 32);
+
+ binding_table[0] =
+ gen6_bind_buf(batch, dst, GEN6_SURFACEFORMAT_B8G8R8A8_UNORM, 1);
+ binding_table[1] =
+ gen6_bind_buf(batch, src, GEN6_SURFACEFORMAT_B8G8R8A8_UNORM, 0);
+
+ return batch_offset(batch, binding_table);
+}
+
+static void
+gen6_emit_sip(struct intel_batchbuffer *batch)
+{
+ OUT_BATCH(GEN6_STATE_SIP | 0);
+ OUT_BATCH(0);
+}
+
+static void
+gen6_emit_urb(struct intel_batchbuffer *batch)
+{
+ OUT_BATCH(GEN6_3DSTATE_URB | (3 - 2));
+ OUT_BATCH((1 - 1) << GEN6_3DSTATE_URB_VS_SIZE_SHIFT |
+ 24 << GEN6_3DSTATE_URB_VS_ENTRIES_SHIFT); /* at least 24 on GEN6 */
+ OUT_BATCH(0 << GEN6_3DSTATE_URB_GS_SIZE_SHIFT |
+ 0 << GEN6_3DSTATE_URB_GS_ENTRIES_SHIFT); /* no GS thread */
+}
+
+static void
+gen6_emit_state_base_address(struct intel_batchbuffer *batch)
+{
+ OUT_BATCH(GEN6_STATE_BASE_ADDRESS | (10 - 2));
+ OUT_BATCH(0); /* general */
+ OUT_RELOC(batch->bo, /* surface */
+ I915_GEM_DOMAIN_INSTRUCTION, 0,
+ BASE_ADDRESS_MODIFY);
+ OUT_RELOC(batch->bo, /* instruction */
+ I915_GEM_DOMAIN_INSTRUCTION, 0,
+ BASE_ADDRESS_MODIFY);
+ OUT_BATCH(0); /* indirect */
+ OUT_RELOC(batch->bo, /* dynamic */
+ I915_GEM_DOMAIN_INSTRUCTION, 0,
+ BASE_ADDRESS_MODIFY);
+
+ /* upper bounds, disable */
+ OUT_BATCH(0);
+ OUT_BATCH(BASE_ADDRESS_MODIFY);
+ OUT_BATCH(0);
+ OUT_BATCH(BASE_ADDRESS_MODIFY);
+}
+
+static void
+gen6_emit_viewports(struct intel_batchbuffer *batch, uint32_t cc_vp)
+{
+ OUT_BATCH(GEN6_3DSTATE_VIEWPORT_STATE_POINTERS |
+ GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_CC |
+ (4 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(cc_vp);
+}
+
+static void
+gen6_emit_vs(struct intel_batchbuffer *batch)
+{
+ /* disable VS constant buffer */
+ OUT_BATCH(GEN6_3DSTATE_CONSTANT_VS | (5 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN6_3DSTATE_VS | (6 - 2));
+ OUT_BATCH(0); /* no VS kernel */
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0); /* pass-through */
+}
+
+static void
+gen6_emit_gs(struct intel_batchbuffer *batch)
+{
+ /* disable GS constant buffer */
+ OUT_BATCH(GEN6_3DSTATE_CONSTANT_GS | (5 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN6_3DSTATE_GS | (7 - 2));
+ OUT_BATCH(0); /* no GS kernel */
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0); /* pass-through */
+}
+
+static void
+gen6_emit_clip(struct intel_batchbuffer *batch)
+{
+ OUT_BATCH(GEN6_3DSTATE_CLIP | (4 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH(0); /* pass-through */
+ OUT_BATCH(0);
+}
+
+static void
+gen6_emit_wm_constants(struct intel_batchbuffer *batch)
+{
+ /* disable WM constant buffer */
+ OUT_BATCH(GEN6_3DSTATE_CONSTANT_PS | (5 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+}
+
+static void
+gen6_emit_null_depth_buffer(struct intel_batchbuffer *batch)
+{
+ OUT_BATCH(GEN6_3DSTATE_DEPTH_BUFFER | (7 - 2));
+ OUT_BATCH(GEN6_SURFACE_NULL << GEN6_3DSTATE_DEPTH_BUFFER_TYPE_SHIFT |
+ GEN6_DEPTHFORMAT_D32_FLOAT << GEN6_3DSTATE_DEPTH_BUFFER_FORMAT_SHIFT);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN6_3DSTATE_CLEAR_PARAMS | (2 - 2));
+ OUT_BATCH(0);
+}
+
+static void
+gen6_emit_invariant(struct intel_batchbuffer *batch)
+{
+ OUT_BATCH(GEN6_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+
+ OUT_BATCH(GEN6_3DSTATE_MULTISAMPLE | (3 - 2));
+ OUT_BATCH(GEN6_3DSTATE_MULTISAMPLE_PIXEL_LOCATION_CENTER |
+ GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_1); /* 1 sample/pixel */
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN6_3DSTATE_SAMPLE_MASK | (2 - 2));
+ OUT_BATCH(1);
+}
+
+static void
+gen6_emit_cc(struct intel_batchbuffer *batch, uint32_t blend)
+{
+ OUT_BATCH(GEN6_3DSTATE_CC_STATE_POINTERS | (4 - 2));
+ OUT_BATCH(blend | 1);
+ OUT_BATCH(1024 | 1);
+ OUT_BATCH(1024 | 1);
+}
+
+static void
+gen6_emit_sampler(struct intel_batchbuffer *batch, uint32_t state)
+{
+ OUT_BATCH(GEN6_3DSTATE_SAMPLER_STATE_POINTERS |
+ GEN6_3DSTATE_SAMPLER_STATE_MODIFY_PS |
+ (4 - 2));
+ OUT_BATCH(0); /* VS */
+ OUT_BATCH(0); /* GS */
+ OUT_BATCH(state);
+}
+
+static void
+gen6_emit_sf(struct intel_batchbuffer *batch)
+{
+ OUT_BATCH(GEN6_3DSTATE_SF | (20 - 2));
+ OUT_BATCH(1 << GEN6_3DSTATE_SF_NUM_OUTPUTS_SHIFT |
+ 1 << GEN6_3DSTATE_SF_URB_ENTRY_READ_LENGTH_SHIFT |
+ 1 << GEN6_3DSTATE_SF_URB_ENTRY_READ_OFFSET_SHIFT);
+ OUT_BATCH(0);
+ OUT_BATCH(GEN6_3DSTATE_SF_CULL_NONE);
+ OUT_BATCH(2 << GEN6_3DSTATE_SF_TRIFAN_PROVOKE_SHIFT); /* DW4 */
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0); /* DW9 */
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0); /* DW14 */
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0); /* DW19 */
+}
+
+static void
+gen6_emit_wm(struct intel_batchbuffer *batch, int kernel)
+{
+ OUT_BATCH(GEN6_3DSTATE_WM | (9 - 2));
+ OUT_BATCH(kernel);
+ OUT_BATCH(1 << GEN6_3DSTATE_WM_SAMPLER_COUNT_SHIFT |
+ 2 << GEN6_3DSTATE_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT);
+ OUT_BATCH(0);
+ OUT_BATCH(6 << GEN6_3DSTATE_WM_DISPATCH_START_GRF_0_SHIFT); /* DW4 */
+ OUT_BATCH((40 - 1) << GEN6_3DSTATE_WM_MAX_THREADS_SHIFT |
+ GEN6_3DSTATE_WM_DISPATCH_ENABLE |
+ GEN6_3DSTATE_WM_16_DISPATCH_ENABLE);
+ OUT_BATCH(1 << GEN6_3DSTATE_WM_NUM_SF_OUTPUTS_SHIFT |
+ GEN6_3DSTATE_WM_PERSPECTIVE_PIXEL_BARYCENTRIC);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+}
+
+static void
+gen6_emit_binding_table(struct intel_batchbuffer *batch, uint32_t wm_table)
+{
+ OUT_BATCH(GEN6_3DSTATE_BINDING_TABLE_POINTERS |
+ GEN6_3DSTATE_BINDING_TABLE_MODIFY_PS |
+ (4 - 2));
+ OUT_BATCH(0); /* vs */
+ OUT_BATCH(0); /* gs */
+ OUT_BATCH(wm_table);
+}
+
+static void
+gen6_emit_drawing_rectangle(struct intel_batchbuffer *batch, struct scratch_buf *dst)
+{
+ OUT_BATCH(GEN6_3DSTATE_DRAWING_RECTANGLE | (4 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH((buf_height(dst) - 1) << 16 | (buf_width(dst) - 1));
+ OUT_BATCH(0);
+}
+
+static void
+gen6_emit_vertex_elements(struct intel_batchbuffer *batch)
+{
+ /* The VUE layout
+ * dword 0-3: pad (0.0, 0.0, 0.0. 0.0)
+ * dword 4-7: position (x, y, 1.0, 1.0),
+ * dword 8-11: texture coordinate 0 (u0, v0, 0, 0)
+ *
+ * dword 4-11 are fetched from vertex buffer
+ */
+ OUT_BATCH(GEN6_3DSTATE_VERTEX_ELEMENTS | (2 * 3 + 1 - 2));
+
+ OUT_BATCH(0 << VE0_VERTEX_BUFFER_INDEX_SHIFT | VE0_VALID |
+ GEN6_SURFACEFORMAT_R32G32B32A32_FLOAT << VE0_FORMAT_SHIFT |
+ 0 << VE0_OFFSET_SHIFT);
+ OUT_BATCH(GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_0_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_1_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_2_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_3_SHIFT);
+
+ /* x,y */
+ OUT_BATCH(0 << VE0_VERTEX_BUFFER_INDEX_SHIFT | VE0_VALID |
+ GEN6_SURFACEFORMAT_R16G16_SSCALED << VE0_FORMAT_SHIFT |
+ 0 << VE0_OFFSET_SHIFT); /* offsets vb in bytes */
+ OUT_BATCH(GEN6_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT |
+ GEN6_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT |
+ GEN6_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT |
+ GEN6_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT);
+
+ /* u0, v0 */
+ OUT_BATCH(0 << VE0_VERTEX_BUFFER_INDEX_SHIFT | VE0_VALID |
+ GEN6_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT |
+ 4 << VE0_OFFSET_SHIFT); /* offset vb in bytes */
+ OUT_BATCH(GEN6_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT |
+ GEN6_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_2_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_3_SHIFT);
+}
+
+static uint32_t
+gen6_create_cc_viewport(struct intel_batchbuffer *batch)
+{
+ struct gen6_cc_viewport *vp;
+
+ vp = batch_alloc(batch, sizeof(*vp), 32);
+
+ vp->min_depth = -1.e35;
+ vp->max_depth = 1.e35;
+
+ return batch_offset(batch, vp);
+}
+
+static uint32_t
+gen6_create_cc_blend(struct intel_batchbuffer *batch)
+{
+ struct gen6_blend_state *blend;
+
+ blend = batch_alloc(batch, sizeof(*blend), 64);
+
+ blend->blend0.dest_blend_factor = GEN6_BLENDFACTOR_ZERO;
+ blend->blend0.source_blend_factor = GEN6_BLENDFACTOR_ONE;
+ blend->blend0.blend_func = GEN6_BLENDFUNCTION_ADD;
+ blend->blend0.blend_enable = 1;
+
+ blend->blend1.post_blend_clamp_enable = 1;
+ blend->blend1.pre_blend_clamp_enable = 1;
+
+ return batch_offset(batch, blend);
+}
+
+static uint32_t
+gen6_create_kernel(struct intel_batchbuffer *batch)
+{
+ return batch_copy(batch, ps_kernel_nomask_affine,
+ sizeof(ps_kernel_nomask_affine),
+ 64);
+}
+
+static uint32_t
+gen6_create_sampler(struct intel_batchbuffer *batch,
+ sampler_filter_t filter,
+ sampler_extend_t extend)
+{
+ struct gen6_sampler_state *ss;
+
+ ss = batch_alloc(batch, sizeof(*ss), 32);
+ ss->ss0.lod_preclamp = 1; /* GL mode */
+
+ /* We use the legacy mode to get the semantics specified by
+ * the Render extension. */
+ ss->ss0.border_color_mode = GEN6_BORDER_COLOR_MODE_LEGACY;
+
+ switch (filter) {
+ default:
+ case SAMPLER_FILTER_NEAREST:
+ ss->ss0.min_filter = GEN6_MAPFILTER_NEAREST;
+ ss->ss0.mag_filter = GEN6_MAPFILTER_NEAREST;
+ break;
+ case SAMPLER_FILTER_BILINEAR:
+ ss->ss0.min_filter = GEN6_MAPFILTER_LINEAR;
+ ss->ss0.mag_filter = GEN6_MAPFILTER_LINEAR;
+ break;
+ }
+
+ switch (extend) {
+ default:
+ case SAMPLER_EXTEND_NONE:
+ ss->ss1.r_wrap_mode = GEN6_TEXCOORDMODE_CLAMP_BORDER;
+ ss->ss1.s_wrap_mode = GEN6_TEXCOORDMODE_CLAMP_BORDER;
+ ss->ss1.t_wrap_mode = GEN6_TEXCOORDMODE_CLAMP_BORDER;
+ break;
+ case SAMPLER_EXTEND_REPEAT:
+ ss->ss1.r_wrap_mode = GEN6_TEXCOORDMODE_WRAP;
+ ss->ss1.s_wrap_mode = GEN6_TEXCOORDMODE_WRAP;
+ ss->ss1.t_wrap_mode = GEN6_TEXCOORDMODE_WRAP;
+ break;
+ case SAMPLER_EXTEND_PAD:
+ ss->ss1.r_wrap_mode = GEN6_TEXCOORDMODE_CLAMP;
+ ss->ss1.s_wrap_mode = GEN6_TEXCOORDMODE_CLAMP;
+ ss->ss1.t_wrap_mode = GEN6_TEXCOORDMODE_CLAMP;
+ break;
+ case SAMPLER_EXTEND_REFLECT:
+ ss->ss1.r_wrap_mode = GEN6_TEXCOORDMODE_MIRROR;
+ ss->ss1.s_wrap_mode = GEN6_TEXCOORDMODE_MIRROR;
+ ss->ss1.t_wrap_mode = GEN6_TEXCOORDMODE_MIRROR;
+ break;
+ }
+
+ return batch_offset(batch, ss);
+}
+
+static void gen6_emit_vertex_buffer(struct intel_batchbuffer *batch)
+{
+ OUT_BATCH(GEN6_3DSTATE_VERTEX_BUFFERS | 3);
+ OUT_BATCH(VB0_VERTEXDATA |
+ 0 << VB0_BUFFER_INDEX_SHIFT |
+ VERTEX_SIZE << VB0_BUFFER_PITCH_SHIFT);
+ OUT_RELOC(batch->bo, I915_GEM_DOMAIN_VERTEX, 0, 0);
+ OUT_RELOC(batch->bo, I915_GEM_DOMAIN_VERTEX, 0, batch->bo->size-1);
+ OUT_BATCH(0);
+}
+
+static uint32_t gen6_emit_primitive(struct intel_batchbuffer *batch)
+{
+ uint32_t offset;
+
+ OUT_BATCH(GEN6_3DPRIMITIVE |
+ GEN6_3DPRIMITIVE_VERTEX_SEQUENTIAL |
+ _3DPRIM_RECTLIST << GEN6_3DPRIMITIVE_TOPOLOGY_SHIFT |
+ 0 << 9 |
+ 4);
+ OUT_BATCH(3); /* vertex count */
+ offset = batch_used(batch);
+ OUT_BATCH(0); /* vertex_index */
+ OUT_BATCH(1); /* single instance */
+ OUT_BATCH(0); /* start instance location */
+ OUT_BATCH(0); /* index buffer offset, ignored */
+
+ return offset;
+}
+
+void gen6_render_copyfunc(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned width, unsigned height,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y)
+{
+ uint32_t wm_state, wm_kernel, wm_table;
+ uint32_t cc_vp, cc_blend, offset;
+ uint32_t batch_end;
+
+ intel_batchbuffer_flush(batch);
+
+ batch->ptr = batch->buffer + 1024;
+ batch_alloc(batch, 64, 64);
+ wm_table = gen6_bind_surfaces(batch, src, dst);
+ wm_kernel = gen6_create_kernel(batch);
+ wm_state = gen6_create_sampler(batch,
+ SAMPLER_FILTER_NEAREST,
+ SAMPLER_EXTEND_NONE);
+
+ cc_vp = gen6_create_cc_viewport(batch);
+ cc_blend = gen6_create_cc_blend(batch);
+
+ batch->ptr = batch->buffer;
+
+ gen6_emit_invariant(batch);
+ gen6_emit_state_base_address(batch);
+
+ gen6_emit_sip(batch);
+ gen6_emit_urb(batch);
+
+ gen6_emit_viewports(batch, cc_vp);
+ gen6_emit_vs(batch);
+ gen6_emit_gs(batch);
+ gen6_emit_clip(batch);
+ gen6_emit_wm_constants(batch);
+ gen6_emit_null_depth_buffer(batch);
+
+ gen6_emit_drawing_rectangle(batch, dst);
+ gen6_emit_cc(batch, cc_blend);
+ gen6_emit_sampler(batch, wm_state);
+ gen6_emit_sf(batch);
+ gen6_emit_wm(batch, wm_kernel);
+ gen6_emit_vertex_elements(batch);
+ gen6_emit_binding_table(batch, wm_table);
+
+ gen6_emit_vertex_buffer(batch);
+ offset = gen6_emit_primitive(batch);
+
+ OUT_BATCH(MI_BATCH_BUFFER_END);
+ batch_end = batch_align(batch, 8);
+
+ *(uint32_t*)(batch->buffer + offset) =
+ batch_round_upto(batch, VERTEX_SIZE)/VERTEX_SIZE;
+
+ emit_vertex_2s(batch, dst_x + width, dst_y + height);
+ emit_vertex_normalized(batch, src_x + width, buf_width(src));
+ emit_vertex_normalized(batch, src_y + height, buf_height(src));
+
+ emit_vertex_2s(batch, dst_x, dst_y + height);
+ emit_vertex_normalized(batch, src_x, buf_width(src));
+ emit_vertex_normalized(batch, src_y + height, buf_height(src));
+
+ emit_vertex_2s(batch, dst_x, dst_y);
+ emit_vertex_normalized(batch, src_x, buf_width(src));
+ emit_vertex_normalized(batch, src_y, buf_height(src));
+
+ gen6_render_flush(batch, batch_end);
+ intel_batchbuffer_reset(batch);
+}
diff --git a/lib/rendercopy_gen7.c b/lib/rendercopy_gen7.c
new file mode 100644
index 00000000..56181abf
--- /dev/null
+++ b/lib/rendercopy_gen7.c
@@ -0,0 +1,801 @@
+#include "rendercopy.h"
+#include "gen7_render.h"
+
+#include <assert.h>
+
+#define ALIGN(x, y) (((x) + (y)-1) & ~((y)-1))
+#define VERTEX_SIZE (3*4)
+
+#if DEBUG_RENDERCPY
+static void dump_batch(struct intel_batchbuffer *batch)
+#else
+#define dump_batch(x) do { } while(0)
+#endif
+
+struct {
+ uint32_t cc_state;
+ uint32_t blend_state;
+ uint32_t ds_state;
+} cc;
+
+struct {
+ uint32_t cc_state;
+ uint32_t sf_clip_state;
+} viewport;
+
+/* see shaders/ps/blit.g7a */
+static const uint32_t ps_kernel[][4] = {
+#if 1
+ { 0x0060005a, 0x214077bd, 0x000000c0, 0x008d0040 },
+ { 0x0060005a, 0x216077bd, 0x000000c0, 0x008d0080 },
+ { 0x0060005a, 0x218077bd, 0x000000d0, 0x008d0040 },
+ { 0x0060005a, 0x21a077bd, 0x000000d0, 0x008d0080 },
+ { 0x02800031, 0x2e001e3d, 0x00000140, 0x08840001 },
+ { 0x05800031, 0x20001e3c, 0x00000e00, 0x90031000 },
+
+#else
+ /* Write all -1 */
+ { 0x00600001, 0x2e000061, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x2e200061, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x2e400061, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x2e600061, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x2e800061, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x2ea00061, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x2ec00061, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x2ee00061, 0x00000000, 0x3f800000 },
+ { 0x05800031, 0x20001e3c, 0x00000e00, 0x90031000 },
+#endif
+};
+
+static uint32_t
+batch_used(struct intel_batchbuffer *batch)
+{
+ return batch->ptr - batch->buffer;
+}
+
+static uint32_t
+batch_align(struct intel_batchbuffer *batch, uint32_t align)
+{
+ uint32_t offset = batch_used(batch);
+ offset = ALIGN(offset, align);
+ batch->ptr = batch->buffer + offset;
+ return offset;
+}
+
+static void *
+batch_alloc(struct intel_batchbuffer *batch, uint32_t size, uint32_t align)
+{
+ uint32_t offset = batch_align(batch, align);
+ batch->ptr += size;
+ return memset(batch->buffer + offset, 0, size);
+}
+
+static uint32_t
+batch_offset(struct intel_batchbuffer *batch, void *ptr)
+{
+ return (uint8_t *)ptr - batch->buffer;
+}
+
+static uint32_t
+batch_copy(struct intel_batchbuffer *batch, const void *ptr, uint32_t size, uint32_t align)
+{
+ return batch_offset(batch, memcpy(batch_alloc(batch, size, align), ptr, size));
+}
+
+static void
+gen6_render_flush(struct intel_batchbuffer *batch, uint32_t batch_end)
+{
+ int ret;
+
+ ret = drm_intel_bo_subdata(batch->bo, 0, 4096, batch->buffer);
+ if (ret == 0)
+ ret = drm_intel_bo_mrb_exec(batch->bo, batch_end,
+ NULL, 0, 0, 0);
+ assert(ret == 0);
+}
+
+/* Mostly copy+paste from gen6, except height, width, pitch moved */
+static uint32_t
+gen7_bind_buf(struct intel_batchbuffer *batch, struct scratch_buf *buf,
+ uint32_t format, int is_dst) {
+ struct gen7_surface_state *ss;
+ uint32_t write_domain, read_domain;
+ int ret;
+
+ if (is_dst) {
+ write_domain = read_domain = I915_GEM_DOMAIN_RENDER;
+ } else {
+ write_domain = 0;
+ read_domain = I915_GEM_DOMAIN_SAMPLER;
+ }
+
+ ss = batch_alloc(batch, sizeof(*ss), 32);
+ ss->ss0.surface_type = GEN6_SURFACE_2D;
+ ss->ss0.surface_format = format;
+ ss->ss0.render_cache_read_write = 1; /* GEN7+ */
+ ss->ss0.tiled_surface = buf->tiling != I915_TILING_NONE;
+ ss->ss0.tile_walk = buf->tiling == I915_TILING_Y;
+
+ ss->ss1.base_addr = buf->bo->offset;
+
+ ret = drm_intel_bo_emit_reloc(batch->bo,
+ batch_offset(batch, ss) + 4,
+ buf->bo, 0,
+ read_domain, write_domain);
+ assert(ret == 0);
+
+ ss->ss2.height = buf_height(buf) - 1;
+ ss->ss2.width = buf_width(buf) - 1;
+ ss->ss3.pitch = buf->stride - 1;
+
+ if (IS_HASWELL(batch->devid)) {
+ ss->ss7.shader_chanel_select_a = 4;
+ ss->ss7.shader_chanel_select_g = 5;
+ ss->ss7.shader_chanel_select_b = 6;
+ ss->ss7.shader_chanel_select_a = 7;
+ }
+
+ return batch_offset(batch, ss);
+}
+
+static uint32_t
+gen7_bind_surfaces(struct intel_batchbuffer *batch,
+ struct scratch_buf *src,
+ struct scratch_buf *dst) {
+ uint32_t *binding_table;
+
+ binding_table = batch_alloc(batch, 8, 32);
+
+ binding_table[0] =
+ gen7_bind_buf(batch, dst, GEN6_SURFACEFORMAT_B8G8R8A8_UNORM, 1);
+ binding_table[1] =
+ gen7_bind_buf(batch, src, GEN6_SURFACEFORMAT_B8G8R8A8_UNORM, 0);
+
+ return batch_offset(batch, binding_table);
+}
+
+/* Mostly copy+paste from gen6, except wrap modes moved */
+static uint32_t
+gen7_create_sampler(struct intel_batchbuffer *batch) {
+ struct gen7_sampler_state *ss;
+
+ ss = batch_alloc(batch, sizeof(*ss), 32);
+
+ ss->ss0.min_filter = GEN6_MAPFILTER_NEAREST;
+ ss->ss0.mag_filter = GEN6_MAPFILTER_NEAREST;
+ ss->ss3.r_wrap_mode = GEN6_TEXCOORDMODE_CLAMP;
+ ss->ss3.s_wrap_mode = GEN6_TEXCOORDMODE_CLAMP;
+ ss->ss3.t_wrap_mode = GEN6_TEXCOORDMODE_CLAMP;
+
+ /* I've experimented with non-normalized coordinates and using the LD
+ * sampler fetch, but couldn't make it work. */
+ ss->ss3.non_normalized_coord = 0;
+
+ return batch_offset(batch, ss);
+}
+
+/**
+ * gen7_fill_vertex_buffer_data populate vertex buffer with data.
+ *
+ * The vertex buffer consists of 3 vertices to construct a RECTLIST. The 4th
+ * vertex is implied (automatically derived by the HW). Each element has the
+ * destination offset, and the normalized texture offset (src). The rectangle
+ * itself will span the entire subsurface to be copied.
+ *
+ * see gen6_emit_vertex_elements
+ */
+static uint32_t
+gen7_fill_vertex_buffer_data(struct intel_batchbuffer *batch,
+ struct scratch_buf *src,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t dst_x, uint32_t dst_y,
+ uint32_t width, uint32_t height) {
+ void *ret;
+
+ ret = batch->ptr;
+
+ emit_vertex_2s(batch, dst_x + width, dst_y + height);
+ emit_vertex_normalized(batch, src_x + width, buf_width(src));
+ emit_vertex_normalized(batch, src_y + height, buf_height(src));
+
+ emit_vertex_2s(batch, dst_x, dst_y + height);
+ emit_vertex_normalized(batch, src_x, buf_width(src));
+ emit_vertex_normalized(batch, src_y + height, buf_height(src));
+
+ emit_vertex_2s(batch, dst_x, dst_y);
+ emit_vertex_normalized(batch, src_x, buf_width(src));
+ emit_vertex_normalized(batch, src_y, buf_height(src));
+
+ return batch_offset(batch, ret);
+}
+
+/**
+ * gen6_emit_vertex_elements - The vertex elements describe the contents of the
+ * vertex buffer. We pack the vertex buffer in a semi weird way, conforming to
+ * what gen6_rendercopy did. The most straightforward would be to store
+ * everything as floats.
+ *
+ * see gen7_fill_vertex_buffer_data() for where the corresponding elements are
+ * packed.
+ */
+static void
+gen6_emit_vertex_elements(struct intel_batchbuffer *batch) {
+ /*
+ * The VUE layout
+ * dword 0-3: pad (0, 0, 0. 0)
+ * dword 4-7: position (x, y, 0, 1.0),
+ * dword 8-11: texture coordinate 0 (u0, v0, 0, 1.0)
+ */
+ OUT_BATCH(GEN6_3DSTATE_VERTEX_ELEMENTS | (3 * 2 + 1 - 2));
+
+ /* Element state 0. These are 4 dwords of 0 required for the VUE format.
+ * We don't really know or care what they do.
+ */
+ OUT_BATCH(0 << VE0_VERTEX_BUFFER_INDEX_SHIFT | VE0_VALID |
+ GEN6_SURFACEFORMAT_R32G32B32A32_FLOAT << VE0_FORMAT_SHIFT |
+ 0 << VE0_OFFSET_SHIFT); /* we specify 0, but it's really does not exist */
+ OUT_BATCH(GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_0_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_1_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_2_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_3_SHIFT);
+
+ /* Element state 1 - Our "destination" vertices. These are passed down
+ * through the pipeline, and eventually make it to the pixel shader as
+ * the offsets in the destination surface. It's packed as the 16
+ * signed/scaled because of gen6 rendercopy. I see no particular reason
+ * for doing this though.
+ */
+ OUT_BATCH(0 << VE0_VERTEX_BUFFER_INDEX_SHIFT | VE0_VALID |
+ GEN6_SURFACEFORMAT_R16G16_SSCALED << VE0_FORMAT_SHIFT |
+ 0 << VE0_OFFSET_SHIFT); /* offsets vb in bytes */
+ OUT_BATCH(GEN6_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT |
+ GEN6_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_2_SHIFT |
+ GEN6_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT);
+
+ /* Element state 2. Last but not least we store the U,V components as
+ * normalized floats. These will be used in the pixel shader to sample
+ * from the source buffer.
+ */
+ OUT_BATCH(0 << VE0_VERTEX_BUFFER_INDEX_SHIFT | VE0_VALID |
+ GEN6_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT |
+ 4 << VE0_OFFSET_SHIFT); /* offset vb in bytes */
+ OUT_BATCH(GEN6_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT |
+ GEN6_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT |
+ GEN6_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_2_SHIFT |
+ GEN6_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT);
+}
+
+/**
+ * gen7_emit_vertex_buffer emit the vertex buffers command
+ *
+ * @batch
+ * @offset - bytw offset within the @batch where the vertex buffer starts.
+ */
+static void gen7_emit_vertex_buffer(struct intel_batchbuffer *batch,
+ uint32_t offset) {
+ OUT_BATCH(GEN6_3DSTATE_VERTEX_BUFFERS | (4 * 1 - 1));
+ OUT_BATCH(0 << VB0_BUFFER_INDEX_SHIFT | /* VB 0th index */
+ VB0_VERTEXDATA |
+ GEN7_VB0_BUFFER_ADDR_MOD_EN | /* Address Modify Enable */
+ VERTEX_SIZE << VB0_BUFFER_PITCH_SHIFT);
+ OUT_RELOC(batch->bo, I915_GEM_DOMAIN_VERTEX, 0, offset);
+ OUT_RELOC(batch->bo, I915_GEM_DOMAIN_VERTEX, 0, offset + (VERTEX_SIZE * 3) - 1);
+ OUT_BATCH(0);
+}
+
+static uint32_t
+gen6_create_cc_state(struct intel_batchbuffer *batch)
+{
+ struct gen6_color_calc_state *cc_state;
+ cc_state = batch_alloc(batch, sizeof(*cc_state), 64);
+ return batch_offset(batch, cc_state);
+}
+
+static uint32_t
+gen6_create_depth_stencil_state(struct intel_batchbuffer *batch)
+{
+ struct gen6_depth_stencil_state *depth;
+ depth = batch_alloc(batch, sizeof(*depth), 64);
+ depth->ds0.stencil_enable = 0;
+ return batch_offset(batch, depth);
+}
+
+static uint32_t
+gen6_create_blend_state(struct intel_batchbuffer *batch)
+{
+ struct gen6_blend_state *blend;
+ blend = batch_alloc(batch, sizeof(*blend), 64);
+ blend->blend0.blend_enable = 0;
+ blend->blend1.pre_blend_clamp_enable = 1;
+ return batch_offset(batch, blend);
+}
+
+static uint32_t
+gen6_create_cc_viewport(struct intel_batchbuffer *batch)
+{
+ struct gen6_cc_viewport *vp;
+
+ vp = batch_alloc(batch, sizeof(*vp), 32);
+ /* XXX I don't understand this */
+ vp->min_depth = -1.e35;
+ vp->max_depth = 1.e35;
+ return batch_offset(batch, vp);
+}
+
+static uint32_t
+gen7_create_sf_clip_viewport(struct intel_batchbuffer *batch) {
+ /* XXX these are likely not needed */
+ struct gen7_sf_clip_viewport *scv_state;
+ scv_state = batch_alloc(batch, sizeof(*scv_state), 64);
+ scv_state->guardband.xmin = 0;
+ scv_state->guardband.xmax = 1.0f;
+ scv_state->guardband.ymin = 0;
+ scv_state->guardband.ymax = 1.0f;
+ return batch_offset(batch, scv_state);
+}
+
+static uint32_t
+gen6_create_scissor_rect(struct intel_batchbuffer *batch)
+{
+ struct gen6_scissor_rect *scissor;
+ scissor = batch_alloc(batch, sizeof(*scissor), 64);
+ return batch_offset(batch, scissor);
+}
+
+
+
+
+
+static void
+gen6_emit_sip(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN6_STATE_SIP | 0);
+ OUT_BATCH(0);
+}
+
+static void
+gen7_emit_push_constants(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_VS);
+ OUT_BATCH(0);
+ OUT_BATCH(GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_HS);
+ OUT_BATCH(0);
+ OUT_BATCH(GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_DS);
+ OUT_BATCH(0);
+ OUT_BATCH(GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_GS);
+ OUT_BATCH(0);
+ OUT_BATCH(GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_PS);
+ OUT_BATCH(0);
+}
+
+static void
+gen7_emit_state_base_address(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN6_STATE_BASE_ADDRESS | (10 - 2));
+ /* general (stateless) */
+ /* surface */
+ /* instruction */
+ /* indirect */
+ /* dynamic */
+ OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
+ OUT_RELOC(batch->bo, I915_GEM_DOMAIN_SAMPLER, 0, BASE_ADDRESS_MODIFY);
+ OUT_RELOC(batch->bo, I915_GEM_DOMAIN_RENDER | I915_GEM_DOMAIN_INSTRUCTION,
+ 0, BASE_ADDRESS_MODIFY);
+ OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
+ OUT_RELOC(batch->bo, I915_GEM_DOMAIN_INSTRUCTION, 0, BASE_ADDRESS_MODIFY);
+
+ OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
+ OUT_BATCH(0xfffff000 | BASE_ADDRESS_MODIFY); // copied from mesa
+ OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
+ OUT_BATCH(0 | BASE_ADDRESS_MODIFY);
+}
+
+static void
+gen7_emit_urb(struct intel_batchbuffer *batch) {
+ /* XXX: Min valid values from mesa */
+ const int vs_entries = 32;
+ const int vs_size = 2;
+ const int vs_start = 2;
+
+ OUT_BATCH(GEN7_3DSTATE_URB_VS);
+ OUT_BATCH(vs_entries | ((vs_size - 1) << 16) | (vs_start << 25));
+ OUT_BATCH(GEN7_3DSTATE_URB_GS);
+ OUT_BATCH(vs_start << 25);
+ OUT_BATCH(GEN7_3DSTATE_URB_HS);
+ OUT_BATCH(vs_start << 25);
+ OUT_BATCH(GEN7_3DSTATE_URB_DS);
+ OUT_BATCH(vs_start << 25);
+}
+
+static void
+gen7_emit_cc(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN7_3DSTATE_BLEND_STATE_POINTERS);
+ OUT_BATCH(cc.blend_state | 1);
+
+ OUT_BATCH(GEN6_3DSTATE_CC_STATE_POINTERS);
+ OUT_BATCH(cc.cc_state | 1);
+
+ OUT_BATCH(GEN7_3DSTATE_DS_STATE_POINTERS);
+ OUT_BATCH(cc.ds_state | 1);
+}
+
+static void
+gen7_emit_multisample(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN6_3DSTATE_MULTISAMPLE | 2);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN6_3DSTATE_SAMPLE_MASK);
+ OUT_BATCH(1);
+}
+
+static void
+gen7_emit_vs(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_VS);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_VS);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN6_3DSTATE_CONSTANT_VS | (7-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN6_3DSTATE_VS | (6-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+}
+
+static void
+gen7_emit_hs(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN7_3DSTATE_CONSTANT_HS | (7-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_HS | (7-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_HS);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_HS);
+ OUT_BATCH(0);
+}
+
+static void
+gen7_emit_gs(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN7_3DSTATE_CONSTANT_GS | (7-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_GS | (7-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_GS);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_GS);
+ OUT_BATCH(0);
+}
+
+static void
+gen7_emit_ds(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN7_3DSTATE_CONSTANT_DS | (7-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_DS | (6-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_DS);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_DS);
+ OUT_BATCH(0);
+}
+
+static void
+gen7_emit_null_state(struct intel_batchbuffer *batch) {
+ gen7_emit_hs(batch);
+ OUT_BATCH(GEN7_3DSTATE_TE | (4-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ gen7_emit_gs(batch);
+ gen7_emit_ds(batch);
+ gen7_emit_vs(batch);
+}
+
+static void
+gen7_emit_clip(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN6_3DSTATE_CLIP | (4 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH(0); /* pass-through */
+ OUT_BATCH(0);
+}
+
+static void
+gen7_emit_sf(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN7_3DSTATE_SBE | (14 - 2));
+#ifdef GPU_HANG
+ OUT_BATCH(0 << 22 | 1 << 11 | 1 << 4);
+#else
+ OUT_BATCH(1 << 22 | 1 << 11 | 1 << 4);
+#endif
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN6_3DSTATE_SF | (7 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH(GEN6_3DSTATE_SF_CULL_NONE);
+// OUT_BATCH(2 << GEN6_3DSTATE_SF_TRIFAN_PROVOKE_SHIFT);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+}
+
+static void
+gen7_emit_ps(struct intel_batchbuffer *batch, uint32_t kernel) {
+ const int max_threads = 86;
+
+ OUT_BATCH(GEN6_3DSTATE_WM | (3 - 2));
+ OUT_BATCH(GEN7_WM_DISPATCH_ENABLE |
+ /* XXX: I don't understand the BARYCENTRIC stuff, but it
+ * appears we need it to put our setup data in the place we
+ * expect (g6, see below) */
+ GEN7_3DSTATE_PS_PERSPECTIVE_PIXEL_BARYCENTRIC);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN6_3DSTATE_CONSTANT_PS | (7-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_PS | (8-2));
+ OUT_BATCH(kernel);
+ OUT_BATCH(1 << GEN6_3DSTATE_WM_SAMPLER_COUNT_SHITF |
+ 2 << GEN6_3DSTATE_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT);
+ OUT_BATCH(0); /* scratch space stuff */
+ if (IS_HASWELL(batch->devid)) {
+ OUT_BATCH((max_threads - 1) << GEN7_3DSTATE_WM_MAX_THREADS_SHIFT |
+ GEN7_3DSTATE_PS_ATTRIBUTE_ENABLED |
+ GEN6_3DSTATE_WM_16_DISPATCH_ENABLE);
+ } else {
+ OUT_BATCH((max_threads - 1) << HSW_3DSTATE_WM_MAX_THREADS_SHIFT |
+ GEN7_3DSTATE_PS_ATTRIBUTE_ENABLED |
+ GEN6_3DSTATE_WM_16_DISPATCH_ENABLE);
+ }
+ OUT_BATCH(6 << GEN6_3DSTATE_WM_DISPATCH_START_GRF_0_SHIFT);
+ OUT_BATCH(0); // kernel 1
+ OUT_BATCH(0); // kernel 2
+}
+
+static void
+gen7_emit_depth(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER | (7-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_HIER_DEPTH_BUFFER | (3-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ OUT_BATCH(GEN7_3DSTATE_STENCIL_BUFFER | (3-2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+}
+
+static void
+gen7_emit_clear(struct intel_batchbuffer *batch) {
+ OUT_BATCH(GEN7_3DSTATE_CLEAR_PARAMS | (3-2));
+ OUT_BATCH(0);
+ OUT_BATCH(1); // clear valid
+}
+
+static void
+gen6_emit_drawing_rectangle(struct intel_batchbuffer *batch, struct scratch_buf *dst)
+{
+ OUT_BATCH(GEN6_3DSTATE_DRAWING_RECTANGLE | (4 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH((buf_height(dst) - 1) << 16 | (buf_width(dst) - 1));
+ OUT_BATCH(0);
+}
+
+/* Vertex elements MUST be defined before this according to spec */
+static void gen7_emit_primitive(struct intel_batchbuffer *batch, uint32_t offset)
+{
+ OUT_BATCH(GEN6_3DPRIMITIVE | (7-2));
+ OUT_BATCH(_3DPRIM_RECTLIST);
+ OUT_BATCH(3); /* vertex count */
+ OUT_BATCH(0); /* We're specifying this instead with offset in GEN6_3DSTATE_VERTEX_BUFFERS */
+ OUT_BATCH(1); /* single instance */
+ OUT_BATCH(0); /* start instance location */
+ OUT_BATCH(0); /* index buffer offset, ignored */
+}
+
+/* The general rule is if it's named gen6 it is directly copied from
+ * gen6_render_copyfunc.
+ *
+ * This sets up most of the 3d pipeline, and most of that to NULL state. The
+ * docs aren't specific about exactly what must be set up NULL, but the general
+ * rule is we could be run at any time, and so the most state we set to NULL,
+ * the better our odds of success.
+ *
+ * +---------------+ <---- 4096
+ * | ^ |
+ * | | |
+ * | various |
+ * | state |
+ * | | |
+ * |_______|_______| <---- 2048 + ?
+ * | ^ |
+ * | | |
+ * | batch |
+ * | commands |
+ * | | |
+ * | | |
+ * +---------------+ <---- 0 + ?
+ *
+ * The batch commands point to state within tthe batch, so all state offsets should be
+ * 0 < offset < 4096. Both commands and state build upwards, and are constructed
+ * in that order. This means too many batch commands can delete state if not
+ * careful.
+ *
+ */
+
+#define BATCH_STATE_SPLIT 2048
+void gen7_render_copyfunc(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned width, unsigned height,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y)
+{
+ uint32_t ps_sampler_state, ps_kernel_off, ps_binding_table;
+ uint32_t scissor_state;
+ uint32_t vertex_buffer;
+ uint32_t batch_end;
+
+ intel_batchbuffer_flush(batch);
+
+ batch_align(batch, 8);
+
+ batch->ptr = &batch->buffer[BATCH_STATE_SPLIT];
+
+ ps_binding_table = gen7_bind_surfaces(batch, src, dst);
+ ps_sampler_state = gen7_create_sampler(batch);
+ ps_kernel_off = batch_copy(batch, ps_kernel, sizeof(ps_kernel), 64);
+ vertex_buffer = gen7_fill_vertex_buffer_data(batch, src, src_x, src_y, dst_x, dst_y, width, height);
+ cc.cc_state = gen6_create_cc_state(batch);
+ cc.ds_state = gen6_create_depth_stencil_state(batch);
+ cc.blend_state = gen6_create_blend_state(batch);
+ viewport.cc_state = gen6_create_cc_viewport(batch);
+ viewport.sf_clip_state = gen7_create_sf_clip_viewport(batch);
+ scissor_state = gen6_create_scissor_rect(batch);
+ /* TODO: theree is other state which isn't setup */
+
+ assert(batch->ptr < &batch->buffer[4095]);
+
+ batch->ptr = batch->buffer;
+
+ /* Start emitting the commands. The order roughly follows the mesa blorp
+ * order */
+ OUT_BATCH(GEN6_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+
+ gen6_emit_sip(batch);
+
+ gen7_emit_push_constants(batch);
+
+ gen7_emit_state_base_address(batch);
+
+ OUT_BATCH(GEN7_3DSTATE_VIEWPORT_STATE_POINTERS_CC);
+ OUT_BATCH(viewport.cc_state);
+ OUT_BATCH(GEN7_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP);
+ OUT_BATCH(viewport.sf_clip_state);
+
+ gen7_emit_urb(batch);
+
+ gen7_emit_cc(batch);
+
+ gen7_emit_multisample(batch);
+
+ gen7_emit_null_state(batch);
+
+ OUT_BATCH(GEN7_3DSTATE_STREAMOUT | 1);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+
+ gen7_emit_clip(batch);
+
+ gen7_emit_sf(batch);
+
+ OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_PS);
+ OUT_BATCH(ps_binding_table);
+
+ OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_PS);
+ OUT_BATCH(ps_sampler_state);
+
+ gen7_emit_ps(batch, ps_kernel_off);
+
+ OUT_BATCH(GEN6_3DSTATE_SCISSOR_STATE_POINTERS);
+ OUT_BATCH(scissor_state);
+
+ gen7_emit_depth(batch);
+
+ gen7_emit_clear(batch);
+
+ gen6_emit_drawing_rectangle(batch, dst);
+
+ gen7_emit_vertex_buffer(batch, vertex_buffer);
+ gen6_emit_vertex_elements(batch);
+
+ gen7_emit_primitive(batch, vertex_buffer);
+
+ OUT_BATCH(MI_BATCH_BUFFER_END);
+
+ batch_end = batch_align(batch, 8);
+ assert(batch_end < BATCH_STATE_SPLIT);
+
+ dump_batch(batch);
+
+ gen6_render_flush(batch, batch_end);
+ intel_batchbuffer_reset(batch);
+}
+
+#if DEBUG_RENDERCPY
+static void dump_batch(struct intel_batchbuffer *batch) {
+ int fd = open("/tmp/i965-batchbuffers.dump", O_WRONLY | O_CREAT, 0666);
+ if (fd != -1) {
+ write(fd, batch->buffer, 4096);
+ fd = close(fd);
+ }
+}
+#endif
diff --git a/lib/rendercopy_i830.c b/lib/rendercopy_i830.c
new file mode 100644
index 00000000..28c3e99e
--- /dev/null
+++ b/lib/rendercopy_i830.c
@@ -0,0 +1,229 @@
+#include "i830_reg.h"
+#include "rendercopy.h"
+
+#define TB0C_LAST_STAGE (1 << 31)
+#define TB0C_RESULT_SCALE_1X (0 << 29)
+#define TB0C_RESULT_SCALE_2X (1 << 29)
+#define TB0C_RESULT_SCALE_4X (2 << 29)
+#define TB0C_OP_ARG1 (1 << 25)
+#define TB0C_OP_MODULE (3 << 25)
+#define TB0C_OUTPUT_WRITE_CURRENT (0 << 24)
+#define TB0C_OUTPUT_WRITE_ACCUM (1 << 24)
+#define TB0C_ARG3_REPLICATE_ALPHA (1<<23)
+#define TB0C_ARG3_INVERT (1<<22)
+#define TB0C_ARG3_SEL_XXX
+#define TB0C_ARG2_REPLICATE_ALPHA (1<<17)
+#define TB0C_ARG2_INVERT (1<<16)
+#define TB0C_ARG2_SEL_ONE (0 << 12)
+#define TB0C_ARG2_SEL_FACTOR (1 << 12)
+#define TB0C_ARG2_SEL_TEXEL0 (6 << 12)
+#define TB0C_ARG2_SEL_TEXEL1 (7 << 12)
+#define TB0C_ARG2_SEL_TEXEL2 (8 << 12)
+#define TB0C_ARG2_SEL_TEXEL3 (9 << 12)
+#define TB0C_ARG1_REPLICATE_ALPHA (1<<11)
+#define TB0C_ARG1_INVERT (1<<10)
+#define TB0C_ARG1_SEL_ONE (0 << 6)
+#define TB0C_ARG1_SEL_TEXEL0 (6 << 6)
+#define TB0C_ARG1_SEL_TEXEL1 (7 << 6)
+#define TB0C_ARG1_SEL_TEXEL2 (8 << 6)
+#define TB0C_ARG1_SEL_TEXEL3 (9 << 6)
+#define TB0C_ARG0_REPLICATE_ALPHA (1<<5)
+#define TB0C_ARG0_SEL_XXX
+
+#define TB0A_CTR_STAGE_ENABLE (1<<31)
+#define TB0A_RESULT_SCALE_1X (0 << 29)
+#define TB0A_RESULT_SCALE_2X (1 << 29)
+#define TB0A_RESULT_SCALE_4X (2 << 29)
+#define TB0A_OP_ARG1 (1 << 25)
+#define TB0A_OP_MODULE (3 << 25)
+#define TB0A_OUTPUT_WRITE_CURRENT (0<<24)
+#define TB0A_OUTPUT_WRITE_ACCUM (1<<24)
+#define TB0A_CTR_STAGE_SEL_BITS_XXX
+#define TB0A_ARG3_SEL_XXX
+#define TB0A_ARG3_INVERT (1<<17)
+#define TB0A_ARG2_INVERT (1<<16)
+#define TB0A_ARG2_SEL_ONE (0 << 12)
+#define TB0A_ARG2_SEL_TEXEL0 (6 << 12)
+#define TB0A_ARG2_SEL_TEXEL1 (7 << 12)
+#define TB0A_ARG2_SEL_TEXEL2 (8 << 12)
+#define TB0A_ARG2_SEL_TEXEL3 (9 << 12)
+#define TB0A_ARG1_INVERT (1<<10)
+#define TB0A_ARG1_SEL_ONE (0 << 6)
+#define TB0A_ARG1_SEL_TEXEL0 (6 << 6)
+#define TB0A_ARG1_SEL_TEXEL1 (7 << 6)
+#define TB0A_ARG1_SEL_TEXEL2 (8 << 6)
+#define TB0A_ARG1_SEL_TEXEL3 (9 << 6)
+
+
+static void gen2_emit_invariant(struct intel_batchbuffer *batch)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(i));
+ OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | MAP_UNIT(i) |
+ DISABLE_TEX_STREAM_BUMP |
+ ENABLE_TEX_STREAM_COORD_SET | TEX_STREAM_COORD_SET(i) |
+ ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(i));
+ OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
+ OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(i));
+ }
+
+ OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD);
+ OUT_BATCH(TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) |
+ TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) |
+ TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
+ TEXBIND_SET0(TEXCOORDSRC_VTXSET_0));
+
+ OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+
+ OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
+ OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
+
+ OUT_BATCH(_3DSTATE_W_STATE_CMD);
+ OUT_BATCH(MAGIC_W_STATE_DWORD1);
+ OUT_BATCH(0x3f800000 /* 1.0 in IEEE float */ );
+
+ OUT_BATCH(_3DSTATE_INDPT_ALPHA_BLEND_CMD |
+ DISABLE_INDPT_ALPHA_BLEND |
+ ENABLE_ALPHA_BLENDFUNC | ABLENDFUNC_ADD);
+
+ OUT_BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD);
+ OUT_BATCH(0);
+
+ OUT_BATCH(_3DSTATE_MODES_1_CMD |
+ ENABLE_COLR_BLND_FUNC | BLENDFUNC_ADD |
+ ENABLE_SRC_BLND_FACTOR | SRC_BLND_FACT(BLENDFACTOR_ONE) |
+ ENABLE_DST_BLND_FACTOR | DST_BLND_FACT(BLENDFACTOR_ZERO));
+
+ OUT_BATCH(_3DSTATE_ENABLES_1_CMD |
+ DISABLE_LOGIC_OP |
+ DISABLE_STENCIL_TEST |
+ DISABLE_DEPTH_BIAS |
+ DISABLE_SPEC_ADD |
+ DISABLE_FOG |
+ DISABLE_ALPHA_TEST |
+ DISABLE_DEPTH_TEST |
+ ENABLE_COLOR_BLEND);
+
+ OUT_BATCH(_3DSTATE_ENABLES_2_CMD |
+ DISABLE_STENCIL_WRITE |
+ DISABLE_DITHER |
+ DISABLE_DEPTH_WRITE |
+ ENABLE_COLOR_MASK |
+ ENABLE_COLOR_WRITE |
+ ENABLE_TEX_CACHE);
+}
+
+static void gen2_emit_target(struct intel_batchbuffer *batch,
+ struct scratch_buf *dst)
+{
+ uint32_t tiling;
+
+ tiling = 0;
+ if (dst->tiling != I915_TILING_NONE)
+ tiling = BUF_3D_TILED_SURFACE;
+ if (dst->tiling == I915_TILING_Y)
+ tiling |= BUF_3D_TILE_WALK_Y;
+
+ OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
+ OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling | BUF_3D_PITCH(dst->stride));
+ OUT_RELOC(dst->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+
+ OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
+ OUT_BATCH(COLR_BUF_ARGB8888 |
+ DSTORG_HORT_BIAS(0x8) |
+ DSTORG_VERT_BIAS(0x8));
+
+ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(0); /* ymin, xmin */
+ OUT_BATCH(DRAW_YMAX(buf_height(dst) - 1) |
+ DRAW_XMAX(buf_width(dst) - 1));
+ OUT_BATCH(0); /* yorig, xorig */
+}
+
+static void gen2_emit_texture(struct intel_batchbuffer *batch,
+ struct scratch_buf *src,
+ int unit)
+{
+ uint32_t tiling;
+
+ tiling = 0;
+ if (src->tiling != I915_TILING_NONE)
+ tiling = TM0S1_TILED_SURFACE;
+ if (src->tiling == I915_TILING_Y)
+ tiling |= TM0S1_TILE_WALK;
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
+ OUT_RELOC(src->bo, I915_GEM_DOMAIN_SAMPLER, 0, 0);
+ OUT_BATCH((buf_height(src) - 1) << TM0S1_HEIGHT_SHIFT |
+ (buf_width(src) - 1) << TM0S1_WIDTH_SHIFT |
+ MAPSURF_32BIT | MT_32BIT_ARGB8888 | tiling);
+ OUT_BATCH((src->stride / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
+ OUT_BATCH(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT |
+ FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT |
+ MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
+ OUT_BATCH(0); /* default color */
+
+ OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
+ ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
+ TEXCOORDTYPE_CARTESIAN |
+ ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER) |
+ ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER));
+}
+
+static void gen2_emit_copy_pipeline(struct intel_batchbuffer *batch)
+{
+ OUT_BATCH(_3DSTATE_INDPT_ALPHA_BLEND_CMD | DISABLE_INDPT_ALPHA_BLEND);
+ OUT_BATCH(_3DSTATE_ENABLES_1_CMD | DISABLE_LOGIC_OP |
+ DISABLE_STENCIL_TEST | DISABLE_DEPTH_BIAS |
+ DISABLE_SPEC_ADD | DISABLE_FOG | DISABLE_ALPHA_TEST |
+ DISABLE_COLOR_BLEND | DISABLE_DEPTH_TEST);
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+ LOAD_TEXTURE_BLEND_STAGE(0) | 1);
+ OUT_BATCH(TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X |
+ TB0C_OUTPUT_WRITE_CURRENT |
+ TB0C_OP_ARG1 | TB0C_ARG1_SEL_TEXEL0);
+ OUT_BATCH(TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT |
+ TB0A_OP_ARG1 | TB0A_ARG1_SEL_TEXEL0);
+}
+
+void gen2_render_copyfunc(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned width, unsigned height,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y)
+{
+ gen2_emit_invariant(batch);
+ gen2_emit_copy_pipeline(batch);
+
+ gen2_emit_target(batch, dst);
+ gen2_emit_texture(batch, src, 0);
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
+ OUT_BATCH(1<<12);
+ OUT_BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
+ OUT_BATCH(S8_ENABLE_COLOR_BUFFER_WRITE);
+
+ OUT_BATCH(_3DSTATE_VERTEX_FORMAT_2_CMD | TEXCOORDFMT_2D << 0);
+
+ OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (3*4 -1));
+ emit_vertex(batch, dst_x + width);
+ emit_vertex(batch, dst_y + height);
+ emit_vertex_normalized(batch, src_x + width, buf_width(src));
+ emit_vertex_normalized(batch, src_y + height, buf_height(src));
+
+ emit_vertex(batch, dst_x);
+ emit_vertex(batch, dst_y + height);
+ emit_vertex_normalized(batch, src_x, buf_width(src));
+ emit_vertex_normalized(batch, src_y + height, buf_height(src));
+
+ emit_vertex(batch, dst_x);
+ emit_vertex(batch, dst_y);
+ emit_vertex_normalized(batch, src_x, buf_width(src));
+ emit_vertex_normalized(batch, src_y, buf_height(src));
+
+ intel_batchbuffer_flush(batch);
+}
diff --git a/lib/rendercopy_i915.c b/lib/rendercopy_i915.c
new file mode 100644
index 00000000..4b15dfe3
--- /dev/null
+++ b/lib/rendercopy_i915.c
@@ -0,0 +1,180 @@
+#include "i915_reg.h"
+#include "i915_3d.h"
+#include "rendercopy.h"
+
+void gen3_render_copyfunc(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned width, unsigned height,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y)
+{
+ /* invariant state */
+ {
+ OUT_BATCH(_3DSTATE_AA_CMD |
+ AA_LINE_ECAAR_WIDTH_ENABLE |
+ AA_LINE_ECAAR_WIDTH_1_0 |
+ AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
+ OUT_BATCH(_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+ IAB_MODIFY_ENABLE |
+ IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
+ IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE <<
+ IAB_SRC_FACTOR_SHIFT) |
+ IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO <<
+ IAB_DST_FACTOR_SHIFT));
+ OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS |
+ CSB_TCB(0, 0) |
+ CSB_TCB(1, 1) |
+ CSB_TCB(2, 2) |
+ CSB_TCB(3, 3) |
+ CSB_TCB(4, 4) |
+ CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7));
+ OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D);
+ OUT_BATCH(_3DSTATE_MODES_4_CMD |
+ ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
+ ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) |
+ ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff));
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 2);
+ OUT_BATCH(0x00000000); /* Disable texture coordinate wrap-shortest */
+ OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) |
+ S4_LINE_WIDTH_ONE |
+ S4_CULLMODE_NONE |
+ S4_VFMT_XY);
+ OUT_BATCH(0x00000000); /* Stencil. */
+ OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+ OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE);
+ OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
+ OUT_BATCH(0);
+ OUT_BATCH(_3DSTATE_STIPPLE);
+ OUT_BATCH(0x00000000);
+ OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
+ }
+
+ /* samler state */
+ {
+#define TEX_COUNT 1
+ uint32_t tiling_bits = 0;
+ if (src->tiling != I915_TILING_NONE)
+ tiling_bits = MS3_TILED_SURFACE;
+ if (src->tiling == I915_TILING_Y)
+ tiling_bits |= MS3_TILE_WALK;
+
+ OUT_BATCH(_3DSTATE_MAP_STATE | (3 * TEX_COUNT));
+ OUT_BATCH((1 << TEX_COUNT) - 1);
+ OUT_RELOC(src->bo, I915_GEM_DOMAIN_SAMPLER, 0, 0);
+ OUT_BATCH(MAPSURF_32BIT | MT_32BIT_ARGB8888 |
+ tiling_bits |
+ (buf_height(src) - 1) << MS3_HEIGHT_SHIFT |
+ (buf_width(src) - 1) << MS3_WIDTH_SHIFT);
+ OUT_BATCH((src->stride/4-1) << MS4_PITCH_SHIFT);
+
+ OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * TEX_COUNT));
+ OUT_BATCH((1 << TEX_COUNT) - 1);
+ OUT_BATCH(MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MAG_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+ OUT_BATCH(TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT |
+ TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT |
+ 0 << SS3_TEXTUREMAP_INDEX_SHIFT);
+ OUT_BATCH(0x00000000);
+ }
+
+ /* render target state */
+ {
+ uint32_t tiling_bits = 0;
+ if (dst->tiling != I915_TILING_NONE)
+ tiling_bits = BUF_3D_TILED_SURFACE;
+ if (dst->tiling == I915_TILING_Y)
+ tiling_bits |= BUF_3D_TILE_WALK_Y;
+
+ OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
+ OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits |
+ BUF_3D_PITCH(dst->stride));
+ OUT_RELOC(dst->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+
+ OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
+ OUT_BATCH(COLR_BUF_ARGB8888 |
+ DSTORG_HORT_BIAS(0x8) |
+ DSTORG_VERT_BIAS(0x8));
+
+ /* draw rect is unconditional */
+ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
+ OUT_BATCH(0x00000000);
+ OUT_BATCH(0x00000000); /* ymin, xmin */
+ OUT_BATCH(DRAW_YMAX(buf_height(dst) - 1) |
+ DRAW_XMAX(buf_width(dst) - 1));
+ /* yorig, xorig (relate to color buffer?) */
+ OUT_BATCH(0x00000000);
+ }
+
+ /* texfmt */
+ {
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(1) | I1_LOAD_S(2) | I1_LOAD_S(6) | 2);
+ OUT_BATCH((4 << S1_VERTEX_WIDTH_SHIFT) |
+ (4 << S1_VERTEX_PITCH_SHIFT));
+ OUT_BATCH(~S2_TEXCOORD_FMT(0, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D));
+ OUT_BATCH(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+ BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT |
+ BLENDFACT_ONE << S6_CBUF_SRC_BLEND_FACT_SHIFT |
+ BLENDFACT_ZERO << S6_CBUF_DST_BLEND_FACT_SHIFT);
+ }
+
+ /* frage shader */
+ {
+ OUT_BATCH(_3DSTATE_PIXEL_SHADER_PROGRAM | (1 + 3*3 - 2));
+ /* decl FS_T0 */
+ OUT_BATCH(D0_DCL |
+ REG_TYPE(FS_T0) << D0_TYPE_SHIFT |
+ REG_NR(FS_T0) << D0_NR_SHIFT |
+ ((REG_TYPE(FS_T0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ /* decl FS_S0 */
+ OUT_BATCH(D0_DCL |
+ (REG_TYPE(FS_S0) << D0_TYPE_SHIFT) |
+ (REG_NR(FS_S0) << D0_NR_SHIFT) |
+ ((REG_TYPE(FS_S0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ /* texld(FS_OC, FS_S0, FS_T0 */
+ OUT_BATCH(T0_TEXLD |
+ (REG_TYPE(FS_OC) << T0_DEST_TYPE_SHIFT) |
+ (REG_NR(FS_OC) << T0_DEST_NR_SHIFT) |
+ (REG_NR(FS_S0) << T0_SAMPLER_NR_SHIFT));
+ OUT_BATCH((REG_TYPE(FS_T0) << T1_ADDRESS_REG_TYPE_SHIFT) |
+ (REG_NR(FS_T0) << T1_ADDRESS_REG_NR_SHIFT));
+ OUT_BATCH(0);
+ }
+
+ OUT_BATCH(PRIM3D_RECTLIST | (3*4 - 1));
+ emit_vertex(batch, dst_x + width);
+ emit_vertex(batch, dst_y + height);
+ emit_vertex(batch, src_x + width);
+ emit_vertex(batch, src_y + height);
+
+ emit_vertex(batch, dst_x);
+ emit_vertex(batch, dst_y + height);
+ emit_vertex(batch, src_x);
+ emit_vertex(batch, src_y + height);
+
+ emit_vertex(batch, dst_x);
+ emit_vertex(batch, dst_y);
+ emit_vertex(batch, src_x);
+ emit_vertex(batch, src_y);
+
+ intel_batchbuffer_flush(batch);
+}
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 00000000..0d04f934
--- /dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,30 @@
+appmandir = $(APP_MAN_DIR)
+appman_PRE = \
+ intel_audio_dump.man \
+ intel_bios_dumper.man \
+ intel_bios_reader.man \
+ intel_error_decode.man \
+ intel_gpu_top.man \
+ intel_gtt.man \
+ intel_infoframes.man \
+ intel_lid.man \
+ intel_panel_fitter.man \
+ intel_reg_dumper.man \
+ intel_reg_read.man \
+ intel_reg_write.man \
+ intel_stepping.man \
+ intel_upload_blit_large.man \
+ intel_upload_blit_large_gtt.man \
+ intel_upload_blit_large_map.man \
+ intel_upload_blit_small.man
+
+appman_DATA = $(appman_PRE:man=$(APP_MAN_SUFFIX))
+
+EXTRA_DIST = $(appman_PRE)
+CLEANFILES = $(appman_DATA)
+
+# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure
+SUFFIXES = .$(APP_MAN_SUFFIX) .man
+
+.man.$(APP_MAN_SUFFIX):
+ $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
diff --git a/man/intel_audio_dump.man b/man/intel_audio_dump.man
new file mode 100644
index 00000000..89a81ec4
--- /dev/null
+++ b/man/intel_audio_dump.man
@@ -0,0 +1,11 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_audio_dump __appmansuffix__ __xorgversion__
+.SH NAME
+intel_audio_dump \- Dumps the Intel GPU registers for HDMI audio setup.
+.SH SYNOPSIS
+.B intel_audio_dump
+.SH DESCRIPTION
+.B intel_audio_dump
+dumps and decodes registers containing the configuration of HDMI audio
+handling on Intel GPUs.
diff --git a/man/intel_bios_dumper.man b/man/intel_bios_dumper.man
new file mode 100644
index 00000000..c9acaa46
--- /dev/null
+++ b/man/intel_bios_dumper.man
@@ -0,0 +1,14 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_bios_dumper __appmansuffix__ __xorgversion__
+.SH NAME
+intel_bios_dumper \- Saves the Intel video BIOS contents to a file.
+.SH SYNOPSIS
+.B intel_bios_dumper \fIfilename\fR
+.SH DESCRIPTION
+.B intel_bios_dumper
+is a tool to save the contents of the Intel video BIOS to a file. It
+can then be parsed offline for debugging issues with the video bios
+table handling.
+.SH SEE ALSO
+.BR intel_bios_reader(1)
diff --git a/man/intel_bios_reader.man b/man/intel_bios_reader.man
new file mode 100644
index 00000000..2f125fc9
--- /dev/null
+++ b/man/intel_bios_reader.man
@@ -0,0 +1,15 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_bios_reader __appmansuffix__ __xorgversion__
+.SH NAME
+intel_bios_reader \- Parses an Intel BIOS and displays many of its tables
+.SH SYNOPSIS
+.B intel_bios_reader \fIfilename\fR
+.SH DESCRIPTION
+.B intel_bios_reader
+is a tool to parse the contents of an Intel video BIOS file. The file
+can come from intel_bios_dumper. This can be used for quick debugging
+of video bios table handling, which is harder when done inside of the
+kernel graphics driver.
+.SH SEE ALSO
+.BR intel_bios_dumper (1)
diff --git a/man/intel_error_decode.man b/man/intel_error_decode.man
new file mode 100644
index 00000000..e53d898d
--- /dev/null
+++ b/man/intel_error_decode.man
@@ -0,0 +1,20 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_error_decode __appmansuffix__ __xorgversion__
+.SH NAME
+intel_error_decode \- Decodes an Intel GPU dump automatically captured by the kernel at the time of an error.
+.SH SYNOPSIS
+.nf
+.B intel_error_decode
+.B intel_error_decode [ filename ]
+.fi
+.SH DESCRIPTION
+.B intel_error_decode
+is a tool that decodes the instructions and state of the GPU at the time of
+an error. It requires kernel 2.6.34 or newer, and either debugfs mounted on
+/sys/kernel/debug or /debug containing a current i915_error_state or you can
+pass a file containing a saved error.
+.SS Options
+.TP
+.B filename
+Decodes a previously saved error.
diff --git a/man/intel_gpu_top.man b/man/intel_gpu_top.man
new file mode 100644
index 00000000..b307a238
--- /dev/null
+++ b/man/intel_gpu_top.man
@@ -0,0 +1,41 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_gpu_top __appmansuffix__ __xorgversion__
+.SH NAME
+intel_gpu_top \- Display a top-like summary of Intel GPU usage
+.SH SYNOPSIS
+.nf
+.B intel_gpu_top
+.B intel_gpu_top [ parameters ]
+.SH DESCRIPTION
+.B intel_gpu_top
+is a tool to display usage information of an Intel GPU. It requires root
+privilege to map the graphics device.
+.SS Options
+.TP
+.B -s [samples per second]
+number of samples to acquire per second
+.TP
+.B -o [output file]
+collect usage statistics to [file]. If file is "-", run non-interactively
+and output statistics to stdout.
+.TP
+.B -e ["command to profile"]
+execute a command, and leave when it is finished. Note that the entire command
+with all parameters should be included as one parameter.
+.TP
+.B -h
+show usage notes
+.SH EXAMPLES
+.TP
+intel_gpu_top -o "cairo-trace-gvim.log" -s 100 -e "cairo-perf-trace /tmp/gvim"
+will run cairo-perf-trace with /tmp/gvim trace, non-interactively, saving the
+statistics into cairo-trace-gvim.log file, and collecting 100 samples per
+second.
+.PP
+Note that idle units are not
+displayed, so an entirely idle GPU will only display the ring status and
+header.
+.SH BUGS
+Some GPUs report some units as busy when they aren't, such that even when
+idle and not hung, it will show up as 100% busy.
diff --git a/man/intel_gtt.man b/man/intel_gtt.man
new file mode 100644
index 00000000..8b23f287
--- /dev/null
+++ b/man/intel_gtt.man
@@ -0,0 +1,14 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_gtt __appmansuffix__ __xorgversion__
+.SH NAME
+intel_gtt \- Dump the contents of an Intel GPU's GTT
+.SH SYNOPSIS
+.B intel_gtt
+.SH DESCRIPTION
+.B intel_gtt
+is a tool to view the contents of the GTT on an Intel GPU. The GTT is
+the page table that maps between GPU addresses and system memory.
+This tool can be useful in debugging the Linux AGP driver
+initialization of the chip or in debugging later overwriting of the
+GTT with garbage data.
diff --git a/man/intel_infoframes.man b/man/intel_infoframes.man
new file mode 100644
index 00000000..b0159492
--- /dev/null
+++ b/man/intel_infoframes.man
@@ -0,0 +1,26 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_infoframes __appmansuffix__ __xorgversion__
+.SH NAME
+intel_infoframes \- View and change HDMI InfoFrames
+.SH SYNOPSIS
+.B intel_infoframes
+.SH DESCRIPTION
+.B intel_infoframes
+is a tool to view and change the HDMI InfoFrames sent by the GPU. Its main
+purpose is to be used as a debugging tool. In some cases (e.g., when
+changing modes) the Kernel will undo the changes made by this tool.
+
+Descriptions of the InfoFrame fields can be found on the HDMI and CEA-861
+specifications.
+
+Use the
+.B -h
+or
+.B --help
+options to learn how to use the command
+.SH LIMITATIONS
+Not all HDMI monitors respect the InfoFrames sent to them. Only GEN 4
+or newer hardware is supported yet.
+.SH SEE ALSO
+HDMI specification, CEA-861 specification.
diff --git a/man/intel_lid.man b/man/intel_lid.man
new file mode 100644
index 00000000..d06af79b
--- /dev/null
+++ b/man/intel_lid.man
@@ -0,0 +1,12 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_lid __appmansuffix__ __xorgversion__
+.SH NAME
+intel_ \- Polls the values of different reports about laptop lid state.
+.SH SYNOPSIS
+.B intel_lid
+.SH DESCRIPTION
+.B intel_lid
+is a tool to poll ACPI and the BIOS scratch register's reporting of
+laptop lid state. This can be used for debugging issues with laptop
+modesetting for lid opening and closing.
diff --git a/man/intel_panel_fitter.man b/man/intel_panel_fitter.man
new file mode 100644
index 00000000..9a46a2ed
--- /dev/null
+++ b/man/intel_panel_fitter.man
@@ -0,0 +1,50 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_panel_fitter __appmansuffix__ __xorgversion__
+.SH NAME
+intel_panel_fitter \- Change the panel fitter settings
+.SH SYNOPSIS
+.B intel_panel_fitter [options]
+.SH DESCRIPTION
+.B intel_panel_fitter
+is a tool that allows you to change the panel fitter settings, so you can change
+the size of the screen being displayed on your monitor without changing the real
+pixel size of your desktop. The biggest use case for this tool is to work around
+overscan done by TVs and some monitors in interlaced mode.
+.SS Options
+.TP
+.B -p [pipe]
+pipe to be used (A, B or C, but C is only present on Ivy Bridge and newer).
+.TP
+.B -x [value]
+final screen width size in pixels (needs -p option).
+.TP
+.B -y [value]
+final screen height size in pixels (needs -p option).
+.TP
+.B -d
+disable panel fitter (needs -p option, ignores -x and -y options).
+.TP
+.B -l
+list current state of each pipe.
+.TP
+.B -h
+prints the help message.
+.SS
+
+.SH EXAMPLES
+.TP
+.B intel_panel_fitter -l
+will list the current status of each pipe, so you can decide what to do.
+.TP
+.B intel_panel_fitter -p A -x 1850 -y 1040
+will change the pipe A size to 1850x1040 pixels.
+.TP
+.B intel_panel_fitter -p A -d
+will disable the panel fitter for pipe A.
+
+.SH NOTES
+In the future, there will be support for this feature inside the Linux Kernel.
+
+Machines older than Ironlake are still not supported, but support may be
+possible to implement.
diff --git a/man/intel_reg_dumper.man b/man/intel_reg_dumper.man
new file mode 100644
index 00000000..89f6b9f9
--- /dev/null
+++ b/man/intel_reg_dumper.man
@@ -0,0 +1,33 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_reg_dumper __appmansuffix__ __xorgversion__
+.SH NAME
+intel_reg_dumper \- Decode a bunch of Intel GPU registers for debugging
+.SH SYNOPSIS
+.B intel_reg_dumper [ options ] [ file ]
+.SH DESCRIPTION
+.B intel_reg_dumper
+is a tool to read and decode the values of many Intel GPU registers. It is
+commonly used in debugging video mode setting issues. If the
+.B file
+argument is present, the registers will be decoded from the given file
+instead of the current registers. Use the
+.B intel_reg_snapshot
+tool to generate such files.
+
+When the
+.B file
+argument is present and the
+.B -d
+argument is not present,
+.B intel_reg_dumper
+will assume the file was generated on an Ironlake machine.
+.SH OPTIONS
+.TP
+.B -d id
+when a dump file is used, use 'id' as device id (in hex)
+.TP
+.B -h
+prints a help message
+.SH SEE ALSO
+.BR intel_reg_snapshot(1)
diff --git a/man/intel_reg_read.man b/man/intel_reg_read.man
new file mode 100644
index 00000000..cc2bf612
--- /dev/null
+++ b/man/intel_reg_read.man
@@ -0,0 +1,15 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_reg_read __appmansuffix__ __xorgversion__
+.SH NAME
+intel_reg_read \- Reads an Intel GPU register value
+.SH SYNOPSIS
+.B intel_reg_read \fIregister\fR
+.SH DESCRIPTION
+.B intel_reg_read
+is a tool to read Intel GPU registers, for use in debugging. The
+\fIregister\fR argument is given as hexadecimal.
+.SH EXAMPLES
+.TP
+intel_reg_read 0x61230
+Shows the register value for the first internal panel fitter.
diff --git a/man/intel_reg_snapshot.man b/man/intel_reg_snapshot.man
new file mode 100644
index 00000000..1930f613
--- /dev/null
+++ b/man/intel_reg_snapshot.man
@@ -0,0 +1,15 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_reg_snapshot __appmansuffix__ __xorgversion__
+.SH NAME
+intel_reg_snapshot \- Take a GPU register snapshot
+.SH SYNOPSIS
+.B intel_reg_snapshot
+.SH DESCRIPTION
+.B intel_reg_snapshot
+takes a snapshot of the registers of an Intel GPU, and writes it to standard
+output. These files can be inspected later with the
+.B intel_reg_dumper
+tool.
+.SH SEE ALSO
+.BR intel_reg_dumper(1)
diff --git a/man/intel_reg_write.man b/man/intel_reg_write.man
new file mode 100644
index 00000000..cb1731c6
--- /dev/null
+++ b/man/intel_reg_write.man
@@ -0,0 +1,16 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_reg_write __appmansuffix__ __xorgversion__
+.SH NAME
+intel_reg_write \- Set an Intel GPU register to a value
+.SH SYNOPSIS
+.B intel_reg_write \fIregister\fR \fIvalue\fR
+.SH DESCRIPTION
+.B intel_reg_write
+is a tool to set Intel GPU registers to values, for use in speeding up
+debugging. The \fIregister\fR and \fIvalue\fR arguments are given as
+hexadecimal.
+.SH EXAMPLES
+.TP
+intel_reg_write 0x61230 0x0
+Disables the first internal panel fitter.
diff --git a/man/intel_stepping.man b/man/intel_stepping.man
new file mode 100644
index 00000000..fe172107
--- /dev/null
+++ b/man/intel_stepping.man
@@ -0,0 +1,15 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_stepping __appmansuffix__ __xorgversion__
+.SH NAME
+intel_stepping \- Display the stepping information for an Intel GPU
+.SH SYNOPSIS
+.B intel_stepping
+.SH DESCRIPTION
+.B intel_stepping
+is a tool to print the stepping information for an Intel GPU, along with
+the PCI ID and revision used to determine it.
+It requires root privilege to map the graphics device.
+.SH BUGS
+Not all the known stepping IDs or chipsets are included, so the output
+on some devices may not be as specific as possible.
diff --git a/man/intel_upload_blit_large.man b/man/intel_upload_blit_large.man
new file mode 100644
index 00000000..9c75e1a1
--- /dev/null
+++ b/man/intel_upload_blit_large.man
@@ -0,0 +1,18 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_upload_blit_large __appmansuffix__ __xorgversion__
+.SH NAME
+intel_upload_blit_large \- microbenchmark of Intel GPU performance
+.SH SYNOPSIS
+.nf
+.B intel_upload_blit_large
+.fi
+.SH DESCRIPTION
+.B intel_upload_blit_large
+is a microbenchmark tool for DRM performance. It should be run with kernel
+modesetting enabled, and may require root privilege for correct operation.
+It does not require X to be running.
+.PP
+Given that it is a microbenchmark, its utility is largely for regression
+testing of the kernel, and not for general conclusions on graphics
+performance.
diff --git a/man/intel_upload_blit_large_gtt.man b/man/intel_upload_blit_large_gtt.man
new file mode 100644
index 00000000..fbe4623c
--- /dev/null
+++ b/man/intel_upload_blit_large_gtt.man
@@ -0,0 +1,18 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_upload_blit_large_gtt __appmansuffix__ __xorgversion__
+.SH NAME
+intel_upload_blit_large_gtt \- microbenchmark of Intel GPU performance
+.SH SYNOPSIS
+.nf
+.B intel_upload_blit_large_gtt
+.fi
+.SH DESCRIPTION
+.B intel_upload_blit_large_gtt
+is a microbenchmark tool for DRM performance. It should be run with kernel
+modesetting enabled, and may require root privilege for correct operation.
+It does not require X to be running.
+.PP
+Given that it is a microbenchmark, its utility is largely for regression
+testing of the kernel, and not for general conclusions on graphics
+performance.
diff --git a/man/intel_upload_blit_large_map.man b/man/intel_upload_blit_large_map.man
new file mode 100644
index 00000000..04123f3d
--- /dev/null
+++ b/man/intel_upload_blit_large_map.man
@@ -0,0 +1,18 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_upload_blit_large_map __appmansuffix__ __xorgversion__
+.SH NAME
+intel_upload_blit_large_map \- microbenchmark of Intel GPU performance
+.SH SYNOPSIS
+.nf
+.B intel_upload_blit_large_map
+.fi
+.SH DESCRIPTION
+.B intel_upload_blit_large_map
+is a microbenchmark tool for DRM performance. It should be run with kernel
+modesetting enabled, and may require root privilege for correct operation.
+It does not require X to be running.
+.PP
+Given that it is a microbenchmark, its utility is largely for regression
+testing of the kernel, and not for general conclusions on graphics
+performance.
diff --git a/man/intel_upload_blit_small.man b/man/intel_upload_blit_small.man
new file mode 100644
index 00000000..478bbfc5
--- /dev/null
+++ b/man/intel_upload_blit_small.man
@@ -0,0 +1,18 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH intel_upload_blit_small __appmansuffix__ __xorgversion__
+.SH NAME
+intel_upload_blit_small \- microbenchmark of Intel GPU performance
+.SH SYNOPSIS
+.nf
+.B intel_upload_blit_small
+.fi
+.SH DESCRIPTION
+.B intel_upload_blit_small
+is a microbenchmark tool for DRM performance. It should be run with kernel
+modesetting enabled, and may require root privilege for correct operation.
+It does not require X to be running.
+.PP
+Given that it is a microbenchmark, its utility is largely for regression
+testing of the kernel, and not for general conclusions on graphics
+performance.
diff --git a/packaging/intel-gpu-tools.changes b/packaging/intel-gpu-tools.changes
new file mode 100644
index 00000000..d0f8a262
--- /dev/null
+++ b/packaging/intel-gpu-tools.changes
@@ -0,0 +1,5 @@
+* Fri Jan 25 2013 Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com> intel-gpu-tools-1.3
+- Initial release to Tizen
+- custom .gbs.conf file
+- packaging information
+
diff --git a/packaging/intel-gpu-tools.spec b/packaging/intel-gpu-tools.spec
new file mode 100644
index 00000000..596dbd3e
--- /dev/null
+++ b/packaging/intel-gpu-tools.spec
@@ -0,0 +1,36 @@
+Name: intel-gpu-tools
+Summary: Diagnositc tools for Intel Integrated Graphics
+Version: 1.3
+Release: 1
+VCS: git/xorg/app/intel-gpu-tools.git#intel-gpu-tools-1.3-1-g24e49c7
+Group: Development/Tools
+License: MIT
+URL: http://xorg.freedesktop.org/
+Source0: http://xorg.freedesktop.org/archive/individual/app/intel-gpu-tools-%{version}.tar.bz2
+BuildRequires: pkgconfig(libdrm_intel)
+BuildRequires: pkgconfig(pciaccess)
+BuildRequires: pkgconfig(xorg-macros)
+BuildRequires: pkgconfig(cairo)
+BuildRequires: pkgconfig(libudev)
+
+%description
+Description: %{summary}
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+%reconfigure --disable-static \
+ --disable-nouveau
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%files
+%defattr(-,root,root,-)
+%doc README
+%{_bindir}/*
+%doc %{_mandir}/man1/*.1.gz
+
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
new file mode 100644
index 00000000..baf3612e
--- /dev/null
+++ b/scripts/Makefile.am
@@ -0,0 +1,3 @@
+
+dist_noinst_SCRIPTS = who.sh
+noinst_PYTHON = throttle.py
diff --git a/scripts/convert_itp.py b/scripts/convert_itp.py
new file mode 100755
index 00000000..4474f34d
--- /dev/null
+++ b/scripts/convert_itp.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python3
+
+#this script helps to convert internal debugger scripts given to us into our tools
+
+import sys
+import fileinput
+
+def replace_with_dict(text, dicto):
+ for key, val in dicto.items():
+ text = text.replace(key, val)
+ return text
+
+for lines in fileinput.input([sys.argv[1]], inplace=True):
+ lines = lines.strip()
+ if lines == '': continue # strip empty lines
+ replace_dict = {'dword(' : '../tools/intel_reg_read ', 'MMADDR + ' : '', '//' : '#', ')p;' : '', ')p ' : ' -c '}
+ print(replace_with_dict(lines, replace_dict))
diff --git a/scripts/display_debug.sh b/scripts/display_debug.sh
new file mode 100755
index 00000000..f854f90b
--- /dev/null
+++ b/scripts/display_debug.sh
@@ -0,0 +1,172 @@
+#!/bin/bash
+
+# FBC_CFB_BASE 0x43200
+../tools/intel_reg_read 0x43200
+# FBC_CTL 0x43208
+../tools/intel_reg_read 0x43208
+# ERR_INT 0x44040
+../tools/intel_reg_read 0x44040
+# DE_RRMR 0x44050
+../tools/intel_reg_read 0x44050
+# ARB_CTL 0x45000
+../tools/intel_reg_read 0x45000
+# ARB_CTL2 0x45004
+../tools/intel_reg_read 0x45004
+# MSG_CTL 0x45010
+../tools/intel_reg_read 0x45010
+# Watermarks
+../tools/intel_reg_read 0x45100
+../tools/intel_reg_read 0x45104
+../tools/intel_reg_read 0x45200
+../tools/intel_reg_read 0x45108
+../tools/intel_reg_read 0x4510C
+../tools/intel_reg_read 0x45110
+../tools/intel_reg_read 0x45120
+../tools/intel_reg_read 0x45124
+../tools/intel_reg_read 0x45128
+# Pipe A timing 0x60000-0x6004C
+../tools/intel_reg_read 0x60000 -c 0x13;
+# Pipe B timing 0x61000-0x6104C
+../tools/intel_reg_read 0x61000 -c 0x13;
+# Pipe C timing 0x62000-0x6204C
+../tools/intel_reg_read 0x62000 -c 0x13;
+# FDI A 0x60100
+# FDI B 0x61100
+# FDI C 0x62100
+# EDP 0x64000
+../tools/intel_reg_read 0x60100
+../tools/intel_reg_read 0x61100
+../tools/intel_reg_read 0x62100
+../tools/intel_reg_read 0x64000
+# Panel fitter A window size 0x68074
+# Panel fitter A control 0x68080
+../tools/intel_reg_read 0x68074
+../tools/intel_reg_read 0x68080
+# Panel fitter B window size 0x68874
+# Panel fitter B control 0x68880
+../tools/intel_reg_read 0x68874
+../tools/intel_reg_read 0x68880
+# Panel fitter C window size 0x69074
+# Panel fitter C control 0x69080
+../tools/intel_reg_read 0x69074
+../tools/intel_reg_read 0x69080
+# Pipe A config 0x70008
+# Pipe B config 0x71008
+# Pipe C config 0x72008
+../tools/intel_reg_read 0x70008
+../tools/intel_reg_read 0x71008
+../tools/intel_reg_read 0x72008
+# Cursor A control 0x70080
+# Cursor B control 0x71080
+# Cursor C control 0x72080
+../tools/intel_reg_read 0x70080
+../tools/intel_reg_read 0x71080
+../tools/intel_reg_read 0x72080
+# Primary A control 0x70180
+# Primary B control 0x71180
+# Primary C control 0x72180
+../tools/intel_reg_read 0x70180
+../tools/intel_reg_read 0x71180
+../tools/intel_reg_read 0x72180
+# Sprite A control 0x70280
+# Sprite B control 0x71280
+# Sprite C control 0x72280
+../tools/intel_reg_read 0x70280
+../tools/intel_reg_read 0x71280
+../tools/intel_reg_read 0x72280
+# Sprite A size 0x70290
+# Sprite B size 0x71290
+# Sprite C size 0x72290
+../tools/intel_reg_read 0x70290
+../tools/intel_reg_read 0x71290
+../tools/intel_reg_read 0x72290
+# Sprite A scaling 0x70304
+# Sprite B scaling 0x71304
+# Sprite C scaling 0x72304
+../tools/intel_reg_read 0x70304
+../tools/intel_reg_read 0x71304
+../tools/intel_reg_read 0x72304
+# PCH DE Interrupt enable 0xC400C
+../tools/intel_reg_read 0xC400C
+# PCH DE Interrupt IIR 0xC4008
+../tools/intel_reg_read 0xC4008
+# PCH DE hotplug 0xC4030
+../tools/intel_reg_read 0xC4030
+# SERR_INT 0xC4040
+../tools/intel_reg_read 0xC4040
+# PCH DPLL A CTL 0xC6014
+# PCH DPLL A Divisor 0 0xC6040
+# PCH DPLL A Divisor 1 0xC6044
+../tools/intel_reg_read 0xC6014
+../tools/intel_reg_read 0xC6040
+../tools/intel_reg_read 0xC6044
+# PCH DPLL B CTL 0xC6018
+# PCH DPLL B Divisor 0 0xC6048
+# PCH DPLL B Divisor 1 0xC604C
+../tools/intel_reg_read 0xC6018
+../tools/intel_reg_read 0xC6048
+../tools/intel_reg_read 0xC604C
+# PCH DPLL DREF CTL 0xC6200
+../tools/intel_reg_read 0xC6200
+# PCH DPLL SEL 0xC7000
+../tools/intel_reg_read 0xC7000
+# PCH Panel Status 0xC7200
+../tools/intel_reg_read 0xC7200
+# PCH Panel Control 0xC7204
+../tools/intel_reg_read 0xC7204
+# Transcoder A timing 0xE0000-0xE004F
+# Transcoder B timing 0xE1000-0xE104F
+# Transcoder C timing 0xE2000-0xE204F
+../tools/intel_reg_read 0xE0000 -c 0x14;
+../tools/intel_reg_read 0xE1000 -c 0x14;
+../tools/intel_reg_read 0xE2000 -c 0x14;
+# Transcoder A DP CTL 0xE0300
+# Transcoder B DP CTL 0xE1300
+# Transcoder C DP CTL 0xE2300
+../tools/intel_reg_read 0xE0300
+../tools/intel_reg_read 0xE1300
+../tools/intel_reg_read 0xE2300
+# CRT DAC CTL 0xE1100
+../tools/intel_reg_read 0xE1100
+# HDMI/DVI B CTL 0xE1140
+# HDMI/DVI C CTL 0xE1150
+# HDMI/DVI D CTL 0xE1160
+../tools/intel_reg_read 0xE1140
+../tools/intel_reg_read 0xE1150
+../tools/intel_reg_read 0xE1160
+# LVDS 0xE1180
+../tools/intel_reg_read 0xE1180
+# DP B CTL 0xE4100
+# DP C CTL 0xE4200
+# DP D CTL 0xE4300
+../tools/intel_reg_read 0xE4100
+../tools/intel_reg_read 0xE4200
+../tools/intel_reg_read 0xE4300
+# Transcoder A config 0xF0008
+# FDI RX A CTL 0xF000C
+# FDI RX A MISC 0xF0010
+# FDI RX A IIR 0xF0014
+# FDI RX A IMR 0xF0018
+../tools/intel_reg_read 0xF0008 -c 5;
+# Transcoder B config 0xF1008
+# FDI RX B CTL 0xF100C
+# FDI RX B MISC 0xF1010
+# FDI RX B IIR 0xF1014
+# FDI RX B IMR 0xF1018
+../tools/intel_reg_read 0xF1008 -c 5;
+# Transcoder C config 0xF2008
+# FDI RX C CTL 0xF200C
+# FDI RX C MISC 0xF2010
+# FDI RX C IIR 0xF2014
+# FDI RX C IMR 0xF2018
+../tools/intel_reg_read 0xF2008 -c 5;
+#Check if frame and line counters are running
+../tools/intel_reg_read 0x44070
+../tools/intel_reg_read 0x70050
+../tools/intel_reg_read 0x71050
+../tools/intel_reg_read 0x72050
+sleep 2;
+../tools/intel_reg_read 0x44070
+../tools/intel_reg_read 0x70050
+../tools/intel_reg_read 0x71050
+../tools/intel_reg_read 0x72050
diff --git a/scripts/throttle.py b/scripts/throttle.py
new file mode 100755
index 00000000..126175ca
--- /dev/null
+++ b/scripts/throttle.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+#
+# Usage:
+# scripts/throttle.py trace-dat
+#
+# Shows how often the trace throttles and for how long.
+
+import getopt
+from tracecmd import *
+import sys
+
+requests = {}
+throttle = {}
+prev_throttle = 0;
+
+def read_events(t):
+ for cpu in range(0, t.cpus):
+ e = t.read_event(cpu)
+ while e:
+ if e.name == 'i915_gem_request_complete':
+ seqno = e.num_field('seqno')
+ requests[seqno] = e.ts;
+
+ if e.name == 'i915_gem_request_throttle_begin':
+ seqno = e.num_field('seqno')
+ throttle[seqno] = e.ts
+
+ if e.name == 'i915_gem_request_throttle_end':
+ global prev_throttle
+
+ ts = 0
+ sum_dispatch = 0
+ num_dispatch = 0
+ max_dispatch = 0
+
+ seqno = e.num_field('seqno')
+ s = prev_throttle
+ if s == 0:
+ s = seqno
+ while s <= seqno:
+ if requests.has_key(s):
+ if ts:
+ delta = requests[s] - ts
+ num_dispatch += 1
+ sum_dispatch += delta
+ if delta > max_dispatch: max_dispatch = delta
+ ts = requests[s]
+ s += 1
+
+ if throttle.has_key(seqno) and throttle.has_key(prev_throttle) and num_dispatch:
+ print "throttle +%d: %dms -- %d dispatch, avg %.3fms, max %dus" % ((throttle[seqno]-throttle[prev_throttle])/1000000, (e.ts - throttle[seqno]) / 1000000, num_dispatch, sum_dispatch / (1000000. * num_dispatch), max_dispatch / 1000)
+ throttle[seqno] = e.ts
+
+ prev_throttle = seqno
+
+ e = t.read_event(cpu)
+
+if __name__ == "__main__":
+ if len(sys.argv) >=2:
+ filename = sys.argv[1]
+ else:
+ filename = "trace.dat"
+
+ print "Initializing trace '%s'..." % (filename)
+ trace = Trace(filename)
+ read_events(trace)
+
diff --git a/scripts/who.sh b/scripts/who.sh
new file mode 100755
index 00000000..b2216398
--- /dev/null
+++ b/scripts/who.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+#
+# usage: sudo who.sh
+#
+# Requires root permissions to both query who has the device open,
+# and to read the mappings of likely root-owned processes
+#
+
+for i in `lsof -t /dev/dri/card0`; do
+ who=`readlink /proc/$i/exe`
+ count=`grep /dev/dri/card0 /proc/$i/maps | wc -l | cut -f1 -d\ `
+ echo "$who [$i]: $count"
+done
diff --git a/shaders/ps/README b/shaders/ps/README
new file mode 100644
index 00000000..b196d025
--- /dev/null
+++ b/shaders/ps/README
@@ -0,0 +1 @@
+These files are here for reference only.
diff --git a/shaders/ps/blit.g7a b/shaders/ps/blit.g7a
new file mode 100644
index 00000000..deeedcc5
--- /dev/null
+++ b/shaders/ps/blit.g7a
@@ -0,0 +1,66 @@
+/* Assemble with ".../intel-gen4asm/src/intel-gen4asm -g 7" */
+
+
+/* Move pixels into g10-g13. The pixel shaader does not load what you want. It
+ * loads the input data for a plane function to calculate what you want. The
+ * following is boiler plate code to move our normalized texture coordinates
+ * (u,v) into g10-g13. It does this 4 subspans (16 pixels) at a time.
+ *
+ * This should do the same thing, but it doesn't work for some reason.
+ * pln(16) g10 g6<0,1,0>F g2<8,8,1>F { align1 };
+ * pln(16) g12 g6.16<1>F g2<8,8,1>F { align1 };
+ */
+/* U */
+pln (8) g10<1>F g6.0<0,1,0>F g2.0<8,8,1>F { align1 }; /* pixel 0-7 */
+pln (8) g11<1>F g6.0<0,1,0>F g4.0<8,8,1>F { align1 }; /* pixel 8-15 */
+/* V */
+pln (8) g12<1>F g6.16<0,1,0> g2.0<8,8,1>F { align1 }; /* pixel 0-7 */
+pln (8) g13<1>F g6.16<0,1,0> g4.0<8,8,1>F { align1 }; /* pixel 8-15 */
+
+
+/* Next the we want the sampler to fetch the src texture (ie. src buffer). This
+ * is done with a pretty simple send message. The output goes to g112, which is
+ * exactly what we're supposed to use in our final send message.
+ * In intel-gen4asm, we should end up parsed by the following rule:
+ * predicate SEND execsize dst sendleadreg sndopr directsrcoperand instoptions
+ *
+ * Send message descriptor:
+ * 28:25 = message len = 4 // our 4 registers have 16 pixels
+ * 24:20 = response len = 8 // Each pixel is RGBA32, so we need 8 registers
+ * 19:19 = header present = 0
+ * 18:17 = SIMD16 = 2
+ * 16:12 = TYPE = 0 (regular sample)
+ * 11:08 = Sampler index = ignored/0
+ * 7:0 = binding table index = src = 1
+ * 0x8840001
+ *
+ * Send message extra descriptor
+ * 5:5 = End of Thread = 0
+ * 3:0 = Target Function ID = SFID_SAMPLER (2)
+ * 0x2
+ */
+
+send(16) g112 g10 0x2 0x8840001 { align1 };
+
+/* g112-g119 now contains the sample source input, and all we must do is write
+ * it out to the destination render target. This is done with the send message
+ * as well. The only extra bits are to terminate the pixel shader.
+ *
+ * Send message descriptor:
+ * 28:25 = message len = 8 // 16 pixels RGBA32
+ * 24:20 = response len = 0
+ * 19:19 = header present = 0
+ * 17:14 = message type = Render Target Write (12)
+ * 12:12 = Last Render Target Select = 1
+ * 10:08 = Message Type = SIMD16 (0)
+ * 07:00 = Binding Table Index = dest = 0
+ * 0x10031000
+ *
+ * Send message extra descriptor
+ * 5:5 = End of Thread = 1
+ * 3:0 = Target Function ID = SFID_DP_RC (5)
+ * 0x25
+ */
+send(16) null g112 0x25 0x10031000 { align1, EOT };
+
+/* vim: set ft=c ts=4 sw=2 tw=80 et: */
diff --git a/shaders/ps/neg1_test.g7a b/shaders/ps/neg1_test.g7a
new file mode 100644
index 00000000..744a7690
--- /dev/null
+++ b/shaders/ps/neg1_test.g7a
@@ -0,0 +1,9 @@
+mov(8) g112:UD 0x3f800000:UD { align1 };
+mov(8) g113:UD 0x3f800000:UD { align1 };
+mov(8) g114:UD 0x3f800000:UD { align1 };
+mov(8) g115:UD 0x3f800000:UD { align1 };
+mov(8) g116:UD 0x3f800000:UD { align1 };
+mov(8) g117:UD 0x3f800000:UD { align1 };
+mov(8) g118:UD 0x3f800000:UD { align1 };
+mov(8) g119:UD 0x3f800000:UD { align1 };
+send(16) null g112 0x25 0x10031000 { align1, EOT };
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 00000000..1a6795bc
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1,78 @@
+flip_test
+drm_vma_limiter
+drm_vma_limiter_cached
+drm_vma_limiter_cpu
+drm_vma_limiter_gtt
+gem_bad_address
+gem_bad_batch
+gem_bad_blit
+gem_bad_length
+gem_basic
+gem_cs_prefetch
+gem_cpu_concurrent_blit
+gem_ctx_bad_destroy
+gem_ctx_bad_exec
+gem_ctx_basic
+gem_ctx_create
+gem_ctx_exec
+gem_double_irq_loop
+gem_dummy_reloc_loop
+gem_exec_bad_domains
+gem_exec_blt
+gem_exec_faulting_reloc
+gem_exec_nop
+gem_fenced_exec_thrash
+gem_fence_thrash
+gem_flink
+gem_gtt_speed
+gem_gtt_concurrent_blit
+gem_gtt_cpu_tlb
+gem_hang
+gem_hangcheck_forcewake
+gem_largeobject
+gem_linear_blits
+gem_mmap
+gem_mmap_gtt
+gem_mmap_offset_exhaustion
+gem_partial_pwrite_pread
+gem_pipe_control_store_loop
+gem_pread_after_blit
+gem_pwrite
+gem_readwrite
+gem_reloc_vs_gpu
+gem_reg_read
+gem_ringfill
+gem_ring_sync_loop
+gem_set_tiling_vs_blt
+gem_set_tiling_vs_gtt
+gem_set_tiling_vs_pwrite
+gem_storedw_batches_loop
+gem_storedw_loop_blt
+gem_storedw_loop_bsd
+gem_storedw_loop_render
+gem_stress
+gem_tiled_blits
+gem_tiled_fence_blits
+gem_tiled_partial_pwrite_pread
+gem_tiled_pread
+gem_tiled_pread_pwrite
+gem_tiled_swapping
+gem_unfence_active_buffers
+gem_unref_active_buffers
+gem_vmap_blits
+gem_wait_render_timeout
+gen3_mixed_blits
+gen3_render_linear_blits
+gen3_render_mixed_blits
+gen3_render_tiledx_blits
+gen3_render_tiledy_blits
+getclient
+getstats
+getversion
+prime_nv_api
+prime_nv_pcopy
+prime_nv_test
+prime_self_import
+testdisplay
+sysfs_rc6_residency
+# Please keep sorted alphabetically
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 00000000..e29a383a
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,148 @@
+noinst_PROGRAMS = \
+ gem_stress \
+ $(TESTS_progs) \
+ $(HANG) \
+ $(NULL)
+
+if HAVE_NOUVEAU
+NOUVEAU_TESTS = \
+ prime_nv_api \
+ prime_nv_pcopy \
+ prime_nv_test
+endif
+
+TESTS_progs = \
+ getversion \
+ getclient \
+ getstats \
+ gem_basic \
+ gem_cpu_concurrent_blit \
+ gem_gtt_concurrent_blit \
+ gem_exec_nop \
+ gem_exec_blt \
+ gem_exec_bad_domains \
+ gem_exec_faulting_reloc \
+ gem_flink \
+ gem_readwrite \
+ gem_ringfill \
+ gem_mmap \
+ gem_mmap_gtt \
+ gem_mmap_offset_exhaustion \
+ gem_pwrite \
+ gem_pread_after_blit \
+ gem_set_tiling_vs_blt \
+ gem_set_tiling_vs_gtt \
+ gem_set_tiling_vs_pwrite \
+ gem_tiled_pread \
+ gem_tiled_pread_pwrite \
+ gem_tiled_partial_pwrite_pread \
+ gem_tiled_swapping \
+ gem_partial_pwrite_pread \
+ gem_linear_blits \
+ gem_vmap_blits \
+ gem_tiled_blits \
+ gem_tiled_fence_blits \
+ gem_largeobject \
+ gem_bad_length \
+ gem_fence_thrash \
+ gem_fenced_exec_thrash \
+ gem_gtt_speed \
+ gem_gtt_cpu_tlb \
+ gem_cs_prefetch \
+ gen3_render_linear_blits \
+ gen3_render_tiledx_blits \
+ gen3_render_tiledy_blits \
+ gen3_render_mixed_blits \
+ gen3_mixed_blits \
+ gem_storedw_loop_render \
+ gem_storedw_loop_blt \
+ gem_storedw_loop_bsd \
+ gem_storedw_batches_loop \
+ gem_dummy_reloc_loop \
+ gem_double_irq_loop \
+ gem_ring_sync_loop \
+ gem_pipe_control_store_loop \
+ gem_unfence_active_buffers \
+ gem_unref_active_buffers \
+ gem_reloc_vs_gpu \
+ drm_vma_limiter \
+ drm_vma_limiter_cpu \
+ drm_vma_limiter_gtt \
+ drm_vma_limiter_cached \
+ sysfs_rc6_residency \
+ flip_test \
+ gem_wait_render_timeout \
+ gem_ctx_create \
+ gem_ctx_bad_destroy \
+ gem_ctx_exec \
+ gem_ctx_bad_exec \
+ gem_ctx_basic \
+ gem_reg_read \
+ $(NOUVEAU_TESTS) \
+ prime_self_import \
+ $(NULL)
+
+# IMPORTANT: The ZZ_ tests need to be run last!
+# ... and make can't deal with inlined comments ...
+TESTS_scripts = \
+ debugfs_reader \
+ debugfs_emon_crash \
+ sysfs_l3_parity \
+ sysfs_edid_timing \
+ module_reload \
+ ZZ_check_dmesg \
+ ZZ_hangman \
+ $(NULL)
+
+kernel_tests = \
+ $(TESTS_progs) \
+ $(TESTS_scripts) \
+ $(NULL)
+
+TESTS = \
+ $(NULL)
+
+test:
+ whoami | grep root || ( echo ERROR: not running as root; exit 1 )
+ ./check_drm_clients
+ make TESTS="${kernel_tests}" check
+
+HANG = \
+ gem_bad_batch \
+ gem_hang \
+ gem_bad_blit \
+ gem_bad_address \
+ $(NULL)
+
+EXTRA_PROGRAMS = $(TESTS_progs) $(HANG)
+EXTRA_DIST = $(TESTS_scripts) drm_lib.sh check_drm_clients debugfs_wedged
+CLEANFILES = $(EXTRA_PROGRAMS)
+
+AM_CFLAGS = $(DRM_CFLAGS) $(CWARNFLAGS) \
+ -I$(srcdir)/.. \
+ -I$(srcdir)/../lib
+LDADD = ../lib/libintel_tools.la $(PCIACCESS_LIBS) $(DRM_LIBS)
+
+testdisplay_SOURCES = \
+ testdisplay.c \
+ testdisplay.h \
+ testdisplay_hotplug.c \
+ $(NULL)
+
+TESTS_progs += testdisplay
+LDADD += $(CAIRO_LIBS) $(LIBUDEV_LIBS) $(GLIB_LIBS)
+AM_CFLAGS += $(CAIRO_CFLAGS) $(LIBUDEV_CFLAGS) $(GLIB_CFLAGS)
+
+gem_fence_thrash_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS)
+gem_fence_thrash_LDADD = $(LDADD) -lpthread
+
+gem_wait_render_timeout_LDADD = $(LDADD) -lrt
+
+gem_ctx_basic_LDADD = $(LDADD) -lpthread
+
+prime_nv_test_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS)
+prime_nv_test_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS)
+prime_nv_api_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS)
+prime_nv_api_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS)
+prime_nv_pcopy_CFLAGS = $(AM_CFLAGS) $(DRM_NOUVEAU_CFLAGS)
+prime_nv_pcopy_LDADD = $(LDADD) $(DRM_NOUVEAU_LIBS)
diff --git a/tests/ZZ_check_dmesg b/tests/ZZ_check_dmesg
new file mode 100755
index 00000000..e28ba35f
--- /dev/null
+++ b/tests/ZZ_check_dmesg
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if dmesg | grep '\*ERROR\*' > /dev/null ; then
+ echo "DRM_ERROR dirt in dmesg"
+ exit 1
+fi
+
+if dmesg | grep -- '------\[ cut here \]----' > /dev/null ; then
+ echo "found a backtrace in dmesg"
+ exit 1
+fi
diff --git a/tests/ZZ_hangman b/tests/ZZ_hangman
new file mode 100755
index 00000000..b8f4a682
--- /dev/null
+++ b/tests/ZZ_hangman
@@ -0,0 +1,42 @@
+#!/bin/bash
+#
+# Testcase: Simulate gpu hang
+#
+# This check uses the stop_rings facility to exercise the gpu hang code.
+# by reading /sys/kernel/debug/dri/0/i915_emon_status too quickly
+#
+
+SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )"
+. $SOURCE_DIR/drm_lib.sh
+
+oldpath=`pwd`
+
+cd $i915_path
+
+if [ ! -f i915_ring_stop ] ; then
+ echo "kernel doesn't support ring stopping"
+ exit 77
+fi
+
+if cat i915_error_state | grep -v "no error state collected" > /dev/null ; then
+ echo "gpu hang dectected"
+ exit 1
+fi
+
+# stop rings
+echo 0xf > i915_ring_stop
+echo "rings stopped"
+
+(cd $oldpath; $SOURCE_DIR/gem_exec_nop) > /dev/null
+
+if cat i915_error_state | grep -v "no error state collected" > /dev/null ; then
+ echo "gpu hang correctly dectected"
+else
+ echo "gpu hang not dectected"
+ exit 2
+fi
+
+# clear error state
+echo > i915_error_state
+
+exit 0
diff --git a/tests/check_drm_clients b/tests/check_drm_clients
new file mode 100755
index 00000000..eb12416a
--- /dev/null
+++ b/tests/check_drm_clients
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )"
+. $SOURCE_DIR/drm_lib.sh
+
+exit 0
diff --git a/tests/debugfs_emon_crash b/tests/debugfs_emon_crash
new file mode 100755
index 00000000..6e139a41
--- /dev/null
+++ b/tests/debugfs_emon_crash
@@ -0,0 +1,16 @@
+#!/bin/bash
+#
+# This check if we can crash the kernel with segmentation-fault
+# by reading /sys/kernel/debug/dri/0/i915_emon_status too quickly
+#
+
+SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )"
+. $SOURCE_DIR/drm_lib.sh
+
+for z in $(seq 1 1000); do
+ cat $i915_path/i915_emon_status > /dev/null 2&>1
+done
+
+# If we got here, we haven't crashed
+
+exit 0
diff --git a/tests/debugfs_reader b/tests/debugfs_reader
new file mode 100755
index 00000000..80d59988
--- /dev/null
+++ b/tests/debugfs_reader
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )"
+. $SOURCE_DIR/drm_lib.sh
+
+# read everything we can
+cat $i915_path/* > /dev/null 2>&1
+
+exit 0
diff --git a/tests/debugfs_wedged b/tests/debugfs_wedged
new file mode 100755
index 00000000..80a32f61
--- /dev/null
+++ b/tests/debugfs_wedged
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )"
+. $SOURCE_DIR/drm_lib.sh
+
+# Testcase: wedge the hw to check the error_state reading
+#
+# Unfortunately wedged is permanent, so this test is not run by default
+echo 1 > ${i915_path}/i915_wedged
+cat $i915_path/i915_error_state > /dev/null 2>&1
diff --git a/tests/drm_lib.sh b/tests/drm_lib.sh
new file mode 100755
index 00000000..a76fd474
--- /dev/null
+++ b/tests/drm_lib.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+die() {
+ echo "$@"
+ exit 1
+}
+
+if [ -d /debug/dri ] ; then
+ debugfs_path=/debug/dri
+fi
+
+if [ -d /sys/kernel/debug/dri ] ; then
+ debugfs_path=/sys/kernel/debug/dri
+fi
+
+i915_path=x
+for dir in `ls $debugfs_path` ; do
+ if [ -f $debugfs_path/$dir/i915_error_state ] ; then
+ i915_path=$debugfs_path/$dir
+ break
+ fi
+done
+
+if [ $i915_path = "x" ] ; then
+ die " i915 debugfs path not found."
+fi
+
+# read everything we can
+if [ `cat $i915_path/clients | wc -l` -gt "2" ] ; then
+ die "ERROR: other drm clients running"
+fi
+
+
diff --git a/tests/drm_vma_limiter.c b/tests/drm_vma_limiter.c
new file mode 100644
index 00000000..1971e2dc
--- /dev/null
+++ b/tests/drm_vma_limiter.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+/* Testcase: check whether the libdrm vma limiter works
+ *
+ * We've had reports of the X server exhausting the default rlimit of 64k vma's
+ * in the kernel. libdrm has grown facilities to limit the vma caching since,
+ * this checks whether they actually work.
+ */
+
+/* we do both cpu and gtt maps, so only need half of 64k to exhaust */
+#define BO_ARRAY_SIZE 35000
+drm_intel_bo *bos[BO_ARRAY_SIZE];
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int i;
+ char *ptr;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ drm_intel_bufmgr_gem_set_vma_cache_size(bufmgr, 500);
+
+ for (i = 0; i < BO_ARRAY_SIZE; i++) {
+ bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096);
+ assert(bos[i]);
+
+ drm_intel_bo_map(bos[i], 1);
+ ptr = bos[i]->virtual;
+ assert(ptr);
+ *ptr = 'c';
+ drm_intel_bo_unmap(bos[i]);
+
+ drm_intel_gem_bo_map_gtt(bos[i]);
+ ptr = bos[i]->virtual;
+ assert(ptr);
+ *ptr = 'c';
+ drm_intel_gem_bo_unmap_gtt(bos[i]);
+ }
+
+ /* and recheck whether a second map of the same still works */
+ for (i = 0; i < BO_ARRAY_SIZE; i++) {
+ bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096);
+ assert(bos[i]);
+
+ drm_intel_bo_map(bos[i], 1);
+ ptr = bos[i]->virtual;
+ assert(*ptr = 'c');
+ drm_intel_bo_unmap(bos[i]);
+
+ drm_intel_gem_bo_map_gtt(bos[i]);
+ ptr = bos[i]->virtual;
+ assert(*ptr = 'c');
+ drm_intel_gem_bo_unmap_gtt(bos[i]);
+ }
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/drm_vma_limiter_cached.c b/tests/drm_vma_limiter_cached.c
new file mode 100644
index 00000000..37976185
--- /dev/null
+++ b/tests/drm_vma_limiter_cached.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+/* Testcase: check whether the libdrm vma limiter works
+ *
+ * We've had reports of the X server exhausting the default rlimit of 64k vma's
+ * in the kernel. libdrm has grown facilities to limit the vma caching since,
+ * this checks whether they actually work.
+ *
+ * This one checks whether mmaps of unused cached bos are also properly reaped.
+ */
+
+/* we do both cpu and gtt maps, so only need half of 64k to exhaust */
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int i;
+ char *ptr;
+ drm_intel_bo *load_bo;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ load_bo = drm_intel_bo_alloc(bufmgr, "target bo", 1024*4096, 4096);
+ assert(load_bo);
+
+ drm_intel_bufmgr_gem_set_vma_cache_size(bufmgr, 500);
+
+ /* IMPORTANT: we need to enable buffer reuse, otherwise we won't test
+ * the libdrm bo cache! */
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ /* put some load onto the gpu to keep the light buffers active for long
+ * enough */
+ for (i = 0; i < 10000; i++) {
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ 4096);
+ OUT_BATCH(0); /* dst x1,y1 */
+ OUT_BATCH((1024 << 16) | 512);
+ OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH((0 << 16) | 512); /* src x1, y1 */
+ OUT_BATCH(4096);
+ OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+ }
+
+#define GROUP_SZ 100
+ for (i = 0; i < 68000; ) {
+ int j;
+ drm_intel_bo *bo[GROUP_SZ];
+
+ for (j = 0; j < GROUP_SZ; j++, i++) {
+ bo[j] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096);
+ assert(bo[j]);
+
+ drm_intel_gem_bo_map_gtt(bo[j]);
+ ptr = bo[j]->virtual;
+ assert(ptr);
+ *ptr = 'c';
+ drm_intel_gem_bo_unmap_gtt(bo[j]);
+
+ /* put it onto the active list ... */
+ BEGIN_BATCH(6);
+ OUT_BATCH(XY_COLOR_BLT_CMD |
+ XY_COLOR_BLT_WRITE_ALPHA |
+ XY_COLOR_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ 128);
+ OUT_BATCH(0); /* dst x1,y1 */
+ OUT_BATCH((1 << 16) | 1);
+ OUT_RELOC(bo[j], I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0xffffffff); /* color */
+ ADVANCE_BATCH();
+ }
+ intel_batchbuffer_flush(batch);
+
+ for (j = 0; j < GROUP_SZ; j++)
+ drm_intel_bo_unreference(bo[j]);
+ }
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/drm_vma_limiter_cpu.c b/tests/drm_vma_limiter_cpu.c
new file mode 100644
index 00000000..24ce188e
--- /dev/null
+++ b/tests/drm_vma_limiter_cpu.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+/* Testcase: check whether the libdrm vma limiter works
+ *
+ * We've had reports of the X server exhausting the default rlimit of 64k vma's
+ * in the kernel. libdrm has grown facilities to limit the vma caching since,
+ * this checks whether they actually work.
+ *
+ * This one checks cpu mmaps only.
+ */
+
+#define BO_ARRAY_SIZE 68000
+drm_intel_bo *bos[BO_ARRAY_SIZE];
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int i;
+ char *ptr;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ drm_intel_bufmgr_gem_set_vma_cache_size(bufmgr, 500);
+
+ for (i = 0; i < BO_ARRAY_SIZE; i++) {
+ bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096);
+ assert(bos[i]);
+
+ drm_intel_bo_map(bos[i], 1);
+ ptr = bos[i]->virtual;
+ assert(ptr);
+ *ptr = 'c';
+ drm_intel_bo_unmap(bos[i]);
+ }
+
+ /* and recheck whether a second map of the same still works */
+ for (i = 0; i < BO_ARRAY_SIZE; i++) {
+ bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096);
+ assert(bos[i]);
+
+ drm_intel_bo_map(bos[i], 1);
+ ptr = bos[i]->virtual;
+ assert(*ptr = 'c');
+ drm_intel_bo_unmap(bos[i]);
+ }
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/drm_vma_limiter_gtt.c b/tests/drm_vma_limiter_gtt.c
new file mode 100644
index 00000000..540ea917
--- /dev/null
+++ b/tests/drm_vma_limiter_gtt.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+/* Testcase: check whether the libdrm vma limiter works
+ *
+ * We've had reports of the X server exhausting the default rlimit of 64k vma's
+ * in the kernel. libdrm has grown facilities to limit the vma caching since,
+ * this checks whether they actually work.
+ *
+ * This one checks cpu mmaps only.
+ */
+
+/* we do both cpu and gtt maps, so only need half of 64k to exhaust */
+#define BO_ARRAY_SIZE 68000
+drm_intel_bo *bos[BO_ARRAY_SIZE];
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int i;
+ char *ptr;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ drm_intel_bufmgr_gem_set_vma_cache_size(bufmgr, 500);
+
+ for (i = 0; i < BO_ARRAY_SIZE; i++) {
+ bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096);
+ assert(bos[i]);
+
+ drm_intel_gem_bo_map_gtt(bos[i]);
+ ptr = bos[i]->virtual;
+ assert(ptr);
+ *ptr = 'c';
+ drm_intel_gem_bo_unmap_gtt(bos[i]);
+ }
+
+ /* and recheck whether a second map of the same still works */
+ for (i = 0; i < BO_ARRAY_SIZE; i++) {
+ bos[i] = drm_intel_bo_alloc(bufmgr, "mmap bo", 4096, 4096);
+ assert(bos[i]);
+
+ drm_intel_gem_bo_map_gtt(bos[i]);
+ ptr = bos[i]->virtual;
+ assert(*ptr = 'c');
+ drm_intel_gem_bo_unmap_gtt(bos[i]);
+ }
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/flip_test.c b/tests/flip_test.c
new file mode 100644
index 00000000..67105905
--- /dev/null
+++ b/tests/flip_test.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2012 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <cairo.h>
+#include <errno.h>
+#include <math.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "testdisplay.h"
+
+drmModeRes *resources;
+int drm_fd;
+int test_time = 3;
+
+uint32_t *fb_ptr;
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct type_name {
+ int type;
+ const char *name;
+};
+
+struct test_output {
+ uint32_t id;
+ int mode_valid;
+ drmModeModeInfo mode;
+ drmModeEncoder *encoder;
+ drmModeConnector *connector;
+ int crtc;
+ int pipe;
+ unsigned int current_fb_id;
+ unsigned int fb_ids[2];
+};
+
+static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void *data)
+{
+ struct test_output *o = data;
+ unsigned int new_fb_id;
+
+ if (o->current_fb_id == o->fb_ids[0])
+ new_fb_id = o->fb_ids[1];
+ else
+ new_fb_id = o->fb_ids[0];
+
+ drmModePageFlip(drm_fd, o->crtc, new_fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, o);
+ o->current_fb_id = new_fb_id;
+}
+
+static void connector_find_preferred_mode(struct test_output *o, int crtc_id)
+{
+ drmModeConnector *connector;
+ drmModeEncoder *encoder = NULL;
+ int i, j;
+
+ /* First, find the connector & mode */
+ o->mode_valid = 0;
+ o->crtc = 0;
+ connector = drmModeGetConnector(drm_fd, o->id);
+ assert(connector);
+
+ if (connector->connection != DRM_MODE_CONNECTED) {
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ if (!connector->count_modes) {
+ fprintf(stderr, "connector %d has no modes\n", o->id);
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ if (connector->connector_id != o->id) {
+ fprintf(stderr, "connector id doesn't match (%d != %d)\n",
+ connector->connector_id, o->id);
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ for (j = 0; j < connector->count_modes; j++) {
+ o->mode = connector->modes[j];
+ if (o->mode.type & DRM_MODE_TYPE_PREFERRED) {
+ o->mode_valid = 1;
+ break;
+ }
+ }
+
+ if (!o->mode_valid) {
+ if (connector->count_modes > 0) {
+ /* use the first mode as test mode */
+ o->mode = connector->modes[0];
+ o->mode_valid = 1;
+ }
+ else {
+ fprintf(stderr, "failed to find any modes on connector %d\n",
+ o->id);
+ return;
+ }
+ }
+
+ /* Now get the encoder */
+ for (i = 0; i < connector->count_encoders; i++) {
+ encoder = drmModeGetEncoder(drm_fd, connector->encoders[i]);
+
+ if (!encoder) {
+ fprintf(stderr, "could not get encoder %i: %s\n",
+ resources->encoders[i], strerror(errno));
+ drmModeFreeEncoder(encoder);
+ continue;
+ }
+
+ break;
+ }
+
+ o->encoder = encoder;
+
+ if (i == resources->count_encoders) {
+ fprintf(stderr, "failed to find encoder\n");
+ o->mode_valid = 0;
+ return;
+ }
+
+ /* Find first CRTC not in use */
+ for (i = 0; i < resources->count_crtcs; i++) {
+ if (resources->crtcs[i] != crtc_id)
+ continue;
+ if (resources->crtcs[i] &&
+ (o->encoder->possible_crtcs & (1<<i))) {
+ o->crtc = resources->crtcs[i];
+ break;
+ }
+ }
+
+ if (!o->crtc) {
+ fprintf(stderr, "could not find requested crtc %d\n", crtc_id);
+ o->mode_valid = 0;
+ return;
+ }
+
+ o->pipe = i;
+
+ o->connector = connector;
+}
+
+static void
+paint_flip_mode(cairo_t *cr, int width, int height, void *priv)
+{
+ bool odd_frame = (bool) priv;
+
+ if (odd_frame)
+ cairo_rectangle(cr, width/4, height/2, width/4, height/8);
+ else
+ cairo_rectangle(cr, width/2, height/2, width/4, height/8);
+
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+}
+
+static void set_mode(struct test_output *o, int crtc)
+{
+ int ret;
+ int bpp = 32, depth = 24;
+ drmEventContext evctx;
+ int width, height;
+ struct timeval end;
+ struct kmstest_fb fb_info[2];
+
+ connector_find_preferred_mode(o, crtc);
+ if (!o->mode_valid)
+ return;
+
+ width = o->mode.hdisplay;
+ height = o->mode.vdisplay;
+
+ o->fb_ids[0] = kmstest_create_fb(drm_fd, width, height, bpp, depth,
+ false, &fb_info[0],
+ paint_flip_mode, (void *)false);
+ o->fb_ids[1] = kmstest_create_fb(drm_fd, width, height, bpp, depth,
+ false, &fb_info[1],
+ paint_flip_mode, (void *)true);
+ if (!o->fb_ids[0] || !o->fb_ids[1]) {
+ fprintf(stderr, "failed to create fbs\n");
+ exit(3);
+ }
+
+ gem_close(drm_fd, fb_info[0].gem_handle);
+ gem_close(drm_fd, fb_info[1].gem_handle);
+
+ kmstest_dump_mode(&o->mode);
+ if (drmModeSetCrtc(drm_fd, o->crtc, o->fb_ids[0], 0, 0,
+ &o->id, 1, &o->mode)) {
+ fprintf(stderr, "failed to set mode (%dx%d@%dHz): %s\n",
+ width, height, o->mode.vrefresh,
+ strerror(errno));
+ exit(3);
+ }
+
+ ret = drmModePageFlip(drm_fd, o->crtc, o->fb_ids[1],
+ DRM_MODE_PAGE_FLIP_EVENT, o);
+ if (ret) {
+ fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
+ exit(4);
+ }
+ o->current_fb_id = o->fb_ids[1];
+
+ memset(&evctx, 0, sizeof evctx);
+ evctx.version = DRM_EVENT_CONTEXT_VERSION;
+ evctx.vblank_handler = NULL;
+ evctx.page_flip_handler = page_flip_handler;
+
+ gettimeofday(&end, NULL);
+ end.tv_sec += 3;
+
+ while (1) {
+ struct timeval now, timeout = { .tv_sec = 3, .tv_usec = 0 };
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ FD_SET(drm_fd, &fds);
+ ret = select(drm_fd + 1, &fds, NULL, NULL, &timeout);
+
+ if (ret <= 0) {
+ fprintf(stderr, "select timed out or error (ret %d)\n",
+ ret);
+ exit(1);
+ } else if (FD_ISSET(0, &fds)) {
+ fprintf(stderr, "no fds active, breaking\n");
+ exit(2);
+ }
+
+ gettimeofday(&now, NULL);
+ if (now.tv_sec > end.tv_sec ||
+ (now.tv_sec == end.tv_sec && now.tv_usec >= end.tv_usec)) {
+ ret = 0;
+ break;
+ }
+
+ drmHandleEvent(drm_fd, &evctx);
+ }
+
+ fprintf(stdout, "page flipping on crtc %d, connector %d: PASSED\n",
+ crtc, o->id);
+
+ drmModeFreeEncoder(o->encoder);
+ drmModeFreeConnector(o->connector);
+}
+
+static int run_test(void)
+{
+ struct test_output *connectors;
+ int c, i;
+
+ resources = drmModeGetResources(drm_fd);
+ if (!resources) {
+ fprintf(stderr, "drmModeGetResources failed: %s\n",
+ strerror(errno));
+ exit(5);
+ }
+
+ connectors = calloc(resources->count_connectors,
+ sizeof(struct test_output));
+ assert(connectors);
+
+ /* Find any connected displays */
+ for (c = 0; c < resources->count_connectors; c++) {
+ connectors[c].id = resources->connectors[c];
+ for (i = 0; i < resources->count_crtcs; i++)
+ set_mode(&connectors[c], resources->crtcs[i]);
+ }
+
+ drmModeFreeResources(resources);
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ drm_fd = drm_open_any();
+
+ run_test();
+
+ close(drm_fd);
+
+ return 0;
+}
diff --git a/tests/gem_bad_address.c b/tests/gem_bad_address.c
new file mode 100644
index 00000000..fbb96497
--- /dev/null
+++ b/tests/gem_bad_address.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Jesse Barnes <jbarnes@virtuousgeek.org> (based on gem_bad_blit.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+#define BAD_GTT_DEST ((512*1024*1024)) /* past end of aperture */
+
+static void
+bad_store(void)
+{
+ BEGIN_BATCH(4);
+ OUT_BATCH(MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL | 1 << 21);
+ OUT_BATCH(0);
+ OUT_BATCH(BAD_GTT_DEST);
+ OUT_BATCH(0xdeadbeef);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ bad_store();
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_bad_batch.c b/tests/gem_bad_batch.c
new file mode 100644
index 00000000..db6636ae
--- /dev/null
+++ b/tests/gem_bad_batch.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Jesse Barnes <jbarnes@virtuousgeek.org> (based on gem_bad_blit.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+static void
+bad_batch(void)
+{
+ BEGIN_BATCH(2);
+ OUT_BATCH(MI_BATCH_BUFFER_START);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ bad_batch();
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_bad_blit.c b/tests/gem_bad_blit.c
new file mode 100644
index 00000000..22165270
--- /dev/null
+++ b/tests/gem_bad_blit.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file gem_tiled_blits.c
+ *
+ * This is a test of doing many tiled blits, with a working set
+ * larger than the aperture size.
+ *
+ * The goal is to catch a couple types of failure;
+ * - Fence management problems on pre-965.
+ * - A17 or L-shaped memory tiling workaround problems in acceleration.
+ *
+ * The model is to fill a collection of 1MB objects in a way that can't trip
+ * over A6 swizzling -- upload data to a non-tiled object, blit to the tiled
+ * object. Then, copy the 1MB objects randomly between each other for a while.
+ * Finally, download their data through linear objects again and see what
+ * resulted.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+#define BAD_GTT_DEST ((256*1024*1024)) /* past end of aperture */
+
+static void
+bad_blit(drm_intel_bo *src_bo, uint32_t devid)
+{
+ uint32_t src_pitch = 512, dst_pitch = 512;
+ uint32_t cmd_bits = 0;
+
+ if (IS_965(devid)) {
+ src_pitch /= 4;
+ cmd_bits |= XY_SRC_COPY_BLT_SRC_TILED;
+ }
+
+ if (IS_965(devid)) {
+ dst_pitch /= 4;
+ cmd_bits |= XY_SRC_COPY_BLT_DST_TILED;
+ }
+
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB |
+ cmd_bits);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ dst_pitch);
+ OUT_BATCH(0); /* dst x1,y1 */
+ OUT_BATCH((64 << 16) | 64); /* 64x64 blit */
+ OUT_BATCH(BAD_GTT_DEST);
+ OUT_BATCH(0); /* src x1,y1 */
+ OUT_BATCH(src_pitch);
+ OUT_RELOC(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+}
+
+int main(int argc, char **argv)
+{
+ drm_intel_bo *src;
+ int fd;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ src = drm_intel_bo_alloc(bufmgr, "src", 128 * 128, 4096);
+
+ bad_blit(src, batch->devid);
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_bad_length.c b/tests/gem_bad_length.c
new file mode 100644
index 00000000..41f44d7f
--- /dev/null
+++ b/tests/gem_bad_length.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define MI_BATCH_BUFFER_END (0xA<<23)
+
+/*
+ * Testcase: Minmal bo_create and batchbuffer exec
+ *
+ * Originally this caught an kernel oops due to the unchecked assumption that
+ * objects have size > 0.
+ */
+
+static uint32_t do_gem_create(int fd, int size, int *retval)
+{
+ struct drm_i915_gem_create create;
+ int ret;
+
+ create.handle = 0;
+ create.size = (size + 4095) & -4096;
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create);
+ assert(retval || ret == 0);
+ if (retval)
+ *retval = errno;
+
+ return create.handle;
+}
+
+static int gem_exec(int fd, struct drm_i915_gem_execbuffer2 *execbuf)
+{
+ return drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
+}
+
+static void create0(int fd)
+{
+ int retval = 0;
+ printf("trying to create a zero-length gem object\n");
+ do_gem_create(fd, 0, &retval);
+ assert(retval == EINVAL);
+}
+
+static void exec0(int fd)
+{
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 exec[1];
+ uint32_t buf[2] = { MI_BATCH_BUFFER_END, 0 };
+
+ /* Just try executing with a zero-length bo.
+ * We expect the kernel to either accept the nop batch, or reject it
+ * for the zero-length buffer, but never crash.
+ */
+
+ exec[0].handle = gem_create(fd, 4096);
+ gem_write(fd, exec[0].handle, 0, buf, sizeof(buf));
+ exec[0].relocation_count = 0;
+ exec[0].relocs_ptr = 0;
+ exec[0].alignment = 0;
+ exec[0].offset = 0;
+ exec[0].flags = 0;
+ exec[0].rsvd1 = 0;
+ exec[0].rsvd2 = 0;
+
+ execbuf.buffers_ptr = (uintptr_t)exec;
+ execbuf.buffer_count = 1;
+ execbuf.batch_start_offset = 0;
+ execbuf.batch_len = sizeof(buf);
+ execbuf.cliprects_ptr = 0;
+ execbuf.num_cliprects = 0;
+ execbuf.DR1 = 0;
+ execbuf.DR4 = 0;
+ execbuf.flags = 0;
+ i915_execbuffer2_set_context_id(execbuf, 0);
+ execbuf.rsvd2 = 0;
+
+ printf("trying to run an empty batchbuffer\n");
+ gem_exec(fd, &execbuf);
+
+ gem_close(fd, exec[0].handle);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+
+ fd = drm_open_any();
+
+ create0(fd);
+
+ //exec0(fd);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_basic.c b/tests/gem_basic.c
new file mode 100644
index 00000000..24ad445f
--- /dev/null
+++ b/tests/gem_basic.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+static void
+test_bad_close(int fd)
+{
+ struct drm_gem_close close_bo;
+ int ret;
+
+ printf("Testing error return on bad close ioctl.\n");
+
+ close_bo.handle = 0x10101010;
+ ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
+
+ assert(ret == -1 && errno == EINVAL);
+}
+
+static void
+test_create_close(int fd)
+{
+ uint32_t handle;
+
+ printf("Testing creating and closing an object.\n");
+
+ handle = gem_create(fd, 16*1024);
+
+ gem_close(fd, handle);
+}
+
+static void
+test_create_fd_close(int fd)
+{
+ printf("Testing closing with an object allocated.\n");
+
+ gem_create(fd, 16*1024);
+ /* leak it */
+
+ close(fd);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+
+ fd = drm_open_any();
+
+ test_bad_close(fd);
+ test_create_close(fd);
+ test_create_fd_close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_cpu_concurrent_blit.c b/tests/gem_cpu_concurrent_blit.c
new file mode 100644
index 00000000..fd517d00
--- /dev/null
+++ b/tests/gem_cpu_concurrent_blit.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright © 2009,2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file gem_cpu_concurrent_blit.c
+ *
+ * This is a test of CPU read/write behavior when writing to active
+ * buffers.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static void
+set_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
+{
+ int size = width * height;
+ uint32_t *vaddr;
+
+ drm_intel_bo_map(bo, true);
+ vaddr = bo->virtual;
+ while (size--)
+ *vaddr++ = val;
+ drm_intel_bo_unmap(bo);
+}
+
+static void
+cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
+{
+ int size = width * height;
+ uint32_t *vaddr;
+
+ drm_intel_bo_map(bo, false);
+ vaddr = bo->virtual;
+ while (size--)
+ assert(*vaddr++ == val);
+ drm_intel_bo_unmap(bo);
+}
+
+static drm_intel_bo *
+create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height)
+{
+ drm_intel_bo *bo;
+
+ bo = drm_intel_bo_alloc(bufmgr, "bo", 4*width*height, 0);
+ assert(bo);
+
+ set_bo(bo, val, width, height);
+
+ return bo;
+}
+
+int
+main(int argc, char **argv)
+{
+ drm_intel_bufmgr *bufmgr;
+ struct intel_batchbuffer *batch;
+ int num_buffers = 128, max;
+ drm_intel_bo *src[128], *dst[128], *dummy;
+ int width = 512, height = 512;
+ int fd;
+ int i;
+
+ fd = drm_open_any();
+
+ max = gem_aperture_size (fd) / (1024 * 1024) / 2;
+ if (num_buffers > max)
+ num_buffers = max;
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ for (i = 0; i < num_buffers; i++) {
+ src[i] = create_bo(bufmgr, i, width, height);
+ dst[i] = create_bo(bufmgr, ~i, width, height);
+ }
+ dummy = create_bo(bufmgr, 0, width, height);
+
+ /* try to overwrite the source values */
+ for (i = 0; i < num_buffers; i++)
+ intel_copy_bo(batch, dst[i], src[i], width, height);
+ for (i = num_buffers; i--; )
+ set_bo(src[i], 0xdeadbeef, width, height);
+ for (i = 0; i < num_buffers; i++)
+ cmp_bo(dst[i], i, width, height);
+
+ /* try to read the results before the copy completes */
+ for (i = 0; i < num_buffers; i++)
+ intel_copy_bo(batch, dst[i], src[i], width, height);
+ for (i = num_buffers; i--; )
+ cmp_bo(dst[i], 0xdeadbeef, width, height);
+
+ /* and finally try to trick the kernel into loosing the pending write */
+ for (i = num_buffers; i--; )
+ set_bo(src[i], 0xabcdabcd, width, height);
+ for (i = 0; i < num_buffers; i++)
+ intel_copy_bo(batch, dst[i], src[i], width, height);
+ for (i = num_buffers; i--; )
+ intel_copy_bo(batch, dummy, dst[i], width, height);
+ for (i = num_buffers; i--; )
+ cmp_bo(dst[i], 0xabcdabcd, width, height);
+
+ return 0;
+}
diff --git a/tests/gem_cs_prefetch.c b/tests/gem_cs_prefetch.c
new file mode 100644
index 00000000..4fb2fc4e
--- /dev/null
+++ b/tests/gem_cs_prefetch.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+/*
+ * Testcase: Test the CS prefetch behaviour on batches
+ *
+ * Historically the batch prefetcher doesn't check whether it's crossing page
+ * boundaries and likes to throw up when it gets a pagefault in return for his
+ * over-eager behaviour. Check for this.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+static void exec(int fd, uint32_t handle)
+{
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 gem_exec[1];
+ int ret = 0;
+
+ gem_exec[0].handle = handle;
+ gem_exec[0].relocation_count = 0;
+ gem_exec[0].relocs_ptr = 0;
+ gem_exec[0].alignment = 0;
+ gem_exec[0].offset = 0;
+ gem_exec[0].flags = 0;
+ gem_exec[0].rsvd1 = 0;
+ gem_exec[0].rsvd2 = 0;
+
+ execbuf.buffers_ptr = (uintptr_t)gem_exec;
+ execbuf.buffer_count = 1;
+ execbuf.batch_start_offset = 0;
+ execbuf.batch_len = 4096;
+ execbuf.cliprects_ptr = 0;
+ execbuf.num_cliprects = 0;
+ execbuf.DR1 = 0;
+ execbuf.DR4 = 0;
+ execbuf.flags = 0;
+ execbuf.rsvd1 = 0;
+ execbuf.rsvd2 = 0;
+
+ ret = drmIoctl(fd,
+ DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ &execbuf);
+ gem_sync(fd, handle);
+ assert(ret == 0);
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t batch_end[4] = {MI_BATCH_BUFFER_END, 0, 0, 0};
+ int fd, i, ret;
+ uint64_t aper_size;
+ int count;
+ drm_intel_bo *sample_batch_bo;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ aper_size = gem_aperture_size(fd);
+
+ /* presume a big per-bo overhead */
+ if (intel_get_total_ram_mb() < (aper_size / (1024*1024)) * 3 / 2) {
+ fprintf(stderr, "not enough mem to run test\n");
+ return 77;
+ }
+
+ count = aper_size / 4096;
+
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+ assert(batch);
+
+ sample_batch_bo = drm_intel_bo_alloc(bufmgr, "", 4096, 4096);
+ assert(sample_batch_bo);
+ ret = drm_intel_bo_subdata(sample_batch_bo, 4096-sizeof(batch_end),
+ sizeof(batch_end), batch_end);
+ assert(ret == 0);
+
+ /* fill the entire gart with batches and run them */
+ for (i = 0; i < count; i++) {
+ drm_intel_bo *batch_bo;
+
+ batch_bo = drm_intel_bo_alloc(bufmgr, "", 4096, 4096);
+ assert(batch_bo);
+
+ /* copy the sample batch with the gpu to the new one, so that we
+ * also test the unmappable part of the gtt. */
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ 4096);
+ OUT_BATCH(0); /* dst y1,x1 */
+ OUT_BATCH((1 << 16) | 1024);
+ OUT_RELOC(batch_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH((0 << 16) | 0); /* src x1, y1 */
+ OUT_BATCH(4096);
+ OUT_RELOC(sample_batch_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+ if (i % 100 == 0)
+ gem_sync(fd, batch_bo->handle);
+
+ drm_intel_bo_disable_reuse(batch_bo);
+
+ /* launch the newly created batch */
+ exec(fd, batch_bo->handle);
+
+ // leak buffers
+ //drm_intel_bo_unreference(batch_bo);
+ drmtest_progress("gem_cs_prefetch: ", i, count);
+ }
+
+ fprintf(stderr, "Test suceeded, cleanup up - this might take a while.\n");
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_ctx_bad_destroy.c b/tests/gem_ctx_bad_destroy.c
new file mode 100644
index 00000000..02d24eb3
--- /dev/null
+++ b/tests/gem_ctx_bad_destroy.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+/*
+ * Negative test cases for destroy contexts
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "i915_drm.h"
+#include "drmtest.h"
+
+struct local_drm_i915_context_create {
+ __u32 ctx_id;
+ __u32 pad;
+};
+
+struct local_drm_i915_context_destroy {
+ __u32 ctx_id;
+ __u32 pad;
+};
+
+#define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_context_create)
+#define CONTEXT_DESTROY_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2e, struct local_drm_i915_context_destroy)
+
+static uint32_t context_create(int fd)
+{
+ struct local_drm_i915_context_create create;
+ int ret;
+
+ ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create);
+ if (ret == -1 && (errno == ENODEV || errno == EINVAL))
+ exit(77);
+ else if (ret)
+ abort();
+
+ return create.ctx_id;
+}
+
+static void handle_bad(int ret, int lerrno, int expected, const char *desc)
+{
+ if (ret != 0 && lerrno != expected) {
+ fprintf(stderr, "%s - errno was %d, but should have been %d\n",
+ desc, lerrno, expected);
+ exit(EXIT_FAILURE);
+ } else if (ret == 0) {
+ fprintf(stderr, "%s - Command succeeded, but should have failed\n",
+ desc);
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ struct local_drm_i915_context_destroy destroy;
+ uint32_t ctx_id;
+ int ret, fd;
+
+ fd = drm_open_any();
+
+ ctx_id = context_create(fd);
+
+ destroy.ctx_id = ctx_id;
+ /* Make sure a proper destroy works first */
+ ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy);
+ assert(ret == 0);
+
+ /* try double destroy */
+ ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy);
+ handle_bad(ret, errno, ENOENT, "double destroy");
+
+ /* destroy something random */
+ destroy.ctx_id = 2;
+ ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy);
+ handle_bad(ret, errno, ENOENT, "random destroy");
+
+ /* Try to destroy the default context */
+ destroy.ctx_id = 0;
+ ret = drmIoctl(fd, CONTEXT_DESTROY_IOCTL, &destroy);
+ handle_bad(ret, errno, ENOENT, "default destroy");
+
+ close(fd);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tests/gem_ctx_bad_exec.c b/tests/gem_ctx_bad_exec.c
new file mode 100644
index 00000000..8a57fd41
--- /dev/null
+++ b/tests/gem_ctx_bad_exec.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+/*
+ * Negative test cases:
+ * test we can't submit contexts to unsupported rings
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+struct local_drm_i915_gem_context_create {
+ __u32 ctx_id;
+ __u32 pad;
+};
+
+#define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_gem_context_create)
+
+static uint32_t context_create(int fd)
+{
+ struct local_drm_i915_gem_context_create create;
+ int ret;
+
+ ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create);
+ if (ret == -1 && (errno == ENODEV || errno == EINVAL)) {
+ exit(77);
+ } else if (ret) {
+ abort();
+ }
+
+ return create.ctx_id;
+}
+
+/* Copied from gem_exec_nop.c */
+static int exec(int fd, uint32_t handle, int ring, int ctx_id)
+{
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 gem_exec;
+ int ret = 0;
+
+ gem_exec.handle = handle;
+ gem_exec.relocation_count = 0;
+ gem_exec.relocs_ptr = 0;
+ gem_exec.alignment = 0;
+ gem_exec.offset = 0;
+ gem_exec.flags = 0;
+ gem_exec.rsvd1 = 0;
+ gem_exec.rsvd2 = 0;
+
+ execbuf.buffers_ptr = (uintptr_t)&gem_exec;
+ execbuf.buffer_count = 1;
+ execbuf.batch_start_offset = 0;
+ execbuf.batch_len = 8;
+ execbuf.cliprects_ptr = 0;
+ execbuf.num_cliprects = 0;
+ execbuf.DR1 = 0;
+ execbuf.DR4 = 0;
+ execbuf.flags = ring;
+ i915_execbuffer2_set_context_id(execbuf, ctx_id);
+ execbuf.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ &execbuf);
+ gem_sync(fd, handle);
+
+ return ret;
+}
+
+#define MI_BATCH_BUFFER_END (0xA<<23)
+int main(int argc, char *argv[])
+{
+ uint32_t handle;
+ uint32_t batch[2] = {MI_BATCH_BUFFER_END};
+ uint32_t ctx_id;
+ int fd;
+ fd = drm_open_any();
+
+ ctx_id = context_create(fd);
+
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, sizeof(batch));
+ assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0);
+ assert(exec(fd, handle, I915_EXEC_BSD, ctx_id) != 0);
+ assert(exec(fd, handle, I915_EXEC_BLT, ctx_id) != 0);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tests/gem_ctx_basic.c b/tests/gem_ctx_basic.c
new file mode 100644
index 00000000..632651ae
--- /dev/null
+++ b/tests/gem_ctx_basic.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+/*
+ * This test is useful for finding memory and refcount leaks.
+ */
+
+#include <pthread.h>
+#include "rendercopy.h"
+
+/* options */
+int num_contexts = 10;
+int uncontexted = 0; /* test only context create/destroy */
+int multiple_fds = 1;
+int iter = 10000;
+
+/* globals */
+pthread_t *threads;
+int *returns;
+int devid;
+int fd;
+
+static void init_buffer(drm_intel_bufmgr *bufmgr,
+ struct scratch_buf *buf,
+ uint32_t size)
+{
+ buf->bo = drm_intel_bo_alloc(bufmgr, "", size, 4096);
+ buf->size = size;
+ assert(buf->bo);
+ buf->tiling = I915_TILING_NONE;
+ buf->stride = 4096;
+}
+
+static void *work(void *arg)
+{
+ struct intel_batchbuffer *batch;
+ drm_intel_context *context;
+ drm_intel_bufmgr *bufmgr;
+ int thread_id = *(int *)arg;
+ int td_fd;
+ int i;
+
+ if (multiple_fds)
+ td_fd = fd = drm_open_any();
+ else
+ td_fd = fd;
+
+ assert(td_fd >= 0);
+
+ bufmgr = drm_intel_bufmgr_gem_init(td_fd, 4096);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+ context = drm_intel_gem_context_create(bufmgr);
+
+ if (!context) {
+ returns[thread_id] = 77;
+ goto out;
+ }
+
+ for (i = 0; i < iter; i++) {
+ struct scratch_buf src, dst;
+
+ init_buffer(bufmgr, &src, 4096);
+ init_buffer(bufmgr, &dst, 4096);
+
+
+ if (uncontexted) {
+ gen6_render_copyfunc(batch, &src, 0, 0, 0, 0, &dst, 0, 0);
+ } else {
+ int ret;
+ ret = drm_intel_bo_subdata(batch->bo, 0, 4096, batch->buffer);
+ assert(ret == 0);
+ intel_batchbuffer_flush_with_context(batch, context);
+ }
+ }
+
+out:
+ drm_intel_gem_context_destroy(context);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ if (multiple_fds)
+ close(td_fd);
+
+ pthread_exit(&returns[thread_id]);
+}
+
+static void parse(int argc, char *argv[])
+{
+ int opt;
+ while ((opt = getopt(argc, argv, "i:c:n:muh?")) != -1) {
+ switch (opt) {
+ case 'i':
+ iter = atoi(optarg);
+ break;
+ case 'c':
+ num_contexts = atoi(optarg);
+ break;
+ case 'm':
+ multiple_fds = 1;
+ break;
+ case 'u':
+ uncontexted = 1;
+ break;
+ case 'h':
+ case '?':
+ default:
+ exit(EXIT_SUCCESS);
+ break;
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+
+ fd = drm_open_any();
+ devid = intel_get_drm_devid(fd);
+
+ parse(argc, argv);
+
+ threads = calloc(num_contexts, sizeof(*threads));
+ returns = calloc(num_contexts, sizeof(*returns));
+
+ for (i = 0; i < num_contexts; i++)
+ pthread_create(&threads[i], NULL, work, &i);
+
+ for (i = 0; i < num_contexts; i++) {
+ int thread_status, ret;
+ void *retval;
+ ret = pthread_join(threads[i], &retval);
+ thread_status = *(int *)retval;
+ if (!ret && thread_status)
+ exit(thread_status);
+ }
+
+ free(returns);
+ free(threads);
+ close(fd);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tests/gem_ctx_create.c b/tests/gem_ctx_create.c
new file mode 100644
index 00000000..def76d34
--- /dev/null
+++ b/tests/gem_ctx_create.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "i915_drm.h"
+#include "drmtest.h"
+
+struct local_drm_i915_gem_context_create {
+ __u32 ctx_id;
+ __u32 pad;
+};
+
+#define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_gem_context_create)
+
+int main(int argc, char *argv[])
+{
+ int ret, fd;
+ struct local_drm_i915_gem_context_create create;
+
+ create.ctx_id = rand();
+ create.pad = rand();
+
+ fd = drm_open_any();
+
+ ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create);
+ if (ret != 0 && (errno == ENODEV || errno == EINVAL)) {
+ fprintf(stderr, "Kernel is too old, or contexts not supported: %s\n",
+ strerror(errno));
+ exit(77);
+ } else if (ret != 0) {
+ fprintf(stderr, "%s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ assert(create.ctx_id != 0);
+
+ close(fd);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tests/gem_ctx_exec.c b/tests/gem_ctx_exec.c
new file mode 100644
index 00000000..423f1eec
--- /dev/null
+++ b/tests/gem_ctx_exec.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+/*
+ * This test covers basic context switch functionality
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+struct local_drm_i915_gem_context_create {
+ __u32 ctx_id;
+ __u32 pad;
+};
+
+struct local_drm_i915_gem_context_destroy {
+ __u32 ctx_id;
+ __u32 pad;
+};
+
+#define CONTEXT_CREATE_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2d, struct local_drm_i915_gem_context_create)
+#define CONTEXT_DESTROY_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x23, struct local_drm_i915_gem_context_destroy)
+
+static uint32_t context_create(int fd)
+{
+ struct local_drm_i915_gem_context_create create;
+ int ret;
+
+ ret = drmIoctl(fd, CONTEXT_CREATE_IOCTL, &create);
+ if (ret == -1 && (errno == ENODEV || errno == EINVAL))
+ exit(77);
+ else if (ret)
+ abort();
+
+ return create.ctx_id;
+}
+
+static void context_destroy(int fd, uint32_t ctx_id)
+{
+ struct local_drm_i915_gem_context_destroy destroy;
+ destroy.ctx_id = ctx_id;
+ do_ioctl(fd, CONTEXT_DESTROY_IOCTL, &destroy);
+}
+
+/* Copied from gem_exec_nop.c */
+static int exec(int fd, uint32_t handle, int ring, int ctx_id)
+{
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 gem_exec;
+ int ret = 0;
+
+ gem_exec.handle = handle;
+ gem_exec.relocation_count = 0;
+ gem_exec.relocs_ptr = 0;
+ gem_exec.alignment = 0;
+ gem_exec.offset = 0;
+ gem_exec.flags = 0;
+ gem_exec.rsvd1 = 0;
+ gem_exec.rsvd2 = 0;
+
+ execbuf.buffers_ptr = (uintptr_t)&gem_exec;
+ execbuf.buffer_count = 1;
+ execbuf.batch_start_offset = 0;
+ execbuf.batch_len = 8;
+ execbuf.cliprects_ptr = 0;
+ execbuf.num_cliprects = 0;
+ execbuf.DR1 = 0;
+ execbuf.DR4 = 0;
+ execbuf.flags = ring;
+ i915_execbuffer2_set_context_id(execbuf, ctx_id);
+ execbuf.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ &execbuf);
+ gem_sync(fd, handle);
+
+ return ret;
+}
+
+#define MI_BATCH_BUFFER_END (0xA<<23)
+int main(int argc, char *argv[])
+{
+ uint32_t handle;
+ uint32_t batch[2] = {0, MI_BATCH_BUFFER_END};
+ uint32_t ctx_id;
+ int fd;
+ fd = drm_open_any();
+
+ ctx_id = context_create(fd);
+ handle = gem_create(fd, 4096);
+
+ gem_write(fd, handle, 0, batch, sizeof(batch));
+ assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0);
+ context_destroy(fd, ctx_id);
+
+ ctx_id = context_create(fd);
+ assert(exec(fd, handle, I915_EXEC_RENDER, ctx_id) == 0);
+ context_destroy(fd, ctx_id);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tests/gem_double_irq_loop.c b/tests/gem_double_irq_loop.c
new file mode 100644
index 00000000..f2f8b1a8
--- /dev/null
+++ b/tests/gem_double_irq_loop.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch> (based on gem_storedw_*.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+#include "i830_reg.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static drm_intel_bo *target_buffer, *blt_bo;
+
+/*
+ * Testcase: Basic check for missed irqs on blt
+ *
+ * Execs one large and then immediately a tiny batch on the blt ring. Then waits
+ * on the second batch. This hopefully catches races in our irq acknowledgement.
+ */
+
+
+#define MI_COND_BATCH_BUFFER_END (0x36<<23 | 1)
+#define MI_DO_COMPARE (1<<21)
+static void
+dummy_reloc_loop(void)
+{
+ int i;
+
+ for (i = 0; i < 0x800; i++) {
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ 4*4096);
+ OUT_BATCH(2048 << 16 | 0);
+ OUT_BATCH((4096) << 16 | (2048));
+ OUT_RELOC_FENCED(blt_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(4*4096);
+ OUT_RELOC_FENCED(blt_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+ intel_batchbuffer_flush(batch);
+
+ BEGIN_BATCH(4);
+ OUT_BATCH(MI_FLUSH_DW | 1);
+ OUT_BATCH(0); /* reserved */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(MI_NOOP | (1<<22) | (0xf));
+ ADVANCE_BATCH();
+ intel_batchbuffer_flush(batch);
+
+ drm_intel_bo_map(target_buffer, 0);
+ // map to force completion
+ drm_intel_bo_unmap(target_buffer);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int devid;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: %s\n", argv[0]);
+ exit(-1);
+ }
+
+ fd = drm_open_any();
+ devid = intel_get_drm_devid(fd);
+ if (!HAS_BLT_RING(devid)) {
+ fprintf(stderr, "not (yet) implemented for pre-snb\n");
+ return 77;
+ }
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+ if (!batch) {
+ fprintf(stderr, "failed to create batch buffer\n");
+ exit(-1);
+ }
+
+ target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
+ if (!target_buffer) {
+ fprintf(stderr, "failed to alloc target buffer\n");
+ exit(-1);
+ }
+
+ blt_bo = drm_intel_bo_alloc(bufmgr, "target bo", 4*4096*4096, 4096);
+ if (!blt_bo) {
+ fprintf(stderr, "failed to alloc blt buffer\n");
+ exit(-1);
+ }
+
+ dummy_reloc_loop();
+
+ drm_intel_bo_unreference(target_buffer);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_dummy_reloc_loop.c b/tests/gem_dummy_reloc_loop.c
new file mode 100644
index 00000000..82d8f77e
--- /dev/null
+++ b/tests/gem_dummy_reloc_loop.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch> (based on gem_storedw_*.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+#include "i830_reg.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static drm_intel_bo *target_buffer;
+
+/*
+ * Testcase: Basic check of ring<->cpu sync using a dummy reloc
+ *
+ * The last test (that randomly switches the ring) seems to be pretty effective
+ * at hitting the missed irq bug that's worked around with the HWSTAM irq write.
+ */
+
+
+#define MI_COND_BATCH_BUFFER_END (0x36<<23 | 1)
+#define MI_DO_COMPARE (1<<21)
+static void
+dummy_reloc_loop(int ring)
+{
+ int i;
+
+ for (i = 0; i < 0x100000; i++) {
+ if (ring == I915_EXEC_RENDER) {
+ BEGIN_BATCH(4);
+ OUT_BATCH(MI_COND_BATCH_BUFFER_END | MI_DO_COMPARE);
+ OUT_BATCH(0xffffffff); /* compare dword */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(MI_NOOP);
+ ADVANCE_BATCH();
+ } else {
+ BEGIN_BATCH(4);
+ OUT_BATCH(MI_FLUSH_DW | 1);
+ OUT_BATCH(0); /* reserved */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(MI_NOOP | (1<<22) | (0xf));
+ ADVANCE_BATCH();
+ }
+ intel_batchbuffer_flush_on_ring(batch, ring);
+
+ drm_intel_bo_map(target_buffer, 0);
+ // map to force completion
+ drm_intel_bo_unmap(target_buffer);
+ }
+}
+
+static void
+dummy_reloc_loop_random_ring(void)
+{
+ int i;
+
+ srandom(0xdeadbeef);
+
+ for (i = 0; i < 0x100000; i++) {
+ int ring = random() % 3 + 1;
+
+ if (ring == I915_EXEC_RENDER) {
+ BEGIN_BATCH(4);
+ OUT_BATCH(MI_COND_BATCH_BUFFER_END | MI_DO_COMPARE);
+ OUT_BATCH(0xffffffff); /* compare dword */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(MI_NOOP);
+ ADVANCE_BATCH();
+ } else {
+ BEGIN_BATCH(4);
+ OUT_BATCH(MI_FLUSH_DW | 1);
+ OUT_BATCH(0); /* reserved */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(MI_NOOP | (1<<22) | (0xf));
+ ADVANCE_BATCH();
+ }
+ intel_batchbuffer_flush_on_ring(batch, ring);
+
+ drm_intel_bo_map(target_buffer, 0);
+ // map to force waiting on rendering
+ drm_intel_bo_unmap(target_buffer);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int devid;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: %s\n", argv[0]);
+ exit(-1);
+ }
+
+ fd = drm_open_any();
+ devid = intel_get_drm_devid(fd);
+ if (!HAS_BLT_RING(devid)) {
+ fprintf(stderr, "not (yet) implemented for pre-snb\n");
+ return 77;
+ }
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+ if (!batch) {
+ fprintf(stderr, "failed to create batch buffer\n");
+ exit(-1);
+ }
+
+ target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
+ if (!target_buffer) {
+ fprintf(stderr, "failed to alloc target buffer\n");
+ exit(-1);
+ }
+
+ fprintf(stderr, "running dummy loop on render\n");
+ dummy_reloc_loop(I915_EXEC_RENDER);
+ fprintf(stderr, "dummy loop run on render completed\n");
+
+ if (!HAS_BSD_RING(devid))
+ goto skip;
+
+ sleep(2);
+ fprintf(stderr, "running dummy loop on bsd\n");
+ dummy_reloc_loop(I915_EXEC_BSD);
+ fprintf(stderr, "dummy loop run on bsd completed\n");
+
+ if (!HAS_BLT_RING(devid))
+ goto skip;
+
+ sleep(2);
+ fprintf(stderr, "running dummy loop on blt\n");
+ dummy_reloc_loop(I915_EXEC_BLT);
+ fprintf(stderr, "dummy loop run on blt completed\n");
+
+ sleep(2);
+ fprintf(stderr, "running dummy loop on random rings\n");
+ dummy_reloc_loop_random_ring();
+ fprintf(stderr, "dummy loop run on random rings completed\n");
+
+skip:
+ drm_intel_bo_unreference(target_buffer);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_exec_bad_domains.c b/tests/gem_exec_bad_domains.c
new file mode 100644
index 00000000..f3ee08b7
--- /dev/null
+++ b/tests/gem_exec_bad_domains.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+/* Testcase: Test whether the kernel rejects relocations with non-gpu domains
+ *
+ * If it does not, it'll oops somewhen later on because we don't expect that.
+ */
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+#define BAD_GTT_DEST ((512*1024*1024)) /* past end of aperture */
+
+static int
+run_batch(void)
+{
+ unsigned int used = batch->ptr - batch->buffer;
+ int ret;
+
+ if (used == 0)
+ return 0;
+
+ /* Round batchbuffer usage to 2 DWORDs. */
+ if ((used & 4) == 0) {
+ *(uint32_t *) (batch->ptr) = 0; /* noop */
+ batch->ptr += 4;
+ }
+
+ /* Mark the end of the buffer. */
+ *(uint32_t *)(batch->ptr) = MI_BATCH_BUFFER_END; /* noop */
+ batch->ptr += 4;
+ used = batch->ptr - batch->buffer;
+
+ ret = drm_intel_bo_subdata(batch->bo, 0, used, batch->buffer);
+ assert(ret == 0);
+
+ batch->ptr = NULL;
+
+ ret = drm_intel_bo_mrb_exec(batch->bo, used, NULL, 0, 0, 0);
+
+ intel_batchbuffer_reset(batch);
+
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int fd, ret;
+ drm_intel_bo *tmp;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ tmp = drm_intel_bo_alloc(bufmgr, "tmp", 128 * 128, 4096);
+
+ BEGIN_BATCH(2);
+ OUT_BATCH(0);
+ OUT_RELOC(tmp, I915_GEM_DOMAIN_CPU, 0, 0);
+ ADVANCE_BATCH();
+ ret = run_batch();
+ if (ret != -EINVAL) {
+ fprintf(stderr, "(cpu, 0) reloc not rejected\n");
+ exit(1);
+ }
+
+ BEGIN_BATCH(2);
+ OUT_BATCH(0);
+ OUT_RELOC(tmp, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU, 0);
+ ADVANCE_BATCH();
+ ret = run_batch();
+ if (ret != -EINVAL) {
+ fprintf(stderr, "(cpu, cpu) reloc not rejected\n");
+ exit(1);
+ }
+
+ BEGIN_BATCH(2);
+ OUT_BATCH(0);
+ OUT_RELOC(tmp, I915_GEM_DOMAIN_GTT, 0, 0);
+ ADVANCE_BATCH();
+ ret = run_batch();
+ if (ret != -EINVAL) {
+ fprintf(stderr, "(gtt, 0) reloc not rejected\n");
+ exit(1);
+ }
+
+ BEGIN_BATCH(2);
+ OUT_BATCH(0);
+ OUT_RELOC(tmp, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT, 0);
+ ADVANCE_BATCH();
+ ret = run_batch();
+ if (ret != -EINVAL) {
+ fprintf(stderr, "(gtt, gtt) reloc not rejected\n");
+ exit(1);
+ }
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_exec_blt.c b/tests/gem_exec_blt.c
new file mode 100644
index 00000000..eb5ae668
--- /dev/null
+++ b/tests/gem_exec_blt.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+
+#define OBJECT_SIZE 16384
+
+#define COPY_BLT_CMD (2<<29|0x53<<22|0x6)
+#define BLT_WRITE_ALPHA (1<<21)
+#define BLT_WRITE_RGB (1<<20)
+#define BLT_SRC_TILED (1<<15)
+#define BLT_DST_TILED (1<<11)
+
+static int gem_linear_blt(uint32_t *batch,
+ uint32_t src,
+ uint32_t dst,
+ uint32_t length,
+ struct drm_i915_gem_relocation_entry *reloc)
+{
+ uint32_t *b = batch;
+ int height = length / (16 * 1024);
+
+ assert(height <= 1<<16);
+
+ if (height) {
+ b[0] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB;
+ b[1] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024);
+ b[2] = 0;
+ b[3] = height << 16 | (4*1024);
+ b[4] = 0;
+ reloc->offset = (b-batch+4) * sizeof(uint32_t);
+ reloc->delta = 0;
+ reloc->target_handle = dst;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = I915_GEM_DOMAIN_RENDER;
+ reloc->presumed_offset = 0;
+ reloc++;
+
+ b[5] = 0;
+ b[6] = 16*1024;
+ b[7] = 0;
+ reloc->offset = (b-batch+7) * sizeof(uint32_t);
+ reloc->delta = 0;
+ reloc->target_handle = src;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = 0;
+ reloc->presumed_offset = 0;
+ reloc++;
+
+ b += 8;
+ length -= height * 16*1024;
+ }
+
+ if (length) {
+ b[0] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB;
+ b[1] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024);
+ b[2] = height << 16;
+ b[3] = (1+height) << 16 | (length / 4);
+ b[4] = 0;
+ reloc->offset = (b-batch+4) * sizeof(uint32_t);
+ reloc->delta = 0;
+ reloc->target_handle = dst;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = I915_GEM_DOMAIN_RENDER;
+ reloc->presumed_offset = 0;
+ reloc++;
+
+ b[5] = height << 16;
+ b[6] = 16*1024;
+ b[7] = 0;
+ reloc->offset = (b-batch+7) * sizeof(uint32_t);
+ reloc->delta = 0;
+ reloc->target_handle = src;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = 0;
+ reloc->presumed_offset = 0;
+ reloc++;
+
+ b += 8;
+ }
+
+ b[0] = MI_BATCH_BUFFER_END;
+ b[1] = 0;
+
+ return (b+2 - batch) * sizeof(uint32_t);
+}
+
+static int gem_exec(int fd, struct drm_i915_gem_execbuffer2 *execbuf, int loops)
+{
+ int ret = 0;
+
+ while (loops-- && ret == 0) {
+ ret = drmIoctl(fd,
+ DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ execbuf);
+ }
+
+ return ret;
+}
+
+static double elapsed(const struct timeval *start,
+ const struct timeval *end,
+ int loop)
+{
+ return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec))/loop;
+}
+
+static const char *bytes_per_sec(char *buf, double v)
+{
+ const char *order[] = {
+ "",
+ "KiB",
+ "MiB",
+ "GiB",
+ "TiB",
+ "PiB",
+ NULL,
+ }, **o = order;
+
+ while (v > 1024 && o[1]) {
+ v /= 1024;
+ o++;
+ }
+ sprintf(buf, "%.1f%s/s", v, *o);
+ return buf;
+}
+
+static void run(int object_size)
+{
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 exec[3];
+ struct drm_i915_gem_relocation_entry reloc[4];
+ uint32_t buf[20];
+ uint32_t handle, src, dst;
+ int fd, len, count;
+ int ring;
+
+ fd = drm_open_any();
+ handle = gem_create(fd, 4096);
+ src = gem_create(fd, object_size);
+ dst = gem_create(fd, object_size);
+
+ len = gem_linear_blt(buf, src, dst, object_size, reloc);
+ gem_write(fd, handle, 0, buf, len);
+
+ exec[0].handle = src;
+ exec[0].relocation_count = 0;
+ exec[0].relocs_ptr = 0;
+ exec[0].alignment = 0;
+ exec[0].offset = 0;
+ exec[0].flags = 0;
+ exec[0].rsvd1 = 0;
+ exec[0].rsvd2 = 0;
+
+ exec[1].handle = dst;
+ exec[1].relocation_count = 0;
+ exec[1].relocs_ptr = 0;
+ exec[1].alignment = 0;
+ exec[1].offset = 0;
+ exec[1].flags = 0;
+ exec[1].rsvd1 = 0;
+ exec[1].rsvd2 = 0;
+
+ exec[2].handle = handle;
+ exec[2].relocation_count = len > 40 ? 4 : 2;
+ exec[2].relocs_ptr = (uintptr_t)reloc;
+ exec[2].alignment = 0;
+ exec[2].offset = 0;
+ exec[2].flags = 0;
+ exec[2].rsvd1 = 0;
+ exec[2].rsvd2 = 0;
+
+ ring = 0;
+ if (HAS_BLT_RING(intel_get_drm_devid(fd)))
+ ring = I915_EXEC_BLT;
+
+ execbuf.buffers_ptr = (uintptr_t)exec;
+ execbuf.buffer_count = 3;
+ execbuf.batch_start_offset = 0;
+ execbuf.batch_len = len;
+ execbuf.cliprects_ptr = 0;
+ execbuf.num_cliprects = 0;
+ execbuf.DR1 = 0;
+ execbuf.DR4 = 0;
+ execbuf.flags = ring;
+ i915_execbuffer2_set_context_id(execbuf, 0);
+ execbuf.rsvd2 = 0;
+
+ for (count = 1; count <= 1<<17; count <<= 1) {
+ struct timeval start, end;
+
+ gettimeofday(&start, NULL);
+ if (gem_exec(fd, &execbuf, count))
+ exit(1);
+ gem_sync(fd, handle);
+ gettimeofday(&end, NULL);
+ printf("Time to blt %d bytes x %6d: %7.3fµs, %s\n",
+ object_size, count,
+ elapsed(&start, &end, count),
+ bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
+ fflush(stdout);
+ }
+ gem_close(fd, handle);
+
+ close(fd);
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+
+ if (argc > 1) {
+ for (i = 1; i < argc; i++) {
+ int object_size = atoi(argv[i]);
+ if (object_size)
+ run((object_size + 3) & -4);
+ }
+ } else
+ run(OBJECT_SIZE);
+
+ return 0;
+}
diff --git a/tests/gem_exec_faulting_reloc.c b/tests/gem_exec_faulting_reloc.c
new file mode 100644
index 00000000..863a1b03
--- /dev/null
+++ b/tests/gem_exec_faulting_reloc.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+
+/* Testcase: Submit patches with relocations in memory that will fault
+ *
+ * To be really evil, use a gtt mmap for them.
+ */
+
+#define OBJECT_SIZE 16384
+
+#define COPY_BLT_CMD (2<<29|0x53<<22|0x6)
+#define BLT_WRITE_ALPHA (1<<21)
+#define BLT_WRITE_RGB (1<<20)
+#define BLT_SRC_TILED (1<<15)
+#define BLT_DST_TILED (1<<11)
+
+static int gem_linear_blt(uint32_t *batch,
+ uint32_t src,
+ uint32_t dst,
+ uint32_t length,
+ struct drm_i915_gem_relocation_entry *reloc)
+{
+ uint32_t *b = batch;
+ int height = length / (16 * 1024);
+
+ assert(height <= 1<<16);
+
+ if (height) {
+ b[0] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB;
+ b[1] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024);
+ b[2] = 0;
+ b[3] = height << 16 | (4*1024);
+ b[4] = 0;
+ reloc->offset = (b-batch+4) * sizeof(uint32_t);
+ reloc->delta = 0;
+ reloc->target_handle = dst;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = I915_GEM_DOMAIN_RENDER;
+ reloc->presumed_offset = 0;
+ reloc++;
+
+ b[5] = 0;
+ b[6] = 16*1024;
+ b[7] = 0;
+ reloc->offset = (b-batch+7) * sizeof(uint32_t);
+ reloc->delta = 0;
+ reloc->target_handle = src;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = 0;
+ reloc->presumed_offset = 0;
+ reloc++;
+
+ b += 8;
+ length -= height * 16*1024;
+ }
+
+ if (length) {
+ b[0] = COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB;
+ b[1] = 0xcc << 16 | 1 << 25 | 1 << 24 | (16*1024);
+ b[2] = height << 16;
+ b[3] = (1+height) << 16 | (length / 4);
+ b[4] = 0;
+ reloc->offset = (b-batch+4) * sizeof(uint32_t);
+ reloc->delta = 0;
+ reloc->target_handle = dst;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = I915_GEM_DOMAIN_RENDER;
+ reloc->presumed_offset = 0;
+ reloc++;
+
+ b[5] = height << 16;
+ b[6] = 16*1024;
+ b[7] = 0;
+ reloc->offset = (b-batch+7) * sizeof(uint32_t);
+ reloc->delta = 0;
+ reloc->target_handle = src;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = 0;
+ reloc->presumed_offset = 0;
+ reloc++;
+
+ b += 8;
+ }
+
+ b[0] = MI_BATCH_BUFFER_END;
+ b[1] = 0;
+
+ return (b+2 - batch) * sizeof(uint32_t);
+}
+
+static void gem_exec(int fd, struct drm_i915_gem_execbuffer2 *execbuf)
+{
+ int ret;
+
+ ret = drmIoctl(fd,
+ DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ execbuf);
+ assert(ret == 0);
+}
+
+static void run(int object_size)
+{
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 exec[3];
+ struct drm_i915_gem_relocation_entry reloc[4];
+ uint32_t buf[20];
+ uint32_t handle, handle_relocs, src, dst;
+ void *gtt_relocs;
+ int fd, len;
+ int ring;
+
+ fd = drm_open_any();
+ handle = gem_create(fd, 4096);
+ src = gem_create(fd, object_size);
+ dst = gem_create(fd, object_size);
+
+ len = gem_linear_blt(buf, src, dst, object_size, reloc);
+ gem_write(fd, handle, 0, buf, len);
+
+ exec[0].handle = src;
+ exec[0].relocation_count = 0;
+ exec[0].relocs_ptr = 0;
+ exec[0].alignment = 0;
+ exec[0].offset = 0;
+ exec[0].flags = 0;
+ exec[0].rsvd1 = 0;
+ exec[0].rsvd2 = 0;
+
+ exec[1].handle = dst;
+ exec[1].relocation_count = 0;
+ exec[1].relocs_ptr = 0;
+ exec[1].alignment = 0;
+ exec[1].offset = 0;
+ exec[1].flags = 0;
+ exec[1].rsvd1 = 0;
+ exec[1].rsvd2 = 0;
+
+ handle_relocs = gem_create(fd, 4096);
+ gem_write(fd, handle_relocs, 0, reloc, sizeof(reloc));
+ gtt_relocs = gem_mmap(fd, handle_relocs, 4096,
+ PROT_READ | PROT_WRITE);
+ assert(gtt_relocs);
+
+ exec[2].handle = handle;
+ exec[2].relocation_count = len > 40 ? 4 : 2;
+ /* A newly mmap gtt bo will fault on first access. */
+ exec[2].relocs_ptr = (uintptr_t)gtt_relocs;
+ exec[2].alignment = 0;
+ exec[2].offset = 0;
+ exec[2].flags = 0;
+ exec[2].rsvd1 = 0;
+ exec[2].rsvd2 = 0;
+
+ ring = 0;
+ if (HAS_BLT_RING(intel_get_drm_devid(fd)))
+ ring = I915_EXEC_BLT;
+
+ execbuf.buffers_ptr = (uintptr_t)exec;
+ execbuf.buffer_count = 3;
+ execbuf.batch_start_offset = 0;
+ execbuf.batch_len = len;
+ execbuf.cliprects_ptr = 0;
+ execbuf.num_cliprects = 0;
+ execbuf.DR1 = 0;
+ execbuf.DR4 = 0;
+ execbuf.flags = ring;
+ i915_execbuffer2_set_context_id(execbuf, 0);
+ execbuf.rsvd2 = 0;
+
+ gem_exec(fd, &execbuf);
+ gem_sync(fd, handle);
+
+ gem_close(fd, handle);
+
+ close(fd);
+}
+
+int main(int argc, char **argv)
+{
+ run(OBJECT_SIZE);
+
+ return 0;
+}
diff --git a/tests/gem_exec_nop.c b/tests/gem_exec_nop.c
new file mode 100644
index 00000000..9dd055cf
--- /dev/null
+++ b/tests/gem_exec_nop.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define MI_BATCH_BUFFER_END (0xA<<23)
+
+static double elapsed(const struct timeval *start,
+ const struct timeval *end,
+ int loop)
+{
+ return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec))/loop;
+}
+
+static int exec(int fd, uint32_t handle, int loops)
+{
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 gem_exec[1];
+ int ret = 0;
+
+ gem_exec[0].handle = handle;
+ gem_exec[0].relocation_count = 0;
+ gem_exec[0].relocs_ptr = 0;
+ gem_exec[0].alignment = 0;
+ gem_exec[0].offset = 0;
+ gem_exec[0].flags = 0;
+ gem_exec[0].rsvd1 = 0;
+ gem_exec[0].rsvd2 = 0;
+
+ execbuf.buffers_ptr = (uintptr_t)gem_exec;
+ execbuf.buffer_count = 1;
+ execbuf.batch_start_offset = 0;
+ execbuf.batch_len = 8;
+ execbuf.cliprects_ptr = 0;
+ execbuf.num_cliprects = 0;
+ execbuf.DR1 = 0;
+ execbuf.DR4 = 0;
+ execbuf.flags = 0;
+ i915_execbuffer2_set_context_id(execbuf, 0);
+ execbuf.rsvd2 = 0;
+
+ while (loops-- && ret == 0) {
+ ret = drmIoctl(fd,
+ DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ &execbuf);
+ }
+ gem_sync(fd, handle);
+
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t batch[2] = {MI_BATCH_BUFFER_END};
+ uint32_t handle;
+ int count;
+ int fd;
+
+ fd = drm_open_any();
+
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, sizeof(batch));
+
+ for (count = 1; count <= 1<<17; count <<= 1) {
+ struct timeval start, end;
+
+ gettimeofday(&start, NULL);
+ if (exec(fd, handle, count))
+ exit(1);
+ gettimeofday(&end, NULL);
+ printf("Time to exec x %d: %7.3fµs\n",
+ count, elapsed(&start, &end, count));
+ fflush(stdout);
+ }
+ gem_close(fd, handle);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_fence_thrash.c b/tests/gem_fence_thrash.c
new file mode 100644
index 00000000..3d50e334
--- /dev/null
+++ b/tests/gem_fence_thrash.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2008-9 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define OBJECT_SIZE (128*1024) /* restricted to 1MiB alignment on i915 fences */
+
+/* Before introduction of the LRU list for fences, allocation of a fence for a page
+ * fault would use the first inactive fence (i.e. in preference one with no outstanding
+ * GPU activity, or it would wait on the first to finish). Given the choice, it would simply
+ * reuse the fence that had just been allocated for the previous page-fault - the worst choice
+ * when copying between two buffers and thus constantly swapping fences.
+ */
+
+static void *
+bo_create (int fd)
+{
+ void *ptr;
+ int handle;
+
+ handle = gem_create(fd, OBJECT_SIZE);
+
+ gem_set_tiling(fd, handle, I915_TILING_X, 1024);
+
+ ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
+
+ /* XXX: mmap_gtt pulls the bo into the GTT read domain. */
+ gem_sync(fd, handle);
+
+ return ptr;
+}
+
+static void *
+bo_copy (void *_arg)
+{
+ int fd = *(int *)_arg;
+ int n;
+ char *a, *b;
+
+ a = bo_create (fd);
+ b = bo_create (fd);
+
+ for (n = 0; n < 1000; n++) {
+ memcpy (a, b, OBJECT_SIZE);
+ sched_yield ();
+ }
+
+ return NULL;
+}
+
+int
+main(int argc, char **argv)
+{
+ drm_i915_getparam_t gp;
+ pthread_t threads[32];
+ int n, num_fences;
+ int fd, ret;
+
+ fd = drm_open_any();
+
+ gp.param = I915_PARAM_NUM_FENCES_AVAIL;
+ gp.value = &num_fences;
+ ret = ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+ assert (ret == 0);
+
+ printf ("creating %d threads\n", num_fences);
+ assert (num_fences < sizeof (threads) / sizeof (threads[0]));
+
+ for (n = 0; n < num_fences; n++)
+ pthread_create (&threads[n], NULL, bo_copy, &fd);
+
+ for (n = 0; n < num_fences; n++)
+ pthread_join (threads[n], NULL);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_fenced_exec_thrash.c b/tests/gem_fenced_exec_thrash.c
new file mode 100644
index 00000000..8281449e
--- /dev/null
+++ b/tests/gem_fenced_exec_thrash.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <drm.h>
+#include <i915_drm.h>
+
+#include "drmtest.h"
+
+#define WIDTH 1024
+#define HEIGHT 1024
+#define OBJECT_SIZE (4*WIDTH*HEIGHT)
+
+#define BATCH_SIZE 4096
+
+#define MAX_FENCES 16
+
+#define MI_BATCH_BUFFER_END (0xA<<23)
+
+/*
+ * Testcase: execbuf fence accounting
+ *
+ * We had a bug where we were falsely accounting upon reservation already
+ * fenced buffers as occupying a fence register even if they did not require
+ * one for the batch.
+ *
+ * We aim to exercise this by performing a sequence of fenced BLT
+ * with 2*num_avail_fence buffers, but alternating which half are fenced in
+ * each command.
+ */
+
+static uint32_t
+tiled_bo_create (int fd)
+{
+ uint32_t handle;
+
+ handle = gem_create(fd, OBJECT_SIZE);
+
+ gem_set_tiling(fd, handle, I915_TILING_X, WIDTH*4);
+
+ return handle;
+}
+
+static uint32_t
+batch_create (int fd)
+{
+ uint32_t buf[] = { MI_BATCH_BUFFER_END, 0 };
+ uint32_t batch_handle;
+
+ batch_handle = gem_create(fd, BATCH_SIZE);
+
+ gem_write(fd, batch_handle, 0, buf, sizeof(buf));
+
+ return batch_handle;
+}
+
+static int get_num_fences(int fd)
+{
+ drm_i915_getparam_t gp;
+ int ret, val;
+
+ gp.param = I915_PARAM_NUM_FENCES_AVAIL;
+ gp.value = &val;
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+ assert (ret == 0);
+
+ printf ("total %d fences\n", val);
+ assert(val > 4);
+
+ return val - 2;
+}
+
+static void fill_reloc(struct drm_i915_gem_relocation_entry *reloc, uint32_t handle)
+{
+ reloc->offset = 2 * sizeof(uint32_t);
+ reloc->target_handle = handle;
+ reloc->read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc->write_domain = 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct drm_i915_gem_execbuffer2 execbuf[2];
+ struct drm_i915_gem_exec_object2 exec[2][2*MAX_FENCES+1];
+ struct drm_i915_gem_relocation_entry reloc[2*MAX_FENCES];
+
+ int fd = drm_open_any();
+ int i, n, num_fences;
+ int loop = 1000;
+
+ memset(execbuf, 0, sizeof(execbuf));
+ memset(exec, 0, sizeof(exec));
+ memset(reloc, 0, sizeof(reloc));
+
+ num_fences = get_num_fences(fd) & ~1;
+ assert(num_fences <= MAX_FENCES);
+ for (n = 0; n < 2*num_fences; n++) {
+ uint32_t handle = tiled_bo_create(fd);
+ exec[1][2*num_fences - n-1].handle = exec[0][n].handle = handle;
+ fill_reloc(&reloc[n], handle);
+ }
+
+ for (i = 0; i < 2; i++) {
+ for (n = 0; n < num_fences; n++)
+ exec[i][n].flags = EXEC_OBJECT_NEEDS_FENCE;
+
+ exec[i][2*num_fences].handle = batch_create(fd);
+ exec[i][2*num_fences].relocs_ptr = (uintptr_t)reloc;
+ exec[i][2*num_fences].relocation_count = 2*num_fences;
+
+ execbuf[i].buffers_ptr = (uintptr_t)exec[i];
+ execbuf[i].buffer_count = 2*num_fences+1;
+ execbuf[i].batch_len = 2*sizeof(uint32_t);
+ }
+
+ do {
+ int ret;
+
+ ret = drmIoctl(fd,
+ DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ &execbuf[0]);
+ assert(ret == 0);
+
+ ret = drmIoctl(fd,
+ DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ &execbuf[1]);
+ assert(ret == 0);
+ } while (--loop);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_flink.c b/tests/gem_flink.c
new file mode 100644
index 00000000..c8694808
--- /dev/null
+++ b/tests/gem_flink.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+static void
+test_flink(int fd)
+{
+ struct drm_i915_gem_create create;
+ struct drm_gem_flink flink;
+ struct drm_gem_open gem_open;
+ int ret;
+
+ printf("Testing flink and open.\n");
+
+ memset(&create, 0, sizeof(create));
+ create.size = 16 * 1024;
+ ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create);
+ assert(ret == 0);
+
+ flink.handle = create.handle;
+ ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
+ assert(ret == 0);
+
+ gem_open.name = flink.name;
+ ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &gem_open);
+ assert(ret == 0);
+ assert(gem_open.handle != 0);
+}
+
+static void
+test_double_flink(int fd)
+{
+ struct drm_i915_gem_create create;
+ struct drm_gem_flink flink;
+ struct drm_gem_flink flink2;
+ int ret;
+
+ printf("Testing repeated flink.\n");
+
+ memset(&create, 0, sizeof(create));
+ create.size = 16 * 1024;
+ ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create);
+ assert(ret == 0);
+
+ flink.handle = create.handle;
+ ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
+ assert(ret == 0);
+
+ flink2.handle = create.handle;
+ ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink2);
+ assert(ret == 0);
+ assert(flink2.name == flink.name);
+}
+
+static void
+test_bad_flink(int fd)
+{
+ struct drm_gem_flink flink;
+ int ret;
+
+ printf("Testing error return on bad flink ioctl.\n");
+
+ flink.handle = 0x10101010;
+ ret = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
+ assert(ret == -1 && errno == ENOENT);
+}
+
+static void
+test_bad_open(int fd)
+{
+ struct drm_gem_open gem_open;
+ int ret;
+
+ printf("Testing error return on bad open ioctl.\n");
+
+ gem_open.name = 0x10101010;
+ ret = ioctl(fd, DRM_IOCTL_GEM_OPEN, &gem_open);
+
+ assert(ret == -1 && errno == ENOENT);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+
+ fd = drm_open_any();
+
+ test_flink(fd);
+ test_double_flink(fd);
+ test_bad_flink(fd);
+ test_bad_open(fd);
+
+ return 0;
+}
diff --git a/tests/gem_gtt_concurrent_blit.c b/tests/gem_gtt_concurrent_blit.c
new file mode 100644
index 00000000..c68af7b5
--- /dev/null
+++ b/tests/gem_gtt_concurrent_blit.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright © 2009,2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file gem_cpu_concurrent_blit.c
+ *
+ * This is a test of GTT mmap read/write behavior when writing to active
+ * buffers.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static void
+set_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
+{
+ int size = width * height;
+ uint32_t *vaddr;
+
+ drm_intel_gem_bo_start_gtt_access(bo, true);
+ vaddr = bo->virtual;
+ while (size--)
+ *vaddr++ = val;
+}
+
+static void
+cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
+{
+ int size = width * height;
+ uint32_t *vaddr;
+
+ drm_intel_gem_bo_start_gtt_access(bo, false);
+ vaddr = bo->virtual;
+ while (size--)
+ assert(*vaddr++ == val);
+}
+
+static drm_intel_bo *
+create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height)
+{
+ drm_intel_bo *bo;
+
+ bo = drm_intel_bo_alloc(bufmgr, "bo", 4*width*height, 0);
+ assert(bo);
+
+ /* gtt map doesn't have a write parameter, so just keep the mapping
+ * around (to avoid the set_domain with the gtt write domain set) and
+ * manually tell the kernel when we start access the gtt. */
+ drm_intel_gem_bo_map_gtt(bo);
+
+ set_bo(bo, val, width, height);
+
+ return bo;
+}
+
+int
+main(int argc, char **argv)
+{
+ drm_intel_bufmgr *bufmgr;
+ struct intel_batchbuffer *batch;
+ int num_buffers = 128, max;
+ drm_intel_bo *src[128], *dst[128], *dummy;
+ int width = 512, height = 512;
+ int fd;
+ int i;
+
+ fd = drm_open_any();
+
+ max = gem_aperture_size (fd) / (1024 * 1024) / 2;
+ if (num_buffers > max)
+ num_buffers = max;
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ for (i = 0; i < num_buffers; i++) {
+ src[i] = create_bo(bufmgr, i, width, height);
+ dst[i] = create_bo(bufmgr, ~i, width, height);
+ }
+ dummy = create_bo(bufmgr, 0, width, height);
+
+ /* try to overwrite the source values */
+ for (i = 0; i < num_buffers; i++)
+ intel_copy_bo(batch, dst[i], src[i], width, height);
+ for (i = num_buffers; i--; )
+ set_bo(src[i], 0xdeadbeef, width, height);
+ for (i = 0; i < num_buffers; i++)
+ cmp_bo(dst[i], i, width, height);
+
+ /* try to read the results before the copy completes */
+ for (i = 0; i < num_buffers; i++)
+ intel_copy_bo(batch, dst[i], src[i], width, height);
+ for (i = num_buffers; i--; )
+ cmp_bo(dst[i], 0xdeadbeef, width, height);
+
+ /* and finally try to trick the kernel into loosing the pending write */
+ for (i = num_buffers; i--; )
+ set_bo(src[i], 0xabcdabcd, width, height);
+ for (i = 0; i < num_buffers; i++)
+ intel_copy_bo(batch, dst[i], src[i], width, height);
+ for (i = num_buffers; i--; )
+ intel_copy_bo(batch, dummy, dst[i], width, height);
+ for (i = num_buffers; i--; )
+ cmp_bo(dst[i], 0xabcdabcd, width, height);
+
+ return 0;
+}
diff --git a/tests/gem_gtt_cpu_tlb.c b/tests/gem_gtt_cpu_tlb.c
new file mode 100644
index 00000000..68533709
--- /dev/null
+++ b/tests/gem_gtt_cpu_tlb.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+/** @file gem_gtt_cpu_tlb.c
+ *
+ * This test checks whether gtt tlbs for cpu access are correctly invalidated.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#define OBJ_SIZE (1024*1024)
+
+#define PAGE_SIZE 4096
+
+static uint32_t
+create_bo(int fd)
+{
+ uint32_t handle;
+ uint32_t *data;
+ int i;
+
+ handle = gem_create(fd, OBJ_SIZE);
+
+ /* Fill the BO with dwords starting at start_val */
+ data = gem_mmap(fd, handle, OBJ_SIZE, PROT_READ | PROT_WRITE);
+ for (i = 0; i < OBJ_SIZE/4; i++)
+ data[i] = i;
+ munmap(data, OBJ_SIZE);
+
+ return handle;
+}
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+ int i;
+ uint32_t handle;
+
+ uint32_t *ptr;
+
+ fd = drm_open_any();
+
+ handle = gem_create(fd, OBJ_SIZE);
+
+ /* touch one page */
+ ptr = gem_mmap(fd, handle, OBJ_SIZE, PROT_READ | PROT_WRITE);
+ *ptr = 0xdeadbeef;
+ munmap(ptr, OBJ_SIZE);
+
+ gem_close(fd, handle);
+
+ /* stirr up the page allocator a bit. */
+ ptr = malloc(OBJ_SIZE);
+ assert(ptr);
+ memset(ptr, 0x1, OBJ_SIZE);
+
+ handle = create_bo(fd);
+
+ /* Read a bunch of random subsets of the data and check that they come
+ * out right.
+ */
+ gem_read(fd, handle, 0, ptr, OBJ_SIZE);
+ for (i = 0; i < OBJ_SIZE/4; i++)
+ assert(ptr[i] == i);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_gtt_speed.c b/tests/gem_gtt_speed.c
new file mode 100644
index 00000000..73a3c6dc
--- /dev/null
+++ b/tests/gem_gtt_speed.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define OBJECT_SIZE 16384
+
+static double elapsed(const struct timeval *start,
+ const struct timeval *end,
+ int loop)
+{
+ return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec))/loop;
+}
+
+int main(int argc, char **argv)
+{
+ struct timeval start, end;
+ uint8_t *buf;
+ uint32_t handle;
+ int size = OBJECT_SIZE;
+ int loop, i, tiling;
+ int fd;
+
+ if (argc > 1)
+ size = atoi(argv[1]);
+ if (size == 0) {
+ fprintf(stderr, "Invalid object size specified\n");
+ return 1;
+ }
+
+ buf = malloc(size);
+ memset(buf, 0, size);
+ fd = drm_open_any();
+
+ handle = gem_create(fd, size);
+ assert(handle);
+
+ for (tiling = I915_TILING_NONE; tiling <= I915_TILING_Y; tiling++) {
+ if (tiling != I915_TILING_NONE) {
+ printf("\nSetting tiling mode to %s\n",
+ tiling == I915_TILING_X ? "X" : "Y");
+ gem_set_tiling(fd, handle, tiling, 512);
+ }
+
+ if (tiling == I915_TILING_NONE) {
+ gem_set_domain(fd, handle,
+ I915_GEM_DOMAIN_CPU,
+ I915_GEM_DOMAIN_CPU);
+
+ {
+ uint32_t *base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE);
+ volatile uint32_t *ptr = base;
+ int x = 0;
+
+ for (i = 0; i < size/sizeof(*ptr); i++)
+ x += ptr[i];
+
+ /* force overtly clever gcc to actually compute x */
+ ptr[0] = x;
+
+ munmap(base, size);
+
+ /* mmap read */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++) {
+ base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE);
+ ptr = base;
+ x = 0;
+
+ for (i = 0; i < size/sizeof(*ptr); i++)
+ x += ptr[i];
+
+ /* force overtly clever gcc to actually compute x */
+ ptr[0] = x;
+
+ munmap(base, size);
+ }
+ gettimeofday(&end, NULL);
+ printf("Time to read %dk through a CPU map: %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ /* mmap write */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++) {
+ base = gem_mmap__cpu(fd, handle, size, PROT_READ | PROT_WRITE);
+ ptr = base;
+
+ for (i = 0; i < size/sizeof(*ptr); i++)
+ ptr[i] = i;
+
+ munmap(base, size);
+ }
+ gettimeofday(&end, NULL);
+ printf("Time to write %dk through a CPU map: %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+ }
+
+ /* CPU pwrite */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++)
+ gem_write(fd, handle, 0, buf, size);
+ gettimeofday(&end, NULL);
+ printf("Time to pwrite %dk through the CPU: %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ /* CPU pread */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++)
+ gem_read(fd, handle, 0, buf, size);
+ gettimeofday(&end, NULL);
+ printf("Time to pread %dk through the CPU: %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+ }
+
+ /* prefault into gtt */
+ {
+ uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE);
+ volatile uint32_t *ptr = base;
+ int x = 0;
+
+ for (i = 0; i < size/sizeof(*ptr); i++)
+ x += ptr[i];
+
+ /* force overtly clever gcc to actually compute x */
+ ptr[0] = x;
+
+ munmap(base, size);
+ }
+ /* mmap read */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++) {
+ uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE);
+ volatile uint32_t *ptr = base;
+ int x = 0;
+
+ for (i = 0; i < size/sizeof(*ptr); i++)
+ x += ptr[i];
+
+ /* force overtly clever gcc to actually compute x */
+ ptr[0] = x;
+
+ munmap(base, size);
+ }
+ gettimeofday(&end, NULL);
+ printf("Time to read %dk through a GTT map: %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ /* mmap write */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++) {
+ uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE);
+ volatile uint32_t *ptr = base;
+
+ for (i = 0; i < size/sizeof(*ptr); i++)
+ ptr[i] = i;
+
+ munmap(base, size);
+ }
+ gettimeofday(&end, NULL);
+ printf("Time to write %dk through a GTT map: %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ /* mmap read */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++) {
+ uint32_t *base = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE);
+ volatile uint32_t *ptr = base;
+ int x = 0;
+
+ for (i = 0; i < size/sizeof(*ptr); i++)
+ x += ptr[i];
+
+ /* force overtly clever gcc to actually compute x */
+ ptr[0] = x;
+
+ munmap(base, size);
+ }
+ gettimeofday(&end, NULL);
+ printf("Time to read %dk (again) through a GTT map: %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ if (tiling == I915_TILING_NONE) {
+ /* GTT pwrite */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++)
+ gem_write(fd, handle, 0, buf, size);
+ gettimeofday(&end, NULL);
+ printf("Time to pwrite %dk through the GTT: %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ /* GTT pread */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++)
+ gem_read(fd, handle, 0, buf, size);
+ gettimeofday(&end, NULL);
+ printf("Time to pread %dk through the GTT: %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ /* GTT pwrite, including clflush */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++) {
+ gem_write(fd, handle, 0, buf, size);
+ gem_sync(fd, handle);
+ }
+ gettimeofday(&end, NULL);
+ printf("Time to pwrite %dk through the GTT (clflush): %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ /* GTT pread, including clflush */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++) {
+ gem_sync(fd, handle);
+ gem_read(fd, handle, 0, buf, size);
+ }
+ gettimeofday(&end, NULL);
+ printf("Time to pread %dk through the GTT (clflush): %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ /* partial writes */
+ printf("Now partial writes.\n");
+ size /= 4;
+
+ /* partial GTT pwrite, including clflush */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++) {
+ gem_write(fd, handle, 0, buf, size);
+ gem_sync(fd, handle);
+ }
+ gettimeofday(&end, NULL);
+ printf("Time to pwrite %dk through the GTT (clflush): %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ /* partial GTT pread, including clflush */
+ gettimeofday(&start, NULL);
+ for (loop = 0; loop < 1000; loop++) {
+ gem_sync(fd, handle);
+ gem_read(fd, handle, 0, buf, size);
+ }
+ gettimeofday(&end, NULL);
+ printf("Time to pread %dk through the GTT (clflush): %7.3fµs\n",
+ size/1024, elapsed(&start, &end, loop));
+
+ size *= 4;
+ }
+
+ }
+
+ gem_close(fd, handle);
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_hang.c b/tests/gem_hang.c
new file mode 100644
index 00000000..f9db3400
--- /dev/null
+++ b/tests/gem_hang.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Jesse Barnes <jbarnes@virtuousgeek.org> (based on gem_bad_blit.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static int bad_pipe;
+
+static void
+gpu_hang(void)
+{
+ int cmd;
+
+ cmd = bad_pipe ? MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW :
+ MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW;
+
+ BEGIN_BATCH(6);
+ /* The documentation says that the LOAD_SCAN_LINES command
+ * always comes in pairs. Don't ask me why. */
+ OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | (bad_pipe << 20));
+ OUT_BATCH((0 << 16) | 2048);
+ OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | (bad_pipe << 20));
+ OUT_BATCH((0 << 16) | 2048);
+ OUT_BATCH(MI_WAIT_FOR_EVENT | cmd);
+ OUT_BATCH(MI_NOOP);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <disabled pipe number>\n",
+ argv[0]);
+ exit(-1);
+ }
+
+ bad_pipe = atoi(argv[1]);
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ gpu_hang();
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_hangcheck_forcewake.c b/tests/gem_hangcheck_forcewake.c
new file mode 100644
index 00000000..96a30fef
--- /dev/null
+++ b/tests/gem_hangcheck_forcewake.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+/*
+ * Testcase: Provoke the hangcheck timer on an otherwise idle system
+ *
+ * This tries to hit forcewake locking bugs when the hangcheck runs. Somehow we
+ * often luck out and the hangcheck runs while someone else is already holding
+ * the dev->struct_mutex.
+ *
+ * It's imperative that nothing else runs while this test runs, i.e. kill your X
+ * session, please.
+ */
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+uint32_t blob[2048*2048];
+
+#define MAX_BLT_SIZE 128
+int main(int argc, char **argv)
+{
+ drm_intel_bo *bo = NULL;
+ uint32_t tiling_mode = I915_TILING_X;
+ unsigned long pitch, act_size;
+ int fd, i, devid;
+
+ memset(blob, 'A', sizeof(blob));
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ devid = intel_get_drm_devid(fd);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+ act_size = 2048;
+ printf("filling ring\n");
+ drm_intel_bo_unreference(bo);
+ bo = drm_intel_bo_alloc_tiled(bufmgr, "tiled bo", act_size, act_size,
+ 4, &tiling_mode, &pitch, 0);
+
+ drm_intel_bo_subdata(bo, 0, act_size*act_size*4, blob);
+
+ if (IS_965(devid))
+ pitch /= 4;
+
+ for (i = 0; i < 10000; i++) {
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB |
+ XY_SRC_COPY_BLT_SRC_TILED |
+ XY_SRC_COPY_BLT_DST_TILED);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ pitch);
+ OUT_BATCH(0 << 16 | 1024);
+ OUT_BATCH((2048) << 16 | (2048));
+ OUT_RELOC_FENCED(bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(pitch);
+ OUT_RELOC_FENCED(bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ BEGIN_BATCH(3);
+ OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ }
+ }
+
+ printf("waiting\n");
+ sleep(10);
+
+ printf("done waiting, check dmesg\n");
+ drm_intel_bo_unreference(bo);
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_largeobject.c b/tests/gem_largeobject.c
new file mode 100644
index 00000000..163bf101
--- /dev/null
+++ b/tests/gem_largeobject.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jesse Barnes <jbarnes@virtuousgeek.org>
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+/* Should take 64 pages to store the page pointers on 64 bit */
+#define OBJ_SIZE (128 * 1024 * 1024)
+
+unsigned char data[OBJ_SIZE];
+
+static void
+test_large_object(int fd)
+{
+ struct drm_i915_gem_create create;
+ struct drm_i915_gem_pin pin;
+ uint32_t obj_size;
+ int ret;
+
+ memset(&create, 0, sizeof(create));
+ memset(&pin, 0, sizeof(pin));
+
+ if (gem_aperture_size(fd)*3/4 < OBJ_SIZE/2)
+ obj_size = OBJ_SIZE / 4;
+ else if (gem_aperture_size(fd)*3/4 < OBJ_SIZE)
+ obj_size = OBJ_SIZE / 2;
+ else
+ obj_size = OBJ_SIZE;
+ create.size = obj_size;
+ printf("obj size %i\n", obj_size);
+
+ ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create);
+ if (ret) {
+ fprintf(stderr, "object creation failed: %s\n",
+ strerror(errno));
+ exit(ret);
+ }
+
+ pin.handle = create.handle;
+ ret = ioctl(fd, DRM_IOCTL_I915_GEM_PIN, &pin);
+ if (ret) {
+ fprintf(stderr, "pin failed: %s\n",
+ strerror(errno));
+ exit(ret);
+ }
+
+ gem_write(fd, create.handle, 0, data, obj_size);
+
+ /* kernel should clean this up for us */
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+
+ fd = drm_open_any();
+
+ test_large_object(fd);
+
+ return 0;
+}
diff --git a/tests/gem_linear_blits.c b/tests/gem_linear_blits.c
new file mode 100644
index 00000000..fe15f1d1
--- /dev/null
+++ b/tests/gem_linear_blits.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file gem_linear_blits.c
+ *
+ * This is a test of doing many blits, with a working set
+ * larger than the aperture size.
+ *
+ * The goal is to simply ensure the basics work.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+#define WIDTH 512
+#define HEIGHT 512
+
+static uint32_t linear[WIDTH*HEIGHT];
+
+static void
+copy(int fd, uint32_t dst, uint32_t src)
+{
+ uint32_t batch[10];
+ struct drm_i915_gem_relocation_entry reloc[2];
+ struct drm_i915_gem_exec_object2 obj[3];
+ struct drm_i915_gem_execbuffer2 exec;
+ uint32_t handle;
+ int ret;
+
+ batch[0] = XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB;
+ batch[1] = (3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ WIDTH*4;
+ batch[2] = 0; /* dst x1,y1 */
+ batch[3] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */
+ batch[4] = 0; /* dst reloc */
+ batch[5] = 0; /* src x1,y1 */
+ batch[6] = WIDTH*4;
+ batch[7] = 0; /* src reloc */
+ batch[8] = MI_BATCH_BUFFER_END;
+ batch[9] = MI_NOOP;
+
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, sizeof(batch));
+
+ reloc[0].target_handle = dst;
+ reloc[0].delta = 0;
+ reloc[0].offset = 4 * sizeof(batch[0]);
+ reloc[0].presumed_offset = 0;
+ reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;;
+ reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
+
+ reloc[1].target_handle = src;
+ reloc[1].delta = 0;
+ reloc[1].offset = 7 * sizeof(batch[0]);
+ reloc[1].presumed_offset = 0;
+ reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;;
+ reloc[1].write_domain = 0;
+
+ obj[0].handle = dst;
+ obj[0].relocation_count = 0;
+ obj[0].relocs_ptr = 0;
+ obj[0].alignment = 0;
+ obj[0].offset = 0;
+ obj[0].flags = 0;
+ obj[0].rsvd1 = 0;
+ obj[0].rsvd2 = 0;
+
+ obj[1].handle = src;
+ obj[1].relocation_count = 0;
+ obj[1].relocs_ptr = 0;
+ obj[1].alignment = 0;
+ obj[1].offset = 0;
+ obj[1].flags = 0;
+ obj[1].rsvd1 = 0;
+ obj[1].rsvd2 = 0;
+
+ obj[2].handle = handle;
+ obj[2].relocation_count = 2;
+ obj[2].relocs_ptr = (uintptr_t)reloc;
+ obj[2].alignment = 0;
+ obj[2].offset = 0;
+ obj[2].flags = 0;
+ obj[2].rsvd1 = obj[2].rsvd2 = 0;
+
+ exec.buffers_ptr = (uintptr_t)obj;
+ exec.buffer_count = 3;
+ exec.batch_start_offset = 0;
+ exec.batch_len = sizeof(batch);
+ exec.DR1 = exec.DR4 = 0;
+ exec.num_cliprects = 0;
+ exec.cliprects_ptr = 0;
+ exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0;
+ i915_execbuffer2_set_context_id(exec, 0);
+ exec.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ while (ret && errno == EBUSY) {
+ drmCommandNone(fd, DRM_I915_GEM_THROTTLE);
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ }
+ assert(ret == 0);
+
+ gem_close(fd, handle);
+}
+
+static uint32_t
+create_bo(int fd, uint32_t val)
+{
+ uint32_t handle;
+ int i;
+
+ handle = gem_create(fd, sizeof(linear));
+
+ /* Fill the BO with dwords starting at val */
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ linear[i] = val++;
+ gem_write(fd, handle, 0, linear, sizeof(linear));
+
+ return handle;
+}
+
+static void
+check_bo(int fd, uint32_t handle, uint32_t val)
+{
+ int i;
+
+ gem_read(fd, handle, 0, linear, sizeof(linear));
+ for (i = 0; i < WIDTH*HEIGHT; i++) {
+ if (linear[i] != val) {
+ fprintf(stderr, "Expected 0x%08x, found 0x%08x "
+ "at offset 0x%08x\n",
+ val, linear[i], i * 4);
+ abort();
+ }
+ val++;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t *handle, *start_val;
+ uint32_t start = 0;
+ int i, fd, count;
+
+ fd = drm_open_any();
+
+ count = 0;
+ if (argc > 1)
+ count = atoi(argv[1]);
+ if (count == 0)
+ count = 3 * gem_aperture_size(fd) / (1024*1024) / 2;
+
+ if (count > intel_get_total_ram_mb() * 9 / 10) {
+ count = intel_get_total_ram_mb() * 9 / 10;
+ printf("not enough RAM to run test, reducing buffer count\n");
+ }
+
+ printf("Using %d 1MiB buffers\n", count);
+
+ handle = malloc(sizeof(uint32_t)*count*2);
+ start_val = handle + count;
+
+ for (i = 0; i < count; i++) {
+ handle[i] = create_bo(fd, start);
+ start_val[i] = start;
+ start += 1024 * 1024 / 4;
+ }
+
+ printf("Verifying initialisation...\n");
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ printf("Cyclic blits, forward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = i % count;
+ int dst = (i + 1) % count;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ printf("Cyclic blits, backward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = (i + 1) % count;
+ int dst = i % count;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ printf("Random blits...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = random() % count;
+ int dst = random() % count;
+
+ if (src == dst)
+ continue;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ return 0;
+}
diff --git a/tests/gem_mmap.c b/tests/gem_mmap.c
new file mode 100644
index 00000000..f9369f43
--- /dev/null
+++ b/tests/gem_mmap.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define OBJECT_SIZE 16384
+
+int main(int argc, char **argv)
+{
+ int fd;
+ struct drm_i915_gem_mmap arg;
+ uint8_t expected[OBJECT_SIZE];
+ uint8_t buf[OBJECT_SIZE];
+ uint8_t *addr;
+ int ret;
+ int handle;
+
+ fd = drm_open_any();
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = 0x10101010;
+ arg.offset = 0;
+ arg.size = 4096;
+ printf("Testing mmaping of bad object.\n");
+ ret = ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg);
+ assert(ret == -1 && errno == ENOENT);
+
+ handle = gem_create(fd, OBJECT_SIZE);
+
+ printf("Testing mmaping of newly created object.\n");
+ arg.handle = handle;
+ arg.offset = 0;
+ arg.size = OBJECT_SIZE;
+ ret = ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg);
+ assert(ret == 0);
+ addr = (uint8_t *)(uintptr_t)arg.addr_ptr;
+
+ printf("Testing contents of newly created object.\n");
+ memset(expected, 0, sizeof(expected));
+ assert(memcmp(addr, expected, sizeof(expected)) == 0);
+
+ printf("Testing coherency of writes and mmap reads.\n");
+ memset(buf, 0, sizeof(buf));
+ memset(buf + 1024, 0x01, 1024);
+ memset(expected + 1024, 0x01, 1024);
+ gem_write(fd, handle, 0, buf, OBJECT_SIZE);
+ assert(memcmp(buf, addr, sizeof(buf)) == 0);
+
+ printf("Testing that mapping stays after close\n");
+ gem_close(fd, handle);
+ assert(memcmp(buf, addr, sizeof(buf)) == 0);
+
+ printf("Testing unmapping\n");
+ munmap(addr, OBJECT_SIZE);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_mmap_gtt.c b/tests/gem_mmap_gtt.c
new file mode 100644
index 00000000..e7a48679
--- /dev/null
+++ b/tests/gem_mmap_gtt.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define OBJECT_SIZE (16*1024*1024)
+
+static void set_domain(int fd, uint32_t handle)
+{
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+}
+
+static void *
+mmap_bo(int fd, uint32_t handle)
+{
+ void *ptr;
+
+ ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
+ assert(ptr != MAP_FAILED);
+
+ return ptr;
+}
+
+static void *
+create_pointer(int fd)
+{
+ uint32_t handle;
+ void *ptr;
+
+ handle = gem_create(fd, OBJECT_SIZE);
+
+ ptr = mmap_bo(fd, handle);
+
+ gem_close(fd, handle);
+
+ return ptr;
+}
+
+static void
+test_copy(int fd)
+{
+ void *src, *dst;
+
+ /* copy from a fresh src to fresh dst to force pagefault on both */
+ src = create_pointer(fd);
+ dst = create_pointer(fd);
+
+ memcpy(dst, src, OBJECT_SIZE);
+ memcpy(src, dst, OBJECT_SIZE);
+
+ munmap(dst, OBJECT_SIZE);
+ munmap(src, OBJECT_SIZE);
+}
+
+static void
+test_write(int fd)
+{
+ void *src;
+ uint32_t dst;
+
+ /* copy from a fresh src to fresh dst to force pagefault on both */
+ src = create_pointer(fd);
+ dst = gem_create(fd, OBJECT_SIZE);
+
+ gem_write(fd, dst, 0, src, OBJECT_SIZE);
+
+ gem_close(fd, dst);
+ munmap(src, OBJECT_SIZE);
+}
+
+static void
+test_write_gtt(int fd)
+{
+ uint32_t dst;
+ char *dst_gtt;
+ void *src;
+
+ dst = gem_create(fd, OBJECT_SIZE);
+
+ /* prefault object into gtt */
+ dst_gtt = mmap_bo(fd, dst);
+ set_domain(fd, dst);
+ memset(dst_gtt, 0, OBJECT_SIZE);
+ munmap(dst_gtt, OBJECT_SIZE);
+
+ src = create_pointer(fd);
+
+ gem_write(fd, dst, 0, src, OBJECT_SIZE);
+
+ gem_close(fd, dst);
+ munmap(src, OBJECT_SIZE);
+}
+
+static void
+test_read(int fd)
+{
+ void *dst;
+ uint32_t src;
+
+ /* copy from a fresh src to fresh dst to force pagefault on both */
+ dst = create_pointer(fd);
+ src = gem_create(fd, OBJECT_SIZE);
+
+ gem_read(fd, src, 0, dst, OBJECT_SIZE);
+
+ gem_close(fd, src);
+ munmap(dst, OBJECT_SIZE);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+
+ fd = drm_open_any();
+
+ test_copy(fd);
+ test_read(fd);
+ test_write(fd);
+ test_write_gtt(fd);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_mmap_offset_exhaustion.c b/tests/gem_mmap_offset_exhaustion.c
new file mode 100644
index 00000000..51ae5990
--- /dev/null
+++ b/tests/gem_mmap_offset_exhaustion.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define OBJECT_SIZE (1024*1024)
+
+/* Testcase: checks whether the kernel handles mmap offset exhaustion correctly
+ *
+ * Currently the kernel doesn't reap the mmap offset of purged objects, albeit
+ * there's nothing that prevents it ABI-wise and it helps to get out of corners
+ * (because drm_mm is only 32bit on 32bit archs unfortunately.
+ *
+ * Note that on 64bit machines we have plenty of address space (because drm_mm
+ * uses unsigned long).
+ */
+
+static void
+create_and_map_bo(int fd)
+{
+ uint32_t handle;
+ char *ptr;
+
+ handle = gem_create(fd, OBJECT_SIZE);
+
+ ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
+
+ if (!ptr) {
+ fprintf(stderr, "mmap failed\n");
+ assert(ptr);
+ }
+
+ /* touch it to force it into the gtt */
+ *ptr = 0;
+
+ /* but then unmap it again because we only have limited address space on
+ * 32 bit */
+ munmap(ptr, OBJECT_SIZE);
+
+ /* we happily leak objects to exhaust mmap offset space, the kernel will
+ * reap backing storage. */
+ gem_madvise(fd, handle, I915_MADV_DONTNEED);
+}
+
+int main(int argc, char **argv)
+{
+ int fd, i;
+
+ fd = drm_open_any();
+
+ /* we have 32bit of address space, so try to fit one MB more
+ * than that. */
+ for (i = 0; i < 4096 + 1; i++)
+ create_and_map_bo(fd);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_partial_pwrite_pread.c b/tests/gem_partial_pwrite_pread.c
new file mode 100644
index 00000000..5c8f6f5f
--- /dev/null
+++ b/tests/gem_partial_pwrite_pread.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+/*
+ * Testcase: pwrite/pread consistency when touching partial cachelines
+ *
+ * Some fancy new pwrite/pread optimizations clflush in-line while
+ * reading/writing. Check whether all required clflushes happen.
+ *
+ */
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+drm_intel_bo *scratch_bo;
+drm_intel_bo *staging_bo;
+#define BO_SIZE (4*4096)
+uint32_t devid;
+uint64_t mappable_gtt_limit;
+int fd;
+
+static void
+copy_bo(drm_intel_bo *src, drm_intel_bo *dst)
+{
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ 4096);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH((BO_SIZE/4096) << 16 | 1024);
+ OUT_RELOC_FENCED(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(4096);
+ OUT_RELOC_FENCED(src, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+}
+
+static void
+blt_bo_fill(drm_intel_bo *tmp_bo, drm_intel_bo *bo, int val)
+{
+ uint8_t *gtt_ptr;
+ int i;
+
+ drm_intel_gem_bo_map_gtt(tmp_bo);
+ gtt_ptr = tmp_bo->virtual;
+
+ for (i = 0; i < BO_SIZE; i++)
+ gtt_ptr[i] = val;
+
+ drm_intel_gem_bo_unmap_gtt(tmp_bo);
+
+ if (bo->offset < mappable_gtt_limit &&
+ (IS_G33(devid) || intel_gen(devid) >= 4))
+ drmtest_trash_aperture();
+
+ copy_bo(tmp_bo, bo);
+}
+
+#define MAX_BLT_SIZE 128
+#define ROUNDS 1000
+int main(int argc, char **argv)
+{
+ int i, j;
+ uint8_t tmp[BO_SIZE];
+ uint8_t *gtt_ptr;
+
+ srandom(0xdeadbeef);
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ devid = intel_get_drm_devid(fd);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+ /* overallocate the buffers we're actually using because */
+ scratch_bo = drm_intel_bo_alloc(bufmgr, "scratch bo", BO_SIZE, 4096);
+ staging_bo = drm_intel_bo_alloc(bufmgr, "staging bo", BO_SIZE, 4096);
+
+ drmtest_init_aperture_trashers(bufmgr);
+ mappable_gtt_limit = gem_mappable_aperture_size();
+
+ printf("checking partial reads\n");
+ for (i = 0; i < ROUNDS; i++) {
+ int start, len;
+ int val = i % 256;
+
+ blt_bo_fill(staging_bo, scratch_bo, i);
+
+ start = random() % BO_SIZE;
+ len = random() % (BO_SIZE-start) + 1;
+
+ drm_intel_bo_get_subdata(scratch_bo, start, len, tmp);
+ for (j = 0; j < len; j++) {
+ if (tmp[j] != val) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+
+ drmtest_progress("partial reads test: ", i, ROUNDS);
+ }
+
+ printf("checking partial writes\n");
+ for (i = 0; i < ROUNDS; i++) {
+ int start, len;
+ int val = i % 256;
+
+ blt_bo_fill(staging_bo, scratch_bo, i);
+
+ start = random() % BO_SIZE;
+ len = random() % (BO_SIZE-start) + 1;
+
+ memset(tmp, i + 63, BO_SIZE);
+
+ drm_intel_bo_subdata(scratch_bo, start, len, tmp);
+
+ copy_bo(scratch_bo, staging_bo);
+ drm_intel_gem_bo_map_gtt(staging_bo);
+ gtt_ptr = staging_bo->virtual;
+
+ for (j = 0; j < start; j++) {
+ if (gtt_ptr[j] != val) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+ for (; j < start + len; j++) {
+ if (gtt_ptr[j] != tmp[0]) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], i);
+ exit(1);
+ }
+ }
+ for (; j < BO_SIZE; j++) {
+ if (gtt_ptr[j] != val) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+ drm_intel_gem_bo_unmap_gtt(staging_bo);
+
+ drmtest_progress("partial writes test: ", i, ROUNDS);
+ }
+
+ printf("checking partial writes after partial reads\n");
+ for (i = 0; i < ROUNDS; i++) {
+ int start, len;
+ int val = i % 256;
+
+ blt_bo_fill(staging_bo, scratch_bo, i);
+
+ /* partial read */
+ start = random() % BO_SIZE;
+ len = random() % (BO_SIZE-start) + 1;
+
+ drm_intel_bo_get_subdata(scratch_bo, start, len, tmp);
+ for (j = 0; j < len; j++) {
+ if (tmp[j] != val) {
+ printf("mismatch in read at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+
+ /* Change contents through gtt to make the pread cachelines
+ * stale. */
+ val = (i + 17) % 256;
+ blt_bo_fill(staging_bo, scratch_bo, val);
+
+ /* partial write */
+ start = random() % BO_SIZE;
+ len = random() % (BO_SIZE-start) + 1;
+
+ memset(tmp, i + 63, BO_SIZE);
+
+ drm_intel_bo_subdata(scratch_bo, start, len, tmp);
+
+ copy_bo(scratch_bo, staging_bo);
+ drm_intel_gem_bo_map_gtt(staging_bo);
+ gtt_ptr = staging_bo->virtual;
+
+ for (j = 0; j < start; j++) {
+ if (gtt_ptr[j] != val) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+ for (; j < start + len; j++) {
+ if (gtt_ptr[j] != tmp[0]) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], tmp[0]);
+ exit(1);
+ }
+ }
+ for (; j < BO_SIZE; j++) {
+ if (gtt_ptr[j] != val) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+ drm_intel_gem_bo_unmap_gtt(staging_bo);
+
+ drmtest_progress("partial read/writes test: ", i, ROUNDS);
+ }
+
+ drmtest_cleanup_aperture_trashers();
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_pipe_control_store_loop.c b/tests/gem_pipe_control_store_loop.c
new file mode 100644
index 00000000..e03cddd7
--- /dev/null
+++ b/tests/gem_pipe_control_store_loop.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch> (based on gem_storedw_*.c)
+ *
+ */
+
+/*
+ * Testcase: (TLB-)Coherency of pipe_control QW writes
+ *
+ * Writes a counter-value into an always newly allocated target bo (by disabling
+ * buffer reuse). Decently trashes on tlb inconsistencies, too.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+uint32_t devid;
+
+#define GFX_OP_PIPE_CONTROL ((0x3<<29)|(0x3<<27)|(0x2<<24)|2)
+#define PIPE_CONTROL_WRITE_IMMEDIATE (1<<14)
+#define PIPE_CONTROL_WRITE_TIMESTAMP (3<<14)
+#define PIPE_CONTROL_DEPTH_STALL (1<<13)
+#define PIPE_CONTROL_WC_FLUSH (1<<12)
+#define PIPE_CONTROL_IS_FLUSH (1<<11) /* MBZ on Ironlake */
+#define PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */
+#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1)
+#define PIPE_CONTROL_CS_STALL (1<<20)
+#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
+
+/* Like the store dword test, but we create new command buffers each time */
+static void
+store_pipe_control_loop(void)
+{
+ int i, val = 0;
+ uint32_t *buf;
+ drm_intel_bo *target_bo;
+
+ for (i = 0; i < 0x10000; i++) {
+ /* we want to check tlb consistency of the pipe_control target,
+ * so get a new buffer every time around */
+ target_bo = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
+ if (!target_bo) {
+ fprintf(stderr, "failed to alloc target buffer\n");
+ exit(-1);
+ }
+
+ /* gem_storedw_batches_loop.c is a bit overenthusiastic with
+ * creating new batchbuffers - with buffer reuse disabled, the
+ * support code will do that for us. */
+ if (intel_gen(devid) >= 6) {
+ /* work-around hw issue, see intel_emit_post_sync_nonzero_flush
+ * in mesa sources. */
+ BEGIN_BATCH(4);
+ OUT_BATCH(GFX_OP_PIPE_CONTROL);
+ OUT_BATCH(PIPE_CONTROL_CS_STALL |
+ PIPE_CONTROL_STALL_AT_SCOREBOARD);
+ OUT_BATCH(0); /* address */
+ OUT_BATCH(0); /* write data */
+ ADVANCE_BATCH();
+
+ BEGIN_BATCH(4);
+ OUT_BATCH(GFX_OP_PIPE_CONTROL);
+ OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE);
+ OUT_RELOC(target_bo,
+ I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
+ PIPE_CONTROL_GLOBAL_GTT);
+ OUT_BATCH(val); /* write data */
+ ADVANCE_BATCH();
+ } else if (intel_gen(devid) >= 4) {
+ BEGIN_BATCH(4);
+ OUT_BATCH(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_WC_FLUSH |
+ PIPE_CONTROL_TC_FLUSH |
+ PIPE_CONTROL_WRITE_IMMEDIATE | 2);
+ OUT_RELOC(target_bo,
+ I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
+ PIPE_CONTROL_GLOBAL_GTT);
+ OUT_BATCH(val);
+ OUT_BATCH(0xdeadbeef);
+ ADVANCE_BATCH();
+ }
+
+ intel_batchbuffer_flush_on_ring(batch, 0);
+
+ drm_intel_bo_map(target_bo, 1);
+
+ buf = target_bo->virtual;
+ if (buf[0] != val) {
+ fprintf(stderr,
+ "value mismatch: cur 0x%08x, stored 0x%08x\n",
+ buf[0], val);
+ exit(-1);
+ }
+ buf[0] = 0; /* let batch write it again */
+ drm_intel_bo_unmap(target_bo);
+
+ drm_intel_bo_unreference(target_bo);
+
+ val++;
+ }
+
+ printf("completed %d writes successfully\n", i);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: %s\n", argv[0]);
+ exit(-1);
+ }
+
+ fd = drm_open_any();
+ devid = intel_get_drm_devid(fd);
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+
+ if (IS_GEN2(devid) || IS_GEN3(devid)) {
+ fprintf(stderr, "no pipe_control on gen2/3\n");
+ return 77;
+ }
+ if (devid == PCI_CHIP_I965_G) {
+ fprintf(stderr, "pipe_control totally broken on i965\n");
+ return 77;
+ }
+ /* IMPORTANT: No call to
+ * drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ * here because we wan't to have fresh buffers (to trash the tlb)
+ * every time! */
+
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+ if (!batch) {
+ fprintf(stderr, "failed to create batch buffer\n");
+ exit(-1);
+ }
+
+ store_pipe_control_loop();
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_pread_after_blit.c b/tests/gem_pread_after_blit.c
new file mode 100644
index 00000000..c9c8b02c
--- /dev/null
+++ b/tests/gem_pread_after_blit.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file gem_pread_after_blit.c
+ *
+ * This is a test of pread's behavior when getting values out of just-drawn-to
+ * buffers.
+ *
+ * The goal is to catch failure in the whole-buffer-flush or
+ * ranged-buffer-flush paths in the kernel.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static const int width = 512, height = 512;
+static const int size = 1024 * 1024;
+
+#define PAGE_SIZE 4096
+
+static drm_intel_bo *
+create_bo(uint32_t val)
+{
+ drm_intel_bo *bo;
+ uint32_t *vaddr;
+ int i;
+
+ bo = drm_intel_bo_alloc(bufmgr, "src bo", size, 4096);
+
+ /* Fill the BO with dwords starting at start_val */
+ drm_intel_bo_map(bo, 1);
+ vaddr = bo->virtual;
+
+ for (i = 0; i < 1024 * 1024 / 4; i++)
+ vaddr[i] = val++;
+
+ drm_intel_bo_unmap(bo);
+
+ return bo;
+}
+
+static void
+verify_large_read(drm_intel_bo *bo, uint32_t val)
+{
+ uint32_t buf[size / 4];
+ int i;
+
+ drm_intel_bo_get_subdata(bo, 0, size, buf);
+
+ for (i = 0; i < size / 4; i++) {
+ if (buf[i] != val) {
+ fprintf(stderr,
+ "Unexpected value 0x%08x instead of "
+ "0x%08x at offset 0x%08x (%p)\n",
+ buf[i], val, i * 4, buf);
+ abort();
+ }
+ val++;
+ }
+}
+
+/** This reads at the size that Mesa usees for software fallbacks. */
+static void
+verify_small_read(drm_intel_bo *bo, uint32_t val)
+{
+ uint32_t buf[4096 / 4];
+ int offset, i;
+
+ for (i = 0; i < 4096 / 4; i++)
+ buf[i] = 0x00c0ffee;
+
+ for (offset = 0; offset < size; offset += PAGE_SIZE) {
+ drm_intel_bo_get_subdata(bo, offset, PAGE_SIZE, buf);
+
+ for (i = 0; i < PAGE_SIZE; i += 4) {
+ if (buf[i / 4] != val) {
+ fprintf(stderr,
+ "Unexpected value 0x%08x instead of "
+ "0x%08x at offset 0x%08x\n",
+ buf[i / 4], val, i * 4);
+ abort();
+ }
+ val++;
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+ drm_intel_bo *src1, *src2, *bo;
+ uint32_t start1 = 0;
+ uint32_t start2 = 1024 * 1024 / 4;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ src1 = create_bo(start1);
+ src2 = create_bo(start2);
+
+ bo = drm_intel_bo_alloc(bufmgr, "dst bo", size, 4096);
+
+ /* First, do a full-buffer read after blitting */
+ printf("Large read after blit 1\n");
+ intel_copy_bo(batch, bo, src1, width, height);
+ verify_large_read(bo, start1);
+ printf("Large read after blit 2\n");
+ intel_copy_bo(batch, bo, src2, width, height);
+ verify_large_read(bo, start2);
+
+ printf("Small reads after blit 1\n");
+ intel_copy_bo(batch, bo, src1, width, height);
+ verify_small_read(bo, start1);
+ printf("Small reads after blit 2\n");
+ intel_copy_bo(batch, bo, src2, width, height);
+ verify_small_read(bo, start2);
+
+ printf("Large read after blit 3\n");
+ intel_copy_bo(batch, bo, src1, width, height);
+ verify_large_read(bo, start1);
+
+ drm_intel_bo_unreference(src1);
+ drm_intel_bo_unreference(src2);
+ drm_intel_bo_unreference(bo);
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_pwrite.c b/tests/gem_pwrite.c
new file mode 100644
index 00000000..051ed3b5
--- /dev/null
+++ b/tests/gem_pwrite.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define OBJECT_SIZE 16384
+
+#define COPY_BLT_CMD (2<<29|0x53<<22|0x6)
+#define BLT_WRITE_ALPHA (1<<21)
+#define BLT_WRITE_RGB (1<<20)
+#define BLT_SRC_TILED (1<<15)
+#define BLT_DST_TILED (1<<11)
+#define MI_BATCH_BUFFER_END (0xA<<23)
+
+static void do_gem_write(int fd, uint32_t handle, void *buf, int len, int loops)
+{
+ while (loops--)
+ gem_write(fd, handle, 0, buf, len);
+}
+
+static double elapsed(const struct timeval *start,
+ const struct timeval *end,
+ int loop)
+{
+ return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec))/loop;
+}
+
+static const char *bytes_per_sec(char *buf, double v)
+{
+ const char *order[] = {
+ "",
+ "KiB",
+ "MiB",
+ "GiB",
+ "TiB",
+ NULL,
+ }, **o = order;
+
+ while (v > 1000 && o[1]) {
+ v /= 1000;
+ o++;
+ }
+ sprintf(buf, "%.1f%s/s", v, *o);
+ return buf;
+}
+
+
+int main(int argc, char **argv)
+{
+ int object_size = 0;
+ uint32_t buf[20];
+ uint32_t *src, dst;
+ int fd, count;
+
+ if (argc > 1)
+ object_size = atoi(argv[1]);
+ if (object_size == 0)
+ object_size = OBJECT_SIZE;
+ object_size = (object_size + 3) & -4;
+
+ fd = drm_open_any();
+
+ dst = gem_create(fd, object_size);
+ src = malloc(object_size);
+ for (count = 1; count <= 1<<17; count <<= 1) {
+ struct timeval start, end;
+
+ gettimeofday(&start, NULL);
+ do_gem_write(fd, dst, src, object_size, count);
+ gettimeofday(&end, NULL);
+ printf("Time to pwrite %d bytes x %6d: %7.3fµs, %s\n",
+ object_size, count,
+ elapsed(&start, &end, count),
+ bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
+ fflush(stdout);
+ }
+ free(src);
+ gem_close(fd, dst);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_readwrite.c b/tests/gem_readwrite.c
new file mode 100644
index 00000000..68c3ff28
--- /dev/null
+++ b/tests/gem_readwrite.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define OBJECT_SIZE 16384
+
+static int
+do_read(int fd, int handle, void *buf, int offset, int size)
+{
+ struct drm_i915_gem_pread read;
+
+ /* Ensure that we don't have any convenient data in buf in case
+ * we fail.
+ */
+ memset(buf, 0xd0, size);
+
+ memset(&read, 0, sizeof(read));
+ read.handle = handle;
+ read.data_ptr = (uintptr_t)buf;
+ read.size = size;
+ read.offset = offset;
+
+ return ioctl(fd, DRM_IOCTL_I915_GEM_PREAD, &read);
+}
+
+static int
+do_write(int fd, int handle, void *buf, int offset, int size)
+{
+ struct drm_i915_gem_pwrite write;
+
+ memset(&write, 0, sizeof(write));
+ write.handle = handle;
+ write.data_ptr = (uintptr_t)buf;
+ write.size = size;
+ write.offset = offset;
+
+ return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &write);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ uint8_t expected[OBJECT_SIZE];
+ uint8_t buf[OBJECT_SIZE];
+ int ret;
+ int handle;
+
+ fd = drm_open_any();
+
+ handle = gem_create(fd, OBJECT_SIZE);
+
+ printf("Testing contents of newly created object.\n");
+ ret = do_read(fd, handle, buf, 0, OBJECT_SIZE);
+ assert(ret == 0);
+ memset(&expected, 0, sizeof(expected));
+ assert(memcmp(expected, buf, sizeof(expected)) == 0);
+
+ printf("Testing read beyond end of buffer.\n");
+ ret = do_read(fd, handle, buf, OBJECT_SIZE / 2, OBJECT_SIZE);
+ assert(ret == -1 && errno == EINVAL);
+
+ printf("Testing full write of buffer\n");
+ memset(buf, 0, sizeof(buf));
+ memset(buf + 1024, 0x01, 1024);
+ memset(expected + 1024, 0x01, 1024);
+ ret = do_write(fd, handle, buf, 0, OBJECT_SIZE);
+ assert(ret == 0);
+ ret = do_read(fd, handle, buf, 0, OBJECT_SIZE);
+ assert(ret == 0);
+ assert(memcmp(buf, expected, sizeof(buf)) == 0);
+
+ printf("Testing partial write of buffer\n");
+ memset(buf + 4096, 0x02, 1024);
+ memset(expected + 4096, 0x02, 1024);
+ ret = do_write(fd, handle, buf + 4096, 4096, 1024);
+ assert(ret == 0);
+ ret = do_read(fd, handle, buf, 0, OBJECT_SIZE);
+ assert(ret == 0);
+ assert(memcmp(buf, expected, sizeof(buf)) == 0);
+
+ printf("Testing partial read of buffer\n");
+ ret = do_read(fd, handle, buf, 512, 1024);
+ assert(ret == 0);
+ assert(memcmp(buf, expected + 512, 1024) == 0);
+
+ printf("Testing read of bad buffer handle\n");
+ ret = do_read(fd, 1234, buf, 0, 1024);
+ assert(ret == -1 && errno == ENOENT);
+
+ printf("Testing write of bad buffer handle\n");
+ ret = do_write(fd, 1234, buf, 0, 1024);
+ assert(ret == -1 && errno == ENOENT);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_reg_read.c b/tests/gem_reg_read.c
new file mode 100644
index 00000000..1d6db1f1
--- /dev/null
+++ b/tests/gem_reg_read.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "i915_drm.h"
+#include "drmtest.h"
+
+struct local_drm_i915_reg_read {
+ __u64 offset;
+ __u64 val; /* Return value */
+};
+
+#define REG_READ_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x31, struct local_drm_i915_reg_read)
+
+static void handle_bad(int ret, int lerrno, int expected, const char *desc)
+{
+ if (ret != 0 && lerrno != expected) {
+ fprintf(stderr, "%s - errno was %d, but should have been %d\n",
+ desc, lerrno, expected);
+ exit(EXIT_FAILURE);
+ } else if (ret == 0) {
+ fprintf(stderr, "%s - Command succeeded, but should have failed\n",
+ desc);
+ exit(EXIT_FAILURE);
+ }
+}
+
+static uint64_t timer_query(int fd)
+{
+ struct local_drm_i915_reg_read read;
+ int ret;
+
+ read.offset = 0x2358;
+ ret = drmIoctl(fd, REG_READ_IOCTL, &read);
+ if (ret) {
+ perror("positive test case failed: ");
+ exit(EXIT_FAILURE);
+ }
+
+ return read.val;
+}
+
+int main(int argc, char *argv[])
+{
+ struct local_drm_i915_reg_read read;
+ int ret, fd;
+ uint64_t val;
+
+ fd = drm_open_any();
+
+ read.offset = 0x2358;
+ ret = drmIoctl(fd, REG_READ_IOCTL, &read);
+ if (errno == EINVAL)
+ exit(77);
+ else if (ret)
+ exit(EXIT_FAILURE);
+
+ val = timer_query(fd);
+ sleep(1);
+ if (timer_query(fd) == val) {
+ fprintf(stderr, "Timer isn't moving, probably busted\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* bad reg */
+ read.offset = 0x12345678;
+ ret = drmIoctl(fd, REG_READ_IOCTL, &read);
+ handle_bad(ret, errno, EINVAL, "bad register");
+
+ close(fd);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tests/gem_reloc_vs_gpu.c b/tests/gem_reloc_vs_gpu.c
new file mode 100644
index 00000000..47681d51
--- /dev/null
+++ b/tests/gem_reloc_vs_gpu.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+/*
+ * Testcase: Kernel relocations vs. gpu races
+ *
+ */
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+uint32_t blob[2048*2048];
+#define NUM_TARGET_BOS 16
+drm_intel_bo *pc_target_bo[NUM_TARGET_BOS];
+drm_intel_bo *dummy_bo;
+drm_intel_bo *special_bo;
+uint32_t devid;
+int special_reloc_ofs;
+int special_batch_len;
+
+#define GFX_OP_PIPE_CONTROL ((0x3<<29)|(0x3<<27)|(0x2<<24)|2)
+#define PIPE_CONTROL_WRITE_IMMEDIATE (1<<14)
+#define PIPE_CONTROL_WRITE_TIMESTAMP (3<<14)
+#define PIPE_CONTROL_DEPTH_STALL (1<<13)
+#define PIPE_CONTROL_WC_FLUSH (1<<12)
+#define PIPE_CONTROL_IS_FLUSH (1<<11) /* MBZ on Ironlake */
+#define PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */
+#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1<<1)
+#define PIPE_CONTROL_CS_STALL (1<<20)
+#define PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
+
+static void create_special_bo(void)
+{
+ uint32_t data[1024];
+ int len = 0;
+ int small_pitch = 64;
+#define BATCH(dw) data[len++] = (dw);
+
+ memset(data, 0, 4096);
+ special_bo = drm_intel_bo_alloc(bufmgr, "special batch", 4096, 4096);
+
+ BATCH(XY_COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
+ BATCH((3 << 24) | (0xf0 << 16) | small_pitch);
+ BATCH(0);
+ BATCH(1 << 16 | 1);
+ special_reloc_ofs = 4*len;
+ BATCH(0);
+ BATCH(0xdeadbeef);
+
+#define CMD_POLY_STIPPLE_OFFSET 0x7906
+ /* batchbuffer end */
+ if (IS_GEN5(batch->devid)) {
+ BATCH(CMD_POLY_STIPPLE_OFFSET << 16);
+ BATCH(0);
+ }
+ assert(len % 2 == 0);
+ BATCH(MI_NOOP);
+ BATCH(MI_BATCH_BUFFER_END);
+
+ drm_intel_bo_subdata(special_bo, 0, 4096, data);
+ special_batch_len = len*4;
+}
+
+static void emit_dummy_load(int pitch)
+{
+ int i;
+ uint32_t tile_flags = 0;
+
+ if (IS_965(devid)) {
+ pitch /= 4;
+ tile_flags = XY_SRC_COPY_BLT_SRC_TILED |
+ XY_SRC_COPY_BLT_DST_TILED;
+ }
+
+ for (i = 0; i < 10; i++) {
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB |
+ tile_flags);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ pitch);
+ OUT_BATCH(0 << 16 | 1024);
+ OUT_BATCH((2048) << 16 | (2048));
+ OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(pitch);
+ OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ BEGIN_BATCH(3);
+ OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ }
+ }
+ intel_batchbuffer_flush(batch);
+}
+
+#define MAX_BLT_SIZE 128
+int main(int argc, char **argv)
+{
+ uint32_t tiling_mode = I915_TILING_X;
+ unsigned long pitch, act_size;
+ int fd, i, ring;
+ uint32_t test;
+
+ memset(blob, 'A', sizeof(blob));
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ /* disable reuse, otherwise the test fails */
+ //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ devid = intel_get_drm_devid(fd);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+ act_size = 2048;
+ dummy_bo = drm_intel_bo_alloc_tiled(bufmgr, "tiled dummy_bo", act_size, act_size,
+ 4, &tiling_mode, &pitch, 0);
+
+ drm_intel_bo_subdata(dummy_bo, 0, act_size*act_size*4, blob);
+
+ create_special_bo();
+
+ if (intel_gen(devid) >= 6)
+ ring = I915_EXEC_BLT;
+ else
+ ring = 0;
+
+ for (i = 0; i < NUM_TARGET_BOS; i++) {
+ pc_target_bo[i] = drm_intel_bo_alloc(bufmgr, "special batch", 4096, 4096);
+ emit_dummy_load(pitch);
+ assert(pc_target_bo[i]->offset == 0);
+ drm_intel_bo_emit_reloc(special_bo, special_reloc_ofs,
+ pc_target_bo[i],
+ 0,
+ I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER);
+ drm_intel_bo_mrb_exec(special_bo, special_batch_len, NULL,
+ 0, 0, ring);
+ }
+
+ /* Only check at the end to avoid unnecessary synchronous behaviour. */
+ for (i = 0; i < NUM_TARGET_BOS; i++) {
+ drm_intel_bo_get_subdata(pc_target_bo[i], 0, 4, &test);
+ if (test != 0xdeadbeef) {
+ fprintf(stderr, "mismatch in buffer %i: 0x%08x instead of 0xdeadbeef\n", i, test);
+ exit(1);
+ }
+ drm_intel_bo_unreference(pc_target_bo[i]);
+ }
+
+ drm_intel_gem_bo_map_gtt(dummy_bo);
+ drm_intel_gem_bo_unmap_gtt(dummy_bo);
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_ring_sync_loop.c b/tests/gem_ring_sync_loop.c
new file mode 100644
index 00000000..b689bcde
--- /dev/null
+++ b/tests/gem_ring_sync_loop.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch> (based on gem_storedw_*.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+#include "i830_reg.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static drm_intel_bo *target_buffer;
+
+/*
+ * Testcase: Basic check of ring<->ring sync using a dummy reloc
+ *
+ * Extremely efficient at catching missed irqs with semaphores=0 ...
+ */
+
+#define MI_COND_BATCH_BUFFER_END (0x36<<23 | 1)
+#define MI_DO_COMPARE (1<<21)
+
+static void
+store_dword_loop(void)
+{
+ int i;
+
+ srandom(0xdeadbeef);
+
+ for (i = 0; i < 0x100000; i++) {
+ int ring = random() % 3 + 1;
+
+ if (ring == I915_EXEC_RENDER) {
+ BEGIN_BATCH(4);
+ OUT_BATCH(MI_COND_BATCH_BUFFER_END | MI_DO_COMPARE);
+ OUT_BATCH(0xffffffff); /* compare dword */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(MI_NOOP);
+ ADVANCE_BATCH();
+ } else {
+ BEGIN_BATCH(4);
+ OUT_BATCH(MI_FLUSH_DW | 1);
+ OUT_BATCH(0); /* reserved */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(MI_NOOP | (1<<22) | (0xf));
+ ADVANCE_BATCH();
+ }
+ intel_batchbuffer_flush_on_ring(batch, ring);
+ }
+
+ drm_intel_bo_map(target_buffer, 0);
+ // map to force waiting on rendering
+ drm_intel_bo_unmap(target_buffer);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int devid;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: %s\n", argv[0]);
+ exit(-1);
+ }
+
+ fd = drm_open_any();
+ devid = intel_get_drm_devid(fd);
+ if (!HAS_BLT_RING(devid)) {
+ fprintf(stderr, "inter ring check needs gen6+\n");
+ return 77;
+ }
+
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+ if (!batch) {
+ fprintf(stderr, "failed to create batch buffer\n");
+ exit(-1);
+ }
+
+ target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
+ if (!target_buffer) {
+ fprintf(stderr, "failed to alloc target buffer\n");
+ exit(-1);
+ }
+
+ store_dword_loop();
+
+ drm_intel_bo_unreference(target_buffer);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_ringfill.c b/tests/gem_ringfill.c
new file mode 100644
index 00000000..5bae8f11
--- /dev/null
+++ b/tests/gem_ringfill.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file gem_ringfill.c
+ *
+ * This is a test of doing many tiny batchbuffer operations, in the hope of
+ * catching failure to manage the ring properly near full.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include "drm.h"
+#include "i915_drm.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+#include "rendercopy.h"
+
+struct bo {
+ const char *ring;
+ drm_intel_bo *src, *dst, *tmp;
+};
+
+static const int width = 512, height = 512;
+
+static void create_bo(drm_intel_bufmgr *bufmgr,
+ struct bo *b,
+ const char *ring)
+{
+ int size = 4 * width * height, i;
+ uint32_t *map;
+
+ b->ring = ring;
+ b->src = drm_intel_bo_alloc(bufmgr, "src", size, 4096);
+ b->dst = drm_intel_bo_alloc(bufmgr, "dst", size, 4096);
+ b->tmp = drm_intel_bo_alloc(bufmgr, "tmp", size, 4096);
+
+ /* Fill the src with indexes of the pixels */
+ drm_intel_bo_map(b->src, true);
+ map = b->src->virtual;
+ for (i = 0; i < width * height; i++)
+ map[i] = i;
+ drm_intel_bo_unmap(b->src);
+
+ /* Fill the dst with garbage. */
+ drm_intel_bo_map(b->dst, true);
+ map = b->dst->virtual;
+ for (i = 0; i < width * height; i++)
+ map[i] = 0xd0d0d0d0;
+ drm_intel_bo_unmap(b->dst);
+}
+
+static int check_bo(struct bo *b)
+{
+ const uint32_t *map;
+ int i, fails = 0;
+
+ drm_intel_bo_map(b->dst, false);
+ map = b->dst->virtual;
+ for (i = 0; i < width*height; i++) {
+ if (map[i] != i && ++fails <= 9) {
+ int x = i % width;
+ int y = i / width;
+
+ printf("%s: copy #%d at %d,%d failed: read 0x%08x\n",
+ b->ring, i, x, y, map[i]);
+ }
+ }
+ drm_intel_bo_unmap(b->dst);
+
+ return fails;
+}
+
+static void destroy_bo(struct bo *b)
+{
+ drm_intel_bo_unreference(b->src);
+ drm_intel_bo_unreference(b->tmp);
+ drm_intel_bo_unreference(b->dst);
+}
+
+static int check_ring(drm_intel_bufmgr *bufmgr,
+ struct intel_batchbuffer *batch,
+ const char *ring,
+ render_copyfunc_t copy)
+{
+ struct scratch_buf src, tmp, dst;
+ struct bo bo;
+ char output[100];
+ int i;
+
+ snprintf(output, 100, "filling %s ring: ", ring);
+
+ create_bo(bufmgr, &bo, ring);
+
+ src.stride = 4 * width;
+ src.tiling = 0;
+ src.data = src.cpu_mapping = NULL;
+ src.size = 4 * width * height;
+ src.num_tiles = 4 * width * height;
+ dst = tmp = src;
+
+ src.bo = bo.src;
+ tmp.bo = bo.tmp;
+ dst.bo = bo.dst;
+
+ /* The ring we've been using is 128k, and each rendering op
+ * will use at least 8 dwords:
+ *
+ * BATCH_START
+ * BATCH_START offset
+ * MI_FLUSH
+ * STORE_DATA_INDEX
+ * STORE_DATA_INDEX offset
+ * STORE_DATA_INDEX value
+ * MI_USER_INTERRUPT
+ * (padding)
+ *
+ * So iterate just a little more than that -- if we don't fill the ring
+ * doing this, we aren't likely to with this test.
+ */
+ for (i = 0; i < width * height; i++) {
+ int x = i % width;
+ int y = i / width;
+
+ drmtest_progress(output, i, width*height);
+
+ assert(y < height);
+
+ /* Dummy load to fill the ring */
+ copy(batch, &src, 0, 0, width, height, &tmp, 0, 0);
+ /* And copy the src into dst, pixel by pixel */
+ copy(batch, &src, x, y, 1, 1, &dst, x, y);
+ }
+
+ /* verify */
+ printf("verifying\n");
+ i = check_bo(&bo);
+ destroy_bo(&bo);
+
+ return i;
+}
+
+static void blt_copy(struct intel_batchbuffer *batch,
+ struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ unsigned w, unsigned h,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y)
+{
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ dst->stride);
+ OUT_BATCH((dst_y << 16) | dst_x); /* dst x1,y1 */
+ OUT_BATCH(((dst_y + h) << 16) | (dst_x + w)); /* dst x2,y2 */
+ OUT_RELOC(dst->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH((src_y << 16) | src_x); /* src x1,y1 */
+ OUT_BATCH(src->stride);
+ OUT_RELOC(src->bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+}
+
+int main(int argc, char **argv)
+{
+ drm_intel_bufmgr *bufmgr;
+ struct intel_batchbuffer *batch;
+ render_copyfunc_t copy;
+ int fd, fails = 0;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ fails += check_ring(bufmgr, batch, "blt", blt_copy);
+
+ /* Strictly only required on architectures with a separate BLT ring,
+ * but lets stress everybody.
+ */
+ copy = NULL;
+ if (IS_GEN2(batch->devid))
+ copy = gen2_render_copyfunc;
+ else if (IS_GEN3(batch->devid))
+ copy = gen3_render_copyfunc;
+ else if (IS_GEN6(batch->devid))
+ copy = gen6_render_copyfunc;
+ if (copy)
+ fails += check_ring(bufmgr, batch, "render", copy);
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return fails != 0;
+}
diff --git a/tests/gem_set_tiling_vs_blt.c b/tests/gem_set_tiling_vs_blt.c
new file mode 100644
index 00000000..5fa90d49
--- /dev/null
+++ b/tests/gem_set_tiling_vs_blt.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+/** @file gem_set_tiling_vs_blt.c
+ *
+ * Testcase: Check for proper synchronization of tiling changes vs. tiled gpu
+ * access
+ *
+ * The blitter on gen3 and earlier needs properly set up fences. Which also
+ * means that for untiled blits we may not set up a fence before that blt has
+ * finished.
+ *
+ * Current kernels have a bug there, but it's pretty hard to hit because you
+ * need:
+ * - a blt on an untiled object which is aligned correctly for tiling.
+ * - a set_tiling to switch that object to tiling
+ * - another blt without any intervening cpu access that uses this object.
+ *
+ * Testcase has been extended to also check tiled->untiled and tiled->tiled
+ * transitions (i.e. changing stride).
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdbool.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+uint32_t devid;
+
+#define TEST_SIZE (1024*1024)
+#define TEST_STRIDE (4*1024)
+#define TEST_HEIGHT(stride) (TEST_SIZE/(stride))
+#define TEST_WIDTH(stride) ((stride)/4)
+
+uint32_t data[TEST_SIZE/4];
+
+static void do_test(uint32_t tiling, unsigned stride,
+ uint32_t tiling_after, unsigned stride_after)
+{
+ drm_intel_bo *busy_bo, *test_bo, *target_bo;
+ int i, ret;
+ uint32_t *ptr;
+ uint32_t test_bo_handle;
+ uint32_t blt_stride, blt_bits;
+ bool tiling_changed = false;
+
+ printf("filling ring .. ");
+ busy_bo = drm_intel_bo_alloc(bufmgr, "busy bo bo", 16*1024*1024, 4096);
+
+ for (i = 0; i < 250; i++) {
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ 2*1024*4);
+ OUT_BATCH(0 << 16 | 1024);
+ OUT_BATCH((2048) << 16 | (2048));
+ OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(2*1024*4);
+ OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ BEGIN_BATCH(3);
+ OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ }
+ }
+ intel_batchbuffer_flush(batch);
+
+ printf("playing tricks .. ");
+ /* first allocate the target so it gets out of the way of playing funky
+ * tricks */
+ target_bo = drm_intel_bo_alloc(bufmgr, "target bo", TEST_SIZE, 4096);
+
+ /* allocate buffer with parameters _after_ transition we want to check
+ * and touch it, so that it's properly aligned in the gtt. */
+ test_bo = drm_intel_bo_alloc(bufmgr, "tiled busy bo", TEST_SIZE, 4096);
+ test_bo_handle = test_bo->handle;
+ ret = drm_intel_bo_set_tiling(test_bo, &tiling_after, stride_after);
+ assert(ret == 0);
+ drm_intel_gem_bo_map_gtt(test_bo);
+ ptr = test_bo->virtual;
+ *ptr = 0;
+ ptr = NULL;
+ drm_intel_gem_bo_unmap_gtt(test_bo);
+
+ drm_intel_bo_unreference(test_bo);
+
+ test_bo = NULL;
+
+ /* note we need a bo bigger than batches, otherwise the buffer reuse
+ * trick will fail. */
+ test_bo = drm_intel_bo_alloc(bufmgr, "busy bo", TEST_SIZE, 4096);
+ if (test_bo_handle != test_bo->handle)
+ fprintf(stderr, "libdrm reuse trick failed\n");
+ test_bo_handle = test_bo->handle;
+ /* ensure we have the right tiling before we start. */
+ ret = drm_intel_bo_set_tiling(test_bo, &tiling, stride);
+ assert(ret == 0);
+
+ if (tiling == I915_TILING_NONE) {
+ drm_intel_bo_subdata(test_bo, 0, TEST_SIZE, data);
+ } else {
+ drm_intel_gem_bo_map_gtt(test_bo);
+ ptr = test_bo->virtual;
+ memcpy(ptr, data, TEST_SIZE);
+ ptr = NULL;
+ drm_intel_gem_bo_unmap_gtt(test_bo);
+ }
+
+ blt_stride = stride;
+ blt_bits = 0;
+ if (intel_gen(devid) >= 4 && tiling != I915_TILING_NONE) {
+ blt_stride /= 4;
+ blt_bits = XY_SRC_COPY_BLT_SRC_TILED;
+ }
+
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ blt_bits |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ stride);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH((TEST_HEIGHT(stride)) << 16 | (TEST_WIDTH(stride)));
+ OUT_RELOC_FENCED(target_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(blt_stride);
+ OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+ intel_batchbuffer_flush(batch);
+
+ drm_intel_bo_unreference(test_bo);
+
+ test_bo = drm_intel_bo_alloc_for_render(bufmgr, "tiled busy bo", TEST_SIZE, 4096);
+ if (test_bo_handle != test_bo->handle)
+ fprintf(stderr, "libdrm reuse trick failed\n");
+ ret = drm_intel_bo_set_tiling(test_bo, &tiling_after, stride_after);
+ assert(ret == 0);
+
+ /* Note: We don't care about gen4+ here because the blitter doesn't use
+ * fences there. So not setting tiling flags on the tiled buffer is ok.
+ */
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ stride_after);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH((1) << 16 | (1));
+ OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(stride_after);
+ OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+ intel_batchbuffer_flush(batch);
+
+ /* Now try to trick the kernel the kernel into changing up the fencing
+ * too early. */
+
+ printf("checking .. ");
+ memset(data, 0, TEST_SIZE);
+ drm_intel_bo_get_subdata(target_bo, 0, TEST_SIZE, data);
+ for (i = 0; i < TEST_SIZE/4; i++)
+ assert(data[i] == i);
+
+ /* check whether tiling on the test_bo actually changed. */
+ drm_intel_gem_bo_map_gtt(test_bo);
+ ptr = test_bo->virtual;
+ for (i = 0; i < TEST_SIZE/4; i++)
+ if (ptr[i] != data[i])
+ tiling_changed = true;
+ ptr = NULL;
+ drm_intel_gem_bo_unmap_gtt(test_bo);
+ assert(tiling_changed);
+
+ drm_intel_bo_unreference(test_bo);
+ drm_intel_bo_unreference(target_bo);
+ drm_intel_bo_unreference(busy_bo);
+ printf("done\n");
+}
+
+int main(int argc, char **argv)
+{
+ int i, fd;
+ uint32_t tiling, tiling_after;
+
+ for (i = 0; i < 1024*256; i++)
+ data[i] = i;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ devid = intel_get_drm_devid(fd);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+
+ printf("testing untiled->tiled transisition:\n");
+ tiling = I915_TILING_NONE;
+ tiling_after = I915_TILING_X;
+ do_test(tiling, TEST_STRIDE, tiling_after, TEST_STRIDE);
+ assert(tiling == I915_TILING_NONE);
+ assert(tiling_after == I915_TILING_X);
+
+ printf("testing tiled->untiled transisition:\n");
+ tiling = I915_TILING_X;
+ tiling_after = I915_TILING_NONE;
+ do_test(tiling, TEST_STRIDE, tiling_after, TEST_STRIDE);
+ assert(tiling == I915_TILING_X);
+ assert(tiling_after == I915_TILING_NONE);
+
+ printf("testing tiled->tiled transisition:\n");
+ tiling = I915_TILING_X;
+ tiling_after = I915_TILING_X;
+ do_test(tiling, TEST_STRIDE/2, tiling_after, TEST_STRIDE);
+ assert(tiling == I915_TILING_X);
+ assert(tiling_after == I915_TILING_X);
+
+ return 0;
+}
diff --git a/tests/gem_set_tiling_vs_gtt.c b/tests/gem_set_tiling_vs_gtt.c
new file mode 100644
index 00000000..1241b54d
--- /dev/null
+++ b/tests/gem_set_tiling_vs_gtt.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#define OBJECT_SIZE (1024*1024)
+#define TEST_STRIDE (1024*4)
+
+/**
+ * Testcase: Check set_tiling vs gtt mmap coherency
+ */
+
+int main(int argc, char **argv)
+{
+ int fd;
+ uint32_t *ptr;
+ uint32_t data[OBJECT_SIZE/4];
+ int i;
+ uint32_t handle;
+ bool tiling_changed;
+ int tile_height;
+
+ fd = drm_open_any();
+
+ if (IS_GEN2(intel_get_drm_devid(fd)))
+ tile_height = 16;
+ else
+ tile_height = 8;
+
+ handle = gem_create(fd, OBJECT_SIZE);
+ ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
+ assert(ptr);
+
+ /* gtt coherency is done with set_domain in libdrm, don't break that */
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ for (i = 0; i < OBJECT_SIZE/4; i++)
+ ptr[i] = data[i] = i;
+
+ gem_set_tiling(fd, handle, I915_TILING_X, TEST_STRIDE);
+
+ printf("testing untiled->tiled\n");
+ tiling_changed = false;
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, 0);
+ /* Too lazy to check for the correct tiling, and impossible anyway on
+ * bit17 swizzling machines. */
+ for (i = 0; i < OBJECT_SIZE/4; i++)
+ if (ptr[i] != data[i])
+ tiling_changed = true;
+ assert(tiling_changed);
+
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ for (i = 0; i < OBJECT_SIZE/4; i++)
+ ptr[i] = data[i] = i;
+
+ gem_set_tiling(fd, handle, I915_TILING_X, TEST_STRIDE*2);
+
+ printf("testing tiled->tiled\n");
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, 0);
+ for (i = 0; i < OBJECT_SIZE/4; i++) {
+ int tile_row = i / (TEST_STRIDE * tile_height / 4);
+ int row = i / (TEST_STRIDE * 2 / 4);
+ int half = i & (TEST_STRIDE / 4);
+ int ofs = i % (TEST_STRIDE / 4);
+ int data_i = (tile_row/2)*(TEST_STRIDE * tile_height / 4)
+ + row*TEST_STRIDE/4
+ + half*tile_height + ofs;
+ uint32_t val = data[data_i];
+
+ if (ptr[i] != val) {
+ printf("mismatch at %i, row=%i, half=%i, ofs=%i\n",
+ i, row, half, ofs);
+ printf("read: 0x%08x, expected: 0x%08x\n",
+ ptr[i], val);
+ assert(0);
+ }
+
+ }
+
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ for (i = 0; i < OBJECT_SIZE/4; i++)
+ ptr[i] = data[i] = i;
+
+ gem_set_tiling(fd, handle, I915_TILING_NONE, 0);
+ printf("testing tiled->untiled\n");
+ tiling_changed = false;
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, 0);
+ /* Too lazy to check for the correct tiling, and impossible anyway on
+ * bit17 swizzling machines. */
+ for (i = 0; i < OBJECT_SIZE/4; i++)
+ if (ptr[i] != data[i])
+ tiling_changed = true;
+ assert(tiling_changed);
+
+ munmap(ptr, OBJECT_SIZE);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_set_tiling_vs_pwrite.c b/tests/gem_set_tiling_vs_pwrite.c
new file mode 100644
index 00000000..35ec5cdc
--- /dev/null
+++ b/tests/gem_set_tiling_vs_pwrite.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#define OBJECT_SIZE (1024*1024)
+#define TEST_STRIDE (1024*4)
+
+/**
+ * Testcase: Check set_tiling vs pwrite coherency
+ */
+
+int main(int argc, char **argv)
+{
+ int fd;
+ uint32_t *ptr;
+ uint32_t data[OBJECT_SIZE/4];
+ int i;
+ uint32_t handle;
+
+ fd = drm_open_any();
+
+ for (i = 0; i < OBJECT_SIZE/4; i++)
+ data[i] = i;
+
+ handle = gem_create(fd, OBJECT_SIZE);
+ ptr = gem_mmap(fd, handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
+ assert(ptr);
+
+ gem_set_tiling(fd, handle, I915_TILING_X, TEST_STRIDE);
+
+ /* touch it */
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ *ptr = 0xdeadbeef;
+
+ printf("testing pwrite on tiled buffer\n");
+ gem_write(fd, handle, 0, data, OBJECT_SIZE);
+ memset(data, 0, OBJECT_SIZE);
+ gem_read(fd, handle, 0, data, OBJECT_SIZE);
+ for (i = 0; i < OBJECT_SIZE/4; i++)
+ assert(i == data[i]);
+
+ /* touch it before changing the tiling, so that the fence sticks around */
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ *ptr = 0xdeadbeef;
+
+ gem_set_tiling(fd, handle, I915_TILING_NONE, 0);
+
+ printf("testing pwrite on untiled, but still fenced buffer\n");
+ gem_write(fd, handle, 0, data, OBJECT_SIZE);
+ memset(data, 0, OBJECT_SIZE);
+ gem_read(fd, handle, 0, data, OBJECT_SIZE);
+ for (i = 0; i < OBJECT_SIZE/4; i++)
+ assert(i == data[i]);
+
+ munmap(ptr, OBJECT_SIZE);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_storedw_batches_loop.c b/tests/gem_storedw_batches_loop.c
new file mode 100644
index 00000000..8cf5f719
--- /dev/null
+++ b/tests/gem_storedw_batches_loop.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Jesse Barnes <jbarnes@virtuousgeek.org> (based on gem_bad_blit.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+static drm_intel_bo *target_bo;
+static int has_ppgtt = 0;
+
+/* Like the store dword test, but we create new command buffers each time */
+static void
+store_dword_loop(void)
+{
+ int cmd, i, val = 0, ret;
+ uint32_t *buf;
+ drm_intel_bo *cmd_bo;
+
+ cmd = MI_STORE_DWORD_IMM;
+ if (!has_ppgtt)
+ cmd |= MI_MEM_VIRTUAL;
+
+ for (i = 0; i < 0x80000; i++) {
+ cmd_bo = drm_intel_bo_alloc(bufmgr, "cmd bo", 4096, 4096);
+ if (!cmd_bo) {
+ fprintf(stderr, "failed to alloc cmd bo\n");
+ exit(-1);
+ }
+
+ drm_intel_bo_map(cmd_bo, 1);
+ buf = cmd_bo->virtual;
+
+ buf[0] = cmd;
+ buf[1] = 0;
+ buf[2] = target_bo->offset;
+ buf[3] = 0x42000000 + val;
+
+ ret = drm_intel_bo_references(cmd_bo, target_bo);
+ if (ret) {
+ fprintf(stderr, "failed to link cmd & target bos\n");
+ exit(-1);
+ }
+
+ ret = drm_intel_bo_emit_reloc(cmd_bo, 8, target_bo, 0,
+ I915_GEM_DOMAIN_INSTRUCTION,
+ I915_GEM_DOMAIN_INSTRUCTION);
+ if (ret) {
+ fprintf(stderr, "failed to emit reloc\n");
+ exit(-1);
+ }
+
+ buf[4] = MI_BATCH_BUFFER_END;
+ buf[5] = MI_BATCH_BUFFER_END;
+
+ drm_intel_bo_unmap(cmd_bo);
+
+ ret = drm_intel_bo_references(cmd_bo, target_bo);
+ if (ret != 1) {
+ fprintf(stderr, "bad bo reference count: %d\n", ret);
+ exit(-1);
+ }
+
+ ret = drm_intel_bo_exec(cmd_bo, 6 * 4, NULL, 0, 0);
+ if (ret) {
+ fprintf(stderr, "bo exec failed: %d\n", ret);
+ exit(-1);
+ }
+
+ drm_intel_bo_wait_rendering(cmd_bo);
+
+ drm_intel_bo_map(target_bo, 1);
+
+ buf = target_bo->virtual;
+ if (buf[0] != (0x42000000 | val)) {
+ fprintf(stderr,
+ "value mismatch: cur 0x%08x, stored 0x%08x\n",
+ buf[0], 0x42000000 | val);
+ exit(-1);
+ }
+ buf[0] = 0; /* let batch write it again */
+ drm_intel_bo_unmap(target_bo);
+
+ drm_intel_bo_unreference(cmd_bo);
+
+ val++;
+ }
+
+ printf("completed %d writes successfully\n", i);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int devid;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: %s\n", argv[0]);
+ exit(-1);
+ }
+
+ fd = drm_open_any();
+ devid = intel_get_drm_devid(fd);
+
+ has_ppgtt = gem_uses_aliasing_ppgtt(fd);
+
+ if (IS_GEN2(devid) || IS_GEN3(devid) || IS_GEN4(devid) || IS_GEN5(devid)) {
+
+ fprintf(stderr, "MI_STORE_DATA can only use GTT address on gen4+/g33 and"
+ "needs snoopable mem on pre-gen6\n");
+ return 77;
+ }
+
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+// drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ target_bo = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
+ if (!target_bo) {
+ fprintf(stderr, "failed to alloc target buffer\n");
+ exit(-1);
+ }
+
+ store_dword_loop();
+
+ drm_intel_bo_unreference(target_bo);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_storedw_loop_blt.c b/tests/gem_storedw_loop_blt.c
new file mode 100644
index 00000000..dda9b835
--- /dev/null
+++ b/tests/gem_storedw_loop_blt.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Jesse Barnes <jbarnes@virtuousgeek.org> (based on gem_bad_blit.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static drm_intel_bo *target_buffer;
+static int has_ppgtt = 0;
+
+/*
+ * Testcase: Basic blitter MI check using MI_STORE_DATA_IMM
+ */
+
+static void
+store_dword_loop(void)
+{
+ int cmd, i, val = 0;
+ uint32_t *buf;
+
+ cmd = MI_STORE_DWORD_IMM;
+ if (!has_ppgtt)
+ cmd |= MI_MEM_VIRTUAL;
+
+ for (i = 0; i < 0x100000; i++) {
+ BEGIN_BATCH(4);
+ OUT_BATCH(cmd);
+ OUT_BATCH(0); /* reserved */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_INSTRUCTION,
+ I915_GEM_DOMAIN_INSTRUCTION, 0);
+ OUT_BATCH(val);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush_on_ring(batch, I915_EXEC_BLT);
+
+ drm_intel_bo_map(target_buffer, 0);
+
+ buf = target_buffer->virtual;
+ if (buf[0] != val) {
+ fprintf(stderr,
+ "value mismatch: cur 0x%08x, stored 0x%08x\n",
+ buf[0], val);
+ exit(-1);
+ }
+
+ drm_intel_bo_unmap(target_buffer);
+
+ val++;
+ }
+
+ drm_intel_bo_map(target_buffer, 0);
+ buf = target_buffer->virtual;
+
+ printf("completed %d writes successfully, current value: 0x%08x\n", i,
+ buf[0]);
+ drm_intel_bo_unmap(target_buffer);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int devid;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: %s\n", argv[0]);
+ exit(-1);
+ }
+
+ fd = drm_open_any();
+ devid = intel_get_drm_devid(fd);
+
+ has_ppgtt = gem_uses_aliasing_ppgtt(fd);
+
+ if (IS_GEN2(devid) || IS_GEN3(devid) || IS_GEN4(devid) || IS_GEN5(devid)) {
+
+ fprintf(stderr, "MI_STORE_DATA can only use GTT address on gen4+/g33 and "
+ "needs snoopable mem on pre-gen6\n");
+ return 77;
+ }
+
+ /* This only works with ppgtt */
+ if (!has_ppgtt) {
+ fprintf(stderr, "no ppgtt detected, which is required\n");
+ return 77;
+ }
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+ if (!batch) {
+ fprintf(stderr, "failed to create batch buffer\n");
+ exit(-1);
+ }
+
+ target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
+ if (!target_buffer) {
+ fprintf(stderr, "failed to alloc target buffer\n");
+ exit(-1);
+ }
+
+ store_dword_loop();
+
+ drm_intel_bo_unreference(target_buffer);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_storedw_loop_bsd.c b/tests/gem_storedw_loop_bsd.c
new file mode 100644
index 00000000..d7c61047
--- /dev/null
+++ b/tests/gem_storedw_loop_bsd.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Jesse Barnes <jbarnes@virtuousgeek.org> (based on gem_bad_blit.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static drm_intel_bo *target_buffer;
+static int has_ppgtt = 0;
+
+/*
+ * Testcase: Basic bsd MI check using MI_STORE_DATA_IMM
+ */
+
+static void
+store_dword_loop(void)
+{
+ int cmd, i, val = 0;
+ uint32_t *buf;
+
+ cmd = MI_STORE_DWORD_IMM;
+ if (!has_ppgtt)
+ cmd |= MI_MEM_VIRTUAL;
+
+ for (i = 0; i < 0x100000; i++) {
+ BEGIN_BATCH(4);
+ OUT_BATCH(cmd);
+ OUT_BATCH(0); /* reserved */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_INSTRUCTION,
+ I915_GEM_DOMAIN_INSTRUCTION, 0);
+ OUT_BATCH(val);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush_on_ring(batch, I915_EXEC_BSD);
+
+ drm_intel_bo_map(target_buffer, 0);
+
+ buf = target_buffer->virtual;
+ if (buf[0] != val) {
+ fprintf(stderr,
+ "value mismatch: cur 0x%08x, stored 0x%08x\n",
+ buf[0], val);
+ exit(-1);
+ }
+
+ drm_intel_bo_unmap(target_buffer);
+
+ val++;
+ }
+
+ drm_intel_bo_map(target_buffer, 0);
+ buf = target_buffer->virtual;
+
+ printf("completed %d writes successfully, current value: 0x%08x\n", i,
+ buf[0]);
+ drm_intel_bo_unmap(target_buffer);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int devid;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: %s\n", argv[0]);
+ exit(-1);
+ }
+
+ fd = drm_open_any();
+ devid = intel_get_drm_devid(fd);
+
+ has_ppgtt = gem_uses_aliasing_ppgtt(fd);
+
+ if (IS_GEN2(devid) || IS_GEN3(devid) || IS_GEN4(devid) || IS_GEN5(devid)) {
+
+ fprintf(stderr, "MI_STORE_DATA can only use GTT address on gen4+/g33 and "
+ "needs snoopable mem on pre-gen6\n");
+ return 77;
+ }
+
+ if (IS_GEN6(devid)) {
+
+ fprintf(stderr, "MI_STORE_DATA broken on gen6 bsd\n");
+ return 77;
+ }
+
+ /* This only works with ppgtt */
+ if (!has_ppgtt) {
+ fprintf(stderr, "no ppgtt detected, which is required\n");
+ return 77;
+ }
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+ if (!batch) {
+ fprintf(stderr, "failed to create batch buffer\n");
+ exit(-1);
+ }
+
+ target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
+ if (!target_buffer) {
+ fprintf(stderr, "failed to alloc target buffer\n");
+ exit(-1);
+ }
+
+ store_dword_loop();
+
+ drm_intel_bo_unreference(target_buffer);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_storedw_loop_render.c b/tests/gem_storedw_loop_render.c
new file mode 100644
index 00000000..19a41b65
--- /dev/null
+++ b/tests/gem_storedw_loop_render.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Jesse Barnes <jbarnes@virtuousgeek.org> (based on gem_bad_blit.c)
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static drm_intel_bo *target_buffer;
+static int has_ppgtt = 0;
+
+/*
+ * Testcase: Basic render MI check using MI_STORE_DATA_IMM
+ */
+
+static void
+store_dword_loop(void)
+{
+ int cmd, i, val = 0;
+ uint32_t *buf;
+
+ cmd = MI_STORE_DWORD_IMM;
+ if (!has_ppgtt)
+ cmd |= MI_MEM_VIRTUAL;
+
+ for (i = 0; i < 0x100000; i++) {
+ BEGIN_BATCH(4);
+ OUT_BATCH(cmd);
+ OUT_BATCH(0); /* reserved */
+ OUT_RELOC(target_buffer, I915_GEM_DOMAIN_INSTRUCTION,
+ I915_GEM_DOMAIN_INSTRUCTION, 0);
+ OUT_BATCH(val);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush_on_ring(batch, 0);
+
+ drm_intel_bo_map(target_buffer, 0);
+
+ buf = target_buffer->virtual;
+ if (buf[0] != val) {
+ fprintf(stderr,
+ "value mismatch: cur 0x%08x, stored 0x%08x\n",
+ buf[0], val);
+ exit(-1);
+ }
+
+ drm_intel_bo_unmap(target_buffer);
+
+ val++;
+ }
+
+ drm_intel_bo_map(target_buffer, 0);
+ buf = target_buffer->virtual;
+
+ printf("completed %d writes successfully, current value: 0x%08x\n", i,
+ buf[0]);
+ drm_intel_bo_unmap(target_buffer);
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ int devid;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: %s\n", argv[0]);
+ exit(-1);
+ }
+
+ fd = drm_open_any();
+ devid = intel_get_drm_devid(fd);
+
+ has_ppgtt = gem_uses_aliasing_ppgtt(fd);
+
+ if (IS_GEN2(devid) || IS_GEN3(devid) || IS_GEN4(devid) || IS_GEN5(devid)) {
+
+ fprintf(stderr, "MI_STORE_DATA can only use GTT address on gen4+/g33 and "
+ "needs snoopable mem on pre-gen6\n");
+ return 77;
+ }
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+ if (!batch) {
+ fprintf(stderr, "failed to create batch buffer\n");
+ exit(-1);
+ }
+
+ target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
+ if (!target_buffer) {
+ fprintf(stderr, "failed to alloc target buffer\n");
+ exit(-1);
+ }
+
+ store_dword_loop();
+
+ drm_intel_bo_unreference(target_buffer);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_stress.c b/tests/gem_stress.c
new file mode 100644
index 00000000..69239ac1
--- /dev/null
+++ b/tests/gem_stress.c
@@ -0,0 +1,945 @@
+/*
+ * Copyright © 2011 Daniel Vetter
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ * Partially based upon gem_tiled_fence_blits.c
+ */
+
+/** @file gem_stress.c
+ *
+ * This is a general gem coherency test. It's designed to eventually replicate
+ * any possible sequence of access patterns. It works by copying a set of tiles
+ * between two sets of backing buffer objects, randomly permutating the assinged
+ * position on each copy operations.
+ *
+ * The copy operation are done in tiny portions (to reduce any race windows
+ * for corruptions, hence increasing the chances for observing one) and are
+ * constantly switched between all means to copy stuff (fenced blitter, unfenced
+ * render, mmap, pwrite/read).
+ *
+ * After every complete move of a set tiling parameters of a buffer are randomly
+ * changed to simulate the effects of libdrm caching.
+ *
+ * Buffers are 1mb big to nicely fit into fences on gen2/3. A few are further
+ * split up to test relaxed fencing. Using this to push the average working set
+ * size over the available gtt space forces objects to be mapped as unfenceable
+ * (and as a side-effect tests gtt map/unmap coherency).
+ *
+ * In short: designed for maximum evilness.
+ */
+
+#include "rendercopy.h"
+
+#define CMD_POLY_STIPPLE_OFFSET 0x7906
+
+/** TODO:
+ * - beat on relaxed fencing (i.e. mappable/fenceable tracking in the kernel)
+ * - render copy (to check fence tracking and cache coherency management by the
+ * kernel)
+ * - multi-threading: probably just a wrapper script to launch multiple
+ * instances + an option to accordingly reduce the working set
+ * - gen6 inter-ring coherency (needs render copy, first)
+ * - variable buffer size
+ * - add an option to fork a second process that randomly sends signals to the
+ * first one (to check consistency of the kernel recovery paths)
+ */
+
+drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+int drm_fd;
+int devid;
+int num_fences;
+
+drm_intel_bo *busy_bo;
+
+struct option_struct {
+ unsigned scratch_buf_size;
+ unsigned max_dimension;
+ unsigned num_buffers;
+ int trace_tile;
+ int no_hw;
+ int gpu_busy_load;
+ int use_render;
+ int use_blt;
+ int forced_tiling;
+ int use_cpu_maps;
+ int total_rounds;
+ int fail;
+ int tiles_per_buf;
+ int ducttape;
+ int tile_size;
+ int check_render_cpyfn;
+ int use_signal_helper;
+};
+
+struct option_struct options;
+
+#define MAX_BUFS 4096
+#define SCRATCH_BUF_SIZE 1024*1024
+#define BUSY_BUF_SIZE (256*4096)
+#define TILE_BYTES(size) ((size)*(size)*sizeof(uint32_t))
+
+static struct scratch_buf buffers[2][MAX_BUFS];
+/* tile i is at logical position tile_permutation[i] */
+static unsigned *tile_permutation;
+static unsigned num_buffers = 0;
+static unsigned current_set = 0;
+static unsigned target_set = 0;
+static unsigned num_total_tiles = 0;
+
+int fence_storm = 0;
+static int gpu_busy_load = 10;
+
+struct {
+ unsigned num_failed;
+ unsigned max_failed_reads;
+} stats;
+
+static void tile2xy(struct scratch_buf *buf, unsigned tile, unsigned *x, unsigned *y)
+{
+ assert(tile < buf->num_tiles);
+ *x = (tile*options.tile_size) % (buf->stride/sizeof(uint32_t));
+ *y = ((tile*options.tile_size) / (buf->stride/sizeof(uint32_t))) * options.tile_size;
+}
+
+static void emit_blt(drm_intel_bo *src_bo, uint32_t src_tiling, unsigned src_pitch,
+ unsigned src_x, unsigned src_y, unsigned w, unsigned h,
+ drm_intel_bo *dst_bo, uint32_t dst_tiling, unsigned dst_pitch,
+ unsigned dst_x, unsigned dst_y)
+{
+ uint32_t cmd_bits = 0;
+
+ if (IS_965(devid) && src_tiling) {
+ src_pitch /= 4;
+ cmd_bits |= XY_SRC_COPY_BLT_SRC_TILED;
+ }
+
+ if (IS_965(devid) && dst_tiling) {
+ dst_pitch /= 4;
+ cmd_bits |= XY_SRC_COPY_BLT_DST_TILED;
+ }
+
+ /* copy lower half to upper half */
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB |
+ cmd_bits);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ dst_pitch);
+ OUT_BATCH(dst_y << 16 | dst_x);
+ OUT_BATCH((dst_y+h) << 16 | (dst_x+w));
+ OUT_RELOC_FENCED(dst_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(src_y << 16 | src_x);
+ OUT_BATCH(src_pitch);
+ OUT_RELOC_FENCED(src_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ BEGIN_BATCH(3);
+ OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ }
+}
+
+/* All this gem trashing wastes too much cpu time, so give the gpu something to
+ * do to increase changes for races. */
+static void keep_gpu_busy(void)
+{
+ int tmp;
+
+ tmp = 1 << gpu_busy_load;
+ assert(tmp <= 1024);
+
+ emit_blt(busy_bo, 0, 4096, 0, 0, tmp, 128,
+ busy_bo, 0, 4096, 0, 128);
+}
+
+static void set_to_cpu_domain(struct scratch_buf *buf, int writing)
+{
+ gem_set_domain(drm_fd, buf->bo->handle, I915_GEM_DOMAIN_CPU,
+ writing ? I915_GEM_DOMAIN_CPU : 0);
+}
+
+static unsigned int copyfunc_seq = 0;
+static void (*copyfunc)(struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y,
+ unsigned logical_tile_no);
+
+/* stride, x, y in units of uint32_t! */
+static void cpucpy2d(uint32_t *src, unsigned src_stride, unsigned src_x, unsigned src_y,
+ uint32_t *dst, unsigned dst_stride, unsigned dst_x, unsigned dst_y,
+ unsigned logical_tile_no)
+{
+ int i, j;
+ int failed = 0;
+
+ for (i = 0; i < options.tile_size; i++) {
+ for (j = 0; j < options.tile_size; j++) {
+ unsigned dst_ofs = dst_x + j + dst_stride * (dst_y + i);
+ unsigned src_ofs = src_x + j + src_stride * (src_y + i);
+ unsigned expect = logical_tile_no*options.tile_size*options.tile_size
+ + i*options.tile_size + j;
+ uint32_t tmp = src[src_ofs];
+ if (tmp != expect) {
+ printf("mismatch at tile %i pos %i, read %i, expected %i, diff %i\n",
+ logical_tile_no, i*options.tile_size + j, tmp, expect, (int) tmp - expect);
+ if (options.trace_tile >= 0 && options.fail)
+ exit(1);
+ failed++;
+ }
+ /* when not aborting, correct any errors */
+ dst[dst_ofs] = expect;
+ }
+ }
+ if (failed && options.fail)
+ exit(1);
+
+ if (failed > stats.max_failed_reads)
+ stats.max_failed_reads = failed;
+ if (failed)
+ stats.num_failed++;
+}
+
+static void cpu_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y,
+ unsigned logical_tile_no)
+{
+ assert(batch->ptr == batch->buffer);
+
+ if (options.ducttape)
+ drm_intel_bo_wait_rendering(dst->bo);
+
+ if (options.use_cpu_maps) {
+ set_to_cpu_domain(src, 0);
+ set_to_cpu_domain(dst, 1);
+ }
+
+ cpucpy2d(src->data, src->stride/sizeof(uint32_t), src_x, src_y,
+ dst->data, dst->stride/sizeof(uint32_t), dst_x, dst_y,
+ logical_tile_no);
+}
+
+static void prw_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y,
+ unsigned logical_tile_no)
+{
+ uint32_t tmp_tile[options.tile_size*options.tile_size];
+ int i;
+
+ assert(batch->ptr == batch->buffer);
+
+ if (options.ducttape)
+ drm_intel_bo_wait_rendering(dst->bo);
+
+ if (src->tiling == I915_TILING_NONE) {
+ for (i = 0; i < options.tile_size; i++) {
+ unsigned ofs = src_x*sizeof(uint32_t) + src->stride*(src_y + i);
+ drm_intel_bo_get_subdata(src->bo, ofs,
+ options.tile_size*sizeof(uint32_t),
+ tmp_tile + options.tile_size*i);
+ }
+ } else {
+ if (options.use_cpu_maps)
+ set_to_cpu_domain(src, 0);
+
+ cpucpy2d(src->data, src->stride/sizeof(uint32_t), src_x, src_y,
+ tmp_tile, options.tile_size, 0, 0, logical_tile_no);
+ }
+
+ if (dst->tiling == I915_TILING_NONE) {
+ for (i = 0; i < options.tile_size; i++) {
+ unsigned ofs = dst_x*sizeof(uint32_t) + dst->stride*(dst_y + i);
+ drm_intel_bo_subdata(dst->bo, ofs,
+ options.tile_size*sizeof(uint32_t),
+ tmp_tile + options.tile_size*i);
+ }
+ } else {
+ if (options.use_cpu_maps)
+ set_to_cpu_domain(dst, 1);
+
+ cpucpy2d(tmp_tile, options.tile_size, 0, 0,
+ dst->data, dst->stride/sizeof(uint32_t), dst_x, dst_y,
+ logical_tile_no);
+ }
+}
+
+static void blitter_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y,
+ unsigned logical_tile_no)
+{
+ static unsigned keep_gpu_busy_counter = 0;
+
+ /* check both edges of the fence usage */
+ if (keep_gpu_busy_counter & 1 && !fence_storm)
+ keep_gpu_busy();
+
+ emit_blt(src->bo, src->tiling, src->stride, src_x, src_y,
+ options.tile_size, options.tile_size,
+ dst->bo, dst->tiling, dst->stride, dst_x, dst_y);
+
+ if (!(keep_gpu_busy_counter & 1) && !fence_storm)
+ keep_gpu_busy();
+
+ keep_gpu_busy_counter++;
+
+ if (src->tiling)
+ fence_storm--;
+ if (dst->tiling)
+ fence_storm--;
+
+ if (fence_storm <= 1) {
+ fence_storm = 0;
+ intel_batchbuffer_flush(batch);
+ }
+}
+
+static void render_copyfunc(struct scratch_buf *src, unsigned src_x, unsigned src_y,
+ struct scratch_buf *dst, unsigned dst_x, unsigned dst_y,
+ unsigned logical_tile_no)
+{
+ static unsigned keep_gpu_busy_counter = 0;
+
+ /* check both edges of the fence usage */
+ if (keep_gpu_busy_counter & 1)
+ keep_gpu_busy();
+
+ if (IS_GEN2(devid))
+ gen2_render_copyfunc(batch,
+ src, src_x, src_y,
+ options.tile_size, options.tile_size,
+ dst, dst_x, dst_y);
+ else if (IS_GEN3(devid))
+ gen3_render_copyfunc(batch,
+ src, src_x, src_y,
+ options.tile_size, options.tile_size,
+ dst, dst_x, dst_y);
+ else if (IS_GEN6(devid))
+ gen6_render_copyfunc(batch,
+ src, src_x, src_y,
+ options.tile_size, options.tile_size,
+ dst, dst_x, dst_y);
+ else if (IS_GEN7(devid))
+ gen7_render_copyfunc(batch,
+ src, src_x, src_y,
+ options.tile_size, options.tile_size,
+ dst, dst_x, dst_y);
+ else
+ blitter_copyfunc(src, src_x, src_y,
+ dst, dst_x, dst_y,
+ logical_tile_no);
+ if (!(keep_gpu_busy_counter & 1))
+ keep_gpu_busy();
+
+ keep_gpu_busy_counter++;
+ intel_batchbuffer_flush(batch);
+}
+
+static void next_copyfunc(int tile)
+{
+ if (fence_storm) {
+ if (tile == options.trace_tile)
+ printf(" using fence storm\n");
+ return;
+ }
+
+ if (copyfunc_seq % 61 == 0
+ && options.forced_tiling != I915_TILING_NONE) {
+ if (tile == options.trace_tile)
+ printf(" using fence storm\n");
+ fence_storm = num_fences;
+ copyfunc = blitter_copyfunc;
+ } else if (copyfunc_seq % 17 == 0) {
+ if (tile == options.trace_tile)
+ printf(" using cpu\n");
+ copyfunc = cpu_copyfunc;
+ } else if (copyfunc_seq % 19 == 0) {
+ if (tile == options.trace_tile)
+ printf(" using prw\n");
+ copyfunc = prw_copyfunc;
+ } else if (copyfunc_seq % 3 == 0 && options.use_render) {
+ if (tile == options.trace_tile)
+ printf(" using render\n");
+ copyfunc = render_copyfunc;
+ } else if (options.use_blt){
+ if (tile == options.trace_tile)
+ printf(" using blitter\n");
+ copyfunc = blitter_copyfunc;
+ } else if (options.use_render){
+ if (tile == options.trace_tile)
+ printf(" using render\n");
+ copyfunc = render_copyfunc;
+ } else {
+ copyfunc = cpu_copyfunc;
+ }
+
+ copyfunc_seq++;
+}
+
+static void fan_out(void)
+{
+ uint32_t tmp_tile[options.tile_size*options.tile_size];
+ uint32_t seq = 0;
+ int i, k;
+ unsigned tile, buf_idx, x, y;
+
+ for (i = 0; i < num_total_tiles; i++) {
+ tile = i;
+ buf_idx = tile / options.tiles_per_buf;
+ tile %= options.tiles_per_buf;
+
+ tile2xy(&buffers[current_set][buf_idx], tile, &x, &y);
+
+ for (k = 0; k < options.tile_size*options.tile_size; k++)
+ tmp_tile[k] = seq++;
+
+ if (options.use_cpu_maps)
+ set_to_cpu_domain(&buffers[current_set][buf_idx], 1);
+
+ cpucpy2d(tmp_tile, options.tile_size, 0, 0,
+ buffers[current_set][buf_idx].data,
+ buffers[current_set][buf_idx].stride / sizeof(uint32_t),
+ x, y, i);
+ }
+
+ for (i = 0; i < num_total_tiles; i++)
+ tile_permutation[i] = i;
+}
+
+static void fan_in_and_check(void)
+{
+ uint32_t tmp_tile[options.tile_size*options.tile_size];
+ unsigned tile, buf_idx, x, y;
+ int i;
+ for (i = 0; i < num_total_tiles; i++) {
+ tile = tile_permutation[i];
+ buf_idx = tile / options.tiles_per_buf;
+ tile %= options.tiles_per_buf;
+
+ tile2xy(&buffers[current_set][buf_idx], tile, &x, &y);
+
+ if (options.use_cpu_maps)
+ set_to_cpu_domain(&buffers[current_set][buf_idx], 0);
+
+ cpucpy2d(buffers[current_set][buf_idx].data,
+ buffers[current_set][buf_idx].stride / sizeof(uint32_t),
+ x, y,
+ tmp_tile, options.tile_size, 0, 0,
+ i);
+ }
+}
+
+static void sanitize_stride(struct scratch_buf *buf)
+{
+
+ if (buf_height(buf) > options.max_dimension)
+ buf->stride = buf->size / options.max_dimension;
+
+ if (buf_height(buf) < options.tile_size)
+ buf->stride = buf->size / options.tile_size;
+
+ if (buf_width(buf) < options.tile_size)
+ buf->stride = options.tile_size * sizeof(uint32_t);
+
+ assert(buf->stride <= 8192);
+ assert(buf_width(buf) <= options.max_dimension);
+ assert(buf_height(buf) <= options.max_dimension);
+
+ assert(buf_width(buf) >= options.tile_size);
+ assert(buf_height(buf) >= options.tile_size);
+
+}
+
+static void init_buffer(struct scratch_buf *buf, unsigned size)
+{
+ buf->bo = drm_intel_bo_alloc(bufmgr, "tiled bo", size, 4096);
+ buf->size = size;
+ assert(buf->bo);
+ buf->tiling = I915_TILING_NONE;
+ buf->stride = 4096;
+
+ sanitize_stride(buf);
+
+ if (options.no_hw)
+ buf->data = malloc(size);
+ else {
+ if (options.use_cpu_maps)
+ drm_intel_bo_map(buf->bo, 1);
+ else
+ drm_intel_gem_bo_map_gtt(buf->bo);
+ buf->data = buf->bo->virtual;
+ }
+
+ buf->num_tiles = options.tiles_per_buf;
+}
+
+static void exchange_buf(void *array, unsigned i, unsigned j)
+{
+ struct scratch_buf *buf_arr, tmp;
+ buf_arr = array;
+
+ memcpy(&tmp, &buf_arr[i], sizeof(struct scratch_buf));
+ memcpy(&buf_arr[i], &buf_arr[j], sizeof(struct scratch_buf));
+ memcpy(&buf_arr[j], &tmp, sizeof(struct scratch_buf));
+}
+
+
+static void init_set(unsigned set)
+{
+ long int r;
+ int i;
+
+ drmtest_permute_array(buffers[set], num_buffers, exchange_buf);
+
+ if (current_set == 1 && options.gpu_busy_load == 0) {
+ gpu_busy_load++;
+ if (gpu_busy_load > 10)
+ gpu_busy_load = 6;
+ }
+
+ for (i = 0; i < num_buffers; i++) {
+ r = random();
+ if ((r & 3) != 0)
+ continue;
+ r >>= 2;
+
+ if ((r & 3) != 0)
+ buffers[set][i].tiling = I915_TILING_X;
+ else
+ buffers[set][i].tiling = I915_TILING_NONE;
+ r >>= 2;
+ if (options.forced_tiling >= 0)
+ buffers[set][i].tiling = options.forced_tiling;
+
+ if (buffers[set][i].tiling == I915_TILING_NONE) {
+ /* min 64 byte stride */
+ r %= 8;
+ buffers[set][i].stride = 64 * (1 << r);
+ } else if (IS_GEN2(devid)) {
+ /* min 128 byte stride */
+ r %= 7;
+ buffers[set][i].stride = 128 * (1 << r);
+ } else {
+ /* min 512 byte stride */
+ r %= 5;
+ buffers[set][i].stride = 512 * (1 << r);
+ }
+
+ sanitize_stride(&buffers[set][i]);
+
+ gem_set_tiling(drm_fd, buffers[set][i].bo->handle,
+ buffers[set][i].tiling,
+ buffers[set][i].stride);
+
+ if (options.trace_tile != -1 && i == options.trace_tile/options.tiles_per_buf)
+ printf("changing buffer %i containing tile %i: tiling %i, stride %i\n", i,
+ options.trace_tile,
+ buffers[set][i].tiling, buffers[set][i].stride);
+ }
+}
+
+static void exchange_uint(void *array, unsigned i, unsigned j)
+{
+ unsigned *i_arr = array;
+ unsigned i_tmp;
+
+ i_tmp = i_arr[i];
+ i_arr[i] = i_arr[j];
+ i_arr[j] = i_tmp;
+}
+
+static void copy_tiles(unsigned *permutation)
+{
+ unsigned src_tile, src_buf_idx, src_x, src_y;
+ unsigned dst_tile, dst_buf_idx, dst_x, dst_y;
+ struct scratch_buf *src_buf, *dst_buf;
+ int i, idx;
+ for (i = 0; i < num_total_tiles; i++) {
+ /* tile_permutation is independent of current_permutation, so
+ * abuse it to randomize the order of the src bos */
+ idx = tile_permutation[i];
+ src_buf_idx = idx / options.tiles_per_buf;
+ src_tile = idx % options.tiles_per_buf;
+ src_buf = &buffers[current_set][src_buf_idx];
+
+ tile2xy(src_buf, src_tile, &src_x, &src_y);
+
+ dst_buf_idx = permutation[idx] / options.tiles_per_buf;
+ dst_tile = permutation[idx] % options.tiles_per_buf;
+ dst_buf = &buffers[target_set][dst_buf_idx];
+
+ tile2xy(dst_buf, dst_tile, &dst_x, &dst_y);
+
+ if (options.trace_tile == i)
+ printf("copying tile %i from %i (%i, %i) to %i (%i, %i)", i,
+ tile_permutation[i], src_buf_idx, src_tile,
+ permutation[idx], dst_buf_idx, dst_tile);
+
+ if (options.no_hw) {
+ cpucpy2d(src_buf->data,
+ src_buf->stride / sizeof(uint32_t),
+ src_x, src_y,
+ dst_buf->data,
+ dst_buf->stride / sizeof(uint32_t),
+ dst_x, dst_y,
+ i);
+ } else {
+ next_copyfunc(i);
+
+ copyfunc(src_buf, src_x, src_y, dst_buf, dst_x, dst_y,
+ i);
+ }
+ }
+
+ intel_batchbuffer_flush(batch);
+}
+
+static int get_num_fences(void)
+{
+ drm_i915_getparam_t gp;
+ int ret, val;
+
+ gp.param = I915_PARAM_NUM_FENCES_AVAIL;
+ gp.value = &val;
+ ret = drmIoctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+ assert (ret == 0);
+
+ printf ("total %d fences\n", val);
+ assert(val > 4);
+
+ return val - 2;
+}
+
+static void sanitize_tiles_per_buf(void)
+{
+ if (options.tiles_per_buf > options.scratch_buf_size / TILE_BYTES(options.tile_size))
+ options.tiles_per_buf = options.scratch_buf_size / TILE_BYTES(options.tile_size);
+}
+
+static void parse_options(int argc, char **argv)
+{
+ int c, tmp;
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"no-hw", 0, 0, 'd'},
+ {"buf-size", 1, 0, 's'},
+ {"gpu-busy-load", 1, 0, 'g'},
+ {"no-signals", 0, 0, 'S'},
+ {"buffer-count", 1, 0, 'c'},
+ {"trace-tile", 1, 0, 't'},
+ {"disable-blt", 0, 0, 'b'},
+ {"disable-render", 0, 0, 'r'},
+ {"untiled", 0, 0, 'u'},
+ {"x-tiled", 0, 0, 'x'},
+ {"use-cpu-maps", 0, 0, 'm'},
+ {"rounds", 1, 0, 'o'},
+ {"no-fail", 0, 0, 'f'},
+ {"tiles-per-buf", 0, 0, 'p'},
+#define DUCTAPE 0xdead0001
+ {"remove-duct-tape", 0, 0, DUCTAPE},
+#define TILESZ 0xdead0002
+ {"tile-size", 1, 0, TILESZ},
+#define CHCK_RENDER 0xdead0003
+ {"check-render-cpyfn", 0, 0, CHCK_RENDER},
+ };
+
+ options.scratch_buf_size = 256*4096;
+ options.no_hw = 0;
+ options.use_signal_helper = 1;
+ options.gpu_busy_load = 0;
+ options.num_buffers = 0;
+ options.trace_tile = -1;
+ options.use_render = 1;
+ options.use_blt = 1;
+ options.forced_tiling = -1;
+ options.use_cpu_maps = 0;
+ options.total_rounds = 512;
+ options.fail = 1;
+ options.ducttape = 1;
+ options.tile_size = 16;
+ options.tiles_per_buf = options.scratch_buf_size / TILE_BYTES(options.tile_size);
+ options.check_render_cpyfn = 0;
+
+ while((c = getopt_long(argc, argv, "ds:g:c:t:rbuxmo:fp:",
+ long_options, &option_index)) != -1) {
+ switch(c) {
+ case 'd':
+ options.no_hw = 1;
+ printf("no-hw debug mode\n");
+ break;
+ case 'S':
+ options.use_signal_helper = 0;
+ printf("disabling that pesky nuisance who keeps interrupting us\n");
+ break;
+ case 's':
+ tmp = atoi(optarg);
+ if (tmp < options.tile_size*8192)
+ printf("scratch buffer size needs to be at least %i\n",
+ options.tile_size*8192);
+ else if (tmp & (tmp - 1)) {
+ printf("scratch buffer size needs to be a power-of-two\n");
+ } else {
+ printf("fixed scratch buffer size to %u\n", tmp);
+ options.scratch_buf_size = tmp;
+ sanitize_tiles_per_buf();
+ }
+ break;
+ case 'g':
+ tmp = atoi(optarg);
+ if (tmp < 0 || tmp > 10)
+ printf("gpu busy load needs to be bigger than 0 and smaller than 10\n");
+ else {
+ printf("gpu busy load factor set to %i\n", tmp);
+ gpu_busy_load = options.gpu_busy_load = tmp;
+ }
+ break;
+ case 'c':
+ options.num_buffers = atoi(optarg);
+ printf("buffer count set to %i\n", options.num_buffers);
+ break;
+ case 't':
+ options.trace_tile = atoi(optarg);
+ printf("tracing tile %i\n", options.trace_tile);
+ break;
+ case 'r':
+ options.use_render = 0;
+ printf("disabling render copy\n");
+ break;
+ case 'b':
+ options.use_blt = 0;
+ printf("disabling blt copy\n");
+ break;
+ case 'u':
+ options.forced_tiling = I915_TILING_NONE;
+ printf("disabling tiling\n");
+ break;
+ case 'x':
+ if (options.use_cpu_maps) {
+ printf("tiling not possible with cpu maps\n");
+ } else {
+ options.forced_tiling = I915_TILING_X;
+ printf("using only X-tiling\n");
+ }
+ break;
+ case 'm':
+ options.use_cpu_maps = 1;
+ options.forced_tiling = I915_TILING_NONE;
+ printf("disabling tiling\n");
+ break;
+ case 'o':
+ options.total_rounds = atoi(optarg);
+ printf("total rounds %i\n", options.total_rounds);
+ break;
+ case 'f':
+ options.fail = 0;
+ printf("not failing when detecting errors\n");
+ break;
+ case 'p':
+ options.tiles_per_buf = atoi(optarg);
+ printf("tiles per buffer %i\n", options.tiles_per_buf);
+ break;
+ case DUCTAPE:
+ options.ducttape = 0;
+ printf("applying duct-tape\n");
+ break;
+ case TILESZ:
+ options.tile_size = atoi(optarg);
+ sanitize_tiles_per_buf();
+ printf("til size %i\n", options.tile_size);
+ break;
+ case CHCK_RENDER:
+ options.check_render_cpyfn = 1;
+ printf("checking render copy function\n");
+ break;
+ default:
+ printf("unkown command options\n");
+ break;
+ }
+ }
+
+ if (optind < argc)
+ printf("unkown command options\n");
+
+ /* actually 32767, according to docs, but that kills our nice pot calculations. */
+ options.max_dimension = 16*1024;
+ if (options.use_render) {
+ if (IS_GEN2(devid) || IS_GEN3(devid))
+ options.max_dimension = 2048;
+ else
+ options.max_dimension = 8192;
+ }
+ printf("Limiting buffer to %dx%d\n",
+ options.max_dimension, options.max_dimension);
+}
+
+static void init(void)
+{
+ int i;
+ unsigned tmp;
+
+ if (options.num_buffers == 0) {
+ tmp = gem_aperture_size(drm_fd);
+ tmp = tmp > 256*(1024*1024) ? 256*(1024*1024) : tmp;
+ num_buffers = 2 * tmp / options.scratch_buf_size / 3;
+ num_buffers /= 2;
+ printf("using %u buffers\n", num_buffers);
+ } else
+ num_buffers = options.num_buffers;
+
+ bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ drm_intel_bufmgr_gem_enable_fenced_relocs(bufmgr);
+ num_fences = get_num_fences();
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+ busy_bo = drm_intel_bo_alloc(bufmgr, "tiled bo", BUSY_BUF_SIZE, 4096);
+ if (options.forced_tiling >= 0)
+ gem_set_tiling(drm_fd, busy_bo->handle, options.forced_tiling, 4096);
+
+ for (i = 0; i < num_buffers; i++) {
+ init_buffer(&buffers[0][i], options.scratch_buf_size);
+ init_buffer(&buffers[1][i], options.scratch_buf_size);
+
+ num_total_tiles += buffers[0][i].num_tiles;
+ }
+ current_set = 0;
+
+ /* just in case it helps reproducability */
+ srandom(0xdeadbeef);
+}
+
+static void check_render_copyfunc(void)
+{
+ struct scratch_buf src, dst;
+ uint32_t *ptr;
+ int i, j, pass;
+
+ if (!options.check_render_cpyfn)
+ return;
+
+ init_buffer(&src, options.scratch_buf_size);
+ init_buffer(&dst, options.scratch_buf_size);
+
+ for (pass = 0; pass < 16; pass++) {
+ int sx = random() % (buf_width(&src)-options.tile_size);
+ int sy = random() % (buf_height(&src)-options.tile_size);
+ int dx = random() % (buf_width(&dst)-options.tile_size);
+ int dy = random() % (buf_height(&dst)-options.tile_size);
+
+ if (options.use_cpu_maps)
+ set_to_cpu_domain(&src, 1);
+
+ memset(src.data, 0xff, options.scratch_buf_size);
+ for (j = 0; j < options.tile_size; j++) {
+ ptr = (uint32_t*)((char *)src.data + sx*4 + (sy+j) * src.stride);
+ for (i = 0; i < options.tile_size; i++)
+ ptr[i] = j * options.tile_size + i;
+ }
+
+ render_copyfunc(&src, sx, sy, &dst, dx, dy, 0);
+
+ if (options.use_cpu_maps)
+ set_to_cpu_domain(&dst, 0);
+
+ for (j = 0; j < options.tile_size; j++) {
+ ptr = (uint32_t*)((char *)dst.data + dx*4 + (dy+j) * dst.stride);
+ for (i = 0; i < options.tile_size; i++)
+ if (ptr[i] != j * options.tile_size + i) {
+ printf("render copyfunc mismatch at (%d, %d): found %d, expected %d\n",
+ i, j, ptr[i], j*options.tile_size + i);
+ }
+ }
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ int i, j;
+ unsigned *current_permutation, *tmp_permutation;
+
+ drm_fd = drm_open_any();
+ devid = intel_get_drm_devid(drm_fd);
+
+ parse_options(argc, argv);
+
+ /* start our little helper early before too may allocations occur */
+ if (options.use_signal_helper)
+ drmtest_fork_signal_helper();
+
+ init();
+
+ check_render_copyfunc();
+
+ tile_permutation = malloc(num_total_tiles*sizeof(uint32_t));
+ current_permutation = malloc(num_total_tiles*sizeof(uint32_t));
+ tmp_permutation = malloc(num_total_tiles*sizeof(uint32_t));
+ assert(tile_permutation);
+ assert(current_permutation);
+ assert(tmp_permutation);
+
+ fan_out();
+
+ for (i = 0; i < options.total_rounds; i++) {
+ printf("round %i\n", i);
+ if (i % 64 == 63) {
+ fan_in_and_check();
+ printf("everything correct after %i rounds\n", i + 1);
+ }
+
+ target_set = (current_set + 1) & 1;
+ init_set(target_set);
+
+ for (j = 0; j < num_total_tiles; j++)
+ current_permutation[j] = j;
+ drmtest_permute_array(current_permutation, num_total_tiles, exchange_uint);
+
+ copy_tiles(current_permutation);
+
+ memcpy(tmp_permutation, tile_permutation, sizeof(unsigned)*num_total_tiles);
+
+ /* accumulate the permutations */
+ for (j = 0; j < num_total_tiles; j++)
+ tile_permutation[j] = current_permutation[tmp_permutation[j]];
+
+ current_set = target_set;
+ }
+
+ fan_in_and_check();
+
+ fprintf(stderr, "num failed tiles %u, max incoherent bytes %zd\n",
+ stats.num_failed, stats.max_failed_reads*sizeof(uint32_t));
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(drm_fd);
+
+ drmtest_stop_signal_helper();
+
+ return 0;
+}
diff --git a/tests/gem_tiled_blits.c b/tests/gem_tiled_blits.c
new file mode 100644
index 00000000..86c9a886
--- /dev/null
+++ b/tests/gem_tiled_blits.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file gem_tiled_blits.c
+ *
+ * This is a test of doing many tiled blits, with a working set
+ * larger than the aperture size.
+ *
+ * The goal is to catch a couple types of failure;
+ * - Fence management problems on pre-965.
+ * - A17 or L-shaped memory tiling workaround problems in acceleration.
+ *
+ * The model is to fill a collection of 1MB objects in a way that can't trip
+ * over A6 swizzling -- upload data to a non-tiled object, blit to the tiled
+ * object. Then, copy the 1MB objects randomly between each other for a while.
+ * Finally, download their data through linear objects again and see what
+ * resulted.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static int width = 512, height = 512;
+
+static drm_intel_bo *
+create_bo(uint32_t start_val)
+{
+ drm_intel_bo *bo, *linear_bo;
+ uint32_t *linear;
+ uint32_t tiling = I915_TILING_X;
+ int ret, i;
+
+ bo = drm_intel_bo_alloc(bufmgr, "tiled bo", 1024 * 1024, 4096);
+ ret = drm_intel_bo_set_tiling(bo, &tiling, width * 4);
+ assert(ret == 0);
+ assert(tiling == I915_TILING_X);
+
+ linear_bo = drm_intel_bo_alloc(bufmgr, "linear src", 1024 * 1024, 4096);
+
+ /* Fill the BO with dwords starting at start_val */
+ drm_intel_bo_map(linear_bo, 1);
+ linear = linear_bo->virtual;
+ for (i = 0; i < 1024 * 1024 / 4; i++)
+ linear[i] = start_val++;
+ drm_intel_bo_unmap(linear_bo);
+
+ intel_copy_bo (batch, bo, linear_bo, width, height);
+
+ drm_intel_bo_unreference(linear_bo);
+
+ return bo;
+}
+
+static void
+check_bo(drm_intel_bo *bo, uint32_t start_val)
+{
+ drm_intel_bo *linear_bo;
+ uint32_t *linear;
+ int i;
+
+ linear_bo = drm_intel_bo_alloc(bufmgr, "linear dst", 1024 * 1024, 4096);
+
+ intel_copy_bo(batch, linear_bo, bo, width, height);
+
+ drm_intel_bo_map(linear_bo, 0);
+ linear = linear_bo->virtual;
+
+ for (i = 0; i < 1024 * 1024 / 4; i++) {
+ if (linear[i] != start_val) {
+ fprintf(stderr, "Expected 0x%08x, found 0x%08x "
+ "at offset 0x%08x\n",
+ start_val, linear[i], i * 4);
+ abort();
+ }
+ start_val++;
+ }
+ drm_intel_bo_unmap(linear_bo);
+
+ drm_intel_bo_unreference(linear_bo);
+}
+
+int main(int argc, char **argv)
+{
+ drm_intel_bo **bo;
+ uint32_t *bo_start_val;
+ uint32_t start = 0;
+ int i, fd, count;
+
+ fd = drm_open_any();
+
+ count = 0;
+ if (argc > 1)
+ count = atoi(argv[1]);
+ if (count == 0) {
+ count = 3 * gem_aperture_size(fd) / (1024*1024) / 2;
+ count += (count & 1) == 0;
+ }
+
+ if (count > intel_get_total_ram_mb() * 9 / 10) {
+ count = intel_get_total_ram_mb() * 9 / 10;
+ printf("not enough RAM to run test, reducing buffer count\n");
+ }
+
+ printf("Using %d 1MiB buffers\n", count);
+
+ bo = malloc(sizeof(drm_intel_bo *)*count);
+ bo_start_val = malloc(sizeof(uint32_t)*count);
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ for (i = 0; i < count; i++) {
+ bo[i] = create_bo(start);
+ bo_start_val[i] = start;
+ start += 1024 * 1024 / 4;
+ }
+ printf("Verifying initialisation...\n");
+ for (i = 0; i < count; i++)
+ check_bo(bo[i], bo_start_val[i]);
+
+ printf("Cyclic blits, forward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = i % count;
+ int dst = (i+1) % count;
+
+ if (src == dst)
+ continue;
+
+ intel_copy_bo(batch, bo[dst], bo[src], width, height);
+ bo_start_val[dst] = bo_start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(bo[i], bo_start_val[i]);
+
+ printf("Cyclic blits, backward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = (i+1) % count;
+ int dst = i % count;
+
+ if (src == dst)
+ continue;
+
+ intel_copy_bo(batch, bo[dst], bo[src], width, height);
+ bo_start_val[dst] = bo_start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(bo[i], bo_start_val[i]);
+
+ printf("Random blits...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = random() % count;
+ int dst = random() % count;
+
+ if (src == dst)
+ continue;
+
+ intel_copy_bo(batch, bo[dst], bo[src], width, height);
+ bo_start_val[dst] = bo_start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(bo[i], bo_start_val[i]);
+
+ for (i = 0; i < count; i++) {
+ drm_intel_bo_unreference(bo[i]);
+ bo[i] = NULL;
+ }
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_tiled_fence_blits.c b/tests/gem_tiled_fence_blits.c
new file mode 100644
index 00000000..dc654793
--- /dev/null
+++ b/tests/gem_tiled_fence_blits.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright © 2009,2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file gem_tiled_fence_blits.c
+ *
+ * This is a test of doing many tiled blits, with a working set
+ * larger than the aperture size.
+ *
+ * The goal is to catch a couple types of failure;
+ * - Fence management problems on pre-965.
+ * - A17 or L-shaped memory tiling workaround problems in acceleration.
+ *
+ * The model is to fill a collection of 1MB objects in a way that can't trip
+ * over A6 swizzling -- upload data to a non-tiled object, blit to the tiled
+ * object. Then, copy the 1MB objects randomly between each other for a while.
+ * Finally, download their data through linear objects again and see what
+ * resulted.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static int width = 512, height = 512;
+static uint32_t linear[1024*1024/4];
+
+static drm_intel_bo *
+create_bo(int fd, uint32_t start_val)
+{
+ drm_intel_bo *bo;
+ uint32_t tiling = I915_TILING_X;
+ int ret, i;
+
+ bo = drm_intel_bo_alloc(bufmgr, "tiled bo", 1024 * 1024, 4096);
+ ret = drm_intel_bo_set_tiling(bo, &tiling, width * 4);
+ assert(ret == 0);
+ assert(tiling == I915_TILING_X);
+
+ /* Fill the BO with dwords starting at start_val */
+ for (i = 0; i < 1024 * 1024 / 4; i++)
+ linear[i] = start_val++;
+
+ gem_write(fd, bo->handle, 0, linear, sizeof(linear));
+
+ return bo;
+}
+
+static void
+check_bo(int fd, drm_intel_bo *bo, uint32_t start_val)
+{
+ int i;
+
+ gem_read(fd, bo->handle, 0, linear, sizeof(linear));
+
+ for (i = 0; i < 1024 * 1024 / 4; i++) {
+ if (linear[i] != start_val) {
+ fprintf(stderr, "Expected 0x%08x, found 0x%08x "
+ "at offset 0x%08x\n",
+ start_val, linear[i], i * 4);
+ abort();
+ }
+ start_val++;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ drm_intel_bo *bo[4096];
+ uint32_t bo_start_val[4096];
+ uint32_t start = 0;
+ int fd, i, count;
+
+ fd = drm_open_any();
+ count = 3 * gem_aperture_size(fd) / (1024*1024) / 2;
+ if (count > intel_get_total_ram_mb() * 9 / 10) {
+ count = intel_get_total_ram_mb() * 9 / 10;
+ printf("not enough RAM to run test, reducing buffer count\n");
+ }
+ count |= 1;
+ printf("Using %d 1MiB buffers\n", count);
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ for (i = 0; i < count; i++) {
+ bo[i] = create_bo(fd, start);
+ bo_start_val[i] = start;
+
+ /*
+ printf("Creating bo %d\n", i);
+ check_bo(bo[i], bo_start_val[i]);
+ */
+
+ start += 1024 * 1024 / 4;
+ }
+
+ for (i = 0; i < count; i++) {
+ int src = count - i - 1;
+ intel_copy_bo(batch, bo[i], bo[src], width, height);
+ bo_start_val[i] = bo_start_val[src];
+ }
+
+ for (i = 0; i < count * 4; i++) {
+ int src = random() % count;
+ int dst = random() % count;
+
+ if (src == dst)
+ continue;
+
+ intel_copy_bo(batch, bo[dst], bo[src], width, height);
+ bo_start_val[dst] = bo_start_val[src];
+
+ /*
+ check_bo(bo[dst], bo_start_val[dst]);
+ printf("%d: copy bo %d to %d\n", i, src, dst);
+ */
+ }
+
+ for (i = 0; i < count; i++) {
+ /*
+ printf("check %d\n", i);
+ */
+ check_bo(fd, bo[i], bo_start_val[i]);
+
+ drm_intel_bo_unreference(bo[i]);
+ bo[i] = NULL;
+ }
+
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_tiled_partial_pwrite_pread.c b/tests/gem_tiled_partial_pwrite_pread.c
new file mode 100644
index 00000000..bd0d4e09
--- /dev/null
+++ b/tests/gem_tiled_partial_pwrite_pread.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+/*
+ * Testcase: pwrite/pread consistency when touching partial cachelines
+ *
+ * Some fancy new pwrite/pread optimizations clflush in-line while
+ * reading/writing. Check whether all required clflushes happen.
+ *
+ * Unfortunately really old mesa used unaligned pread/pwrite for s/w fallback
+ * rendering, so we need to check whether this works on tiled buffers, too.
+ *
+ */
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+
+drm_intel_bo *scratch_bo;
+drm_intel_bo *staging_bo;
+drm_intel_bo *tiled_staging_bo;
+unsigned long scratch_pitch;
+#define BO_SIZE (32*4096)
+uint32_t devid;
+uint64_t mappable_gtt_limit;
+int fd;
+
+static void
+copy_bo(drm_intel_bo *src, int src_tiled,
+ drm_intel_bo *dst, int dst_tiled)
+{
+ unsigned long dst_pitch = scratch_pitch;
+ unsigned long src_pitch = scratch_pitch;
+ uint32_t cmd_bits = 0;
+
+ /* dst is tiled ... */
+ if (intel_gen(devid) >= 4 && dst_tiled) {
+ dst_pitch /= 4;
+ cmd_bits |= XY_SRC_COPY_BLT_DST_TILED;
+ }
+
+ if (intel_gen(devid) >= 4 && dst_tiled) {
+ src_pitch /= 4;
+ cmd_bits |= XY_SRC_COPY_BLT_SRC_TILED;
+ }
+
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB |
+ cmd_bits);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ dst_pitch);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(BO_SIZE/scratch_pitch << 16 | 1024);
+ OUT_RELOC_FENCED(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(src_pitch);
+ OUT_RELOC_FENCED(src, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+}
+
+static void
+blt_bo_fill(drm_intel_bo *tmp_bo, drm_intel_bo *bo, int val)
+{
+ uint8_t *gtt_ptr;
+ int i;
+
+ drm_intel_gem_bo_map_gtt(tmp_bo);
+ gtt_ptr = tmp_bo->virtual;
+
+ for (i = 0; i < BO_SIZE; i++)
+ gtt_ptr[i] = val;
+
+ drm_intel_gem_bo_unmap_gtt(tmp_bo);
+
+ if (bo->offset < mappable_gtt_limit &&
+ (IS_G33(devid) || intel_gen(devid) >= 4))
+ drmtest_trash_aperture();
+
+ copy_bo(tmp_bo, 0, bo, 1);
+}
+
+#define MAX_BLT_SIZE 128
+#define ROUNDS 200
+int main(int argc, char **argv)
+{
+ int i, j;
+ uint8_t tmp[BO_SIZE];
+ uint8_t compare_tmp[BO_SIZE];
+ uint32_t tiling_mode = I915_TILING_X;
+
+ srandom(0xdeadbeef);
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ devid = intel_get_drm_devid(fd);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+ /* overallocate the buffers we're actually using because */
+ scratch_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024,
+ BO_SIZE/4096, 4,
+ &tiling_mode, &scratch_pitch, 0);
+ assert(tiling_mode == I915_TILING_X);
+ assert(scratch_pitch == 4096);
+ staging_bo = drm_intel_bo_alloc(bufmgr, "staging bo", BO_SIZE, 4096);
+ tiled_staging_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024,
+ BO_SIZE/4096, 4,
+ &tiling_mode,
+ &scratch_pitch, 0);
+
+ drmtest_init_aperture_trashers(bufmgr);
+ mappable_gtt_limit = gem_mappable_aperture_size();
+
+ printf("checking partial reads\n");
+ for (i = 0; i < ROUNDS; i++) {
+ int start, len;
+ int val = i % 256;
+
+ blt_bo_fill(staging_bo, scratch_bo, i);
+
+ start = random() % BO_SIZE;
+ len = random() % (BO_SIZE-start) + 1;
+
+ drm_intel_bo_get_subdata(scratch_bo, start, len, tmp);
+ for (j = 0; j < len; j++) {
+ if (tmp[j] != val) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ start + j, tmp[j], val);
+ exit(1);
+ }
+ }
+
+ drmtest_progress("partial reads test: ", i, ROUNDS);
+ }
+
+ printf("checking partial writes\n");
+ for (i = 0; i < ROUNDS; i++) {
+ int start, len;
+ int val = i % 256;
+
+ blt_bo_fill(staging_bo, scratch_bo, i);
+
+ start = random() % BO_SIZE;
+ len = random() % (BO_SIZE-start) + 1;
+
+ memset(tmp, i + 63, BO_SIZE);
+
+ drm_intel_bo_subdata(scratch_bo, start, len, tmp);
+
+ copy_bo(scratch_bo, 1, tiled_staging_bo, 1);
+ drm_intel_bo_get_subdata(tiled_staging_bo, 0, BO_SIZE,
+ compare_tmp);
+
+ for (j = 0; j < start; j++) {
+ if (compare_tmp[j] != val) {
+ printf("amismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+ for (; j < start + len; j++) {
+ if (compare_tmp[j] != tmp[0]) {
+ printf("bmismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], i);
+ exit(1);
+ }
+ }
+ for (; j < BO_SIZE; j++) {
+ if (compare_tmp[j] != val) {
+ printf("cmismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+ drm_intel_gem_bo_unmap_gtt(staging_bo);
+
+ drmtest_progress("partial writes test: ", i, ROUNDS);
+ }
+
+ printf("checking partial writes after partial reads\n");
+ for (i = 0; i < ROUNDS; i++) {
+ int start, len;
+ int val = i % 256;
+
+ blt_bo_fill(staging_bo, scratch_bo, i);
+
+ /* partial read */
+ start = random() % BO_SIZE;
+ len = random() % (BO_SIZE-start) + 1;
+
+ drm_intel_bo_get_subdata(scratch_bo, start, len, tmp);
+ for (j = 0; j < len; j++) {
+ if (tmp[j] != val) {
+ printf("mismatch in read at %i, got: %i, expected: %i\n",
+ start + j, tmp[j], val);
+ exit(1);
+ }
+ }
+
+ /* Change contents through gtt to make the pread cachelines
+ * stale. */
+ val = (i + 17) % 256;
+ blt_bo_fill(staging_bo, scratch_bo, val);
+
+ /* partial write */
+ start = random() % BO_SIZE;
+ len = random() % (BO_SIZE-start) + 1;
+
+ memset(tmp, i + 63, BO_SIZE);
+
+ drm_intel_bo_subdata(scratch_bo, start, len, tmp);
+
+ copy_bo(scratch_bo, 1, tiled_staging_bo, 1);
+ drm_intel_bo_get_subdata(tiled_staging_bo, 0, BO_SIZE,
+ compare_tmp);
+
+ for (j = 0; j < start; j++) {
+ if (compare_tmp[j] != val) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+ for (; j < start + len; j++) {
+ if (compare_tmp[j] != tmp[0]) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], tmp[0]);
+ exit(1);
+ }
+ }
+ for (; j < BO_SIZE; j++) {
+ if (compare_tmp[j] != val) {
+ printf("mismatch at %i, got: %i, expected: %i\n",
+ j, tmp[j], val);
+ exit(1);
+ }
+ }
+ drm_intel_gem_bo_unmap_gtt(staging_bo);
+
+ drmtest_progress("partial read/writes test: ", i, ROUNDS);
+ }
+
+ drmtest_cleanup_aperture_trashers();
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_tiled_pread.c b/tests/gem_tiled_pread.c
new file mode 100644
index 00000000..189affce
--- /dev/null
+++ b/tests/gem_tiled_pread.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file gem_tiled_pread.c
+ *
+ * This is a test of pread's behavior on tiled objects with respect to the
+ * reported swizzling value.
+ *
+ * The goal is to exercise the slow_bit17_copy path for reading on bit17
+ * machines, but will also be useful for catching swizzling value bugs on
+ * other systems.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#define WIDTH 512
+#define HEIGHT 512
+static uint32_t linear[WIDTH * HEIGHT];
+
+#define PAGE_SIZE 4096
+
+static int tile_width;
+static int tile_height;
+static int tile_size;
+
+static void
+gem_get_tiling(int fd, uint32_t handle, uint32_t *tiling, uint32_t *swizzle)
+{
+ struct drm_i915_gem_get_tiling get_tiling;
+ int ret;
+
+ memset(&get_tiling, 0, sizeof(get_tiling));
+ get_tiling.handle = handle;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling);
+ assert(ret == 0);
+
+ *tiling = get_tiling.tiling_mode;
+ *swizzle = get_tiling.swizzle_mode;
+}
+
+static uint32_t
+create_bo(int fd)
+{
+ uint32_t handle;
+ uint32_t *data;
+ int i;
+
+ handle = gem_create(fd, sizeof(linear));
+ gem_set_tiling(fd, handle, I915_TILING_X, WIDTH * sizeof(uint32_t));
+
+ /* Fill the BO with dwords starting at start_val */
+ data = gem_mmap(fd, handle, sizeof(linear), PROT_READ | PROT_WRITE);
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ data[i] = i;
+ munmap(data, sizeof(linear));
+
+ return handle;
+}
+
+static int
+swizzle_bit(int bit, int offset)
+{
+ return (offset & (1 << bit)) >> (bit - 6);
+}
+
+/* Translate from a swizzled offset in the tiled buffer to the corresponding
+ * value from the original linear buffer.
+ */
+static uint32_t
+calculate_expected(int offset)
+{
+ int tile_off = offset & (tile_size - 1);
+ int tile_base = offset & -tile_size;
+ int tile_index = tile_base / tile_size;
+ int tiles_per_row = 4*WIDTH / tile_width;
+
+ /* base x,y values from the tile (page) index. */
+ int base_y = tile_index / tiles_per_row * tile_height;
+ int base_x = tile_index % tiles_per_row * (tile_width/4);
+
+ /* x, y offsets within the tile */
+ int tile_y = tile_off / tile_width;
+ int tile_x = (tile_off % tile_width) / 4;
+
+ /* printf("%3d, %3d, %3d,%3d\n", base_x, base_y, tile_x, tile_y); */
+ return (base_y + tile_y) * WIDTH + base_x + tile_x;
+}
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+ int i, iter = 100;
+ uint32_t tiling, swizzle;
+ uint32_t handle;
+ uint32_t devid;
+
+ fd = drm_open_any();
+
+ handle = create_bo(fd);
+ gem_get_tiling(fd, handle, &tiling, &swizzle);
+
+ devid = intel_get_drm_devid(fd);
+
+ if (IS_GEN2(devid)) {
+ tile_height = 16;
+ tile_width = 128;
+ tile_size = 2048;
+ } else {
+ tile_height = 8;
+ tile_width = 512;
+ tile_size = PAGE_SIZE;
+ }
+
+ /* Read a bunch of random subsets of the data and check that they come
+ * out right.
+ */
+ for (i = 0; i < iter; i++) {
+ int size = WIDTH * HEIGHT * 4;
+ int offset = (random() % size) & ~3;
+ int len = (random() % size) & ~3;
+ int j;
+
+ if (len == 0)
+ len = 4;
+
+ if (offset + len > size)
+ len = size - offset;
+
+ if (i == 0) {
+ offset = 0;
+ len = size;
+ }
+
+ gem_read(fd, handle, offset, linear, len);
+
+ /* Translate from offsets in the read buffer to the swizzled
+ * address that it corresponds to. This is the opposite of
+ * what Mesa does (calculate offset to be read given the linear
+ * offset it's looking for).
+ */
+ for (j = offset; j < offset + len; j += 4) {
+ uint32_t expected_val, found_val;
+ int swizzled_offset;
+ const char *swizzle_str;
+
+ switch (swizzle) {
+ case I915_BIT_6_SWIZZLE_NONE:
+ swizzled_offset = j;
+ swizzle_str = "none";
+ break;
+ case I915_BIT_6_SWIZZLE_9:
+ swizzled_offset = j ^
+ swizzle_bit(9, j);
+ swizzle_str = "bit9";
+ break;
+ case I915_BIT_6_SWIZZLE_9_10:
+ swizzled_offset = j ^
+ swizzle_bit(9, j) ^
+ swizzle_bit(10, j);
+ swizzle_str = "bit9^10";
+ break;
+ case I915_BIT_6_SWIZZLE_9_11:
+ swizzled_offset = j ^
+ swizzle_bit(9, j) ^
+ swizzle_bit(11, j);
+ swizzle_str = "bit9^11";
+ break;
+ case I915_BIT_6_SWIZZLE_9_10_11:
+ swizzled_offset = j ^
+ swizzle_bit(9, j) ^
+ swizzle_bit(10, j) ^
+ swizzle_bit(11, j);
+ swizzle_str = "bit9^10^11";
+ break;
+ default:
+ fprintf(stderr, "Bad swizzle bits; %d\n",
+ swizzle);
+ abort();
+ }
+ expected_val = calculate_expected(swizzled_offset);
+ found_val = linear[(j - offset) / 4];
+ if (expected_val != found_val) {
+ fprintf(stderr,
+ "Bad read [%d]: %d instead of %d at 0x%08x "
+ "for read from 0x%08x to 0x%08x, swizzle=%s\n",
+ i, found_val, expected_val, j,
+ offset, offset + len,
+ swizzle_str);
+ abort();
+ }
+ }
+ }
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_tiled_pread_pwrite.c b/tests/gem_tiled_pread_pwrite.c
new file mode 100644
index 00000000..e2225c5e
--- /dev/null
+++ b/tests/gem_tiled_pread_pwrite.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file gem_tiled_pread_pwrite.c
+ *
+ * This is a test of pread's behavior on tiled objects with respect to the
+ * reported swizzling value.
+ *
+ * The goal is to exercise the slow_bit17_copy path for reading on bit17
+ * machines, but will also be useful for catching swizzling value bugs on
+ * other systems.
+ */
+
+/*
+ * Testcase: Test swizzling by testing pwrite does the invers of pread
+ *
+ * Together with the explicit pread testcase, this should cover our swizzle
+ * handling.
+ *
+ * Note that this test will use swap in an effort to test all of ram.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#define WIDTH 512
+#define HEIGHT 512
+static uint32_t linear[WIDTH * HEIGHT];
+static uint32_t current_tiling_mode;
+
+#define PAGE_SIZE 4096
+
+static void
+gem_get_tiling(int fd, uint32_t handle, uint32_t *tiling, uint32_t *swizzle)
+{
+ struct drm_i915_gem_get_tiling get_tiling;
+ int ret;
+
+ memset(&get_tiling, 0, sizeof(get_tiling));
+ get_tiling.handle = handle;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling);
+ assert(ret == 0);
+
+ *tiling = get_tiling.tiling_mode;
+ *swizzle = get_tiling.swizzle_mode;
+}
+
+static uint32_t
+create_bo_and_fill(int fd)
+{
+ uint32_t handle;
+ uint32_t *data;
+ int i;
+
+ handle = gem_create(fd, sizeof(linear));
+ gem_set_tiling(fd, handle, current_tiling_mode, WIDTH * sizeof(uint32_t));
+
+ /* Fill the BO with dwords starting at start_val */
+ data = gem_mmap(fd, handle, sizeof(linear), PROT_READ | PROT_WRITE);
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ data[i] = i;
+ munmap(data, sizeof(linear));
+
+ return handle;
+}
+
+static uint32_t
+create_bo(int fd)
+{
+ uint32_t handle;
+
+ handle = gem_create(fd, sizeof(linear));
+ gem_set_tiling(fd, handle, current_tiling_mode, WIDTH * sizeof(uint32_t));
+
+ return handle;
+}
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+ uint32_t *data;
+ int i, j;
+ uint32_t tiling, swizzle;
+ uint32_t handle, handle_target;
+ int count;
+
+
+ fd = drm_open_any();
+ count = intel_get_total_ram_mb() * 9 / 10;
+
+ for (i = 0; i < count/2; i++) {
+ current_tiling_mode = I915_TILING_X;
+
+ handle = create_bo_and_fill(fd);
+ gem_get_tiling(fd, handle, &tiling, &swizzle);
+
+ gem_read(fd, handle, 0, linear, sizeof(linear));
+
+ handle_target = create_bo(fd);
+ gem_write(fd, handle_target, 0, linear, sizeof(linear));
+
+ /* Check the target bo's contents. */
+ data = gem_mmap(fd, handle_target, sizeof(linear), PROT_READ | PROT_WRITE);
+ for (j = 0; j < WIDTH*HEIGHT; j++)
+ if (data[j] != j) {
+ fprintf(stderr, "mismatch at %i: %i\n",
+ j, data[j]);
+ exit(1);
+ }
+ munmap(data, sizeof(linear));
+
+ /* Leak both bos so that we use all of system mem! */
+
+ drmtest_progress("gem_tiled_pread_pwrite: ", i, count/2);
+ }
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_tiled_swapping.c b/tests/gem_tiled_swapping.c
new file mode 100644
index 00000000..d1484f0e
--- /dev/null
+++ b/tests/gem_tiled_swapping.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+/** @file gem_tiled_pread_pwrite.c
+ *
+ * This is a test of pread's behavior on tiled objects with respect to the
+ * reported swizzling value.
+ *
+ * The goal is to exercise the slow_bit17_copy path for reading on bit17
+ * machines, but will also be useful for catching swizzling value bugs on
+ * other systems.
+ */
+
+/*
+ * Testcase: Exercise swizzle code for swapping
+ *
+ * The swizzle checks in the swapin path are at a different place than the ones
+ * for pread/pwrite, so we need to check them separately.
+ *
+ * This test obviously needs swap present (and exits if none is detected).
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#define WIDTH 512
+#define HEIGHT 512
+static uint32_t linear[WIDTH * HEIGHT];
+static uint32_t current_tiling_mode;
+
+#define PAGE_SIZE 4096
+
+static uint32_t
+create_bo_and_fill(int fd)
+{
+ uint32_t handle;
+ uint32_t *data;
+ int i;
+
+ handle = gem_create(fd, sizeof(linear));
+ gem_set_tiling(fd, handle, current_tiling_mode, WIDTH * sizeof(uint32_t));
+
+ /* Fill the BO with dwords starting at start_val */
+ data = gem_mmap(fd, handle, sizeof(linear), PROT_READ | PROT_WRITE);
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ data[i] = i;
+ munmap(data, sizeof(linear));
+
+ return handle;
+}
+
+uint32_t *bo_handles;
+int *idx_arr;
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+ uint32_t *data;
+ int i, j;
+ int count;
+ current_tiling_mode = I915_TILING_X;
+
+ fd = drm_open_any();
+ /* need slightly more than total ram */
+ count = intel_get_total_ram_mb() * 11 / 10;
+ bo_handles = calloc(count, sizeof(uint32_t));
+ assert(bo_handles);
+
+ idx_arr = calloc(count, sizeof(int));
+ assert(idx_arr);
+
+ if (intel_get_total_swap_mb() == 0) {
+ printf("no swap detected\n");
+ return 77;
+ }
+
+ if (intel_get_total_ram_mb() / 4 > intel_get_total_swap_mb()) {
+ printf("not enough swap detected\n");
+ return 77;
+ }
+
+ for (i = 0; i < count; i++)
+ bo_handles[i] = create_bo_and_fill(fd);
+
+ for (i = 0; i < count; i++)
+ idx_arr[i] = i;
+
+ drmtest_permute_array(idx_arr, count,
+ drmtest_exchange_int);
+
+ for (i = 0; i < count/2; i++) {
+ /* Check the target bo's contents. */
+ data = gem_mmap(fd, bo_handles[idx_arr[i]],
+ sizeof(linear), PROT_READ | PROT_WRITE);
+ for (j = 0; j < WIDTH*HEIGHT; j++)
+ if (data[j] != j) {
+ fprintf(stderr, "mismatch at %i: %i\n",
+ j, data[j]);
+ exit(1);
+ }
+ munmap(data, sizeof(linear));
+ }
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_unfence_active_buffers.c b/tests/gem_unfence_active_buffers.c
new file mode 100644
index 00000000..bffc62ea
--- /dev/null
+++ b/tests/gem_unfence_active_buffers.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+/** @file gem_unfence_active_buffers.c
+ *
+ * Testcase: Check for use-after free in the fence stealing code
+ *
+ * If we're stealing the fence of a active object where the active list is the
+ * only thing holding a reference, we need to be careful not to access the old
+ * object we're stealing the fence from after that reference has been dropped by
+ * retire_requests.
+ *
+ * Note that this needs slab poisoning enabled in the kernel to reliably hit the
+ * problem - the race window is too small.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdbool.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+uint32_t devid;
+
+#define TEST_SIZE (1024*1024)
+#define TEST_STRIDE (4*1024)
+
+uint32_t data[TEST_SIZE/4];
+
+int main(int argc, char **argv)
+{
+ int i, ret, fd, num_fences;
+ drm_intel_bo *busy_bo, *test_bo;
+ uint32_t tiling = I915_TILING_X;
+
+ for (i = 0; i < 1024*256; i++)
+ data[i] = i;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ devid = intel_get_drm_devid(fd);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+ printf("filling ring\n");
+ busy_bo = drm_intel_bo_alloc(bufmgr, "busy bo bo", 16*1024*1024, 4096);
+
+ for (i = 0; i < 250; i++) {
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ 2*1024*4);
+ OUT_BATCH(0 << 16 | 1024);
+ OUT_BATCH((2048) << 16 | (2048));
+ OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(2*1024*4);
+ OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ BEGIN_BATCH(3);
+ OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ }
+ }
+ intel_batchbuffer_flush(batch);
+
+ num_fences = gem_available_fences(fd);
+ printf("creating havoc on %i fences\n", num_fences);
+
+ for (i = 0; i < num_fences*2; i++) {
+ test_bo = drm_intel_bo_alloc(bufmgr, "test_bo",
+ TEST_SIZE, 4096);
+ ret = drm_intel_bo_set_tiling(test_bo, &tiling, TEST_STRIDE);
+ assert(ret == 0);
+
+ drm_intel_bo_disable_reuse(test_bo);
+
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ TEST_STRIDE);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH((1) << 16 | (1));
+ OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(TEST_STRIDE);
+ OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+ intel_batchbuffer_flush(batch);
+ printf("test bo offset: %#lx\n", test_bo->offset);
+
+ drm_intel_bo_unreference(test_bo);
+ }
+
+ /* launch a few batchs to ensure the damaged slab objects get reused. */
+ for (i = 0; i < 10; i++) {
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ 2*1024*4);
+ OUT_BATCH(0 << 16 | 1024);
+ OUT_BATCH((1) << 16 | (1));
+ OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(0 << 16 | 0);
+ OUT_BATCH(2*1024*4);
+ OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ BEGIN_BATCH(3);
+ OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ }
+ }
+ intel_batchbuffer_flush(batch);
+
+ return 0;
+}
diff --git a/tests/gem_unref_active_buffers.c b/tests/gem_unref_active_buffers.c
new file mode 100644
index 00000000..aa29c1de
--- /dev/null
+++ b/tests/gem_unref_active_buffers.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+/*
+ * Testcase: Unreferencing of active buffers
+ *
+ * Execs buffers and immediately unreferences them, hence the kernel active list
+ * will be the last one to hold a reference on them. Usually libdrm bo caching
+ * prevents that by keeping another reference.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+static drm_intel_bufmgr *bufmgr;
+struct intel_batchbuffer *batch;
+static drm_intel_bo *load_bo;
+
+int main(int argc, char **argv)
+{
+ int fd, i;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ if (!bufmgr) {
+ fprintf(stderr, "failed to init libdrm\n");
+ exit(-1);
+ }
+ /* don't enable buffer reuse!! */
+ //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+ assert(batch);
+
+ /* put some load onto the gpu to keep the light buffers active for long
+ * enough */
+ for (i = 0; i < 1000; i++) {
+ load_bo = drm_intel_bo_alloc(bufmgr, "target bo", 1024*4096, 4096);
+ if (!load_bo) {
+ fprintf(stderr, "failed to alloc target buffer\n");
+ exit(-1);
+ }
+
+ BEGIN_BATCH(8);
+ OUT_BATCH(XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ 4096);
+ OUT_BATCH(0); /* dst x1,y1 */
+ OUT_BATCH((1024 << 16) | 512);
+ OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH((0 << 16) | 512); /* src x1, y1 */
+ OUT_BATCH(4096);
+ OUT_RELOC(load_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+
+ drm_intel_bo_disable_reuse(load_bo);
+ drm_intel_bo_unreference(load_bo);
+ }
+
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gem_vmap_blits.c b/tests/gem_vmap_blits.c
new file mode 100644
index 00000000..b8868214
--- /dev/null
+++ b/tests/gem_vmap_blits.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright © 2009,2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file gem_vmap_blits.c
+ *
+ * This is a test of doing many blits using a mixture of normal system pages
+ * and uncached linear buffers, with a working set larger than the
+ * aperture size.
+ *
+ * The goal is to simply ensure the basics work.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
+#include "intel_gpu_tools.h"
+
+#if !defined(I915_PARAM_HAS_VMAP)
+#warning No vmap support in drm, skipping
+int main(int argc, char **argv)
+{
+ fprintf(stderr, "No vmap support in drm.\n");
+ return 77;
+}
+#else
+
+#define WIDTH 512
+#define HEIGHT 512
+
+static uint32_t linear[WIDTH*HEIGHT];
+
+static uint32_t gem_vmap(int fd, void *ptr, int size, int read_only)
+{
+ struct drm_i915_gem_vmap vmap;
+
+ vmap.user_ptr = (uintptr_t)ptr;
+ vmap.user_size = size;
+ vmap.flags = 0;
+ if (read_only)
+ vmap.flags |= I915_VMAP_READ_ONLY;
+
+ if (drmIoctl(fd, DRM_IOCTL_I915_GEM_VMAP, &vmap))
+ return 0;
+
+ return vmap.handle;
+}
+
+
+static void gem_vmap_sync(int fd, uint32_t handle)
+{
+ gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+}
+
+static void
+gem_read(int fd, uint32_t handle, int offset, int size, void *buf)
+{
+ struct drm_i915_gem_pread pread;
+ int ret;
+
+ pread.handle = handle;
+ pread.offset = offset;
+ pread.size = size;
+ pread.data_ptr = (uintptr_t)buf;
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
+ assert(ret == 0);
+}
+
+static void
+copy(int fd, uint32_t dst, uint32_t src)
+{
+ uint32_t batch[10];
+ struct drm_i915_gem_relocation_entry reloc[2];
+ struct drm_i915_gem_exec_object2 obj[3];
+ struct drm_i915_gem_execbuffer2 exec;
+ uint32_t handle;
+ int ret;
+
+ batch[0] = XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB;
+ batch[1] = (3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ WIDTH*4;
+ batch[2] = 0; /* dst x1,y1 */
+ batch[3] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */
+ batch[4] = 0; /* dst reloc */
+ batch[5] = 0; /* src x1,y1 */
+ batch[6] = WIDTH*4;
+ batch[7] = 0; /* src reloc */
+ batch[8] = MI_BATCH_BUFFER_END;
+ batch[9] = MI_NOOP;
+
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, sizeof(batch));
+
+ reloc[0].target_handle = dst;
+ reloc[0].delta = 0;
+ reloc[0].offset = 4 * sizeof(batch[0]);
+ reloc[0].presumed_offset = 0;
+ reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;;
+ reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
+
+ reloc[1].target_handle = src;
+ reloc[1].delta = 0;
+ reloc[1].offset = 7 * sizeof(batch[0]);
+ reloc[1].presumed_offset = 0;
+ reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;;
+ reloc[1].write_domain = 0;
+
+ obj[0].handle = dst;
+ obj[0].relocation_count = 0;
+ obj[0].relocs_ptr = 0;
+ obj[0].alignment = 0;
+ obj[0].offset = 0;
+ obj[0].flags = 0;
+ obj[0].rsvd1 = 0;
+ obj[0].rsvd2 = 0;
+
+ obj[1].handle = src;
+ obj[1].relocation_count = 0;
+ obj[1].relocs_ptr = 0;
+ obj[1].alignment = 0;
+ obj[1].offset = 0;
+ obj[1].flags = 0;
+ obj[1].rsvd1 = 0;
+ obj[1].rsvd2 = 0;
+
+ obj[2].handle = handle;
+ obj[2].relocation_count = 2;
+ obj[2].relocs_ptr = (uintptr_t)reloc;
+ obj[2].alignment = 0;
+ obj[2].offset = 0;
+ obj[2].flags = 0;
+ obj[2].rsvd1 = obj[2].rsvd2 = 0;
+
+ exec.buffers_ptr = (uintptr_t)obj;
+ exec.buffer_count = 3;
+ exec.batch_start_offset = 0;
+ exec.batch_len = sizeof(batch);
+ exec.DR1 = exec.DR4 = 0;
+ exec.num_cliprects = 0;
+ exec.cliprects_ptr = 0;
+ exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0;
+ exec.rsvd1 = exec.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ while (ret && errno == EBUSY) {
+ drmCommandNone(fd, DRM_I915_GEM_THROTTLE);
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ }
+ assert(ret == 0);
+
+ gem_close(fd, handle);
+}
+
+static uint32_t
+create_vmap(int fd, uint32_t val, uint32_t *ptr)
+{
+ uint32_t handle;
+ int i;
+
+ handle = gem_vmap(fd, ptr, sizeof(linear), 0);
+
+ /* Fill the BO with dwords starting at val */
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ ptr[i] = val++;
+
+ return handle;
+}
+
+static uint32_t
+create_bo(int fd, uint32_t val)
+{
+ uint32_t handle;
+ int i;
+
+ handle = gem_create(fd, sizeof(linear));
+
+ /* Fill the BO with dwords starting at val */
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ linear[i] = val++;
+ gem_write(fd, handle, 0, linear, sizeof(linear));
+
+ return handle;
+}
+
+static void
+check_cpu(uint32_t *ptr, uint32_t val)
+{
+ int i;
+
+ for (i = 0; i < WIDTH*HEIGHT; i++) {
+ if (ptr[i] != val) {
+ fprintf(stderr, "Expected 0x%08x, found 0x%08x "
+ "at offset 0x%08x\n",
+ val, ptr[i], i * 4);
+ abort();
+ }
+ val++;
+ }
+}
+
+static void
+check_gpu(int fd, uint32_t handle, uint32_t val)
+{
+ gem_read(fd, handle, 0, linear, sizeof(linear));
+ check_cpu(linear, val);
+}
+
+static int has_vmap(int fd)
+{
+ drm_i915_getparam_t gp;
+ int i;
+
+ gp.param = I915_PARAM_HAS_VMAP;
+ gp.value = &i;
+
+ return drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) == 0 && i > 0;
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t *memory;
+ uint32_t *cpu, *cpu_val;
+ uint32_t *gpu, *gpu_val;
+ uint32_t start = 0;
+ int i, fd, count;
+
+ fd = drm_open_any();
+
+ if (!has_vmap(fd)) {
+ fprintf(stderr, "No vmap support, ignoring.\n");
+ return 77;
+ }
+
+ count = 0;
+ if (argc > 1)
+ count = atoi(argv[1]);
+ if (count == 0)
+ count = 3 * gem_aperture_size(fd) / (1024*1024) / 4;
+ printf("Using 2x%d 1MiB buffers\n", count);
+
+ memory = malloc(count*sizeof(linear));
+ if (memory == NULL) {
+ fprintf(stderr, "Unable to allocate %lld bytes\n",
+ (long long)count*sizeof(linear));
+ return 1;
+ }
+
+ gpu = malloc(sizeof(uint32_t)*count*4);
+ gpu_val = gpu + count;
+ cpu = gpu_val + count;
+ cpu_val = cpu + count;
+
+ for (i = 0; i < count; i++) {
+ gpu[i] = create_bo(fd, start);
+ gpu_val[i] = start;
+ start += WIDTH*HEIGHT;
+ }
+
+ for (i = 0; i < count; i++) {
+ cpu[i] = create_vmap(fd, start, memory+i*WIDTH*HEIGHT);
+ cpu_val[i] = start;
+ start += WIDTH*HEIGHT;;
+ }
+
+ printf("Verifying initialisation...\n");
+ for (i = 0; i < count; i++) {
+ check_gpu(fd, gpu[i], gpu_val[i]);
+ check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
+ }
+
+ printf("Cyclic blits cpu->gpu, forward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = i % count;
+ int dst = (i + 1) % count;
+
+ copy(fd, gpu[dst], cpu[src]);
+ gpu_val[dst] = cpu_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_gpu(fd, gpu[i], gpu_val[i]);
+
+ printf("Cyclic blits gpu->cpu, backward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = (i + 1) % count;
+ int dst = i % count;
+
+ copy(fd, cpu[dst], gpu[src]);
+ cpu_val[dst] = gpu_val[src];
+ }
+ for (i = 0; i < count; i++) {
+ gem_vmap_sync(fd, cpu[i]);
+ check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
+ }
+
+ printf("Random blits...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = random() % count;
+ int dst = random() % count;
+
+ if (random() & 1) {
+ copy(fd, gpu[dst], cpu[src]);
+ gpu_val[dst] = cpu_val[src];
+ } else {
+ copy(fd, cpu[dst], gpu[src]);
+ cpu_val[dst] = gpu_val[src];
+ }
+ }
+ for (i = 0; i < count; i++) {
+ check_gpu(fd, gpu[i], gpu_val[i]);
+ gem_vmap_sync(fd, cpu[i]);
+ check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/tests/gem_wait_render_timeout.c b/tests/gem_wait_render_timeout.c
new file mode 100644
index 00000000..c321d36c
--- /dev/null
+++ b/tests/gem_wait_render_timeout.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include "drm.h"
+#include "rendercopy.h"
+
+#define MSEC_PER_SEC 1000L
+#define USEC_PER_MSEC 1000L
+#define NSEC_PER_USEC 1000L
+#define NSEC_PER_MSEC 1000000L
+#define USEC_PER_SEC 1000000L
+#define NSEC_PER_SEC 1000000000L
+
+#define ENOUGH_WORK_IN_SECONDS 2
+#define BUF_SIZE (8<<20)
+#define BUF_PAGES ((8<<20)>>12)
+drm_intel_bo *dst, *dst2;
+
+/* returns time diff in milliseconds */
+static int64_t
+do_time_diff(struct timespec *end, struct timespec *start)
+{
+ int64_t ret;
+ ret = (MSEC_PER_SEC * difftime(end->tv_sec, start->tv_sec)) +
+ ((end->tv_nsec/NSEC_PER_MSEC) - (start->tv_nsec/NSEC_PER_MSEC));
+ return ret;
+}
+
+/* to avoid stupid depencies on libdrm, copy&paste */
+struct local_drm_i915_gem_wait {
+ /** Handle of BO we shall wait on */
+ __u32 bo_handle;
+ __u32 flags;
+ /** Number of nanoseconds to wait, Returns time remaining. */
+ __u64 timeout_ns;
+};
+
+# define WAIT_IOCTL DRM_IOWR(DRM_COMMAND_BASE + 0x2c, struct local_drm_i915_gem_wait)
+
+static int
+gem_bo_wait_timeout(int fd, uint32_t handle, uint64_t *timeout_ns)
+{
+ struct local_drm_i915_gem_wait wait;
+ int ret;
+
+ assert(timeout_ns);
+
+ wait.bo_handle = handle;
+ wait.timeout_ns = *timeout_ns;
+ wait.flags = 0;
+ ret = drmIoctl(fd, WAIT_IOCTL, &wait);
+ *timeout_ns = wait.timeout_ns;
+
+ return ret ? -errno : 0;
+}
+
+static bool
+gem_bo_busy(int fd, uint32_t handle)
+{
+ struct drm_i915_gem_busy busy;
+
+ busy.handle = handle;
+ do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_BUSY, &busy));
+
+ return !!busy.busy;
+}
+
+static void blt_color_fill(struct intel_batchbuffer *batch,
+ drm_intel_bo *buf,
+ const unsigned int pages)
+{
+ const unsigned short height = pages/4;
+ const unsigned short width = 4096;
+ BEGIN_BATCH(5);
+ OUT_BATCH(COLOR_BLT_CMD |
+ COLOR_BLT_WRITE_ALPHA |
+ COLOR_BLT_WRITE_RGB);
+ OUT_BATCH((3 << 24) | /* 32 Bit Color */
+ 0xF0 | /* Raster OP copy background register */
+ 0); /* Dest pitch is 0 */
+ OUT_BATCH(width << 16 |
+ height);
+ OUT_RELOC(buf, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
+ OUT_BATCH(rand()); /* random pattern */
+ ADVANCE_BATCH();
+}
+
+int main(int argc, char **argv)
+{
+ drm_intel_bufmgr *bufmgr;
+ struct intel_batchbuffer *batch;
+ uint64_t timeout = ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC;
+ int fd, ret;
+ const bool do_signals = true; /* signals will seem to make the operation
+ * use less process CPU time */
+ bool done = false;
+ int i, iter = 1;
+
+ fd = drm_open_any();
+
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+
+ dst = drm_intel_bo_alloc(bufmgr, "dst", BUF_SIZE, 4096);
+ dst2 = drm_intel_bo_alloc(bufmgr, "dst2", BUF_SIZE, 4096);
+
+ if (gem_bo_wait_timeout(fd, dst->handle, &timeout) == -EINVAL) {
+ printf("kernel doesn't support wait_timeout, skipping test\n");
+ return -77;
+ }
+ timeout = ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC;
+
+ /* Figure out a rough number of fills required to consume 1 second of
+ * GPU work.
+ */
+ do {
+ struct timespec start, end;
+ long diff;
+
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
+#endif
+
+ assert(clock_gettime(CLOCK_MONOTONIC_RAW, &start) == 0);
+ for (i = 0; i < iter; i++)
+ blt_color_fill(batch, dst, BUF_PAGES);
+ intel_batchbuffer_flush(batch);
+ drm_intel_bo_wait_rendering(dst);
+ assert(clock_gettime(CLOCK_MONOTONIC_RAW, &end) == 0);
+
+ diff = do_time_diff(&end, &start);
+ assert(diff >= 0);
+
+ if ((diff / MSEC_PER_SEC) > ENOUGH_WORK_IN_SECONDS)
+ done = true;
+ else
+ iter <<= 1;
+ } while (!done && iter < 1000000);
+
+ assert(iter < 1000000);
+
+ printf("%d iters is enough work\n", iter);
+ gem_quiescent_gpu(fd);
+ if (do_signals)
+ drmtest_fork_signal_helper();
+
+ /* We should be able to do half as much work in the same amount of time,
+ * but because we might schedule almost twice as much as required, we
+ * might accidentally time out. Hence add some fudge. */
+ for (i = 0; i < iter/3; i++)
+ blt_color_fill(batch, dst2, BUF_PAGES);
+
+ intel_batchbuffer_flush(batch);
+ assert(gem_bo_busy(fd, dst2->handle) == true);
+
+ ret = gem_bo_wait_timeout(fd, dst2->handle, &timeout);
+ if (ret) {
+ fprintf(stderr, "Timed wait failed %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ assert(gem_bo_busy(fd, dst2->handle) == false);
+ assert(timeout != 0);
+ if (timeout == (ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC))
+ printf("Buffer was already done!\n");
+ else {
+ printf("Finished with %lu time remaining\n", timeout);
+ }
+
+ /* check that polling with timeout=0 works. */
+ timeout = 0;
+ assert(gem_bo_wait_timeout(fd, dst2->handle, &timeout) == 0);
+ assert(timeout == 0);
+
+ /* Now check that we correctly time out, twice the auto-tune load should
+ * be good enough. */
+ timeout = ENOUGH_WORK_IN_SECONDS * NSEC_PER_SEC;
+ for (i = 0; i < iter*2; i++)
+ blt_color_fill(batch, dst2, BUF_PAGES);
+
+ intel_batchbuffer_flush(batch);
+
+ ret = gem_bo_wait_timeout(fd, dst2->handle, &timeout);
+ assert(ret == -ETIME);
+ assert(timeout == 0);
+ assert(gem_bo_busy(fd, dst2->handle) == true);
+
+ /* check that polling with timeout=0 works. */
+ timeout = 0;
+ assert(gem_bo_wait_timeout(fd, dst2->handle, &timeout) == -ETIME);
+ assert(timeout == 0);
+
+
+ if (do_signals)
+ drmtest_stop_signal_helper();
+ drm_intel_bo_unreference(dst2);
+ drm_intel_bo_unreference(dst);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(fd);
+
+ return 0;
+}
diff --git a/tests/gen3_mixed_blits.c b/tests/gen3_mixed_blits.c
new file mode 100644
index 00000000..5bb6d868
--- /dev/null
+++ b/tests/gen3_mixed_blits.c
@@ -0,0 +1,541 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file gen3_linear_render_blits.c
+ *
+ * This is a test of doing many blits, with a working set
+ * larger than the aperture size.
+ *
+ * The goal is to simply ensure the basics work.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#include "i915_reg.h"
+#include "i915_3d.h"
+
+#define WIDTH (512)
+#define HEIGHT (512)
+
+static inline uint32_t pack_float(float f)
+{
+ union {
+ uint32_t dw;
+ float f;
+ } u;
+ u.f = f;
+ return u.dw;
+}
+
+static uint32_t fill_reloc(struct drm_i915_gem_relocation_entry *reloc,
+ uint32_t offset,
+ uint32_t handle,
+ uint32_t read_domain,
+ uint32_t write_domain)
+{
+ reloc->target_handle = handle;
+ reloc->delta = 0;
+ reloc->offset = offset * sizeof(uint32_t);
+ reloc->presumed_offset = 0;
+ reloc->read_domains = read_domain;
+ reloc->write_domain = write_domain;
+
+ return reloc->presumed_offset + reloc->delta;
+}
+
+static void
+render_copy(int fd,
+ uint32_t dst, int dst_tiling,
+ uint32_t src, int src_tiling,
+ int use_fence)
+{
+ uint32_t batch[1024], *b = batch;
+ struct drm_i915_gem_relocation_entry reloc[2], *r = reloc;
+ struct drm_i915_gem_exec_object2 obj[3];
+ struct drm_i915_gem_execbuffer2 exec;
+ uint32_t handle;
+ uint32_t tiling_bits;
+ int ret;
+
+ /* invariant state */
+ *b++ = (_3DSTATE_AA_CMD |
+ AA_LINE_ECAAR_WIDTH_ENABLE |
+ AA_LINE_ECAAR_WIDTH_1_0 |
+ AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
+ *b++ = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+ IAB_MODIFY_ENABLE |
+ IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
+ IAB_MODIFY_SRC_FACTOR |
+ (BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT) |
+ IAB_MODIFY_DST_FACTOR |
+ (BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT));
+ *b++ = (_3DSTATE_DFLT_DIFFUSE_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_SPEC_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_Z_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_COORD_SET_BINDINGS |
+ CSB_TCB(0, 0) |
+ CSB_TCB(1, 1) |
+ CSB_TCB(2, 2) |
+ CSB_TCB(3, 3) |
+ CSB_TCB(4, 4) |
+ CSB_TCB(5, 5) |
+ CSB_TCB(6, 6) |
+ CSB_TCB(7, 7));
+ *b++ = (_3DSTATE_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) |
+ ENABLE_TEXKILL_3D_4D |
+ TEXKILL_4D);
+ *b++ = (_3DSTATE_MODES_4_CMD |
+ ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
+ ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) |
+ ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff));
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 2);
+ *b++ = (0x00000000); /* Disable texture coordinate wrap-shortest */
+ *b++ = ((1 << S4_POINT_WIDTH_SHIFT) |
+ S4_LINE_WIDTH_ONE |
+ S4_CULLMODE_NONE |
+ S4_VFMT_XY);
+ *b++ = (0x00000000); /* Stencil. */
+ *b++ = (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+ *b++ = (_3DSTATE_SCISSOR_RECT_0_CMD);
+ *b++ = (0);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DEPTH_SUBRECT_DISABLE);
+ *b++ = (_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
+ *b++ = (0);
+ *b++ = (_3DSTATE_STIPPLE);
+ *b++ = (0x00000000);
+ *b++ = (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
+
+ /* samler state */
+ if (use_fence) {
+ tiling_bits = MS3_USE_FENCE_REGS;
+ } else {
+ tiling_bits = 0;
+ if (src_tiling != I915_TILING_NONE)
+ tiling_bits = MS3_TILED_SURFACE;
+ if (src_tiling == I915_TILING_Y)
+ tiling_bits |= MS3_TILE_WALK;
+ }
+
+#define TEX_COUNT 1
+ *b++ = (_3DSTATE_MAP_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b = fill_reloc(r++, b-batch, src, I915_GEM_DOMAIN_SAMPLER, 0); b++;
+ *b++ = (MAPSURF_32BIT | MT_32BIT_ARGB8888 | tiling_bits |
+ (HEIGHT - 1) << MS3_HEIGHT_SHIFT |
+ (WIDTH - 1) << MS3_WIDTH_SHIFT);
+ *b++ = ((WIDTH-1) << MS4_PITCH_SHIFT);
+
+ *b++ = (_3DSTATE_SAMPLER_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b++ = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MAG_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+ *b++ = (TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT |
+ TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT |
+ 0 << SS3_TEXTUREMAP_INDEX_SHIFT);
+ *b++ = (0x00000000);
+
+ /* render target state */
+ if (use_fence) {
+ tiling_bits = BUF_3D_USE_FENCE;
+ } else {
+ tiling_bits = 0;
+ if (dst_tiling != I915_TILING_NONE)
+ tiling_bits = BUF_3D_TILED_SURFACE;
+ if (dst_tiling == I915_TILING_Y)
+ tiling_bits |= BUF_3D_TILE_WALK_Y;
+ }
+ *b++ = (_3DSTATE_BUF_INFO_CMD);
+ *b++ = (BUF_3D_ID_COLOR_BACK | tiling_bits | WIDTH*4);
+ *b = fill_reloc(r++, b-batch, dst,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+ b++;
+
+ *b++ = (_3DSTATE_DST_BUF_VARS_CMD);
+ *b++ = (COLR_BUF_ARGB8888 |
+ DSTORG_HORT_BIAS(0x8) |
+ DSTORG_VERT_BIAS(0x8));
+
+ /* draw rect is unconditional */
+ *b++ = (_3DSTATE_DRAW_RECT_CMD);
+ *b++ = (0x00000000);
+ *b++ = (0x00000000); /* ymin, xmin */
+ *b++ = (DRAW_YMAX(HEIGHT - 1) |
+ DRAW_XMAX(WIDTH - 1));
+ /* yorig, xorig (relate to color buffer?) */
+ *b++ = (0x00000000);
+
+ /* texfmt */
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(1) | I1_LOAD_S(2) | I1_LOAD_S(6) | 2);
+ *b++ = ((4 << S1_VERTEX_WIDTH_SHIFT) | (4 << S1_VERTEX_PITCH_SHIFT));
+ *b++ = (~S2_TEXCOORD_FMT(0, TEXCOORDFMT_NOT_PRESENT) |
+ S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D));
+ *b++ = (S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+ BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT |
+ BLENDFACT_ONE << S6_CBUF_SRC_BLEND_FACT_SHIFT |
+ BLENDFACT_ZERO << S6_CBUF_DST_BLEND_FACT_SHIFT);
+
+ /* pixel shader */
+ *b++ = (_3DSTATE_PIXEL_SHADER_PROGRAM | (1 + 3*3 - 2));
+ /* decl FS_T0 */
+ *b++ = (D0_DCL |
+ REG_TYPE(FS_T0) << D0_TYPE_SHIFT |
+ REG_NR(FS_T0) << D0_NR_SHIFT |
+ ((REG_TYPE(FS_T0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* decl FS_S0 */
+ *b++ = (D0_DCL |
+ (REG_TYPE(FS_S0) << D0_TYPE_SHIFT) |
+ (REG_NR(FS_S0) << D0_NR_SHIFT) |
+ ((REG_TYPE(FS_S0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* texld(FS_OC, FS_S0, FS_T0 */
+ *b++ = (T0_TEXLD |
+ (REG_TYPE(FS_OC) << T0_DEST_TYPE_SHIFT) |
+ (REG_NR(FS_OC) << T0_DEST_NR_SHIFT) |
+ (REG_NR(FS_S0) << T0_SAMPLER_NR_SHIFT));
+ *b++ = ((REG_TYPE(FS_T0) << T1_ADDRESS_REG_TYPE_SHIFT) |
+ (REG_NR(FS_T0) << T1_ADDRESS_REG_NR_SHIFT));
+ *b++ = (0);
+
+ *b++ = (PRIM3D_RECTLIST | (3*4 - 1));
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+
+ *b++ = MI_BATCH_BUFFER_END;
+ if ((b - batch) & 1)
+ *b++ = 0;
+
+ assert(b - batch <= 1024);
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0]));
+
+ assert(r-reloc == 2);
+
+ tiling_bits = 0;
+ if (use_fence)
+ tiling_bits = EXEC_OBJECT_NEEDS_FENCE;
+
+ obj[0].handle = dst;
+ obj[0].relocation_count = 0;
+ obj[0].relocs_ptr = 0;
+ obj[0].alignment = 0;
+ obj[0].offset = 0;
+ obj[0].flags = tiling_bits;
+ obj[0].rsvd1 = 0;
+ obj[0].rsvd2 = 0;
+
+ obj[1].handle = src;
+ obj[1].relocation_count = 0;
+ obj[1].relocs_ptr = 0;
+ obj[1].alignment = 0;
+ obj[1].offset = 0;
+ obj[1].flags = tiling_bits;
+ obj[1].rsvd1 = 0;
+ obj[1].rsvd2 = 0;
+
+ obj[2].handle = handle;
+ obj[2].relocation_count = 2;
+ obj[2].relocs_ptr = (uintptr_t)reloc;
+ obj[2].alignment = 0;
+ obj[2].offset = 0;
+ obj[2].flags = 0;
+ obj[2].rsvd1 = obj[2].rsvd2 = 0;
+
+ exec.buffers_ptr = (uintptr_t)obj;
+ exec.buffer_count = 3;
+ exec.batch_start_offset = 0;
+ exec.batch_len = (b-batch)*sizeof(batch[0]);
+ exec.DR1 = exec.DR4 = 0;
+ exec.num_cliprects = 0;
+ exec.cliprects_ptr = 0;
+ exec.flags = 0;
+ i915_execbuffer2_set_context_id(exec, 0);
+ exec.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ while (ret && errno == EBUSY) {
+ drmCommandNone(fd, DRM_I915_GEM_THROTTLE);
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ }
+ assert(ret == 0);
+
+ gem_close(fd, handle);
+}
+
+static void blt_copy(int fd, uint32_t dst, uint32_t src)
+{
+ uint32_t batch[1024], *b = batch;
+ struct drm_i915_gem_relocation_entry reloc[2], *r = reloc;
+ struct drm_i915_gem_exec_object2 obj[3];
+ struct drm_i915_gem_execbuffer2 exec;
+ uint32_t handle;
+ int ret;
+
+ *b++ = (XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ *b++ = 3 << 24 | 0xcc << 16 | WIDTH * 4;
+ *b++ = 0;
+ *b++ = HEIGHT << 16 | WIDTH;
+ *b = fill_reloc(r++, b-batch, dst,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); b++;
+ *b++ = 0;
+ *b++ = WIDTH*4;
+ *b = fill_reloc(r++, b-batch, src, I915_GEM_DOMAIN_RENDER, 0); b++;
+
+ *b++ = MI_BATCH_BUFFER_END;
+ if ((b - batch) & 1)
+ *b++ = 0;
+
+ assert(b - batch <= 1024);
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0]));
+
+ assert(r-reloc == 2);
+
+ obj[0].handle = dst;
+ obj[0].relocation_count = 0;
+ obj[0].relocs_ptr = 0;
+ obj[0].alignment = 0;
+ obj[0].offset = 0;
+ obj[0].flags = EXEC_OBJECT_NEEDS_FENCE;
+ obj[0].rsvd1 = 0;
+ obj[0].rsvd2 = 0;
+
+ obj[1].handle = src;
+ obj[1].relocation_count = 0;
+ obj[1].relocs_ptr = 0;
+ obj[1].alignment = 0;
+ obj[1].offset = 0;
+ obj[1].flags = EXEC_OBJECT_NEEDS_FENCE;
+ obj[1].rsvd1 = 0;
+ obj[1].rsvd2 = 0;
+
+ obj[2].handle = handle;
+ obj[2].relocation_count = 2;
+ obj[2].relocs_ptr = (uintptr_t)reloc;
+ obj[2].alignment = 0;
+ obj[2].offset = 0;
+ obj[2].flags = 0;
+ obj[2].rsvd1 = obj[2].rsvd2 = 0;
+
+ exec.buffers_ptr = (uintptr_t)obj;
+ exec.buffer_count = 3;
+ exec.batch_start_offset = 0;
+ exec.batch_len = (b-batch)*sizeof(batch[0]);
+ exec.DR1 = exec.DR4 = 0;
+ exec.num_cliprects = 0;
+ exec.cliprects_ptr = 0;
+ exec.flags = 0;
+ i915_execbuffer2_set_context_id(exec, 0);
+ exec.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ while (ret && errno == EBUSY) {
+ drmCommandNone(fd, DRM_I915_GEM_THROTTLE);
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ }
+ assert(ret == 0);
+
+ gem_close(fd, handle);
+}
+
+
+static void
+copy(int fd,
+ uint32_t dst, int dst_tiling,
+ uint32_t src, int src_tiling)
+{
+retry:
+ switch (random() % 3) {
+ case 0: render_copy(fd, dst, dst_tiling, src, src_tiling, 0); break;
+ case 1: render_copy(fd, dst, dst_tiling, src, src_tiling, 1); break;
+ case 2: if (dst_tiling == I915_TILING_Y || src_tiling == I915_TILING_Y)
+ goto retry;
+ blt_copy(fd, dst, src);
+ break;
+ }
+}
+
+static uint32_t
+create_bo(int fd, uint32_t val, int tiling)
+{
+ uint32_t handle;
+ uint32_t *v;
+ int i;
+
+ handle = gem_create(fd, WIDTH*HEIGHT*4);
+ gem_set_tiling(fd, handle, tiling, WIDTH*4);
+
+ /* Fill the BO with dwords starting at val */
+ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ | PROT_WRITE);
+ assert(v);
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ v[i] = val++;
+ munmap(v, WIDTH*HEIGHT*4);
+
+ return handle;
+}
+
+static void
+check_bo(int fd, uint32_t handle, uint32_t val)
+{
+ uint32_t *v;
+ int i;
+
+ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ);
+ assert(v);
+ for (i = 0; i < WIDTH*HEIGHT; i++) {
+ if (v[i] != val) {
+ fprintf(stderr, "Expected 0x%08x, found 0x%08x "
+ "at offset 0x%08x\n",
+ val, v[i], i * 4);
+ abort();
+ }
+ val++;
+ }
+ munmap(v, WIDTH*HEIGHT*4);
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t *handle, *tiling, *start_val;
+ uint32_t start = 0;
+ int i, fd, count;
+
+ fd = drm_open_any();
+
+ if (!IS_GEN3(intel_get_drm_devid(fd))) {
+ printf("gen3-only test, doing nothing\n");
+ return 77;
+ }
+
+ count = 0;
+ if (argc > 1)
+ count = atoi(argv[1]);
+ if (count == 0)
+ count = 3 * gem_aperture_size(fd) / (1024*1024) / 2;
+ printf("Using %d 1MiB buffers\n", count);
+
+ handle = malloc(sizeof(uint32_t)*count*3);
+ tiling = handle + count;
+ start_val = tiling + count;
+
+ for (i = 0; i < count; i++) {
+ handle[i] = create_bo(fd, start, tiling[i] = i % 3);
+ start_val[i] = start;
+ start += 1024 * 1024 / 4;
+ }
+
+ printf("Verifying initialisation..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ printf("Cyclic blits, forward..."); fflush(stdout);
+ for (i = 0; i < count * 32; i++) {
+ int src = i % count;
+ int dst = (i + 1) % count;
+
+ copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]);
+ start_val[dst] = start_val[src];
+ }
+ printf("verifying..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ printf("Cyclic blits, backward..."); fflush(stdout);
+ for (i = 0; i < count * 32; i++) {
+ int src = (i + 1) % count;
+ int dst = i % count;
+
+ copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]);
+ start_val[dst] = start_val[src];
+ }
+ printf("verifying..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ printf("Random blits..."); fflush(stdout);
+ for (i = 0; i < count * 32; i++) {
+ int src = random() % count;
+ int dst = random() % count;
+
+ while (src == dst)
+ dst = random() % count;
+
+ copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]);
+ start_val[dst] = start_val[src];
+ }
+ printf("verifying..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ return 0;
+}
diff --git a/tests/gen3_render_linear_blits.c b/tests/gen3_render_linear_blits.c
new file mode 100644
index 00000000..529e23ff
--- /dev/null
+++ b/tests/gen3_render_linear_blits.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file gen3_linear_render_blits.c
+ *
+ * This is a test of doing many blits, with a working set
+ * larger than the aperture size.
+ *
+ * The goal is to simply ensure the basics work.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#include "i915_reg.h"
+#include "i915_3d.h"
+
+#define WIDTH 512
+#define HEIGHT 512
+
+static uint32_t linear[WIDTH*HEIGHT];
+
+static inline uint32_t pack_float(float f)
+{
+ union {
+ uint32_t dw;
+ float f;
+ } u;
+ u.f = f;
+ return u.dw;
+}
+
+static uint32_t fill_reloc(struct drm_i915_gem_relocation_entry *reloc,
+ uint32_t offset,
+ uint32_t handle,
+ uint32_t read_domain,
+ uint32_t write_domain)
+{
+ reloc->target_handle = handle;
+ reloc->delta = 0;
+ reloc->offset = offset * sizeof(uint32_t);
+ reloc->presumed_offset = 0;
+ reloc->read_domains = read_domain;
+ reloc->write_domain = write_domain;
+
+ return reloc->presumed_offset + reloc->delta;
+}
+
+static void
+copy(int fd, uint32_t dst, uint32_t src)
+{
+ uint32_t batch[1024], *b = batch;
+ struct drm_i915_gem_relocation_entry reloc[2], *r = reloc;
+ struct drm_i915_gem_exec_object2 obj[3];
+ struct drm_i915_gem_execbuffer2 exec;
+ uint32_t handle;
+ int ret;
+
+ /* invariant state */
+ *b++ = (_3DSTATE_AA_CMD |
+ AA_LINE_ECAAR_WIDTH_ENABLE |
+ AA_LINE_ECAAR_WIDTH_1_0 |
+ AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
+ *b++ = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+ IAB_MODIFY_ENABLE |
+ IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
+ IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE <<
+ IAB_SRC_FACTOR_SHIFT) |
+ IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO <<
+ IAB_DST_FACTOR_SHIFT));
+ *b++ = (_3DSTATE_DFLT_DIFFUSE_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_SPEC_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_Z_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_COORD_SET_BINDINGS |
+ CSB_TCB(0, 0) |
+ CSB_TCB(1, 1) |
+ CSB_TCB(2, 2) |
+ CSB_TCB(3, 3) |
+ CSB_TCB(4, 4) |
+ CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7));
+ *b++ = (_3DSTATE_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D);
+ *b++ = (_3DSTATE_MODES_4_CMD |
+ ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
+ ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) |
+ ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff));
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 2);
+ *b++ = (0x00000000); /* Disable texture coordinate wrap-shortest */
+ *b++ = ((1 << S4_POINT_WIDTH_SHIFT) |
+ S4_LINE_WIDTH_ONE |
+ S4_CULLMODE_NONE |
+ S4_VFMT_XY);
+ *b++ = (0x00000000); /* Stencil. */
+ *b++ = (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+ *b++ = (_3DSTATE_SCISSOR_RECT_0_CMD);
+ *b++ = (0);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DEPTH_SUBRECT_DISABLE);
+ *b++ = (_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
+ *b++ = (0);
+ *b++ = (_3DSTATE_STIPPLE);
+ *b++ = (0x00000000);
+ *b++ = (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
+
+ /* samler state */
+#define TEX_COUNT 1
+ *b++ = (_3DSTATE_MAP_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b = fill_reloc(r++, b-batch, src, I915_GEM_DOMAIN_SAMPLER, 0); b++;
+ *b++ = (MAPSURF_32BIT | MT_32BIT_ARGB8888 |
+ (HEIGHT - 1) << MS3_HEIGHT_SHIFT |
+ (WIDTH - 1) << MS3_WIDTH_SHIFT);
+ *b++ = ((WIDTH-1) << MS4_PITCH_SHIFT);
+
+ *b++ = (_3DSTATE_SAMPLER_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b++ = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MAG_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+ *b++ = (TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT |
+ TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT |
+ 0 << SS3_TEXTUREMAP_INDEX_SHIFT);
+ *b++ = (0x00000000);
+
+ /* render target state */
+ *b++ = (_3DSTATE_BUF_INFO_CMD);
+ *b++ = (BUF_3D_ID_COLOR_BACK | WIDTH*4);
+ *b = fill_reloc(r++, b-batch, dst,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+ b++;
+
+ *b++ = (_3DSTATE_DST_BUF_VARS_CMD);
+ *b++ = (COLR_BUF_ARGB8888 |
+ DSTORG_HORT_BIAS(0x8) |
+ DSTORG_VERT_BIAS(0x8));
+
+ /* draw rect is unconditional */
+ *b++ = (_3DSTATE_DRAW_RECT_CMD);
+ *b++ = (0x00000000);
+ *b++ = (0x00000000); /* ymin, xmin */
+ *b++ = (DRAW_YMAX(HEIGHT - 1) |
+ DRAW_XMAX(WIDTH - 1));
+ /* yorig, xorig (relate to color buffer?) */
+ *b++ = (0x00000000);
+
+ /* texfmt */
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(1) | I1_LOAD_S(2) | I1_LOAD_S(6) | 2);
+ *b++ = ((4 << S1_VERTEX_WIDTH_SHIFT) | (4 << S1_VERTEX_PITCH_SHIFT));
+ *b++ = (~S2_TEXCOORD_FMT(0, TEXCOORDFMT_NOT_PRESENT) |
+ S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D));
+ *b++ = (S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+ BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT |
+ BLENDFACT_ONE << S6_CBUF_SRC_BLEND_FACT_SHIFT |
+ BLENDFACT_ZERO << S6_CBUF_DST_BLEND_FACT_SHIFT);
+
+ /* pixel shader */
+ *b++ = (_3DSTATE_PIXEL_SHADER_PROGRAM | (1 + 3*3 - 2));
+ /* decl FS_T0 */
+ *b++ = (D0_DCL |
+ REG_TYPE(FS_T0) << D0_TYPE_SHIFT |
+ REG_NR(FS_T0) << D0_NR_SHIFT |
+ ((REG_TYPE(FS_T0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* decl FS_S0 */
+ *b++ = (D0_DCL |
+ (REG_TYPE(FS_S0) << D0_TYPE_SHIFT) |
+ (REG_NR(FS_S0) << D0_NR_SHIFT) |
+ ((REG_TYPE(FS_S0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* texld(FS_OC, FS_S0, FS_T0 */
+ *b++ = (T0_TEXLD |
+ (REG_TYPE(FS_OC) << T0_DEST_TYPE_SHIFT) |
+ (REG_NR(FS_OC) << T0_DEST_NR_SHIFT) |
+ (REG_NR(FS_S0) << T0_SAMPLER_NR_SHIFT));
+ *b++ = ((REG_TYPE(FS_T0) << T1_ADDRESS_REG_TYPE_SHIFT) |
+ (REG_NR(FS_T0) << T1_ADDRESS_REG_NR_SHIFT));
+ *b++ = (0);
+
+ *b++ = (PRIM3D_RECTLIST | (3*4 - 1));
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+
+ *b++ = MI_BATCH_BUFFER_END;
+ if ((b - batch) & 1)
+ *b++ = 0;
+
+ assert(b - batch <= 1024);
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0]));
+
+ assert(r-reloc == 2);
+
+ obj[0].handle = dst;
+ obj[0].relocation_count = 0;
+ obj[0].relocs_ptr = 0;
+ obj[0].alignment = 0;
+ obj[0].offset = 0;
+ obj[0].flags = 0;
+ obj[0].rsvd1 = 0;
+ obj[0].rsvd2 = 0;
+
+ obj[1].handle = src;
+ obj[1].relocation_count = 0;
+ obj[1].relocs_ptr = 0;
+ obj[1].alignment = 0;
+ obj[1].offset = 0;
+ obj[1].flags = 0;
+ obj[1].rsvd1 = 0;
+ obj[1].rsvd2 = 0;
+
+ obj[2].handle = handle;
+ obj[2].relocation_count = 2;
+ obj[2].relocs_ptr = (uintptr_t)reloc;
+ obj[2].alignment = 0;
+ obj[2].offset = 0;
+ obj[2].flags = 0;
+ obj[2].rsvd1 = obj[2].rsvd2 = 0;
+
+ exec.buffers_ptr = (uintptr_t)obj;
+ exec.buffer_count = 3;
+ exec.batch_start_offset = 0;
+ exec.batch_len = (b-batch)*sizeof(batch[0]);
+ exec.DR1 = exec.DR4 = 0;
+ exec.num_cliprects = 0;
+ exec.cliprects_ptr = 0;
+ exec.flags = 0;
+ i915_execbuffer2_set_context_id(exec, 0);
+ exec.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ while (ret && errno == EBUSY) {
+ drmCommandNone(fd, DRM_I915_GEM_THROTTLE);
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ }
+ assert(ret == 0);
+
+ gem_close(fd, handle);
+}
+
+static uint32_t
+create_bo(int fd, uint32_t val)
+{
+ uint32_t handle;
+ int i;
+
+ handle = gem_create(fd, sizeof(linear));
+
+ /* Fill the BO with dwords starting at val */
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ linear[i] = val++;
+ gem_write(fd, handle, 0, linear, sizeof(linear));
+
+ return handle;
+}
+
+static void
+check_bo(int fd, uint32_t handle, uint32_t val)
+{
+ int i;
+
+ gem_read(fd, handle, 0, linear, sizeof(linear));
+ for (i = 0; i < WIDTH*HEIGHT; i++) {
+ if (linear[i] != val) {
+ fprintf(stderr, "Expected 0x%08x, found 0x%08x "
+ "at offset 0x%08x\n",
+ val, linear[i], i * 4);
+ abort();
+ }
+ val++;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t *handle, *start_val;
+ uint32_t start = 0;
+ int i, fd, count;
+
+ fd = drm_open_any();
+
+ if (!IS_GEN3(intel_get_drm_devid(fd))) {
+ printf("gen3-only test, doing nothing\n");
+ return 77;
+ }
+
+ count = 0;
+ if (argc > 1)
+ count = atoi(argv[1]);
+ if (count == 0)
+ count = 3 * gem_aperture_size(fd) / (1024*1024) / 2;
+ printf("Using %d 1MiB buffers\n", count);
+
+ handle = malloc(sizeof(uint32_t)*count*2);
+ start_val = handle + count;
+
+ for (i = 0; i < count; i++) {
+ handle[i] = create_bo(fd, start);
+ start_val[i] = start;
+ start += 1024 * 1024 / 4;
+ }
+
+ printf("Verifying initialisation...\n");
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ printf("Cyclic blits, forward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = i % count;
+ int dst = (i + 1) % count;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ printf("Cyclic blits, backward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = (i + 1) % count;
+ int dst = i % count;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ printf("Random blits...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = random() % count;
+ int dst = random() % count;
+
+ if (src == dst)
+ continue;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ return 0;
+}
diff --git a/tests/gen3_render_mixed_blits.c b/tests/gen3_render_mixed_blits.c
new file mode 100644
index 00000000..1353b9d7
--- /dev/null
+++ b/tests/gen3_render_mixed_blits.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file gen3_linear_render_blits.c
+ *
+ * This is a test of doing many blits, with a working set
+ * larger than the aperture size.
+ *
+ * The goal is to simply ensure the basics work.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#include "i915_reg.h"
+#include "i915_3d.h"
+
+#define WIDTH 512
+#define HEIGHT 512
+
+static inline uint32_t pack_float(float f)
+{
+ union {
+ uint32_t dw;
+ float f;
+ } u;
+ u.f = f;
+ return u.dw;
+}
+
+static uint32_t fill_reloc(struct drm_i915_gem_relocation_entry *reloc,
+ uint32_t offset,
+ uint32_t handle,
+ uint32_t read_domain,
+ uint32_t write_domain)
+{
+ reloc->target_handle = handle;
+ reloc->delta = 0;
+ reloc->offset = offset * sizeof(uint32_t);
+ reloc->presumed_offset = 0;
+ reloc->read_domains = read_domain;
+ reloc->write_domain = write_domain;
+
+ return reloc->presumed_offset + reloc->delta;
+}
+
+static void
+copy(int fd,
+ uint32_t dst, int dst_tiling,
+ uint32_t src, int src_tiling)
+{
+ uint32_t batch[1024], *b = batch;
+ struct drm_i915_gem_relocation_entry reloc[2], *r = reloc;
+ struct drm_i915_gem_exec_object2 obj[3];
+ struct drm_i915_gem_execbuffer2 exec;
+ uint32_t handle;
+ uint32_t tiling_bits;
+ int ret;
+
+ /* invariant state */
+ *b++ = (_3DSTATE_AA_CMD |
+ AA_LINE_ECAAR_WIDTH_ENABLE |
+ AA_LINE_ECAAR_WIDTH_1_0 |
+ AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
+ *b++ = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+ IAB_MODIFY_ENABLE |
+ IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
+ IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE <<
+ IAB_SRC_FACTOR_SHIFT) |
+ IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO <<
+ IAB_DST_FACTOR_SHIFT));
+ *b++ = (_3DSTATE_DFLT_DIFFUSE_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_SPEC_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_Z_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_COORD_SET_BINDINGS |
+ CSB_TCB(0, 0) |
+ CSB_TCB(1, 1) |
+ CSB_TCB(2, 2) |
+ CSB_TCB(3, 3) |
+ CSB_TCB(4, 4) |
+ CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7));
+ *b++ = (_3DSTATE_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D);
+ *b++ = (_3DSTATE_MODES_4_CMD |
+ ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
+ ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) |
+ ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff));
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 2);
+ *b++ = (0x00000000); /* Disable texture coordinate wrap-shortest */
+ *b++ = ((1 << S4_POINT_WIDTH_SHIFT) |
+ S4_LINE_WIDTH_ONE |
+ S4_CULLMODE_NONE |
+ S4_VFMT_XY);
+ *b++ = (0x00000000); /* Stencil. */
+ *b++ = (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+ *b++ = (_3DSTATE_SCISSOR_RECT_0_CMD);
+ *b++ = (0);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DEPTH_SUBRECT_DISABLE);
+ *b++ = (_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
+ *b++ = (0);
+ *b++ = (_3DSTATE_STIPPLE);
+ *b++ = (0x00000000);
+ *b++ = (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
+
+ /* samler state */
+ tiling_bits = 0;
+ if (src_tiling != I915_TILING_NONE)
+ tiling_bits = MS3_TILED_SURFACE;
+ if (src_tiling == I915_TILING_Y)
+ tiling_bits |= MS3_TILE_WALK;
+
+#define TEX_COUNT 1
+ *b++ = (_3DSTATE_MAP_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b = fill_reloc(r++, b-batch, src, I915_GEM_DOMAIN_SAMPLER, 0); b++;
+ *b++ = (MAPSURF_32BIT | MT_32BIT_ARGB8888 | tiling_bits |
+ (HEIGHT - 1) << MS3_HEIGHT_SHIFT |
+ (WIDTH - 1) << MS3_WIDTH_SHIFT);
+ *b++ = ((WIDTH-1) << MS4_PITCH_SHIFT);
+
+ *b++ = (_3DSTATE_SAMPLER_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b++ = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MAG_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+ *b++ = (TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT |
+ TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT |
+ 0 << SS3_TEXTUREMAP_INDEX_SHIFT);
+ *b++ = (0x00000000);
+
+ /* render target state */
+ tiling_bits = 0;
+ if (dst_tiling != I915_TILING_NONE)
+ tiling_bits = BUF_3D_TILED_SURFACE;
+ if (dst_tiling == I915_TILING_Y)
+ tiling_bits |= BUF_3D_TILE_WALK_Y;
+ *b++ = (_3DSTATE_BUF_INFO_CMD);
+ *b++ = (BUF_3D_ID_COLOR_BACK | tiling_bits | WIDTH*4);
+ *b = fill_reloc(r++, b-batch, dst,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+ b++;
+
+ *b++ = (_3DSTATE_DST_BUF_VARS_CMD);
+ *b++ = (COLR_BUF_ARGB8888 |
+ DSTORG_HORT_BIAS(0x8) |
+ DSTORG_VERT_BIAS(0x8));
+
+ /* draw rect is unconditional */
+ *b++ = (_3DSTATE_DRAW_RECT_CMD);
+ *b++ = (0x00000000);
+ *b++ = (0x00000000); /* ymin, xmin */
+ *b++ = (DRAW_YMAX(HEIGHT - 1) |
+ DRAW_XMAX(WIDTH - 1));
+ /* yorig, xorig (relate to color buffer?) */
+ *b++ = (0x00000000);
+
+ /* texfmt */
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(1) | I1_LOAD_S(2) | I1_LOAD_S(6) | 2);
+ *b++ = ((4 << S1_VERTEX_WIDTH_SHIFT) | (4 << S1_VERTEX_PITCH_SHIFT));
+ *b++ = (~S2_TEXCOORD_FMT(0, TEXCOORDFMT_NOT_PRESENT) |
+ S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D));
+ *b++ = (S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+ BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT |
+ BLENDFACT_ONE << S6_CBUF_SRC_BLEND_FACT_SHIFT |
+ BLENDFACT_ZERO << S6_CBUF_DST_BLEND_FACT_SHIFT);
+
+ /* pixel shader */
+ *b++ = (_3DSTATE_PIXEL_SHADER_PROGRAM | (1 + 3*3 - 2));
+ /* decl FS_T0 */
+ *b++ = (D0_DCL |
+ REG_TYPE(FS_T0) << D0_TYPE_SHIFT |
+ REG_NR(FS_T0) << D0_NR_SHIFT |
+ ((REG_TYPE(FS_T0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* decl FS_S0 */
+ *b++ = (D0_DCL |
+ (REG_TYPE(FS_S0) << D0_TYPE_SHIFT) |
+ (REG_NR(FS_S0) << D0_NR_SHIFT) |
+ ((REG_TYPE(FS_S0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* texld(FS_OC, FS_S0, FS_T0 */
+ *b++ = (T0_TEXLD |
+ (REG_TYPE(FS_OC) << T0_DEST_TYPE_SHIFT) |
+ (REG_NR(FS_OC) << T0_DEST_NR_SHIFT) |
+ (REG_NR(FS_S0) << T0_SAMPLER_NR_SHIFT));
+ *b++ = ((REG_TYPE(FS_T0) << T1_ADDRESS_REG_TYPE_SHIFT) |
+ (REG_NR(FS_T0) << T1_ADDRESS_REG_NR_SHIFT));
+ *b++ = (0);
+
+ *b++ = (PRIM3D_RECTLIST | (3*4 - 1));
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+
+ *b++ = MI_BATCH_BUFFER_END;
+ if ((b - batch) & 1)
+ *b++ = 0;
+
+ assert(b - batch <= 1024);
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0]));
+
+ assert(r-reloc == 2);
+
+ obj[0].handle = dst;
+ obj[0].relocation_count = 0;
+ obj[0].relocs_ptr = 0;
+ obj[0].alignment = 0;
+ obj[0].offset = 0;
+ obj[0].flags = 0;
+ obj[0].rsvd1 = 0;
+ obj[0].rsvd2 = 0;
+
+ obj[1].handle = src;
+ obj[1].relocation_count = 0;
+ obj[1].relocs_ptr = 0;
+ obj[1].alignment = 0;
+ obj[1].offset = 0;
+ obj[1].flags = 0;
+ obj[1].rsvd1 = 0;
+ obj[1].rsvd2 = 0;
+
+ obj[2].handle = handle;
+ obj[2].relocation_count = 2;
+ obj[2].relocs_ptr = (uintptr_t)reloc;
+ obj[2].alignment = 0;
+ obj[2].offset = 0;
+ obj[2].flags = 0;
+ obj[2].rsvd1 = obj[2].rsvd2 = 0;
+
+ exec.buffers_ptr = (uintptr_t)obj;
+ exec.buffer_count = 3;
+ exec.batch_start_offset = 0;
+ exec.batch_len = (b-batch)*sizeof(batch[0]);
+ exec.DR1 = exec.DR4 = 0;
+ exec.num_cliprects = 0;
+ exec.cliprects_ptr = 0;
+ exec.flags = 0;
+ i915_execbuffer2_set_context_id(exec, 0);
+ exec.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ while (ret && errno == EBUSY) {
+ drmCommandNone(fd, DRM_I915_GEM_THROTTLE);
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ }
+ assert(ret == 0);
+
+ gem_close(fd, handle);
+}
+
+static uint32_t
+create_bo(int fd, uint32_t val, int tiling)
+{
+ uint32_t handle;
+ uint32_t *v;
+ int i;
+
+ handle = gem_create(fd, WIDTH*HEIGHT*4);
+ gem_set_tiling(fd, handle, tiling, WIDTH*4);
+
+ /* Fill the BO with dwords starting at val */
+ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ | PROT_WRITE);
+ assert(v);
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ v[i] = val++;
+ munmap(v, WIDTH*HEIGHT*4);
+
+ return handle;
+}
+
+static void
+check_bo(int fd, uint32_t handle, uint32_t val)
+{
+ uint32_t *v;
+ int i;
+
+ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ);
+ assert(v);
+ for (i = 0; i < WIDTH*HEIGHT; i++) {
+ if (v[i] != val) {
+ fprintf(stderr, "Expected 0x%08x, found 0x%08x "
+ "at offset 0x%08x\n",
+ val, v[i], i * 4);
+ abort();
+ }
+ val++;
+ }
+ munmap(v, WIDTH*HEIGHT*4);
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t *handle, *tiling, *start_val;
+ uint32_t start = 0;
+ int i, fd, count;
+
+ fd = drm_open_any();
+
+ if (!IS_GEN3(intel_get_drm_devid(fd))) {
+ printf("gen3-only test, doing nothing\n");
+ return 77;
+ }
+
+ count = 0;
+ if (argc > 1)
+ count = atoi(argv[1]);
+ if (count == 0)
+ count = 3 * gem_aperture_size(fd) / (1024*1024) / 2;
+ printf("Using %d 1MiB buffers\n", count);
+
+ handle = malloc(sizeof(uint32_t)*count*3);
+ tiling = handle + count;
+ start_val = tiling + count;
+
+ for (i = 0; i < count; i++) {
+ handle[i] = create_bo(fd, start, tiling[i] = i % 3);
+ start_val[i] = start;
+ start += 1024 * 1024 / 4;
+ }
+
+ printf("Verifying initialisation..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ printf("Cyclic blits, forward..."); fflush(stdout);
+ for (i = 0; i < count * 32; i++) {
+ int src = i % count;
+ int dst = (i + 1) % count;
+
+ copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]);
+ start_val[dst] = start_val[src];
+ }
+ printf("verifying..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ printf("Cyclic blits, backward..."); fflush(stdout);
+ for (i = 0; i < count * 32; i++) {
+ int src = (i + 1) % count;
+ int dst = i % count;
+
+ copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]);
+ start_val[dst] = start_val[src];
+ }
+ printf("verifying..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ printf("Random blits..."); fflush(stdout);
+ for (i = 0; i < count * 32; i++) {
+ int src = random() % count;
+ int dst = random() % count;
+
+ while (src == dst)
+ dst = random() % count;
+
+ copy(fd, handle[dst], tiling[dst], handle[src], tiling[src]);
+ start_val[dst] = start_val[src];
+ }
+ printf("verifying..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ return 0;
+}
diff --git a/tests/gen3_render_tiledx_blits.c b/tests/gen3_render_tiledx_blits.c
new file mode 100644
index 00000000..0e96e797
--- /dev/null
+++ b/tests/gen3_render_tiledx_blits.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file gen3_linear_render_blits.c
+ *
+ * This is a test of doing many blits, with a working set
+ * larger than the aperture size.
+ *
+ * The goal is to simply ensure the basics work.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#include "i915_reg.h"
+#include "i915_3d.h"
+
+#define WIDTH 512
+#define HEIGHT 512
+
+static inline uint32_t pack_float(float f)
+{
+ union {
+ uint32_t dw;
+ float f;
+ } u;
+ u.f = f;
+ return u.dw;
+}
+
+static uint32_t fill_reloc(struct drm_i915_gem_relocation_entry *reloc,
+ uint32_t offset,
+ uint32_t handle,
+ uint32_t read_domain,
+ uint32_t write_domain)
+{
+ reloc->target_handle = handle;
+ reloc->delta = 0;
+ reloc->offset = offset * sizeof(uint32_t);
+ reloc->presumed_offset = 0;
+ reloc->read_domains = read_domain;
+ reloc->write_domain = write_domain;
+
+ return reloc->presumed_offset + reloc->delta;
+}
+
+static void
+copy(int fd, uint32_t dst, uint32_t src)
+{
+ uint32_t batch[1024], *b = batch;
+ struct drm_i915_gem_relocation_entry reloc[2], *r = reloc;
+ struct drm_i915_gem_exec_object2 obj[3];
+ struct drm_i915_gem_execbuffer2 exec;
+ uint32_t handle;
+ int ret;
+
+ /* invariant state */
+ *b++ = (_3DSTATE_AA_CMD |
+ AA_LINE_ECAAR_WIDTH_ENABLE |
+ AA_LINE_ECAAR_WIDTH_1_0 |
+ AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
+ *b++ = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+ IAB_MODIFY_ENABLE |
+ IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
+ IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE <<
+ IAB_SRC_FACTOR_SHIFT) |
+ IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO <<
+ IAB_DST_FACTOR_SHIFT));
+ *b++ = (_3DSTATE_DFLT_DIFFUSE_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_SPEC_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_Z_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_COORD_SET_BINDINGS |
+ CSB_TCB(0, 0) |
+ CSB_TCB(1, 1) |
+ CSB_TCB(2, 2) |
+ CSB_TCB(3, 3) |
+ CSB_TCB(4, 4) |
+ CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7));
+ *b++ = (_3DSTATE_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D);
+ *b++ = (_3DSTATE_MODES_4_CMD |
+ ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
+ ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) |
+ ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff));
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 2);
+ *b++ = (0x00000000); /* Disable texture coordinate wrap-shortest */
+ *b++ = ((1 << S4_POINT_WIDTH_SHIFT) |
+ S4_LINE_WIDTH_ONE |
+ S4_CULLMODE_NONE |
+ S4_VFMT_XY);
+ *b++ = (0x00000000); /* Stencil. */
+ *b++ = (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+ *b++ = (_3DSTATE_SCISSOR_RECT_0_CMD);
+ *b++ = (0);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DEPTH_SUBRECT_DISABLE);
+ *b++ = (_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
+ *b++ = (0);
+ *b++ = (_3DSTATE_STIPPLE);
+ *b++ = (0x00000000);
+ *b++ = (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
+
+ /* samler state */
+#define TEX_COUNT 1
+ *b++ = (_3DSTATE_MAP_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b = fill_reloc(r++, b-batch, src, I915_GEM_DOMAIN_SAMPLER, 0); b++;
+ *b++ = (MAPSURF_32BIT | MT_32BIT_ARGB8888 |
+ MS3_TILED_SURFACE |
+ (HEIGHT - 1) << MS3_HEIGHT_SHIFT |
+ (WIDTH - 1) << MS3_WIDTH_SHIFT);
+ *b++ = ((WIDTH-1) << MS4_PITCH_SHIFT);
+
+ *b++ = (_3DSTATE_SAMPLER_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b++ = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MAG_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+ *b++ = (TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT |
+ TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT |
+ 0 << SS3_TEXTUREMAP_INDEX_SHIFT);
+ *b++ = (0x00000000);
+
+ /* render target state */
+ *b++ = (_3DSTATE_BUF_INFO_CMD);
+ *b++ = (BUF_3D_ID_COLOR_BACK | BUF_3D_TILED_SURFACE | WIDTH*4);
+ *b = fill_reloc(r++, b-batch, dst,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+ b++;
+
+ *b++ = (_3DSTATE_DST_BUF_VARS_CMD);
+ *b++ = (COLR_BUF_ARGB8888 |
+ DSTORG_HORT_BIAS(0x8) |
+ DSTORG_VERT_BIAS(0x8));
+
+ /* draw rect is unconditional */
+ *b++ = (_3DSTATE_DRAW_RECT_CMD);
+ *b++ = (0x00000000);
+ *b++ = (0x00000000); /* ymin, xmin */
+ *b++ = (DRAW_YMAX(HEIGHT - 1) |
+ DRAW_XMAX(WIDTH - 1));
+ /* yorig, xorig (relate to color buffer?) */
+ *b++ = (0x00000000);
+
+ /* texfmt */
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(1) | I1_LOAD_S(2) | I1_LOAD_S(6) | 2);
+ *b++ = ((4 << S1_VERTEX_WIDTH_SHIFT) | (4 << S1_VERTEX_PITCH_SHIFT));
+ *b++ = (~S2_TEXCOORD_FMT(0, TEXCOORDFMT_NOT_PRESENT) |
+ S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D));
+ *b++ = (S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+ BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT |
+ BLENDFACT_ONE << S6_CBUF_SRC_BLEND_FACT_SHIFT |
+ BLENDFACT_ZERO << S6_CBUF_DST_BLEND_FACT_SHIFT);
+
+ /* pixel shader */
+ *b++ = (_3DSTATE_PIXEL_SHADER_PROGRAM | (1 + 3*3 - 2));
+ /* decl FS_T0 */
+ *b++ = (D0_DCL |
+ REG_TYPE(FS_T0) << D0_TYPE_SHIFT |
+ REG_NR(FS_T0) << D0_NR_SHIFT |
+ ((REG_TYPE(FS_T0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* decl FS_S0 */
+ *b++ = (D0_DCL |
+ (REG_TYPE(FS_S0) << D0_TYPE_SHIFT) |
+ (REG_NR(FS_S0) << D0_NR_SHIFT) |
+ ((REG_TYPE(FS_S0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* texld(FS_OC, FS_S0, FS_T0 */
+ *b++ = (T0_TEXLD |
+ (REG_TYPE(FS_OC) << T0_DEST_TYPE_SHIFT) |
+ (REG_NR(FS_OC) << T0_DEST_NR_SHIFT) |
+ (REG_NR(FS_S0) << T0_SAMPLER_NR_SHIFT));
+ *b++ = ((REG_TYPE(FS_T0) << T1_ADDRESS_REG_TYPE_SHIFT) |
+ (REG_NR(FS_T0) << T1_ADDRESS_REG_NR_SHIFT));
+ *b++ = (0);
+
+ *b++ = (PRIM3D_RECTLIST | (3*4 - 1));
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+
+ *b++ = MI_BATCH_BUFFER_END;
+ if ((b - batch) & 1)
+ *b++ = 0;
+
+ assert(b - batch <= 1024);
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0]));
+
+ assert(r-reloc == 2);
+
+ obj[0].handle = dst;
+ obj[0].relocation_count = 0;
+ obj[0].relocs_ptr = 0;
+ obj[0].alignment = 0;
+ obj[0].offset = 0;
+ obj[0].flags = 0;
+ obj[0].rsvd1 = 0;
+ obj[0].rsvd2 = 0;
+
+ obj[1].handle = src;
+ obj[1].relocation_count = 0;
+ obj[1].relocs_ptr = 0;
+ obj[1].alignment = 0;
+ obj[1].offset = 0;
+ obj[1].flags = 0;
+ obj[1].rsvd1 = 0;
+ obj[1].rsvd2 = 0;
+
+ obj[2].handle = handle;
+ obj[2].relocation_count = 2;
+ obj[2].relocs_ptr = (uintptr_t)reloc;
+ obj[2].alignment = 0;
+ obj[2].offset = 0;
+ obj[2].flags = 0;
+ obj[2].rsvd1 = obj[2].rsvd2 = 0;
+
+ exec.buffers_ptr = (uintptr_t)obj;
+ exec.buffer_count = 3;
+ exec.batch_start_offset = 0;
+ exec.batch_len = (b-batch)*sizeof(batch[0]);
+ exec.DR1 = exec.DR4 = 0;
+ exec.num_cliprects = 0;
+ exec.cliprects_ptr = 0;
+ exec.flags = 0;
+ i915_execbuffer2_set_context_id(exec, 0);
+ exec.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ while (ret && errno == EBUSY) {
+ drmCommandNone(fd, DRM_I915_GEM_THROTTLE);
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ }
+ assert(ret == 0);
+
+ gem_close(fd, handle);
+}
+
+static uint32_t
+create_bo(int fd, uint32_t val)
+{
+ uint32_t handle;
+ uint32_t *v;
+ int i;
+
+ handle = gem_create(fd, WIDTH*HEIGHT*4);
+ gem_set_tiling(fd, handle, I915_TILING_X, WIDTH*4);
+
+ /* Fill the BO with dwords starting at val */
+ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ | PROT_WRITE);
+ assert(v);
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ v[i] = val++;
+ munmap(v, WIDTH*HEIGHT*4);
+
+ return handle;
+}
+
+static void
+check_bo(int fd, uint32_t handle, uint32_t val)
+{
+ uint32_t *v;
+ int i;
+
+ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ);
+ assert(v);
+ for (i = 0; i < WIDTH*HEIGHT; i++) {
+ if (v[i] != val) {
+ fprintf(stderr, "Expected 0x%08x, found 0x%08x "
+ "at offset 0x%08x\n",
+ val, v[i], i * 4);
+ abort();
+ }
+ val++;
+ }
+ munmap(v, WIDTH*HEIGHT*4);
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t *handle, *start_val;
+ uint32_t start = 0;
+ int i, fd, count;
+
+ fd = drm_open_any();
+
+ if (!IS_GEN3(intel_get_drm_devid(fd))) {
+ printf("gen3-only test, doing nothing\n");
+ return 77;
+ }
+
+ count = 0;
+ if (argc > 1)
+ count = atoi(argv[1]);
+ if (count == 0)
+ count = 3 * gem_aperture_size(fd) / (1024*1024) / 2;
+ printf("Using %d 1MiB buffers\n", count);
+
+ handle = malloc(sizeof(uint32_t)*count*2);
+ start_val = handle + count;
+
+ for (i = 0; i < count; i++) {
+ handle[i] = create_bo(fd, start);
+ start_val[i] = start;
+ start += 1024 * 1024 / 4;
+ }
+
+ printf("Verifying initialisation...\n");
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ printf("Cyclic blits, forward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = i % count;
+ int dst = (i + 1) % count;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ printf("Cyclic blits, backward...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = (i + 1) % count;
+ int dst = i % count;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ printf("Random blits...\n");
+ for (i = 0; i < count * 4; i++) {
+ int src = random() % count;
+ int dst = random() % count;
+
+ if (src == dst)
+ continue;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+
+ return 0;
+}
diff --git a/tests/gen3_render_tiledy_blits.c b/tests/gen3_render_tiledy_blits.c
new file mode 100644
index 00000000..90fc7eb9
--- /dev/null
+++ b/tests/gen3_render_tiledy_blits.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file gen3_linear_render_blits.c
+ *
+ * This is a test of doing many blits, with a working set
+ * larger than the aperture size.
+ *
+ * The goal is to simply ensure the basics work.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "intel_gpu_tools.h"
+
+#include "i915_reg.h"
+#include "i915_3d.h"
+
+#define WIDTH 512
+#define HEIGHT 512
+
+static inline uint32_t pack_float(float f)
+{
+ union {
+ uint32_t dw;
+ float f;
+ } u;
+ u.f = f;
+ return u.dw;
+}
+
+static uint32_t fill_reloc(struct drm_i915_gem_relocation_entry *reloc,
+ uint32_t offset,
+ uint32_t handle,
+ uint32_t read_domain,
+ uint32_t write_domain)
+{
+ reloc->target_handle = handle;
+ reloc->delta = 0;
+ reloc->offset = offset * sizeof(uint32_t);
+ reloc->presumed_offset = 0;
+ reloc->read_domains = read_domain;
+ reloc->write_domain = write_domain;
+
+ return reloc->presumed_offset + reloc->delta;
+}
+
+static void
+copy(int fd, uint32_t dst, uint32_t src)
+{
+ uint32_t batch[1024], *b = batch;
+ struct drm_i915_gem_relocation_entry reloc[2], *r = reloc;
+ struct drm_i915_gem_exec_object2 obj[3];
+ struct drm_i915_gem_execbuffer2 exec;
+ uint32_t handle;
+ int ret;
+
+ /* invariant state */
+ *b++ = (_3DSTATE_AA_CMD |
+ AA_LINE_ECAAR_WIDTH_ENABLE |
+ AA_LINE_ECAAR_WIDTH_1_0 |
+ AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
+ *b++ = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+ IAB_MODIFY_ENABLE |
+ IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
+ IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE <<
+ IAB_SRC_FACTOR_SHIFT) |
+ IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO <<
+ IAB_DST_FACTOR_SHIFT));
+ *b++ = (_3DSTATE_DFLT_DIFFUSE_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_SPEC_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DFLT_Z_CMD);
+ *b++ = (0);
+ *b++ = (_3DSTATE_COORD_SET_BINDINGS |
+ CSB_TCB(0, 0) |
+ CSB_TCB(1, 1) |
+ CSB_TCB(2, 2) |
+ CSB_TCB(3, 3) |
+ CSB_TCB(4, 4) |
+ CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7));
+ *b++ = (_3DSTATE_RASTER_RULES_CMD |
+ ENABLE_POINT_RASTER_RULE |
+ OGL_POINT_RASTER_RULE |
+ ENABLE_LINE_STRIP_PROVOKE_VRTX |
+ ENABLE_TRI_FAN_PROVOKE_VRTX |
+ LINE_STRIP_PROVOKE_VRTX(1) |
+ TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D);
+ *b++ = (_3DSTATE_MODES_4_CMD |
+ ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
+ ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) |
+ ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff));
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 2);
+ *b++ = (0x00000000); /* Disable texture coordinate wrap-shortest */
+ *b++ = ((1 << S4_POINT_WIDTH_SHIFT) |
+ S4_LINE_WIDTH_ONE |
+ S4_CULLMODE_NONE |
+ S4_VFMT_XY);
+ *b++ = (0x00000000); /* Stencil. */
+ *b++ = (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+ *b++ = (_3DSTATE_SCISSOR_RECT_0_CMD);
+ *b++ = (0);
+ *b++ = (0);
+ *b++ = (_3DSTATE_DEPTH_SUBRECT_DISABLE);
+ *b++ = (_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
+ *b++ = (0);
+ *b++ = (_3DSTATE_STIPPLE);
+ *b++ = (0x00000000);
+ *b++ = (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
+
+ /* samler state */
+#define TEX_COUNT 1
+ *b++ = (_3DSTATE_MAP_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b = fill_reloc(r++, b-batch, src, I915_GEM_DOMAIN_SAMPLER, 0); b++;
+ *b++ = (MAPSURF_32BIT | MT_32BIT_ARGB8888 |
+ MS3_TILED_SURFACE | MS3_TILE_WALK |
+ (HEIGHT - 1) << MS3_HEIGHT_SHIFT |
+ (WIDTH - 1) << MS3_WIDTH_SHIFT);
+ *b++ = ((WIDTH-1) << MS4_PITCH_SHIFT);
+
+ *b++ = (_3DSTATE_SAMPLER_STATE | (3 * TEX_COUNT));
+ *b++ = ((1 << TEX_COUNT) - 1);
+ *b++ = (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MAG_FILTER_SHIFT |
+ FILTER_NEAREST << SS2_MIN_FILTER_SHIFT);
+ *b++ = (TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT |
+ TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT |
+ 0 << SS3_TEXTUREMAP_INDEX_SHIFT);
+ *b++ = (0x00000000);
+
+ /* render target state */
+ *b++ = (_3DSTATE_BUF_INFO_CMD);
+ *b++ = (BUF_3D_ID_COLOR_BACK | BUF_3D_TILED_SURFACE | BUF_3D_TILE_WALK_Y | WIDTH*4);
+ *b = fill_reloc(r++, b-batch, dst,
+ I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+ b++;
+
+ *b++ = (_3DSTATE_DST_BUF_VARS_CMD);
+ *b++ = (COLR_BUF_ARGB8888 |
+ DSTORG_HORT_BIAS(0x8) |
+ DSTORG_VERT_BIAS(0x8));
+
+ /* draw rect is unconditional */
+ *b++ = (_3DSTATE_DRAW_RECT_CMD);
+ *b++ = (0x00000000);
+ *b++ = (0x00000000); /* ymin, xmin */
+ *b++ = (DRAW_YMAX(HEIGHT - 1) |
+ DRAW_XMAX(WIDTH - 1));
+ /* yorig, xorig (relate to color buffer?) */
+ *b++ = (0x00000000);
+
+ /* texfmt */
+ *b++ = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(1) | I1_LOAD_S(2) | I1_LOAD_S(6) | 2);
+ *b++ = ((4 << S1_VERTEX_WIDTH_SHIFT) | (4 << S1_VERTEX_PITCH_SHIFT));
+ *b++ = (~S2_TEXCOORD_FMT(0, TEXCOORDFMT_NOT_PRESENT) |
+ S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D));
+ *b++ = (S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+ BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT |
+ BLENDFACT_ONE << S6_CBUF_SRC_BLEND_FACT_SHIFT |
+ BLENDFACT_ZERO << S6_CBUF_DST_BLEND_FACT_SHIFT);
+
+ /* pixel shader */
+ *b++ = (_3DSTATE_PIXEL_SHADER_PROGRAM | (1 + 3*3 - 2));
+ /* decl FS_T0 */
+ *b++ = (D0_DCL |
+ REG_TYPE(FS_T0) << D0_TYPE_SHIFT |
+ REG_NR(FS_T0) << D0_NR_SHIFT |
+ ((REG_TYPE(FS_T0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* decl FS_S0 */
+ *b++ = (D0_DCL |
+ (REG_TYPE(FS_S0) << D0_TYPE_SHIFT) |
+ (REG_NR(FS_S0) << D0_NR_SHIFT) |
+ ((REG_TYPE(FS_S0) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0));
+ *b++ = (0);
+ *b++ = (0);
+ /* texld(FS_OC, FS_S0, FS_T0 */
+ *b++ = (T0_TEXLD |
+ (REG_TYPE(FS_OC) << T0_DEST_TYPE_SHIFT) |
+ (REG_NR(FS_OC) << T0_DEST_NR_SHIFT) |
+ (REG_NR(FS_S0) << T0_SAMPLER_NR_SHIFT));
+ *b++ = ((REG_TYPE(FS_T0) << T1_ADDRESS_REG_TYPE_SHIFT) |
+ (REG_NR(FS_T0) << T1_ADDRESS_REG_NR_SHIFT));
+ *b++ = (0);
+
+ *b++ = (PRIM3D_RECTLIST | (3*4 - 1));
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(WIDTH);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+ *b++ = pack_float(0);
+ *b++ = pack_float(HEIGHT);
+
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+ *b++ = pack_float(0);
+
+ *b++ = MI_BATCH_BUFFER_END;
+ if ((b - batch) & 1)
+ *b++ = 0;
+
+ assert(b - batch <= 1024);
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, (b-batch)*sizeof(batch[0]));
+
+ assert(r-reloc == 2);
+
+ obj[0].handle = dst;
+ obj[0].relocation_count = 0;
+ obj[0].relocs_ptr = 0;
+ obj[0].alignment = 0;
+ obj[0].offset = 0;
+ obj[0].flags = 0;
+ obj[0].rsvd1 = 0;
+ obj[0].rsvd2 = 0;
+
+ obj[1].handle = src;
+ obj[1].relocation_count = 0;
+ obj[1].relocs_ptr = 0;
+ obj[1].alignment = 0;
+ obj[1].offset = 0;
+ obj[1].flags = 0;
+ obj[1].rsvd1 = 0;
+ obj[1].rsvd2 = 0;
+
+ obj[2].handle = handle;
+ obj[2].relocation_count = 2;
+ obj[2].relocs_ptr = (uintptr_t)reloc;
+ obj[2].alignment = 0;
+ obj[2].offset = 0;
+ obj[2].flags = 0;
+ obj[2].rsvd1 = obj[2].rsvd2 = 0;
+
+ exec.buffers_ptr = (uintptr_t)obj;
+ exec.buffer_count = 3;
+ exec.batch_start_offset = 0;
+ exec.batch_len = (b-batch)*sizeof(batch[0]);
+ exec.DR1 = exec.DR4 = 0;
+ exec.num_cliprects = 0;
+ exec.cliprects_ptr = 0;
+ exec.flags = 0;
+ i915_execbuffer2_set_context_id(exec, 0);
+ exec.rsvd2 = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ while (ret && errno == EBUSY) {
+ drmCommandNone(fd, DRM_I915_GEM_THROTTLE);
+ ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
+ }
+ assert(ret == 0);
+
+ gem_close(fd, handle);
+}
+
+static uint32_t
+create_bo(int fd, uint32_t val)
+{
+ uint32_t handle;
+ uint32_t *v;
+ int i;
+
+ handle = gem_create(fd, WIDTH*HEIGHT*4);
+ gem_set_tiling(fd, handle, I915_TILING_Y, WIDTH*4);
+
+ /* Fill the BO with dwords starting at val */
+ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ | PROT_WRITE);
+ assert(v);
+ for (i = 0; i < WIDTH*HEIGHT; i++)
+ v[i] = val++;
+ munmap(v, WIDTH*HEIGHT*4);
+
+ return handle;
+}
+
+static void
+check_bo(int fd, uint32_t handle, uint32_t val)
+{
+ uint32_t *v;
+ int i;
+
+ v = gem_mmap(fd, handle, WIDTH*HEIGHT*4, PROT_READ);
+ assert(v);
+ for (i = 0; i < WIDTH*HEIGHT; i++) {
+ if (v[i] != val) {
+ fprintf(stderr, "Expected 0x%08x, found 0x%08x "
+ "at offset 0x%08x\n",
+ val, v[i], i * 4);
+ abort();
+ }
+ val++;
+ }
+ munmap(v, WIDTH*HEIGHT*4);
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t *handle, *start_val;
+ uint32_t start = 0;
+ int i, fd, count;
+
+ fd = drm_open_any();
+
+ if (!IS_GEN3(intel_get_drm_devid(fd))) {
+ printf("gen3-only test, doing nothing\n");
+ return 77;
+ }
+
+ count = 0;
+ if (argc > 1)
+ count = atoi(argv[1]);
+ if (count == 0)
+ count = 3 * gem_aperture_size(fd) / (1024*1024) / 2;
+ printf("Using %d 1MiB buffers\n", count);
+
+ handle = malloc(sizeof(uint32_t)*count*2);
+ start_val = handle + count;
+
+ for (i = 0; i < count; i++) {
+ handle[i] = create_bo(fd, start);
+ start_val[i] = start;
+ start += 1024 * 1024 / 4;
+ }
+
+ printf("Verifying initialisation..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ printf("Cyclic blits, forward..."); fflush(stdout);
+ for (i = 0; i < count * 32; i++) {
+ int src = i % count;
+ int dst = (i + 1) % count;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ printf("verifying..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ printf("Cyclic blits, backward..."); fflush(stdout);
+ for (i = 0; i < count * 32; i++) {
+ int src = (i + 1) % count;
+ int dst = i % count;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ printf("verifying..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ printf("Random blits..."); fflush(stdout);
+ for (i = 0; i < count * 32; i++) {
+ int src = random() % count;
+ int dst = random() % count;
+
+ while (src == dst)
+ dst = random() % count;
+
+ copy(fd, handle[dst], handle[src]);
+ start_val[dst] = start_val[src];
+ }
+ printf("verifying..."); fflush(stdout);
+ for (i = 0; i < count; i++)
+ check_bo(fd, handle[i], start_val[i]);
+ printf("done\n");
+
+ return 0;
+}
diff --git a/tests/getclient.c b/tests/getclient.c
new file mode 100644
index 00000000..481ce119
--- /dev/null
+++ b/tests/getclient.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <limits.h>
+#include <sys/ioctl.h>
+#include "drmtest.h"
+
+/**
+ * Checks DRM_IOCTL_GET_CLIENT.
+ */
+int main(int argc, char **argv)
+{
+ int fd, ret;
+ drm_client_t client;
+
+ fd = drm_open_any();
+
+ /* Look for client index 0. This should exist whether we're operating
+ * on an otherwise unused drm device, or the X Server is running on
+ * the device.
+ */
+ client.idx = 0;
+ ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client);
+ assert(ret == 0);
+
+ /* Look for some absurd client index and make sure it's invalid.
+ * The DRM drivers currently always return data, so the user has
+ * no real way to detect when the list has terminated. That's bad,
+ * and this test is XFAIL as a result.
+ */
+ client.idx = 0x7fffffff;
+ ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client);
+ assert(ret == -1 && errno == EINVAL);
+
+ close(fd);
+ return 0;
+}
diff --git a/tests/getstats.c b/tests/getstats.c
new file mode 100644
index 00000000..8a7d2999
--- /dev/null
+++ b/tests/getstats.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <limits.h>
+#include <sys/ioctl.h>
+#include "drmtest.h"
+
+/**
+ * Checks DRM_IOCTL_GET_STATS.
+ *
+ * I don't care too much about the actual contents, just that the kernel
+ * doesn't crash.
+ */
+int main(int argc, char **argv)
+{
+ int fd, ret;
+ drm_stats_t stats;
+
+ fd = drm_open_any();
+
+ ret = ioctl(fd, DRM_IOCTL_GET_STATS, &stats);
+ assert(ret == 0);
+
+ close(fd);
+ return 0;
+}
diff --git a/tests/getversion.c b/tests/getversion.c
new file mode 100644
index 00000000..4847e796
--- /dev/null
+++ b/tests/getversion.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <string.h>
+#include <sys/ioctl.h>
+#include "drmtest.h"
+
+/**
+ * Checks DRM_IOCTL_GET_VERSION and libdrm's drmGetVersion() interface to it.
+ */
+int main(int argc, char **argv)
+{
+ int fd;
+ drmVersionPtr v;
+
+ fd = drm_open_any();
+ v = drmGetVersion(fd);
+ assert(strlen(v->name) != 0);
+ assert(strlen(v->date) != 0);
+ assert(strlen(v->desc) != 0);
+ assert(v->version_major >= 1);
+ drmFree(v);
+ close(fd);
+ return 0;
+}
diff --git a/tests/module_reload b/tests/module_reload
new file mode 100755
index 00000000..400fdd04
--- /dev/null
+++ b/tests/module_reload
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Testcase: Reload the drm module
+#
+# ... we've broken this way too often :(
+#
+
+SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )"
+. $SOURCE_DIR/drm_lib.sh
+
+# no other drm service should be running, so we can just unbind
+
+# vtcon0 is vga, vtcon1 fbcon and let's pray that won't change due to boot load
+# time changes
+if ! echo 0 > /sys/class/vtconsole/vtcon1/bind ; then
+ echo -e "no kms unload support"
+ echo "please enable CONFIG_VT_HW_CONSOLE_BINDING in the kernel"
+ exit 77
+fi
+
+#ignore errors in ips - gen5 only
+rmmod intel_ips &> /dev/null
+rmmod i915
+#ignore errors in intel-gtt, often built-in
+rmmod intel-gtt &> /dev/null
+rmmod drm_kms_helper
+rmmod drm
+
+if lsmod | grep i915 &> /dev/null ; then
+ echo WARNING: i915.ko still loaded!
+ exitcode=1
+else
+ echo module successfully unloaded
+ exitcode=0
+fi
+
+modprobe i915
+echo 1 > /sys/class/vtconsole/vtcon1/bind
+
+# try to run something
+$SOURCE_DIR/gem_exec_nop > /dev/null && echo "module successfully loaded again"
diff --git a/tests/pass.png b/tests/pass.png
new file mode 100644
index 00000000..36a5236b
--- /dev/null
+++ b/tests/pass.png
Binary files differ
diff --git a/tests/prime_nv_api.c b/tests/prime_nv_api.c
new file mode 100644
index 00000000..962e903d
--- /dev/null
+++ b/tests/prime_nv_api.c
@@ -0,0 +1,408 @@
+/* wierd use of API tests */
+
+/* test1- export buffer from intel, import same fd twice into nouveau,
+ check handles match
+ test2 - export buffer from intel, import fd once, close fd, try import again
+ fail if it succeeds
+ test3 - export buffer from intel, import twice on nouveau, check handle is the same
+ test4 - export handle twice from intel, import into nouveau twice, check handle is the same
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "intel_bufmgr.h"
+#include "nouveau.h"
+#include "intel_gpu_tools.h"
+#include "intel_batchbuffer.h"
+
+#define BO_SIZE (256*1024)
+
+int intel_fd = -1, intel_fd2 = -1, nouveau_fd = -1, nouveau_fd2 = -1;
+drm_intel_bufmgr *bufmgr;
+drm_intel_bufmgr *bufmgr2;
+struct nouveau_device *ndev, *ndev2;
+struct nouveau_client *nclient, *nclient2;
+uint32_t devid;
+struct intel_batchbuffer *intel_batch;
+
+static int find_and_open_devices(void)
+{
+ int i;
+ char path[80];
+ struct stat buf;
+ FILE *fl;
+ char vendor_id[8];
+ int venid;
+ for (i = 0; i < 9; i++) {
+ sprintf(path, "/sys/class/drm/card%d/device/vendor", i);
+ if (stat(path, &buf))
+ break;
+
+ fl = fopen(path, "r");
+ if (!fl)
+ break;
+
+ fgets(vendor_id, 8, fl);
+ fclose(fl);
+
+ venid = strtoul(vendor_id, NULL, 16);
+ sprintf(path, "/dev/dri/card%d", i);
+ if (venid == 0x8086) {
+ intel_fd = open(path, O_RDWR);
+ if (!intel_fd)
+ return -1;
+ intel_fd2 = open(path, O_RDWR);
+ if (!intel_fd2)
+ return -1;
+ } else if (venid == 0x10de) {
+ nouveau_fd = open(path, O_RDWR);
+ if (!nouveau_fd)
+ return -1;
+ nouveau_fd2 = open(path, O_RDWR);
+ if (!nouveau_fd2)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int test1(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ ret = drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+ if (ret)
+ goto out;
+
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo);
+ if (ret < 0) {
+ close(prime_fd);
+ goto out;
+ }
+ ret = nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2);
+ close(prime_fd);
+ if (ret < 0)
+ goto out;
+
+ if (nvbo->handle != nvbo2->handle)
+ ret = -1;
+out:
+ nouveau_bo_ref(NULL, &nvbo2);
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+
+static int test2(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ ret = drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+ if (ret < 0)
+ goto out;
+
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo);
+ close(prime_fd);
+ if (ret < 0)
+ goto out;
+ ret = nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2);
+ if (ret == 0)
+ ret = -1;
+ else
+ ret = 0;
+
+out:
+ nouveau_bo_ref(NULL, &nvbo2);
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+
+/* import handle twice on one driver */
+static int test3(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ ret = drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+ if (ret < 0)
+ goto out;
+
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo);
+ if (ret < 0) {
+ close(prime_fd);
+ goto out;
+ }
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo2);
+ close(prime_fd);
+ if (ret < 0)
+ goto out;
+
+ if (nvbo->handle != nvbo2->handle)
+ ret = -1;
+
+out:
+ nouveau_bo_ref(NULL, &nvbo2);
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+/* export handle twice from one driver - import twice
+ see if we get same object */
+static int test4(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd, prime_fd2;
+ struct nouveau_bo *nvbo = NULL, *nvbo2 = NULL;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd2);
+
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo);
+ close(prime_fd);
+ if (ret >= 0)
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd2, &nvbo2);
+ close(prime_fd2);
+ if (ret < 0)
+ goto out;
+
+ if (nvbo->handle != nvbo2->handle)
+ ret = -1;
+
+out:
+ nouveau_bo_ref(NULL, &nvbo2);
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+/* export handle from intel driver - reimport to intel driver
+ see if you get same object */
+static int test5(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo, *test_intel_bo2;
+ int prime_fd;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+
+ test_intel_bo2 = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE);
+ close(prime_fd);
+ if (!test_intel_bo2) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+ if (test_intel_bo->handle != test_intel_bo2->handle)
+ ret = -1;
+
+out:
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+/* nouveau export reimport test */
+static int test6(void)
+{
+ int ret;
+ int prime_fd;
+ struct nouveau_bo *nvbo, *nvbo2;
+
+ ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
+ 0, BO_SIZE, NULL, &nvbo);
+ if (ret < 0)
+ return ret;
+ ret = nouveau_bo_set_prime(nvbo, &prime_fd);
+ if (ret < 0)
+ return ret;
+
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo2);
+ close(prime_fd);
+ if (ret < 0)
+ return ret;
+
+ if (nvbo->handle != nvbo2->handle)
+ fprintf(stderr,"mismatch handles %d %d\n", nvbo->handle, nvbo2->handle);
+ nouveau_bo_ref(NULL, &nvbo);
+ nouveau_bo_ref(NULL, &nvbo2);
+ return 0;
+}
+
+/* export handle from intel driver - reimport to another intel driver bufmgr
+ see if you get same object */
+static int test7(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo, *test_intel_bo2;
+ int prime_fd;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+
+ test_intel_bo2 = drm_intel_bo_gem_create_from_prime(bufmgr2, prime_fd, BO_SIZE);
+ close(prime_fd);
+ if (!test_intel_bo2) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+ /* not sure what to test for, just that we don't explode */
+out:
+ drm_intel_bo_unreference(test_intel_bo2);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+/* nouveau export reimport to other driver test */
+static int test8(void)
+{
+ int ret;
+ int prime_fd;
+ struct nouveau_bo *nvbo, *nvbo2;
+
+ ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
+ 0, BO_SIZE, NULL, &nvbo);
+ if (ret < 0)
+ return ret;
+ ret = nouveau_bo_set_prime(nvbo, &prime_fd);
+ if (ret < 0)
+ return ret;
+
+ ret = nouveau_bo_prime_handle_ref(ndev2, prime_fd, &nvbo2);
+ close(prime_fd);
+ if (ret < 0)
+ return ret;
+
+ /* not sure what to test for, just make sure we don't explode */
+ nouveau_bo_ref(NULL, &nvbo);
+ nouveau_bo_ref(NULL, &nvbo2);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ ret = find_and_open_devices();
+ if (ret < 0)
+ return ret;
+
+ if (nouveau_fd == -1 || intel_fd == -1 || nouveau_fd2 == -1 || intel_fd2 == -1) {
+ fprintf(stderr,"failed to find intel and nouveau GPU\n");
+ return 77;
+ }
+
+ /* set up intel bufmgr */
+ bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096);
+ if (!bufmgr)
+ return -1;
+ /* Do not enable reuse, we share (almost) all buffers. */
+ //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ bufmgr2 = drm_intel_bufmgr_gem_init(intel_fd2, 4096);
+ if (!bufmgr2)
+ return -1;
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr2);
+
+ /* set up nouveau bufmgr */
+ ret = nouveau_device_wrap(nouveau_fd, 0, &ndev);
+ if (ret < 0) {
+ fprintf(stderr,"failed to wrap nouveau device\n");
+ return 77;
+ }
+
+ ret = nouveau_client_new(ndev, &nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to setup nouveau client\n");
+ return -1;
+ }
+
+ /* set up nouveau bufmgr */
+ ret = nouveau_device_wrap(nouveau_fd2, 0, &ndev2);
+ if (ret < 0) {
+ fprintf(stderr,"failed to wrap nouveau device\n");
+ return 77;
+ }
+
+ ret = nouveau_client_new(ndev2, &nclient2);
+ if (ret < 0) {
+ fprintf(stderr,"failed to setup nouveau client\n");
+ return -1;
+ }
+
+ /* set up an intel batch buffer */
+ devid = intel_get_drm_devid(intel_fd);
+ intel_batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+ ret = test1();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 1\n");
+
+ ret = test2();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 2\n");
+
+ ret = test3();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 3\n");
+
+ ret = test4();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 4\n");
+
+ ret = test5();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 5\n");
+
+ ret = test6();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 6\n");
+
+ ret = test7();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 7\n");
+
+ ret = test8();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 8\n");
+
+ intel_batchbuffer_free(intel_batch);
+
+ nouveau_device_del(&ndev);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(intel_fd);
+ close(nouveau_fd);
+
+ return ret;
+}
diff --git a/tests/prime_nv_pcopy.c b/tests/prime_nv_pcopy.c
new file mode 100644
index 00000000..21dccf38
--- /dev/null
+++ b/tests/prime_nv_pcopy.c
@@ -0,0 +1,1329 @@
+/* basic set of prime tests between intel and nouveau */
+
+/* test list -
+ 1. share buffer from intel -> nouveau.
+ 2. share buffer from nouveau -> intel
+ 3. share intel->nouveau, map on both, write intel, read nouveau
+ 4. share intel->nouveau, blit intel fill, readback on nouveau
+ test 1 + map buffer, read/write, map other size.
+ do some hw actions on the buffer
+ some illegal operations -
+ close prime fd try and map
+
+ TODO add some nouveau rendering tests
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "i915_drm.h"
+#include "intel_bufmgr.h"
+#include "nouveau.h"
+#include "intel_gpu_tools.h"
+#include "intel_batchbuffer.h"
+
+static int intel_fd = -1, nouveau_fd = -1;
+static drm_intel_bufmgr *bufmgr;
+static struct nouveau_device *ndev;
+static struct nouveau_client *nclient;
+static uint32_t devid;
+static struct intel_batchbuffer *batch;
+static struct nouveau_object *nchannel, *pcopy;
+static struct nouveau_bufctx *nbufctx;
+static struct nouveau_pushbuf *npush;
+
+static struct nouveau_bo *query_bo;
+static uint32_t query_counter;
+static volatile uint32_t *query;
+static uint32_t memtype_intel, tile_intel_y, tile_intel_x;
+
+#define SUBC_COPY(x) 6, (x)
+#define NV01_SUBCHAN_OBJECT 0
+
+#define NV01_SUBC(subc, mthd) SUBC_##subc((NV01_SUBCHAN_##mthd))
+
+#if 0
+#define dbg(fmt...) fprintf(stderr, fmt);
+#else
+#define dbg(...) do { } while (0)
+#endif
+
+typedef struct {
+ uint32_t w, h;
+ uint32_t pitch, lines;
+} rect;
+
+static int nv_bo_alloc(struct nouveau_bo **bo, rect *r,
+ uint32_t w, uint32_t h, uint32_t tile_mode,
+ int handle, uint32_t dom)
+{
+ uint32_t size;
+ uint32_t dx = 1, dy = 1, memtype = 0;
+ int ret;
+
+ *bo = NULL;
+ if (tile_mode) {
+ uint32_t tile_y;
+ uint32_t tile_x;
+
+ /* Y major tiling */
+ if ((tile_mode & 0xf) == 0xe)
+ /* but the internal layout is different */
+ tile_x = 7;
+ else
+ tile_x = 6 + (tile_mode & 0xf);
+ if (ndev->chipset < 0xc0) {
+ memtype = 0x70;
+ tile_y = 2;
+ } else {
+ memtype = 0xfe;
+ tile_y = 3;
+ }
+ if ((tile_mode & 0xf) == 0xe)
+ memtype = memtype_intel;
+ tile_y += ((tile_mode & 0xf0)>>4);
+
+ dx = 1 << tile_x;
+ dy = 1 << tile_y;
+ dbg("Tiling requirements: x y %u %u\n", dx, dy);
+ }
+
+ r->w = w;
+ r->h = h;
+
+ r->pitch = w = (w + dx-1) & ~(dx-1);
+ r->lines = h = (h + dy-1) & ~(dy-1);
+ size = w*h;
+
+ if (handle < 0) {
+ union nouveau_bo_config cfg;
+ cfg.nv50.memtype = memtype;
+ cfg.nv50.tile_mode = tile_mode;
+ if (dom == NOUVEAU_BO_GART)
+ dom |= NOUVEAU_BO_MAP;
+ ret = nouveau_bo_new(ndev, dom, 4096, size, &cfg, bo);
+ if (!ret)
+ ret = nouveau_bo_map(*bo, NOUVEAU_BO_RDWR, nclient);
+ if (ret) {
+ fprintf(stderr, "creating bo failed with %i %s\n",
+ ret, strerror(-ret));
+ nouveau_bo_ref(NULL, bo);
+ return ret;
+ }
+
+ dbg("new flags %08x memtype %08x tile %08x\n", (*bo)->flags, (*bo)->config.nv50.memtype, (*bo)->config.nv50.tile_mode);
+ if (tile_mode == tile_intel_y || tile_mode == tile_intel_x) {
+ dbg("tile mode was: %02x, now: %02x\n", (*bo)->config.nv50.tile_mode, tile_mode);
+ /* Doesn't like intel tiling much.. */
+ (*bo)->config.nv50.tile_mode = tile_mode;
+ }
+ } else {
+ ret = nouveau_bo_prime_handle_ref(ndev, handle, bo);
+ close(handle);
+ if (ret < 0) {
+ fprintf(stderr, "receiving bo failed with %i %s\n",
+ ret, strerror(-ret));
+ return ret;
+ }
+ if ((*bo)->size < size) {
+ fprintf(stderr, "expected bo size to be at least %u,"
+ "but received %"PRIu64"\n", size, (*bo)->size);
+ nouveau_bo_ref(NULL, bo);
+ return -1;
+ }
+ dbg("prime flags %08x memtype %08x tile %08x\n", (*bo)->flags, (*bo)->config.nv50.memtype, (*bo)->config.nv50.tile_mode);
+ (*bo)->config.nv50.memtype = memtype;
+ (*bo)->config.nv50.tile_mode = tile_mode;
+ }
+ dbg("size: %"PRIu64"\n", (*bo)->size);
+
+ return ret;
+}
+
+static inline void
+PUSH_DATA(struct nouveau_pushbuf *push, uint32_t data)
+{
+ *push->cur++ = data;
+}
+
+static inline void
+BEGIN_NV04(struct nouveau_pushbuf *push, int subc, int mthd, int size)
+{
+ PUSH_DATA (push, 0x00000000 | (size << 18) | (subc << 13) | mthd);
+}
+
+static inline void
+BEGIN_NI04(struct nouveau_pushbuf *push, int subc, int mthd, int size)
+{
+ PUSH_DATA (push, 0x40000000 | (size << 18) | (subc << 13) | mthd);
+}
+
+static inline void
+BEGIN_NVC0(struct nouveau_pushbuf *push, int subc, int mthd, int size)
+{
+ PUSH_DATA (push, 0x20000000 | (size << 16) | (subc << 13) | (mthd / 4));
+}
+
+static inline void
+BEGIN_NVXX(struct nouveau_pushbuf *push, int subc, int mthd, int size)
+{
+ if (ndev->chipset < 0xc0)
+ BEGIN_NV04(push, subc, mthd, size);
+ else
+ BEGIN_NVC0(push, subc, mthd, size);
+}
+
+static void
+noop_intel(drm_intel_bo *bo)
+{
+ BEGIN_BATCH(3);
+ OUT_BATCH(MI_NOOP);
+ OUT_BATCH(MI_BATCH_BUFFER_END);
+ OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+ ADVANCE_BATCH();
+
+ intel_batchbuffer_flush(batch);
+}
+
+static int find_and_open_devices(void)
+{
+ int i;
+ char path[80], *unused;
+ struct stat buf;
+ FILE *fl;
+ char vendor_id[8] = {};
+ int venid;
+ for (i = 0; i < 9; i++) {
+ sprintf(path, "/sys/class/drm/card%d/device/vendor", i);
+ if (stat(path, &buf))
+ break;
+
+ fl = fopen(path, "r");
+ if (!fl)
+ break;
+
+ unused = fgets(vendor_id, sizeof(vendor_id)-1, fl);
+ (void)unused;
+ fclose(fl);
+
+ venid = strtoul(vendor_id, NULL, 16);
+ sprintf(path, "/dev/dri/card%d", i);
+ if (venid == 0x8086) {
+ intel_fd = open(path, O_RDWR);
+ if (!intel_fd)
+ return -1;
+ } else if (venid == 0x10de) {
+ nouveau_fd = open(path, O_RDWR);
+ if (!nouveau_fd)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int init_nouveau(void)
+{
+ struct nv04_fifo nv04_data = { .vram = 0xbeef0201,
+ .gart = 0xbeef0202 };
+ struct nvc0_fifo nvc0_data = { };
+ struct nouveau_fifo *fifo;
+ int size, ret;
+ uint32_t class;
+ void *data;
+
+ ret = nouveau_device_wrap(nouveau_fd, 0, &ndev);
+ if (ret < 0) {
+ fprintf(stderr,"failed to wrap nouveau device\n");
+ return ret;
+ }
+
+ ret = nouveau_client_new(ndev, &nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to setup nouveau client\n");
+ return ret;
+ }
+
+ if (ndev->chipset < 0xa3 || ndev->chipset == 0xaa || ndev->chipset == 0xac) {
+ fprintf(stderr, "Your card doesn't support PCOPY\n");
+ return -1;
+ }
+
+ // TODO: Get a kepler and add support for it
+ if (ndev->chipset >= 0xe0) {
+ fprintf(stderr, "Unsure how kepler works!\n");
+ return -1;
+ }
+ ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
+ 4096, 4096, NULL, &query_bo);
+ if (!ret)
+ ret = nouveau_bo_map(query_bo, NOUVEAU_BO_RDWR, nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to setup query counter\n");
+ return ret;
+ }
+ query = query_bo->map;
+ *query = query_counter;
+
+ if (ndev->chipset < 0xc0) {
+ class = 0x85b5;
+ data = &nv04_data;
+ size = sizeof(nv04_data);
+ } else {
+ class = ndev->chipset < 0xe0 ? 0x490b5 : 0xa0b5;
+ data = &nvc0_data;
+ size = sizeof(nvc0_data);
+ }
+
+ ret = nouveau_object_new(&ndev->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS,
+ data, size, &nchannel);
+ if (ret) {
+ fprintf(stderr, "Error creating GPU channel: %d\n", ret);
+ if (ret == -ENODEV) {
+ fprintf(stderr, "Make sure nouveau_accel is active\n");
+ fprintf(stderr, "nvd9 is likely broken regardless\n");
+ }
+ return ret;
+ }
+
+ fifo = nchannel->data;
+
+ ret = nouveau_pushbuf_new(nclient, nchannel, 4, 32 * 1024,
+ true, &npush);
+ if (ret) {
+ fprintf(stderr, "Error allocating DMA push buffer: %d\n", ret);
+ return ret;
+ }
+
+ ret = nouveau_bufctx_new(nclient, 1, &nbufctx);
+ if (ret) {
+ fprintf(stderr, "Error allocating buffer context: %d\n", ret);
+ return ret;
+ }
+
+ npush->user_priv = nbufctx;
+
+ /* Hope this is enough init for PCOPY */
+ ret = nouveau_object_new(nchannel, class, class & 0xffff, NULL, 0, &pcopy);
+ if (ret) {
+ fprintf(stderr, "Failed to allocate pcopy: %d\n", ret);
+ return ret;
+ }
+ ret = nouveau_pushbuf_space(npush, 512, 0, 0);
+ if (ret) {
+ fprintf(stderr, "No space in pushbuf: %d\n", ret);
+ return ret;
+ }
+ if (ndev->chipset < 0xc0) {
+ struct nv04_fifo *nv04_fifo = (struct nv04_fifo*)fifo;
+ tile_intel_y = 0x3e;
+ tile_intel_x = 0x13;
+
+ BEGIN_NV04(npush, NV01_SUBC(COPY, OBJECT), 1);
+ PUSH_DATA(npush, pcopy->handle);
+ BEGIN_NV04(npush, SUBC_COPY(0x0180), 3);
+ PUSH_DATA(npush, nv04_fifo->vram);
+ PUSH_DATA(npush, nv04_fifo->vram);
+ PUSH_DATA(npush, nv04_fifo->vram);
+ } else {
+ tile_intel_y = 0x2e;
+ tile_intel_x = 0x03;
+ BEGIN_NVC0(npush, NV01_SUBC(COPY, OBJECT), 1);
+ PUSH_DATA(npush, pcopy->handle);
+ }
+ nouveau_pushbuf_kick(npush, npush->channel);
+ return ret;
+}
+
+static void fill16(void *ptr, uint32_t val)
+{
+ uint32_t *p = ptr;
+ val = (val) | (val << 8) | (val << 16) | (val << 24);
+ p[0] = p[1] = p[2] = p[3] = val;
+}
+
+#define TILE_SIZE 4096
+
+static int swtile_y(uint8_t *out, const uint8_t *in, int w, int h)
+{
+ uint32_t x, y, dx, dy;
+ uint8_t *endptr = out + w * h;
+ assert(!(w % 128));
+ assert(!(h % 32));
+
+ for (y = 0; y < h; y += 32) {
+ for (x = 0; x < w; x += 128, out += TILE_SIZE) {
+ for (dx = 0; dx < 8; ++dx) {
+ for (dy = 0; dy < 32; ++dy) {
+ uint32_t out_ofs = (dx * 32 + dy) * 16;
+ uint32_t in_ofs = (y + dy) * w + (x + 16 * dx);
+ assert(out_ofs < TILE_SIZE);
+ assert(in_ofs < w*h);
+
+ // To do the Y tiling quirk:
+ // out_ofs = out_ofs ^ (((out_ofs >> 9) & 1) << 6);
+ memcpy(&out[out_ofs], &in[in_ofs], 16);
+ }
+ }
+ }
+ }
+ assert(out == endptr);
+ return 0;
+}
+
+static int swtile_x(uint8_t *out, const uint8_t *in, int w, int h)
+{
+ uint32_t x, y, dy;
+ uint8_t *endptr = out + w * h;
+ assert(!(w % 512));
+ assert(!(h % 8));
+
+ for (y = 0; y < h; y += 8) {
+ for (x = 0; x < w; x += 512, out += TILE_SIZE) {
+ for (dy = 0; dy < 8; ++dy) {
+ uint32_t out_ofs = 512 * dy;
+ uint32_t in_ofs = (y + dy) * w + x;
+ assert(out_ofs < TILE_SIZE);
+ assert(in_ofs < w*h);
+ memcpy(&out[out_ofs], &in[in_ofs], 512);
+ }
+ }
+ }
+ assert(out == endptr);
+ return 0;
+}
+
+#if 0
+/* X tiling is approximately linear, except tiled in 512x8 blocks, so lets abuse that
+ *
+ * How? Whole contiguous tiles can be copied safely as if linear
+ */
+
+static int perform_copy_hack(struct nouveau_bo *nvbo, const rect *dst,
+ uint32_t dst_x, uint32_t dst_y,
+ struct nouveau_bo *nvbi, const rect *src,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t w, uint32_t h)
+{
+ struct nouveau_pushbuf_refn refs[] = {
+ { nvbi, (nvbi->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_RD },
+ { nvbo, (nvbo->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_WR },
+ { query_bo, NOUVEAU_BO_GART | NOUVEAU_BO_RDWR }
+ };
+ uint32_t exec = 0x00000000;
+ uint32_t src_off = 0, dst_off = 0;
+ struct nouveau_pushbuf *push = npush;
+ uint32_t dw, tiles, tile_src = nvbi->config.nv50.tile_mode, tile_dst = nvbo->config.nv50.tile_mode;
+
+ if (tile_src == tile_intel_x)
+ dw = 512 - (src_x & 512);
+ else
+ dw = 512 - (dst_x % 512);
+
+ if (!nvbi->config.nv50.memtype)
+ exec |= 0x00000010;
+ if (!tile_src)
+ src_off = src_y * src->pitch + src_x;
+
+ if (!nvbo->config.nv50.memtype)
+ exec |= 0x00000100;
+ if (!tile_dst)
+ dst_off = dst_y * dst->pitch + dst_x;
+
+ if (dw > w)
+ dw = w;
+ tiles = 1 + ((w - dw + 511)/512);
+
+ if (nouveau_pushbuf_space(push, 8 + tiles * 32, 0, 0) ||
+ nouveau_pushbuf_refn(push, refs, 3))
+ return -1;
+
+ for (; w; w -= dw, src_x += dw, dst_x += dw, dw = w > 512 ? 512 : w) {
+ if (tile_src == tile_intel_x) {
+ /* Find the correct tiled offset */
+ src_off = 8 * dst->pitch * (src_y / 8);
+ src_off += src_x / 512 * 4096;
+ src_off += (src_x % 512) + 512 * (src_y % 8);
+
+ if (!tile_dst)
+ dst_off = dst_y * dst->pitch + dst_x;
+ } else {
+ if (!tile_src)
+ src_off = src_y * src->pitch + src_x;
+
+ dst_off = 8 * dst->pitch * (dst_y / 8);
+ dst_off += dst_x / 512 * 4096;
+ dst_off += (dst_x % 512) + 512 * (dst_y % 8);
+ }
+
+ fprintf(stderr, "Copying from %u to %u for %u bytes\n", src_x, dst_x, dw);
+ fprintf(stderr, "src ofs: %u, dst ofs: %u\n", src_off, dst_off);
+ BEGIN_NVXX(push, SUBC_COPY(0x0200), 7);
+ PUSH_DATA (push, tile_src == tile_intel_x ? 0 : nvbi->config.nv50.tile_mode);
+ PUSH_DATA (push, src->pitch);
+ PUSH_DATA (push, src->h);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, src_x);
+ PUSH_DATA (push, src_y);
+
+ BEGIN_NVXX(push, SUBC_COPY(0x0220), 7);
+ PUSH_DATA (push, tile_dst == tile_intel_x ? 0 : nvbo->config.nv50.tile_mode);
+ PUSH_DATA (push, dst->pitch);
+ PUSH_DATA (push, dst->h);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, dst_x);
+ PUSH_DATA (push, dst_y);
+
+ BEGIN_NVXX(push, SUBC_COPY(0x030c), 8);
+ PUSH_DATA (push, (nvbi->offset + src_off) >> 32);
+ PUSH_DATA (push, (nvbi->offset + src_off));
+ PUSH_DATA (push, (nvbo->offset + dst_off) >> 32);
+ PUSH_DATA (push, (nvbo->offset + dst_off));
+ PUSH_DATA (push, src->pitch);
+ PUSH_DATA (push, dst->pitch);
+ PUSH_DATA (push, dw);
+ PUSH_DATA (push, h);
+
+ if (w == dw) {
+ exec |= 0x3000; /* QUERY|QUERY_SHORT */
+ BEGIN_NVXX(push, SUBC_COPY(0x0338), 3);
+ PUSH_DATA (push, (query_bo->offset) >> 32);
+ PUSH_DATA (push, (query_bo->offset));
+ PUSH_DATA (push, ++query_counter);
+ }
+
+ BEGIN_NVXX(push, SUBC_COPY(0x0300), 1);
+ PUSH_DATA (push, exec);
+ }
+ nouveau_pushbuf_kick(push, push->channel);
+ while (*query < query_counter) { }
+ return 0;
+}
+#endif
+
+static int perform_copy(struct nouveau_bo *nvbo, const rect *dst,
+ uint32_t dst_x, uint32_t dst_y,
+ struct nouveau_bo *nvbi, const rect *src,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t w, uint32_t h)
+{
+#if 0
+ /* Too much effort */
+ if (nvbi->config.nv50.tile_mode == tile_intel_x &&
+ nvbo->config.nv50.tile_mode == tile_intel_x)
+ return -1;
+ else if (nvbi->config.nv50.tile_mode == tile_intel_x ||
+ nvbo->config.nv50.tile_mode == tile_intel_x)
+ return perform_copy_hack(nvbo, dst, dst_x, dst_y,
+ nvbi, src, src_x, src_y, w, h);
+#endif
+ struct nouveau_pushbuf_refn refs[] = {
+ { nvbi, (nvbi->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_RD },
+ { nvbo, (nvbo->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_WR },
+ { query_bo, NOUVEAU_BO_GART | NOUVEAU_BO_RDWR }
+ };
+ uint32_t cpp = 1, exec = 0x00003000; /* QUERY|QUERY_SHORT|FORMAT */
+ uint32_t src_off = 0, dst_off = 0;
+ struct nouveau_pushbuf *push = npush;
+
+ if (nvbi->config.nv50.tile_mode == tile_intel_y)
+ dbg("src is y-tiled\n");
+ if (nvbo->config.nv50.tile_mode == tile_intel_y)
+ dbg("dst is y-tiled\n");
+
+ if (nouveau_pushbuf_space(push, 64, 0, 0) ||
+ nouveau_pushbuf_refn(push, refs, 3))
+ return -1;
+
+ if (!nvbi->config.nv50.tile_mode) {
+ src_off = src_y * src->pitch + src_x;
+ exec |= 0x00000010;
+ }
+
+ if (!nvbo->config.nv50.tile_mode) {
+ dst_off = dst_y * dst->pitch + dst_x;
+ exec |= 0x00000100;
+ }
+
+ BEGIN_NVXX(push, SUBC_COPY(0x0200), 7);
+ PUSH_DATA (push, nvbi->config.nv50.tile_mode);
+ PUSH_DATA (push, src->pitch / cpp);
+ PUSH_DATA (push, src->h);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, src_x / cpp);
+ PUSH_DATA (push, src_y);
+
+ BEGIN_NVXX(push, SUBC_COPY(0x0220), 7);
+ PUSH_DATA (push, nvbo->config.nv50.tile_mode);
+ PUSH_DATA (push, dst->pitch / cpp);
+ PUSH_DATA (push, dst->h);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, dst_x / cpp);
+ PUSH_DATA (push, dst_y);
+
+ BEGIN_NVXX(push, SUBC_COPY(0x030c), 9);
+ PUSH_DATA (push, (nvbi->offset + src_off) >> 32);
+ PUSH_DATA (push, (nvbi->offset + src_off));
+ PUSH_DATA (push, (nvbo->offset + dst_off) >> 32);
+ PUSH_DATA (push, (nvbo->offset + dst_off));
+ PUSH_DATA (push, src->pitch);
+ PUSH_DATA (push, dst->pitch);
+ PUSH_DATA (push, w / cpp);
+ PUSH_DATA (push, h);
+ PUSH_DATA (push, 0x03333120);
+
+ BEGIN_NVXX(push, SUBC_COPY(0x0338), 3);
+ PUSH_DATA (push, (query_bo->offset) >> 32);
+ PUSH_DATA (push, (query_bo->offset));
+ PUSH_DATA (push, ++query_counter);
+
+ BEGIN_NVXX(push, SUBC_COPY(0x0300), 1);
+ PUSH_DATA (push, exec);
+
+ nouveau_pushbuf_kick(push, push->channel);
+ while (*query < query_counter) { usleep(1000); }
+ return 0;
+}
+
+static int check1_macro(uint32_t *p, uint32_t w, uint32_t h)
+{
+ uint32_t i, val, j;
+
+ for (i = 0; i < 256; ++i, p += 4) {
+ val = (i) | (i << 8) | (i << 16) | (i << 24);
+ if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) {
+ fprintf(stderr, "Retile check failed in first tile!\n");
+ fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n",
+ p[0], p[1], p[2], p[3], val);
+ return -1;
+ }
+ }
+
+ val = 0x3e3e3e3e;
+ for (i = 0; i < 256 * (w-1); ++i, p += 4) {
+ if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) {
+ fprintf(stderr, "Retile check failed in second tile!\n");
+ fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n",
+ p[0], p[1], p[2], p[3], val);
+ return -1;
+ }
+ }
+
+ for (j = 1; j < h; ++j) {
+ val = 0x7e7e7e7e;
+ for (i = 0; i < 256; ++i, p += 4) {
+ if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) {
+ fprintf(stderr, "Retile check failed in third tile!\n");
+ fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n",
+ p[0], p[1], p[2], p[3], val);
+ return -1;
+ }
+ }
+
+ val = 0xcececece;
+ for (i = 0; i < 256 * (w-1); ++i, p += 4) {
+ if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) {
+ fprintf(stderr, "Retile check failed in fourth tile!\n");
+ fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n",
+ p[0], p[1], p[2], p[3], val);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* test 1, see if we can copy from linear to intel Y format safely */
+static int test1_macro(void)
+{
+ int ret, prime_fd = -1;
+ struct nouveau_bo *nvbo = NULL, *nvbi = NULL;
+ rect dst, src;
+ uint8_t *ptr;
+ uint32_t w = 2 * 128, h = 2 * 32, x, y;
+
+ ret = nv_bo_alloc(&nvbi, &src, w, h, 0, -1, NOUVEAU_BO_GART);
+ if (ret >= 0)
+ ret = nv_bo_alloc(&nvbo, &dst, w, h, tile_intel_y, -1, NOUVEAU_BO_GART);
+ if (ret < 0)
+ goto out;
+
+ nouveau_bo_set_prime(nvbo, &prime_fd);
+
+ /* Set up something for our tile that should map into the first
+ * y-major tile, assuming my understanding of documentation is
+ * correct
+ */
+
+ /* First tile should be read out in groups of 16 bytes that
+ * are all set to a linear increasing value..
+ */
+ ptr = nvbi->map;
+ for (x = 0; x < 128; x += 16)
+ for (y = 0; y < 32; ++y)
+ fill16(&ptr[y * w + x], x * 2 + y);
+
+ /* second tile */
+ for (x = 128; x < w; x += 16)
+ for (y = 0; y < 32; ++y)
+ fill16(&ptr[y * w + x], 0x3e);
+
+ /* third tile */
+ for (x = 0; x < 128; x += 16)
+ for (y = 32; y < h; ++y)
+ fill16(&ptr[y * w + x], 0x7e);
+
+ /* last tile */
+ for (x = 128; x < w; x += 16)
+ for (y = 32; y < h; ++y)
+ fill16(&ptr[y * w + x], 0xce);
+ memset(nvbo->map, 0xfc, w * h);
+
+ if (pcopy)
+ ret = perform_copy(nvbo, &dst, 0, 0, nvbi, &src, 0, 0, w, h);
+ else
+ ret = swtile_y(nvbo->map, nvbi->map, w, h);
+ if (!ret)
+ ret = check1_macro(nvbo->map, w/128, h/32);
+
+out:
+ nouveau_bo_ref(NULL, &nvbo);
+ nouveau_bo_ref(NULL, &nvbi);
+ close(prime_fd);
+ return ret;
+}
+
+static int dump_line(uint8_t *map)
+{
+ uint32_t dx, dy;
+ fprintf(stderr, "Dumping sub-tile:\n");
+ for (dy = 0; dy < 32; ++dy) {
+ for (dx = 0; dx < 15; ++dx, ++map) {
+ fprintf(stderr, "%02x ", *map);
+ }
+ fprintf(stderr, "%02x\n", *(map++));
+ }
+ return -1;
+}
+
+static int check1_micro(void *map, uint32_t pitch, uint32_t lines,
+ uint32_t dst_x, uint32_t dst_y, uint32_t w, uint32_t h)
+{
+ uint32_t x, y;
+
+ /* check only the relevant subrectangle [0..w) [0...h) */
+ uint8_t *m = map;
+ for (y = 0; y < h; ++y, m += pitch) {
+ for (x = 0; x < w; ++x) {
+ uint8_t expected = ((y & 3) << 6) | (x & 0x3f);
+ if (expected != m[x]) {
+ fprintf(stderr, "failed check at x=%u y=%u, expected %02x got %02x\n",
+ x, y, expected, m[x]);
+ return dump_line(m);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* test 1, but check micro format, should be unaffected by bit9 swizzling */
+static int test1_micro(void)
+{
+ struct nouveau_bo *bo_intel = NULL, *bo_nvidia = NULL, *bo_linear = NULL;
+ rect intel, nvidia, linear;
+ int ret = -1;
+ uint32_t tiling = I915_TILING_Y;
+
+ uint32_t src_x = 0, src_y = 0;
+ uint32_t dst_x = 0, dst_y = 0;
+ uint32_t x, y, w = 256, h = 64;
+
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", w * h, 4096);
+ if (!test_intel_bo)
+ return -1;
+ drm_intel_bo_set_tiling(test_intel_bo, &tiling, w);
+ if (tiling != I915_TILING_Y) {
+ fprintf(stderr, "Couldn't set y tiling\n");
+ goto out;
+ }
+ ret = drm_intel_gem_bo_map_gtt(test_intel_bo);
+ if (ret)
+ goto out;
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+ if (prime_fd < 0) {
+ drm_intel_bo_unreference(test_intel_bo);
+ goto out;
+ }
+ noop_intel(test_intel_bo);
+
+ ret = nv_bo_alloc(&bo_intel, &intel, w, h, tile_intel_y, prime_fd, 0);
+ if (!ret)
+ ret = nv_bo_alloc(&bo_nvidia, &nvidia, w, h, 0x10, -1, NOUVEAU_BO_VRAM);
+ if (!ret)
+ ret = nv_bo_alloc(&bo_linear, &linear, w, h, 0, -1, NOUVEAU_BO_GART);
+ if (ret)
+ goto out;
+
+ for (y = 0; y < linear.h; ++y) {
+ uint8_t *map = bo_linear->map;
+ map += y * linear.pitch;
+ for (x = 0; x < linear.pitch; ++x) {
+ uint8_t pos = x & 0x3f;
+ /* low 4 bits: micro tile pos */
+ /* 2 bits: x pos in tile (wraps) */
+ /* 2 bits: y pos in tile (wraps) */
+ pos |= (y & 3) << 6;
+ map[x] = pos;
+ }
+ }
+
+ ret = perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h);
+ if (ret)
+ goto out;
+
+ /* Perform the actual sub rectangle copy */
+ if (pcopy)
+ ret = perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h);
+ else
+ ret = swtile_y(test_intel_bo->virtual, bo_linear->map, w, h);
+ if (ret)
+ goto out;
+
+ noop_intel(test_intel_bo);
+ ret = check1_micro(test_intel_bo->virtual, intel.pitch, intel.h, dst_x, dst_y, w, h);
+
+out:
+ nouveau_bo_ref(NULL, &bo_linear);
+ nouveau_bo_ref(NULL, &bo_nvidia);
+ nouveau_bo_ref(NULL, &bo_intel);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+static int check1_swizzle(uint32_t *p, uint32_t pitch, uint32_t lines,
+ uint32_t dst_x, uint32_t dst_y, uint32_t w, uint32_t h)
+{
+ uint32_t i, val, j;
+
+ for (j = 0; j < 32; ++j, p += (pitch - w)/4) {
+ for (i = 0; i < 8; ++i, p += 4) {
+ val = (i * 32) + j;
+ val = (val) | (val << 8) | (val << 16) | (val << 24);
+ if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) {
+ fprintf(stderr, "Retile check failed in first tile!\n");
+ fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n",
+ p[0], p[1], p[2], p[3], val);
+ return -1;
+ }
+ }
+
+ val = 0x3e3e3e3e;
+ for (; i < w/16; ++i, p += 4) {
+ if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) {
+ fprintf(stderr, "Retile check failed in second tile!\n");
+ fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n",
+ p[0], p[1], p[2], p[3], val);
+ return -1;
+ }
+ }
+ }
+
+ for (j = 32; j < h; ++j, p += (pitch - w)/4) {
+ val = 0x7e7e7e7e;
+ for (i = 0; i < 8; ++i, p += 4) {
+ if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) {
+ fprintf(stderr, "Retile check failed in third tile!\n");
+ fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n",
+ p[0], p[1], p[2], p[3], val);
+ return -1;
+ }
+ }
+
+ val = 0xcececece;
+ for (; i < w/16; ++i, p += 4) {
+ if (p[0] != val || p[1] != val || p[2] != val || p[3] != val) {
+ fprintf(stderr, "Retile check failed in fourth tile!\n");
+ fprintf(stderr, "%08x %08x %08x %08x instead of %08x\n",
+ p[0], p[1], p[2], p[3], val);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Create a new bo, set tiling to y, and see if macro swizzling is done correctl */
+static int test1_swizzle(void)
+{
+ struct nouveau_bo *bo_intel = NULL, *bo_nvidia = NULL, *bo_linear = NULL;
+ rect intel, nvidia, linear;
+ int ret = -1;
+ uint32_t tiling = I915_TILING_Y;
+
+ uint32_t src_x = 0, src_y = 0;
+ uint32_t dst_x = 0, dst_y = 0;
+ uint32_t x, y, w = 256, h = 64;
+ uint8_t *ptr;
+
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", w * h, 4096);
+ if (!test_intel_bo)
+ return -1;
+ drm_intel_bo_set_tiling(test_intel_bo, &tiling, w);
+ if (tiling != I915_TILING_Y) {
+ fprintf(stderr, "Couldn't set y tiling\n");
+ goto out;
+ }
+ ret = drm_intel_gem_bo_map_gtt(test_intel_bo);
+ if (ret)
+ goto out;
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+ if (prime_fd < 0) {
+ drm_intel_bo_unreference(test_intel_bo);
+ goto out;
+ }
+
+ ret = nv_bo_alloc(&bo_intel, &intel, w, h, tile_intel_y, prime_fd, 0);
+ if (!ret)
+ ret = nv_bo_alloc(&bo_nvidia, &nvidia, w, h, 0x10, -1, NOUVEAU_BO_VRAM);
+ if (!ret)
+ ret = nv_bo_alloc(&bo_linear, &linear, w, h, 0, -1, NOUVEAU_BO_GART);
+ if (ret)
+ goto out;
+
+ noop_intel(test_intel_bo);
+ ptr = bo_linear->map;
+ for (x = 0; x < 128; x += 16)
+ for (y = 0; y < 32; ++y)
+ fill16(&ptr[y * w + x], x * 2 + y);
+
+ /* second tile */
+ for (x = 128; x < w; x += 16)
+ for (y = 0; y < 32; ++y)
+ fill16(&ptr[y * w + x], 0x3e);
+
+ /* third tile */
+ for (x = 0; x < 128; x += 16)
+ for (y = 32; y < h; ++y)
+ fill16(&ptr[y * w + x], 0x7e);
+
+ /* last tile */
+ for (x = 128; x < w; x += 16)
+ for (y = 32; y < h; ++y)
+ fill16(&ptr[y * w + x], 0xce);
+
+ ret = perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h);
+ if (ret)
+ goto out;
+
+ /* Perform the actual sub rectangle copy */
+ ret = perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h);
+ if (ret)
+ goto out;
+ noop_intel(test_intel_bo);
+
+ ret = check1_swizzle(test_intel_bo->virtual, intel.pitch, intel.h, dst_x, dst_y, w, h);
+
+out:
+ nouveau_bo_ref(NULL, &bo_linear);
+ nouveau_bo_ref(NULL, &bo_nvidia);
+ nouveau_bo_ref(NULL, &bo_intel);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+/* test 2, see if we can copy from linear to intel X format safely
+ * Seems nvidia lacks a method to do it, so just keep this test
+ * as a reference for potential future tests. Software tiling is
+ * used for now
+ */
+static int test2(void)
+{
+ int ret;
+ struct nouveau_bo *nvbo = NULL, *nvbi = NULL;
+ rect dst, src;
+ uint8_t *ptr;
+ uint32_t w = 1024, h = 16, x, y;
+
+ ret = nv_bo_alloc(&nvbi, &src, w, h, 0, -1, NOUVEAU_BO_GART);
+ if (ret >= 0)
+ ret = nv_bo_alloc(&nvbo, &dst, w, h, tile_intel_x, -1, NOUVEAU_BO_GART);
+ if (ret < 0)
+ goto out;
+
+ /* Set up something for our tile that should map into the first
+ * y-major tile, assuming my understanding of documentation is
+ * correct
+ */
+
+ /* First tile should be read out in groups of 16 bytes that
+ * are all set to a linear increasing value..
+ */
+ ptr = nvbi->map;
+ for (y = 0; y < 8; ++y)
+ for (x = 0; x < 512; x += 16)
+ fill16(&ptr[y * w + x], (y * 512 + x)/16);
+
+ for (y = 0; y < 8; ++y)
+ for (x = 512; x < w; x += 16)
+ fill16(&ptr[y * w + x], 0x3e);
+
+ for (y = 8; y < h; ++y)
+ for (x = 0; x < 512; x += 16)
+ fill16(&ptr[y * w + x], 0x7e);
+
+ for (y = 8; y < h; ++y)
+ for (x = 512; x < w; x += 16)
+ fill16(&ptr[y * w + x], 0xce);
+ memset(nvbo->map, 0xfc, w * h);
+
+ /* do this in software, there is no X major tiling in PCOPY (yet?) */
+ if (0 && pcopy)
+ ret = perform_copy(nvbo, &dst, 0, 0, nvbi, &src, 0, 0, w, h);
+ else
+ ret = swtile_x(nvbo->map, nvbi->map, w, h);
+ if (!ret)
+ ret = check1_macro(nvbo->map, w/512, h/8);
+
+out:
+ nouveau_bo_ref(NULL, &nvbo);
+ nouveau_bo_ref(NULL, &nvbi);
+ return ret;
+}
+
+static int check3(const uint32_t *p, uint32_t pitch, uint32_t lines,
+ uint32_t sub_x, uint32_t sub_y,
+ uint32_t sub_w, uint32_t sub_h)
+{
+ uint32_t x, y;
+
+ sub_w += sub_x;
+ sub_h += sub_y;
+
+ if (p[pitch * lines / 4 - 1] == 0x03030303) {
+ fprintf(stderr, "copy failed: Not all lines have been copied back!\n");
+ return -1;
+ }
+
+ for (y = 0; y < lines; ++y) {
+ for (x = 0; x < pitch; x += 4, ++p) {
+ uint32_t expected;
+ if ((x < sub_x || x >= sub_w) ||
+ (y < sub_y || y >= sub_h))
+ expected = 0x80808080;
+ else
+ expected = 0x04040404;
+ if (*p != expected) {
+ fprintf(stderr, "%u,%u should be %08x, but is %08x\n", x, y, expected, *p);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* copy from nvidia bo to intel bo and copy to a linear bo to check if tiling went succesful */
+static int test3_base(int tile_src, int tile_dst)
+{
+ struct nouveau_bo *bo_intel = NULL, *bo_nvidia = NULL, *bo_linear = NULL;
+ rect intel, nvidia, linear;
+ int ret;
+ uint32_t cpp = 4;
+
+ uint32_t src_x = 1 * cpp, src_y = 1;
+ uint32_t dst_x = 2 * cpp, dst_y = 26;
+ uint32_t w = 298 * cpp, h = 298;
+
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", 2048 * cpp * 768, 4096);
+ if (!test_intel_bo)
+ return -1;
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+ if (prime_fd < 0) {
+ drm_intel_bo_unreference(test_intel_bo);
+ return -1;
+ }
+
+ ret = nv_bo_alloc(&bo_intel, &intel, 2048 * cpp, 768, tile_dst, prime_fd, 0);
+ if (!ret)
+ ret = nv_bo_alloc(&bo_nvidia, &nvidia, 300 * cpp, 300, tile_src, -1, NOUVEAU_BO_VRAM);
+ if (!ret)
+ ret = nv_bo_alloc(&bo_linear, &linear, 2048 * cpp, 768, 0, -1, NOUVEAU_BO_GART);
+ if (ret)
+ goto out;
+
+ noop_intel(test_intel_bo);
+ memset(bo_linear->map, 0x80, bo_linear->size);
+ ret = perform_copy(bo_intel, &intel, 0, 0, bo_linear, &linear, 0, 0, linear.pitch, linear.h);
+ if (ret)
+ goto out;
+ noop_intel(test_intel_bo);
+
+ memset(bo_linear->map, 0x04, bo_linear->size);
+ ret = perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h);
+ if (ret)
+ goto out;
+
+ /* Perform the actual sub rectangle copy */
+ noop_intel(test_intel_bo);
+ ret = perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h);
+ if (ret)
+ goto out;
+ noop_intel(test_intel_bo);
+
+ memset(bo_linear->map, 0x3, bo_linear->size);
+ noop_intel(test_intel_bo);
+ ret = perform_copy(bo_linear, &linear, 0, 0, bo_intel, &intel, 0, 0, intel.pitch, intel.h);
+ if (ret)
+ goto out;
+ noop_intel(test_intel_bo);
+
+ ret = check3(bo_linear->map, linear.pitch, linear.h, dst_x, dst_y, w, h);
+
+out:
+ nouveau_bo_ref(NULL, &bo_linear);
+ nouveau_bo_ref(NULL, &bo_nvidia);
+ nouveau_bo_ref(NULL, &bo_intel);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+static int test3_1(void)
+{
+ /* nvidia tiling to intel */
+ return test3_base(0x40, tile_intel_y);
+}
+
+static int test3_2(void)
+{
+ /* intel tiling to nvidia */
+ return test3_base(tile_intel_y, 0x40);
+}
+
+static int test3_3(void)
+{
+ /* intel tiling to linear */
+ return test3_base(tile_intel_y, 0);
+}
+
+static int test3_4(void)
+{
+ /* linear tiling to intel */
+ return test3_base(0, tile_intel_y);
+}
+
+static int test3_5(void)
+{
+ /* linear to linear */
+ return test3_base(0, 0);
+}
+
+/* Acquire when == SEQUENCE */
+#define SEMA_ACQUIRE_EQUAL 1
+
+/* Release, and write a 16 byte query structure to sema:
+ * { (uint32)seq, (uint32)0, (uint64)timestamp } */
+#define SEMA_WRITE_LONG 2
+
+/* Acquire when >= SEQUENCE */
+#define SEMA_ACQUIRE_GEQUAL 4
+
+/* Test only new style semaphores, old ones are AWFUL */
+static int test_semaphore(void)
+{
+ drm_intel_bo *test_intel_bo = NULL;
+ struct nouveau_bo *sema_bo = NULL;
+ int ret = -1, prime_fd;
+ uint32_t *sema;
+ struct nouveau_pushbuf *push = npush;
+
+ if (ndev->chipset < 0x84)
+ return -1;
+
+ /* Should probably be kept in sysmem */
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "semaphore bo", 4096, 4096);
+ if (!test_intel_bo)
+ goto out;
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+ if (prime_fd < 0)
+ goto out;
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &sema_bo);
+ close(prime_fd);
+ if (ret < 0)
+ goto out;
+
+ ret = drm_intel_gem_bo_map_gtt(test_intel_bo);
+ if (ret != 0) {
+ fprintf(stderr,"failed to map bo\n");
+ goto out;
+ }
+ sema = test_intel_bo->virtual;
+ sema++;
+ *sema = 0;
+
+ ret = -1;
+ if (nouveau_pushbuf_space(push, 64, 0, 0) ||
+ nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn)
+ { sema_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR }, 1))
+ goto out;
+
+ if (ndev->chipset < 0xc0) {
+ struct nv04_fifo *nv04_fifo = nchannel->data;
+ /* kernel binds it's own dma object here and overwrites old one,
+ * so just rebind vram every time we submit
+ */
+ BEGIN_NV04(npush, SUBC_COPY(0x0060), 1);
+ PUSH_DATA(npush, nv04_fifo->vram);
+ }
+ BEGIN_NVXX(push, SUBC_COPY(0x0010), 4);
+ PUSH_DATA(push, sema_bo->offset >> 32);
+ PUSH_DATA(push, sema_bo->offset + 4);
+ PUSH_DATA(push, 2); // SEQUENCE
+ PUSH_DATA(push, SEMA_WRITE_LONG); // TRIGGER
+
+ BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
+ PUSH_DATA(push, 3);
+ PUSH_DATA(push, SEMA_ACQUIRE_EQUAL);
+ BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
+ PUSH_DATA(push, 4);
+ PUSH_DATA(push, SEMA_WRITE_LONG);
+
+ BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
+ PUSH_DATA(push, 5);
+ PUSH_DATA(push, SEMA_ACQUIRE_GEQUAL);
+ BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
+ PUSH_DATA(push, 6);
+ PUSH_DATA(push, SEMA_WRITE_LONG);
+
+ BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
+ PUSH_DATA(push, 7);
+ PUSH_DATA(push, SEMA_ACQUIRE_GEQUAL);
+ BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
+ PUSH_DATA(push, 9);
+ PUSH_DATA(push, SEMA_WRITE_LONG);
+ nouveau_pushbuf_kick(push, push->channel);
+
+ usleep(1000);
+ if (*sema != 2) {
+ fprintf(stderr, "new sema should be 2 is %u\n", *sema);
+ goto out;
+ }
+
+ *sema = 3;
+ usleep(1000);
+ if (*sema != 4) {
+ fprintf(stderr, "new sema should be 4 is %u\n", *sema);
+ goto out;
+ }
+
+ *sema = 5;
+ usleep(1000);
+ if (*sema != 6) {
+ fprintf(stderr, "new sema should be 6 is %u\n", *sema);
+ goto out;
+ }
+
+ *sema = 8;
+ usleep(1000);
+ if (*sema != 9) {
+ fprintf(stderr, "new sema should be 9 is %u\n", *sema);
+ goto out;
+ }
+ ret = 0;
+
+out:
+ nouveau_bo_ref(NULL, &sema_bo);
+ if (test_intel_bo)
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret, failed = 0, run = 0;
+
+ ret = find_and_open_devices();
+ if (ret < 0)
+ return ret;
+
+ if (nouveau_fd == -1 || intel_fd == -1) {
+ fprintf(stderr,"failed to find intel and nouveau GPU\n");
+ return 77;
+ }
+
+ /* set up intel bufmgr */
+ bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096);
+ if (!bufmgr)
+ return -1;
+ /* Do not enable reuse, we share (almost) all buffers. */
+ //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ /* set up nouveau bufmgr */
+ ret = init_nouveau();
+ if (ret < 0)
+ return 77;
+
+ /* set up an intel batch buffer */
+ devid = intel_get_drm_devid(intel_fd);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+#define xtest(x, args...) do { \
+ ret = ((x)(args)); \
+ ++run; \
+ if (ret) { \
+ ++failed; \
+ fprintf(stderr, "prime_pcopy: failed " #x "\n"); } \
+ } while (0)
+
+ xtest(test1_macro);
+ xtest(test1_micro);
+ xtest(test1_swizzle);
+ xtest(test2);
+ xtest(test3_1);
+ xtest(test3_2);
+ xtest(test3_3);
+ xtest(test3_4);
+ xtest(test3_5);
+ xtest(test_semaphore);
+
+ nouveau_bo_ref(NULL, &query_bo);
+ nouveau_object_del(&pcopy);
+ nouveau_bufctx_del(&nbufctx);
+ nouveau_pushbuf_del(&npush);
+ nouveau_object_del(&nchannel);
+
+ intel_batchbuffer_free(batch);
+
+ nouveau_client_del(&nclient);
+ nouveau_device_del(&ndev);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(intel_fd);
+ close(nouveau_fd);
+
+ printf("Tests: %u run, %u failed\n", run, failed);
+ return failed;
+}
diff --git a/tests/prime_nv_test.c b/tests/prime_nv_test.c
new file mode 100644
index 00000000..2269f84f
--- /dev/null
+++ b/tests/prime_nv_test.c
@@ -0,0 +1,582 @@
+/* basic set of prime tests between intel and nouveau */
+
+/* test list -
+ 1. share buffer from intel -> nouveau.
+ 2. share buffer from nouveau -> intel
+ 3. share intel->nouveau, map on both, write intel, read nouveau
+ 4. share intel->nouveau, blit intel fill, readback on nouveau
+ test 1 + map buffer, read/write, map other size.
+ do some hw actions on the buffer
+ some illegal operations -
+ close prime fd try and map
+
+ TODO add some nouveau rendering tests
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include "i915_drm.h"
+#include "intel_bufmgr.h"
+#include "nouveau.h"
+#include "intel_gpu_tools.h"
+#include "intel_batchbuffer.h"
+
+int intel_fd = -1, nouveau_fd = -1;
+drm_intel_bufmgr *bufmgr;
+struct nouveau_device *ndev;
+struct nouveau_client *nclient;
+uint32_t devid;
+struct intel_batchbuffer *intel_batch;
+
+#define BO_SIZE (256*1024)
+
+static int find_and_open_devices(void)
+{
+ int i;
+ char path[80];
+ struct stat buf;
+ FILE *fl;
+ char vendor_id[8];
+ int venid;
+ for (i = 0; i < 9; i++) {
+ sprintf(path, "/sys/class/drm/card%d/device/vendor", i);
+ if (stat(path, &buf))
+ break;
+
+ fl = fopen(path, "r");
+ if (!fl)
+ break;
+
+ fgets(vendor_id, 8, fl);
+ fclose(fl);
+
+ venid = strtoul(vendor_id, NULL, 16);
+ sprintf(path, "/dev/dri/card%d", i);
+ if (venid == 0x8086) {
+ intel_fd = open(path, O_RDWR);
+ if (!intel_fd)
+ return -1;
+ } else if (venid == 0x10de) {
+ nouveau_fd = open(path, O_RDWR);
+ if (!nouveau_fd)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * prime test 1 -
+ * allocate buffer on intel,
+ * set prime on buffer,
+ * retrive buffer from nouveau,
+ * close prime_fd,
+ * unref buffers
+ */
+static int test1(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo);
+ close(prime_fd);
+ if (ret < 0)
+ return ret;
+
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return 0;
+}
+
+/*
+ * prime test 2 -
+ * allocate buffer on nouveau
+ * set prime on buffer,
+ * retrive buffer from intel
+ * close prime_fd,
+ * unref buffers
+ */
+static int test2(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo;
+
+ ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
+ 0, BO_SIZE, NULL, &nvbo);
+ if (ret < 0)
+ return ret;
+ ret = nouveau_bo_set_prime(nvbo, &prime_fd);
+ if (ret < 0)
+ return ret;
+
+ test_intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE);
+ close(prime_fd);
+ if (!test_intel_bo)
+ return -1;
+
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return 0;
+}
+
+/*
+ * allocate intel, give to nouveau, map on nouveau
+ * write 0xdeadbeef, non-gtt map on intel, read
+ */
+static int test3(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo = NULL;
+ uint32_t *ptr;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo);
+ if (ret < 0) {
+ fprintf(stderr,"failed to ref prime buffer %d\n", ret);
+ close(prime_fd);
+ goto free_intel;
+ }
+ close(prime_fd);
+ goto free_intel;
+
+ ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to map nouveau bo\n");
+ goto out;
+ }
+
+ ptr = nvbo->map;
+ *ptr = 0xdeadbeef;
+
+ drm_intel_bo_map(test_intel_bo, 1);
+
+ ptr = test_intel_bo->virtual;
+
+ if (*ptr != 0xdeadbeef) {
+ fprintf(stderr,"mapped value doesn't match\n");
+ ret = -1;
+ }
+out:
+ nouveau_bo_ref(NULL, &nvbo);
+free_intel:
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+/*
+ * allocate intel, give to nouveau, map on nouveau
+ * write 0xdeadbeef, gtt map on intel, read
+ */
+static int test4(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo = NULL;
+ uint32_t *ptr;
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo);
+ close(prime_fd);
+ if (ret < 0) {
+ fprintf(stderr,"failed to ref prime buffer\n");
+ return ret;
+ }
+
+ ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to map nouveau bo\n");
+ goto out;
+ }
+
+
+ ptr = nvbo->map;
+ *ptr = 0xdeadbeef;
+
+ drm_intel_gem_bo_map_gtt(test_intel_bo);
+ ptr = test_intel_bo->virtual;
+
+ if (*ptr != 0xdeadbeef) {
+ fprintf(stderr,"mapped value doesn't match\n");
+ ret = -1;
+ }
+out:
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+/* test drm_intel_bo_map doesn't work properly,
+ this tries to map the backing shmem fd, which doesn't exist
+ for these objects */
+static int test5(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo;
+ uint32_t *ptr;
+
+ ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
+ 0, BO_SIZE, NULL, &nvbo);
+ if (ret < 0)
+ return ret;
+ ret = nouveau_bo_set_prime(nvbo, &prime_fd);
+ if (ret < 0)
+ return ret;
+
+ test_intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE);
+ close(prime_fd);
+ if (!test_intel_bo)
+ return -1;
+
+ ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to map nouveau bo\n");
+ goto out;
+ }
+
+ ptr = nvbo->map;
+ *ptr = 0xdeadbeef;
+
+ ret = drm_intel_bo_map(test_intel_bo, 0);
+ if (ret != 0) {
+ /* failed to map the bo is expected */
+ ret = 0;
+ goto out;
+ }
+ if (!test_intel_bo->virtual) {
+ ret = 0;
+ goto out;
+ }
+ ptr = test_intel_bo->virtual;
+
+ if (*ptr != 0xdeadbeef) {
+ fprintf(stderr,"mapped value doesn't match %08x\n", *ptr);
+ ret = -1;
+ }
+ out:
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+/* test drm_intel_bo_map_gtt works properly,
+ this tries to map the backing shmem fd, which doesn't exist
+ for these objects */
+static int test6(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo;
+ uint32_t *ptr;
+
+ ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
+ 0, BO_SIZE, NULL, &nvbo);
+ if (ret < 0)
+ return ret;
+ ret = nouveau_bo_set_prime(nvbo, &prime_fd);
+ if (ret < 0)
+ return ret;
+
+ test_intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE);
+ close(prime_fd);
+ if (!test_intel_bo)
+ return -1;
+
+ ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to map nouveau bo\n");
+ goto out;
+ }
+
+ ptr = nvbo->map;
+ *ptr = 0xdeadbeef;
+ *(ptr + 1) = 0xa55a55;
+
+ ret = drm_intel_gem_bo_map_gtt(test_intel_bo);
+ if (ret != 0) {
+ fprintf(stderr,"failed to map bo\n");
+ goto out;
+ }
+ if (!test_intel_bo->virtual) {
+ ret = -1;
+ fprintf(stderr,"failed to map bo\n");
+ goto out;
+ }
+ ptr = test_intel_bo->virtual;
+
+ if (*ptr != 0xdeadbeef) {
+ fprintf(stderr,"mapped value doesn't match %08x %08x\n", *ptr, *(ptr + 1));
+ ret = -1;
+ }
+ out:
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+static int do_read(int fd, int handle, void *buf, int offset, int size)
+{
+ struct drm_i915_gem_pread intel_pread;
+
+ /* Ensure that we don't have any convenient data in buf in case
+ * we fail.
+ */
+ memset(buf, 0xd0, size);
+
+ memset(&intel_pread, 0, sizeof(intel_pread));
+ intel_pread.handle = handle;
+ intel_pread.data_ptr = (uintptr_t)buf;
+ intel_pread.size = size;
+ intel_pread.offset = offset;
+
+ return ioctl(fd, DRM_IOCTL_I915_GEM_PREAD, &intel_pread);
+}
+
+static int do_write(int fd, int handle, void *buf, int offset, int size)
+{
+ struct drm_i915_gem_pwrite intel_pwrite;
+
+ memset(&intel_pwrite, 0, sizeof(intel_pwrite));
+ intel_pwrite.handle = handle;
+ intel_pwrite.data_ptr = (uintptr_t)buf;
+ intel_pwrite.size = size;
+ intel_pwrite.offset = offset;
+
+ return ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &intel_pwrite);
+}
+
+/* test 7 - import from nouveau into intel, test pread/pwrite fail */
+static int test7(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo;
+ uint32_t *ptr;
+ uint32_t buf[64];
+
+ ret = nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
+ 0, BO_SIZE, NULL, &nvbo);
+ if (ret < 0)
+ return ret;
+ ret = nouveau_bo_set_prime(nvbo, &prime_fd);
+ if (ret < 0)
+ return ret;
+
+ test_intel_bo = drm_intel_bo_gem_create_from_prime(bufmgr, prime_fd, BO_SIZE);
+ close(prime_fd);
+ if (!test_intel_bo)
+ return -1;
+
+ ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to map nouveau bo\n");
+ goto out;
+ }
+
+ ptr = nvbo->map;
+ *ptr = 0xdeadbeef;
+
+ ret = do_read(intel_fd, test_intel_bo->handle, buf, 0, 256);
+ if (ret != -1) {
+ fprintf(stderr,"pread succeedded %d\n", ret);
+ goto out;
+ }
+ buf[0] = 0xabcdef55;
+
+ ret = do_write(intel_fd, test_intel_bo->handle, buf, 0, 4);
+ if (ret != -1) {
+ fprintf(stderr,"pwrite succeedded\n");
+ goto out;
+ }
+ ret = 0;
+ out:
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+static void
+set_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
+{
+ int size = width * height;
+ uint32_t *vaddr;
+
+ drm_intel_gem_bo_start_gtt_access(bo, true);
+ vaddr = bo->virtual;
+ while (size--)
+ *vaddr++ = val;
+}
+
+static drm_intel_bo *
+create_bo(drm_intel_bufmgr *ibufmgr, uint32_t val, int width, int height)
+{
+ drm_intel_bo *bo;
+
+ bo = drm_intel_bo_alloc(ibufmgr, "bo", 4*width*height, 0);
+ assert(bo);
+
+ /* gtt map doesn't have a write parameter, so just keep the mapping
+ * around (to avoid the set_domain with the gtt write domain set) and
+ * manually tell the kernel when we start access the gtt. */
+ drm_intel_gem_bo_map_gtt(bo);
+
+ set_bo(bo, val, width, height);
+
+ return bo;
+}
+
+/* use intel hw to fill the BO with a blit from another BO,
+ then readback from the nouveau bo, check value is correct */
+static int test8(void)
+{
+ int ret;
+ drm_intel_bo *test_intel_bo, *src_bo;
+ int prime_fd;
+ struct nouveau_bo *nvbo = NULL;
+ uint32_t *ptr;
+
+ src_bo = create_bo(bufmgr, 0xaa55aa55, 256, 1);
+
+ test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096);
+
+ drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
+
+ ret = nouveau_bo_prime_handle_ref(ndev, prime_fd, &nvbo);
+ close(prime_fd);
+ if (ret < 0) {
+ fprintf(stderr,"failed to ref prime buffer\n");
+ return ret;
+ }
+
+ intel_copy_bo(intel_batch, test_intel_bo, src_bo, 256, 1);
+
+ ret = nouveau_bo_map(nvbo, NOUVEAU_BO_RDWR, nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to map nouveau bo\n");
+ goto out;
+ }
+
+ drm_intel_bo_map(test_intel_bo, 0);
+
+ ptr = nvbo->map;
+ if (*ptr != 0xaa55aa55) {
+ fprintf(stderr,"mapped value doesn't match\n");
+ ret = -1;
+ }
+out:
+ nouveau_bo_ref(NULL, &nvbo);
+ drm_intel_bo_unreference(test_intel_bo);
+ return ret;
+}
+
+/* test 8 use nouveau to do blit */
+
+/* test 9 nouveau copy engine?? */
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ ret = find_and_open_devices();
+ if (ret < 0)
+ return ret;
+
+ if (nouveau_fd == -1 || intel_fd == -1) {
+ fprintf(stderr,"failed to find intel and nouveau GPU\n");
+ return 77;
+ }
+
+ /* set up intel bufmgr */
+ bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096);
+ if (!bufmgr)
+ return -1;
+ /* Do not enable reuse, we share (almost) all buffers. */
+ //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+
+ /* set up nouveau bufmgr */
+ ret = nouveau_device_wrap(nouveau_fd, 0, &ndev);
+ if (ret < 0) {
+ fprintf(stderr,"failed to wrap nouveau device\n");
+ return 77;
+ }
+
+ ret = nouveau_client_new(ndev, &nclient);
+ if (ret < 0) {
+ fprintf(stderr,"failed to setup nouveau client\n");
+ return -1;
+ }
+
+ /* set up an intel batch buffer */
+ devid = intel_get_drm_devid(intel_fd);
+ intel_batch = intel_batchbuffer_alloc(bufmgr, devid);
+
+ /* create an object on the i915 */
+ ret = test1();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 1\n");
+
+ ret = test2();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 2\n");
+
+ ret = test3();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 3\n");
+
+ ret = test4();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 4\n");
+
+ ret = test5();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 5\n");
+
+ ret = test6();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 6\n");
+
+ ret = test7();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 7\n");
+
+ ret = test8();
+ if (ret)
+ fprintf(stderr,"prime_test: failed test 8\n");
+
+ intel_batchbuffer_free(intel_batch);
+
+ nouveau_device_del(&ndev);
+ drm_intel_bufmgr_destroy(bufmgr);
+
+ close(intel_fd);
+ close(nouveau_fd);
+
+ return ret;
+}
diff --git a/tests/prime_self_import.c b/tests/prime_self_import.c
new file mode 100644
index 00000000..111ed4da
--- /dev/null
+++ b/tests/prime_self_import.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Daniel Vetter <daniel.vetter@ffwll.ch>
+ *
+ */
+
+/*
+ * Testcase: Check whether prime import/export works on the same device
+ *
+ * ... but with different fds, i.e. the wayland usecase.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "i915_drm.h"
+#include "drmtest.h"
+
+#define BO_SIZE (16*1024)
+
+static void
+check_bo(int fd1, uint32_t handle1, int fd2, uint32_t handle2)
+{
+ char *ptr1, *ptr2;
+ static char counter = 0;
+ int i;
+
+ ptr1 = gem_mmap(fd1, handle1, BO_SIZE, PROT_READ | PROT_WRITE);
+ ptr2 = gem_mmap(fd2, handle2, BO_SIZE, PROT_READ | PROT_WRITE);
+
+ assert(ptr1);
+
+ /* check whether it's still our old object first. */
+ for (i = 0; i < BO_SIZE; i++) {
+ assert(ptr1[i] == counter);
+ assert(ptr2[i] == counter);
+ }
+
+ counter++;
+
+ memset(ptr1, counter, BO_SIZE);
+ assert(memcmp(ptr1, ptr2, BO_SIZE) == 0);
+
+ munmap(ptr1, BO_SIZE);
+ munmap(ptr2, BO_SIZE);
+}
+
+int main(int argc, char **argv)
+{
+ int fd1, fd2;
+ uint32_t handle, handle_import1, handle_import2, handle_selfimport;
+ int dma_buf_fd;
+
+ fd1 = drm_open_any();
+ fd2 = drm_open_any();
+
+ handle = gem_create(fd1, BO_SIZE);
+
+ dma_buf_fd = prime_handle_to_fd(fd1, handle);
+ handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
+
+ check_bo(fd1, handle, fd2, handle_import1);
+
+ /* reimport should give us the same handle so that userspace can check
+ * whether it has that bo already somewhere. */
+ handle_import2 = prime_fd_to_handle(fd2, dma_buf_fd);
+ assert(handle_import1 == handle_import2);
+
+ /* Same for re-importing on the exporting fd. */
+ handle_selfimport = prime_fd_to_handle(fd1, dma_buf_fd);
+ assert(handle == handle_selfimport);
+
+ /* close dma_buf, check whether nothing disappears. */
+ close(dma_buf_fd);
+ check_bo(fd1, handle, fd2, handle_import1);
+
+ gem_close(fd1, handle);
+ check_bo(fd2, handle_import1, fd2, handle_import1);
+
+ /* re-import into old exporter */
+ dma_buf_fd = prime_handle_to_fd(fd2, handle_import1);
+ /* but drop all references to the obj in between */
+ gem_close(fd2, handle_import1);
+ handle = prime_fd_to_handle(fd1, dma_buf_fd);
+ handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
+ check_bo(fd1, handle, fd2, handle_import1);
+
+ /* Completely rip out exporting fd. */
+ close(fd1);
+ check_bo(fd2, handle_import1, fd2, handle_import1);
+
+ return 0;
+}
diff --git a/tests/sysfs_edid_timing b/tests/sysfs_edid_timing
new file mode 100755
index 00000000..3a8c6c0e
--- /dev/null
+++ b/tests/sysfs_edid_timing
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# This check the time we take to read the content of all the possible connectors.
+# Without the edid -ENXIO patch (http://permalink.gmane.org/gmane.comp.video.dri.devel/62083),
+# we sometimes take a *really* long time. So let's just check for some reasonable timing here
+#
+
+TIME1=$(date +%s%N)
+cat $(find /sys/devices/|grep drm | grep /status) > /dev/null
+TIME2=$(date +%s%N)
+
+# time in ms
+RES=$(((TIME2 - TIME1) / 1000000))
+
+if [ $RES -gt 600 ]; then
+ echo "Talking to outputs took ${RES}ms, something is wrong"
+ exit 1
+fi
+
+exit 0
diff --git a/tests/sysfs_l3_parity b/tests/sysfs_l3_parity
new file mode 100755
index 00000000..6f814a13
--- /dev/null
+++ b/tests/sysfs_l3_parity
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+if ! find /sys/class/drm/card*/ | grep l3_parity > /dev/null ; then
+ echo "no l3_parity interface, skipping test"
+ exit 77
+fi
+
+SOURCE_DIR="$( dirname "${BASH_SOURCE[0]}" )"
+. $SOURCE_DIR/drm_lib.sh
+
+$SOURCE_DIR/../tools/intel_l3_parity -c
+
+#Check that we can remap a row
+$SOURCE_DIR/../tools/intel_l3_parity 0,0,0
+disabled=`$SOURCE_DIR/../tools/intel_l3_parity | grep -c 'Row 0, Bank 0, Subbank 0 is disabled'`
+if [ "$disabled" != "1" ] ; then
+ echo "Fail"
+ exit 1
+fi
+
+$SOURCE_DIR/../tools/intel_l3_parity -c
+
+#Check that we can clear remaps
+if [ `$SOURCE_DIR/../tools/intel_l3_parity | wc -c` != "0" ] ; then
+ echo "Fail"
+ exit 1
+fi
diff --git a/tests/sysfs_rc6_residency.c b/tests/sysfs_rc6_residency.c
new file mode 100644
index 00000000..2f33697a
--- /dev/null
+++ b/tests/sysfs_rc6_residency.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "drmtest.h"
+
+#define SLEEP_DURATION 3000 // in milliseconds
+#define RC6_FUDGE 900 // in milliseconds
+
+static unsigned int readit(const char *path)
+{
+ unsigned int ret;
+
+ FILE *file;
+ file = fopen(path, "r");
+ if (file == NULL) {
+ fprintf(stderr, "Couldn't open %s (%d)\n", path, errno);
+ abort();
+ }
+ fscanf(file, "%u", &ret);
+ fclose(file);
+
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ const int device = drm_get_card(0);
+ char *path, *pathp, *pathpp;
+ int fd, ret;
+ unsigned int value1, value1p, value1pp, value2, value2p, value2pp;
+ FILE *file;
+ int diff;
+
+ /* Use drm_open_any to verify device existence */
+ fd = drm_open_any();
+ close(fd);
+
+ ret = asprintf(&path, "/sys/class/drm/card%d/power/rc6_enable", device);
+ assert(ret != -1);
+
+ /* For some reason my ivb isn't idle even after syncing up with the gpu.
+ * Let's add a sleept just to make it happy. */
+ sleep(5);
+
+ file = fopen(path, "r");
+ if (!file) {
+ printf("kernel too old or rc6 not supported on this platform.\n");
+ exit(77);
+ }
+
+ /* claim success if no rc6 enabled. */
+ if (readit(path) == 0)
+ exit(EXIT_SUCCESS);
+
+ ret = asprintf(&path, "/sys/class/drm/card%d/power/rc6_residency_ms", device);
+ assert(ret != -1);
+ ret = asprintf(&pathp, "/sys/class/drm/card%d/power/rc6p_residency_ms", device);
+ assert(ret != -1);
+ ret = asprintf(&pathpp, "/sys/class/drm/card%d/power/rc6pp_residency_ms", device);
+ assert(ret != -1);
+
+ value1 = readit(path);
+ value1p = readit(pathp);
+ value1pp = readit(pathpp);
+ sleep(SLEEP_DURATION / 1000);
+ value2 = readit(path);
+ value2p = readit(pathp);
+ value2pp = readit(pathpp);
+
+ free(pathpp);
+ free(pathp);
+ free(path);
+
+ diff = (value2pp - value1pp) +
+ (value2p - value1p) +
+ (value2 - value1);
+
+ if (diff > (SLEEP_DURATION + RC6_FUDGE)) {
+ fprintf(stderr, "Diff was too high. That is unpossible\n");
+ exit(EXIT_FAILURE);
+ }
+ if (diff < (SLEEP_DURATION - RC6_FUDGE)) {
+ fprintf(stderr, "GPU was not in RC6 long enough. Check that "
+ "the GPU is as idle as possible (ie. no X, "
+ "running and running no other tests)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tests/testdisplay.c b/tests/testdisplay.c
new file mode 100644
index 00000000..14d7da39
--- /dev/null
+++ b/tests/testdisplay.c
@@ -0,0 +1,765 @@
+/*
+ * Copyright 2010 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/*
+ * This program is intended for testing of display functionality. It should
+ * allow for testing of
+ * - hotplug
+ * - mode setting
+ * - clone & twin modes
+ * - panel fitting
+ * - test patterns & pixel generators
+ * Additional programs can test the detected outputs against VBT provided
+ * device lists (both docked & undocked).
+ *
+ * TODO:
+ * - pixel generator in transcoder
+ * - test pattern reg in pipe
+ * - test patterns on outputs (e.g. TV)
+ * - handle hotplug (leaks crtcs, can't handle clones)
+ * - allow mode force
+ * - expose output specific controls
+ * - e.g. DDC-CI brightness
+ * - HDMI controls
+ * - panel brightness
+ * - DP commands (e.g. poweroff)
+ * - verify outputs against VBT/physical connectors
+ */
+#include "config.h"
+
+#include <assert.h>
+#include <cairo.h>
+#include <errno.h>
+#include <math.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "i915_drm.h"
+#include "drmtest.h"
+#include "testdisplay.h"
+
+#include <stdlib.h>
+#include <signal.h>
+
+drmModeRes *resources;
+int drm_fd, modes;
+int dump_info = 0, test_all_modes =0, test_preferred_mode = 0, force_mode = 0,
+ test_plane, enable_tiling;
+int sleep_between_modes = 5;
+uint32_t depth = 24, stride, bpp;
+int qr_code = 0;
+
+drmModeModeInfo force_timing;
+
+int crtc_x, crtc_y, crtc_w, crtc_h, width, height;
+unsigned int plane_fb_id;
+unsigned int plane_crtc_id;
+unsigned int plane_id;
+int plane_width, plane_height;
+static const uint32_t SPRITE_COLOR_KEY = 0x00aaaaaa;
+uint32_t *fb_ptr;
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct type_name {
+ int type;
+ const char *name;
+};
+
+#define type_name_fn(res) \
+static const char * res##_str(int type) { \
+ unsigned int i; \
+ for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
+ if (res##_names[i].type == type) \
+ return res##_names[i].name; \
+ } \
+ return "(invalid)"; \
+}
+
+struct type_name encoder_type_names[] = {
+ { DRM_MODE_ENCODER_NONE, "none" },
+ { DRM_MODE_ENCODER_DAC, "DAC" },
+ { DRM_MODE_ENCODER_TMDS, "TMDS" },
+ { DRM_MODE_ENCODER_LVDS, "LVDS" },
+ { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
+};
+
+type_name_fn(encoder_type)
+
+struct type_name connector_status_names[] = {
+ { DRM_MODE_CONNECTED, "connected" },
+ { DRM_MODE_DISCONNECTED, "disconnected" },
+ { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
+};
+
+type_name_fn(connector_status)
+
+struct type_name connector_type_names[] = {
+ { DRM_MODE_CONNECTOR_Unknown, "unknown" },
+ { DRM_MODE_CONNECTOR_VGA, "VGA" },
+ { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
+ { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
+ { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
+ { DRM_MODE_CONNECTOR_Composite, "composite" },
+ { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
+ { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
+ { DRM_MODE_CONNECTOR_Component, "component" },
+ { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
+ { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" },
+ { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
+ { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
+ { DRM_MODE_CONNECTOR_TV, "TV" },
+ { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort" },
+};
+
+type_name_fn(connector_type)
+
+/*
+ * Mode setting with the kernel interfaces is a bit of a chore.
+ * First you have to find the connector in question and make sure the
+ * requested mode is available.
+ * Then you need to find the encoder attached to that connector so you
+ * can bind it with a free crtc.
+ */
+struct connector {
+ uint32_t id;
+ int mode_valid;
+ drmModeModeInfo mode;
+ drmModeEncoder *encoder;
+ drmModeConnector *connector;
+ int crtc;
+ int pipe;
+};
+
+static void dump_connectors_fd(int drmfd)
+{
+ int i, j;
+
+ drmModeRes *mode_resources = drmModeGetResources(drmfd);
+
+ if (!mode_resources) {
+ fprintf(stderr, "drmModeGetResources failed: %s\n",
+ strerror(errno));
+ return;
+ }
+
+ printf("Connectors:\n");
+ printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
+ for (i = 0; i < mode_resources->count_connectors; i++) {
+ drmModeConnector *connector;
+
+ connector = drmModeGetConnector(drmfd, mode_resources->connectors[i]);
+ if (!connector) {
+ fprintf(stderr, "could not get connector %i: %s\n",
+ mode_resources->connectors[i], strerror(errno));
+ continue;
+ }
+
+ printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
+ connector->connector_id,
+ connector->encoder_id,
+ connector_status_str(connector->connection),
+ connector_type_str(connector->connector_type),
+ connector->mmWidth, connector->mmHeight,
+ connector->count_modes);
+
+ if (!connector->count_modes)
+ continue;
+
+ printf(" modes:\n");
+ printf(" name refresh (Hz) hdisp hss hse htot vdisp "
+ "vss vse vtot flags type clock\n");
+ for (j = 0; j < connector->count_modes; j++)
+ kmstest_dump_mode(&connector->modes[j]);
+
+ drmModeFreeConnector(connector);
+ }
+ printf("\n");
+
+ drmModeFreeResources(mode_resources);
+}
+
+static void dump_crtcs_fd(int drmfd)
+{
+ int i;
+ drmModeRes *mode_resources = drmModeGetResources(drmfd);
+
+ printf("CRTCs:\n");
+ printf("id\tfb\tpos\tsize\n");
+ for (i = 0; i < mode_resources->count_crtcs; i++) {
+ drmModeCrtc *crtc;
+
+ crtc = drmModeGetCrtc(drmfd, mode_resources->crtcs[i]);
+ if (!crtc) {
+ fprintf(stderr, "could not get crtc %i: %s\n",
+ mode_resources->crtcs[i], strerror(errno));
+ continue;
+ }
+ printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
+ crtc->crtc_id,
+ crtc->buffer_id,
+ crtc->x, crtc->y,
+ crtc->width, crtc->height);
+ kmstest_dump_mode(&crtc->mode);
+
+ drmModeFreeCrtc(crtc);
+ }
+ printf("\n");
+
+ drmModeFreeResources(mode_resources);
+}
+
+static void connector_find_preferred_mode(struct connector *c)
+{
+ drmModeConnector *connector;
+ drmModeEncoder *encoder = NULL;
+ int i, j;
+
+ /* First, find the connector & mode */
+ c->mode_valid = 0;
+ connector = drmModeGetConnector(drm_fd, c->id);
+ if (!connector) {
+ fprintf(stderr, "could not get connector %d: %s\n",
+ c->id, strerror(errno));
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ if (connector->connection != DRM_MODE_CONNECTED) {
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ if (!connector->count_modes) {
+ fprintf(stderr, "connector %d has no modes\n", c->id);
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ if (connector->connector_id != c->id) {
+ fprintf(stderr, "connector id doesn't match (%d != %d)\n",
+ connector->connector_id, c->id);
+ drmModeFreeConnector(connector);
+ return;
+ }
+
+ for (j = 0; j < connector->count_modes; j++) {
+ c->mode = connector->modes[j];
+ if (c->mode.type & DRM_MODE_TYPE_PREFERRED) {
+ c->mode_valid = 1;
+ break;
+ }
+ }
+
+ if (!c->mode_valid) {
+ if (connector->count_modes > 0) {
+ /* use the first mode as test mode */
+ c->mode = connector->modes[0];
+ c->mode_valid = 1;
+ }
+ else {
+ fprintf(stderr, "failed to find any modes on connector %d\n",
+ c->id);
+ return;
+ }
+ }
+
+ /* Now get the encoder */
+ for (i = 0; i < connector->count_encoders; i++) {
+ encoder = drmModeGetEncoder(drm_fd, connector->encoders[i]);
+
+ if (!encoder) {
+ fprintf(stderr, "could not get encoder %i: %s\n",
+ resources->encoders[i], strerror(errno));
+ drmModeFreeEncoder(encoder);
+ continue;
+ }
+
+ break;
+ }
+
+ c->encoder = encoder;
+
+ if (i == resources->count_encoders) {
+ fprintf(stderr, "failed to find encoder\n");
+ c->mode_valid = 0;
+ return;
+ }
+
+ /* Find first CRTC not in use */
+ for (i = 0; i < resources->count_crtcs; i++) {
+ if (resources->crtcs[i] && (c->encoder->possible_crtcs & (1<<i)))
+ break;
+ }
+ c->crtc = resources->crtcs[i];
+ c->pipe = i;
+
+ if(test_preferred_mode || force_mode)
+ resources->crtcs[i] = 0;
+
+ c->connector = connector;
+}
+
+static void
+paint_color_key(void)
+{
+ int i, j;
+
+ for (i = crtc_y; i < crtc_y + crtc_h; i++)
+ for (j = crtc_x; j < crtc_x + crtc_w; j++) {
+ uint32_t offset;
+
+ offset = (i * width) + j;
+ fb_ptr[offset] = SPRITE_COLOR_KEY;
+ }
+}
+
+static void paint_image(cairo_t *cr, const char *file)
+{
+ int img_x, img_y, img_w, img_h, img_w_o, img_h_o;
+ double img_w_scale, img_h_scale;
+
+ cairo_surface_t *image;
+
+ img_y = height * (0.10 );
+ img_h = height * 0.08 * 4;
+ img_w = img_h;
+
+ img_x = (width / 2) - (img_w / 2);
+
+ image = cairo_image_surface_create_from_png(file);
+
+ img_w_o = cairo_image_surface_get_width(image);
+ img_h_o = cairo_image_surface_get_height(image);
+
+ cairo_translate(cr, img_x, img_y);
+
+ img_w_scale = (double)img_w / (double)img_w_o;
+ img_h_scale = (double)img_h / (double)img_h_o;
+ cairo_scale(cr, img_w_scale, img_h_scale);
+
+ cairo_set_source_surface(cr, image, 0, 0);
+ cairo_scale(cr, 1, 1);
+
+ cairo_paint(cr);
+ cairo_surface_destroy(image);
+}
+
+static void
+paint_output_info(cairo_t *cr, int l_width, int l_height, void *priv)
+{
+ struct connector *c = priv;
+ cairo_text_extents_t name_extents, mode_extents;
+ char name_buf[128], mode_buf[128];
+ int i, x, y, modes_x, modes_y;
+
+ /* Get text extents for each string */
+ snprintf(name_buf, sizeof name_buf, "%s",
+ connector_type_str(c->connector->connector_type));
+ cairo_set_font_size(cr, 48);
+ cairo_select_font_face(cr, "Helvetica",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_text_extents(cr, name_buf, &name_extents);
+
+ snprintf(mode_buf, sizeof mode_buf, "%s @ %dHz on %s encoder",
+ c->mode.name, c->mode.vrefresh,
+ encoder_type_str(c->encoder->encoder_type));
+ cairo_set_font_size(cr, 36);
+ cairo_text_extents(cr, mode_buf, &mode_extents);
+
+ /* Paint output name */
+ x = l_width / 2;
+ x -= name_extents.width / 2;
+ y = l_height / 2;
+ y -= (name_extents.height / 2) - (mode_extents.height / 2) - 10;
+ cairo_set_font_size(cr, 48);
+ cairo_move_to(cr, x, y);
+ cairo_text_path(cr, name_buf);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_stroke_preserve(cr);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+
+ /* Paint mode name */
+ x = l_width / 2;
+ x -= mode_extents.width / 2;
+ modes_x = x;
+ y = l_height / 2;
+ y += (mode_extents.height / 2) + (name_extents.height / 2) + 10;
+ cairo_set_font_size(cr, 36);
+ cairo_move_to(cr, x, y);
+ cairo_text_path(cr, mode_buf);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_stroke_preserve(cr);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+
+ /* List available modes */
+ snprintf(mode_buf, sizeof mode_buf, "Available modes:");
+ cairo_set_font_size(cr, 18);
+ cairo_text_extents(cr, mode_buf, &mode_extents);
+ x = modes_x;
+ modes_x = x + mode_extents.width;
+ y += mode_extents.height + 10;
+ modes_y = y;
+ cairo_move_to(cr, x, y);
+ cairo_text_path(cr, mode_buf);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_stroke_preserve(cr);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+
+ for (i = 0; i < c->connector->count_modes; i++) {
+ snprintf(mode_buf, sizeof mode_buf, "%s @ %dHz",
+ c->connector->modes[i].name,
+ c->connector->modes[i].vrefresh);
+ cairo_set_font_size(cr, 18);
+ cairo_text_extents(cr, mode_buf, &mode_extents);
+ x = modes_x - mode_extents.width; /* right justify modes */
+ y += mode_extents.height + 10;
+ if (y + mode_extents.height >= height) {
+ y = modes_y + mode_extents.height + 10;
+ modes_x += mode_extents.width + 10;
+ x = modes_x - mode_extents.width;
+ }
+ cairo_move_to(cr, x, y);
+ cairo_text_path(cr, mode_buf);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_stroke_preserve(cr);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+ }
+
+ if (qr_code)
+ paint_image(cr, "./pass.png");
+}
+
+static void sighandler(int signo)
+{
+ return;
+}
+
+static void set_single(void)
+{
+ int sigs[] = { SIGUSR1 };
+ struct sigaction sa;
+ sa.sa_handler = sighandler;
+
+ sigemptyset(&sa.sa_mask);
+
+ if (sigaction(sigs[0], &sa, NULL) == -1)
+ perror("Could not set signal handler");
+}
+
+static void
+set_mode(struct connector *c)
+{
+ unsigned int fb_id = 0;
+ int j, test_mode_num;
+
+ if (depth <= 8)
+ bpp = 8;
+ else if (depth > 8 && depth <= 16)
+ bpp = 16;
+ else if (depth > 16 && depth <= 32)
+ bpp = 32;
+
+ connector_find_preferred_mode(c);
+ if (!c->mode_valid)
+ return;
+
+ test_mode_num = 1;
+ if (force_mode){
+ memcpy( &c->mode, &force_timing, sizeof(force_timing));
+ c->mode.vrefresh =(force_timing.clock*1e3)/(force_timing.htotal*force_timing.vtotal);
+ c->mode_valid = 1;
+ sprintf(c->mode.name, "%dx%d", force_timing.hdisplay, force_timing.vdisplay);
+ } else if (test_all_modes)
+ test_mode_num = c->connector->count_modes;
+
+ for (j = 0; j < test_mode_num; j++) {
+ struct kmstest_fb fb_info;
+
+ if (test_all_modes)
+ c->mode = c->connector->modes[j];
+
+ if (!c->mode_valid)
+ continue;
+
+ width = c->mode.hdisplay;
+ height = c->mode.vdisplay;
+
+ fb_id = kmstest_create_fb(drm_fd, width, height, bpp, depth,
+ enable_tiling, &fb_info,
+ paint_output_info, c);
+
+ fb_ptr = gem_mmap(drm_fd, fb_info.gem_handle,
+ fb_info.size, PROT_READ | PROT_WRITE);
+ assert(fb_ptr);
+ paint_color_key();
+
+ gem_close(drm_fd, fb_info.gem_handle);
+
+ fprintf(stdout, "CRTS(%u):",c->crtc);
+ kmstest_dump_mode(&c->mode);
+ if (drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0,
+ &c->id, 1, &c->mode)) {
+ fprintf(stderr, "failed to set mode (%dx%d@%dHz): %s\n",
+ width, height, c->mode.vrefresh,
+ strerror(errno));
+ continue;
+ }
+
+ if (sleep_between_modes && test_all_modes && !qr_code)
+ sleep(sleep_between_modes);
+
+ if (qr_code){
+ set_single();
+ pause();
+ }
+
+ }
+
+ if(test_all_modes){
+ drmModeRmFB(drm_fd,fb_id);
+ drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0, &c->id, 1, 0);
+ }
+
+ drmModeFreeEncoder(c->encoder);
+ drmModeFreeConnector(c->connector);
+}
+
+/*
+ * Re-probe outputs and light up as many as possible.
+ *
+ * On Intel, we have two CRTCs that we can drive independently with
+ * different timings and scanout buffers.
+ *
+ * Each connector has a corresponding encoder, except in the SDVO case
+ * where an encoder may have multiple connectors.
+ */
+int update_display(void)
+{
+ struct connector *connectors;
+ int c;
+
+ resources = drmModeGetResources(drm_fd);
+ if (!resources) {
+ fprintf(stderr, "drmModeGetResources failed: %s\n",
+ strerror(errno));
+ return 0;
+ }
+
+ connectors = calloc(resources->count_connectors,
+ sizeof(struct connector));
+ if (!connectors)
+ return 0;
+
+ if (dump_info) {
+ dump_connectors_fd(drm_fd);
+ dump_crtcs_fd(drm_fd);
+ }
+
+ if (test_preferred_mode || test_all_modes || force_mode) {
+ /* Find any connected displays */
+ for (c = 0; c < resources->count_connectors; c++) {
+ connectors[c].id = resources->connectors[c];
+ set_mode(&connectors[c]);
+ }
+ }
+ drmModeFreeResources(resources);
+ return 1;
+}
+
+static char optstr[] = "hiaf:s:d:p:mrt";
+
+static void usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-hiasdpmtf]\n", name);
+ fprintf(stderr, "\t-i\tdump info\n");
+ fprintf(stderr, "\t-a\ttest all modes\n");
+ fprintf(stderr, "\t-s\t<duration>\tsleep between each mode test\n");
+ fprintf(stderr, "\t-d\t<depth>\tbit depth of scanout buffer\n");
+ fprintf(stderr, "\t-p\t<planew,h>,<crtcx,y>,<crtcw,h> test overlay plane\n");
+ fprintf(stderr, "\t-m\ttest the preferred mode\n");
+ fprintf(stderr, "\t-t\tuse a tiled framebuffer\n");
+ fprintf(stderr, "\t-r\tprint a QR code on the screen whose content is \"pass\" for the automatic test\n");
+ fprintf(stderr, "\t-f\t<clock MHz>,<hdisp>,<hsync-start>,<hsync-end>,<htotal>,\n");
+ fprintf(stderr, "\t\t<vdisp>,<vsync-start>,<vsync-end>,<vtotal>\n");
+ fprintf(stderr, "\t\ttest force mode\n");
+ fprintf(stderr, "\tDefault is to test all modes.\n");
+ exit(0);
+}
+
+#define dump_resource(res) if (res) dump_##res()
+
+static gboolean input_event(GIOChannel *source, GIOCondition condition,
+ gpointer data)
+{
+ gchar buf[2];
+ gsize count;
+
+ count = read(g_io_channel_unix_get_fd(source), buf, sizeof(buf));
+ if (buf[0] == 'q' && (count == 1 || buf[1] == '\n')) {
+ exit(0);
+ }
+
+ return TRUE;
+}
+
+static void enter_exec_path( char **argv )
+{
+ char *exec_path = NULL;
+ char *pos = NULL;
+ short len_path = 0;
+
+ len_path = strlen( argv[0] );
+ exec_path = (char*) malloc(len_path);
+
+ memcpy(exec_path, argv[0], len_path);
+ pos = strrchr(exec_path, '/');
+ if (pos != NULL)
+ *(pos+1) = '\0';
+
+ chdir(exec_path);
+ free(exec_path);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ int ret = 0;
+ GIOChannel *stdinchannel;
+ GMainLoop *mainloop;
+ float force_clock;
+
+ enter_exec_path( argv );
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ switch (c) {
+ case 'i':
+ dump_info = 1;
+ break;
+ case 'a':
+ test_all_modes = 1;
+ break;
+ case 'f':
+ force_mode = 1;
+ if(sscanf(optarg,"%f,%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu",
+ &force_clock,&force_timing.hdisplay, &force_timing.hsync_start,&force_timing.hsync_end,&force_timing.htotal,
+ &force_timing.vdisplay, &force_timing.vsync_start, &force_timing.vsync_end, &force_timing.vtotal)!= 9)
+ usage(argv[0]);
+ force_timing.clock = force_clock*1000;
+
+ break;
+ case 's':
+ sleep_between_modes = atoi(optarg);
+ break;
+ case 'd':
+ depth = atoi(optarg);
+ fprintf(stderr, "using depth %d\n", depth);
+ break;
+ case 'p':
+ if (sscanf(optarg, "%d,%d,%d,%d,%d,%d", &plane_width,
+ &plane_height, &crtc_x, &crtc_y,
+ &crtc_w, &crtc_h) != 6)
+ usage(argv[0]);
+ test_plane = 1;
+ break;
+ case 'm':
+ test_preferred_mode = 1;
+ break;
+ case 't':
+ enable_tiling = 1;
+ break;
+ case 'r':
+ qr_code = 1;
+ break;
+ default:
+ fprintf(stderr, "unknown option %c\n", c);
+ /* fall through */
+ case 'h':
+ usage(argv[0]);
+ break;
+ }
+ }
+ if (!test_all_modes && !force_mode && !dump_info &&
+ !test_preferred_mode)
+ test_all_modes = 1;
+
+ drm_fd = drm_open_any();
+
+ mainloop = g_main_loop_new(NULL, FALSE);
+ if (!mainloop) {
+ fprintf(stderr, "failed to create glib mainloop\n");
+ ret = -1;
+ goto out_close;
+ }
+
+ if (!testdisplay_setup_hotplug()) {
+ fprintf(stderr, "failed to initialize hotplug support\n");
+ goto out_mainloop;
+ }
+
+ stdinchannel = g_io_channel_unix_new(0);
+ if (!stdinchannel) {
+ fprintf(stderr, "failed to create stdin GIO channel\n");
+ goto out_hotplug;
+ }
+
+ ret = g_io_add_watch(stdinchannel, G_IO_IN | G_IO_ERR, input_event,
+ NULL);
+ if (ret < 0) {
+ fprintf(stderr, "failed to add watch on stdin GIO channel\n");
+ goto out_stdio;
+ }
+
+ ret = 0;
+
+ if (!update_display()) {
+ ret = 1;
+ goto out_stdio;
+ }
+
+ if (dump_info || test_all_modes)
+ goto out_stdio;
+
+ g_main_loop_run(mainloop);
+
+out_stdio:
+ g_io_channel_shutdown(stdinchannel, TRUE, NULL);
+out_hotplug:
+ testdisplay_cleanup_hotplug();
+out_mainloop:
+ g_main_loop_unref(mainloop);
+out_close:
+ close(drm_fd);
+
+ return ret;
+}
diff --git a/tests/testdisplay.h b/tests/testdisplay.h
new file mode 100644
index 00000000..962e6219
--- /dev/null
+++ b/tests/testdisplay.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+
+extern int drm_fd;
+
+gboolean testdisplay_setup_hotplug(void);
+void testdisplay_cleanup_hotplug(void);
+
+/* called by the hotplug code */
+int update_display(void);
diff --git a/tests/testdisplay_hotplug.c b/tests/testdisplay_hotplug.c
new file mode 100644
index 00000000..3f80dc73
--- /dev/null
+++ b/tests/testdisplay_hotplug.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2010 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "testdisplay.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_UDEV
+#include <libudev.h>
+static struct udev_monitor *uevent_monitor;
+static struct udev *udev;
+static GIOChannel *udevchannel;
+
+static gboolean hotplug_event(GIOChannel *source, GIOCondition condition,
+ gpointer data)
+{
+ struct udev_device *dev;
+ dev_t udev_devnum;
+ struct stat s;
+ const char *hotplug;
+
+ dev = udev_monitor_receive_device(uevent_monitor);
+ if (!dev)
+ goto out;
+
+ udev_devnum = udev_device_get_devnum(dev);
+ fstat(drm_fd, &s);
+
+ hotplug = udev_device_get_property_value(dev, "HOTPLUG");
+
+ if (memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
+ hotplug && atoi(hotplug) == 1)
+ update_display();
+
+ udev_device_unref(dev);
+out:
+ return TRUE;
+}
+
+
+gboolean testdisplay_setup_hotplug(void)
+{
+ int ret;
+
+ udev = udev_new();
+ if (!udev) {
+ fprintf(stderr, "failed to create udev object\n");
+ goto out;
+ }
+
+ uevent_monitor = udev_monitor_new_from_netlink(udev, "udev");
+ if (!uevent_monitor) {
+ fprintf(stderr, "failed to create udev event monitor\n");
+ goto out;
+ }
+
+ ret = udev_monitor_filter_add_match_subsystem_devtype(uevent_monitor,
+ "drm",
+ "drm_minor");
+ if (ret < 0) {
+ fprintf(stderr, "failed to filter for drm events\n");
+ goto out;
+ }
+
+ ret = udev_monitor_enable_receiving(uevent_monitor);
+ if (ret < 0) {
+ fprintf(stderr, "failed to enable udev event reception\n");
+ goto out;
+ }
+
+ udevchannel =
+ g_io_channel_unix_new(udev_monitor_get_fd(uevent_monitor));
+ if (!udevchannel) {
+ fprintf(stderr, "failed to create udev GIO channel\n");
+ goto out;
+ }
+
+ ret = g_io_add_watch(udevchannel, G_IO_IN | G_IO_ERR, hotplug_event,
+ udev);
+ if (ret < 0) {
+ fprintf(stderr, "failed to add watch on udev GIO channel\n");
+ goto out;
+ }
+
+ return TRUE;
+
+out:
+ testdisplay_cleanup_hotplug();
+ return FALSE;
+}
+
+void testdisplay_cleanup_hotplug(void)
+{
+ if (udevchannel)
+ g_io_channel_shutdown(udevchannel, TRUE, NULL);
+ if (uevent_monitor)
+ udev_monitor_unref(uevent_monitor);
+ if (udev)
+ udev_unref(udev);
+}
+#else
+gboolean testdisplay_setup_hotplug(void)
+{
+ fprintf(stderr, "no hotplug support on this platform\n");
+ return TRUE;
+}
+
+void testdisplay_cleanup_hotplug(void)
+{
+}
+#endif
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644
index 00000000..c15e3c36
--- /dev/null
+++ b/tools/.gitignore
@@ -0,0 +1,24 @@
+forcewaked
+intel_audio_dump
+intel_backlight
+intel_bios_dumper
+intel_bios_reader
+intel_disable_clock_gating
+intel_dump_decode
+intel_error_decode
+intel_forcewaked
+intel_gpu_dump
+intel_gpu_time
+intel_gpu_top
+intel_gtt
+intel_infoframes
+intel_l3_parity
+intel_lid
+intel_panel_fitter
+intel_reg_checker
+intel_reg_dumper
+intel_reg_read
+intel_reg_snapshot
+intel_reg_write
+intel_stepping
+# Please keep sorted alphabetically
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 00000000..71fb087f
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,42 @@
+bin_PROGRAMS = \
+ intel_disable_clock_gating \
+ intel_audio_dump \
+ intel_backlight \
+ intel_bios_dumper \
+ intel_bios_reader \
+ intel_error_decode \
+ intel_gpu_top \
+ intel_gpu_time \
+ intel_gtt \
+ intel_stepping \
+ intel_reg_checker \
+ intel_reg_dumper \
+ intel_reg_snapshot \
+ intel_reg_write \
+ intel_reg_read \
+ intel_forcewaked \
+ intel_dpio_read \
+ intel_dpio_write \
+ intel_l3_parity
+
+noinst_PROGRAMS = \
+ intel_dump_decode \
+ intel_infoframes \
+ intel_lid \
+ intel_panel_fitter
+
+dist_bin_SCRIPTS = intel_gpu_abrt
+
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib
+AM_CFLAGS = $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) $(CAIRO_CFLAGS)
+LDADD = $(top_builddir)/lib/libintel_tools.la $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS)
+
+intel_dump_decode_SOURCES = \
+ intel_dump_decode.c
+
+intel_error_decode_SOURCES = \
+ intel_error_decode.c
+
+intel_bios_reader_SOURCES = \
+ intel_bios_reader.c \
+ intel_bios.h
diff --git a/tools/intel_audio_dump.c b/tools/intel_audio_dump.c
new file mode 100644
index 00000000..8b9da303
--- /dev/null
+++ b/tools/intel_audio_dump.c
@@ -0,0 +1,1969 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Zhenyu Wang <zhenyu.z.wang@intel.com>
+ * Wu Fengguang <fengguang.wu@intel.com>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <arpa/inet.h>
+#include "intel_gpu_tools.h"
+
+static uint32_t devid;
+
+
+#define BITSTO(n) (n >= sizeof(long) * 8 ? ~0 : (1UL << (n)) - 1)
+#define BITMASK(high, low) (BITSTO(high+1) & ~BITSTO(low))
+#define BITS(reg, high, low) (((reg) & (BITMASK(high, low))) >> (low))
+#define BIT(reg, n) BITS(reg, n, n)
+
+#define min_t(type, x, y) ({ \
+ type __min1 = (x); \
+ type __min2 = (y); \
+ __min1 < __min2 ? __min1: __min2; })
+
+#define OPNAME(names, index) \
+ names[min_t(unsigned int, index, ARRAY_SIZE(names) - 1)]
+
+#define dump_reg(reg, desc) \
+ do { \
+ dword = INREG(reg); \
+ printf("%-21s 0x%08x %s\n", # reg, dword, desc); \
+ } while (0)
+
+
+static const char *pixel_clock[] = {
+ [0] = "25.2 / 1.001 MHz",
+ [1] = "25.2 MHz",
+ [2] = "27 MHz",
+ [3] = "27 * 1.001 MHz",
+ [4] = "54 MHz",
+ [5] = "54 * 1.001 MHz",
+ [6] = "74.25 / 1.001 MHz",
+ [7] = "74.25 MHz",
+ [8] = "148.5 / 1.001 MHz",
+ [9] = "148.5 MHz",
+ [10] = "Reserved",
+};
+
+static const char *power_state[] = {
+ [0] = "D0",
+ [1] = "D1",
+ [2] = "D2",
+ [3] = "D3",
+};
+
+static const char *stream_type[] = {
+ [0] = "default samples",
+ [1] = "one bit stream",
+ [2] = "DST stream",
+ [3] = "MLP stream",
+ [4] = "Reserved",
+};
+
+static const char *dip_port[] = {
+ [0] = "Reserved",
+ [1] = "Digital Port B",
+ [2] = "Digital Port C",
+ [3] = "Digital Port D",
+};
+
+static const char *dip_type[] = {
+ [0] = "Audio DIP Disabled",
+ [1] = "Audio DIP Enabled",
+};
+
+static const char *dip_index[] = {
+ [0] = "Audio DIP",
+ [1] = "ACP DIP",
+ [2] = "ISRC1 DIP",
+ [3] = "ISRC2 DIP",
+ [4] = "Reserved",
+};
+
+static const char *dip_trans[] = {
+ [0] = "disabled",
+ [1] = "reserved",
+ [2] = "send once",
+ [3] = "best effort",
+};
+
+static const char *video_dip_index[] = {
+ [0] = "AVI DIP",
+ [1] = "Vendor-specific DIP",
+ [2] = "Gamut Metadata DIP",
+ [3] = "Source Product Description DIP",
+};
+
+static const char *video_dip_trans[] = {
+ [0] = "send once",
+ [1] = "send every vsync",
+ [2] = "send at least every other vsync",
+ [3] = "reserved",
+};
+
+static const char *trans_to_port_sel[] = {
+ [0] = "no port",
+ [1] = "Digital Port B",
+ [2] = "Digital Port C",
+ [3] = "Digital Port D",
+ [4] = "reserved",
+ [5] = "reserved",
+ [6] = "reserved",
+ [7] = "reserved",
+};
+
+static const char *ddi_mode[] = {
+ [0] = "HDMI mode",
+ [1] = "DVI mode",
+ [2] = "DP SST mode",
+ [3] = "DP MST mode",
+ [4] = "DP FDI mode",
+ [5] = "reserved",
+ [6] = "reserved",
+ [7] = "reserved",
+};
+
+static const char *transcoder_select[] = {
+ [0] = "Transcoder A",
+ [1] = "Transcoder B",
+ [2] = "Transcoder C",
+ [3] = "reserved",
+};
+
+static const char *dp_port_width[] = {
+ [0] = "x1 mode",
+ [1] = "x2 mode",
+ [2] = "reserved",
+ [3] = "x4 mode",
+ [4] = "reserved",
+ [5] = "reserved",
+ [6] = "reserved",
+ [7] = "reserved",
+};
+
+static const char *bits_per_sample[] = {
+ [0] = "reserved",
+ [1] = "16 bits",
+ [2] = "24 bits",
+ [3] = "32 bits",
+ [4] = "20 bits",
+ [5] = "reserved",
+};
+
+static const char *sdvo_hdmi_encoding[] = {
+ [0] = "SDVO",
+ [1] = "reserved",
+ [2] = "TMDS",
+ [3] = "reserved",
+};
+
+static const char *n_index_value[] = {
+ [0] = "HDMI",
+ [1] = "DisplayPort",
+};
+
+static void do_self_tests(void)
+{
+ if (BIT(1, 0) != 1)
+ exit(1);
+ if (BIT(0x80000000, 31) != 1)
+ exit(2);
+ if (BITS(0xc0000000, 31, 30) != 3)
+ exit(3);
+}
+
+/*
+ * EagleLake registers
+ */
+#define AUD_CONFIG 0x62000
+#define AUD_DEBUG 0x62010
+#define AUD_VID_DID 0x62020
+#define AUD_RID 0x62024
+#define AUD_SUBN_CNT 0x62028
+#define AUD_FUNC_GRP 0x62040
+#define AUD_SUBN_CNT2 0x62044
+#define AUD_GRP_CAP 0x62048
+#define AUD_PWRST 0x6204c
+#define AUD_SUPPWR 0x62050
+#define AUD_SID 0x62054
+#define AUD_OUT_CWCAP 0x62070
+#define AUD_OUT_PCMSIZE 0x62074
+#define AUD_OUT_STR 0x62078
+#define AUD_OUT_DIG_CNVT 0x6207c
+#define AUD_OUT_CH_STR 0x62080
+#define AUD_OUT_STR_DESC 0x62084
+#define AUD_PINW_CAP 0x620a0
+#define AUD_PIN_CAP 0x620a4
+#define AUD_PINW_CONNLNG 0x620a8
+#define AUD_PINW_CONNLST 0x620ac
+#define AUD_PINW_CNTR 0x620b0
+#define AUD_PINW_UNSOLRESP 0x620b8
+#define AUD_CNTL_ST 0x620b4
+#define AUD_PINW_CONFIG 0x620bc
+#define AUD_HDMIW_STATUS 0x620d4
+#define AUD_HDMIW_HDMIEDID 0x6210c
+#define AUD_HDMIW_INFOFR 0x62118
+#define AUD_CONV_CHCNT 0x62120
+#define AUD_CTS_ENABLE 0x62128
+
+#define VIDEO_DIP_CTL 0x61170
+#define VIDEO_DIP_ENABLE (1<<31)
+#define VIDEO_DIP_ENABLE_AVI (1<<21)
+#define VIDEO_DIP_ENABLE_VENDOR (1<<22)
+#define VIDEO_DIP_ENABLE_SPD (1<<24)
+#define VIDEO_DIP_BUF_AVI (0<<19)
+#define VIDEO_DIP_BUF_VENDOR (1<<19)
+#define VIDEO_DIP_BUF_SPD (3<<19)
+#define VIDEO_DIP_TRANS_ONCE (0<<16)
+#define VIDEO_DIP_TRANS_1 (1<<16)
+#define VIDEO_DIP_TRANS_2 (2<<16)
+
+#define AUDIO_HOTPLUG_EN (1<<24)
+
+
+static void dump_eaglelake(void)
+{
+ uint32_t dword;
+ int i;
+
+ /* printf("%-18s %8s %s\n\n", "register name", "raw value", "description"); */
+
+ dump_reg(VIDEO_DIP_CTL, "Video DIP Control");
+ dump_reg(SDVOB, "Digital Display Port B Control Register");
+ dump_reg(SDVOC, "Digital Display Port C Control Register");
+ dump_reg(PORT_HOTPLUG_EN, "Hot Plug Detect Enable");
+
+ dump_reg(AUD_CONFIG, "Audio Configuration");
+ dump_reg(AUD_DEBUG, "Audio Debug");
+ dump_reg(AUD_VID_DID, "Audio Vendor ID / Device ID");
+ dump_reg(AUD_RID, "Audio Revision ID");
+ dump_reg(AUD_SUBN_CNT, "Audio Subordinate Node Count");
+ dump_reg(AUD_FUNC_GRP, "Audio Function Group Type");
+ dump_reg(AUD_SUBN_CNT2, "Audio Subordinate Node Count");
+ dump_reg(AUD_GRP_CAP, "Audio Function Group Capabilities");
+ dump_reg(AUD_PWRST, "Audio Power State");
+ dump_reg(AUD_SUPPWR, "Audio Supported Power States");
+ dump_reg(AUD_SID, "Audio Root Node Subsystem ID");
+ dump_reg(AUD_OUT_CWCAP, "Audio Output Converter Widget Capabilities");
+ dump_reg(AUD_OUT_PCMSIZE, "Audio PCM Size and Rates");
+ dump_reg(AUD_OUT_STR, "Audio Stream Formats");
+ dump_reg(AUD_OUT_DIG_CNVT, "Audio Digital Converter");
+ dump_reg(AUD_OUT_CH_STR, "Audio Channel ID and Stream ID");
+ dump_reg(AUD_OUT_STR_DESC, "Audio Stream Descriptor Format");
+ dump_reg(AUD_PINW_CAP, "Audio Pin Complex Widget Capabilities");
+ dump_reg(AUD_PIN_CAP, "Audio Pin Capabilities");
+ dump_reg(AUD_PINW_CONNLNG, "Audio Connection List Length");
+ dump_reg(AUD_PINW_CONNLST, "Audio Connection List Entry");
+ dump_reg(AUD_PINW_CNTR, "Audio Pin Widget Control");
+ dump_reg(AUD_PINW_UNSOLRESP,"Audio Unsolicited Response Enable");
+ dump_reg(AUD_CNTL_ST, "Audio Control State Register");
+ dump_reg(AUD_PINW_CONFIG, "Audio Configuration Default");
+ dump_reg(AUD_HDMIW_STATUS, "Audio HDMI Status");
+ dump_reg(AUD_HDMIW_HDMIEDID,"Audio HDMI Data EDID Block");
+ dump_reg(AUD_HDMIW_INFOFR, "Audio HDMI Widget Data Island Packet");
+ dump_reg(AUD_CONV_CHCNT, "Audio Converter Channel Count");
+ dump_reg(AUD_CTS_ENABLE, "Audio CTS Programming Enable");
+
+ printf("\nDetails:\n\n");
+
+ dword = INREG(AUD_VID_DID);
+ printf("AUD_VID_DID vendor id\t\t\t0x%x\n", dword >> 16);
+ printf("AUD_VID_DID device id\t\t\t0x%x\n", dword & 0xffff);
+
+ dword = INREG(AUD_RID);
+ printf("AUD_RID major revision\t\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_RID minor revision\t\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_RID revision id\t\t\t0x%lx\n", BITS(dword, 15, 8));
+ printf("AUD_RID stepping id\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(SDVOB);
+ printf("SDVOB enable\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("SDVOB HDMI encoding\t\t\t%u\n", !!(dword & SDVO_ENCODING_HDMI));
+ printf("SDVOB SDVO encoding\t\t\t%u\n", !!(dword & SDVO_ENCODING_SDVO));
+ printf("SDVOB null packets\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("SDVOB audio enabled\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(SDVOC);
+ printf("SDVOC enable\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("SDVOC HDMI encoding\t\t\t%u\n", !!(dword & SDVO_ENCODING_HDMI));
+ printf("SDVOC SDVO encoding\t\t\t%u\n", !!(dword & SDVO_ENCODING_SDVO));
+ printf("SDVOC null packets\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("SDVOC audio enabled\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(PORT_HOTPLUG_EN);
+ printf("PORT_HOTPLUG_EN DisplayPort/HDMI port B\t%ld\n", BIT(dword, 29)),
+ printf("PORT_HOTPLUG_EN DisplayPort/HDMI port C\t%ld\n", BIT(dword, 28)),
+ printf("PORT_HOTPLUG_EN DisplayPort port D\t%ld\n", BIT(dword, 27)),
+ printf("PORT_HOTPLUG_EN SDVOB\t\t\t%ld\n", BIT(dword, 26)),
+ printf("PORT_HOTPLUG_EN SDVOC\t\t\t%ld\n", BIT(dword, 25)),
+ printf("PORT_HOTPLUG_EN audio\t\t\t%ld\n", BIT(dword, 24)),
+ printf("PORT_HOTPLUG_EN TV\t\t\t%ld\n", BIT(dword, 23)),
+ printf("PORT_HOTPLUG_EN CRT\t\t\t%ld\n", BIT(dword, 9)),
+
+ dword = INREG(VIDEO_DIP_CTL);
+ printf("VIDEO_DIP_CTL enable graphics DIP\t%ld\n", BIT(dword, 31)),
+ printf("VIDEO_DIP_CTL port select\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("VIDEO_DIP_CTL DIP buffer trans active\t%lu\n", BIT(dword, 28));
+ printf("VIDEO_DIP_CTL AVI DIP enabled\t\t%lu\n", BIT(dword, 21));
+ printf("VIDEO_DIP_CTL vendor DIP enabled\t%lu\n", BIT(dword, 22));
+ printf("VIDEO_DIP_CTL SPD DIP enabled\t\t%lu\n", BIT(dword, 24));
+ printf("VIDEO_DIP_CTL DIP buffer index\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 19), video_dip_index[BITS(dword, 20, 19)]);
+ printf("VIDEO_DIP_CTL DIP trans freq\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), video_dip_trans[BITS(dword, 17, 16)]);
+ printf("VIDEO_DIP_CTL DIP buffer size\t\t%lu\n", BITS(dword, 11, 8));
+ printf("VIDEO_DIP_CTL DIP address\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(AUD_CONFIG);
+ printf("AUD_CONFIG pixel clock\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG fabrication enabled\t\t%lu\n", BITS(dword, 2, 2));
+ printf("AUD_CONFIG professional use allowed\t%lu\n", BIT(dword, 1));
+ printf("AUD_CONFIG fuse enabled\t\t\t%lu\n", BIT(dword, 0));
+
+ dword = INREG(AUD_DEBUG);
+ printf("AUD_DEBUG function reset\t\t%lu\n", BIT(dword, 0));
+
+ dword = INREG(AUD_SUBN_CNT);
+ printf("AUD_SUBN_CNT starting node number\t0x%lx\n", BITS(dword, 23, 16));
+ printf("AUD_SUBN_CNT total number of nodes\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(AUD_SUBN_CNT2);
+ printf("AUD_SUBN_CNT2 starting node number\t0x%lx\n", BITS(dword, 24, 16));
+ printf("AUD_SUBN_CNT2 total number of nodes\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(AUD_FUNC_GRP);
+ printf("AUD_FUNC_GRP unsol capable\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_FUNC_GRP node type\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(AUD_GRP_CAP);
+ printf("AUD_GRP_CAP beep 0\t\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_GRP_CAP input delay\t\t\t%lu\n", BITS(dword, 11, 8));
+ printf("AUD_GRP_CAP output delay\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(AUD_PWRST);
+ printf("AUD_PWRST device power state\t\t%s\n",
+ power_state[BITS(dword, 5, 4)]);
+ printf("AUD_PWRST device power state setting\t%s\n",
+ power_state[BITS(dword, 1, 0)]);
+
+ dword = INREG(AUD_SUPPWR);
+ printf("AUD_SUPPWR support D0\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_SUPPWR support D1\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_SUPPWR support D2\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_SUPPWR support D3\t\t\t%lu\n", BIT(dword, 3));
+
+ dword = INREG(AUD_OUT_CWCAP);
+ printf("AUD_OUT_CWCAP widget type\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_OUT_CWCAP sample delay\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_OUT_CWCAP channel count\t\t%lu\n",
+ BITS(dword, 15, 13) * 2 + BIT(dword, 0) + 1);
+ printf("AUD_OUT_CWCAP L-R swap\t\t\t%lu\n", BIT(dword, 11));
+ printf("AUD_OUT_CWCAP power control\t\t%lu\n", BIT(dword, 10));
+ printf("AUD_OUT_CWCAP digital\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_OUT_CWCAP conn list\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_OUT_CWCAP unsol\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_CWCAP mute\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_CWCAP format override\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_CWCAP amp param override\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_CWCAP out amp present\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_CWCAP in amp present\t\t%lu\n", BIT(dword, 1));
+
+ dword = INREG(AUD_OUT_DIG_CNVT);
+ printf("AUD_OUT_DIG_CNVT SPDIF category\t\t0x%lx\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT SPDIF level\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT professional\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT non PCM\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT copyright asserted\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT filter preemphasis\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT validity config\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT validity flag\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT digital enable\t\t%lu\n", BIT(dword, 0));
+
+ dword = INREG(AUD_OUT_CH_STR);
+ printf("AUD_OUT_CH_STR stream id\t\t0x%lx\n", BITS(dword, 7, 4));
+ printf("AUD_OUT_CH_STR lowest channel\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC);
+ printf("AUD_OUT_STR_DESC stream channels\t%lu\n", BITS(dword, 3, 0) + 1);
+ printf("AUD_OUT_STR_DESC Bits per Sample\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+
+ dword = INREG(AUD_PINW_CAP);
+ printf("AUD_PINW_CAP widget type\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_PINW_CAP sample delay\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_PINW_CAP channel count\t\t%lu\n",
+ BITS(dword, 15, 13) * 2 + BIT(dword, 0) + 1);
+ printf("AUD_PINW_CAP HDCP\t\t\t%lu\n", BIT(dword, 12));
+ printf("AUD_PINW_CAP L-R swap\t\t\t%lu\n", BIT(dword, 11));
+ printf("AUD_PINW_CAP power control\t\t%lu\n", BIT(dword, 10));
+ printf("AUD_PINW_CAP digital\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_PINW_CAP conn list\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_PINW_CAP unsol\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_PINW_CAP mute\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_PINW_CAP format override\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_PINW_CAP amp param override\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_PINW_CAP out amp present\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_PINW_CAP in amp present\t\t%lu\n", BIT(dword, 1));
+
+
+ dword = INREG(AUD_PIN_CAP);
+ printf("AUD_PIN_CAP EAPD\t\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_PIN_CAP HDMI\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_PIN_CAP output\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_PIN_CAP presence detect\t\t%lu\n", BIT(dword, 2));
+
+ dword = INREG(AUD_PINW_CNTR);
+ printf("AUD_PINW_CNTR mute status\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_PINW_CNTR out enable\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_PINW_CNTR amp mute status\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_PINW_CNTR amp mute status\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_PINW_CNTR stream type\t\t[0x%lx] %s\n",
+ BITS(dword, 2, 0),
+ OPNAME(stream_type, BITS(dword, 2, 0)));
+
+ dword = INREG(AUD_PINW_UNSOLRESP);
+ printf("AUD_PINW_UNSOLRESP enable unsol resp\t%lu\n", BIT(dword, 31));
+
+ dword = INREG(AUD_CNTL_ST);
+ printf("AUD_CNTL_ST DIP audio enabled\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST DIP ACP enabled\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST DIP ISRCx enabled\t\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST DIP port select\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST DIP buffer index\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 18), OPNAME(dip_index, BITS(dword, 20, 18)));
+ printf("AUD_CNTL_ST DIP trans freq\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST DIP address\t\t\t%lu\n", BITS(dword, 3, 0));
+ printf("AUD_CNTL_ST CP ready\t\t\t%lu\n", BIT(dword, 15));
+ printf("AUD_CNTL_ST ELD valid\t\t\t%lu\n", BIT(dword, 14));
+ printf("AUD_CNTL_ST ELD ack\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST ELD bufsize\t\t\t%lu\n", BITS(dword, 13, 9));
+ printf("AUD_CNTL_ST ELD address\t\t\t%lu\n", BITS(dword, 8, 5));
+
+ dword = INREG(AUD_HDMIW_STATUS);
+ printf("AUD_HDMIW_STATUS CDCLK/DOTCLK underrun\t%lu\n", BIT(dword, 31));
+ printf("AUD_HDMIW_STATUS CDCLK/DOTCLK overrun\t%lu\n", BIT(dword, 30));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK underrun\t%lu\n", BIT(dword, 29));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK overrun\t%lu\n", BIT(dword, 28));
+
+ dword = INREG(AUD_CONV_CHCNT);
+ printf("AUD_CONV_CHCNT HDMI HBR enabled\t\t%lu\n", BITS(dword, 15, 14));
+ printf("AUD_CONV_CHCNT HDMI channel count\t%lu\n", BITS(dword, 11, 8) + 1);
+
+ printf("AUD_CONV_CHCNT HDMI channel mapping:\n");
+ for (i = 0; i < 8; i++) {
+ OUTREG(AUD_CONV_CHCNT, i);
+ dword = INREG(AUD_CONV_CHCNT);
+ printf("\t\t\t\t\t[0x%x] %u => %lu \n", dword, i, BITS(dword, 7, 4));
+ }
+
+ printf("AUD_HDMIW_HDMIEDID HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST);
+ dword &= ~BITMASK(8, 5);
+ OUTREG(AUD_CNTL_ST, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR)));
+ printf("\n");
+}
+
+#undef AUD_RID
+#undef AUD_VID_DID
+#undef AUD_PWRST
+#undef AUD_OUT_CH_STR
+#undef AUD_HDMIW_STATUS
+
+/*
+ * IronLake registers
+ */
+#define AUD_CONFIG_A 0xE2000
+#define AUD_CONFIG_B 0xE2100
+#define AUD_CTS_ENABLE_A 0xE2028
+#define AUD_CTS_ENABLE_B 0xE2128
+#define AUD_MISC_CTRL_A 0xE2010
+#define AUD_MISC_CTRL_B 0xE2110
+#define AUD_VID_DID 0xE2020
+#define AUD_RID 0xE2024
+#define AUD_PWRST 0xE204C
+#define AUD_PORT_EN_HD_CFG 0xE207C
+#define AUD_OUT_DIG_CNVT_A 0xE2080
+#define AUD_OUT_DIG_CNVT_B 0xE2180
+#define AUD_OUT_CH_STR 0xE2088
+#define AUD_OUT_STR_DESC_A 0xE2084
+#define AUD_OUT_STR_DESC_B 0xE2184
+#define AUD_PINW_CONNLNG_LIST 0xE20A8
+#define AUD_PINW_CONNLNG_SEL 0xE20AC
+#define AUD_CNTL_ST_A 0xE20B4
+#define AUD_CNTL_ST_B 0xE21B4
+#define AUD_CNTL_ST2 0xE20C0
+#define AUD_HDMIW_STATUS 0xE20D4
+#define AUD_HDMIW_HDMIEDID_A 0xE2050
+#define AUD_HDMIW_HDMIEDID_B 0xE2150
+#define AUD_HDMIW_INFOFR_A 0xE2054
+#define AUD_HDMIW_INFOFR_B 0xE2154
+
+static void dump_ironlake(void)
+{
+ uint32_t dword;
+ int i;
+
+ dump_reg(HDMIB, "sDVO/HDMI Port B Control");
+ dump_reg(HDMIC, "HDMI Port C Control");
+ dump_reg(HDMID, "HDMI Port D Control");
+ dump_reg(PCH_DP_B, "DisplayPort B Control Register");
+ dump_reg(PCH_DP_C, "DisplayPort C Control Register");
+ dump_reg(PCH_DP_D, "DisplayPort D Control Register");
+ dump_reg(AUD_CONFIG_A, "Audio Configuration - Transcoder A");
+ dump_reg(AUD_CONFIG_B, "Audio Configuration - Transcoder B");
+ dump_reg(AUD_CTS_ENABLE_A, "Audio CTS Programming Enable - Transcoder A");
+ dump_reg(AUD_CTS_ENABLE_B, "Audio CTS Programming Enable - Transcoder B");
+ dump_reg(AUD_MISC_CTRL_A, "Audio MISC Control for Transcoder A");
+ dump_reg(AUD_MISC_CTRL_B, "Audio MISC Control for Transcoder B");
+ dump_reg(AUD_VID_DID, "Audio Vendor ID / Device ID");
+ dump_reg(AUD_RID, "Audio Revision ID");
+ dump_reg(AUD_PWRST, "Audio Power State (Function Group, Convertor, Pin Widget)");
+ dump_reg(AUD_PORT_EN_HD_CFG, "Audio Port Enable HDAudio Config");
+ dump_reg(AUD_OUT_DIG_CNVT_A, "Audio Digital Converter - Conv A");
+ dump_reg(AUD_OUT_DIG_CNVT_B, "Audio Digital Converter - Conv B");
+ dump_reg(AUD_OUT_CH_STR, "Audio Channel ID and Stream ID");
+ dump_reg(AUD_OUT_STR_DESC_A, "Audio Stream Descriptor Format - Conv A");
+ dump_reg(AUD_OUT_STR_DESC_B, "Audio Stream Descriptor Format - Conv B");
+ dump_reg(AUD_PINW_CONNLNG_LIST, "Audio Connection List");
+ dump_reg(AUD_PINW_CONNLNG_SEL, "Audio Connection Select");
+ dump_reg(AUD_CNTL_ST_A, "Audio Control State Register - Transcoder A");
+ dump_reg(AUD_CNTL_ST_B, "Audio Control State Register - Transcoder B");
+ dump_reg(AUD_CNTL_ST2, "Audio Control State 2");
+ dump_reg(AUD_HDMIW_STATUS, "Audio HDMI Status");
+ dump_reg(AUD_HDMIW_HDMIEDID_A, "HDMI Data EDID Block - Transcoder A");
+ dump_reg(AUD_HDMIW_HDMIEDID_B, "HDMI Data EDID Block - Transcoder B");
+ dump_reg(AUD_HDMIW_INFOFR_A, "Audio Widget Data Island Packet - Transcoder A");
+ dump_reg(AUD_HDMIW_INFOFR_B, "Audio Widget Data Island Packet - Transcoder B");
+
+ printf("\nDetails:\n\n");
+
+ dword = INREG(AUD_VID_DID);
+ printf("AUD_VID_DID vendor id\t\t\t\t\t0x%x\n", dword >> 16);
+ printf("AUD_VID_DID device id\t\t\t\t\t0x%x\n", dword & 0xffff);
+
+ dword = INREG(AUD_RID);
+ printf("AUD_RID Major_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_RID Minor_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_RID Revision_Id\t\t\t\t\t0x%lx\n", BITS(dword, 15, 8));
+ printf("AUD_RID Stepping_Id\t\t\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(HDMIB);
+ printf("HDMIB HDMIB_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMIB Transcoder_Select\t\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("HDMIB HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMIB SDVOB Hot Plug Interrupt Detect Enable\t\t%lu\n", BIT(dword, 23));
+ printf("HDMIB Digital_Port_B_Detected\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMIB Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMIB Null_packets_enabled_during_Vsync\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("HDMIB Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(HDMIC);
+ printf("HDMIC HDMIC_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMIC Transcoder_Select\t\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("HDMIC HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMIC Digital_Port_C_Detected\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMIC Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMIC Null_packets_enabled_during_Vsync\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("HDMIC Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(HDMID);
+ printf("HDMID HDMID_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMID Transcoder_Select\t\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("HDMID HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMID Digital_Port_D_Detected\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMID Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMID Null_packets_enabled_during_Vsync\t\t\t%u\n", !!(dword & SDVO_NULL_PACKETS_DURING_VSYNC));
+ printf("HDMID Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(PCH_DP_B);
+ printf("PCH_DP_B DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("PCH_DP_B Transcoder_Select\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("PCH_DP_B Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("PCH_DP_B Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("PCH_DP_B HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("PCH_DP_B Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(PCH_DP_C);
+ printf("PCH_DP_C DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("PCH_DP_C Transcoder_Select\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("PCH_DP_C Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("PCH_DP_C Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("PCH_DP_C HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("PCH_DP_C Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(PCH_DP_D);
+ printf("PCH_DP_D DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("PCH_DP_D Transcoder_Select\t\t\t\t%s\n", BIT(dword, 30) ? "Transcoder B" : "Transcoder A");
+ printf("PCH_DP_D Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("PCH_DP_D Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("PCH_DP_D HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("PCH_DP_D Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(AUD_CONFIG_A);
+ printf("AUD_CONFIG_A N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_A N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_A Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_A Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_A Pixel_Clock\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_A Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_B);
+ printf("AUD_CONFIG_B N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_B N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_B Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_B Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_B Pixel_Clock\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_B Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+
+ dword = INREG(AUD_CTS_ENABLE_A);
+ printf("AUD_CTS_ENABLE_A Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_A CTS/M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_A CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_B);
+ printf("AUD_CTS_ENABLE_B Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_B CTS/M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_B CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+
+ dword = INREG(AUD_MISC_CTRL_A);
+ printf("AUD_MISC_CTRL_A Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_A Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_A Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_A Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_B);
+ printf("AUD_MISC_CTRL_B Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_B Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_B Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_B Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+
+ dword = INREG(AUD_PWRST);
+ printf("AUD_PWRST Function_Group_Device_Power_State_Current\t%s\n", power_state[BITS(dword, 23, 22)]);
+ printf("AUD_PWRST Function_Group_Device_Power_State_Set \t%s\n", power_state[BITS(dword, 21, 20)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 19, 18)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Requested \t%s\n", power_state[BITS(dword, 17, 16)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 15, 14)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Requsted \t%s\n", power_state[BITS(dword, 13, 12)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 11, 10)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 9, 8)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 7, 6)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 5, 4)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 3, 2)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 1, 0)]);
+
+ dword = INREG(AUD_PORT_EN_HD_CFG);
+ printf("AUD_PORT_EN_HD_CFG Convertor_A_Digen\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_PORT_EN_HD_CFG Convertor_B_Digen\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_PORT_EN_HD_CFG ConvertorA_Stream_ID\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_PORT_EN_HD_CFG ConvertorB_Stream_ID\t\t%lu\n", BITS(dword, 11, 8));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Out_Enable\t\t\t%lu\n", BIT(dword, 12));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Out_Enable\t\t\t%lu\n", BIT(dword, 13));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Out_Enable\t\t\t%lu\n", BIT(dword, 14));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Amp_Mute_Status\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Amp_Mute_Status\t\t%lu\n", BIT(dword, 17));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Amp_Mute_Status\t\t%lu\n", BIT(dword, 18));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_A);
+ printf("AUD_OUT_DIG_CNVT_A V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_A VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_A PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_A Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_A NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_A PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_A Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_A Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_A Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_A Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_B);
+ printf("AUD_OUT_DIG_CNVT_B V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_B VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_B PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_B Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_B NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_B PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_B Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_B Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_B Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_B Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ printf("AUD_OUT_CH_STR Converter_Channel_MAP PORTB PORTC PORTD\n");
+ for (i = 0; i < 8; i++) {
+ OUTREG(AUD_OUT_CH_STR, i | (i << 8) | (i << 16));
+ dword = INREG(AUD_OUT_CH_STR);
+ printf("\t\t\t\t%lu\t%lu\t%lu\t%lu\n",
+ 1 + BITS(dword, 3, 0),
+ 1 + BITS(dword, 7, 4),
+ 1 + BITS(dword, 15, 12),
+ 1 + BITS(dword, 23, 20));
+ }
+
+ dword = INREG(AUD_OUT_STR_DESC_A);
+ printf("AUD_OUT_STR_DESC_A HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_A Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_A Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_A Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_B);
+ printf("AUD_OUT_STR_DESC_B HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_B Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_B Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_B Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_PINW_CONNLNG_SEL);
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_B\t%lu\n", BITS(dword, 7, 0));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_C\t%lu\n", BITS(dword, 15, 8));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_D\t%lu\n", BITS(dword, 23, 16));
+
+ dword = INREG(AUD_CNTL_ST_A);
+ printf("AUD_CNTL_ST_A DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_A DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_A DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_A DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_A DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_A ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_A ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+ printf("AUD_CNTL_ST_A ELD_access_address\t\t\t%lu\n", BITS(dword, 9, 5));
+
+ dword = INREG(AUD_CNTL_ST_B);
+ printf("AUD_CNTL_ST_B DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_B DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_B DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_B DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_B DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_B ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_B ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+ printf("AUD_CNTL_ST_B ELD_access_address\t\t\t%lu\n", BITS(dword, 9, 5));
+
+ dword = INREG(AUD_CNTL_ST2);
+ printf("AUD_CNTL_ST2 CP_ReadyB\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_CNTL_ST2 ELD_validB\t\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_CNTL_ST2 CP_ReadyC\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_CNTL_ST2 ELD_validC\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST2 CP_ReadyD\t\t\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_CNTL_ST2 ELD_validD\t\t\t\t%lu\n", BIT(dword, 8));
+
+ dword = INREG(AUD_HDMIW_STATUS);
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 31));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 30));
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 29));
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 28));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK_FIFO_Overrun\t\t%lu\n", BIT(dword, 25));
+ printf("AUD_HDMIW_STATUS Function_Reset\t\t\t%lu\n", BIT(dword, 29));
+
+ printf("AUD_HDMIW_HDMIEDID_A HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_A);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_A, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_B HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_B);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_B, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_A HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_A);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_A, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_B HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_B);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_B, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_B)));
+ printf("\n");
+
+}
+
+
+#undef AUD_CONFIG_A
+#undef AUD_MISC_CTRL_A
+#undef AUD_VID_DID
+#undef AUD_RID
+#undef AUD_CTS_ENABLE_A
+#undef AUD_PWRST
+#undef AUD_HDMIW_HDMIEDID_A
+#undef AUD_HDMIW_INFOFR_A
+#undef AUD_PORT_EN_HD_CFG
+#undef AUD_OUT_DIG_CNVT_A
+#undef AUD_OUT_STR_DESC_A
+#undef AUD_OUT_CH_STR
+#undef AUD_PINW_CONNLNG_LIST
+#undef AUD_CNTL_ST_A
+#undef AUD_HDMIW_STATUS
+#undef AUD_CONFIG_B
+#undef AUD_MISC_CTRL_B
+#undef AUD_CTS_ENABLE_B
+#undef AUD_HDMIW_HDMIEDID_B
+#undef AUD_HDMIW_INFOFR_B
+#undef AUD_OUT_DIG_CNVT_B
+#undef AUD_OUT_STR_DESC_B
+#undef AUD_CNTL_ST_B
+
+/*
+ * CougarPoint registers
+ */
+#define DP_CTL_B 0xE4100
+#define DP_CTL_C 0xE4200
+#define DP_AUX_CTL_C 0xE4210
+#define DP_AUX_TST_C 0xE4228
+#define SPORT_DDI_CRC_C 0xE4250
+#define SPORT_DDI_CRC_R 0xE4264
+#define DP_CTL_D 0xE4300
+#define DP_AUX_CTL_D 0xE4310
+#define DP_AUX_TST_D 0xE4328
+#define SPORT_DDI_CRC_CTL_D 0xE4350
+#define AUD_CONFIG_A 0xE5000
+#define AUD_MISC_CTRL_A 0xE5010
+#define AUD_VID_DID 0xE5020
+#define AUD_RID 0xE5024
+#define AUD_CTS_ENABLE_A 0xE5028
+#define AUD_PWRST 0xE504C
+#define AUD_HDMIW_HDMIEDID_A 0xE5050
+#define AUD_HDMIW_INFOFR_A 0xE5054
+#define AUD_PORT_EN_HD_CFG 0xE507C
+#define AUD_OUT_DIG_CNVT_A 0xE5080
+#define AUD_OUT_STR_DESC_A 0xE5084
+#define AUD_OUT_CH_STR 0xE5088
+#define AUD_PINW_CONNLNG_LIST 0xE50A8
+#define AUD_PINW_CONNLNG_SELA 0xE50AC
+#define AUD_CNTL_ST_A 0xE50B4
+#define AUD_CNTRL_ST2 0xE50C0
+#define AUD_CNTRL_ST3 0xE50C4
+#define AUD_HDMIW_STATUS 0xE50D4
+#define AUD_CONFIG_B 0xE5100
+#define AUD_MISC_CTRL_B 0xE5110
+#define AUD_CTS_ENABLE_B 0xE5128
+#define AUD_HDMIW_HDMIEDID_B 0xE5150
+#define AUD_HDMIW_INFOFR_B 0xE5154
+#define AUD_OUT_DIG_CNVT_B 0xE5180
+#define AUD_OUT_STR_DESC_B 0xE5184
+#define AUD_CNTL_ST_B 0xE51B4
+#define AUD_CONFIG_C 0xE5200
+#define AUD_MISC_CTRL_C 0xE5210
+#define AUD_CTS_ENABLE_C 0xE5228
+#define AUD_HDMIW_HDMIEDID_C 0xE5250
+#define AUD_HDMIW_INFOFR_C 0xE5254
+#define AUD_OUT_DIG_CNVT_C 0xE5280
+#define AUD_OUT_STR_DESC_C 0xE5284
+#define AUD_CNTL_ST_C 0xE52B4
+#define AUD_CONFIG_D 0xE5300
+#define AUD_MISC_CTRL_D 0xE5310
+#define AUD_CTS_ENABLE_D 0xE5328
+#define AUD_HDMIW_HDMIEDID_D 0xE5350
+#define AUD_HDMIW_INFOFR_D 0xE5354
+#define AUD_OUT_DIG_CNVT_D 0xE5380
+#define AUD_OUT_STR_DESC_D 0xE5384
+#define AUD_CNTL_ST_D 0xE53B4
+
+#define VIDEO_DIP_CTL_A 0xE0200
+#define VIDEO_DIP_CTL_B 0xE1200
+#define VIDEO_DIP_CTL_C 0xE2200
+#define VIDEO_DIP_CTL_D 0xE3200
+
+
+static void dump_cpt(void)
+{
+ uint32_t dword;
+ int i;
+
+ dump_reg(HDMIB, "sDVO/HDMI Port B Control");
+ dump_reg(HDMIC, "HDMI Port C Control");
+ dump_reg(HDMID, "HDMI Port D Control");
+ dump_reg(DP_CTL_B, "DisplayPort B Control");
+ dump_reg(DP_CTL_C, "DisplayPort C Control");
+ dump_reg(DP_CTL_D, "DisplayPort D Control");
+ dump_reg(TRANS_DP_CTL_A, "Transcoder A DisplayPort Control");
+ dump_reg(TRANS_DP_CTL_B, "Transcoder B DisplayPort Control");
+ dump_reg(TRANS_DP_CTL_C, "Transcoder C DisplayPort Control");
+ dump_reg(AUD_CONFIG_A, "Audio Configuration - Transcoder A");
+ dump_reg(AUD_CONFIG_B, "Audio Configuration - Transcoder B");
+ dump_reg(AUD_CONFIG_C, "Audio Configuration - Transcoder C");
+ dump_reg(AUD_CTS_ENABLE_A, "Audio CTS Programming Enable - Transcoder A");
+ dump_reg(AUD_CTS_ENABLE_B, "Audio CTS Programming Enable - Transcoder B");
+ dump_reg(AUD_CTS_ENABLE_C, "Audio CTS Programming Enable - Transcoder C");
+ dump_reg(AUD_MISC_CTRL_A, "Audio MISC Control for Transcoder A");
+ dump_reg(AUD_MISC_CTRL_B, "Audio MISC Control for Transcoder B");
+ dump_reg(AUD_MISC_CTRL_C, "Audio MISC Control for Transcoder C");
+ dump_reg(AUD_VID_DID, "Audio Vendor ID / Device ID");
+ dump_reg(AUD_RID, "Audio Revision ID");
+ dump_reg(AUD_PWRST, "Audio Power State (Function Group, Convertor, Pin Widget)");
+ dump_reg(AUD_PORT_EN_HD_CFG, "Audio Port Enable HDAudio Config");
+ dump_reg(AUD_OUT_DIG_CNVT_A, "Audio Digital Converter - Conv A");
+ dump_reg(AUD_OUT_DIG_CNVT_B, "Audio Digital Converter - Conv B");
+ dump_reg(AUD_OUT_DIG_CNVT_C, "Audio Digital Converter - Conv C");
+ dump_reg(AUD_OUT_CH_STR, "Audio Channel ID and Stream ID");
+ dump_reg(AUD_OUT_STR_DESC_A, "Audio Stream Descriptor Format - Conv A");
+ dump_reg(AUD_OUT_STR_DESC_B, "Audio Stream Descriptor Format - Conv B");
+ dump_reg(AUD_OUT_STR_DESC_C, "Audio Stream Descriptor Format - Conv C");
+ dump_reg(AUD_PINW_CONNLNG_LIST, "Audio Connection List");
+ dump_reg(AUD_PINW_CONNLNG_SEL, "Audio Connection Select");
+ dump_reg(AUD_CNTL_ST_A, "Audio Control State Register - Transcoder A");
+ dump_reg(AUD_CNTL_ST_B, "Audio Control State Register - Transcoder B");
+ dump_reg(AUD_CNTL_ST_C, "Audio Control State Register - Transcoder C");
+ dump_reg(AUD_CNTRL_ST2, "Audio Control State 2");
+ dump_reg(AUD_CNTRL_ST3, "Audio Control State 3");
+ dump_reg(AUD_HDMIW_STATUS, "Audio HDMI Status");
+ dump_reg(AUD_HDMIW_HDMIEDID_A, "HDMI Data EDID Block - Transcoder A");
+ dump_reg(AUD_HDMIW_HDMIEDID_B, "HDMI Data EDID Block - Transcoder B");
+ dump_reg(AUD_HDMIW_HDMIEDID_C, "HDMI Data EDID Block - Transcoder C");
+ dump_reg(AUD_HDMIW_INFOFR_A, "Audio Widget Data Island Packet - Transcoder A");
+ dump_reg(AUD_HDMIW_INFOFR_B, "Audio Widget Data Island Packet - Transcoder B");
+ dump_reg(AUD_HDMIW_INFOFR_C, "Audio Widget Data Island Packet - Transcoder C");
+
+ printf("\nDetails:\n\n");
+
+ dword = INREG(VIDEO_DIP_CTL_A);
+ printf("VIDEO_DIP_CTL_A Enable_Graphics_DIP\t\t\t%ld\n", BIT(dword, 31)),
+ printf("VIDEO_DIP_CTL_A GCP_DIP_enable\t\t\t\t%ld\n", BIT(dword, 25)),
+ printf("VIDEO_DIP_CTL_A Video_DIP_type_enable AVI\t\t%lu\n", BIT(dword, 21));
+ printf("VIDEO_DIP_CTL_A Video_DIP_type_enable Vendor\t\t%lu\n", BIT(dword, 22));
+ printf("VIDEO_DIP_CTL_A Video_DIP_type_enable Gamut\t\t%lu\n", BIT(dword, 23));
+ printf("VIDEO_DIP_CTL_A Video_DIP_type_enable Source \t\t%lu\n", BIT(dword, 24));
+ printf("VIDEO_DIP_CTL_A Video_DIP_buffer_index\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 19), video_dip_index[BITS(dword, 20, 19)]);
+ printf("VIDEO_DIP_CTL_A Video_DIP_frequency\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), video_dip_trans[BITS(dword, 17, 16)]);
+ printf("VIDEO_DIP_CTL_A Video_DIP_buffer_size\t\t\t%lu\n", BITS(dword, 11, 8));
+ printf("VIDEO_DIP_CTL_A Video_DIP_access_address\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(VIDEO_DIP_CTL_B);
+ printf("VIDEO_DIP_CTL_B Enable_Graphics_DIP\t\t\t%ld\n", BIT(dword, 31)),
+ printf("VIDEO_DIP_CTL_B GCP_DIP_enable\t\t\t\t%ld\n", BIT(dword, 25)),
+ printf("VIDEO_DIP_CTL_B Video_DIP_type_enable AVI\t\t%lu\n", BIT(dword, 21));
+ printf("VIDEO_DIP_CTL_B Video_DIP_type_enable Vendor\t\t%lu\n", BIT(dword, 22));
+ printf("VIDEO_DIP_CTL_B Video_DIP_type_enable Gamut\t\t%lu\n", BIT(dword, 23));
+ printf("VIDEO_DIP_CTL_B Video_DIP_type_enable Source \t\t%lu\n", BIT(dword, 24));
+ printf("VIDEO_DIP_CTL_B Video_DIP_buffer_index\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 19), video_dip_index[BITS(dword, 20, 19)]);
+ printf("VIDEO_DIP_CTL_B Video_DIP_frequency\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), video_dip_trans[BITS(dword, 17, 16)]);
+ printf("VIDEO_DIP_CTL_B Video_DIP_buffer_size\t\t\t%lu\n", BITS(dword, 11, 8));
+ printf("VIDEO_DIP_CTL_B Video_DIP_access_address\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(VIDEO_DIP_CTL_C);
+ printf("VIDEO_DIP_CTL_C Enable_Graphics_DIP\t\t\t%ld\n", BIT(dword, 31)),
+ printf("VIDEO_DIP_CTL_C GCP_DIP_enable\t\t\t\t%ld\n", BIT(dword, 25)),
+ printf("VIDEO_DIP_CTL_C Video_DIP_type_enable AVI\t\t%lu\n", BIT(dword, 21));
+ printf("VIDEO_DIP_CTL_C Video_DIP_type_enable Vendor\t\t%lu\n", BIT(dword, 22));
+ printf("VIDEO_DIP_CTL_C Video_DIP_type_enable Gamut\t\t%lu\n", BIT(dword, 23));
+ printf("VIDEO_DIP_CTL_C Video_DIP_type_enable Source \t\t%lu\n", BIT(dword, 24));
+ printf("VIDEO_DIP_CTL_C Video_DIP_buffer_index\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 19), video_dip_index[BITS(dword, 20, 19)]);
+ printf("VIDEO_DIP_CTL_C Video_DIP_frequency\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), video_dip_trans[BITS(dword, 17, 16)]);
+ printf("VIDEO_DIP_CTL_C Video_DIP_buffer_size\t\t\t%lu\n", BITS(dword, 11, 8));
+ printf("VIDEO_DIP_CTL_C Video_DIP_access_address\t\t%lu\n", BITS(dword, 3, 0));
+
+ dword = INREG(AUD_VID_DID);
+ printf("AUD_VID_DID vendor id\t\t\t\t\t0x%x\n", dword >> 16);
+ printf("AUD_VID_DID device id\t\t\t\t\t0x%x\n", dword & 0xffff);
+
+ dword = INREG(AUD_RID);
+ printf("AUD_RID Major_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_RID Minor_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_RID Revision_Id\t\t\t\t\t0x%lx\n", BITS(dword, 15, 8));
+ printf("AUD_RID Stepping_Id\t\t\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(HDMIB);
+ printf("HDMIB Port_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMIB Transcoder_Select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), transcoder_select[BITS(dword, 30, 29)]);
+ printf("HDMIB sDVO_Border_Enable\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("HDMIB HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMIB SDVO_HPD_Interrupt_Enable\t\t\t\t%lu\n", BIT(dword, 23));
+ printf("HDMIB Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMIB Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMIB HDMI_or_DVI_Select\t\t\t\t%s\n", BIT(dword, 9) ? "HDMI" : "DVI");
+ printf("HDMIB Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(HDMIC);
+ printf("HDMIC Port_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMIC Transcoder_Select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), transcoder_select[BITS(dword, 30, 29)]);
+ printf("HDMIC sDVO_Border_Enable\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("HDMIC HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMIC SDVO_HPD_Interrupt_Enable\t\t\t\t%lu\n", BIT(dword, 23));
+ printf("HDMIC Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMIC Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMIC HDMI_or_DVI_Select\t\t\t\t%s\n", BIT(dword, 9) ? "HDMI" : "DVI");
+ printf("HDMIC Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(HDMID);
+ printf("HDMID Port_Enable\t\t\t\t\t%u\n", !!(dword & SDVO_ENABLE));
+ printf("HDMID Transcoder_Select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), transcoder_select[BITS(dword, 30, 29)]);
+ printf("HDMID sDVO_Border_Enable\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("HDMID HDCP_Port_Select\t\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("HDMID SDVO_HPD_Interrupt_Enable\t\t\t\t%lu\n", BIT(dword, 23));
+ printf("HDMID Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("HDMID Encoding\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 11, 10), sdvo_hdmi_encoding[BITS(dword, 11, 10)]);
+ printf("HDMID HDMI_or_DVI_Select\t\t\t\t%s\n", BIT(dword, 9) ? "HDMI" : "DVI");
+ printf("HDMID Audio_Output_Enable\t\t\t\t%u\n", !!(dword & SDVO_AUDIO_ENABLE));
+
+ dword = INREG(DP_CTL_B);
+ printf("DP_CTL_B DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("DP_CTL_B Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("DP_CTL_B Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("DP_CTL_B HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("DP_CTL_B Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(DP_CTL_C);
+ printf("DP_CTL_C DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("DP_CTL_C Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("DP_CTL_C Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("DP_CTL_C HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("DP_CTL_C Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(DP_CTL_D);
+ printf("DP_CTL_D DisplayPort_Enable\t\t\t\t%lu\n", BIT(dword, 31));
+ printf("DP_CTL_D Port_Width_Selection\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 21, 19), dp_port_width[BITS(dword, 21, 19)]);
+ printf("DP_CTL_D Port_Detected\t\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("DP_CTL_D HDCP_Port_Select\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("DP_CTL_D Audio_Output_Enable\t\t\t\t%lu\n", BIT(dword, 6));
+
+ dword = INREG(AUD_CONFIG_A);
+ printf("AUD_CONFIG_A N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_A N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_A Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_A Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_A Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_A Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_B);
+ printf("AUD_CONFIG_B N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_B N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_B Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_B Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_B Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_B Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_C);
+ printf("AUD_CONFIG_C N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_C N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_C Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_C Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_C Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_C Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+
+ dword = INREG(AUD_CTS_ENABLE_A);
+ printf("AUD_CTS_ENABLE_A Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_A CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_A CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_B);
+ printf("AUD_CTS_ENABLE_B Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_B CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_B CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_C);
+ printf("AUD_CTS_ENABLE_C Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_C CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_C CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+
+ dword = INREG(AUD_MISC_CTRL_A);
+ printf("AUD_MISC_CTRL_A Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_A Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_A Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_A Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_B);
+ printf("AUD_MISC_CTRL_B Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_B Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_B Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_B Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_C);
+ printf("AUD_MISC_CTRL_C Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_C Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_C Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_C Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+
+ dword = INREG(AUD_PWRST);
+ printf("AUD_PWRST Func_Grp_Dev_PwrSt_Curr \t%s\n", power_state[BITS(dword, 27, 26)]);
+ printf("AUD_PWRST Func_Grp_Dev_PwrSt_Set \t%s\n", power_state[BITS(dword, 25, 24)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 15, 14)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Requsted \t%s\n", power_state[BITS(dword, 13, 12)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 19, 18)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Requested \t%s\n", power_state[BITS(dword, 17, 16)]);
+ printf("AUD_PWRST ConvC_Widget_PwrSt_Curr \t%s\n", power_state[BITS(dword, 23, 22)]);
+ printf("AUD_PWRST ConvC_Widget_PwrSt_Req \t%s\n", power_state[BITS(dword, 21, 20)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 3, 2)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 1, 0)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 7, 6)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 5, 4)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 11, 10)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 9, 8)]);
+
+ dword = INREG(AUD_PORT_EN_HD_CFG);
+ printf("AUD_PORT_EN_HD_CFG Convertor_A_Digen\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_PORT_EN_HD_CFG Convertor_B_Digen\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_PORT_EN_HD_CFG Convertor_C_Digen\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_PORT_EN_HD_CFG ConvertorA_Stream_ID\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_PORT_EN_HD_CFG ConvertorB_Stream_ID\t\t%lu\n", BITS(dword, 11, 8));
+ printf("AUD_PORT_EN_HD_CFG ConvertorC_Stream_ID\t\t%lu\n", BITS(dword, 15, 12));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Out_Enable\t\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Out_Enable\t\t\t%lu\n", BIT(dword, 17));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Out_Enable\t\t\t%lu\n", BIT(dword, 18));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Amp_Mute_Status\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Amp_Mute_Status\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Amp_Mute_Status\t\t%lu\n", BIT(dword, 22));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_A);
+ printf("AUD_OUT_DIG_CNVT_A V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_A VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_A PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_A Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_A NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_A PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_A Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_A Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_A Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_A Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_B);
+ printf("AUD_OUT_DIG_CNVT_B V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_B VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_B PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_B Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_B NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_B PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_B Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_B Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_B Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_B Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_C);
+ printf("AUD_OUT_DIG_CNVT_C V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_C VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_C PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_C Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_C NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_C PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_C Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_C Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_C Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_C Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ printf("AUD_OUT_CH_STR Converter_Channel_MAP PORTB PORTC PORTD\n");
+ for (i = 0; i < 8; i++) {
+ OUTREG(AUD_OUT_CH_STR, i | (i << 8) | (i << 16));
+ dword = INREG(AUD_OUT_CH_STR);
+ printf("\t\t\t\t%lu\t%lu\t%lu\t%lu\n",
+ 1 + BITS(dword, 3, 0),
+ 1 + BITS(dword, 7, 4),
+ 1 + BITS(dword, 15, 12),
+ 1 + BITS(dword, 23, 20));
+ }
+
+ dword = INREG(AUD_OUT_STR_DESC_A);
+ printf("AUD_OUT_STR_DESC_A HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_A Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_A Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_A Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_B);
+ printf("AUD_OUT_STR_DESC_B HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_B Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_B Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_B Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_C);
+ printf("AUD_OUT_STR_DESC_C HBR_enable\t\t\t\t%lu\n", BITS(dword, 28, 27));
+ printf("AUD_OUT_STR_DESC_C Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_C Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_C Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_PINW_CONNLNG_SEL);
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_B\t%#lx\n", BITS(dword, 7, 0));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_C\t%#lx\n", BITS(dword, 15, 8));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_D\t%#lx\n", BITS(dword, 23, 16));
+
+ dword = INREG(AUD_CNTL_ST_A);
+ printf("AUD_CNTL_ST_A DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_A DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_A DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_A DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_A DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_A ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_A ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_CNTL_ST_B);
+ printf("AUD_CNTL_ST_B DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_B DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_B DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_B DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_B DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_B ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_B ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_CNTL_ST_C);
+ printf("AUD_CNTL_ST_C DIP_Port_Select\t\t\t\t[%#lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+ printf("AUD_CNTL_ST_C DIP_type_enable_status Audio DIP\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_CNTL_ST_C DIP_type_enable_status ACP DIP\t\t%lu\n", BIT(dword, 22));
+ printf("AUD_CNTL_ST_C DIP_type_enable_status Generic 2 DIP\t%lu\n", BIT(dword, 23));
+ printf("AUD_CNTL_ST_C DIP_transmission_frequency\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("AUD_CNTL_ST_C ELD_ACK\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTL_ST_C ELD_buffer_size\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_CNTRL_ST2);
+ printf("AUD_CNTRL_ST2 CP_ReadyB\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_CNTRL_ST2 ELD_validB\t\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_CNTRL_ST2 CP_ReadyC\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_CNTRL_ST2 ELD_validC\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTRL_ST2 CP_ReadyD\t\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_CNTRL_ST2 ELD_validD\t\t\t\t%lu\n", BIT(dword, 8));
+
+ dword = INREG(AUD_CNTRL_ST3);
+ printf("AUD_CNTRL_ST3 TransA_DPT_Audio_Output_En\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_CNTRL_ST3 TransA_to_Port_Sel\t\t\t[%#lx] %s\n",
+ BITS(dword, 2, 0), trans_to_port_sel[BITS(dword, 2, 0)]);
+ printf("AUD_CNTRL_ST3 TransB_DPT_Audio_Output_En\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_CNTRL_ST3 TransB_to_Port_Sel\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), trans_to_port_sel[BITS(dword, 6, 4)]);
+ printf("AUD_CNTRL_ST3 TransC_DPT_Audio_Output_En\t\t%lu\n", BIT(dword, 11));
+ printf("AUD_CNTRL_ST3 TransC_to_Port_Sel\t\t\t[%#lx] %s\n",
+ BITS(dword, 10, 8), trans_to_port_sel[BITS(dword, 10, 8)]);
+
+ dword = INREG(AUD_HDMIW_STATUS);
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 27));
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 26));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 29));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 28));
+ printf("AUD_HDMIW_STATUS Conv_C_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 31));
+ printf("AUD_HDMIW_STATUS Conv_C_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 30));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK_FIFO_Overrun\t\t%lu\n", BIT(dword, 25));
+ printf("AUD_HDMIW_STATUS Function_Reset\t\t\t%lu\n", BIT(dword, 24));
+
+ printf("AUD_HDMIW_HDMIEDID_A HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_A);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_A, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_B HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_B);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_B, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_C HDMI ELD:\n\t");
+ dword = INREG(AUD_CNTL_ST_C);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_CNTL_ST_C, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_C)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_A HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_A);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_A, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_B HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_B);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_B, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_C HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_CNTL_ST_C);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_CNTL_ST_C, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_C)));
+ printf("\n");
+
+}
+
+#undef AUD_CONFIG_A
+#undef AUD_MISC_CTRL_A
+#undef AUD_VID_DID
+#undef AUD_RID
+#undef AUD_CTS_ENABLE_A
+#undef AUD_PWRST
+#undef AUD_HDMIW_HDMIEDID_A
+#undef AUD_HDMIW_INFOFR_A
+#undef AUD_PORT_EN_HD_CFG
+#undef AUD_OUT_DIG_CNVT_A
+#undef AUD_OUT_STR_DESC_A
+#undef AUD_OUT_CH_STR
+#undef AUD_PINW_CONNLNG_LIST
+#undef AUD_CNTL_ST_A
+#undef AUD_HDMIW_STATUS
+#undef AUD_CONFIG_B
+#undef AUD_MISC_CTRL_B
+#undef AUD_CTS_ENABLE_B
+#undef AUD_HDMIW_HDMIEDID_B
+#undef AUD_HDMIW_INFOFR_B
+#undef AUD_OUT_DIG_CNVT_B
+#undef AUD_OUT_STR_DESC_B
+#undef AUD_CNTL_ST_B
+#undef AUD_CONFIG_C
+#undef AUD_MISC_CTRL_C
+#undef AUD_CTS_ENABLE_C
+#undef AUD_HDMIW_HDMIEDID_C
+#undef AUD_HDMIW_INFOFR_C
+#undef AUD_OUT_DIG_CNVT_C
+#undef AUD_OUT_STR_DESC_C
+
+#undef VIDEO_DIP_CTL_A
+#undef VIDEO_DIP_CTL_B
+#undef VIDEO_DIP_CTL_C
+#undef VIDEO_DIP_CTL_D
+#undef VIDEO_DIP_DATA
+
+/*
+ * Haswell registers
+ */
+
+/* DisplayPort Transport Control */
+#define DP_TP_CTL_A 0x64040
+#define DP_TP_CTL_B 0x64140
+#define DP_TP_CTL_C 0x64240
+#define DP_TP_CTL_D 0x64340
+#define DP_TP_CTL_E 0x64440
+
+/* DisplayPort Transport Status */
+#define DP_TP_ST_A 0x64044
+#define DP_TP_ST_B 0x64144
+#define DP_TP_ST_C 0x64244
+#define DP_TP_ST_D 0x64344
+#define DP_TP_ST_E 0x64444
+
+/* Transcoder configuration */
+#define TRANS_CONF_A 0xF0008
+#define TRANS_CONF_B 0xF1008
+#define TRANS_CONF_C 0xF2008
+
+/* DDI Buffer Control */
+#define DDI_BUF_CTL_A 0x64000
+#define DDI_BUF_CTL_B 0x64100
+#define DDI_BUF_CTL_C 0x64200
+#define DDI_BUF_CTL_D 0x64300
+#define DDI_BUF_CTL_E 0x64400
+
+/* DDI Buffer Translation */
+#define DDI_BUF_TRANS_A 0x64e00
+#define DDI_BUF_TRANS_B 0x64e60
+#define DDI_BUF_TRANS_C 0x64ec0
+#define DDI_BUF_TRANS_D 0x64f20
+#define DDI_BUF_TRANS_E 0x64f80
+
+/* DDI Aux Channel */
+#define DDI_AUX_CHANNEL_CTRL 0x64010
+#define DDI_AUX_DATA 0x64014
+#define DDI_AUX_TST 0x64028
+
+/* DDI CRC Control */
+#define DDI_CRC_CTL_A 0x64050
+#define DDI_CRC_CTL_B 0x64150
+#define DDI_CRC_CTL_C 0x64250
+#define DDI_CRC_CTL_D 0x64350
+#define DDI_CRC_CTL_E 0x64450
+
+/* Pipe DDI Function Control */
+#define PIPE_DDI_FUNC_CTL_A 0x60400
+#define PIPE_DDI_FUNC_CTL_B 0x61400
+#define PIPE_DDI_FUNC_CTL_C 0x62400
+#define PIPE_DDI_FUNC_CTL_EDP 0x6F400
+
+/* Pipe Configuration */
+#define PIPE_CONF_A 0x70008
+#define PIPE_CONF_B 0x71008
+#define PIPE_CONF_C 0x72008
+#define PIPE_CONF_EDP 0x7F008
+
+/* Audio registers */
+#define AUD_CONFIG_A 0x65000
+#define AUD_MISC_CTRL_A 0x65010
+#define AUD_VID_DID 0x65020
+#define AUD_RID 0x65024
+#define AUD_CTS_ENABLE_A 0x65028
+#define AUD_PWRST 0x6504C
+#define AUD_HDMIW_HDMIEDID_A 0x65050
+#define AUD_HDMIW_INFOFR_A 0x65054
+#define AUD_PORT_EN_HD_CFG 0x6507C
+#define AUD_OUT_DIG_CNVT_A 0x65080
+#define AUD_OUT_STR_DESC_A 0x65084
+#define AUD_OUT_CHAN_MAP 0x65088
+#define AUD_PINW_CONNLNG_LIST_A 0x650A8
+#define AUD_PINW_CONNLNG_LIST_B 0x651A8
+#define AUD_PINW_CONNLNG_LIST_C 0x652A8
+#define AUD_PIPE_CONN_SEL_CTRL 0x650AC
+#define AUD_PIN_ELD_CP_VLD 0x650C0
+#define AUD_HDMIW_STATUS 0x650D4
+#define AUD_CONFIG_B 0x65100
+#define AUD_MISC_CTRL_B 0x65110
+#define AUD_CTS_ENABLE_B 0x65128
+#define AUD_HDMIW_HDMIEDID_B 0x65150
+#define AUD_HDMIW_INFOFR_B 0x65154
+#define AUD_OUT_DIG_CNVT_B 0x65180
+#define AUD_OUT_STR_DESC_B 0x65184
+#define AUD_CONFIG_C 0x65200
+#define AUD_MISC_CTRL_C 0x65210
+#define AUD_CTS_ENABLE_C 0x65228
+#define AUD_HDMIW_HDMIEDID_C 0x65250
+#define AUD_HDMIW_INFOFR_C 0x65254
+#define AUD_OUT_DIG_CNVT_C 0x65280
+#define AUD_OUT_STR_DESC_C 0x65284
+#define AUD_DIP_ELD_CTRL_ST_A 0x650b4
+#define AUD_DIP_ELD_CTRL_ST_B 0x651b4
+#define AUD_DIP_ELD_CTRL_ST_C 0x652b4
+
+/* Video DIP Control */
+#define VIDEO_DIP_CTL_A 0x60200
+#define VIDEO_DIP_CTL_B 0x61200
+#define VIDEO_DIP_CTL_C 0x62200
+#define VIDEO_DIP_CTL_D 0x63200
+
+#define VIDEO_DIP_DATA 0x60220
+#define VIDEO_DIP_ECC 0x60240
+
+#define AUD_DP_DIP_STATUS 0x65f20
+
+
+static void dump_hsw(void)
+{
+ uint32_t dword;
+ int i;
+
+ /* HSW DDI Buffer */
+ dump_reg(DDI_BUF_CTL_A, "DDI Buffer Controler A");
+ dump_reg(DDI_BUF_CTL_B, "DDI Buffer Controler B");
+ dump_reg(DDI_BUF_CTL_C, "DDI Buffer Controler C");
+ dump_reg(DDI_BUF_CTL_D, "DDI Buffer Controler D");
+ dump_reg(DDI_BUF_CTL_E, "DDI Buffer Controler E");
+
+ /* HSW Pipe Function */
+ dump_reg(PIPE_CONF_A, "PIPE Configuration A");
+ dump_reg(PIPE_CONF_B, "PIPE Configuration B");
+ dump_reg(PIPE_CONF_C, "PIPE Configuration C");
+ dump_reg(PIPE_CONF_EDP, "PIPE Configuration EDP");
+
+ dump_reg(PIPE_DDI_FUNC_CTL_A, "PIPE DDI Function Control A");
+ dump_reg(PIPE_DDI_FUNC_CTL_B, "PIPE DDI Function Control B");
+ dump_reg(PIPE_DDI_FUNC_CTL_C, "PIPE DDI Function Control C");
+ dump_reg(PIPE_DDI_FUNC_CTL_EDP, "PIPE DDI Function Control EDP");
+
+ /* HSW Display port */
+ dump_reg(DP_TP_CTL_A, "DisplayPort Transport A Control");
+ dump_reg(DP_TP_CTL_B, "DisplayPort Transport B Control");
+ dump_reg(DP_TP_CTL_C, "DisplayPort Transport C Control");
+ dump_reg(DP_TP_CTL_D, "DisplayPort Transport D Control");
+ dump_reg(DP_TP_CTL_E, "DisplayPort Transport E Control");
+
+ dump_reg(DP_TP_ST_A, "DisplayPort Transport A Status");
+ dump_reg(DP_TP_ST_B, "DisplayPort Transport B Status");
+ dump_reg(DP_TP_ST_C, "DisplayPort Transport C Status");
+ dump_reg(DP_TP_ST_D, "DisplayPort Transport D Status");
+ dump_reg(DP_TP_ST_E, "DisplayPort Transport E Status");
+
+ /* HSW Transcoder A configuration */
+ dump_reg(TRANS_CONF_A, "Transcoder A Configuration");
+ dump_reg(TRANS_CONF_B, "Transcoder B Configuration");
+ dump_reg(TRANS_CONF_C, "Transcoder C Configuration");
+
+ /* HSW North Display Audio */
+ dump_reg(AUD_CONFIG_A, "Audio Configuration - Transcoder A");
+ dump_reg(AUD_CONFIG_B, "Audio Configuration - Transcoder B");
+ dump_reg(AUD_CONFIG_C, "Audio Configuration - Transcoder C");
+ dump_reg(AUD_MISC_CTRL_A, "Audio MISC Control for Transcoder A");
+ dump_reg(AUD_MISC_CTRL_B, "Audio MISC Control for Transcoder B");
+ dump_reg(AUD_MISC_CTRL_C, "Audio MISC Control for Transcoder C");
+ dump_reg(AUD_VID_DID, "Audio Vendor ID / Device ID");
+ dump_reg(AUD_RID, "Audio Revision ID");
+ dump_reg(AUD_CTS_ENABLE_A, "Audio CTS Programming Enable - Transcoder A");
+ dump_reg(AUD_CTS_ENABLE_B, "Audio CTS Programming Enable - Transcoder B");
+ dump_reg(AUD_CTS_ENABLE_C, "Audio CTS Programming Enable - Transcoder C");
+ dump_reg(AUD_PWRST, "Audio Power State (Function Group, Convertor, Pin Widget)");
+ dump_reg(AUD_HDMIW_HDMIEDID_A, "HDMI Data EDID Block - Transcoder A");
+ dump_reg(AUD_HDMIW_HDMIEDID_B, "HDMI Data EDID Block - Transcoder B");
+ dump_reg(AUD_HDMIW_HDMIEDID_C, "HDMI Data EDID Block - Transcoder C");
+ dump_reg(AUD_HDMIW_INFOFR_A, "Audio Widget Data Island Packet - Transcoder A");
+ dump_reg(AUD_HDMIW_INFOFR_B, "Audio Widget Data Island Packet - Transcoder B");
+ dump_reg(AUD_HDMIW_INFOFR_C, "Audio Widget Data Island Packet - Transcoder C");
+
+ dump_reg(AUD_PORT_EN_HD_CFG, "Audio Pipe and Convert Configs");
+ dump_reg(AUD_OUT_DIG_CNVT_A, "Audio Digital Converter - Conv A");
+ dump_reg(AUD_OUT_DIG_CNVT_B, "Audio Digital Converter - Conv B");
+ dump_reg(AUD_OUT_DIG_CNVT_C, "Audio Digital Converter - Conv C");
+ dump_reg(AUD_OUT_CHAN_MAP, "Audio Output Channel Mapping");
+ dump_reg(AUD_OUT_STR_DESC_A, "Audio Stream Descriptor Format - Conv A");
+ dump_reg(AUD_OUT_STR_DESC_B, "Audio Stream Descriptor Format - Conv B");
+ dump_reg(AUD_OUT_STR_DESC_C, "Audio Stream Descriptor Format - Conv C");
+ dump_reg(AUD_PINW_CONNLNG_LIST_A, "Audio Connection List entry and Length - Transcoder A");
+ dump_reg(AUD_PINW_CONNLNG_LIST_B, "Audio Connection List entry and Length - Transcoder B");
+ dump_reg(AUD_PINW_CONNLNG_LIST_C, "Audio Connection List entry and Length - Transcoder C");
+ dump_reg(AUD_PIPE_CONN_SEL_CTRL, "Audio Pipe Connection Select Control");
+ dump_reg(AUD_DIP_ELD_CTRL_ST_A, "Audio DIP and ELD control state - Transcoder A");
+ dump_reg(AUD_DIP_ELD_CTRL_ST_B, "Audio DIP and ELD control state - Transcoder B");
+ dump_reg(AUD_DIP_ELD_CTRL_ST_C, "Audio DIP and ELD control state - Transcoder C");
+ dump_reg(AUD_PIN_ELD_CP_VLD, "audio pin eld valid status");
+ dump_reg(AUD_HDMIW_STATUS, "Audio HDMI FIFO Status");
+
+ printf("\nDetails:\n\n");
+
+ dword = INREG(AUD_VID_DID);
+ printf("AUD_VID_DID vendor id\t\t\t\t\t0x%x\n", dword >> 16);
+ printf("AUD_VID_DID device id\t\t\t\t\t0x%x\n", dword & 0xffff);
+
+ dword = INREG(AUD_RID);
+ printf("AUD_RID Major_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 23, 20));
+ printf("AUD_RID Minor_Revision\t\t\t\t\t0x%lx\n", BITS(dword, 19, 16));
+ printf("AUD_RID Revision_Id\t\t\t\t\t0x%lx\n", BITS(dword, 15, 8));
+ printf("AUD_RID Stepping_Id\t\t\t\t\t0x%lx\n", BITS(dword, 7, 0));
+
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_A);
+ printf("Audio DIP and ELD control state for TranscoderA\n");
+ printf("Audio DIP port select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+
+ printf("Audio DIP type enable status\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 24, 21), dip_type[BIT(dword, 21)]);
+
+ printf("DIP Buffer Index \t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 18), dip_index[BITS(dword, 20, 18)]);
+ printf("DIP_transmission_frequency\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("ELD_ACK\t\t\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("ELD_buffer_size\t\t\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_B);
+ printf("Audio DIP and ELD control state for TranscoderB\n");
+ printf("Audio DIP port select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+
+ printf("Audio DIP type enable status\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 24, 21), dip_type[BIT(dword, 21)]);
+
+ printf("DIP Buffer Index \t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 18), dip_index[BITS(dword, 20, 18)]);
+ printf("DIP_transmission_frequency\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("ELD_ACK\t\t\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("ELD_buffer_size\t\t\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_C);
+ printf("Audio DIP and ELD control state for TranscoderC\n");
+ printf("Audio DIP port select\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 30, 29), dip_port[BITS(dword, 30, 29)]);
+
+ printf("Audio DIP type enable status\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 24, 21), dip_type[BIT(dword, 21)]);
+
+ printf("DIP Buffer Index \t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 20, 18), dip_index[BITS(dword, 20, 18)]);
+ printf("DIP_transmission_frequency\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 17, 16), dip_trans[BITS(dword, 17, 16)]);
+ printf("ELD_ACK\t\t\t\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("ELD_buffer_size\t\t\t\t\t\t%lu\n", BITS(dword, 14, 10));
+
+ dword = INREG(DDI_BUF_CTL_A);
+ printf("DDI A Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+ dword = INREG(DDI_BUF_CTL_B);
+ printf("DDI B Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+ dword = INREG(DDI_BUF_CTL_C);
+ printf("DDI C Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+ dword = INREG(DDI_BUF_CTL_D);
+ printf("DDI D Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+ dword = INREG(DDI_BUF_CTL_E);
+ printf("DDI E Buffer control\n");
+ printf("DDI Buffer Enable\t\t\t\t\t%ld\n", BIT(dword, 31));
+ printf("DP port width\t\t\t\t\t\t[0x%lx] %s\n",
+ BITS(dword, 3, 1), dp_port_width[BITS(dword, 3, 1)]);
+
+ dword = INREG(PIPE_DDI_FUNC_CTL_A);
+ printf("Pipe A DDI Function Control\n");
+ printf("PIPE DDI Function Enable\t\t\t\t[0x%lx]\n", BIT(dword, 31));
+ printf("PIPE DDI selection\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 30, 28),
+ trans_to_port_sel[BITS(dword, 30, 28)]);
+ printf("PIPE DDI Mode\t\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 26, 24), ddi_mode[BITS(dword, 26, 24)]);
+ printf("BITS per color\t\t\t\t\t\t[0x%lx]\n", BITS(dword, 22, 20));
+
+ dword = INREG(PIPE_DDI_FUNC_CTL_B);
+ printf("Pipe B DDI Function Control\n");
+ printf("PIPE DDI Function Enable\t\t\t\t[0x%lx]\n", BIT(dword, 31));
+ printf("PIPE DDI selection\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 30, 28),
+ trans_to_port_sel[BITS(dword, 30, 28)]);
+ printf("PIPE DDI Mode \t\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 26, 24), ddi_mode[BITS(dword, 26, 24)]);
+ printf("BITS per color\t\t\t\t\t\t[0x%lx]\n", BITS(dword, 22, 20));
+
+ dword = INREG(PIPE_DDI_FUNC_CTL_C);
+ printf("Pipe C DDI Function Control\n");
+ printf("PIPE DDI Function Enable\t\t\t\t[0x%lx]\n", BIT(dword, 31));
+ printf("PIPE DDI selection\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 30, 28),
+ trans_to_port_sel[BITS(dword, 30, 28)]);
+ printf("PIPE DDI Mode \t\t\t\t\t\t[0x%lx] %s\n", BITS(dword, 26, 24), ddi_mode[BITS(dword, 26, 24)]);
+ printf("BITS per color\t\t\t\t\t\t[0x%lx]\n", BITS(dword, 22, 20));
+
+ dword = INREG(AUD_CONFIG_A);
+ printf("AUD_CONFIG_A N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_A N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_A Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_A Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_A Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_A Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_B);
+ printf("AUD_CONFIG_B N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_B N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_B Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_B Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_B Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_B Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+ dword = INREG(AUD_CONFIG_C);
+ printf("AUD_CONFIG_C N_index_value\t\t\t\t[0x%lx] %s\n", BIT(dword, 29),
+ n_index_value[BIT(dword, 29)]);
+ printf("AUD_CONFIG_C N_programming_enable\t\t\t%lu\n", BIT(dword, 28));
+ printf("AUD_CONFIG_C Upper_N_value\t\t\t\t0x%02lx\n", BITS(dword, 27, 20));
+ printf("AUD_CONFIG_C Lower_N_value\t\t\t\t0x%03lx\n", BITS(dword, 15, 4));
+ printf("AUD_CONFIG_C Pixel_Clock_HDMI\t\t\t\t[0x%lx] %s\n", BITS(dword, 19, 16),
+ OPNAME(pixel_clock, BITS(dword, 19, 16)));
+ printf("AUD_CONFIG_C Disable_NCTS\t\t\t\t%lu\n", BIT(dword, 3));
+
+ dword = INREG(AUD_CTS_ENABLE_A);
+ printf("AUD_CTS_ENABLE_A Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_A CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_A CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_B);
+ printf("AUD_CTS_ENABLE_B Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_B CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_B CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+ dword = INREG(AUD_CTS_ENABLE_C);
+ printf("AUD_CTS_ENABLE_C Enable_CTS_or_M_programming\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_CTS_ENABLE_C CTS_M value Index\t\t\t%s\n", BIT(dword, 21) ? "CTS" : "M");
+ printf("AUD_CTS_ENABLE_C CTS_programming\t\t\t%#lx\n", BITS(dword, 19, 0));
+
+ dword = INREG(AUD_MISC_CTRL_A);
+ printf("AUD_MISC_CTRL_A Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_A Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_A Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_A Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_B);
+ printf("AUD_MISC_CTRL_B Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_B Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_B Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_B Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+ dword = INREG(AUD_MISC_CTRL_C);
+ printf("AUD_MISC_CTRL_C Sample_Fabrication_EN_bit\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_MISC_CTRL_C Sample_present_Disable\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_MISC_CTRL_C Output_Delay\t\t\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_MISC_CTRL_C Pro_Allowed\t\t\t\t%lu\n", BIT(dword, 1));
+
+ dword = INREG(AUD_PWRST);
+ printf("AUD_PWRST Func_Grp_Dev_PwrSt_Curr \t%s\n", power_state[BITS(dword, 27, 26)]);
+ printf("AUD_PWRST Func_Grp_Dev_PwrSt_Set \t%s\n", power_state[BITS(dword, 25, 24)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 15, 14)]);
+ printf("AUD_PWRST ConvertorA_Widget_Power_State_Requsted \t%s\n", power_state[BITS(dword, 13, 12)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 19, 18)]);
+ printf("AUD_PWRST ConvertorB_Widget_Power_State_Requested \t%s\n", power_state[BITS(dword, 17, 16)]);
+ printf("AUD_PWRST ConvC_Widget_PwrSt_Curr \t%s\n", power_state[BITS(dword, 23, 22)]);
+ printf("AUD_PWRST ConvC_Widget_PwrSt_Req \t%s\n", power_state[BITS(dword, 21, 20)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 3, 2)]);
+ printf("AUD_PWRST PinB_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 1, 0)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 7, 6)]);
+ printf("AUD_PWRST PinC_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 5, 4)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Current \t%s\n", power_state[BITS(dword, 11, 10)]);
+ printf("AUD_PWRST PinD_Widget_Power_State_Set \t%s\n", power_state[BITS(dword, 9, 8)]);
+
+ dword = INREG(AUD_PORT_EN_HD_CFG);
+ printf("AUD_PORT_EN_HD_CFG Convertor_A_Digen\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_PORT_EN_HD_CFG Convertor_B_Digen\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_PORT_EN_HD_CFG Convertor_C_Digen\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_PORT_EN_HD_CFG ConvertorA_Stream_ID\t\t%lu\n", BITS(dword, 7, 4));
+ printf("AUD_PORT_EN_HD_CFG ConvertorB_Stream_ID\t\t%lu\n", BITS(dword, 11, 8));
+ printf("AUD_PORT_EN_HD_CFG ConvertorC_Stream_ID\t\t%lu\n", BITS(dword, 15, 12));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Out_Enable\t\t\t%lu\n", BIT(dword, 16));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Out_Enable\t\t\t%lu\n", BIT(dword, 17));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Out_Enable\t\t\t%lu\n", BIT(dword, 18));
+ printf("AUD_PORT_EN_HD_CFG Port_B_Amp_Mute_Status\t\t%lu\n", BIT(dword, 20));
+ printf("AUD_PORT_EN_HD_CFG Port_C_Amp_Mute_Status\t\t%lu\n", BIT(dword, 21));
+ printf("AUD_PORT_EN_HD_CFG Port_D_Amp_Mute_Status\t\t%lu\n", BIT(dword, 22));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_A);
+ printf("AUD_OUT_DIG_CNVT_A V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_A VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_A PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_A Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_A NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_A PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_A Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_A Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_A Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_A Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_B);
+ printf("AUD_OUT_DIG_CNVT_B V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_B VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_B PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_B Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_B NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_B PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_B Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_B Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_B Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_B Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ dword = INREG(AUD_OUT_DIG_CNVT_C);
+ printf("AUD_OUT_DIG_CNVT_C V\t\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_OUT_DIG_CNVT_C VCFG\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_OUT_DIG_CNVT_C PRE\t\t\t\t\t%lu\n", BIT(dword, 3));
+ printf("AUD_OUT_DIG_CNVT_C Copy\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_OUT_DIG_CNVT_C NonAudio\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_OUT_DIG_CNVT_C PRO\t\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_OUT_DIG_CNVT_C Level\t\t\t\t%lu\n", BIT(dword, 7));
+ printf("AUD_OUT_DIG_CNVT_C Category_Code\t\t\t%lu\n", BITS(dword, 14, 8));
+ printf("AUD_OUT_DIG_CNVT_C Lowest_Channel_Number\t\t%lu\n",BITS(dword, 19, 16));
+ printf("AUD_OUT_DIG_CNVT_C Stream_ID\t\t\t\t%lu\n", BITS(dword, 23, 20));
+
+ printf("AUD_OUT_CHAN_MAP Converter_Channel_MAP PORTB PORTC PORTD\n");
+ for (i = 0; i < 8; i++) {
+ OUTREG(AUD_OUT_CHAN_MAP, i | (i << 8) | (i << 16));
+ dword = INREG(AUD_OUT_CHAN_MAP);
+ printf("\t\t\t\t%lu\t%lu\t%lu\t%lu\n",
+ 1 + BITS(dword, 3, 0),
+ 1 + BITS(dword, 7, 4),
+ 1 + BITS(dword, 15, 12),
+ 1 + BITS(dword, 23, 20));
+ }
+
+ dword = INREG(AUD_OUT_STR_DESC_A);
+ printf("AUD_OUT_STR_DESC_A Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_A Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_A Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_B);
+ printf("AUD_OUT_STR_DESC_B Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_B Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_B Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_OUT_STR_DESC_C);
+ printf("AUD_OUT_STR_DESC_C Convertor_Channel_Count\t\t%lu\n", BITS(dword, 20, 16) + 1);
+ printf("AUD_OUT_STR_DESC_C Bits_per_Sample\t\t\t[%#lx] %s\n",
+ BITS(dword, 6, 4), OPNAME(bits_per_sample, BITS(dword, 6, 4)));
+ printf("AUD_OUT_STR_DESC_C Number_of_Channels_in_a_Stream\t%lu\n", 1 + BITS(dword, 3, 0));
+
+ dword = INREG(AUD_PINW_CONNLNG_SEL);
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_B\t%#lx\n", BITS(dword, 7, 0));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_C\t%#lx\n", BITS(dword, 15, 8));
+ printf("AUD_PINW_CONNLNG_SEL Connection_select_Control_D\t%#lx\n", BITS(dword, 23, 16));
+
+ dword = INREG(AUD_PIN_ELD_CP_VLD);
+ printf("AUD_CNTRL_ST2 CP_ReadyB\t\t\t\t%lu\n", BIT(dword, 1));
+ printf("AUD_CNTRL_ST2 ELD_validB\t\t\t\t%lu\n", BIT(dword, 0));
+ printf("AUD_CNTRL_ST2 OUT_enableB\t\t\t\t%lu\n", BIT(dword, 2));
+ printf("AUD_CNTRL_ST2 CP_ReadyC\t\t\t\t%lu\n", BIT(dword, 5));
+ printf("AUD_CNTRL_ST2 ELD_validC\t\t\t\t%lu\n", BIT(dword, 4));
+ printf("AUD_CNTRL_ST2 OUT_enableC\t\t\t\t%lu\n", BIT(dword, 6));
+ printf("AUD_CNTRL_ST2 CP_ReadyD\t\t\t\t%lu\n", BIT(dword, 9));
+ printf("AUD_CNTRL_ST2 ELD_validD\t\t\t\t%lu\n", BIT(dword, 8));
+ printf("AUD_CNTRL_ST2 OUT_enableD\t\t\t\t%lu\n", BIT(dword, 10));
+
+ dword = INREG(AUD_HDMIW_STATUS);
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 27));
+ printf("AUD_HDMIW_STATUS Conv_A_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 26));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 29));
+ printf("AUD_HDMIW_STATUS Conv_B_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 28));
+ printf("AUD_HDMIW_STATUS Conv_C_CDCLK/DOTCLK_FIFO_Underrun\t%lu\n", BIT(dword, 31));
+ printf("AUD_HDMIW_STATUS Conv_C_CDCLK/DOTCLK_FIFO_Overrun\t%lu\n", BIT(dword, 30));
+ printf("AUD_HDMIW_STATUS BCLK/CDCLK_FIFO_Overrun\t\t%lu\n", BIT(dword, 25));
+ printf("AUD_HDMIW_STATUS Function_Reset\t\t\t%lu\n", BIT(dword, 24));
+
+ printf("AUD_HDMIW_HDMIEDID_A HDMI ELD:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_A);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_A, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_B HDMI ELD:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_B);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_B, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_HDMIEDID_C HDMI ELD:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_C);
+ dword &= ~BITMASK(9, 5);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_C, dword);
+ for (i = 0; i < BITS(dword, 14, 10) / 4; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_HDMIEDID_C)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_A HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_A);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_A, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_A)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_B HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_B);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_B, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_B)));
+ printf("\n");
+
+ printf("AUD_HDMIW_INFOFR_C HDMI audio Infoframe:\n\t");
+ dword = INREG(AUD_DIP_ELD_CTRL_ST_C);
+ dword &= ~BITMASK(20, 18);
+ dword &= ~BITMASK(3, 0);
+ OUTREG(AUD_DIP_ELD_CTRL_ST_C, dword);
+ for (i = 0; i < 8; i++)
+ printf("%08x ", htonl(INREG(AUD_HDMIW_INFOFR_C)));
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ struct pci_device *pci_dev;
+
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id; /* XXX not true when mapping! */
+
+ do_self_tests();
+
+ if (argc == 2)
+ intel_map_file(argv[1]);
+ else
+ intel_get_mmio(pci_dev);
+
+ if (IS_GEN6(devid) || IS_GEN7(devid) || getenv("HAS_PCH_SPLIT")) {
+ if (IS_HASWELL(devid)) {
+ printf("Haswell audio registers:\n\n");
+ dump_hsw();
+ return 0;
+ }
+ printf("%s audio registers:\n\n",
+ IS_GEN6(devid) ? "SandyBridge" : "IvyBridge");
+ intel_check_pch();
+ dump_cpt();
+ } else if (IS_GEN5(devid)) {
+ printf("Ironlake audio registers:\n\n");
+ dump_ironlake();
+ } else if (IS_G4X(devid)) {
+ printf("G45 audio registers:\n\n");
+ dump_eaglelake();
+ }
+
+ return 0;
+}
diff --git a/tools/intel_backlight.c b/tools/intel_backlight.c
new file mode 100644
index 00000000..bd7c813b
--- /dev/null
+++ b/tools/intel_backlight.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "intel_gpu_tools.h"
+
+/* XXX PCH only today */
+
+static uint32_t reg_read(uint32_t reg)
+{
+ return *(volatile uint32_t *)((volatile char*)mmio + reg);
+}
+
+static void reg_write(uint32_t reg, uint32_t val)
+{
+ *(volatile uint32_t *)((volatile char*)mmio + reg) = val;
+}
+
+int main(int argc, char** argv)
+{
+ uint32_t current, max;
+
+ intel_get_mmio(intel_get_pci_device());
+
+ current = reg_read(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
+ max = reg_read(BLC_PWM_PCH_CTL2) >> 16;
+
+ printf ("current backlight value: %d%%\n", current * 100 / max);
+
+ if (argc > 1) {
+ uint32_t v = atoi (argv[1]) * max / 100;
+ if (v > max)
+ v = max;
+ reg_write(BLC_PWM_CPU_CTL,
+ (reg_read(BLC_PWM_CPU_CTL) &~ BACKLIGHT_DUTY_CYCLE_MASK) | v);
+ (void) reg_read(BLC_PWM_CPU_CTL);
+ printf ("set backlight to %d%%\n", v * 100 / max);
+ }
+
+ return 0;
+}
diff --git a/tools/intel_bios.h b/tools/intel_bios.h
new file mode 100644
index 00000000..12850203
--- /dev/null
+++ b/tools/intel_bios.h
@@ -0,0 +1,731 @@
+/*
+ * Copyright 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _INTEL_BIOS_H_
+#define _INTEL_BIOS_H_
+
+#include <stdint.h>
+
+struct vbt_header {
+ char signature[20]; /**< Always starts with 'VBT$' */
+ uint16_t version; /**< decimal */
+ uint16_t header_size; /**< in bytes */
+ uint16_t vbt_size; /**< in bytes */
+ uint8_t vbt_checksum;
+ uint8_t reserved0;
+ uint32_t bdb_offset; /**< from beginning of VBT */
+ uint32_t aim_offset[4]; /**< from beginning of VBT */
+} __attribute__ ((packed));
+
+struct bdb_header {
+ char signature[16]; /**< Always 'BIOS_DATA_BLOCK' */
+ uint16_t version; /**< decimal */
+ uint16_t header_size; /**< in bytes */
+ uint16_t bdb_size; /**< in bytes */
+} __attribute__ ((packed));
+
+/*
+ * There are several types of BIOS data blocks (BDBs), each block has
+ * an ID and size in the first 3 bytes (ID in first, size in next 2).
+ * Known types are listed below.
+ */
+#define BDB_GENERAL_FEATURES 1
+#define BDB_GENERAL_DEFINITIONS 2
+#define BDB_OLD_TOGGLE_LIST 3
+#define BDB_MODE_SUPPORT_LIST 4
+#define BDB_GENERIC_MODE_TABLE 5
+#define BDB_EXT_MMIO_REGS 6
+#define BDB_SWF_IO 7
+#define BDB_SWF_MMIO 8
+#define BDB_DOT_CLOCK_TABLE 9
+#define BDB_MODE_REMOVAL_TABLE 10
+#define BDB_CHILD_DEVICE_TABLE 11
+#define BDB_DRIVER_FEATURES 12
+#define BDB_DRIVER_PERSISTENCE 13
+#define BDB_EXT_TABLE_PTRS 14
+#define BDB_DOT_CLOCK_OVERRIDE 15
+#define BDB_DISPLAY_SELECT 16
+/* 17 rsvd */
+#define BDB_DRIVER_ROTATION 18
+#define BDB_DISPLAY_REMOVE 19
+#define BDB_OEM_CUSTOM 20
+#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */
+#define BDB_SDVO_LVDS_OPTIONS 22
+#define BDB_SDVO_PANEL_DTDS 23
+#define BDB_SDVO_LVDS_PNP_IDS 24
+#define BDB_SDVO_LVDS_POWER_SEQ 25
+#define BDB_TV_OPTIONS 26
+#define BDB_EDP 27
+#define BDB_LVDS_OPTIONS 40
+#define BDB_LVDS_LFP_DATA_PTRS 41
+#define BDB_LVDS_LFP_DATA 42
+#define BDB_LVDS_BACKLIGHT 43
+#define BDB_LVDS_POWER 44
+#define BDB_SKIP 254 /* VBIOS private block, ignore */
+
+struct bdb_general_features {
+ /* bits 1 */
+ unsigned char panel_fitting:2;
+ unsigned char flexaim:1;
+ unsigned char msg_enable:1;
+ unsigned char clear_screen:3;
+ unsigned char color_flip:1;
+
+ /* bits 2 */
+ unsigned char download_ext_vbt:1;
+ unsigned char enable_ssc:1;
+ unsigned char ssc_freq:1;
+ unsigned char enable_lfp_on_override:1;
+ unsigned char disable_ssc_ddt:1;
+ unsigned char rsvd8:3; /* finish byte */
+
+ /* bits 3 */
+ unsigned char disable_smooth_vision:1;
+ unsigned char single_dvi:1;
+ unsigned char rsvd9:6; /* finish byte */
+
+ /* bits 4 */
+ unsigned char legacy_monitor_detect;
+
+ /* bits 5 */
+ unsigned char int_crt_support:1;
+ unsigned char int_tv_support:1;
+ unsigned char rsvd11:6; /* finish byte */
+} __attribute__ ((packed));
+
+#define GPIO_PIN_NONE 0x00 /* "N/A" */
+#define GPIO_PIN_I2C 0x01 /* "I2C GPIO pins" */
+#define GPIO_PIN_CRT_DDC 0x02 /* "Analog CRT DDC GPIO pins" */
+/* 915+ */
+#define GPIO_PIN_LVDS 0x03 /* "Integrated LVDS DDC GPIO pins" */
+#define GPIO_PIN_SDVO_I2C 0x05 /* "sDVO I2C GPIO pins" */
+#define GPIO_PIN_SDVO_DDC1 0x1D /* "SDVO DDC1 GPIO pins" */
+#define GPIO_PIN_SDVO_DDC2 0x2D /* "SDVO DDC2 GPIO pins" */
+/* pre-915 */
+#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */
+#define GPIO_PIN_ADD_I2C 0x05 /* "ADDCARD I2C GPIO pins" */
+#define GPIO_PIN_ADD_DDC 0x04 /* "ADDCARD DDC GPIO pins" */
+#define GPIO_PIN_ADD_DDC_I2C 0x06 /* "ADDCARD DDC/I2C GPIO pins" */
+
+/* Pre 915 */
+#define DEVICE_TYPE_NONE 0x00
+#define DEVICE_TYPE_CRT 0x01
+#define DEVICE_TYPE_TV 0x09
+#define DEVICE_TYPE_EFP 0x12
+#define DEVICE_TYPE_LFP 0x22
+/* On 915+ */
+#define DEVICE_TYPE_CRT_DPMS 0x6001
+#define DEVICE_TYPE_CRT_DPMS_HOTPLUG 0x4001
+#define DEVICE_TYPE_TV_COMPOSITE 0x0209
+#define DEVICE_TYPE_TV_MACROVISION 0x0289
+#define DEVICE_TYPE_TV_RF_COMPOSITE 0x020c
+#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE 0x0609
+#define DEVICE_TYPE_TV_SCART 0x0209
+#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
+#define DEVICE_TYPE_EFP_HOTPLUG_PWR 0x6012
+#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR 0x6052
+#define DEVICE_TYPE_EFP_DVI_I 0x6053
+#define DEVICE_TYPE_EFP_DVI_D_DUAL 0x6152
+#define DEVICE_TYPE_EFP_DVI_D_HDCP 0x60d2
+#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR 0x6062
+#define DEVICE_TYPE_OPENLDI_DUALPIX 0x6162
+#define DEVICE_TYPE_LFP_PANELLINK 0x5012
+#define DEVICE_TYPE_LFP_CMOS_PWR 0x5042
+#define DEVICE_TYPE_LFP_LVDS_PWR 0x5062
+#define DEVICE_TYPE_LFP_LVDS_DUAL 0x5162
+#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2
+#define DEVICE_TYPE_INT_HDMI 0xf0D2
+
+#define DEVICE_TYPE_INT_LFP 0x1022
+#define DEVICE_TYPE_INT_TV 0x1009
+#define DEVICE_TYPE_DP 0x68C6
+#define DEVICE_TYPE_DP_HDMI_DVI 0x60d6
+#define DEVICE_TYPE_DP_DVI 0x68d6
+#define DEVICE_TYPE_HDMI_DVI 0x60d2
+#define DEVICE_TYPE_DVI 0x68d2
+#define DEVICE_TYPE_eDP 0x78C6
+
+#define DEVICE_CFG_NONE 0x00
+#define DEVICE_CFG_12BIT_DVOB 0x01
+#define DEVICE_CFG_12BIT_DVOC 0x02
+#define DEVICE_CFG_24BIT_DVOBC 0x09
+#define DEVICE_CFG_24BIT_DVOCB 0x0a
+#define DEVICE_CFG_DUAL_DVOB 0x11
+#define DEVICE_CFG_DUAL_DVOC 0x12
+#define DEVICE_CFG_DUAL_DVOBC 0x13
+#define DEVICE_CFG_DUAL_LINK_DVOBC 0x19
+#define DEVICE_CFG_DUAL_LINK_DVOCB 0x1a
+
+#define DEVICE_WIRE_NONE 0x00
+#define DEVICE_WIRE_DVOB 0x01
+#define DEVICE_WIRE_DVOC 0x02
+#define DEVICE_WIRE_DVOBC 0x03
+#define DEVICE_WIRE_DVOBB 0x05
+#define DEVICE_WIRE_DVOCC 0x06
+#define DEVICE_WIRE_DVOB_MASTER 0x0d
+#define DEVICE_WIRE_DVOC_MASTER 0x0e
+
+#define DEVICE_PORT_DVOA 0x00 /* none on 845+ */
+#define DEVICE_PORT_DVOB 0x01
+#define DEVICE_PORT_DVOC 0x02
+
+#define DEVICE_PORT_NONE 0
+#define DEVICE_PORT_HDMIB 1
+#define DEVICE_PORT_HDMIC 2
+#define DEVICE_PORT_HDMID 3
+#define DEVICE_PORT_DPB 7
+#define DEVICE_PORT_DPC 8
+#define DEVICE_PORT_DPD 9
+
+#define DEVICE_INFO_NONE 0
+#define DEVICE_INFO_HDMI_CERT 1
+#define DEVICE_INFO_DP 2
+#define DEVICE_INFO_DVI 3
+
+struct child_device_config {
+ uint16_t handle;
+ uint16_t device_type; /* See DEVICE_TYPE_* above */
+ uint8_t device_id[10];
+ uint16_t addin_offset;
+ uint8_t dvo_port; /* See DEVICE_PORT_* above */
+ uint8_t i2c_pin;
+ uint8_t slave_addr;
+ uint8_t ddc_pin;
+ uint16_t edid_ptr;
+ uint8_t dvo_cfg; /* See DEVICE_CFG_* above */
+ uint8_t dvo2_port;
+ uint8_t i2c2_pin;
+ uint8_t slave2_addr;
+ uint8_t ddc2_pin;
+ uint8_t capabilities;
+ uint8_t dvo_wiring; /* See DEVICE_WIRE_* above */
+ uint8_t dvo2_wiring;
+ uint16_t extended_type;
+ uint8_t dvo_function;
+} __attribute__ ((packed));
+
+struct efp_child_device_config {
+ uint16_t handle;
+ uint16_t device_type;
+ uint8_t skip1[12];
+ uint8_t port;
+ uint8_t skip2[2];
+ uint8_t ddc_pin;
+ uint8_t skip3[3];
+ uint8_t docked_port;
+ uint8_t hdmi_compat:1;
+ uint8_t conn_info:3;
+ uint8_t skip4:4;
+ uint8_t aux_chan;
+ uint8_t dongle_detect;
+ uint8_t skip5[6];
+} __attribute__ ((packed));
+
+struct bdb_general_definitions {
+ unsigned char crt_ddc_gmbus_pin; /* see GPIO_PIN_* above */
+
+ /* DPMS bits */
+ unsigned char dpms_acpi:1;
+ unsigned char skip_boot_crt_detect:1;
+ unsigned char dpms_aim:1;
+ unsigned char rsvd1:5; /* finish byte */
+
+ /* boot device bits */
+ unsigned char boot_display[2];
+ unsigned char child_dev_size;
+
+ /*
+ * Device info:
+ * If TV is present, it'll be at devices[0]
+ * LVDS will be next, either devices[0] or [1], if present
+ * Max total will be 6, but could be as few as 4 if both
+ * TV and LVDS are missing, so be careful when interpreting
+ * [4] and [5].
+ */
+ struct child_device_config devices[0];
+ /* may be another device block here on some platforms */
+} __attribute__ ((packed));
+
+#define DEVICE_CHILD_SIZE 7
+
+struct bdb_child_devices {
+ uint8_t child_structure_size;
+ struct child_device_config children[DEVICE_CHILD_SIZE];
+} __attribute__ ((packed));
+
+struct bdb_lvds_options {
+ uint8_t panel_type;
+ uint8_t rsvd1;
+ /* LVDS capabilities, stored in a dword */
+ uint8_t pfit_mode:2;
+ uint8_t pfit_text_mode_enhanced:1;
+ uint8_t pfit_gfx_mode_enhanced:1;
+ uint8_t pfit_ratio_auto:1;
+ uint8_t pixel_dither:1;
+ uint8_t lvds_edid:1;
+ uint8_t rsvd2:1;
+ uint8_t rsvd4;
+} __attribute__ ((packed));
+
+/* 915+ only */
+struct bdb_tv_features {
+ /* need to verify bit ordering */
+ uint16_t under_over_scan_via_yprpb:2;
+ uint16_t rsvd1:10;
+ uint16_t under_over_scan_via_dvi:2;
+ uint16_t add_overscan_mode:1;
+ uint16_t rsvd2:1;
+} __attribute__ ((packed));
+
+struct lvds_fp_timing {
+ uint16_t x_res;
+ uint16_t y_res;
+ uint32_t lvds_reg;
+ uint32_t lvds_reg_val;
+ uint32_t pp_on_reg;
+ uint32_t pp_on_reg_val;
+ uint32_t pp_off_reg;
+ uint32_t pp_off_reg_val;
+ uint32_t pp_cycle_reg;
+ uint32_t pp_cycle_reg_val;
+ uint32_t pfit_reg;
+ uint32_t pfit_reg_val;
+ uint16_t terminator;
+} __attribute__ ((packed));
+
+struct lvds_dvo_timing {
+ uint16_t dclk; /**< In 10khz */
+ uint8_t hactive;
+ uint8_t hblank;
+ uint8_t high_h; /**< 7:4 = hactive 11:8, 3:0 = hblank 11:8 */
+ uint8_t vactive;
+ uint8_t vblank;
+ uint8_t high_v; /**< 7:4 = vactive 11:8, 3:0 = vblank 11:8 */
+ uint8_t hsync_off;
+ uint8_t hsync_pulse_width;
+ uint8_t vsync_off;
+ uint8_t high_hsync_off; /**< 7:6 = hsync off 9:8 */
+ uint8_t h_image;
+ uint8_t v_image;
+ uint8_t max_hv;
+ uint8_t h_border;
+ uint8_t v_border;
+ uint8_t flags;
+} __attribute__ ((packed));
+struct lvds_dvo_timing2 {
+ uint16_t clock; /**< In 10khz */
+ uint8_t hactive_lo;
+ uint8_t hblank_lo;
+ uint8_t hblank_hi:4;
+ uint8_t hactive_hi:4;
+ uint8_t vactive_lo;
+ uint8_t vblank_lo;
+ uint8_t vblank_hi:4;
+ uint8_t vactive_hi:4;
+ uint8_t hsync_off_lo;
+ uint8_t hsync_pulse_width;
+ uint8_t vsync_pulse_width:4;
+ uint8_t vsync_off:4;
+ uint8_t rsvd0:6;
+ uint8_t hsync_off_hi:2;
+ uint8_t h_image;
+ uint8_t v_image;
+ uint8_t max_hv;
+ uint8_t h_border;
+ uint8_t v_border;
+ uint8_t rsvd1:3;
+ uint8_t digital:2;
+ uint8_t vsync_positive:1;
+ uint8_t hsync_positive:1;
+ uint8_t rsvd2:1;
+} __attribute__((packed));
+
+struct lvds_pnp_id {
+ uint16_t mfg_name;
+ uint16_t product_code;
+ uint32_t serial;
+ uint8_t mfg_week;
+ uint8_t mfg_year;
+} __attribute__ ((packed));;
+
+/* LFP pointer table contains entries to the struct below */
+struct bdb_lvds_lfp_data_ptr {
+ uint16_t fp_timing_offset; /* offsets are from start of bdb */
+ uint8_t fp_table_size;
+ uint16_t dvo_timing_offset;
+ uint8_t dvo_table_size;
+ uint16_t panel_pnp_id_offset;
+ uint8_t pnp_table_size;
+} __attribute__ ((packed));
+
+struct bdb_lvds_lfp_data_ptrs {
+ uint8_t lvds_entries;
+ struct bdb_lvds_lfp_data_ptr ptr[16];
+} __attribute__ ((packed));
+
+struct bdb_lvds_lfp_data_entry {
+ struct lvds_fp_timing fp_timing;
+ struct lvds_dvo_timing dvo_timing;
+ struct lvds_pnp_id pnp_id;
+} __attribute__ ((packed));
+
+struct bdb_lvds_lfp_data {
+ struct bdb_lvds_lfp_data_entry data[16];
+} __attribute__ ((packed));
+
+#define BACKLIGHT_TYPE_NONE 0
+#define BACKLIGHT_TYPE_I2C 1
+#define BACKLIGHT_TYPE_PWM 2
+
+#define BACKLIGHT_GMBUS_100KHZ 0
+#define BACKLIGHT_GMBUS_50KHZ 1
+#define BACKLIGHT_GMBUS_400KHZ 2
+#define BACKLIGHT_GMBUS_1MHZ 3
+
+struct backlight_info {
+ uint8_t inverter_type:2; /* see BACKLIGHT_TYPE_* above */
+ uint8_t inverter_polarity:1; /* 1 means 0 is max, 255 is min */
+ uint8_t gpio_pins:3; /* see GPIO_PIN_* above */
+ uint8_t gmbus_speed:2;
+ uint16_t pwm_frequency; /* in Hz */
+ uint8_t min_brightness;
+ /* Next two are only for 915+ systems */
+ uint8_t i2c_addr;
+ uint8_t i2c_cmd;
+} __attribute((packed));
+
+struct bdb_backlight_control {
+ uint8_t row_size;
+ struct backlight_info lfps[16];
+} __attribute__ ((packed));
+
+struct bdb_bia {
+ uint8_t bia_enable:1;
+ uint8_t bia_level:3;
+ uint8_t rsvd1:3;
+ uint8_t als_enable:1;
+ uint8_t als_response_data[20];
+} __attribute((packed));
+
+struct aimdb_header {
+ char signature[16];
+ char oem_device[20];
+ uint16_t aimdb_version;
+ uint16_t aimdb_header_size;
+ uint16_t aimdb_size;
+} __attribute__ ((packed));
+
+struct aimdb_block {
+ uint8_t aimdb_id;
+ uint16_t aimdb_size;
+} __attribute__ ((packed));
+
+struct vch_panel_data {
+ uint16_t fp_timing_offset;
+ uint8_t fp_timing_size;
+ uint16_t dvo_timing_offset;
+ uint8_t dvo_timing_size;
+ uint16_t text_fitting_offset;
+ uint8_t text_fitting_size;
+ uint16_t graphics_fitting_offset;
+ uint8_t graphics_fitting_size;
+} __attribute__ ((packed));
+
+struct vch_bdb_22 {
+ struct aimdb_block aimdb_block;
+ struct vch_panel_data panels[16];
+} __attribute__ ((packed));
+
+#define BLC_INVERTER_TYPE_NONE 0
+#define BLC_INVERTER_TYPE_I2C 1
+#define BLC_INVERTER_TYPE_PWM 2
+
+#define BLC_GPIO_NONE 0
+#define BLC_GPIO_I2C 1
+#define BLC_GPIO_CRT_DDC 2
+#define BLC_GPIO_DVI_DDC 3
+#define BLC_GPIO_SDVO_I2C 5
+
+struct blc_struct {
+ uint8_t inverter_type:2;
+ uint8_t inverter_polarity:1; /* 1 means inverted (0 = max brightness) */
+ uint8_t gpio_pins:3;
+ uint8_t gmbus_speed:2;
+ uint16_t pwm_freq; /* in Hz */
+ uint8_t min_brightness; /* (0-255) */
+ uint8_t i2c_slave_addr;
+ uint8_t i2c_cmd;
+} __attribute__ ((packed));
+
+struct bdb_lvds_backlight {
+ uint8_t blcstruct_size;
+ struct blc_struct panels[16];
+} __attribute__ ((packed));
+
+struct bdb_lvds_power {
+ uint8_t dpst_enabled:1;
+ uint8_t pwr_prefs:3;
+ uint8_t rsvd1:3;
+ uint8_t als_enabled:1;
+ uint16_t als_backlight1;
+ uint16_t als_backlight2;
+ uint16_t als_backlight3;
+ uint16_t als_backlight4;
+ uint16_t als_backlight5;
+} __attribute__ ((packed));
+
+#define BDB_DRIVER_NO_LVDS 0
+#define BDB_DRIVER_INT_LVDS 1
+#define BDB_DRIVER_SDVO_LVDS 2
+#define BDB_DRIVER_EDP 3
+
+struct bdb_driver_feature {
+ uint8_t boot_dev_algorithm:1;
+ uint8_t block_display_switch:1;
+ uint8_t allow_display_switch:1;
+ uint8_t hotplug_dvo:1;
+ uint8_t dual_view_zoom:1;
+ uint8_t int15h_hook:1;
+ uint8_t sprite_in_clone:1;
+ uint8_t primary_lfp_id:1;
+
+ uint16_t boot_mode_x;
+ uint16_t boot_mode_y;
+ uint8_t boot_mode_bpp;
+ uint8_t boot_mode_refresh;
+
+ uint16_t enable_lfp_primary:1;
+ uint16_t selective_mode_pruning:1;
+ uint16_t dual_frequency:1;
+ uint16_t render_clock_freq:1; /* 0: high freq; 1: low freq */
+ uint16_t nt_clone_support:1;
+ uint16_t power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
+ uint16_t sprite_display_assign:1; /* 0: secondary; 1: primary */
+ uint16_t cui_aspect_scaling:1;
+ uint16_t preserve_aspect_ratio:1;
+ uint16_t sdvo_device_power_down:1;
+ uint16_t crt_hotplug:1;
+ uint16_t lvds_config:2;
+ uint16_t reserved:3;
+
+ uint8_t static_display:1;
+ uint8_t reserved2:7;
+ uint16_t legacy_crt_max_x;
+ uint16_t legacy_crt_max_y;
+ uint8_t legacy_crt_max_refresh;
+} __attribute__ ((packed));
+
+struct bdb_sdvo_lvds_options {
+ uint8_t panel_backlight;
+ uint8_t h40_set_panel_type;
+ uint8_t panel_type;
+ uint8_t ssc_clk_freq;
+ uint16_t als_low_trip;
+ uint16_t als_high_trip;
+ uint8_t sclalarcoeff_tab_row_num;
+ uint8_t sclalarcoeff_tab_row_size;
+ uint8_t coefficient[8];
+ uint8_t panel_misc_bits_1;
+ uint8_t panel_misc_bits_2;
+ uint8_t panel_misc_bits_3;
+ uint8_t panel_misc_bits_4;
+} __attribute__ ((packed));
+
+#define EDP_18BPP 0
+#define EDP_24BPP 1
+#define EDP_30BPP 2
+#define EDP_RATE_1_62 0
+#define EDP_RATE_2_7 1
+#define EDP_LANE_1 0
+#define EDP_LANE_2 1
+#define EDP_LANE_4 3
+#define EDP_PREEMPHASIS_NONE 0
+#define EDP_PREEMPHASIS_3_5dB 1
+#define EDP_PREEMPHASIS_6dB 2
+#define EDP_PREEMPHASIS_9_5dB 3
+#define EDP_VSWING_0_4V 0
+#define EDP_VSWING_0_6V 1
+#define EDP_VSWING_0_8V 2
+#define EDP_VSWING_1_2V 3
+
+struct edp_power_seq {
+ uint16_t t3;
+ uint16_t t7;
+ uint16_t t9;
+ uint16_t t10;
+ uint16_t t12;
+} __attribute__ ((packed));
+
+struct edp_link_params {
+ uint8_t rate:4;
+ uint8_t lanes:4;
+ uint8_t preemphasis:4;
+ uint8_t vswing:4;
+} __attribute__ ((packed));
+
+struct bdb_edp {
+ struct edp_power_seq power_seqs[16];
+ uint32_t color_depth;
+ uint32_t sdrrs_msa_timing_delay;
+ struct edp_link_params link_params[16];
+} __attribute__ ((packed));
+
+/*
+ * Driver<->VBIOS interaction occurs through scratch bits in
+ * GR18 & SWF*.
+ *
+ * The VBIOS/firmware will signal to the gfx driver through the ASLE interrupt
+ * (visible in the interupt regs at bit 0) when it wants something done.
+ *
+ * Pre-965:
+ * The gfx driver can make calls to the VBIOS/firmware through an SMI request,
+ * generated by writing to offset 0xe0 of the device's config space (see the
+ * publically available 915 PRM for details).
+ *
+ * 965 and above:
+ * IGD OpRegion requests to the VBIOS/firmware are made using SWSCI, which can
+ * be triggered by writing to offset 0xe4 (see the publically available
+ * 965 graphics PRM for details).
+ */
+
+/* GR18 bits are set on display switch and hotkey events */
+#define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */
+#define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */
+#define GR18_HK_NONE (0x0<<3)
+#define GR18_HK_LFP_STRETCH (0x1<<3)
+#define GR18_HK_TOGGLE_DISP (0x2<<3)
+#define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */
+#define GR18_HK_POPUP_DISABLED (0x6<<3)
+#define GR18_HK_POPUP_ENABLED (0x7<<3)
+#define GR18_HK_PFIT (0x8<<3)
+#define GR18_HK_APM_CHANGE (0xa<<3)
+#define GR18_HK_MULTIPLE (0xc<<3)
+#define GR18_USER_INT_EN (1<<2)
+#define GR18_A0000_FLUSH_EN (1<<1)
+#define GR18_SMM_EN (1<<0)
+
+/* Set by driver, cleared by VBIOS */
+#define SWF00_YRES_SHIFT 16
+#define SWF00_XRES_SHIFT 0
+#define SWF00_RES_MASK 0xffff
+
+/* Set by VBIOS at boot time and driver at runtime */
+#define SWF01_TV2_FORMAT_SHIFT 8
+#define SWF01_TV1_FORMAT_SHIFT 0
+#define SWF01_TV_FORMAT_MASK 0xffff
+
+#define SWF10_VBIOS_BLC_I2C_EN (1<<29)
+#define SWF10_GTT_OVERRIDE_EN (1<<28)
+#define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */
+#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
+#define SWF10_OLD_TOGGLE 0x0
+#define SWF10_TOGGLE_LIST_1 0x1
+#define SWF10_TOGGLE_LIST_2 0x2
+#define SWF10_TOGGLE_LIST_3 0x3
+#define SWF10_TOGGLE_LIST_4 0x4
+#define SWF10_PANNING_EN (1<<23)
+#define SWF10_DRIVER_LOADED (1<<22)
+#define SWF10_EXTENDED_DESKTOP (1<<21)
+#define SWF10_EXCLUSIVE_MODE (1<<20)
+#define SWF10_OVERLAY_EN (1<<19)
+#define SWF10_PLANEB_HOLDOFF (1<<18)
+#define SWF10_PLANEA_HOLDOFF (1<<17)
+#define SWF10_VGA_HOLDOFF (1<<16)
+#define SWF10_ACTIVE_DISP_MASK 0xffff
+#define SWF10_PIPEB_LFP2 (1<<15)
+#define SWF10_PIPEB_EFP2 (1<<14)
+#define SWF10_PIPEB_TV2 (1<<13)
+#define SWF10_PIPEB_CRT2 (1<<12)
+#define SWF10_PIPEB_LFP (1<<11)
+#define SWF10_PIPEB_EFP (1<<10)
+#define SWF10_PIPEB_TV (1<<9)
+#define SWF10_PIPEB_CRT (1<<8)
+#define SWF10_PIPEA_LFP2 (1<<7)
+#define SWF10_PIPEA_EFP2 (1<<6)
+#define SWF10_PIPEA_TV2 (1<<5)
+#define SWF10_PIPEA_CRT2 (1<<4)
+#define SWF10_PIPEA_LFP (1<<3)
+#define SWF10_PIPEA_EFP (1<<2)
+#define SWF10_PIPEA_TV (1<<1)
+#define SWF10_PIPEA_CRT (1<<0)
+
+#define SWF11_MEMORY_SIZE_SHIFT 16
+#define SWF11_SV_TEST_EN (1<<15)
+#define SWF11_IS_AGP (1<<14)
+#define SWF11_DISPLAY_HOLDOFF (1<<13)
+#define SWF11_DPMS_REDUCED (1<<12)
+#define SWF11_IS_VBE_MODE (1<<11)
+#define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */
+#define SWF11_DPMS_MASK 0x07
+#define SWF11_DPMS_OFF (1<<2)
+#define SWF11_DPMS_SUSPEND (1<<1)
+#define SWF11_DPMS_STANDBY (1<<0)
+#define SWF11_DPMS_ON 0
+
+#define SWF14_GFX_PFIT_EN (1<<31)
+#define SWF14_TEXT_PFIT_EN (1<<30)
+#define SWF14_LID_SWITCH_EN (1<<29)
+#define SWF14_POPUP_EN (1<<28)
+#define SWF14_DISPLAY_HOLDOFF (1<<27)
+#define SWF14_DISP_DETECT_EN (1<<26)
+#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
+#define SWF14_DRIVER_STATUS (1<<24)
+#define SWF14_OS_TYPE_WIN9X (1<<23)
+#define SWF14_OS_TYPE_WINNT (1<<22)
+/* 21:19 rsvd */
+#define SWF14_PM_TYPE_MASK 0x00070000
+#define SWF14_PM_ACPI_VIDEO (0x4 << 16)
+#define SWF14_PM_ACPI (0x3 << 16)
+#define SWF14_PM_APM_12 (0x2 << 16)
+#define SWF14_PM_APM_11 (0x1 << 16)
+#define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */
+ /* if GR18 indicates a display switch */
+#define SWF14_DS_PIPEB_LFP2_EN (1<<15)
+#define SWF14_DS_PIPEB_EFP2_EN (1<<14)
+#define SWF14_DS_PIPEB_TV2_EN (1<<13)
+#define SWF14_DS_PIPEB_CRT2_EN (1<<12)
+#define SWF14_DS_PIPEB_LFP_EN (1<<11)
+#define SWF14_DS_PIPEB_EFP_EN (1<<10)
+#define SWF14_DS_PIPEB_TV_EN (1<<9)
+#define SWF14_DS_PIPEB_CRT_EN (1<<8)
+#define SWF14_DS_PIPEA_LFP2_EN (1<<7)
+#define SWF14_DS_PIPEA_EFP2_EN (1<<6)
+#define SWF14_DS_PIPEA_TV2_EN (1<<5)
+#define SWF14_DS_PIPEA_CRT2_EN (1<<4)
+#define SWF14_DS_PIPEA_LFP_EN (1<<3)
+#define SWF14_DS_PIPEA_EFP_EN (1<<2)
+#define SWF14_DS_PIPEA_TV_EN (1<<1)
+#define SWF14_DS_PIPEA_CRT_EN (1<<0)
+ /* if GR18 indicates a panel fitting request */
+#define SWF14_PFIT_EN (1<<0) /* 0 means disable */
+ /* if GR18 indicates an APM change request */
+#define SWF14_APM_HIBERNATE 0x4
+#define SWF14_APM_SUSPEND 0x3
+#define SWF14_APM_STANDBY 0x1
+#define SWF14_APM_RESTORE 0x0
+
+#endif /* _INTEL_BIOS_H_ */
diff --git a/tools/intel_bios_dumper.c b/tools/intel_bios_dumper.c
new file mode 100644
index 00000000..6455689f
--- /dev/null
+++ b/tools/intel_bios_dumper.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pciaccess.h>
+#include <err.h>
+
+#ifndef DEFFILEMODE
+#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) /* 0666 */
+#endif
+
+static void usage(void)
+{
+ fprintf(stderr, "usage: bios_dumper <filename>\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ struct pci_device *dev;
+ void *bios;
+ int error, fd;
+
+ if (argc != 2)
+ usage();
+
+ error = pci_system_init();
+ if (error != 0) {
+ fprintf(stderr, "Couldn't initialize PCI system: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ /* Grab the graphics card */
+ dev = pci_device_find_by_slot(0, 0, 2, 0);
+ if (dev == NULL)
+ errx(1, "Couldn't find graphics card");
+
+ error = pci_device_probe(dev);
+ if (error != 0) {
+ fprintf(stderr, "Couldn't probe graphics card: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ if (dev->vendor_id != 0x8086)
+ errx(1, "Graphics card is non-intel");
+
+ /* Some versions of libpciaccess correct this automatically, but some
+ * don't. */
+ if (dev->rom_size == 0)
+ dev->rom_size = 64 * 1024;
+
+ bios = malloc(dev->rom_size);
+ if (bios == NULL)
+ errx(1, "Couldn't allocate memory for BIOS data\n");
+
+ error = pci_device_read_rom(dev, bios);
+ if (error != 0) {
+ fprintf(stderr, "Couldn't read graphics card ROM: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+ if (fd < 0) {
+ fprintf(stderr, "Couldn't open output: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ if (write(fd, bios, dev->rom_size) < dev->rom_size) {
+ fprintf(stderr, "Couldn't write BIOS data: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ close(fd);
+ pci_system_cleanup();
+
+ return 0;
+}
diff --git a/tools/intel_bios_reader.c b/tools/intel_bios_reader.c
new file mode 100644
index 00000000..493fb637
--- /dev/null
+++ b/tools/intel_bios_reader.c
@@ -0,0 +1,947 @@
+/*
+ * Copyright 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "intel_bios.h"
+#include "intel_gpu_tools.h"
+
+static uint32_t devid = -1;
+
+/* no bother to include "edid.h" */
+#define _H_ACTIVE(x) (x[2] + ((x[4] & 0xF0) << 4))
+#define _H_SYNC_OFF(x) (x[8] + ((x[11] & 0xC0) << 2))
+#define _H_SYNC_WIDTH(x) (x[9] + ((x[11] & 0x30) << 4))
+#define _H_BLANK(x) (x[3] + ((x[4] & 0x0F) << 8))
+#define _V_ACTIVE(x) (x[5] + ((x[7] & 0xF0) << 4))
+#define _V_SYNC_OFF(x) ((x[10] >> 4) + ((x[11] & 0x0C) << 2))
+#define _V_SYNC_WIDTH(x) ((x[10] & 0x0F) + ((x[11] & 0x03) << 4))
+#define _V_BLANK(x) (x[6] + ((x[7] & 0x0F) << 8))
+#define _PIXEL_CLOCK(x) (x[0] + (x[1] << 8)) * 10000
+
+uint8_t *VBIOS;
+
+#define INTEL_BIOS_8(_addr) (VBIOS[_addr])
+#define INTEL_BIOS_16(_addr) (VBIOS[_addr] | \
+ (VBIOS[_addr + 1] << 8))
+#define INTEL_BIOS_32(_addr) (VBIOS[_addr] | \
+ (VBIOS[_addr + 1] << 8) | \
+ (VBIOS[_addr + 2] << 16) | \
+ (VBIOS[_addr + 3] << 24))
+
+#define YESNO(val) ((val) ? "yes" : "no")
+
+struct bdb_block {
+ uint8_t id;
+ uint16_t size;
+ void *data;
+};
+
+struct bdb_header *bdb;
+static int tv_present;
+static int lvds_present;
+static int panel_type;
+
+static struct bdb_block *find_section(int section_id, int length)
+{
+ struct bdb_block *block;
+ unsigned char *base = (unsigned char *)bdb;
+ int idx = 0;
+ uint16_t total, current_size;
+ unsigned char current_id;
+
+ /* skip to first section */
+ idx += bdb->header_size;
+ total = bdb->bdb_size;
+ if (total > length)
+ total = length;
+
+ block = malloc(sizeof(*block));
+ if (!block) {
+ fprintf(stderr, "out of memory\n");
+ exit(-1);
+ }
+
+ /* walk the sections looking for section_id */
+ while (idx + 3 < total) {
+ current_id = *(base + idx);
+ current_size = *(uint16_t *)(base + idx + 1);
+ if (idx + current_size > total)
+ return NULL;
+
+ if (current_id == section_id) {
+ block->id = current_id;
+ block->size = current_size;
+ block->data = base + idx + 3;
+ return block;
+ }
+
+ idx += current_size + 3;
+ }
+
+ free(block);
+ return NULL;
+}
+
+static void dump_general_features(int length)
+{
+ struct bdb_general_features *features;
+ struct bdb_block *block;
+
+ block = find_section(BDB_GENERAL_FEATURES, length);
+
+ if (!block)
+ return;
+
+ features = block->data;
+
+ printf("General features block:\n");
+
+ printf("\tPanel fitting: ");
+ switch (features->panel_fitting) {
+ case 0:
+ printf("disabled\n");
+ break;
+ case 1:
+ printf("text only\n");
+ break;
+ case 2:
+ printf("graphics only\n");
+ break;
+ case 3:
+ printf("text & graphics\n");
+ break;
+ }
+ printf("\tFlexaim: %s\n", YESNO(features->flexaim));
+ printf("\tMessage: %s\n", YESNO(features->msg_enable));
+ printf("\tClear screen: %d\n", features->clear_screen);
+ printf("\tDVO color flip required: %s\n", YESNO(features->color_flip));
+ printf("\tExternal VBT: %s\n", YESNO(features->download_ext_vbt));
+ printf("\tEnable SSC: %s\n", YESNO(features->enable_ssc));
+ if (features->enable_ssc) {
+ if (HAS_PCH_SPLIT(devid))
+ printf("\tSSC frequency: %s\n", features->ssc_freq ?
+ "100 MHz" : "120 MHz");
+ else
+ printf("\tSSC frequency: %s\n", features->ssc_freq ?
+ "100 MHz (66 MHz on 855)" : "96 MHz (48 MHz on 855)");
+ }
+ printf("\tLFP on override: %s\n",
+ YESNO(features->enable_lfp_on_override));
+ printf("\tDisable SSC on clone: %s\n",
+ YESNO(features->disable_ssc_ddt));
+ printf("\tDisable smooth vision: %s\n",
+ YESNO(features->disable_smooth_vision));
+ printf("\tSingle DVI for CRT/DVI: %s\n", YESNO(features->single_dvi));
+ printf("\tLegacy monitor detect: %s\n",
+ YESNO(features->legacy_monitor_detect));
+ printf("\tIntegrated CRT: %s\n", YESNO(features->int_crt_support));
+ printf("\tIntegrated TV: %s\n", YESNO(features->int_tv_support));
+
+ tv_present = 1; /* should be based on whether TV DAC exists */
+ lvds_present = 1; /* should be based on IS_MOBILE() */
+
+ free(block);
+}
+
+static void dump_backlight_info(int length)
+{
+ struct bdb_block *block;
+ struct bdb_lvds_backlight *backlight;
+ struct blc_struct *blc;
+
+ block = find_section(BDB_LVDS_BACKLIGHT, length);
+
+ if (!block)
+ return;
+
+ backlight = block->data;
+
+ printf("Backlight info block (len %d):\n", block->size);
+
+ if (sizeof(struct blc_struct) != backlight->blcstruct_size) {
+ printf("\tBacklight struct sizes don't match (expected %zu, got %u), skipping\n",
+ sizeof(struct blc_struct), backlight->blcstruct_size);
+ return;
+ }
+
+ blc = &backlight->panels[panel_type];
+
+ printf("\tInverter type: %d\n", blc->inverter_type);
+ printf("\t polarity: %d\n", blc->inverter_polarity);
+ printf("\t GPIO pins: %d\n", blc->gpio_pins);
+ printf("\t GMBUS speed: %d\n", blc->gmbus_speed);
+ printf("\t PWM freq: %d\n", blc->pwm_freq);
+ printf("\tMinimum brightness: %d\n", blc->min_brightness);
+ printf("\tI2C slave addr: 0x%02x\n", blc->i2c_slave_addr);
+ printf("\tI2C command: 0x%02x\n", blc->i2c_cmd);
+}
+
+static const struct {
+ unsigned short type;
+ const char *name;
+} child_device_types[] = {
+ { DEVICE_TYPE_NONE, "none" },
+ { DEVICE_TYPE_CRT, "CRT" },
+ { DEVICE_TYPE_TV, "TV" },
+ { DEVICE_TYPE_EFP, "EFP" },
+ { DEVICE_TYPE_LFP, "LFP" },
+ { DEVICE_TYPE_CRT_DPMS, "CRT" },
+ { DEVICE_TYPE_CRT_DPMS_HOTPLUG, "CRT" },
+ { DEVICE_TYPE_TV_COMPOSITE, "TV composite" },
+ { DEVICE_TYPE_TV_MACROVISION, "TV" },
+ { DEVICE_TYPE_TV_RF_COMPOSITE, "TV" },
+ { DEVICE_TYPE_TV_SVIDEO_COMPOSITE, "TV S-Video" },
+ { DEVICE_TYPE_TV_SCART, "TV SCART" },
+ { DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR, "TV" },
+ { DEVICE_TYPE_EFP_HOTPLUG_PWR, "EFP" },
+ { DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR, "DVI" },
+ { DEVICE_TYPE_EFP_DVI_I, "DVI-I" },
+ { DEVICE_TYPE_EFP_DVI_D_DUAL, "DL-DVI-D" },
+ { DEVICE_TYPE_EFP_DVI_D_HDCP, "DVI-D" },
+ { DEVICE_TYPE_OPENLDI_HOTPLUG_PWR, "OpenLDI" },
+ { DEVICE_TYPE_OPENLDI_DUALPIX, "OpenLDI" },
+ { DEVICE_TYPE_LFP_PANELLINK, "PanelLink" },
+ { DEVICE_TYPE_LFP_CMOS_PWR, "CMOS LFP" },
+ { DEVICE_TYPE_LFP_LVDS_PWR, "LVDS" },
+ { DEVICE_TYPE_LFP_LVDS_DUAL, "LVDS" },
+ { DEVICE_TYPE_LFP_LVDS_DUAL_HDCP, "LVDS" },
+ { DEVICE_TYPE_INT_LFP, "LFP" },
+ { DEVICE_TYPE_INT_TV, "TV" },
+ { DEVICE_TYPE_DP, "DisplayPort" },
+ { DEVICE_TYPE_DP_HDMI_DVI, "DisplayPort/HDMI/DVI" },
+ { DEVICE_TYPE_DP_DVI, "DisplayPort/DVI" },
+ { DEVICE_TYPE_HDMI_DVI, "HDMI/DVI" },
+ { DEVICE_TYPE_DVI, "DVI" },
+ { DEVICE_TYPE_eDP, "eDP" },
+};
+static const int num_child_device_types =
+ sizeof(child_device_types) / sizeof(child_device_types[0]);
+
+static const char *child_device_type(unsigned short type)
+{
+ int i;
+
+ for (i = 0; i < num_child_device_types; i++)
+ if (child_device_types[i].type == type)
+ return child_device_types[i].name;
+
+ return "unknown";
+}
+
+static const struct {
+ unsigned short type;
+ const char *name;
+} efp_ports[] = {
+ { DEVICE_PORT_NONE, "N/A" },
+ { DEVICE_PORT_HDMIB, "HDMI-B" },
+ { DEVICE_PORT_HDMIC, "HDMI-C" },
+ { DEVICE_PORT_HDMID, "HDMI-D" },
+ { DEVICE_PORT_DPB, "DP-B" },
+ { DEVICE_PORT_DPC, "DP-C" },
+ { DEVICE_PORT_DPD, "DP-D" },
+};
+static const int num_efp_ports = sizeof(efp_ports) / sizeof(efp_ports[0]);
+
+static const char *efp_port(uint8_t type)
+{
+ int i;
+
+ for (i = 0; i < num_efp_ports; i++)
+ if (efp_ports[i].type == type)
+ return efp_ports[i].name;
+
+ return "unknown";
+}
+
+static const struct {
+ unsigned short type;
+ const char *name;
+} efp_conn_info[] = {
+ { DEVICE_INFO_NONE, "N/A" },
+ { DEVICE_INFO_HDMI_CERT, "HDMI certified" },
+ { DEVICE_INFO_DP, "DisplayPort" },
+ { DEVICE_INFO_DVI, "DVI" },
+};
+static const int num_efp_conn_info = sizeof(efp_conn_info) / sizeof(efp_conn_info[0]);
+
+static const char *efp_conn(uint8_t type)
+{
+ int i;
+
+ for (i = 0; i < num_efp_conn_info; i++)
+ if (efp_conn_info[i].type == type)
+ return efp_conn_info[i].name;
+
+ return "unknown";
+}
+
+
+
+static void dump_child_device(struct child_device_config *child)
+{
+ char child_id[11];
+
+ if (!child->device_type)
+ return;
+
+ if (bdb->version < 152) {
+ strncpy(child_id, (char *)child->device_id, 10);
+ child_id[10] = 0;
+
+ printf("\tChild device info:\n");
+ printf("\t\tDevice type: %04x (%s)\n", child->device_type,
+ child_device_type(child->device_type));
+ printf("\t\tSignature: %s\n", child_id);
+ printf("\t\tAIM offset: %d\n", child->addin_offset);
+ printf("\t\tDVO port: 0x%02x\n", child->dvo_port);
+ } else { /* 152+ have EFP blocks here */
+ struct efp_child_device_config *efp =
+ (struct efp_child_device_config *)child;
+ printf("\tEFP device info:\n");
+ printf("\t\tDevice type: 0x%04x (%s)\n", efp->device_type,
+ child_device_type(efp->device_type));
+ printf("\t\tPort: 0x%02x (%s)\n", efp->port,
+ efp_port(efp->port));
+ printf("\t\tDDC pin: 0x%02x\n", efp->ddc_pin);
+ printf("\t\tDock port: 0x%02x (%s)\n", efp->docked_port,
+ efp_port(efp->docked_port));
+ printf("\t\tHDMI compatible? %s\n", efp->hdmi_compat ? "Yes" : "No");
+ printf("\t\tInfo: %s\n", efp_conn(efp->conn_info));
+ printf("\t\tAux channel: 0x%02x\n", efp->aux_chan);
+ printf("\t\tDongle detect: 0x%02x\n", efp->dongle_detect);
+ }
+}
+
+static void dump_general_definitions(int length)
+{
+ struct bdb_block *block;
+ struct bdb_general_definitions *defs;
+ struct child_device_config *child;
+ int i;
+ int child_device_num;
+
+ block = find_section(BDB_GENERAL_DEFINITIONS, length);
+
+ if (!block)
+ return;
+
+ defs = block->data;
+
+ printf("General definitions block:\n");
+
+ printf("\tCRT DDC GMBUS addr: 0x%02x\n", defs->crt_ddc_gmbus_pin);
+ printf("\tUse ACPI DPMS CRT power states: %s\n",
+ YESNO(defs->dpms_acpi));
+ printf("\tSkip CRT detect at boot: %s\n",
+ YESNO(defs->skip_boot_crt_detect));
+ printf("\tUse DPMS on AIM devices: %s\n", YESNO(defs->dpms_aim));
+ printf("\tBoot display type: 0x%02x%02x\n", defs->boot_display[1],
+ defs->boot_display[0]);
+ printf("\tTV data block present: %s\n", YESNO(tv_present));
+ child_device_num = (block->size - sizeof(*defs)) / sizeof(*child);
+ for (i = 0; i < child_device_num; i++)
+ dump_child_device(&defs->devices[i]);
+ free(block);
+}
+
+static void dump_child_devices(int length)
+{
+ struct bdb_block *block;
+ struct bdb_child_devices *child_devs;
+ struct child_device_config *child;
+ int i;
+
+ block = find_section(BDB_CHILD_DEVICE_TABLE, length);
+ if (!block) {
+ printf("No child device table found\n");
+ return;
+ }
+
+ child_devs = block->data;
+
+ printf("Child devices block:\n");
+ for (i = 0; i < DEVICE_CHILD_SIZE; i++) {
+ child = &child_devs->children[i];
+ /* Skip nonexistent children */
+ if (!child->device_type)
+ continue;
+ printf("\tChild device %d\n", i);
+ printf("\t\tType: 0x%04x (%s)\n", child->device_type,
+ child_device_type(child->device_type));
+ printf("\t\tDVO port: 0x%02x\n", child->dvo_port);
+ printf("\t\tI2C pin: 0x%02x\n", child->i2c_pin);
+ printf("\t\tSlave addr: 0x%02x\n", child->slave_addr);
+ printf("\t\tDDC pin: 0x%02x\n", child->ddc_pin);
+ printf("\t\tDVO config: 0x%02x\n", child->dvo_cfg);
+ printf("\t\tDVO wiring: 0x%02x\n", child->dvo_wiring);
+ }
+
+ free(block);
+}
+
+static void dump_lvds_options(int length)
+{
+ struct bdb_block *block;
+ struct bdb_lvds_options *options;
+
+ block = find_section(BDB_LVDS_OPTIONS, length);
+ if (!block) {
+ printf("No LVDS options block\n");
+ return;
+ }
+
+ options = block->data;
+
+ printf("LVDS options block:\n");
+
+ panel_type = options->panel_type;
+ printf("\tPanel type: %d\n", panel_type);
+ printf("\tLVDS EDID available: %s\n", YESNO(options->lvds_edid));
+ printf("\tPixel dither: %s\n", YESNO(options->pixel_dither));
+ printf("\tPFIT auto ratio: %s\n", YESNO(options->pfit_ratio_auto));
+ printf("\tPFIT enhanced graphics mode: %s\n",
+ YESNO(options->pfit_gfx_mode_enhanced));
+ printf("\tPFIT enhanced text mode: %s\n",
+ YESNO(options->pfit_text_mode_enhanced));
+ printf("\tPFIT mode: %d\n", options->pfit_mode);
+
+ free(block);
+}
+
+static void dump_lvds_ptr_data(int length)
+{
+ struct bdb_block *block;
+ struct bdb_lvds_lfp_data *lvds_data;
+ struct bdb_lvds_lfp_data_ptrs *ptrs;
+ struct lvds_fp_timing *fp_timing;
+ struct bdb_lvds_lfp_data_entry *entry;
+ int lfp_data_size;
+
+ block = find_section(BDB_LVDS_LFP_DATA_PTRS, length);
+ if (!block) {
+ printf("No LFP data pointers block\n");
+ return;
+ }
+ ptrs = block->data;
+
+ block = find_section(BDB_LVDS_LFP_DATA, length);
+ if (!block) {
+ printf("No LVDS data block\n");
+ return;
+ }
+ lvds_data = block->data;
+
+ lfp_data_size =
+ ptrs->ptr[1].fp_timing_offset - ptrs->ptr[0].fp_timing_offset;
+ entry =
+ (struct bdb_lvds_lfp_data_entry *)((uint8_t *) lvds_data->data +
+ (lfp_data_size * panel_type));
+ fp_timing = &entry->fp_timing;
+
+ printf("LVDS timing pointer data:\n");
+ printf(" Number of entries: %d\n", ptrs->lvds_entries);
+
+ printf("\tpanel type %02i: %dx%d\n", panel_type, fp_timing->x_res,
+ fp_timing->y_res);
+
+ free(block);
+}
+
+static void dump_lvds_data(int length)
+{
+ struct bdb_block *block;
+ struct bdb_lvds_lfp_data *lvds_data;
+ struct bdb_lvds_lfp_data_ptrs *ptrs;
+ int num_entries;
+ int i;
+ int hdisplay, hsyncstart, hsyncend, htotal;
+ int vdisplay, vsyncstart, vsyncend, vtotal;
+ float clock;
+ int lfp_data_size, dvo_offset;
+
+ block = find_section(BDB_LVDS_LFP_DATA_PTRS, length);
+ if (!block) {
+ printf("No LVDS ptr block\n");
+ return;
+ }
+ ptrs = block->data;
+ lfp_data_size =
+ ptrs->ptr[1].fp_timing_offset - ptrs->ptr[0].fp_timing_offset;
+ dvo_offset =
+ ptrs->ptr[0].dvo_timing_offset - ptrs->ptr[0].fp_timing_offset;
+ free(block);
+
+ block = find_section(BDB_LVDS_LFP_DATA, length);
+ if (!block) {
+ printf("No LVDS data block\n");
+ return;
+ }
+
+ lvds_data = block->data;
+ num_entries = block->size / lfp_data_size;
+
+ printf("LVDS panel data block (preferred block marked with '*'):\n");
+ printf(" Number of entries: %d\n", num_entries);
+
+ for (i = 0; i < num_entries; i++) {
+ uint8_t *lfp_data_ptr =
+ (uint8_t *) lvds_data->data + lfp_data_size * i;
+ uint8_t *timing_data = lfp_data_ptr + dvo_offset;
+ struct bdb_lvds_lfp_data_entry *lfp_data =
+ (struct bdb_lvds_lfp_data_entry *)lfp_data_ptr;
+ char marker;
+
+ if (i == panel_type)
+ marker = '*';
+ else
+ marker = ' ';
+
+ hdisplay = _H_ACTIVE(timing_data);
+ hsyncstart = hdisplay + _H_SYNC_OFF(timing_data);
+ hsyncend = hsyncstart + _H_SYNC_WIDTH(timing_data);
+ htotal = hdisplay + _H_BLANK(timing_data);
+
+ vdisplay = _V_ACTIVE(timing_data);
+ vsyncstart = vdisplay + _V_SYNC_OFF(timing_data);
+ vsyncend = vsyncstart + _V_SYNC_WIDTH(timing_data);
+ vtotal = vdisplay + _V_BLANK(timing_data);
+ clock = _PIXEL_CLOCK(timing_data) / 1000;
+
+ printf("%c\tpanel type %02i: %dx%d clock %d\n", marker,
+ i, lfp_data->fp_timing.x_res, lfp_data->fp_timing.y_res,
+ _PIXEL_CLOCK(timing_data));
+ printf("\t\tinfo:\n");
+ printf("\t\t LVDS: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.lvds_reg_val);
+ printf("\t\t PP_ON_DELAYS: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.pp_on_reg_val);
+ printf("\t\t PP_OFF_DELAYS: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.pp_off_reg_val);
+ printf("\t\t PP_DIVISOR: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.pp_cycle_reg_val);
+ printf("\t\t PFIT: 0x%08lx\n",
+ (unsigned long)lfp_data->fp_timing.pfit_reg_val);
+ printf("\t\ttimings: %d %d %d %d %d %d %d %d %.2f (%s)\n",
+ hdisplay, hsyncstart, hsyncend, htotal,
+ vdisplay, vsyncstart, vsyncend, vtotal, clock,
+ (hsyncend > htotal || vsyncend > vtotal) ?
+ "BAD!" : "good");
+ }
+ free(block);
+}
+
+static void dump_driver_feature(int length)
+{
+ struct bdb_block *block;
+ struct bdb_driver_feature *feature;
+
+ block = find_section(BDB_DRIVER_FEATURES, length);
+ if (!block) {
+ printf("No Driver feature data block\n");
+ return;
+ }
+ feature = block->data;
+
+ printf("Driver feature Data Block:\n");
+ printf("\tBoot Device Algorithm: %s\n", feature->boot_dev_algorithm ?
+ "driver default" : "os default");
+ printf("\tBlock display switching when DVD active: %s\n",
+ YESNO(feature->block_display_switch));
+ printf("\tAllow display switching when in Full Screen DOS: %s\n",
+ YESNO(feature->allow_display_switch));
+ printf("\tHot Plug DVO: %s\n", YESNO(feature->hotplug_dvo));
+ printf("\tDual View Zoom: %s\n", YESNO(feature->dual_view_zoom));
+ printf("\tDriver INT 15h hook: %s\n", YESNO(feature->int15h_hook));
+ printf("\tEnable Sprite in Clone Mode: %s\n",
+ YESNO(feature->sprite_in_clone));
+ printf("\tUse 00000110h ID for Primary LFP: %s\n",
+ YESNO(feature->primary_lfp_id));
+ printf("\tBoot Mode X: %u\n", feature->boot_mode_x);
+ printf("\tBoot Mode Y: %u\n", feature->boot_mode_y);
+ printf("\tBoot Mode Bpp: %u\n", feature->boot_mode_bpp);
+ printf("\tBoot Mode Refresh: %u\n", feature->boot_mode_refresh);
+ printf("\tEnable LFP as primary: %s\n",
+ YESNO(feature->enable_lfp_primary));
+ printf("\tSelective Mode Pruning: %s\n",
+ YESNO(feature->selective_mode_pruning));
+ printf("\tDual-Frequency Graphics Technology: %s\n",
+ YESNO(feature->dual_frequency));
+ printf("\tDefault Render Clock Frequency: %s\n",
+ feature->render_clock_freq ? "low" : "high");
+ printf("\tNT 4.0 Dual Display Clone Support: %s\n",
+ YESNO(feature->nt_clone_support));
+ printf("\tDefault Power Scheme user interface: %s\n",
+ feature->power_scheme_ui ? "3rd party" : "CUI");
+ printf
+ ("\tSprite Display Assignment when Overlay is Active in Clone Mode: %s\n",
+ feature->sprite_display_assign ? "primary" : "secondary");
+ printf("\tDisplay Maintain Aspect Scaling via CUI: %s\n",
+ YESNO(feature->cui_aspect_scaling));
+ printf("\tPreserve Aspect Ratio: %s\n",
+ YESNO(feature->preserve_aspect_ratio));
+ printf("\tEnable SDVO device power down: %s\n",
+ YESNO(feature->sdvo_device_power_down));
+ printf("\tCRT hotplug: %s\n", YESNO(feature->crt_hotplug));
+ printf("\tLVDS config: ");
+ switch (feature->lvds_config) {
+ case BDB_DRIVER_NO_LVDS:
+ printf("No LVDS\n");
+ break;
+ case BDB_DRIVER_INT_LVDS:
+ printf("Integrated LVDS\n");
+ break;
+ case BDB_DRIVER_SDVO_LVDS:
+ printf("SDVO LVDS\n");
+ break;
+ case BDB_DRIVER_EDP:
+ printf("Embedded DisplayPort\n");
+ break;
+ }
+ printf("\tDefine Display statically: %s\n",
+ YESNO(feature->static_display));
+ printf("\tLegacy CRT max X: %d\n", feature->legacy_crt_max_x);
+ printf("\tLegacy CRT max Y: %d\n", feature->legacy_crt_max_y);
+ printf("\tLegacy CRT max refresh: %d\n",
+ feature->legacy_crt_max_refresh);
+ free(block);
+}
+
+static void dump_edp(int length)
+{
+ struct bdb_block *block;
+ struct bdb_edp *edp;
+ int bpp;
+
+ block = find_section(BDB_EDP, length);
+ if (!block) {
+ printf("No EDP data block\n");
+ return;
+ }
+ edp = block->data;
+
+ printf("eDP block: type %d\n", panel_type);
+ printf("\tPower Sequence: T3 %d T7 %d T9 %d T10 %d T12 %d\n",
+ edp->power_seqs[panel_type].t3,
+ edp->power_seqs[panel_type].t7,
+ edp->power_seqs[panel_type].t9,
+ edp->power_seqs[panel_type].t10,
+ edp->power_seqs[panel_type].t12);
+
+ bpp = (edp->color_depth >> (panel_type * 2)) & 3;
+
+ printf("\tPanel color depth: ");
+ switch (bpp) {
+ case EDP_18BPP:
+ printf("18bpp\n");
+ break;
+ case EDP_24BPP:
+ printf("24bpp\n");
+ break;
+ case EDP_30BPP:
+ printf("30bpp\n");
+ break;
+ }
+ printf("\teDP sDRRs MSA timing delay: %d\n", edp->sdrrs_msa_timing_delay);
+ printf("\tLink params:\n");
+ printf("\t\trate: ");
+ if (edp->link_params[panel_type].rate == EDP_RATE_1_62)
+ printf("1.62G\n");
+ else if (edp->link_params[panel_type].rate == EDP_RATE_2_7)
+ printf("2.7G\n");
+ printf("\t\tlanes: ");
+ switch (edp->link_params[panel_type].lanes) {
+ case EDP_LANE_1:
+ printf("x1 mode\n");
+ break;
+ case EDP_LANE_2:
+ printf("x2 mode\n");
+ break;
+ case EDP_LANE_4:
+ printf("x4 mode\n");
+ break;
+ }
+ printf("\t\tpre-emphasis: ");
+ switch (edp->link_params[panel_type].preemphasis) {
+ case EDP_PREEMPHASIS_NONE:
+ printf("none\n");
+ break;
+ case EDP_PREEMPHASIS_3_5dB:
+ printf("3.5dB\n");
+ break;
+ case EDP_PREEMPHASIS_6dB:
+ printf("6dB\n");
+ break;
+ case EDP_PREEMPHASIS_9_5dB:
+ printf("9.5dB\n");
+ break;
+ }
+ printf("\t\tvswing: ");
+ switch (edp->link_params[panel_type].vswing) {
+ case EDP_VSWING_0_4V:
+ printf("0.4V\n");
+ break;
+ case EDP_VSWING_0_6V:
+ printf("0.6V\n");
+ break;
+ case EDP_VSWING_0_8V:
+ printf("0.8V\n");
+ break;
+ case EDP_VSWING_1_2V:
+ printf("1.2V\n");
+ break;
+ }
+ free(block);
+}
+
+static void
+print_detail_timing_data(struct lvds_dvo_timing2 *dvo_timing)
+{
+ int display, sync_start, sync_end, total;
+
+ display = (dvo_timing->hactive_hi << 8) | dvo_timing->hactive_lo;
+ sync_start = display +
+ ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
+ sync_end = sync_start + dvo_timing->hsync_pulse_width;
+ total = display +
+ ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
+ printf("\thdisplay: %d\n", display);
+ printf("\thsync [%d, %d] %s\n", sync_start, sync_end,
+ dvo_timing->hsync_positive ? "+sync" : "-sync");
+ printf("\thtotal: %d\n", total);
+
+ display = (dvo_timing->vactive_hi << 8) | dvo_timing->vactive_lo;
+ sync_start = display + dvo_timing->vsync_off;
+ sync_end = sync_start + dvo_timing->vsync_pulse_width;
+ total = display +
+ ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
+ printf("\tvdisplay: %d\n", display);
+ printf("\tvsync [%d, %d] %s\n", sync_start, sync_end,
+ dvo_timing->vsync_positive ? "+sync" : "-sync");
+ printf("\tvtotal: %d\n", total);
+
+ printf("\tclock: %d\n", dvo_timing->clock * 10);
+}
+
+static void dump_sdvo_panel_dtds(int length)
+{
+ struct bdb_block *block;
+ struct lvds_dvo_timing2 *dvo_timing;
+ int n, count;
+
+ block = find_section(BDB_SDVO_PANEL_DTDS, length);
+ if (!block) {
+ printf("No SDVO panel dtds block\n");
+ return;
+ }
+
+ printf("SDVO panel dtds:\n");
+ count = block->size / sizeof(struct lvds_dvo_timing2);
+ dvo_timing = block->data;
+ for (n = 0; n < count; n++) {
+ printf("%d:\n", n);
+ print_detail_timing_data(dvo_timing++);
+ }
+
+ free(block);
+}
+
+static void dump_sdvo_lvds_options(int length)
+{
+ struct bdb_block *block;
+ struct bdb_sdvo_lvds_options *options;
+
+ block = find_section(BDB_SDVO_LVDS_OPTIONS, length);
+ if (!block) {
+ printf("No SDVO LVDS options block\n");
+ return;
+ }
+
+ options = block->data;
+
+ printf("SDVO LVDS options block:\n");
+ printf("\tbacklight: %d\n", options->panel_backlight);
+ printf("\th40 type: %d\n", options->h40_set_panel_type);
+ printf("\ttype: %d\n", options->panel_type);
+ printf("\tssc_clk_freq: %d\n", options->ssc_clk_freq);
+ printf("\tals_low_trip: %d\n", options->als_low_trip);
+ printf("\tals_high_trip: %d\n", options->als_high_trip);
+ /*
+ u8 sclalarcoeff_tab_row_num;
+ u8 sclalarcoeff_tab_row_size;
+ u8 coefficient[8];
+ */
+ printf("\tmisc[0]: %x\n", options->panel_misc_bits_1);
+ printf("\tmisc[1]: %x\n", options->panel_misc_bits_2);
+ printf("\tmisc[2]: %x\n", options->panel_misc_bits_3);
+ printf("\tmisc[3]: %x\n", options->panel_misc_bits_4);
+
+ free(block);
+}
+
+static int
+get_device_id(unsigned char *bios)
+{
+ int device;
+ int offset = (bios[0x19] << 8) + bios[0x18];
+
+ if (bios[offset] != 'P' ||
+ bios[offset+1] != 'C' ||
+ bios[offset+2] != 'I' ||
+ bios[offset+3] != 'R')
+ return -1;
+
+ device = (bios[offset+7] << 8) + bios[offset+6];
+
+ return device;
+}
+
+int main(int argc, char **argv)
+{
+ int fd;
+ struct vbt_header *vbt = NULL;
+ int vbt_off, bdb_off, i;
+ const char *filename = "bios";
+ struct stat finfo;
+ struct bdb_block *block;
+ char signature[17];
+ char *devid_string;
+
+ if (argc != 2) {
+ printf("usage: %s <rom file>\n", argv[0]);
+ return 1;
+ }
+
+ if ((devid_string = getenv("DEVICE")))
+ devid = strtoul(devid_string, NULL, 0);
+
+ filename = argv[1];
+
+ fd = open(filename, O_RDONLY);
+ if (fd == -1) {
+ printf("Couldn't open \"%s\": %s\n", filename, strerror(errno));
+ return 1;
+ }
+
+ if (stat(filename, &finfo)) {
+ printf("failed to stat \"%s\": %s\n", filename,
+ strerror(errno));
+ return 1;
+ }
+
+ if (finfo.st_size == 0) {
+ int len = 0, ret;
+ finfo.st_size = 8192;
+ VBIOS = malloc (finfo.st_size);
+ while ((ret = read(fd, VBIOS + len, finfo.st_size - len))) {
+ if (ret < 0) {
+ printf("failed to read \"%s\": %s\n", filename,
+ strerror(errno));
+ return 1;
+ }
+
+ len += ret;
+ if (len == finfo.st_size) {
+ finfo.st_size *= 2;
+ VBIOS = realloc(VBIOS, finfo.st_size);
+ }
+ }
+ } else {
+ VBIOS = mmap(NULL, finfo.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (VBIOS == MAP_FAILED) {
+ printf("failed to map \"%s\": %s\n", filename, strerror(errno));
+ return 1;
+ }
+ }
+
+ /* Scour memory looking for the VBT signature */
+ for (i = 0; i + 4 < finfo.st_size; i++) {
+ if (!memcmp(VBIOS + i, "$VBT", 4)) {
+ vbt_off = i;
+ vbt = (struct vbt_header *)(VBIOS + i);
+ break;
+ }
+ }
+
+ if (!vbt) {
+ printf("VBT signature missing\n");
+ return 1;
+ }
+
+ printf("VBT vers: %d.%d\n", vbt->version / 100, vbt->version % 100);
+
+ bdb_off = vbt_off + vbt->bdb_offset;
+ if (bdb_off >= finfo.st_size - sizeof(struct bdb_header)) {
+ printf("Invalid VBT found, BDB points beyond end of data block\n");
+ return 1;
+ }
+
+ bdb = (struct bdb_header *)(VBIOS + bdb_off);
+ strncpy(signature, (char *)bdb->signature, 16);
+ signature[16] = 0;
+ printf("BDB sig: %s\n", signature);
+ printf("BDB vers: %d\n", bdb->version);
+
+ printf("Available sections: ");
+ for (i = 0; i < 256; i++) {
+ block = find_section(i, finfo.st_size);
+ if (!block)
+ continue;
+ printf("%d ", i);
+ free(block);
+ }
+ printf("\n");
+
+ if (devid == -1)
+ devid = get_device_id(VBIOS);
+ if (devid == -1)
+ printf("Warning: could not find PCI device ID!\n");
+
+ dump_general_features(finfo.st_size);
+ dump_general_definitions(finfo.st_size);
+ dump_child_devices(finfo.st_size);
+ dump_lvds_options(finfo.st_size);
+ dump_lvds_data(finfo.st_size);
+ dump_lvds_ptr_data(finfo.st_size);
+ dump_backlight_info(finfo.st_size);
+
+ dump_sdvo_lvds_options(finfo.st_size);
+ dump_sdvo_panel_dtds(finfo.st_size);
+
+ dump_driver_feature(finfo.st_size);
+ dump_edp(finfo.st_size);
+
+ return 0;
+}
diff --git a/tools/intel_disable_clock_gating.c b/tools/intel_disable_clock_gating.c
new file mode 100644
index 00000000..8dde3e18
--- /dev/null
+++ b/tools/intel_disable_clock_gating.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+int main(int argc, char** argv)
+{
+ struct pci_device *pci_dev;
+
+ pci_dev = intel_get_pci_device();
+ intel_get_mmio(pci_dev);
+
+ if (IS_GEN5(pci_dev->device_id)) {
+ printf("Restore method:\n");
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_3DCGDIS0, INREG(PCH_3DCGDIS0));
+ OUTREG(PCH_3DCGDIS0, 0xffffffff);
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_3DCGDIS1, INREG(PCH_3DCGDIS1));
+ OUTREG(PCH_3DCGDIS1, 0xffffffff);
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_3DRAMCGDIS0, INREG(PCH_3DRAMCGDIS0));
+ OUTREG(PCH_3DRAMCGDIS0, 0xffffffff);
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_DSPCLK_GATE_D, INREG(PCH_DSPCLK_GATE_D));
+ OUTREG(PCH_DSPCLK_GATE_D, 0xffffffff);
+
+ printf("intel_reg_write 0x%x 0x%08x\n",
+ PCH_DSPRAMCLK_GATE_D, INREG(PCH_DSPRAMCLK_GATE_D));
+ OUTREG(PCH_DSPRAMCLK_GATE_D, 0xffffffff);
+ } else {
+ fprintf(stderr, "unsupported chipset\n");
+ }
+
+
+ return 0;
+}
+
diff --git a/tools/intel_dpio_read.c b/tools/intel_dpio_read.c
new file mode 100644
index 00000000..c0c904a6
--- /dev/null
+++ b/tools/intel_dpio_read.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Vijay Purushothaman <vijay.a.purushothaman@intel.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+static void usage(char *cmdname)
+{
+ printf("Warning : This program will work only on Valleyview\n");
+ printf("Usage: %s [addr]\n", cmdname);
+ printf("\t addr : in 0xXXXX format\n");
+}
+
+int main(int argc, char** argv)
+{
+ int ret = 0;
+ uint32_t reg, val;
+ char *cmdname = strdup(argv[0]);
+ struct pci_device *dev = intel_get_pci_device();
+
+ if (argc != 2 || !IS_VALLEYVIEW(dev->device_id)) {
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ }
+
+ sscanf(argv[1], "0x%x", &reg);
+
+ intel_register_access_init(dev, 0);
+
+ val = intel_dpio_reg_read(reg);
+
+ printf("Read DPIO register: 0x%x - Value : 0x%x\n", reg, val);
+
+ intel_register_access_fini();
+
+out:
+ free(cmdname);
+ return ret;
+}
diff --git a/tools/intel_dpio_write.c b/tools/intel_dpio_write.c
new file mode 100644
index 00000000..f8429990
--- /dev/null
+++ b/tools/intel_dpio_write.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Vijay Purushothaman <vijay.a.purushothaman@intel.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+static void usage(char *cmdname)
+{
+ printf("Warning : This program will work only on Valleyview\n");
+ printf("Usage: %s [addr] [val]\n", cmdname);
+ printf("\t addr : in 0xXXXX format\n");
+}
+
+int main(int argc, char** argv)
+{
+ int ret = 0;
+ uint32_t reg, val;
+ char *cmdname = strdup(argv[0]);
+ struct pci_device *dev = intel_get_pci_device();
+
+ if (argc != 3 || !IS_VALLEYVIEW(dev->device_id)) {
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ }
+
+ sscanf(argv[1], "0x%x", &reg);
+ sscanf(argv[2], "0x%x", &val);
+
+ intel_register_access_init(dev, 0);
+
+ intel_dpio_reg_write(reg, val);
+
+ intel_register_access_fini();
+
+out:
+ free(cmdname);
+ return ret;
+}
diff --git a/tools/intel_dump_decode.c b/tools/intel_dump_decode.c
new file mode 100644
index 00000000..a3cd2e59
--- /dev/null
+++ b/tools/intel_dump_decode.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#include <intel_bufmgr.h>
+
+struct drm_intel_decode *ctx;
+
+static void
+read_bin_file(const char * filename)
+{
+ uint32_t buf[16384];
+ int fd, offset, ret;
+
+ if (!strcmp(filename, "-"))
+ fd = fileno(stdin);
+ else
+ fd = open (filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf (stderr, "Failed to open %s: %s\n",
+ filename, strerror (errno));
+ exit (1);
+ }
+
+ drm_intel_decode_set_dump_past_end(ctx, 1);
+
+ offset = 0;
+ while ((ret = read (fd, buf, sizeof(buf))) > 0) {
+ drm_intel_decode_set_batch_pointer(ctx, buf, offset, ret/4);
+ drm_intel_decode(ctx);
+ offset += ret;
+ }
+ close (fd);
+}
+
+static void
+read_data_file(const char * filename)
+{
+ FILE *file;
+ uint32_t *data = NULL;
+ int data_size = 0, count = 0, line_number = 0, matched;
+ char *line = NULL;
+ size_t line_size;
+ uint32_t offset, value;
+ uint32_t gtt_offset = 0;
+
+ if (!strcmp(filename, "-"))
+ file = stdin;
+ else
+ file = fopen (filename, "r");
+
+ if (file == NULL) {
+ fprintf (stderr, "Failed to open %s: %s\n",
+ filename, strerror (errno));
+ exit (1);
+ }
+
+ while (getline (&line, &line_size, file) > 0) {
+ line_number++;
+
+ matched = sscanf (line, "%08x : %08x", &offset, &value);
+ if (matched != 2) {
+ printf("ignoring line %s", line);
+
+ continue;
+ }
+
+ count++;
+
+ if (count > data_size) {
+ data_size = data_size ? data_size * 2 : 1024;
+ data = realloc (data, data_size * sizeof (uint32_t));
+ if (data == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+ }
+
+ data[count-1] = value;
+ }
+
+ if (count) {
+ drm_intel_decode_set_batch_pointer(ctx, data, gtt_offset, count);
+ drm_intel_decode(ctx);
+ }
+
+ free (data);
+ free (line);
+
+ fclose (file);
+}
+
+static void
+read_autodetect_file(const char * filename)
+{
+ int binary = 0, c;
+ FILE *file;
+
+ file = fopen (filename, "r");
+ if (file == NULL) {
+ fprintf (stderr, "Failed to open %s: %s\n",
+ filename, strerror (errno));
+ exit (1);
+ }
+
+ while ((c = fgetc(file)) != EOF) {
+ /* totally lazy binary detector */
+ if (c < 10) {
+ binary = 1;
+ break;
+ }
+ }
+
+ fclose(file);
+
+ if (binary == 1)
+ read_bin_file(filename);
+ else
+ read_data_file(filename);
+
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ uint32_t devid = 0xa011;
+ int i, c;
+ int option_index = 0;
+ int binary = -1;
+
+ static struct option long_options[] = {
+ {"devid", 1, 0, 'd'},
+ {"ascii", 0, 0, 'a'},
+ {"binary", 0, 0, 'b'}
+ };
+
+ while((c = getopt_long(argc, argv, "ab",
+ long_options, &option_index)) != -1) {
+ switch(c) {
+ case 'd':
+ devid = strtoul(optarg, NULL, 0);
+ break;
+ case 'b':
+ binary = 1;
+ break;
+ case 'a':
+ binary = 0;
+ break;
+ default:
+ printf("unkown command options\n");
+ break;
+ }
+ }
+
+ ctx = drm_intel_decode_context_alloc(devid);
+
+ if (optind == argc) {
+ fprintf(stderr, "no input file given\n");
+ exit(-1);
+ }
+
+ for (i = optind; i < argc; i++) {
+ /* For stdin input, let's read as data file */
+ if (!strcmp(argv[i], "-")) {
+ read_data_file(argv[i]);
+ continue;
+ }
+ if (binary == 1)
+ read_bin_file(argv[i]);
+ else if (binary == 0)
+ read_data_file(argv[i]);
+ else
+ read_autodetect_file(argv[i]);
+ }
+
+ return 0;
+}
diff --git a/tools/intel_error_decode.c b/tools/intel_error_decode.c
new file mode 100644
index 00000000..e0ec8f60
--- /dev/null
+++ b/tools/intel_error_decode.c
@@ -0,0 +1,515 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2007 Intel Corporation
+ * Copyright © 2009 Intel Corporation
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Carl Worth <cworth@cworth.org>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+/** @file intel_decode.c
+ * This file contains code to print out batchbuffer contents in a
+ * human-readable format.
+ *
+ * The current version only supports i915 packets, and only pretty-prints a
+ * subset of them. The intention is for it to make just a best attempt to
+ * decode, but never crash in the process.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <intel_bufmgr.h>
+
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+#include "instdone.h"
+
+static void
+print_instdone (uint32_t devid, unsigned int instdone, unsigned int instdone1)
+{
+ int i;
+ static int once;
+
+ if (!once) {
+ init_instdone_definitions(devid);
+ once = 1;
+ }
+
+ for (i = 0; i < num_instdone_bits; i++) {
+ int busy = 0;
+
+ if (instdone_bits[i].reg == INST_DONE_1) {
+ if (!(instdone1 & instdone_bits[i].bit))
+ busy = 1;
+ } else {
+ if (!(instdone & instdone_bits[i].bit))
+ busy = 1;
+ }
+
+ if (busy)
+ printf(" busy: %s\n", instdone_bits[i].name);
+ }
+}
+
+static void
+print_i830_pgtbl_err(unsigned int reg)
+{
+ const char *str;
+
+ switch((reg >> 3) & 0xf) {
+ case 0x1: str = "Overlay TLB"; break;
+ case 0x2: str = "Display A TLB"; break;
+ case 0x3: str = "Host TLB"; break;
+ case 0x4: str = "Render TLB"; break;
+ case 0x5: str = "Display C TLB"; break;
+ case 0x6: str = "Mapping TLB"; break;
+ case 0x7: str = "Command Stream TLB"; break;
+ case 0x8: str = "Vertex Buffer TLB"; break;
+ case 0x9: str = "Display B TLB"; break;
+ case 0xa: str = "Reserved System Memory"; break;
+ case 0xb: str = "Compressor TLB"; break;
+ case 0xc: str = "Binner TLB"; break;
+ default: str = "unknown"; break;
+ }
+
+ if (str)
+ printf (" source = %s\n", str);
+
+ switch(reg & 0x7) {
+ case 0x0: str = "Invalid GTT"; break;
+ case 0x1: str = "Invalid GTT PTE"; break;
+ case 0x2: str = "Invalid Memory"; break;
+ case 0x3: str = "Invalid TLB miss"; break;
+ case 0x4: str = "Invalid PTE data"; break;
+ case 0x5: str = "Invalid LocalMemory not present"; break;
+ case 0x6: str = "Invalid Tiling"; break;
+ case 0x7: str = "Host to CAM"; break;
+ }
+ printf (" error = %s\n", str);
+}
+
+static void
+print_i915_pgtbl_err(unsigned int reg)
+{
+ if (reg & (1 << 29))
+ printf (" Cursor A: Invalid GTT PTE\n");
+ if (reg & (1 << 28))
+ printf (" Cursor B: Invalid GTT PTE\n");
+ if (reg & (1 << 27))
+ printf (" MT: Invalid tiling\n");
+ if (reg & (1 << 26))
+ printf (" MT: Invalid GTT PTE\n");
+ if (reg & (1 << 25))
+ printf (" LC: Invalid tiling\n");
+ if (reg & (1 << 24))
+ printf (" LC: Invalid GTT PTE\n");
+ if (reg & (1 << 23))
+ printf (" BIN VertexData: Invalid GTT PTE\n");
+ if (reg & (1 << 22))
+ printf (" BIN Instruction: Invalid GTT PTE\n");
+ if (reg & (1 << 21))
+ printf (" CS VertexData: Invalid GTT PTE\n");
+ if (reg & (1 << 20))
+ printf (" CS Instruction: Invalid GTT PTE\n");
+ if (reg & (1 << 19))
+ printf (" CS: Invalid GTT\n");
+ if (reg & (1 << 18))
+ printf (" Overlay: Invalid tiling\n");
+ if (reg & (1 << 16))
+ printf (" Overlay: Invalid GTT PTE\n");
+ if (reg & (1 << 14))
+ printf (" Display C: Invalid tiling\n");
+ if (reg & (1 << 12))
+ printf (" Display C: Invalid GTT PTE\n");
+ if (reg & (1 << 10))
+ printf (" Display B: Invalid tiling\n");
+ if (reg & (1 << 8))
+ printf (" Display B: Invalid GTT PTE\n");
+ if (reg & (1 << 6))
+ printf (" Display A: Invalid tiling\n");
+ if (reg & (1 << 4))
+ printf (" Display A: Invalid GTT PTE\n");
+ if (reg & (1 << 1))
+ printf (" Host Invalid PTE data\n");
+ if (reg & (1 << 0))
+ printf (" Host Invalid GTT PTE\n");
+}
+
+static void
+print_i965_pgtbl_err(unsigned int reg)
+{
+ if (reg & (1 << 26))
+ printf (" Invalid Sampler Cache GTT entry\n");
+ if (reg & (1 << 24))
+ printf (" Invalid Render Cache GTT entry\n");
+ if (reg & (1 << 23))
+ printf (" Invalid Instruction/State Cache GTT entry\n");
+ if (reg & (1 << 22))
+ printf (" There is no ROC, this cannot occur!\n");
+ if (reg & (1 << 21))
+ printf (" Invalid GTT entry during Vertex Fetch\n");
+ if (reg & (1 << 20))
+ printf (" Invalid GTT entry during Command Fetch\n");
+ if (reg & (1 << 19))
+ printf (" Invalid GTT entry during CS\n");
+ if (reg & (1 << 18))
+ printf (" Invalid GTT entry during Cursor Fetch\n");
+ if (reg & (1 << 17))
+ printf (" Invalid GTT entry during Overlay Fetch\n");
+ if (reg & (1 << 8))
+ printf (" Invalid GTT entry during Display B Fetch\n");
+ if (reg & (1 << 4))
+ printf (" Invalid GTT entry during Display A Fetch\n");
+ if (reg & (1 << 1))
+ printf (" Valid PTE references illegal memory\n");
+ if (reg & (1 << 0))
+ printf (" Invalid GTT entry during fetch for host\n");
+}
+
+static void
+print_pgtbl_err(unsigned int reg, unsigned int devid)
+{
+ if (IS_965(devid)) {
+ return print_i965_pgtbl_err(reg);
+ } else if (IS_GEN3(devid)) {
+ return print_i915_pgtbl_err(reg);
+ } else {
+ return print_i830_pgtbl_err(reg);
+ }
+}
+
+static void
+print_snb_fence(unsigned int devid, uint64_t fence)
+{
+ printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
+ fence & 1 ? "" : "in",
+ fence & (1<<1) ? 'y' : 'x',
+ (int)(((fence>>32)&0xfff)+1)*128,
+ (uint32_t)fence & 0xfffff000,
+ (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
+}
+
+static void
+print_i965_fence(unsigned int devid, uint64_t fence)
+{
+ printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %u\n",
+ fence & 1 ? "" : "in",
+ fence & (1<<1) ? 'y' : 'x',
+ (int)(((fence>>2)&0x1ff)+1)*128,
+ (uint32_t)fence & 0xfffff000,
+ (uint32_t)(((fence>>32)&0xfffff000) - (fence&0xfffff000) + 4096));
+}
+
+static void
+print_i915_fence(unsigned int devid, uint64_t fence)
+{
+ unsigned tile_width;
+ if ((fence & 12) && !IS_915(devid))
+ tile_width = 128;
+ else
+ tile_width = 512;
+
+ printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
+ fence & 1 ? "" : "in",
+ fence & 12 ? 'y' : 'x',
+ (1<<((fence>>4)&0xf))*tile_width,
+ (uint32_t)fence & 0xff00000,
+ 1<<(20 + ((fence>>8)&0xf)));
+}
+
+static void
+print_i830_fence(unsigned int devid, uint64_t fence)
+{
+ printf(" %svalid, %c-tiled, pitch: %i, start: 0x%08x, size: %i\n",
+ fence & 1 ? "" : "in",
+ fence & 12 ? 'y' : 'x',
+ (1<<((fence>>4)&0xf))*128,
+ (uint32_t)fence & 0x7f80000,
+ 1<<(19 + ((fence>>8)&0xf)));
+}
+
+static void
+print_fence(unsigned int devid, uint64_t fence)
+{
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ return print_snb_fence(devid, fence);
+ } else if (IS_GEN4(devid) || IS_GEN5(devid)) {
+ return print_i965_fence(devid, fence);
+ } else if (IS_GEN3(devid)) {
+ return print_i915_fence(devid, fence);
+ } else {
+ return print_i830_fence(devid, fence);
+ }
+}
+
+static void
+read_data_file (FILE *file)
+{
+ struct drm_intel_decode *decode_ctx = NULL;
+ uint32_t devid = PCI_CHIP_I855_GM;
+ uint32_t *data = NULL;
+ long long unsigned fence;
+ int data_size = 0, count = 0, line_number = 0, matched;
+ char *line = NULL;
+ size_t line_size;
+ uint32_t offset, value;
+ uint32_t gtt_offset = 0, new_gtt_offset;
+ const char *buffer_type[2] = { "ringbuffer", "batchbuffer" };
+ char *ring_name = NULL;
+ int is_batch = 1;
+
+ while (getline (&line, &line_size, file) > 0) {
+ char *dashes;
+ line_number++;
+
+ dashes = strstr(line, "---");
+ if (dashes) {
+ char *new_ring_name = malloc(dashes - line);
+ strncpy(new_ring_name, line, dashes - line);
+ new_ring_name[dashes - line - 1] = '\0';
+
+ matched = sscanf (dashes, "--- gtt_offset = 0x%08x\n",
+ &new_gtt_offset);
+ if (matched == 1) {
+ if (count) {
+ printf("%s (%s) at 0x%08x:\n",
+ buffer_type[is_batch],
+ ring_name,
+ gtt_offset);
+ drm_intel_decode_set_batch_pointer(decode_ctx,
+ data, gtt_offset,
+ count);
+ drm_intel_decode(decode_ctx);
+ count = 0;
+ }
+ gtt_offset = new_gtt_offset;
+ is_batch = 1;
+ free(ring_name);
+ ring_name = new_ring_name;
+ continue;
+ }
+
+ matched = sscanf (dashes, "--- ringbuffer = 0x%08x\n",
+ &new_gtt_offset);
+ if (matched == 1) {
+ if (count) {
+ printf("%s (%s) at 0x%08x:\n",
+ buffer_type[is_batch],
+ ring_name,
+ gtt_offset);
+ drm_intel_decode_set_batch_pointer(decode_ctx,
+ data, gtt_offset,
+ count);
+ drm_intel_decode(decode_ctx);
+ count = 0;
+ }
+ gtt_offset = new_gtt_offset;
+ is_batch = 0;
+ free(ring_name);
+ ring_name = new_ring_name;
+ continue;
+ }
+ }
+
+ matched = sscanf (line, "%08x : %08x", &offset, &value);
+ if (matched != 2) {
+ unsigned int reg;
+
+ /* display reg section is after the ringbuffers, don't mix them */
+ if (count) {
+ printf("%s (%s) at 0x%08x:\n",
+ buffer_type[is_batch],
+ ring_name,
+ gtt_offset);
+ drm_intel_decode_set_batch_pointer(decode_ctx,
+ data, gtt_offset,
+ count);
+ drm_intel_decode(decode_ctx);
+ count = 0;
+ }
+
+ printf("%s", line);
+
+ matched = sscanf (line, "PCI ID: 0x%04x\n", &reg);
+ if (matched == 0)
+ matched = sscanf (line, " PCI ID: 0x%04x\n", &reg);
+ if (matched == 1) {
+ devid = reg;
+ printf("Detected GEN%i chipset\n",
+ intel_gen(devid));
+
+ decode_ctx = drm_intel_decode_context_alloc(devid);
+ }
+
+ matched = sscanf (line, " ACTHD: 0x%08x\n", &reg);
+ if (matched == 1)
+ drm_intel_decode_set_head_tail(decode_ctx, reg, 0xffffffff);
+
+ matched = sscanf (line, " PGTBL_ER: 0x%08x\n", &reg);
+ if (matched == 1 && reg)
+ print_pgtbl_err(reg, devid);
+
+ matched = sscanf (line, " INSTDONE: 0x%08x\n", &reg);
+ if (matched == 1)
+ print_instdone (devid, reg, -1);
+
+ matched = sscanf (line, " INSTDONE1: 0x%08x\n", &reg);
+ if (matched == 1)
+ print_instdone (devid, -1, reg);
+
+ matched = sscanf (line, " fence[%i] = %Lx\n", &reg, &fence);
+ if (matched == 2)
+ print_fence (devid, fence);
+
+ continue;
+ }
+
+ count++;
+
+ if (count > data_size) {
+ data_size = data_size ? data_size * 2 : 1024;
+ data = realloc (data, data_size * sizeof (uint32_t));
+ if (data == NULL) {
+ fprintf (stderr, "Out of memory.\n");
+ exit (1);
+ }
+ }
+
+ data[count-1] = value;
+ }
+
+ if (count) {
+ printf("%s (%s) at 0x%08x:\n",
+ buffer_type[is_batch],
+ ring_name,
+ gtt_offset);
+ drm_intel_decode_set_batch_pointer(decode_ctx,
+ data, gtt_offset,
+ count);
+ drm_intel_decode(decode_ctx);
+ }
+
+ free (data);
+ free (line);
+ free (ring_name);
+}
+
+int
+main (int argc, char *argv[])
+{
+ FILE *file;
+ const char *path;
+ char *filename = NULL;
+ struct stat st;
+ int error;
+
+ if (argc > 2) {
+ fprintf (stderr,
+ "intel_gpu_decode: Parse an Intel GPU i915_error_state\n"
+ "Usage:\n"
+ "\t%s [<file>]\n"
+ "\n"
+ "With no arguments, debugfs-dri-directory is probed for in "
+ "/debug and \n"
+ "/sys/kernel/debug. Otherwise, it may be "
+ "specified. If a file is given,\n"
+ "it is parsed as an GPU dump in the format of "
+ "/debug/dri/0/i915_error_state.\n",
+ argv[0]);
+ return 1;
+ }
+
+ if (argc == 1) {
+ if (isatty(0)) {
+ path = "/debug/dri";
+ error = stat (path, &st);
+ if (error != 0) {
+ path = "/sys/kernel/debug/dri";
+ error = stat (path, &st);
+ if (error != 0) {
+ errx(1,
+ "Couldn't find i915 debugfs directory.\n\n"
+ "Is debugfs mounted? You might try mounting it with a command such as:\n\n"
+ "\tsudo mount -t debugfs debugfs /sys/kernel/debug\n");
+ }
+ }
+ } else {
+ read_data_file(stdin);
+ exit(0);
+ }
+ } else {
+ path = argv[1];
+ error = stat (path, &st);
+ if (error != 0) {
+ fprintf (stderr, "Error opening %s: %s\n",
+ path, strerror (errno));
+ exit (1);
+ }
+ }
+
+ if (S_ISDIR (st.st_mode)) {
+ asprintf (&filename, "%s/i915_error_state", path);
+ file = fopen(filename, "r");
+ if (!file) {
+ int minor;
+ for (minor = 0; minor < 64; minor++) {
+ free(filename);
+ asprintf(&filename, "%s/%d/i915_error_state", path, minor);
+ file = fopen(filename, "r");
+ if (file)
+ break;
+ }
+ }
+ if (!file) {
+ fprintf (stderr, "Failed to find i915_error_state beneath %s\n",
+ path);
+ exit (1);
+ }
+ } else {
+ file = fopen(path, "r");
+ if (!file) {
+ fprintf (stderr, "Failed to open %s: %s\n",
+ path, strerror (errno));
+ exit (1);
+ }
+ }
+
+ read_data_file (file);
+ fclose (file);
+
+ if (filename != path)
+ free (filename);
+
+ return 0;
+}
diff --git a/tools/intel_forcewaked.c b/tools/intel_forcewaked.c
new file mode 100644
index 00000000..3ab2d6f8
--- /dev/null
+++ b/tools/intel_forcewaked.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#include <assert.h>
+#include <err.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "intel_gpu_tools.h"
+
+bool daemonized;
+
+#define INFO_PRINT(...) \
+ do { \
+ if (daemonized) \
+ syslog(LOG_INFO, ##__VA_ARGS__); \
+ else \
+ fprintf(stdout, ##__VA_ARGS__); \
+ } while(0)
+
+static void
+help(char *prog) {
+ printf("%s Prevents the GT from sleeping.\n\n", prog);
+ printf("usage: %s [options] \n\n", prog);
+ printf("Options: \n");
+ printf(" -b Run in background/daemon mode\n");
+}
+
+static int
+is_alive(void) {
+ /* Read the timestamp, which should *almost* always be !0 */
+ return (intel_register_read(0x2358) != 0);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ if (argc > 2 || (argc == 2 && !strncmp(argv[1], "-h", 2))) {
+ help(argv[1]);
+ exit(0);
+ }
+
+ if (argc == 2 && (!strncmp(argv[1], "-b", 2)))
+ daemonized = true;
+
+ if (daemonized) {
+ assert(daemon(0, 0) == 0);
+ openlog(argv[0], LOG_CONS | LOG_PID, LOG_USER);
+ INFO_PRINT("started daemon");
+ }
+
+ ret = intel_register_access_init(intel_get_pci_device(), 1);
+ if (ret) {
+ INFO_PRINT("Couldn't init register access\n");
+ exit(1);
+ } else {
+ INFO_PRINT("Forcewake locked\n");
+ }
+ while(1) {
+ if (!is_alive()) {
+ INFO_PRINT("gpu reset? restarting daemon\n");
+ intel_register_access_fini();
+ ret = intel_register_access_init(intel_get_pci_device(),
+ 1);
+ }
+ sleep(1);
+ }
+ intel_register_access_fini();
+ INFO_PRINT("Forcewake unlock\n");
+
+ if (daemonized) {
+ INFO_PRINT("finished\n");
+ closelog();
+ }
+
+ return 0;
+}
diff --git a/tools/intel_gpu_abrt b/tools/intel_gpu_abrt
new file mode 100755
index 00000000..141a5246
--- /dev/null
+++ b/tools/intel_gpu_abrt
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+if [ -d /debug/dri ] ; then
+ debugfs_path=/debug_dri
+fi
+
+if [ -d /sys/kernel/debug/dri ] ; then
+ debugfs_path=/sys/kernel/debug/dri
+fi
+
+i915_debugfs=x
+for dir in `ls $debugfs_path` ; do
+ if [ -f $debugfs_path/$dir/i915_error_state ] ; then
+ i915_debugfs=$debugfs_path/$dir
+ break
+ fi
+done
+
+if [ $i915_debugfs = "x" ] ; then
+ echo i915 debugfs path not found.
+ exit 1
+fi
+
+tmpdir=`mktemp -d`
+tardir=$tmpdir/intel_gpu_abrt
+mkdir $tardir
+
+mkdir $tardir/debugfs
+cp $i915_debugfs/* $tardir/debugfs
+
+mkdir $tardir/mod_opts
+cp /sys/module/i915/parameters/* $tardir/mod_opts
+
+mkdir $tardir/X
+cp /var/log/Xorg.*.log $tardir/X
+cp /etc/X11/xorg.conf $tardir/X
+
+dmesg > $tardir/dmesg
+lspci -nn > $tardir/lspci
+
+(cd $tmpdir; tar -c intel_gpu_abrt ) > intel_gpu_abrt.tar
+
+rm $tmpdir -Rf
+
+exit 0
diff --git a/tools/intel_gpu_time.c b/tools/intel_gpu_time.c
new file mode 100644
index 00000000..c30b84d2
--- /dev/null
+++ b/tools/intel_gpu_time.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2007,2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include "intel_gpu_tools.h"
+
+#define SAMPLES_PER_SEC 10000
+
+static volatile int goddo;
+
+static pid_t spawn(char **argv)
+{
+ pid_t pid;
+
+ pid = fork();
+ if (pid != 0)
+ return pid;
+
+ execvp(argv[0], argv);
+ exit(1);
+}
+
+static void sighandler(int sig)
+{
+ goddo = sig;
+}
+
+int main(int argc, char **argv)
+{
+ pid_t child;
+ uint64_t ring_idle = 0, ring_time = 0;
+ struct timeval start, end;
+ static struct rusage rusage;
+ int status;
+
+ intel_get_mmio(intel_get_pci_device());
+
+ if (argc == 1) {
+ fprintf(stderr, "usage: %s cmd [args...]\n", argv[0]);
+ return 1;
+ }
+
+ signal(SIGCHLD, sighandler);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+
+ gettimeofday(&start, NULL);
+ child = spawn(argv+1);
+ if (child < 0)
+ return 127;
+
+ while (!goddo) {
+ uint32_t ring_head, ring_tail;
+
+ ring_head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR;
+ ring_tail = INREG(LP_RING + RING_TAIL) & TAIL_ADDR;
+
+ if (ring_tail == ring_head)
+ ring_idle++;
+ ring_time++;
+
+ usleep(1000000 / SAMPLES_PER_SEC);
+ }
+ gettimeofday(&end, NULL);
+ timersub(&end, &start, &end);
+
+ waitpid(child, &status, 0);
+
+ getrusage(RUSAGE_CHILDREN, &rusage);
+ printf("user: %ld.%06lds, sys: %ld.%06lds, elapsed: %ld.%06lds, CPU: %.1f%%, GPU: %.1f%%\n",
+ rusage.ru_utime.tv_sec, rusage.ru_utime.tv_usec,
+ rusage.ru_stime.tv_sec, rusage.ru_stime.tv_usec,
+ end.tv_sec, end.tv_usec,
+ 100*(rusage.ru_utime.tv_sec + 1e-6*rusage.ru_utime.tv_usec + rusage.ru_stime.tv_sec + 1e-6*rusage.ru_stime.tv_usec) / (end.tv_sec + 1e-6*end.tv_usec),
+ 100 - ring_idle * 100. / ring_time);
+
+ return WEXITSTATUS(status);
+}
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
new file mode 100644
index 00000000..e561865c
--- /dev/null
+++ b/tools/intel_gpu_top.c
@@ -0,0 +1,716 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Eugeni Dodonov <eugeni.dodonov@intel.com>
+ *
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <string.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#include "intel_gpu_tools.h"
+#include "instdone.h"
+
+#define FORCEWAKE 0xA18C
+#define FORCEWAKE_ACK 0x130090
+
+#define SAMPLES_PER_SEC 10000
+#define SAMPLES_TO_PERCENT_RATIO (SAMPLES_PER_SEC / 100)
+
+#define MAX_NUM_TOP_BITS 100
+
+#define HAS_STATS_REGS(devid) IS_965(devid)
+
+struct top_bit {
+ struct instdone_bit *bit;
+ int count;
+} top_bits[MAX_NUM_TOP_BITS];
+struct top_bit *top_bits_sorted[MAX_NUM_TOP_BITS];
+
+static uint32_t instdone, instdone1;
+
+static const char *bars[] = {
+ " ",
+ "▏",
+ "▎",
+ "▍",
+ "▌",
+ "▋",
+ "▊",
+ "▉",
+ "█"
+};
+
+enum stats_counts {
+ IA_VERTICES,
+ IA_PRIMITIVES,
+ VS_INVOCATION,
+ GS_INVOCATION,
+ GS_PRIMITIVES,
+ CL_INVOCATION,
+ CL_PRIMITIVES,
+ PS_INVOCATION,
+ PS_DEPTH,
+ STATS_COUNT
+};
+
+const uint32_t stats_regs[STATS_COUNT] = {
+ IA_VERTICES_COUNT_QW,
+ IA_PRIMITIVES_COUNT_QW,
+ VS_INVOCATION_COUNT_QW,
+ GS_INVOCATION_COUNT_QW,
+ GS_PRIMITIVES_COUNT_QW,
+ CL_INVOCATION_COUNT_QW,
+ CL_PRIMITIVES_COUNT_QW,
+ PS_INVOCATION_COUNT_QW,
+ PS_DEPTH_COUNT_QW,
+};
+
+const char *stats_reg_names[STATS_COUNT] = {
+ "vert fetch",
+ "prim fetch",
+ "VS invocations",
+ "GS invocations",
+ "GS prims",
+ "CL invocations",
+ "CL prims",
+ "PS invocations",
+ "PS depth pass",
+};
+
+uint64_t stats[STATS_COUNT];
+uint64_t last_stats[STATS_COUNT];
+
+static unsigned long
+gettime(void)
+{
+ struct timeval t;
+ gettimeofday(&t, NULL);
+ return (t.tv_usec + (t.tv_sec * 1000000));
+}
+
+static int
+top_bits_sort(const void *a, const void *b)
+{
+ struct top_bit * const *bit_a = a;
+ struct top_bit * const *bit_b = b;
+ int a_count = (*bit_a)->count;
+ int b_count = (*bit_b)->count;
+
+ if (a_count < b_count)
+ return 1;
+ else if (a_count == b_count)
+ return 0;
+ else
+ return -1;
+}
+
+static void
+update_idle_bit(struct top_bit *top_bit)
+{
+ uint32_t reg_val;
+
+ if (top_bit->bit->reg == INST_DONE_1)
+ reg_val = instdone1;
+ else
+ reg_val = instdone;
+
+ if ((reg_val & top_bit->bit->bit) == 0)
+ top_bit->count++;
+}
+
+static void
+print_clock(const char *name, int clock) {
+ if (clock == -1)
+ printf("%s clock: unknown", name);
+ else
+ printf("%s clock: %d Mhz", name, clock);
+}
+
+static int
+print_clock_info(struct pci_device *pci_dev)
+{
+ uint32_t devid = pci_dev->device_id;
+ uint16_t gcfgc;
+
+ if (IS_GM45(devid)) {
+ int core_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0xf) {
+ case 8:
+ core_clock = 266;
+ break;
+ case 9:
+ core_clock = 320;
+ break;
+ case 11:
+ core_clock = 400;
+ break;
+ case 13:
+ core_clock = 533;
+ break;
+ }
+ print_clock("core", core_clock);
+ } else if (IS_965(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, sampler_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0xf) {
+ case 2:
+ render_clock = 250; sampler_clock = 267;
+ break;
+ case 3:
+ render_clock = 320; sampler_clock = 333;
+ break;
+ case 4:
+ render_clock = 400; sampler_clock = 444;
+ break;
+ case 5:
+ render_clock = 500; sampler_clock = 533;
+ break;
+ }
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("sampler", sampler_clock);
+ } else if (IS_945(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, display_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0x7) {
+ case 0:
+ render_clock = 166;
+ break;
+ case 1:
+ render_clock = 200;
+ break;
+ case 3:
+ render_clock = 250;
+ break;
+ case 5:
+ render_clock = 400;
+ break;
+ }
+
+ switch (gcfgc & 0x70) {
+ case 0:
+ display_clock = 200;
+ break;
+ case 4:
+ display_clock = 320;
+ break;
+ }
+ if (gcfgc & (1 << 7))
+ display_clock = 133;
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("display", display_clock);
+ } else if (IS_915(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, display_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0x7) {
+ case 0:
+ render_clock = 160;
+ break;
+ case 1:
+ render_clock = 190;
+ break;
+ case 4:
+ render_clock = 333;
+ break;
+ }
+ if (gcfgc & (1 << 13))
+ render_clock = 133;
+
+ switch (gcfgc & 0x70) {
+ case 0:
+ display_clock = 190;
+ break;
+ case 4:
+ display_clock = 333;
+ break;
+ }
+ if (gcfgc & (1 << 7))
+ display_clock = 133;
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("display", display_clock);
+ }
+
+
+ printf("\n");
+ return -1;
+}
+
+#define STATS_LEN (20)
+#define PERCENTAGE_BAR_END (79 - STATS_LEN)
+
+static void
+print_percentage_bar(float percent, int cur_line_len)
+{
+ int bar_avail_len = (PERCENTAGE_BAR_END - cur_line_len - 1) * 8;
+ int bar_len = bar_avail_len * (percent + .5) / 100.0;
+ int i;
+
+ for (i = bar_len; i >= 8; i -= 8) {
+ printf("%s", bars[8]);
+ cur_line_len++;
+ }
+ if (i) {
+ printf("%s", bars[i]);
+ cur_line_len++;
+ }
+
+ /* NB: We can't use a field width with utf8 so we manually
+ * guarantee a field with of 45 chars for any bar. */
+ printf("%*s", PERCENTAGE_BAR_END - cur_line_len, "");
+}
+
+struct ring {
+ const char *name;
+ uint32_t mmio;
+ int head, tail, size;
+ uint64_t full;
+ int idle;
+};
+
+static uint32_t ring_read(struct ring *ring, uint32_t reg)
+{
+ return INREG(ring->mmio + reg);
+}
+
+static void ring_init(struct ring *ring)
+{
+ ring->size = (((ring_read(ring, RING_LEN) & RING_NR_PAGES) >> 12) + 1) * 4096;
+}
+
+static void ring_reset(struct ring *ring)
+{
+ ring->idle = ring->full = 0;
+}
+
+static void ring_sample(struct ring *ring)
+{
+ int full;
+
+ if (!ring->size)
+ return;
+
+ ring->head = ring_read(ring, RING_HEAD) & HEAD_ADDR;
+ ring->tail = ring_read(ring, RING_TAIL) & TAIL_ADDR;
+
+ if (ring->tail == ring->head)
+ ring->idle++;
+
+ full = ring->tail - ring->head;
+ if (full < 0)
+ full += ring->size;
+ ring->full += full;
+}
+
+static void ring_print_header(FILE *out, struct ring *ring)
+{
+ fprintf(out, "%.6s%%\tops\t",
+ ring->name
+ );
+}
+
+static void ring_print(struct ring *ring, unsigned long samples_per_sec)
+{
+ int percent_busy, len;
+
+ if (!ring->size)
+ return;
+
+ percent_busy = 100 - 100 * ring->idle / samples_per_sec;
+
+ len = printf("%25s busy: %3d%%: ", ring->name, percent_busy);
+ print_percentage_bar (percent_busy, len);
+ printf("%24s space: %d/%d\n",
+ ring->name,
+ (int)(ring->full / samples_per_sec),
+ ring->size);
+}
+
+static void ring_log(struct ring *ring, unsigned long samples_per_sec,
+ FILE *output)
+{
+ if (ring->size)
+ fprintf(output, "%3d\t%d\t",
+ (int)(100 - 100 * ring->idle / samples_per_sec),
+ (int)(ring->full / samples_per_sec));
+ else
+ fprintf(output, "-1\t-1\t");
+}
+
+static void
+usage(const char *appname)
+{
+ printf("intel_gpu_top - Display a top-like summary of Intel GPU usage\n"
+ "\n"
+ "usage: %s [parameters]\n"
+ "\n"
+ "The following parameters apply:\n"
+ "[-s <samples>] samples per seconds (default %d)\n"
+ "[-e <command>] command to profile\n"
+ "[-o <file>] output statistics to file. If file is '-',"
+ " run in batch mode and output statistics to stdio only \n"
+ "[-h] show this help screen\n"
+ "\n",
+ appname,
+ SAMPLES_PER_SEC
+ );
+ return;
+}
+
+int main(int argc, char **argv)
+{
+ uint32_t devid;
+ struct pci_device *pci_dev;
+ struct ring render_ring = {
+ .name = "render",
+ .mmio = 0x2030,
+ }, bsd_ring = {
+ .name = "bitstream",
+ .mmio = 0x4030,
+ }, bsd6_ring = {
+ .name = "bitstream",
+ .mmio = 0x12030,
+ }, blt_ring = {
+ .name = "blitter",
+ .mmio = 0x22030,
+ };
+ int i, ch;
+ int samples_per_sec = SAMPLES_PER_SEC;
+ FILE *output = NULL;
+ double elapsed_time=0;
+ int print_headers=1;
+ pid_t child_pid=-1;
+ int child_stat;
+ char *cmd=NULL;
+ int interactive=1;
+
+ /* Parse options? */
+ while ((ch = getopt(argc, argv, "s:o:e:h")) != -1) {
+ switch (ch) {
+ case 'e': cmd = strdup(optarg);
+ break;
+ case 's': samples_per_sec = atoi(optarg);
+ if (samples_per_sec < 100) {
+ fprintf(stderr, "Error: samples per second must be >= 100\n");
+ exit(1);
+ }
+ break;
+ case 'o':
+ if (!strcmp(optarg, "-")) {
+ /* Running in non-interactive mode */
+ interactive = 0;
+ output = stdout;
+ }
+ else
+ output = fopen(optarg, "w");
+ if (!output)
+ {
+ perror("fopen");
+ exit(1);
+ }
+ break;
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ default:
+ fprintf(stderr, "Invalid flag %c!\n", (char)optopt);
+ usage(argv[0]);
+ exit(1);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id;
+ intel_get_mmio(pci_dev);
+ init_instdone_definitions(devid);
+
+ /* Do we have a command to run? */
+ if (cmd != NULL) {
+ if (output) {
+ fprintf(output, "# Profiling: %s\n", cmd);
+ fflush(output);
+ }
+ child_pid = fork();
+ if (child_pid < 0) {
+ perror("fork");
+ exit(1);
+ }
+ else if (child_pid == 0) {
+ int res;
+ res = system(cmd);
+ if (res < 0)
+ perror("running command");
+ if (output) {
+ fflush(output);
+ fprintf(output, "# %s exited with status %d\n", cmd, res);
+ fflush(output);
+ }
+ free(cmd);
+ exit(0);
+ } else {
+ free(cmd);
+ }
+ }
+
+ for (i = 0; i < num_instdone_bits; i++) {
+ top_bits[i].bit = &instdone_bits[i];
+ top_bits[i].count = 0;
+ top_bits_sorted[i] = &top_bits[i];
+ }
+
+ /* Grab access to the registers */
+ intel_register_access_init(pci_dev, 0);
+
+ ring_init(&render_ring);
+ if (IS_GEN4(devid) || IS_GEN5(devid))
+ ring_init(&bsd_ring);
+ if (IS_GEN6(devid) || IS_GEN7(devid)) {
+ ring_init(&bsd6_ring);
+ ring_init(&blt_ring);
+ }
+
+ /* Initialize GPU stats */
+ if (HAS_STATS_REGS(devid)) {
+ for (i = 0; i < STATS_COUNT; i++) {
+ uint32_t stats_high, stats_low, stats_high_2;
+
+ do {
+ stats_high = INREG(stats_regs[i] + 4);
+ stats_low = INREG(stats_regs[i]);
+ stats_high_2 = INREG(stats_regs[i] + 4);
+ } while (stats_high != stats_high_2);
+
+ last_stats[i] = (uint64_t)stats_high << 32 |
+ stats_low;
+ }
+ }
+
+ for (;;) {
+ int j;
+ unsigned long long t1, ti, tf, t2;
+ unsigned long long def_sleep = 1000000 / samples_per_sec;
+ unsigned long long last_samples_per_sec = samples_per_sec;
+ unsigned short int max_lines;
+ struct winsize ws;
+ char clear_screen[] = {0x1b, '[', 'H',
+ 0x1b, '[', 'J',
+ 0x0};
+ int percent;
+ int len;
+
+ t1 = gettime();
+
+ ring_reset(&render_ring);
+ ring_reset(&bsd_ring);
+ ring_reset(&bsd6_ring);
+ ring_reset(&blt_ring);
+
+ for (i = 0; i < samples_per_sec; i++) {
+ long long interval;
+ ti = gettime();
+ if (IS_965(devid)) {
+ instdone = INREG(INST_DONE_I965);
+ instdone1 = INREG(INST_DONE_1);
+ } else
+ instdone = INREG(INST_DONE);
+
+ for (j = 0; j < num_instdone_bits; j++)
+ update_idle_bit(&top_bits[j]);
+
+ ring_sample(&render_ring);
+ ring_sample(&bsd_ring);
+ ring_sample(&bsd6_ring);
+ ring_sample(&blt_ring);
+
+ tf = gettime();
+ if (tf - t1 >= 1000000) {
+ /* We are out of sync, bail out */
+ last_samples_per_sec = i+1;
+ break;
+ }
+ interval = def_sleep - (tf - ti);
+ if (interval > 0)
+ usleep(interval);
+ }
+
+ if (HAS_STATS_REGS(devid)) {
+ for (i = 0; i < STATS_COUNT; i++) {
+ uint32_t stats_high, stats_low, stats_high_2;
+
+ do {
+ stats_high = INREG(stats_regs[i] + 4);
+ stats_low = INREG(stats_regs[i]);
+ stats_high_2 = INREG(stats_regs[i] + 4);
+ } while (stats_high != stats_high_2);
+
+ stats[i] = (uint64_t)stats_high << 32 |
+ stats_low;
+ }
+ }
+
+ qsort(top_bits_sorted, num_instdone_bits,
+ sizeof(struct top_bit *), top_bits_sort);
+
+ /* Limit the number of lines printed to the terminal height so the
+ * most important info (at the top) will stay on screen. */
+ max_lines = -1;
+ if (ioctl(0, TIOCGWINSZ, &ws) != -1)
+ max_lines = ws.ws_row - 6; /* exclude header lines */
+ if (max_lines >= num_instdone_bits)
+ max_lines = num_instdone_bits;
+
+ t2 = gettime();
+ elapsed_time += (t2 - t1) / 1000000.0;
+
+ if (interactive) {
+ printf("%s", clear_screen);
+ print_clock_info(pci_dev);
+
+ ring_print(&render_ring, last_samples_per_sec);
+ ring_print(&bsd_ring, last_samples_per_sec);
+ ring_print(&bsd6_ring, last_samples_per_sec);
+ ring_print(&blt_ring, last_samples_per_sec);
+
+ printf("\n%30s %s\n", "task", "percent busy");
+ for (i = 0; i < max_lines; i++) {
+ if (top_bits_sorted[i]->count > 0) {
+ percent = (top_bits_sorted[i]->count * 100) /
+ last_samples_per_sec;
+ len = printf("%30s: %3d%%: ",
+ top_bits_sorted[i]->bit->name,
+ percent);
+ print_percentage_bar (percent, len);
+ } else {
+ printf("%*s", PERCENTAGE_BAR_END, "");
+ }
+
+ if (i < STATS_COUNT && HAS_STATS_REGS(devid)) {
+ printf("%13s: %llu (%lld/sec)",
+ stats_reg_names[i],
+ (long long)stats[i],
+ (long long)(stats[i] - last_stats[i]));
+ last_stats[i] = stats[i];
+ } else {
+ if (!top_bits_sorted[i]->count)
+ break;
+ }
+ printf("\n");
+ }
+ }
+ if (output) {
+ /* Print headers for columns at first run */
+ if (print_headers) {
+ fprintf(output, "# time\t");
+ ring_print_header(output, &render_ring);
+ ring_print_header(output, &bsd_ring);
+ ring_print_header(output, &bsd6_ring);
+ ring_print_header(output, &blt_ring);
+ for (i = 0; i < MAX_NUM_TOP_BITS; i++) {
+ if (i < STATS_COUNT && HAS_STATS_REGS(devid)) {
+ fprintf(output, "%.6s\t",
+ stats_reg_names[i]
+ );
+ }
+ if (!top_bits[i].count)
+ continue;
+ }
+ fprintf(output, "\n");
+ print_headers = 0;
+ }
+
+ /* Print statistics */
+ fprintf(output, "%.2f\t", elapsed_time);
+ ring_log(&render_ring, last_samples_per_sec, output);
+ ring_log(&bsd_ring, last_samples_per_sec, output);
+ ring_log(&bsd6_ring, last_samples_per_sec, output);
+ ring_log(&blt_ring, last_samples_per_sec, output);
+
+ for (i = 0; i < MAX_NUM_TOP_BITS; i++) {
+ if (i < STATS_COUNT && HAS_STATS_REGS(devid)) {
+ fprintf(output, "%lu\t",
+ stats[i] - last_stats[i]);
+ last_stats[i] = stats[i];
+ }
+ if (!top_bits[i].count)
+ continue;
+ }
+ fprintf(output, "\n");
+ fflush(output);
+ }
+
+ for (i = 0; i < num_instdone_bits; i++) {
+ top_bits_sorted[i]->count = 0;
+
+ if (i < STATS_COUNT)
+ last_stats[i] = stats[i];
+ }
+
+ /* Check if child has gone */
+ if (child_pid > 0) {
+ int res;
+ if ((res = waitpid(child_pid, &child_stat, WNOHANG)) == -1) {
+ perror("waitpid");
+ exit(1);
+ }
+ if (res == 0)
+ continue;
+ if (WIFEXITED(child_stat))
+ break;
+ }
+ }
+
+ fclose(output);
+
+ intel_register_access_fini();
+ return 0;
+}
diff --git a/tools/intel_gtt.c b/tools/intel_gtt.c
new file mode 100644
index 00000000..05d36d71
--- /dev/null
+++ b/tools/intel_gtt.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <unistd.h>
+
+#include "intel_gpu_tools.h"
+
+#define INGTT(offset) (*(volatile uint32_t *)(gtt + (offset) / (KB(4) / 4)))
+
+#define KB(x) ((x) * 1024)
+#define MB(x) ((x) * 1024 * 1024)
+
+int main(int argc, char **argv)
+{
+ struct pci_device *pci_dev;
+ int start, aper_size;
+ unsigned char *gtt;
+ uint32_t devid;
+ int flag[] = {
+ PCI_DEV_MAP_FLAG_WRITE_COMBINE,
+ PCI_DEV_MAP_FLAG_WRITABLE,
+ 0
+ }, f;
+
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id;
+
+ if (IS_GEN2(devid)) {
+ printf("Unsupported chipset for gtt dumper\n");
+ exit(1);
+ }
+
+ for (f = 0; flag[f] != 0; f++) {
+ if (IS_GEN3(devid)) {
+ /* 915/945 chips has GTT range in bar 3 */
+ if (pci_device_map_range(pci_dev,
+ pci_dev->regions[3].base_addr,
+ pci_dev->regions[3].size,
+ flag[f],
+ (void **)&gtt) == 0)
+ break;
+ } else {
+ int offset;
+ if (IS_G4X(devid) || IS_GEN5(devid))
+ offset = MB(2);
+ else
+ offset = KB(512);
+ if (pci_device_map_range(pci_dev,
+ pci_dev->regions[0].base_addr + offset,
+ offset,
+ flag[f],
+ (void **)&gtt) == 0)
+ break;
+ }
+ }
+ if (flag[f] == 0) {
+ printf("Failed to map gtt\n");
+ exit(1);
+ }
+
+ aper_size = pci_dev->regions[2].size;
+
+ for (start = 0; start < aper_size; start += KB(4)) {
+ uint32_t start_pte = INGTT(start);
+ uint32_t end;
+ int constant_length = 0;
+ int linear_length = 0;
+
+ /* Check if it's a linear sequence */
+ for (end = start + KB(4); end < aper_size; end += KB(4)) {
+ uint32_t end_pte = INGTT(end);
+ if (end_pte == start_pte + (end - start))
+ linear_length++;
+ else
+ break;
+ }
+ if (linear_length > 0) {
+ printf("0x%08x - 0x%08x: linear from "
+ "0x%08x to 0x%08x\n",
+ start, end - KB(4),
+ start_pte, start_pte + (end - start) - KB(4));
+ start = end - KB(4);
+ continue;
+ }
+
+ /* Check if it's a constant sequence */
+ for (end = start + KB(4); end < aper_size; end += KB(4)) {
+ uint32_t end_pte = INGTT(end);
+ if (end_pte == start_pte)
+ constant_length++;
+ else
+ break;
+ }
+ if (constant_length > 0) {
+ printf("0x%08x - 0x%08x: constant 0x%08x\n",
+ start, end - KB(4), start_pte);
+ start = end - KB(4);
+ continue;
+ }
+
+ printf("0x%08x: 0x%08x\n", start, start_pte);
+ }
+
+ return 0;
+}
diff --git a/tools/intel_infoframes.c b/tools/intel_infoframes.c
new file mode 100644
index 00000000..f5a40067
--- /dev/null
+++ b/tools/intel_infoframes.c
@@ -0,0 +1,1142 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Paulo Zanoni <paulo.r.zanoni@intel.com>
+ *
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include "intel_gpu_tools.h"
+
+typedef enum {
+ TRANSC_A = 0,
+ TRANSC_B = 1,
+ TRANSC_C = 2,
+ TRANSC_INVALID
+} Transcoder;
+
+typedef enum {
+ REG_HDMIB_GEN4 = 0x61140,
+ REG_HDMIC_GEN4 = 0x61160,
+ REG_HDMIB_PCH = 0xe1140,
+ REG_HDMIC_PCH = 0xe1150,
+ REG_HDMID_PCH = 0xe1160,
+ REG_DIP_CTL_GEN4 = 0x61170,
+ REG_DIP_CTL_A = 0xe0200,
+ REG_DIP_CTL_B = 0xe1200,
+ REG_DIP_CTL_C = 0xe2200,
+ REG_DIP_DATA_GEN4 = 0x61178,
+ REG_DIP_DATA_A = 0xe0208,
+ REG_DIP_DATA_B = 0xe1208,
+ REG_DIP_DATA_C = 0xe2208,
+} Register;
+
+typedef enum {
+ DIP_AVI = 0,
+ DIP_VENDOR = 1,
+ DIP_GAMUT = 2,
+ DIP_SPD = 3,
+ DIP_INVALID,
+} DipType;
+
+typedef enum {
+ DIP_FREQ_ONCE = 0,
+ DIP_FREQ_EVERY_VSYNC = 1,
+ DIP_FREQ_EVERY_OTHER_VSYNC = 2,
+ DIP_FREQ_RESERVED = 3,
+} DipFrequency;
+
+typedef enum {
+ SOURCE_DEVICE_UNKNOWN = 0x00,
+ SOURCE_DEVICE_DIGITAL_STB = 0x01,
+ SOURCE_DEVICE_DVD_PLAYER = 0x02,
+ SOURCE_DEVICE_D_VHS = 0x03,
+ SOURCE_DEVICE_HDD_VIDEORECORDER = 0x04,
+ SOURCE_DEVICE_DVC = 0x05,
+ SOURCE_DEVICE_DSC = 0x06,
+ SOURCE_DEVICE_VIDEO_CD = 0x07,
+ SOURCE_DEVICE_GAME = 0x08,
+ SOURCE_DEVICE_PC_GENERAL = 0x09,
+ SOURCE_DEVICE_BLU_RAY_DISK = 0x0a,
+ SOURCE_DEVICE_SUPER_AUDIO_CD = 0x0b,
+ SOURCE_DEVICE_RESERVED = 0x0c
+} SourceDevice;
+
+#define HDMI_PORT_ENABLE (1 << 31)
+#define HDMI_PORT_TRANSCODER_GEN4 (1 << 30)
+#define HDMI_PORT_TRANSCODER_IBX (1 << 30)
+#define HDMI_PORT_TRANSCODER_CPT (3 << 29)
+#define HDMI_PORT_ENCODING (3 << 10)
+#define HDMI_PORT_MODE (1 << 9)
+#define HDMI_PORT_AUDIO (1 << 6)
+#define HDMI_PORT_DETECTED (1 << 2)
+
+#define DIP_CTL_ENABLE (1 << 31)
+#define DIP_CTL_GCP_ENABLE (1 << 25)
+#define DIP_CTL_SPD_ENABLE (1 << 24)
+#define DIP_CTL_GAMUT_ENABLE (1 << 23)
+#define DIP_CTL_VENDOR_ENABLE (1 << 22)
+#define DIP_CTL_AVI_ENABLE (1 << 21)
+#define DIP_CTL_BUFFER_INDEX (3 << 19)
+#define DIP_CTL_BUFFER_AVI (0 << 19)
+#define DIP_CTL_BUFFER_VENDOR (1 << 19)
+#define DIP_CTL_BUFFER_GAMUT (2 << 19)
+#define DIP_CTL_BUFFER_SPD (3 << 19)
+#define DIP_CTL_FREQUENCY (3 << 16)
+#define DIP_CTL_FREQ_ONCE (0 << 16)
+#define DIP_CTL_FREQ_EVERY (1 << 16)
+#define DIP_CTL_FREQ_EVERY_OTHER (2 << 16)
+#define DIP_CTL_BUFFER_SIZE (15 << 8)
+#define DIP_CTL_ACCESS_ADDR (15 << 0)
+
+#define DIP_CTL_PORT_SEL_MASK_GEN4 (3 << 29)
+#define DIP_CTL_PORT_SEL_B_GEN4 (1 << 29)
+#define DIP_CTL_PORT_SEL_C_GEN4 (2 << 29)
+#define DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 (1 << 28)
+
+#define AVI_INFOFRAME_TYPE 0x82
+#define AVI_INFOFRAME_VERSION 0x02
+#define AVI_INFOFRAME_LENGTH 0x0d
+#define SPD_INFOFRAME_TYPE 0x83
+#define SPD_INFOFRAME_VERSION 0x01
+#define SPD_INFOFRAME_LENGTH 0x19
+
+typedef struct {
+ uint8_t type;
+ uint8_t version;
+ uint8_t length;
+ uint8_t ecc;
+} DipInfoFrameHeader;
+
+typedef union {
+ struct {
+ DipInfoFrameHeader header;
+ uint8_t checksum;
+
+ uint8_t S :2;
+ uint8_t B :2;
+ uint8_t A :1;
+ uint8_t Y :2;
+ uint8_t Rsvd0 :1;
+
+ uint8_t R :4;
+ uint8_t M :2;
+ uint8_t C :2;
+
+ uint8_t SC :2;
+ uint8_t Q :2;
+ uint8_t EC :3;
+ uint8_t ITC :1;
+
+ uint8_t VIC :7;
+ uint8_t Rsvd1 :1;
+
+ uint8_t PR :4;
+ uint8_t Rsvd2 :4;
+
+ uint16_t top;
+ uint16_t bottom;
+ uint16_t left;
+ uint16_t right;
+
+ uint16_t Rsvd3;
+ uint32_t Rsvd4[3];
+ } avi;
+ struct {
+ DipInfoFrameHeader header;
+ uint8_t checksum;
+ uint8_t vendor[8];
+ uint8_t description[16];
+ uint8_t source;
+ } __attribute__((packed)) spd;
+ struct {
+ DipInfoFrameHeader header;
+ uint8_t body[27];
+ } generic;
+ uint8_t data8[128];
+ uint32_t data32[16];
+} DipInfoFrame;
+
+Register gen4_hdmi_ports[] = {
+ REG_HDMIB_GEN4,
+ REG_HDMIC_GEN4,
+};
+Register pch_hdmi_ports[] = {
+ REG_HDMIB_PCH,
+ REG_HDMIC_PCH,
+ REG_HDMID_PCH
+};
+Register pch_dip_ctl_regs[] = {
+ REG_DIP_CTL_A,
+ REG_DIP_CTL_B,
+ REG_DIP_CTL_C
+};
+Register pch_dip_data_regs[] = {
+ REG_DIP_DATA_A,
+ REG_DIP_DATA_B,
+ REG_DIP_DATA_C
+};
+const char *hdmi_port_names[] = {
+ "HDMIB",
+ "HDMIC",
+ "HDMID"
+};
+const char *transcoder_names[] = {
+ "A",
+ "B",
+ "C"
+};
+const char *dip_frequency_names[] = {
+ "once",
+ "every vsync",
+ "every other vsync",
+ "reserved (invalid)"
+};
+
+int gen = 0;
+
+static const char *spd_source_to_string(SourceDevice source)
+{
+ switch (source) {
+ case SOURCE_DEVICE_UNKNOWN:
+ return "unknown";
+ case SOURCE_DEVICE_DIGITAL_STB:
+ return "digital stb";
+ case SOURCE_DEVICE_DVD_PLAYER:
+ return "dvd player";
+ case SOURCE_DEVICE_D_VHS:
+ return "d vhs";
+ case SOURCE_DEVICE_HDD_VIDEORECORDER:
+ return "hdd videorecorder";
+ case SOURCE_DEVICE_DVC:
+ return "dvc";
+ case SOURCE_DEVICE_DSC:
+ return "dsc";
+ case SOURCE_DEVICE_VIDEO_CD:
+ return "video cd";
+ case SOURCE_DEVICE_GAME:
+ return "game";
+ case SOURCE_DEVICE_PC_GENERAL:
+ return "pc general";
+ case SOURCE_DEVICE_BLU_RAY_DISK:
+ return "blu-ray disk";
+ case SOURCE_DEVICE_SUPER_AUDIO_CD:
+ return "super audio cd";
+ default:
+ return "reserved";
+ }
+}
+
+static Register get_dip_ctl_reg(Transcoder transcoder)
+{
+ if (gen == 4)
+ return REG_DIP_CTL_GEN4;
+ else
+ return pch_dip_ctl_regs[transcoder];
+}
+
+static Register get_dip_data_reg(Transcoder transcoder)
+{
+ if (gen == 4)
+ return REG_DIP_DATA_GEN4;
+ else
+ return pch_dip_data_regs[transcoder];
+}
+
+static Register get_hdmi_port(int hdmi_port_index)
+{
+ if (gen == 4) {
+ assert(hdmi_port_index < 2);
+ return gen4_hdmi_ports[hdmi_port_index];
+ } else {
+ return pch_hdmi_ports[hdmi_port_index];
+ }
+}
+
+static void load_infoframe(Transcoder transcoder, DipInfoFrame *frame,
+ DipType type)
+{
+ Register ctl_reg = get_dip_ctl_reg(transcoder);
+ Register data_reg = get_dip_data_reg(transcoder);
+ uint32_t ctl_val;
+ uint32_t i;
+
+ ctl_val = INREG(ctl_reg);
+
+ ctl_val &= ~DIP_CTL_BUFFER_INDEX;
+ ctl_val |= type << 19;
+ OUTREG(ctl_reg, ctl_val);
+ ctl_val = INREG(ctl_reg);
+
+ ctl_val &= ~DIP_CTL_ACCESS_ADDR;
+ OUTREG(ctl_reg, ctl_val);
+
+ for (i = 0; i < 16; i++) {
+ ctl_val = INREG(ctl_reg);
+ assert((ctl_val & DIP_CTL_ACCESS_ADDR) == i);
+ frame->data32[i] = INREG(data_reg);
+ }
+}
+
+static int infoframe_valid_checksum(DipInfoFrame *frame)
+{
+ int i;
+ int length = frame->generic.header.length;
+ uint8_t csum;
+
+ csum = frame->generic.header.type + frame->generic.header.version +
+ frame->generic.header.length; /* no ecc */
+ for (i = 0; i < length + 1; i++)
+ csum += frame->generic.body[i];
+
+ return (csum == 0);
+}
+
+static void infoframe_fix_checksum(DipInfoFrame *frame)
+{
+ int i;
+ int length = frame->generic.header.length;
+ uint8_t csum;
+
+ csum = frame->generic.header.type + frame->generic.header.version +
+ frame->generic.header.length; /* no ecc */
+ /* Length does not include the header field nor the checksum */
+ for (i = 1; i < length + 1; i++)
+ csum += frame->generic.body[i];
+ frame->generic.body[0] = 0x100 - csum;
+}
+
+static void dump_port_info(int hdmi_port_index)
+{
+ Register port = get_hdmi_port(hdmi_port_index);
+ uint32_t val = INREG(port);
+ Transcoder transcoder;
+
+ printf("\nPort %s:\n", hdmi_port_names[hdmi_port_index]);
+ printf("- %sdetected\n", val & HDMI_PORT_DETECTED ? "" : "not ");
+ printf("- %s\n", val & HDMI_PORT_ENABLE ? "enabled" : "disabled");
+
+ if (!(val & HDMI_PORT_ENABLE))
+ return;
+
+ if (gen == 4)
+ transcoder = (val & HDMI_PORT_TRANSCODER_GEN4) >> 30;
+ else if (pch >= PCH_CPT)
+ transcoder = (val & HDMI_PORT_TRANSCODER_CPT) >> 29;
+ else
+ transcoder = (val & HDMI_PORT_TRANSCODER_IBX) >> 30;
+ printf("- transcoder: %s\n", transcoder_names[transcoder]);
+
+ switch ((val & HDMI_PORT_ENCODING) >> 10) {
+ case 0:
+ printf("- mode: SDVO\n");
+ break;
+ case 2:
+ printf("- mode: TMDS\n");
+ break;
+ default:
+ printf("- mode: INVALID!\n");
+ }
+
+ printf("- mode: %s\n", val & HDMI_PORT_MODE ? "HDMI" : "DVI");
+ printf("- audio: %s\n", val & HDMI_PORT_AUDIO ? "enabled" : "disabled");
+}
+
+static void dump_raw_infoframe(DipInfoFrame *frame)
+{
+ unsigned int i;
+ printf("- raw:");
+ for (i = 0; i < 16; i++) {
+ if (i % 4 == 0)
+ printf("\n ");
+ printf(" %08x", frame->data32[i]);
+ }
+ printf("\n");
+}
+
+static void dump_avi_info(Transcoder transcoder)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ DipFrequency freq;
+ DipInfoFrame frame;
+
+ load_infoframe(transcoder, &frame, DIP_AVI);
+ val = INREG(reg);
+
+ printf("AVI InfoFrame:\n");
+
+ if (gen == 4) {
+ printf("- %sbeing transmitted\n",
+ val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
+ }
+
+ freq = (val & DIP_CTL_FREQUENCY) >> 16;
+ printf("- frequency: %s\n", dip_frequency_names[freq]);
+
+ dump_raw_infoframe(&frame);
+
+ printf("- type: %x, version: %x, length: %x, ecc: %x, checksum: %x\n",
+ frame.avi.header.type, frame.avi.header.version,
+ frame.avi.header.length, frame.avi.header.ecc,
+ frame.avi.checksum);
+ printf("- S: %x, B: %x, A: %x, Y: %x, Rsvd0: %x\n",
+ frame.avi.S, frame.avi.B, frame.avi.A, frame.avi.Y,
+ frame.avi.Rsvd0);
+ printf("- R: %x, M: %x, C: %x\n",
+ frame.avi.R, frame.avi.M, frame.avi.C);
+ printf("- SC: %x, Q: %x, EC: %x, ITC: %x\n",
+ frame.avi.SC, frame.avi.Q, frame.avi.EC, frame.avi.ITC);
+ printf("- VIC: %x, Rsvd1: %x\n", frame.avi.VIC, frame.avi.Rsvd1);
+ printf("- PR: %x, Rsvd2: %x\n", frame.avi.PR, frame.avi.Rsvd2);
+ printf("- top: %x, bottom: %x, left: %x, right: %x\n",
+ frame.avi.top, frame.avi.bottom, frame.avi.left,
+ frame.avi.right);
+ printf("- Rsvd3: %x, Rsvd4[0]: %x, Rsvd4[1]: %x, Rsvd4[2]: %x\n",
+ frame.avi.Rsvd3, frame.avi.Rsvd4[0], frame.avi.Rsvd4[1],
+ frame.avi.Rsvd4[2]);
+
+ if (!infoframe_valid_checksum(&frame))
+ printf("Invalid InfoFrame checksum!\n");
+}
+
+static void dump_vendor_info(Transcoder transcoder)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ DipFrequency freq;
+ DipInfoFrame frame;
+
+ load_infoframe(transcoder, &frame, DIP_VENDOR);
+ val = INREG(reg);
+
+ printf("Vendor InfoFrame:\n");
+
+ if (gen == 4) {
+ printf("- %sbeing transmitted\n",
+ val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
+ }
+
+ freq = (val & DIP_CTL_FREQUENCY) >> 16;
+ printf("- frequency: %s\n", dip_frequency_names[freq]);
+
+ dump_raw_infoframe(&frame);
+
+ if (!infoframe_valid_checksum(&frame))
+ printf("Invalid InfoFrame checksum!\n");
+}
+
+static void dump_gamut_info(Transcoder transcoder)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ DipFrequency freq;
+ DipInfoFrame frame;
+
+ load_infoframe(transcoder, &frame, DIP_GAMUT);
+ val = INREG(reg);
+
+ printf("Gamut InfoFrame:\n");
+
+ if (gen == 4) {
+ printf("- %sbeing transmitted\n",
+ val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
+ }
+
+ freq = (val & DIP_CTL_FREQUENCY) >> 16;
+ printf("- frequency: %s\n", dip_frequency_names[freq]);
+
+ dump_raw_infoframe(&frame);
+
+ if (!infoframe_valid_checksum(&frame))
+ printf("Invalid InfoFrame checksum!\n");
+}
+
+static void dump_spd_info(Transcoder transcoder)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ DipFrequency freq;
+ DipInfoFrame frame;
+ char vendor[9];
+ char description[17];
+
+ load_infoframe(transcoder, &frame, DIP_SPD);
+ val = INREG(reg);
+
+ printf("SPD InfoFrame:\n");
+
+ if (gen == 4) {
+ printf("- %sbeing transmitted\n",
+ val & DIP_CTL_BUFFER_TRANS_ACTIVE_GEN4 ? "" : "not ");
+ }
+
+ freq = (val & DIP_CTL_FREQUENCY) >> 16;
+ printf("- frequency: %s\n", dip_frequency_names[freq]);
+
+ dump_raw_infoframe(&frame);
+
+ printf("- type: %x, version: %x, length: %x, ecc: %x, checksum: %x\n",
+ frame.spd.header.type, frame.spd.header.version,
+ frame.spd.header.length, frame.spd.header.ecc,
+ frame.spd.checksum);
+
+ memcpy(vendor, frame.spd.vendor, 8);
+ vendor[8] = '\0';
+ memcpy(description, frame.spd.description, 16);
+ description[16] = '\0';
+
+ printf("- vendor: %s\n", vendor);
+ printf("- description: %s\n", description);
+ printf("- source: %s\n", spd_source_to_string(frame.spd.source));
+
+ if (!infoframe_valid_checksum(&frame))
+ printf("Invalid InfoFrame checksum!\n");
+}
+
+static void dump_transcoder_info(Transcoder transcoder)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+
+ if (gen == 4) {
+ printf("\nDIP information:\n");
+ switch (val & DIP_CTL_PORT_SEL_MASK_GEN4) {
+ case DIP_CTL_PORT_SEL_B_GEN4:
+ printf("- port B\n");
+ break;
+ case DIP_CTL_PORT_SEL_C_GEN4:
+ printf("- port C\n");
+ break;
+ default:
+ printf("- INVALID port!\n");
+ }
+ } else {
+ printf("\nTranscoder %s:\n", transcoder_names[transcoder]);
+ }
+ printf("- %s\n", val & DIP_CTL_ENABLE ? "enabled" : "disabled");
+ if (!(val & DIP_CTL_ENABLE))
+ return;
+
+ printf("- GCP: %s\n", val & DIP_CTL_GCP_ENABLE ?
+ "enabled" : "disabled");
+
+ if (val & DIP_CTL_AVI_ENABLE)
+ dump_avi_info(transcoder);
+ if (val & DIP_CTL_VENDOR_ENABLE)
+ dump_vendor_info(transcoder);
+ if (val & DIP_CTL_GAMUT_ENABLE)
+ dump_gamut_info(transcoder);
+ if (val & DIP_CTL_SPD_ENABLE)
+ dump_spd_info(transcoder);
+}
+
+static void dump_all_info(void)
+{
+ unsigned int i;
+
+ if (gen == 4) {
+ for (i = 0; i < ARRAY_SIZE(gen4_hdmi_ports); i++)
+ dump_port_info(i);
+ dump_transcoder_info(0);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(pch_hdmi_ports); i++)
+ dump_port_info(i);
+ for (i = 0; i < ARRAY_SIZE(pch_dip_ctl_regs); i++)
+ dump_transcoder_info(i);
+ }
+}
+
+static void write_infoframe(Transcoder transcoder, DipType type,
+ DipInfoFrame *frame)
+{
+ Register ctl_reg = get_dip_ctl_reg(transcoder);
+ Register data_reg = get_dip_data_reg(transcoder);
+ uint32_t ctl_val;
+ unsigned int i;
+
+ ctl_val = INREG(ctl_reg);
+ ctl_val &= ~DIP_CTL_BUFFER_INDEX;
+ ctl_val |= (type << 19);
+ ctl_val &= ~DIP_CTL_ACCESS_ADDR;
+ OUTREG(ctl_reg, ctl_val);
+
+ for (i = 0; i < 8; i++) {
+ ctl_val = INREG(ctl_reg);
+ assert((ctl_val & DIP_CTL_ACCESS_ADDR) == i);
+ OUTREG(data_reg, frame->data32[i]);
+ }
+}
+
+static void disable_infoframe(Transcoder transcoder, DipType type)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ if (gen != 4 && type == DIP_AVI)
+ val &= ~DIP_CTL_ENABLE;
+ val &= ~(1 << (21 + type));
+ OUTREG(reg, val);
+}
+
+static void enable_infoframe(Transcoder transcoder, DipType type)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ if (gen != 4 && type == DIP_AVI)
+ val |= DIP_CTL_ENABLE;
+ val |= (1 << (21 + type));
+ OUTREG(reg, val);
+}
+
+static int parse_infoframe_option_u(const char *name, const char *s,
+ uint32_t min, uint32_t max,
+ uint32_t *value, char **commands)
+{
+ int read, rc;
+ if (!strcmp(name, s)) {
+ rc = sscanf(*commands, "%x%n", value, &read);
+ *commands = &(*commands)[read];
+ if (rc != 1) {
+ printf("Invalid value.\n");
+ return 0;
+ }
+
+ if (*value < min || *value > max) {
+ printf("Value outside allowed range.\n");
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static int parse_infoframe_option_s(const char *name, const char *s,
+ int min_size, int max_size,
+ char *value, char **commands)
+{
+ int size, read, rc;
+ if (!strcmp(name, s)) {
+ rc = sscanf(*commands, "%31s%n", value, &read);
+ *commands = &(*commands)[read];
+ if (rc != 1) {
+ printf("Invalid value.\n");
+ return 0;
+ }
+
+ size = strlen(value);
+ if (size < min_size || size > max_size) {
+ printf("String either too big or too small.\n");
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static void change_avi_infoframe(Transcoder transcoder, char *commands)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ DipInfoFrame frame;
+ char option[32];
+ uint32_t option_val;
+ int rc, read;
+ char *current = commands;
+
+ load_infoframe(transcoder, &frame, DIP_AVI);
+ val = INREG(reg);
+
+ while (1) {
+ rc = sscanf(current, "%31s%n", option, &read);
+ current = &current[read];
+ if (rc == EOF) {
+ break;
+ } else if (rc != 1) {
+ printf("Invalid option: %s\n", option);
+ continue;
+ }
+
+ if (parse_infoframe_option_u("S", option, 0, 2, &option_val,
+ &current))
+ frame.avi.S = option_val;
+ else if (parse_infoframe_option_u("B", option, 0, 3,
+ &option_val, &current))
+ frame.avi.B = option_val;
+ else if (parse_infoframe_option_u("A", option, 0, 1,
+ &option_val, &current))
+ frame.avi.A = option_val;
+ else if (parse_infoframe_option_u("Y", option, 0, 2,
+ &option_val, &current))
+ frame.avi.Y = option_val;
+ else if (parse_infoframe_option_u("R", option, 0, 15,
+ &option_val, &current))
+ frame.avi.R = option_val;
+ else if (parse_infoframe_option_u("M", option, 0, 2,
+ &option_val, &current))
+ frame.avi.M = option_val;
+ else if (parse_infoframe_option_u("C", option, 0, 3,
+ &option_val, &current))
+ frame.avi.C = option_val;
+ else if (parse_infoframe_option_u("SC", option, 0, 3,
+ &option_val, &current))
+ frame.avi.SC = option_val;
+ else if (parse_infoframe_option_u("Q", option, 0, 2,
+ &option_val, &current))
+ frame.avi.Q = option_val;
+ else if (parse_infoframe_option_u("EC", option, 0, 1,
+ &option_val,&current))
+ frame.avi.EC = option_val;
+ else if (parse_infoframe_option_u("ITC", option, 0, 1,
+ &option_val, &current))
+ frame.avi.ITC = option_val;
+ else if (parse_infoframe_option_u("VIC", option, 0, 127,
+ &option_val, &current))
+ frame.avi.VIC = option_val;
+ else if (parse_infoframe_option_u("PR", option, 0, 15,
+ &option_val, &current))
+ frame.avi.PR = option_val;
+ else if (parse_infoframe_option_u("top", option, 0, 65535,
+ &option_val, &current))
+ frame.avi.top = option_val;
+ else if (parse_infoframe_option_u("bottom", option, 0, 65535,
+ &option_val, &current))
+ frame.avi.bottom = option_val;
+ else if (parse_infoframe_option_u("left", option, 0, 65535,
+ &option_val, &current))
+ frame.avi.left = option_val;
+ else if (parse_infoframe_option_u("right", option, 0, 65535,
+ &option_val, &current))
+ frame.avi.right = option_val;
+ else
+ printf("Unrecognized option: %s\n", option);
+ }
+
+ val &= ~DIP_CTL_FREQUENCY;
+ val |= DIP_CTL_FREQ_EVERY;
+ OUTREG(reg, val);
+
+ frame.avi.header.type = AVI_INFOFRAME_TYPE;
+ frame.avi.header.version = AVI_INFOFRAME_VERSION;
+ frame.avi.header.length = AVI_INFOFRAME_LENGTH;
+ frame.avi.Rsvd0 = 0;
+ frame.avi.Rsvd1 = 0;
+ frame.avi.Rsvd2 = 0;
+ frame.avi.Rsvd3 = 0;
+ frame.avi.Rsvd4[0] = 0;
+ frame.avi.Rsvd4[1] = 0;
+ frame.avi.Rsvd4[2] = 0;
+
+ infoframe_fix_checksum(&frame);
+
+ disable_infoframe(transcoder, DIP_AVI);
+ write_infoframe(transcoder, DIP_AVI, &frame);
+ enable_infoframe(transcoder, DIP_AVI);
+}
+
+static void change_spd_infoframe(Transcoder transcoder, char *commands)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ DipInfoFrame frame;
+ char option[16];
+ char option_val_s[32];
+ uint32_t option_val_i;
+ int rc, read;
+ char *current = commands;
+
+ load_infoframe(transcoder, &frame, DIP_SPD);
+ val = INREG(reg);
+
+ while (1) {
+ rc = sscanf(current, "%31s%n", option, &read);
+ current = &current[read];
+ if (rc == EOF) {
+ break;
+ } else if (rc != 1) {
+ printf("Invalid option: %s\n", option);
+ continue;
+ }
+
+ memset(option_val_s, 0, 32);
+
+ if (parse_infoframe_option_s("vendor", option, 0, 8,
+ option_val_s, &current))
+ memcpy(frame.spd.vendor, option_val_s, 8);
+ else if (parse_infoframe_option_s("description", option, 0, 16,
+ option_val_s, &current))
+ memcpy(frame.spd.description, option_val_s, 16);
+ else if (parse_infoframe_option_u("source", option, 0, 0x0c,
+ &option_val_i, &current))
+ frame.spd.source = option_val_i;
+ else
+ printf("Unrecognized option: %s\n", option);
+ }
+
+ val &= ~DIP_CTL_FREQUENCY;
+ val |= DIP_CTL_FREQ_EVERY_OTHER;
+ OUTREG(reg, val);
+
+ frame.spd.header.type = SPD_INFOFRAME_TYPE;
+ frame.spd.header.version = SPD_INFOFRAME_VERSION;
+ frame.spd.header.length = SPD_INFOFRAME_LENGTH;
+
+ infoframe_fix_checksum(&frame);
+
+ disable_infoframe(transcoder, DIP_SPD);
+ write_infoframe(transcoder, DIP_SPD, &frame);
+ enable_infoframe(transcoder, DIP_SPD);
+}
+
+static void change_infoframe_checksum(Transcoder transcoder, DipType type,
+ uint32_t selected_csum)
+{
+ DipInfoFrame frame;
+
+ load_infoframe(transcoder, &frame, type);
+ frame.generic.body[0] = selected_csum;
+ disable_infoframe(transcoder, type);
+ write_infoframe(transcoder, type, &frame);
+ enable_infoframe(transcoder, type);
+}
+
+static void change_infoframe_frequency(Transcoder transcoder, DipType type,
+ DipFrequency frequency)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+
+ if (type == DIP_AVI && frequency != DIP_FREQ_EVERY_VSYNC) {
+ printf("Error: AVI infoframe must be sent every VSync!\n");
+ frequency = DIP_FREQ_EVERY_VSYNC;
+ }
+
+ val &= ~DIP_CTL_FREQUENCY;
+ val |= (frequency << 16);
+ OUTREG(reg, val);
+}
+
+static void disable_dip(Transcoder transcoder)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ val &= ~DIP_CTL_ENABLE;
+ OUTREG(reg, val);
+}
+
+static void enable_dip(Transcoder transcoder)
+{
+ Register reg = get_dip_ctl_reg(transcoder);
+ uint32_t val = INREG(reg);
+ val |= DIP_CTL_ENABLE;
+ OUTREG(reg, val);
+}
+
+static void disable_hdmi_port(Register reg)
+{
+ uint32_t val = INREG(reg);
+ val &= ~HDMI_PORT_ENABLE;
+ OUTREG(reg, val);
+}
+
+static void enable_hdmi_port(Register reg)
+{
+ uint32_t val = INREG(reg);
+ val |= HDMI_PORT_ENABLE;
+ OUTREG(reg, val);
+}
+
+static void print_usage(void)
+{
+printf("Options:\n"
+" -d, --dump\n"
+" dump information about all transcoders\n"
+" -c, --change-fields [fields]\n"
+" change infoframe fields from selected transcoder\n"
+" -k, --change-checksum [checksum]\n"
+" change infoframe checksum (value in hex)\n"
+" -q, --change-frequency [frequency]\n"
+" change infoframe frequency (once, everyvsync or everyothervsync)\n"
+" -n, --disable\n"
+" disable the selected infoframe from the selected transcoder\n"
+" -N, --enable\n"
+" enable the selected infoframe from the selected transcoder\n"
+" -x, --disable-infoframes\n"
+" disable all infoframes from selected transcoder\n"
+" -X, --enable-infoframes\n"
+" enable sending infoframes on the selected transcoder\n"
+" -p, --disable-hdmi-port [port]\n"
+" disable hdmi port on the selected transcoder (B, C or D)\n"
+" -P, --enable-hdmi-port [port]\n"
+" enable hdmi port on the selected transcoder (B, C or D)\n"
+" -t, --transcoder\n"
+" select transcoder (A, B or C)\n"
+" -f, --infoframe\n"
+" select infoframe (AVI, Vendor, Gamut or SPD)\n"
+" -h, --help\n"
+" prints this message\n"
+"\n"
+"Examples:\n"
+"\n"
+" Dump information:\n"
+" intel_infoframes\n"
+"\n"
+" Disable overscan and set ITC on transcoder B:\n"
+" intel_infoframes -t B -f AVI -c 'S 2 ITC 1'\n"
+"\n"
+" Many actions on the same command:\n"
+" - enable overscan on transcoder A\n"
+" - enable overscan and change description on transcoder B\n"
+" - disable all infoframes on transcoder C\n"
+" - dump the resulting state:\n"
+" intel_infoframes -t A -f AVI -c 'S 1' \\\n"
+" -t B -f AVI -c 'S 2' \\\n"
+" -f SPD -c 'description Linux' \\\n"
+" -t C --disable-infoframes \\\n"
+" -d\n"
+"\n"
+" Even more:\n"
+" - print the help message\n"
+" - completely disable all infoframes on all transcoders\n"
+" - dump the state"
+" - enable sending infoframes on transcoder B, but disable all infoframes\n"
+" - enable AVI infoframes transcoder B, use underscan and declare ITC\n"
+" - also enable SPD infoframes on the same transcoder, change frequency to\n"
+" every vsync and change vendor, description and source\n"
+" - dump the state again\n"
+" intel_infoframes -h \\\n"
+" -t A -x -t B -x -t C -x \\\n"
+" -d \\\n"
+" -t A -X -f AVI -n -f Vendor -n \\\n"
+" -f Gamut -n -f SPD -n \\\n"
+" -f AVI -N -c 'S 2 ITC 1'\\\n"
+" -f SPD -q everyvsync \\\n"
+" -c 'vendor me description mine source 0x09' \\\n"
+" -d\n"
+"\n"
+"Infoframe fields used by the --change-fields option:\n"
+" - AVI infoframe fields:\n"
+" S B A Y R M C SC Q EC ITC VIC PR top bottom left right\n"
+" - SPD infoframe fields:\n"
+" vendor description source\n"
+" - Other infoframe fields are not implemented yet.\n");
+}
+
+#define CHECK_TRANSCODER(transcoder) \
+ if (transcoder == TRANSC_INVALID) { \
+ printf("Transcoder not selected.\n"); \
+ ret = 1; \
+ goto out; \
+ }
+
+#define CHECK_DIP(dip) \
+ if (dip == DIP_INVALID) { \
+ printf("Infoframe not selected.\n"); \
+ ret = 1; \
+ goto out; \
+ }
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ int ret = 0;
+ struct pci_device *pci_dev;
+ Transcoder transcoder = TRANSC_INVALID;
+ DipType dip = DIP_INVALID;
+ Register hdmi_port;
+
+ char short_opts[] = "dc:k:q:nNxXp:P:t:f:h";
+ struct option long_opts[] = {
+ { "dump", no_argument, NULL, 'd' },
+ { "change-fields", required_argument, NULL, 'c' },
+ { "change-checksum", required_argument, NULL, 'k' },
+ { "change-frequency", required_argument, NULL, 'q' },
+ { "disable", no_argument, NULL, 'n' },
+ { "enable", no_argument, NULL, 'N' },
+ { "disable-infoframes", no_argument, NULL, 'x' },
+ { "enable-infoframes", no_argument, NULL, 'X' },
+ { "disable-hdmi-port", required_argument, NULL, 'p' },
+ { "enable-hdmi-port", required_argument, NULL, 'P' },
+ { "transcoder" , required_argument, NULL, 't' },
+ { "infoframe", required_argument, NULL, 'f' },
+ { "help", no_argument, NULL, 'h' },
+ };
+
+ printf("WARNING: This is just a debugging tool! Don't expect it to work"
+ " perfectly: the Kernel might undo our changes.\n");
+
+ pci_dev = intel_get_pci_device();
+ intel_register_access_init(pci_dev, 0);
+ intel_check_pch();
+
+ if (IS_GEN4(pci_dev->device_id))
+ gen = 4;
+ else if (IS_GEN5(pci_dev->device_id))
+ gen = 5;
+ else if (IS_GEN6(pci_dev->device_id))
+ gen = 6;
+ else if (IS_GEN7(pci_dev->device_id))
+ gen = 7;
+ else {
+ printf("This program does not support your hardware yet.\n");
+ ret = 1;
+ goto out;
+ }
+
+ while (1) {
+ opt = getopt_long(argc, argv, short_opts, long_opts, NULL);
+ if (opt == -1)
+ break;
+
+ switch (opt) {
+ case 'd':
+ dump_all_info();
+ break;
+ case 'c':
+ if (transcoder == TRANSC_INVALID) {
+ printf("Transcoder not selected.\n");
+ ret = 1;
+ goto out;
+ }
+ switch (dip) {
+ case DIP_AVI:
+ change_avi_infoframe(transcoder, optarg);
+ break;
+ case DIP_VENDOR:
+ case DIP_GAMUT:
+ printf("Option not implemented yet.\n");
+ ret = 1;
+ goto out;
+ case DIP_SPD:
+ change_spd_infoframe(transcoder, optarg);
+ break;
+ case DIP_INVALID:
+ printf("Infoframe not selected.\n");
+ ret = 1;
+ goto out;
+ }
+ break;
+ case 'k':
+ CHECK_TRANSCODER(transcoder);
+ CHECK_DIP(dip);
+ change_infoframe_checksum(transcoder, dip, atoi(optarg));
+ break;
+ case 'q':
+ CHECK_TRANSCODER(transcoder);
+ CHECK_DIP(dip);
+ if (!strcmp(optarg, "once"))
+ change_infoframe_frequency(transcoder, dip,
+ DIP_FREQ_ONCE);
+ else if (!strcmp(optarg, "everyvsync"))
+ change_infoframe_frequency(transcoder, dip,
+ DIP_FREQ_EVERY_VSYNC);
+ else if (!strcmp(optarg, "everyothervsync"))
+ change_infoframe_frequency(transcoder, dip,
+ DIP_FREQ_EVERY_OTHER_VSYNC);
+ else {
+ printf("Invalid frequency.\n");
+ ret = 1;
+ goto out;
+ }
+ break;
+ case 'n':
+ CHECK_TRANSCODER(transcoder);
+ CHECK_DIP(dip);
+ disable_infoframe(transcoder, dip);
+ break;
+ case 'N':
+ CHECK_TRANSCODER(transcoder);
+ CHECK_DIP(dip);
+ enable_infoframe(transcoder, dip);
+ break;
+ case 'x':
+ CHECK_TRANSCODER(transcoder);
+ disable_dip(transcoder);
+ break;
+ case 'X':
+ CHECK_TRANSCODER(transcoder);
+ enable_dip(transcoder);
+ break;
+ case 'p':
+ case 'P':
+ if (!strcmp(optarg, "B"))
+ hdmi_port = get_hdmi_port(0);
+ else if (!strcmp(optarg, "C"))
+ hdmi_port = get_hdmi_port(1);
+ else if (!strcmp(optarg, "D"))
+ hdmi_port = get_hdmi_port(2);
+ else {
+ printf("Invalid HDMI port.\n");
+ ret = 1;
+ goto out;
+ }
+ if (opt == 'p')
+ disable_hdmi_port(hdmi_port);
+ else
+ enable_hdmi_port(hdmi_port);
+ break;
+ case 't':
+ if (!strcmp(optarg, "A"))
+ transcoder = TRANSC_A;
+ else if (!strcmp(optarg, "B"))
+ transcoder = TRANSC_B;
+ else if (pch >= PCH_CPT && !strcmp(optarg, "C")) {
+ transcoder = TRANSC_C;
+ } else {
+ printf("Invalid transcoder.\n");
+ ret = 1;
+ goto out;
+ }
+ break;
+ case 'f':
+ if (!strcmp(optarg, "AVI"))
+ dip = DIP_AVI;
+ else if (!strcmp(optarg, "Vendor"))
+ dip = DIP_VENDOR;
+ else if (!strcmp(optarg, "Gamut"))
+ dip = DIP_GAMUT;
+ else if (!strcmp(optarg, "SPD"))
+ dip = DIP_SPD;
+ else {
+ printf("Invalid infoframe.\n");
+ ret = 1;
+ goto out;
+ }
+ break;
+ case 'h':
+ print_usage();
+ break;
+ default:
+ print_usage();
+ ret = 1;
+ goto out;
+ }
+ }
+
+out:
+ intel_register_access_fini();
+ return ret;
+}
diff --git a/tools/intel_l3_parity.c b/tools/intel_l3_parity.c
new file mode 100644
index 00000000..260c3d0c
--- /dev/null
+++ b/tools/intel_l3_parity.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Widawsky <ben@bwidawsk.net>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+#include "drmtest.h"
+
+#define NUM_BANKS 4
+#define NUM_SUBBANKS 8
+#define NUM_REGS (NUM_BANKS * NUM_SUBBANKS)
+
+struct __attribute__ ((__packed__)) l3_log_register {
+ uint32_t row0_enable : 1;
+ uint32_t rsvd2 : 4;
+ uint32_t row0 : 11;
+ uint32_t row1_enable : 1;
+ uint32_t rsvd1 : 4;
+ uint32_t row1 : 11;
+} l3log[NUM_BANKS][NUM_SUBBANKS];
+
+static void dumpit(void)
+{
+ int i, j;
+
+ for (i = 0; i < NUM_BANKS; i++) {
+ for (j = 0; j < NUM_SUBBANKS; j++) {
+ struct l3_log_register *reg = &l3log[i][j];
+
+ if (reg->row0_enable)
+ printf("Row %d, Bank %d, Subbank %d is disabled\n",
+ reg->row0, i, j);
+ if (reg->row1_enable)
+ printf("Row %d, Bank %d, Subbank %d is disabled\n",
+ reg->row1, i, j);
+ }
+ }
+}
+
+static int disable_rbs(int row, int bank, int sbank)
+{
+ struct l3_log_register *reg = &l3log[bank][sbank];
+
+ // can't map more than 2 rows
+ if (reg->row0_enable && reg->row1_enable)
+ return -1;
+
+ // can't remap the same row twice
+ if ((reg->row0_enable && reg->row0 == row) ||
+ (reg->row1_enable && reg->row1 == row)) {
+ return -1;
+ }
+
+ if (reg->row0_enable) {
+ reg->row1 = row;
+ reg->row1_enable = 1;
+ } else {
+ reg->row0 = row;
+ reg->row0_enable = 1;
+ }
+
+ return 0;
+}
+
+static int do_parse(int argc, char *argv[])
+{
+ int row, bank, sbank, i, ret;
+
+ for (i = 1; i < argc; i++) {
+ ret = sscanf(argv[i], "%d,%d,%d", &row, &bank, &sbank);
+ if (ret != 3)
+ return i;
+ assert(disable_rbs(row, bank, sbank) == 0);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ const int device = drm_get_card(0);
+ char *path;
+ unsigned int devid;
+ int drm_fd, fd, ret;
+
+ drm_fd = drm_open_any();
+ devid = intel_get_drm_devid(drm_fd);
+
+ ret = asprintf(&path, "/sys/class/drm/card%d/l3_parity", device);
+ assert(ret != -1);
+
+ fd = open(path, O_RDWR);
+ if (fd == -1 && IS_IVYBRIDGE(devid)) {
+ perror("Opening sysfs");
+ exit(EXIT_FAILURE);
+ } else if (fd == -1)
+ exit(EXIT_SUCCESS);
+
+ ret = read(fd, l3log, NUM_REGS * sizeof(uint32_t));
+ if (ret == -1) {
+ perror("Reading sysfs");
+ exit(EXIT_FAILURE);
+ }
+
+ assert(lseek(fd, 0, SEEK_SET) == 0);
+
+ if (argc == 1) {
+ dumpit();
+ exit(EXIT_SUCCESS);
+ } else if (!strncmp("-c", argv[1], 2)) {
+ memset(l3log, 0, sizeof(l3log));
+ } else {
+ ret = do_parse(argc, argv);
+ if (ret != 0) {
+ fprintf(stderr, "Malformed command line at %s\n", argv[ret]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ ret = write(fd, l3log, NUM_REGS * sizeof(uint32_t));
+ if (ret == -1) {
+ perror("Writing sysfs");
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/intel_lid.c b/tools/intel_lid.c
new file mode 100644
index 00000000..908224ee
--- /dev/null
+++ b/tools/intel_lid.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Zhenyu Wang <zhenyu.z.wang@intel.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "intel_gpu_tools.h"
+#include "intel_reg.h"
+#include "intel_bios.h"
+
+enum lid_status {
+ LID_UNKNOWN = -1,
+ LID_OPEN,
+ LID_CLOSE,
+};
+
+#define ACPI_BUTTON "/proc/acpi/button/"
+#define ACPI_LID "/proc/acpi/button/lid/"
+
+static int i830_lvds_acpi_lid_state(void)
+{
+ int fd;
+ DIR *button_dir;
+ DIR *lid_dir;
+ struct dirent *lid_dent;
+ char *state_name;
+ char state[64];
+ enum lid_status ret = LID_UNKNOWN;
+
+ button_dir = opendir(ACPI_BUTTON);
+ /* If acpi button driver is not loaded, bypass ACPI check method */
+ if (button_dir == NULL)
+ goto out;
+ closedir(button_dir);
+
+ lid_dir = opendir(ACPI_LID);
+
+ /* no acpi lid object found */
+ if (lid_dir == NULL)
+ goto out;
+
+ while (1) {
+ lid_dent = readdir(lid_dir);
+ if (lid_dent == NULL) {
+ /* no LID object */
+ closedir(lid_dir);
+ goto out;
+ }
+ if (strcmp(lid_dent->d_name, ".") &&
+ strcmp(lid_dent->d_name, "..")) {
+ break;
+ }
+ }
+ state_name = malloc(strlen(ACPI_LID) + strlen(lid_dent->d_name) + 7);
+ memset(state_name, 0, sizeof(state_name));
+ strcat(state_name, ACPI_LID);
+ strcat(state_name, lid_dent->d_name);
+ strcat(state_name, "/state");
+
+ closedir(lid_dir);
+
+ if ((fd = open(state_name, O_RDONLY)) == -1) {
+ free(state_name);
+ goto out;
+ }
+ free(state_name);
+ if (read(fd, state, 64) == -1) {
+ close(fd);
+ goto out;
+ }
+ close(fd);
+ if (strstr(state, "open"))
+ ret = LID_OPEN;
+ else if (strstr(state, "closed"))
+ ret = LID_CLOSE;
+ else /* "unsupported" */
+ ret = LID_UNKNOWN;
+
+out:
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int swf14, acpi_lid;
+
+ intel_get_mmio(intel_get_pci_device());
+
+ while (1) {
+ swf14 = INREG(SWF14);
+
+ printf("Intel LVDS Lid status:\n");
+ printf("\tSWF14(0x%x) : %s\n", swf14,
+ swf14 & SWF14_LID_SWITCH_EN ? "close" : "open");
+
+ acpi_lid = i830_lvds_acpi_lid_state();
+ switch (acpi_lid) {
+ case LID_UNKNOWN:
+ printf("\tACPI Lid state : unknown\n");
+ break;
+ case LID_OPEN:
+ printf("\tACPI Lid state : open\n");
+ break;
+ case LID_CLOSE:
+ printf("\tACPI Lid state : close\n");
+ break;
+ }
+ sleep(2);
+ }
+ return 0;
+}
diff --git a/tools/intel_panel_fitter.c b/tools/intel_panel_fitter.c
new file mode 100644
index 00000000..f6723d17
--- /dev/null
+++ b/tools/intel_panel_fitter.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Paulo Zanoni <paulo.r.zanoni@intel.com>
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+int gen;
+
+uint32_t HTOTAL[] = { 0x60000, 0x61000, 0x62000 };
+uint32_t VTOTAL[] = { 0x6000C, 0x6100C, 0x6200C };
+uint32_t PIPECONF[] = { 0x70008, 0x71008, 0x72008 };
+uint32_t PIPESRC[] = { 0x6001C, 0x6101C, 0x6201C };
+uint32_t PF_CTRL1[] = { 0x68080, 0x68880, 0x69080 };
+uint32_t PF_WIN_POS[] = { 0x68070, 0x68870, 0x69070 };
+uint32_t PF_WIN_SZ[] = { 0x68074, 0x68874, 0x69074 };
+
+#define PIPECONF_ENABLE (1 << 31)
+#define PIPECONF_INTERLACE_MASK (7 << 21)
+#define PIPECONF_PF_PD (0 << 21)
+#define PIPECONF_PF_ID (1 << 21)
+#define PIPECONF_IF_ID (3 << 21)
+
+#define HTOTAL_ACTIVE_MASK (0xFFF << 0)
+#define VTOTAL_ACTIVE_MASK (0xFFF << 0)
+
+#define PIPESRC_HORIZ_MASK (0xFFF << 16)
+#define PIPESRC_VERT_MASK (0xFFF << 0)
+
+/*#define PF_ENABLE (1 << 31)*/
+#define PF_PIPE_MASK (3 << 29)
+#define PF_FILTER_MASK (3 << 23)
+#define PF_FILTER_MED (1 << 23)
+#define PF_PIPE_A (0 << 29)
+#define PF_PIPE_B (1 << 29)
+#define PF_PIPE_C (2 << 29)
+
+#define PF_WIN_SZ_X_MASK (0x1FFF << 16)
+#define PF_WIN_SZ_Y_MASK (0xFFF << 0)
+
+struct pipe_info {
+ bool enabled;
+ bool pf_enabled;
+ uint32_t interlace_mode;
+ uint32_t tot_width; /* htotal */
+ uint32_t tot_height; /* vtotal */
+ uint32_t src_width; /* pipesrc.x */
+ uint32_t src_height; /* pipesrc.y */
+ uint32_t dst_width; /* pf_win_sz.x */
+ uint32_t dst_height; /* pf_win_sz.y */
+};
+
+static void read_pipe_info(int intel_pipe, struct pipe_info *info)
+{
+ uint32_t conf, vtotal, htotal, src, ctrl1, win_sz;
+
+ conf = INREG(PIPECONF[intel_pipe]);
+ htotal = INREG(HTOTAL[intel_pipe]);
+ vtotal = INREG(VTOTAL[intel_pipe]);
+ src = INREG(PIPESRC[intel_pipe]);
+ ctrl1 = INREG(PF_CTRL1[intel_pipe]);
+ win_sz = INREG(PF_WIN_SZ[intel_pipe]);
+
+ info->enabled = (conf & PIPECONF_ENABLE) ? true : false;
+ info->tot_width = (htotal & HTOTAL_ACTIVE_MASK) + 1;
+ info->tot_height = (vtotal & VTOTAL_ACTIVE_MASK) + 1;
+ info->src_width = ((src & PIPESRC_HORIZ_MASK) >> 16) + 1;
+ info->src_height = (src & PIPESRC_VERT_MASK) + 1;
+ info->interlace_mode = conf & PIPECONF_INTERLACE_MASK;
+ info->pf_enabled = ctrl1 & PF_ENABLE;
+ info->dst_width = (win_sz & PF_WIN_SZ_X_MASK) >> 16;
+ info->dst_height = win_sz & PF_WIN_SZ_Y_MASK;
+}
+
+static void dump_pipe(int intel_pipe)
+{
+ struct pipe_info info;
+
+ read_pipe_info(intel_pipe, &info);
+
+ printf("\nPipe %c:\n", intel_pipe + 'A');
+
+ printf("- %s\n", info.enabled ? "enabled" : "disabled");
+ if (!info.enabled)
+ return;
+
+ switch (info.interlace_mode) {
+ case PIPECONF_PF_PD:
+ printf("- progressive\n");
+ break;
+ case PIPECONF_PF_ID:
+ printf("- interlaced (progressive fetch)\n");
+ break;
+ case PIPECONF_IF_ID:
+ printf("- interlaced (interlaced fetch)\n");
+ break;
+ default:
+ assert(0);
+ }
+
+ printf("- pf %s\n", info.pf_enabled ? "enabled" : "disabled");
+ if (!info.pf_enabled)
+ return;
+
+ printf("- tot %dx%d\n", info.tot_width, info.tot_height);
+ printf("- src %dx%d\n", info.src_width, info.src_height);
+ printf("- dst %dx%d\n", info.dst_width, info.dst_height);
+}
+
+static void dump_info(void)
+{
+ int i;
+ int pipes;
+
+ if (gen < 7)
+ pipes = 2;
+ else
+ pipes = 3;
+
+ for (i = 0; i < pipes; i++) {
+ dump_pipe(i);
+ }
+}
+
+static int change_screen_size(int intel_pipe, int x, int y)
+{
+ struct pipe_info info;
+ uint32_t dst_width, dst_height, pos_x, pos_y;
+ uint32_t ctrl1_val;
+ uint32_t win_pos_val;
+ uint32_t win_sz_val;
+
+ read_pipe_info(intel_pipe, &info);
+
+ if (x == 0) {
+ if (info.dst_width != 0)
+ dst_width = info.dst_width;
+ else
+ dst_width = info.src_width;
+ } else {
+ dst_width = x;
+ }
+
+ if (y == 0) {
+ if (info.dst_height != 0)
+ dst_height = info.dst_height;
+ else
+ dst_height = info.src_height;
+ } else {
+ dst_height = y;
+ }
+
+ pos_x = abs((info.tot_width - dst_width)) / 2;
+ pos_y = abs((info.tot_height - dst_height)) / 2;
+
+ if (pos_x == 1)
+ pos_x = 0;
+
+ if (info.src_width / (double) dst_width > 1.125) {
+ printf("X is too small\n");
+ return 1;
+ } else if (info.tot_width < dst_width) {
+ printf("X is too big\n");
+ return 1;
+ } else if (dst_width & 1) {
+ printf("X must be even\n");
+ return 1;
+ } else if (info.src_height / (double) dst_height > 1.125) {
+ printf("Y is too small\n");
+ return 1;
+ } else if (info.tot_height < dst_height) {
+ printf("Y is too big\n");
+ return 1;
+ } else if (dst_height & 1) {
+ printf("Y must be even\n");
+ return 1;
+ }
+
+ printf("Changing size for pipe %c:\n"
+ "- width: %d -> %d\n"
+ "- height: %d -> %d\n"
+ "- pos: %dx%d\n",
+ intel_pipe + 'A', info.src_width, dst_width, info.src_height,
+ dst_height, pos_x, pos_y);
+
+ ctrl1_val = PF_ENABLE | PF_FILTER_MED;
+
+ /* This can break stuff if the panel fitter is already enabled for
+ * another pipe */
+ if (gen >= 7) {
+ switch (intel_pipe) {
+ case 0:
+ ctrl1_val |= PF_PIPE_A;
+ break;
+ case 1:
+ ctrl1_val |= PF_PIPE_B;
+ break;
+ case 2:
+ ctrl1_val |= PF_PIPE_C;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ OUTREG(PF_CTRL1[intel_pipe], ctrl1_val);
+
+ win_pos_val = pos_x << 16;
+ win_pos_val |= pos_y;
+ OUTREG(PF_WIN_POS[intel_pipe], win_pos_val);
+
+ win_sz_val = dst_width << 16;
+ win_sz_val |= dst_height;
+ OUTREG(PF_WIN_SZ[intel_pipe], win_sz_val);
+
+ return 0;
+}
+
+static int disable_panel_fitter(int intel_pipe)
+{
+ OUTREG(PF_CTRL1[intel_pipe], 0);
+ OUTREG(PF_WIN_POS[intel_pipe], 0);
+ OUTREG(PF_WIN_SZ[intel_pipe], 0);
+ return 0;
+}
+
+static void print_usage(void)
+{
+ printf("Options:\n"
+" -p pipe: pipe to be used (A, B or C)\n"
+" -x value: final screen width size in pixels\n"
+" -y value: final screen height size in pixels\n"
+" -d: disable panel fitter\n"
+" -l: list the current state of each pipe\n"
+" -h: prints this message\n");
+}
+
+int main (int argc, char *argv[])
+{
+ int opt;
+ int ret = 0;
+ char intel_pipe = '\0';
+ int x = 0, y = 0;
+ bool do_disable = false, do_dump = false, do_usage = false;
+ struct pci_device *pci_dev;
+ uint32_t devid;
+
+ printf("WARNING:\n"
+ "This tool is a workaround for people that don't have a Kernel "
+ "with overscan compensation properties: it is just a temporary "
+ "solution that may or may not work. Use it at your own risk.\n");
+
+ pci_dev = intel_get_pci_device();
+ intel_register_access_init(pci_dev, 0);
+ devid = pci_dev->device_id;
+
+ if (!HAS_PCH_SPLIT(devid)) {
+ printf("This tool was only tested on Ironlake and newer\n");
+ ret = 1;
+ goto out;
+ }
+ if (IS_GEN5(devid))
+ gen = 5;
+ else if (IS_GEN6(devid))
+ gen = 6;
+ else
+ gen = 7;
+
+ while ((opt = getopt(argc, argv, "p:x:y:dlh")) != -1) {
+ switch (opt) {
+ case 'p':
+ intel_pipe = optarg[0];
+ if (intel_pipe != 'A' && intel_pipe != 'B' &&
+ (gen <= 6 || intel_pipe != 'C')) {
+ printf("Invalid pipe\n");
+ ret = 1;
+ goto out;
+ }
+ break;
+ case 'x':
+ x = atoi(optarg);
+ break;
+ case 'y':
+ y = atoi(optarg);
+ break;
+ case 'd':
+ do_disable = true;
+ break;
+ case 'l':
+ do_dump = true;
+ break;
+ case 'h':
+ do_usage = true;
+ break;
+ default:
+ do_usage = true;
+ ret = 1;
+ }
+ }
+
+ if (do_usage) {
+ print_usage();
+ } else if (do_dump) {
+ dump_info();
+ } else if (intel_pipe) {
+ if (do_disable)
+ ret = disable_panel_fitter(intel_pipe - 'A');
+ else
+ ret = change_screen_size(intel_pipe - 'A', x, y);
+ } else {
+ print_usage();
+ ret = 1;
+ }
+
+out:
+ intel_register_access_fini();
+ return ret;
+}
diff --git a/tools/intel_reg_checker.c b/tools/intel_reg_checker.c
new file mode 100644
index 00000000..daa8d0fb
--- /dev/null
+++ b/tools/intel_reg_checker.c
@@ -0,0 +1,399 @@
+/* Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include <stdbool.h>
+#include "intel_gpu_tools.h"
+
+static uint32_t devid;
+static int gen;
+
+static inline uint32_t
+read_reg(uint32_t reg)
+{
+ return *(volatile uint32_t *)((volatile char *)mmio + reg);
+}
+
+static uint32_t
+read_and_print_reg(const char *name, uint32_t reg)
+{
+ uint32_t val = read_reg(reg);
+
+ printf("%s (0x%x): 0x%08x\n", name, reg, val);
+
+ return val;
+}
+
+static void
+check_chicken_unset(const char *name, uint32_t reg)
+{
+ uint32_t val = read_and_print_reg(name, reg);
+
+
+ if (val != 0) {
+ fprintf(stderr, " WARN: chicken bits set\n");
+ } else {
+ printf(" OK: chicken bits unset\n");
+ }
+}
+
+static void
+check_bit(uint32_t val, int bit, const char *bitname, bool set)
+{
+ if (!!(val & (1 << bit)) != set) {
+ fprintf(stderr, " (bit %2d) FAIL: %s must be %s\n",
+ bit, bitname, set ? "set" : "unset");
+ } else {
+ printf(" (bit %2d) OK: %s\n", bit, bitname);
+ }
+}
+
+static void
+check_perf_bit(uint32_t val, int bit, const char *bitname, bool set)
+{
+ if (!!(val & (1 << bit)) != set) {
+ printf(" (bit %2d) PERF: %s should be %s\n",
+ bit, bitname, set ? "set" : "unset");
+ } else {
+ printf(" (bit %2d) OK: %s\n", bit, bitname);
+ }
+}
+
+static void
+check_mi_mode(void)
+{
+ /* Described in page 14-16 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+
+ uint32_t mi_mode = read_and_print_reg("MI_MODE", 0x209c);
+
+ /* From page 14:
+ *
+ * Async Flip Performance mode
+ * Project: All
+ * Default Value: 0h
+ * Format: U1
+ * [DevSNB] This bit must be set to ‘1’
+ */
+ if (gen == 6)
+ check_bit(mi_mode, 14, "Async Flip Performance mode", true);
+ else
+ check_perf_bit(mi_mode, 14, "Async Flip Performance mode",
+ false);
+
+ check_perf_bit(mi_mode, 13, "Flush Performance Mode", false);
+
+ /* Our driver relies on MI_FLUSH, unfortunately. */
+ if (gen >= 6)
+ check_bit(mi_mode, 12, "MI_FLUSH enable", true);
+
+ /* From page 15:
+ *
+ * "1h: LRA mode of allocation. Used for validation purposes"
+ */
+ if (gen < 7)
+ check_bit(mi_mode, 7, "Vertex Shader Cache Mode", false);
+
+ /* From page 16:
+ *
+ * "To avoid deadlock conditions in hardware this bit
+ * needs to be set for normal operation.
+ */
+ check_bit(mi_mode, 6, "Vertex Shader Timer Dispatch Enable", true);
+}
+
+static void
+check_gfx_mode(void)
+{
+ /* Described in page 17-19 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t gfx_mode;
+
+ if (gen < 6)
+ return;
+
+ if (gen == 6)
+ gfx_mode = read_and_print_reg("GFX_MODE", 0x2520);
+ else
+ gfx_mode = read_and_print_reg("GFX_MODE", 0x229c);
+
+ /* Our driver only updates page tables at batchbuffer
+ * boundaries, so we don't need TLB flushes at other times.
+ */
+ check_perf_bit(gfx_mode, 13, "Flush TLB Invalidation Mode", true);
+}
+
+static void
+check_gt_mode(void)
+{
+ /* Described in page 20-22 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t gt_mode;
+
+ if (gen < 6)
+ return;
+
+ if (gen == 6)
+ gt_mode = read_and_print_reg("GT_MODE", 0x20d0);
+ else
+ gt_mode = read_and_print_reg("GT_MODE", 0x7008);
+
+ if (gen == 6)
+ check_perf_bit(gt_mode, 8, "Full Rate Sampler Disable", false);
+
+ /* For DevSmallGT, this bit must be set, which means disable
+ * hashing.
+ */
+ if (devid == PCI_CHIP_SANDYBRIDGE_GT1 ||
+ devid == PCI_CHIP_SANDYBRIDGE_M_GT1)
+ check_bit(gt_mode, 6, "WIZ Hashing disable", true);
+ else if (gen == 6)
+ check_perf_bit(gt_mode, 6, "WIZ Hashing disable", false);
+
+ if (gen == 6) {
+ check_perf_bit(gt_mode, 5, "TD Four Row Dispatch Disable",
+ false);
+ check_perf_bit(gt_mode, 4, "Full Size URB Disable", false);
+ check_perf_bit(gt_mode, 3, "Full Size SF FIFO Disable", false);
+ check_perf_bit(gt_mode, 1, "VS Quad Thread Dispatch Disable",
+ false);
+ }
+}
+
+static void
+check_cache_mode_0(void)
+{
+ /* Described in page 23-25 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t cache_mode_0;
+
+ if (gen >= 7)
+ cache_mode_0 = read_and_print_reg("CACHE_MODE_0", 0x7000);
+ else
+ cache_mode_0 = read_and_print_reg("CACHE_MODE_0", 0x2120);
+
+ check_perf_bit(cache_mode_0, 15, "Sampler L2 Disable", false);
+ check_perf_bit(cache_mode_0, 9, "Sampler L2 TLB Prefetch Enable", true);
+ check_perf_bit(cache_mode_0, 8,
+ "Depth Related Cache Pipelined Flush Disable", false);
+
+ /* From page 24:
+ *
+ * "If this bit is set, RCCunit will have LRA as
+ * replacement policy. The default value i.e. ( when this
+ * bit is reset ) indicates that non-LRA eviction
+ * policy. This bit must be reset. LRA replacement policy
+ * is not supported."
+ *
+ * And the same for STC Eviction Policy.
+ */
+ check_bit(cache_mode_0, 5, "STC LRA Eviction Policy", false);
+ if (gen >= 6)
+ check_bit(cache_mode_0, 4, "RCC LRA Eviction Policy", false);
+
+ check_perf_bit(cache_mode_0, 3, "Hierarchical Z Disable", false);
+
+ if (gen == 6) {
+ check_perf_bit(cache_mode_0, 2,
+ "Hierarchical Z RAW Stall Optimization "
+ "Disable", false);
+ }
+
+ /* From page 25:
+ *
+ * "This bit must be 0. Operational Flushes [DevSNB] are
+ * not supported in [DevSNB]. SW must flush the render
+ * target after front buffer rendering."
+ */
+ check_bit(cache_mode_0, 0, "Render Cache Operational Flush", false);
+}
+
+
+static void
+check_cache_mode_1(void)
+{
+ /* Described in page 23-25 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t cache_mode_1;
+
+ if (gen >= 7)
+ cache_mode_1 = read_and_print_reg("CACHE_MODE_1", 0x7004);
+ else
+ cache_mode_1 = read_and_print_reg("CACHE_MODE_1", 0x2124);
+
+ if (gen >= 7) {
+ check_perf_bit(cache_mode_1, 13,
+ "STC Address Lookup Optimization Disable",
+ false);
+ }
+
+ /* From page 24:
+ *
+ * "If this bit is set, Hizunit will have LRA as
+ * replacement policy. The default value i.e. (when this
+ * bit is reset) indicates the non-LRA eviction
+ * policy. For performance reasons, this bit must be
+ * reset."
+ */
+ check_bit(cache_mode_1, 12, "HIZ LRA Eviction Policy", false);
+
+ /* Page 26 describes these bits as reserved (debug only). */
+ check_bit(cache_mode_1, 11,
+ "DAP Instruction and State Cache Invalidate", false);
+ check_bit(cache_mode_1, 10,
+ "Instruction L1 Cache and In-Flight Queue Disable",
+ false);
+ check_bit(cache_mode_1, 9, "Instruction L2 Cache Fill Buffers Disable",
+ false);
+
+
+ if (gen >= 7) {
+ check_perf_bit(cache_mode_1, 6,
+ "Pixel Backend sub-span collection "
+ "Optimization Disable",
+ false);
+ check_perf_bit(cache_mode_1, 5, "MCS Cache Disable", false);
+ }
+ check_perf_bit(cache_mode_1, 4, "Data Disable", false);
+
+ if (gen == 6) {
+ /* In a later update of the documentation, it says:
+ *
+ * "[DevSNB:A0{WKA1}] [DevSNB]: This bit must be
+ * set for depth buffer format
+ * D24_UNORM_S8_UINT."
+ *
+ * XXX: Does that mean A0 only, or all DevSNB?
+ */
+ check_perf_bit(cache_mode_1, 3,
+ "Depth Read Hit Write-Only Optimization "
+ "Disable", false);
+
+ check_perf_bit(cache_mode_1, 2,
+ "Depth Cache LRA Hunt Feature Disable",
+ false);
+ }
+
+ check_bit(cache_mode_1, 1, "Instruction and State L2 Cache Disable",
+ false);
+ check_bit(cache_mode_1, 0, "Instruction and State L1 Cache Disable",
+ false);
+}
+
+
+static void
+check_3d_chicken4(void)
+{
+ /* Described in page 23-25 of the IHD_OS_Vol1_Part3.pdf
+ * specification.
+ */
+ uint32_t _3d_chicken4 = read_and_print_reg("3D_CHICKEN4", 0x20d4);
+
+ check_perf_bit(_3d_chicken4, 6, "3D Scoreboard Hashing Enable", true);
+
+ if (_3d_chicken4 & 0x0fbf) {
+ fprintf(stderr,
+ " WARN: other non-thread deps bits set\n");
+ } else {
+ printf(" OK: other non-thread deps bits unset\n");
+ }
+}
+
+static void
+check_dpfc_control_sa(void)
+{
+ uint32_t dpfc_control_sa;
+
+ if (gen != 6)
+ return;
+
+ dpfc_control_sa = read_and_print_reg("DPFC_CONTROL_SA", 0x100100);
+
+ /* This is needed for framebuffer compression for us to be
+ * able to access the framebuffer by the CPU through the GTT.
+ */
+ check_bit(dpfc_control_sa, 29, "CPU Fence Enable", true);
+}
+
+int main(int argc, char** argv)
+{
+ struct pci_device *dev;
+
+ dev = intel_get_pci_device();
+ devid = dev->device_id;
+ intel_get_mmio(dev);
+
+ if (IS_GEN7(devid))
+ gen = 7;
+ else if (IS_GEN6(devid))
+ gen = 6;
+ else if (IS_GEN5(devid))
+ gen = 5;
+ else
+ gen = 4;
+
+ check_mi_mode();
+ check_gfx_mode();
+ check_gt_mode();
+ check_cache_mode_0();
+ check_cache_mode_1();
+
+ if (gen < 7) {
+ check_chicken_unset("3D_CHICKEN", 0x2084);
+ check_chicken_unset("3D_CHICKEN2", 0x208c);
+ } else {
+ check_chicken_unset("FF_SLICE_CHICKEN", 0x2088);
+ }
+ if (gen >= 6)
+ check_chicken_unset("3D_CHICKEN3", 0x2090);
+ if (gen == 6)
+ check_3d_chicken4();
+
+ if (gen >= 7) {
+ check_chicken_unset("FF_SLICE_CS_CHICKEN1", 0x20e0);
+ check_chicken_unset("FF_SLICE_CS_CHICKEN2", 0x20e4);
+ check_chicken_unset("FF_SLICE_CS_CHICKEN3", 0x20e8);
+ check_chicken_unset("COMMON_SLICE_CHICKEN1", 0x7010);
+ check_chicken_unset("COMMON_SLICE_CHICKEN2", 0x7014);
+ check_chicken_unset("WM_CHICKEN", 0x5580);
+ check_chicken_unset("HALF_SLICE_CHICKEN", 0xe100);
+ check_chicken_unset("HALF_SLICE_CHICKEN2", 0xe180);
+ check_chicken_unset("ROW_CHICKEN", 0xe4f0);
+ check_chicken_unset("ROW_CHICKEN2", 0xe4f4);
+ }
+
+ check_chicken_unset("ECOSKPD", 0x21d0);
+
+ check_dpfc_control_sa();
+
+ return 0;
+}
+
diff --git a/tools/intel_reg_dumper.c b/tools/intel_reg_dumper.c
new file mode 100644
index 00000000..b49d967b
--- /dev/null
+++ b/tools/intel_reg_dumper.c
@@ -0,0 +1,2246 @@
+/*
+ * Copyright © 2006,2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <unistd.h>
+#include "intel_gpu_tools.h"
+
+static uint32_t devid = 0;
+
+#define DEBUGSTRING(func) static void func(char *result, int len, int reg, uint32_t val)
+
+DEBUGSTRING(i830_16bit_func)
+{
+ snprintf(result, len, "0x%04x", (uint16_t) val);
+}
+
+DEBUGSTRING(i830_debug_dcc)
+{
+ const char *addressing = NULL;
+
+ if (!IS_MOBILE(devid))
+ return;
+
+ if (IS_965(devid)) {
+ if (val & (1 << 1))
+ addressing = "dual channel interleaved";
+ else
+ addressing = "single or dual channel asymmetric";
+ } else {
+ switch (val & 3) {
+ case 0:
+ addressing = "single channel";
+ break;
+ case 1:
+ addressing = "dual channel asymmetric";
+ break;
+ case 2:
+ addressing = "dual channel interleaved";
+ break;
+ case 3:
+ addressing = "unknown channel layout";
+ break;
+ }
+ }
+
+ snprintf(result, len, "%s, XOR randomization: %sabled, XOR bit: %d",
+ addressing,
+ (val & (1 << 10)) ? "dis" : "en",
+ (val & (1 << 9)) ? 17 : 11);
+}
+
+DEBUGSTRING(i830_debug_chdecmisc)
+{
+ const char *enhmodesel = NULL;
+
+ switch ((val >> 5) & 3) {
+ case 1:
+ enhmodesel = "XOR bank/rank";
+ break;
+ case 2:
+ enhmodesel = "swap bank";
+ break;
+ case 3:
+ enhmodesel = "XOR bank";
+ break;
+ case 0:
+ enhmodesel = "none";
+ break;
+ }
+
+ snprintf(result, len,
+ "%s, ch2 enh %sabled, ch1 enh %sabled, "
+ "ch0 enh %sabled, "
+ "flex %sabled, ep %spresent", enhmodesel,
+ (val & (1 << 4)) ? "en" : "dis",
+ (val & (1 << 3)) ? "en" : "dis",
+ (val & (1 << 2)) ? "en" : "dis",
+ (val & (1 << 1)) ? "en" : "dis",
+ (val & (1 << 0)) ? "" : "not ");
+}
+
+DEBUGSTRING(i830_debug_xyminus1)
+{
+ snprintf(result, len, "%d, %d", (val & 0xffff) + 1,
+ ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_yxminus1)
+{
+ snprintf(result, len, "%d, %d", ((val & 0xffff0000) >> 16) + 1,
+ (val & 0xffff) + 1);
+}
+
+DEBUGSTRING(i830_debug_xy)
+{
+ snprintf(result, len, "%d, %d", (val & 0xffff), ((val & 0xffff0000) >> 16));
+}
+
+DEBUGSTRING(i830_debug_dspstride)
+{
+ snprintf(result, len, "%d bytes", val);
+}
+
+DEBUGSTRING(i830_debug_dspcntr)
+{
+ const char *enabled = val & DISPLAY_PLANE_ENABLE ? "enabled" : "disabled";
+ char plane = val & DISPPLANE_SEL_PIPE_B ? 'B' : 'A';
+ if (HAS_PCH_SPLIT(devid))
+ snprintf(result, len, "%s", enabled);
+ else
+ snprintf(result, len, "%s, pipe %c", enabled, plane);
+}
+
+DEBUGSTRING(i830_debug_pipeconf)
+{
+ const char *enabled = val & PIPEACONF_ENABLE ? "enabled" : "disabled";
+ const char *bit30, *interlace;
+
+ if (IS_965(devid))
+ bit30 = val & I965_PIPECONF_ACTIVE ? "active" : "inactive";
+ else
+ bit30 =
+ val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide";
+
+ if (HAS_PCH_SPLIT(devid)) {
+ const char *bpc, *rotation;
+
+ switch ((val >> 21) & 7) {
+ case 0:
+ interlace = "pf-pd";
+ break;
+ case 1:
+ interlace = "pf-id";
+ break;
+ case 3:
+ interlace = "if-id";
+ break;
+ case 4:
+ interlace = "if-id-dbl";
+ break;
+ case 5:
+ interlace = "pf-id-dbl";
+ break;
+ default:
+ interlace = "rsvd";
+ break;
+ }
+
+ switch ((val >> 14) & 3) {
+ case 0:
+ rotation = "rotate 0";
+ break;
+ case 1:
+ rotation = "rotate 90";
+ break;
+ case 2:
+ rotation = "rotate 180";
+ break;
+ case 3:
+ rotation = "rotate 270";
+ break;
+ }
+
+ switch (val & (7 << 5)) {
+ case PIPECONF_8BPP:
+ bpc = "8bpc";
+ break;
+ case PIPECONF_10BPP:
+ bpc = "10bpc";
+ break;
+ case PIPECONF_6BPP:
+ bpc = "6bpc";
+ break;
+ case PIPECONF_12BPP:
+ bpc = "12bpc";
+ break;
+ default:
+ bpc = "invalid bpc";
+ break;
+ }
+ snprintf(result, len, "%s, %s, %s, %s, %s", enabled, bit30,
+ interlace, rotation, bpc);
+ } else if (IS_GEN4(devid)) {
+ switch ((val >> 21) & 7) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ interlace = "progressive";
+ break;
+ case 4:
+ interlace = "interlaced embedded";
+ break;
+ case 5:
+ interlace = "interlaced";
+ break;
+ case 6:
+ interlace = "interlaced sdvo";
+ break;
+ case 7:
+ interlace = "interlaced legacy";
+ break;
+ }
+ snprintf(result, len, "%s, %s, %s", enabled, bit30, interlace);
+ } else
+ snprintf(result, len, "%s, %s", enabled, bit30);
+}
+
+DEBUGSTRING(i830_debug_pipestat)
+{
+ const char *_FIFO_UNDERRUN = val & FIFO_UNDERRUN ? " FIFO_UNDERRUN" : "";
+ const char *_CRC_ERROR_ENABLE =
+ val & CRC_ERROR_ENABLE ? " CRC_ERROR_ENABLE" : "";
+ const char *_CRC_DONE_ENABLE =
+ val & CRC_DONE_ENABLE ? " CRC_DONE_ENABLE" : "";
+ const char *_GMBUS_EVENT_ENABLE =
+ val & GMBUS_EVENT_ENABLE ? " GMBUS_EVENT_ENABLE" : "";
+ const char *_VSYNC_INT_ENABLE =
+ val & VSYNC_INT_ENABLE ? " VSYNC_INT_ENABLE" : "";
+ const char *_DLINE_COMPARE_ENABLE =
+ val & DLINE_COMPARE_ENABLE ? " DLINE_COMPARE_ENABLE" : "";
+ const char *_DPST_EVENT_ENABLE =
+ val & DPST_EVENT_ENABLE ? " DPST_EVENT_ENABLE" : "";
+ const char *_LBLC_EVENT_ENABLE =
+ val & LBLC_EVENT_ENABLE ? " LBLC_EVENT_ENABLE" : "";
+ const char *_OFIELD_INT_ENABLE =
+ val & OFIELD_INT_ENABLE ? " OFIELD_INT_ENABLE" : "";
+ const char *_EFIELD_INT_ENABLE =
+ val & EFIELD_INT_ENABLE ? " EFIELD_INT_ENABLE" : "";
+ const char *_SVBLANK_INT_ENABLE =
+ val & SVBLANK_INT_ENABLE ? " SVBLANK_INT_ENABLE" : "";
+ const char *_VBLANK_INT_ENABLE =
+ val & VBLANK_INT_ENABLE ? " VBLANK_INT_ENABLE" : "";
+ const char *_OREG_UPDATE_ENABLE =
+ val & OREG_UPDATE_ENABLE ? " OREG_UPDATE_ENABLE" : "";
+ const char *_CRC_ERROR_INT_STATUS =
+ val & CRC_ERROR_INT_STATUS ? " CRC_ERROR_INT_STATUS" : "";
+ const char *_CRC_DONE_INT_STATUS =
+ val & CRC_DONE_INT_STATUS ? " CRC_DONE_INT_STATUS" : "";
+ const char *_GMBUS_INT_STATUS =
+ val & GMBUS_INT_STATUS ? " GMBUS_INT_STATUS" : "";
+ const char *_VSYNC_INT_STATUS =
+ val & VSYNC_INT_STATUS ? " VSYNC_INT_STATUS" : "";
+ const char *_DLINE_COMPARE_STATUS =
+ val & DLINE_COMPARE_STATUS ? " DLINE_COMPARE_STATUS" : "";
+ const char *_DPST_EVENT_STATUS =
+ val & DPST_EVENT_STATUS ? " DPST_EVENT_STATUS" : "";
+ const char *_LBLC_EVENT_STATUS =
+ val & LBLC_EVENT_STATUS ? " LBLC_EVENT_STATUS" : "";
+ const char *_OFIELD_INT_STATUS =
+ val & OFIELD_INT_STATUS ? " OFIELD_INT_STATUS" : "";
+ const char *_EFIELD_INT_STATUS =
+ val & EFIELD_INT_STATUS ? " EFIELD_INT_STATUS" : "";
+ const char *_SVBLANK_INT_STATUS =
+ val & SVBLANK_INT_STATUS ? " SVBLANK_INT_STATUS" : "";
+ const char *_VBLANK_INT_STATUS =
+ val & VBLANK_INT_STATUS ? " VBLANK_INT_STATUS" : "";
+ const char *_OREG_UPDATE_STATUS =
+ val & OREG_UPDATE_STATUS ? " OREG_UPDATE_STATUS" : "";
+ snprintf(result, len,
+ "status:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ _FIFO_UNDERRUN,
+ _CRC_ERROR_ENABLE,
+ _CRC_DONE_ENABLE,
+ _GMBUS_EVENT_ENABLE,
+ _VSYNC_INT_ENABLE,
+ _DLINE_COMPARE_ENABLE,
+ _DPST_EVENT_ENABLE,
+ _LBLC_EVENT_ENABLE,
+ _OFIELD_INT_ENABLE,
+ _EFIELD_INT_ENABLE,
+ _SVBLANK_INT_ENABLE,
+ _VBLANK_INT_ENABLE,
+ _OREG_UPDATE_ENABLE,
+ _CRC_ERROR_INT_STATUS,
+ _CRC_DONE_INT_STATUS,
+ _GMBUS_INT_STATUS,
+ _VSYNC_INT_STATUS,
+ _DLINE_COMPARE_STATUS,
+ _DPST_EVENT_STATUS,
+ _LBLC_EVENT_STATUS,
+ _OFIELD_INT_STATUS,
+ _EFIELD_INT_STATUS,
+ _SVBLANK_INT_STATUS,
+ _VBLANK_INT_STATUS,
+ _OREG_UPDATE_STATUS);
+}
+
+DEBUGSTRING(ivb_debug_port)
+{
+ const char *drrs = NULL;
+ switch (val & (2 << 30)) {
+ case PORT_DBG_DRRS_HW_STATE_OFF:
+ drrs = "off";
+ break;
+ case PORT_DBG_DRRS_HW_STATE_LOW:
+ drrs = "low";
+ break;
+ case PORT_DBG_DRRS_HW_STATE_HIGH:
+ drrs = "high";
+ break;
+ }
+ snprintf(result, len, "HW DRRS %s",
+ drrs);
+}
+
+DEBUGSTRING(i830_debug_hvtotal)
+{
+ snprintf(result, len, "%d active, %d total",
+ (val & 0xffff) + 1,
+ ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_hvsyncblank)
+{
+ snprintf(result, len, "%d start, %d end",
+ (val & 0xffff) + 1,
+ ((val & 0xffff0000) >> 16) + 1);
+}
+
+DEBUGSTRING(i830_debug_vgacntrl)
+{
+ snprintf(result, len, "%s",
+ val & VGA_DISP_DISABLE ? "disabled" : "enabled");
+}
+
+DEBUGSTRING(i830_debug_fp)
+{
+ if (IS_IGD(devid)) {
+ snprintf(result, len, "n = %d, m1 = %d, m2 = %d",
+ ffs((val & FP_N_IGD_DIV_MASK) >>
+ FP_N_DIV_SHIFT) - 1,
+ ((val & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT),
+ ((val & FP_M2_IGD_DIV_MASK) >>
+ FP_M2_DIV_SHIFT));
+ }
+ snprintf(result, len, "n = %d, m1 = %d, m2 = %d",
+ ((val & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT),
+ ((val & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT),
+ ((val & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT));
+}
+
+DEBUGSTRING(i830_debug_vga_pd)
+{
+ int vga0_p1, vga0_p2, vga1_p1, vga1_p2;
+
+ /* XXX: i9xx version */
+
+ if (val & VGA0_PD_P1_DIV_2)
+ vga0_p1 = 2;
+ else
+ vga0_p1 = ((val & VGA0_PD_P1_MASK) >> VGA0_PD_P1_SHIFT) + 2;
+ vga0_p2 = (val & VGA0_PD_P2_DIV_4) ? 4 : 2;
+
+ if (val & VGA1_PD_P1_DIV_2)
+ vga1_p1 = 2;
+ else
+ vga1_p1 = ((val & VGA1_PD_P1_MASK) >> VGA1_PD_P1_SHIFT) + 2;
+ vga1_p2 = (val & VGA1_PD_P2_DIV_4) ? 4 : 2;
+
+ snprintf(result, len, "vga0 p1 = %d, p2 = %d, vga1 p1 = %d, p2 = %d",
+ vga0_p1, vga0_p2, vga1_p1, vga1_p2);
+}
+
+DEBUGSTRING(i830_debug_pp_status)
+{
+ const char *status = val & PP_ON ? "on" : "off";
+ const char *ready = val & PP_READY ? "ready" : "not ready";
+ const char *seq = "unknown";
+
+ switch (val & PP_SEQUENCE_MASK) {
+ case PP_SEQUENCE_NONE:
+ seq = "idle";
+ break;
+ case PP_SEQUENCE_ON:
+ seq = "on";
+ break;
+ case PP_SEQUENCE_OFF:
+ seq = "off";
+ break;
+ }
+
+ snprintf(result, len, "%s, %s, sequencing %s", status, ready, seq);
+}
+
+DEBUGSTRING(i830_debug_pp_control)
+{
+ snprintf(result, len, "power target: %s",
+ val & POWER_TARGET_ON ? "on" : "off");
+}
+
+DEBUGSTRING(i830_debug_dpll)
+{
+ const char *enabled = val & DPLL_VCO_ENABLE ? "enabled" : "disabled";
+ const char *dvomode = val & DPLL_DVO_HIGH_SPEED ? "dvo" : "non-dvo";
+ const char *vgamode = val & DPLL_VGA_MODE_DIS ? "" : ", VGA";
+ const char *mode = "unknown";
+ const char *clock = "unknown";
+ const char *fpextra = val & DISPLAY_RATE_SELECT_FPA1 ? ", using FPx1!" : "";
+ char sdvoextra[20];
+ int p1, p2 = 0;
+
+ if (IS_GEN2(devid)) {
+ char is_lvds = (INREG(LVDS) & LVDS_PORT_EN) && (reg == DPLL_B);
+
+ if (is_lvds) {
+ mode = "LVDS";
+ p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS)
+ >> DPLL_FPA01_P1_POST_DIV_SHIFT);
+ if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) ==
+ LVDS_CLKB_POWER_UP)
+ p2 = 7;
+ else
+ p2 = 14;
+
+ } else {
+ mode = "DAC/serial";
+ if (val & PLL_P1_DIVIDE_BY_TWO) {
+ p1 = 2;
+ } else {
+ /* Map the number in the field to (3, 33) */
+ p1 = ((val & DPLL_FPA01_P1_POST_DIV_MASK_I830)
+ >> DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+ }
+ if (val & PLL_P2_DIVIDE_BY_4)
+ p2 = 4;
+ else
+ p2 = 2;
+ }
+ } else {
+ if (IS_IGD(devid)) {
+ p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT_IGD);
+ } else {
+ p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >>
+ DPLL_FPA01_P1_POST_DIV_SHIFT);
+ }
+ switch (val & DPLL_MODE_MASK) {
+ case DPLLB_MODE_DAC_SERIAL:
+ mode = "DAC/serial";
+ p2 = val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
+ break;
+ case DPLLB_MODE_LVDS:
+ mode = "LVDS";
+ p2 = val & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
+ break;
+ }
+ }
+
+ switch (val & PLL_REF_INPUT_MASK) {
+ case PLL_REF_INPUT_DREFCLK:
+ clock = "default";
+ break;
+ case PLL_REF_INPUT_TVCLKINA:
+ clock = "TV A";
+ break;
+ case PLL_REF_INPUT_TVCLKINBC:
+ clock = "TV B/C";
+ break;
+ case PLLB_REF_INPUT_SPREADSPECTRUMIN:
+ if (reg == DPLL_B)
+ clock = "spread spectrum";
+ break;
+ }
+
+ if (IS_945(devid)) {
+ sprintf(sdvoextra, ", SDVO mult %d",
+ (int)((val & SDVO_MULTIPLIER_MASK) >>
+ SDVO_MULTIPLIER_SHIFT_HIRES) + 1);
+ } else {
+ sdvoextra[0] = '\0';
+ }
+
+ snprintf(result, len, "%s, %s%s, %s clock, %s mode, p1 = %d, "
+ "p2 = %d%s%s",
+ enabled, dvomode, vgamode, clock, mode, p1, p2,
+ fpextra, sdvoextra);
+}
+
+DEBUGSTRING(i830_debug_dpll_test)
+{
+ const char *dpllandiv = val & DPLLA_TEST_N_BYPASS ? ", DPLLA N bypassed" : "";
+ const char *dpllamdiv = val & DPLLA_TEST_M_BYPASS ? ", DPLLA M bypassed" : "";
+ const char *dpllainput = val & DPLLA_INPUT_BUFFER_ENABLE ?
+ "" : ", DPLLA input buffer disabled";
+ const char *dpllbndiv = val & DPLLB_TEST_N_BYPASS ? ", DPLLB N bypassed" : "";
+ const char *dpllbmdiv = val & DPLLB_TEST_M_BYPASS ? ", DPLLB M bypassed" : "";
+ const char *dpllbinput = val & DPLLB_INPUT_BUFFER_ENABLE ?
+ "" : ", DPLLB input buffer disabled";
+
+ snprintf(result, len, "%s%s%s%s%s%s",
+ dpllandiv, dpllamdiv, dpllainput,
+ dpllbndiv, dpllbmdiv, dpllbinput);
+}
+
+DEBUGSTRING(i830_debug_adpa)
+{
+ char disp_pipe = (val & ADPA_PIPE_B_SELECT) ? 'B' : 'A';
+ const char *enable = (val & ADPA_DAC_ENABLE) ? "enabled" : "disabled";
+ char hsync = (val & ADPA_HSYNC_ACTIVE_HIGH) ? '+' : '-';
+ char vsync = (val & ADPA_VSYNC_ACTIVE_HIGH) ? '+' : '-';
+
+ if (HAS_CPT)
+ disp_pipe = val & (1<<29) ? 'B' : 'A';
+
+ if (HAS_PCH_SPLIT(devid))
+ snprintf(result, len, "%s, transcoder %c, %chsync, %cvsync",
+ enable, disp_pipe, hsync, vsync);
+ else
+ snprintf(result, len, "%s, pipe %c, %chsync, %cvsync",
+ enable, disp_pipe, hsync, vsync);
+}
+
+DEBUGSTRING(i830_debug_lvds)
+{
+ char disp_pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
+ const char *enable = val & LVDS_PORT_EN ? "enabled" : "disabled";
+ int depth;
+ const char *channels;
+
+ if ((val & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
+ depth = 24;
+ else
+ depth = 18;
+ if ((val & LVDS_B0B3_POWER_MASK) == LVDS_B0B3_POWER_UP)
+ channels = "2 channels";
+ else
+ channels = "1 channel";
+
+ if (HAS_CPT)
+ disp_pipe = val & (1<<29) ? 'B' : 'A';
+
+ snprintf(result, len, "%s, pipe %c, %d bit, %s",
+ enable, disp_pipe, depth, channels);
+}
+
+DEBUGSTRING(i830_debug_dvo)
+{
+ const char *enable = val & DVO_ENABLE ? "enabled" : "disabled";
+ char disp_pipe = val & DVO_PIPE_B_SELECT ? 'B' : 'A';
+ const char *stall;
+ char hsync = val & DVO_HSYNC_ACTIVE_HIGH ? '+' : '-';
+ char vsync = val & DVO_VSYNC_ACTIVE_HIGH ? '+' : '-';
+
+ switch (val & DVO_PIPE_STALL_MASK) {
+ case DVO_PIPE_STALL_UNUSED:
+ stall = "no stall";
+ break;
+ case DVO_PIPE_STALL:
+ stall = "stall";
+ break;
+ case DVO_PIPE_STALL_TV:
+ stall = "TV stall";
+ break;
+ default:
+ stall = "unknown stall";
+ break;
+ }
+
+ snprintf(result, len, "%s, pipe %c, %s, %chsync, %cvsync",
+ enable, disp_pipe, stall, hsync, vsync);
+}
+
+DEBUGSTRING(i830_debug_sdvo)
+{
+ const char *enable = val & SDVO_ENABLE ? "enabled" : "disabled";
+ char disp_pipe = val & SDVO_PIPE_B_SELECT ? 'B' : 'A';
+ const char *stall = val & SDVO_STALL_SELECT ? "enabled" : "disabled";
+ const char *detected = val & SDVO_DETECTED ? "" : "not ";
+ const char *gang = val & SDVOC_GANG_MODE ? ", gang mode" : "";
+ char sdvoextra[20];
+
+ if (IS_915(devid)) {
+ sprintf(sdvoextra, ", SDVO mult %d",
+ (int)((val & SDVO_PORT_MULTIPLY_MASK) >>
+ SDVO_PORT_MULTIPLY_SHIFT) + 1);
+ } else {
+ sdvoextra[0] = '\0';
+ }
+
+ snprintf(result, len, "%s, pipe %c, stall %s, %sdetected%s%s",
+ enable, disp_pipe, stall, detected, sdvoextra, gang);
+}
+
+DEBUGSTRING(i830_debug_dspclk_gate_d)
+{
+ const char *DPUNIT_B = val & DPUNIT_B_CLOCK_GATE_DISABLE ? " DPUNIT_B" : "";
+ const char *VSUNIT = val & VSUNIT_CLOCK_GATE_DISABLE ? " VSUNIT" : "";
+ const char *VRHUNIT = val & VRHUNIT_CLOCK_GATE_DISABLE ? " VRHUNIT" : "";
+ const char *VRDUNIT = val & VRDUNIT_CLOCK_GATE_DISABLE ? " VRDUNIT" : "";
+ const char *AUDUNIT = val & AUDUNIT_CLOCK_GATE_DISABLE ? " AUDUNIT" : "";
+ const char *DPUNIT_A = val & DPUNIT_A_CLOCK_GATE_DISABLE ? " DPUNIT_A" : "";
+ const char *DPCUNIT = val & DPCUNIT_CLOCK_GATE_DISABLE ? " DPCUNIT" : "";
+ const char *TVRUNIT = val & TVRUNIT_CLOCK_GATE_DISABLE ? " TVRUNIT" : "";
+ const char *TVCUNIT = val & TVCUNIT_CLOCK_GATE_DISABLE ? " TVCUNIT" : "";
+ const char *TVFUNIT = val & TVFUNIT_CLOCK_GATE_DISABLE ? " TVFUNIT" : "";
+ const char *TVEUNIT = val & TVEUNIT_CLOCK_GATE_DISABLE ? " TVEUNIT" : "";
+ const char *DVSUNIT = val & DVSUNIT_CLOCK_GATE_DISABLE ? " DVSUNIT" : "";
+ const char *DSSUNIT = val & DSSUNIT_CLOCK_GATE_DISABLE ? " DSSUNIT" : "";
+ const char *DDBUNIT = val & DDBUNIT_CLOCK_GATE_DISABLE ? " DDBUNIT" : "";
+ const char *DPRUNIT = val & DPRUNIT_CLOCK_GATE_DISABLE ? " DPRUNIT" : "";
+ const char *DPFUNIT = val & DPFUNIT_CLOCK_GATE_DISABLE ? " DPFUNIT" : "";
+ const char *DPBMUNIT = val & DPBMUNIT_CLOCK_GATE_DISABLE ? " DPBMUNIT" : "";
+ const char *DPLSUNIT = val & DPLSUNIT_CLOCK_GATE_DISABLE ? " DPLSUNIT" : "";
+ const char *DPLUNIT = val & DPLUNIT_CLOCK_GATE_DISABLE ? " DPLUNIT" : "";
+ const char *DPOUNIT = val & DPOUNIT_CLOCK_GATE_DISABLE ? " DPOUNIT" : "";
+ const char *DPBUNIT = val & DPBUNIT_CLOCK_GATE_DISABLE ? " DPBUNIT" : "";
+ const char *DCUNIT = val & DCUNIT_CLOCK_GATE_DISABLE ? " DCUNIT" : "";
+ const char *DPUNIT = val & DPUNIT_CLOCK_GATE_DISABLE ? " DPUNIT" : "";
+ const char *VRUNIT = val & VRUNIT_CLOCK_GATE_DISABLE ? " VRUNIT" : "";
+ const char *OVHUNIT = val & OVHUNIT_CLOCK_GATE_DISABLE ? " OVHUNIT" : "";
+ const char *DPIOUNIT = val & DPIOUNIT_CLOCK_GATE_DISABLE ? " DPIOUNIT" : "";
+ const char *OVFUNIT = val & OVFUNIT_CLOCK_GATE_DISABLE ? " OVFUNIT" : "";
+ const char *OVBUNIT = val & OVBUNIT_CLOCK_GATE_DISABLE ? " OVBUNIT" : "";
+ const char *OVRUNIT = val & OVRUNIT_CLOCK_GATE_DISABLE ? " OVRUNIT" : "";
+ const char *OVCUNIT = val & OVCUNIT_CLOCK_GATE_DISABLE ? " OVCUNIT" : "";
+ const char *OVUUNIT = val & OVUUNIT_CLOCK_GATE_DISABLE ? " OVUUNIT" : "";
+ const char *OVLUNIT = val & OVLUNIT_CLOCK_GATE_DISABLE ? " OVLUNIT" : "";
+
+ snprintf(result, len,
+ "clock gates disabled:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ DPUNIT_B, VSUNIT, VRHUNIT, VRDUNIT, AUDUNIT, DPUNIT_A, DPCUNIT,
+ TVRUNIT, TVCUNIT, TVFUNIT, TVEUNIT, DVSUNIT, DSSUNIT, DDBUNIT,
+ DPRUNIT, DPFUNIT, DPBMUNIT, DPLSUNIT, DPLUNIT, DPOUNIT, DPBUNIT,
+ DCUNIT, DPUNIT, VRUNIT, OVHUNIT, DPIOUNIT, OVFUNIT, OVBUNIT,
+ OVRUNIT, OVCUNIT, OVUUNIT, OVLUNIT);
+}
+
+DEBUGSTRING(i810_debug_915_fence)
+{
+ char format = (val & 1 << 12) ? 'Y' : 'X';
+ int pitch = 128 << ((val & 0x70) >> 4);
+ unsigned int offset = val & 0x0ff00000;
+ int size = (1024 * 1024) << ((val & 0x700) >> 8);
+
+ if (IS_965(devid) || (IS_915(devid) && reg >= FENCE_NEW))
+ return;
+
+ if (format == 'X')
+ pitch *= 4;
+ if (val & 1) {
+ snprintf(result, len, "enabled, %c tiled, %4d pitch, 0x%08x - 0x%08x (%dkb)",
+ format, pitch, offset, offset + size,
+ size / 1024);
+ } else {
+ snprintf(result, len, "disabled");
+ }
+}
+
+DEBUGSTRING(i810_debug_965_fence_start)
+{
+ const char *enable = (val & FENCE_VALID) ? " enabled" : "disabled";
+ char format = (val & I965_FENCE_Y_MAJOR) ? 'Y' : 'X';
+ int pitch = ((val & 0xffc) >> 2) * 128 + 128;
+ unsigned int offset = val & 0xfffff000;
+
+ if (!IS_965(devid))
+ return;
+
+ snprintf(result, len, "%s, %c tile walk, %4d pitch, 0x%08x start",
+ enable, format, pitch, offset);
+}
+
+DEBUGSTRING(i810_debug_965_fence_end)
+{
+ unsigned int end = val & 0xfffff000;
+
+ if (!IS_965(devid))
+ return;
+
+ snprintf(result, len, " 0x%08x end", end);
+}
+
+#define DEFINEREG(reg) \
+ { reg, #reg, NULL, 0 }
+#define DEFINEREG_16BIT(reg) \
+ { reg, #reg, i830_16bit_func, 0 }
+#define DEFINEREG2(reg, func) \
+ { reg, #reg, func, 0 }
+
+struct reg_debug {
+ int reg;
+ const char *name;
+ void (*debug_output) (char *result, int len, int reg, uint32_t val);
+ uint32_t val;
+};
+
+static struct reg_debug intel_debug_regs[] = {
+ DEFINEREG2(DCC, i830_debug_dcc),
+ DEFINEREG2(CHDECMISC, i830_debug_chdecmisc),
+ DEFINEREG_16BIT(C0DRB0),
+ DEFINEREG_16BIT(C0DRB1),
+ DEFINEREG_16BIT(C0DRB2),
+ DEFINEREG_16BIT(C0DRB3),
+ DEFINEREG_16BIT(C1DRB0),
+ DEFINEREG_16BIT(C1DRB1),
+ DEFINEREG_16BIT(C1DRB2),
+ DEFINEREG_16BIT(C1DRB3),
+ DEFINEREG_16BIT(C0DRA01),
+ DEFINEREG_16BIT(C0DRA23),
+ DEFINEREG_16BIT(C1DRA01),
+ DEFINEREG_16BIT(C1DRA23),
+
+ DEFINEREG(PGETBL_CTL),
+
+ DEFINEREG2(VCLK_DIVISOR_VGA0, i830_debug_fp),
+ DEFINEREG2(VCLK_DIVISOR_VGA1, i830_debug_fp),
+ DEFINEREG2(VCLK_POST_DIV, i830_debug_vga_pd),
+ DEFINEREG2(DPLL_TEST, i830_debug_dpll_test),
+ DEFINEREG(CACHE_MODE_0),
+ DEFINEREG(D_STATE),
+ DEFINEREG2(DSPCLK_GATE_D, i830_debug_dspclk_gate_d),
+ DEFINEREG(RENCLK_GATE_D1),
+ DEFINEREG(RENCLK_GATE_D2),
+/* DEFINEREG(RAMCLK_GATE_D), CRL only */
+ DEFINEREG2(SDVOB, i830_debug_sdvo),
+ DEFINEREG2(SDVOC, i830_debug_sdvo),
+/* DEFINEREG(UDIB_SVB_SHB_CODES), CRL only */
+/* DEFINEREG(UDIB_SHA_BLANK_CODES), CRL only */
+ DEFINEREG(SDVOUDI),
+ DEFINEREG(DSPARB),
+ DEFINEREG(DSPFW1),
+ DEFINEREG(DSPFW2),
+ DEFINEREG(DSPFW3),
+
+ DEFINEREG2(ADPA, i830_debug_adpa),
+ DEFINEREG2(LVDS, i830_debug_lvds),
+ DEFINEREG2(DVOA, i830_debug_dvo),
+ DEFINEREG2(DVOB, i830_debug_dvo),
+ DEFINEREG2(DVOC, i830_debug_dvo),
+ DEFINEREG(DVOA_SRCDIM),
+ DEFINEREG(DVOB_SRCDIM),
+ DEFINEREG(DVOC_SRCDIM),
+
+ DEFINEREG(BLC_PWM_CTL),
+ DEFINEREG(BLC_PWM_CTL2),
+
+ DEFINEREG2(PP_CONTROL, i830_debug_pp_control),
+ DEFINEREG2(PP_STATUS, i830_debug_pp_status),
+ DEFINEREG(PP_ON_DELAYS),
+ DEFINEREG(PP_OFF_DELAYS),
+ DEFINEREG(PP_DIVISOR),
+ DEFINEREG(PFIT_CONTROL),
+ DEFINEREG(PFIT_PGM_RATIOS),
+ DEFINEREG(PORT_HOTPLUG_EN),
+ DEFINEREG(PORT_HOTPLUG_STAT),
+
+ DEFINEREG2(DSPACNTR, i830_debug_dspcntr),
+ DEFINEREG2(DSPASTRIDE, i830_debug_dspstride),
+ DEFINEREG2(DSPAPOS, i830_debug_xy),
+ DEFINEREG2(DSPASIZE, i830_debug_xyminus1),
+ DEFINEREG(DSPABASE),
+ DEFINEREG(DSPASURF),
+ DEFINEREG(DSPATILEOFF),
+ DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
+ DEFINEREG2(PIPEASRC, i830_debug_yxminus1),
+ DEFINEREG2(PIPEASTAT, i830_debug_pipestat),
+ DEFINEREG(PIPEA_GMCH_DATA_M),
+ DEFINEREG(PIPEA_GMCH_DATA_N),
+ DEFINEREG(PIPEA_DP_LINK_M),
+ DEFINEREG(PIPEA_DP_LINK_N),
+ DEFINEREG(CURSOR_A_BASE),
+ DEFINEREG(CURSOR_A_CONTROL),
+ DEFINEREG(CURSOR_A_POSITION),
+
+ DEFINEREG2(FPA0, i830_debug_fp),
+ DEFINEREG2(FPA1, i830_debug_fp),
+ DEFINEREG2(DPLL_A, i830_debug_dpll),
+ DEFINEREG(DPLL_A_MD),
+ DEFINEREG2(HTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG(BCLRPAT_A),
+ DEFINEREG(VSYNCSHIFT_A),
+
+ DEFINEREG2(DSPBCNTR, i830_debug_dspcntr),
+ DEFINEREG2(DSPBSTRIDE, i830_debug_dspstride),
+ DEFINEREG2(DSPBPOS, i830_debug_xy),
+ DEFINEREG2(DSPBSIZE, i830_debug_xyminus1),
+ DEFINEREG(DSPBBASE),
+ DEFINEREG(DSPBSURF),
+ DEFINEREG(DSPBTILEOFF),
+ DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
+ DEFINEREG2(PIPEBSRC, i830_debug_yxminus1),
+ DEFINEREG2(PIPEBSTAT, i830_debug_pipestat),
+ DEFINEREG(PIPEB_GMCH_DATA_M),
+ DEFINEREG(PIPEB_GMCH_DATA_N),
+ DEFINEREG(PIPEB_DP_LINK_M),
+ DEFINEREG(PIPEB_DP_LINK_N),
+ DEFINEREG(CURSOR_B_BASE),
+ DEFINEREG(CURSOR_B_CONTROL),
+ DEFINEREG(CURSOR_B_POSITION),
+
+ DEFINEREG2(FPB0, i830_debug_fp),
+ DEFINEREG2(FPB1, i830_debug_fp),
+ DEFINEREG2(DPLL_B, i830_debug_dpll),
+ DEFINEREG(DPLL_B_MD),
+ DEFINEREG2(HTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG(BCLRPAT_B),
+ DEFINEREG(VSYNCSHIFT_B),
+
+ DEFINEREG(VCLK_DIVISOR_VGA0),
+ DEFINEREG(VCLK_DIVISOR_VGA1),
+ DEFINEREG(VCLK_POST_DIV),
+ DEFINEREG2(VGACNTRL, i830_debug_vgacntrl),
+
+ DEFINEREG(TV_CTL),
+ DEFINEREG(TV_DAC),
+ DEFINEREG(TV_CSC_Y),
+ DEFINEREG(TV_CSC_Y2),
+ DEFINEREG(TV_CSC_U),
+ DEFINEREG(TV_CSC_U2),
+ DEFINEREG(TV_CSC_V),
+ DEFINEREG(TV_CSC_V2),
+ DEFINEREG(TV_CLR_KNOBS),
+ DEFINEREG(TV_CLR_LEVEL),
+ DEFINEREG(TV_H_CTL_1),
+ DEFINEREG(TV_H_CTL_2),
+ DEFINEREG(TV_H_CTL_3),
+ DEFINEREG(TV_V_CTL_1),
+ DEFINEREG(TV_V_CTL_2),
+ DEFINEREG(TV_V_CTL_3),
+ DEFINEREG(TV_V_CTL_4),
+ DEFINEREG(TV_V_CTL_5),
+ DEFINEREG(TV_V_CTL_6),
+ DEFINEREG(TV_V_CTL_7),
+ DEFINEREG(TV_SC_CTL_1),
+ DEFINEREG(TV_SC_CTL_2),
+ DEFINEREG(TV_SC_CTL_3),
+ DEFINEREG(TV_WIN_POS),
+ DEFINEREG(TV_WIN_SIZE),
+ DEFINEREG(TV_FILTER_CTL_1),
+ DEFINEREG(TV_FILTER_CTL_2),
+ DEFINEREG(TV_FILTER_CTL_3),
+ DEFINEREG(TV_CC_CONTROL),
+ DEFINEREG(TV_CC_DATA),
+ DEFINEREG(TV_H_LUMA_0),
+ DEFINEREG(TV_H_LUMA_59),
+ DEFINEREG(TV_H_CHROMA_0),
+ DEFINEREG(TV_H_CHROMA_59),
+
+ DEFINEREG(FBC_CFB_BASE),
+ DEFINEREG(FBC_LL_BASE),
+ DEFINEREG(FBC_CONTROL),
+ DEFINEREG(FBC_COMMAND),
+ DEFINEREG(FBC_STATUS),
+ DEFINEREG(FBC_CONTROL2),
+ DEFINEREG(FBC_FENCE_OFF),
+ DEFINEREG(FBC_MOD_NUM),
+
+ DEFINEREG(MI_MODE),
+ /* DEFINEREG(MI_DISPLAY_POWER_DOWN), CRL only */
+ DEFINEREG(MI_ARB_STATE),
+ DEFINEREG(MI_RDRET_STATE),
+ DEFINEREG(ECOSKPD),
+
+ DEFINEREG(DP_B),
+ DEFINEREG(DPB_AUX_CH_CTL),
+ DEFINEREG(DPB_AUX_CH_DATA1),
+ DEFINEREG(DPB_AUX_CH_DATA2),
+ DEFINEREG(DPB_AUX_CH_DATA3),
+ DEFINEREG(DPB_AUX_CH_DATA4),
+ DEFINEREG(DPB_AUX_CH_DATA5),
+
+ DEFINEREG(DP_C),
+ DEFINEREG(DPC_AUX_CH_CTL),
+ DEFINEREG(DPC_AUX_CH_DATA1),
+ DEFINEREG(DPC_AUX_CH_DATA2),
+ DEFINEREG(DPC_AUX_CH_DATA3),
+ DEFINEREG(DPC_AUX_CH_DATA4),
+ DEFINEREG(DPC_AUX_CH_DATA5),
+
+ DEFINEREG(DP_D),
+ DEFINEREG(DPD_AUX_CH_CTL),
+ DEFINEREG(DPD_AUX_CH_DATA1),
+ DEFINEREG(DPD_AUX_CH_DATA2),
+ DEFINEREG(DPD_AUX_CH_DATA3),
+ DEFINEREG(DPD_AUX_CH_DATA4),
+ DEFINEREG(DPD_AUX_CH_DATA5),
+
+ DEFINEREG(AUD_CONFIG),
+ DEFINEREG(AUD_HDMIW_STATUS),
+ DEFINEREG(AUD_CONV_CHCNT),
+ DEFINEREG(VIDEO_DIP_CTL),
+ DEFINEREG(AUD_PINW_CNTR),
+ DEFINEREG(AUD_CNTL_ST),
+ DEFINEREG(AUD_PIN_CAP),
+ DEFINEREG(AUD_PINW_CAP),
+ DEFINEREG(AUD_PINW_UNSOLRESP),
+ DEFINEREG(AUD_OUT_DIG_CNVT),
+ DEFINEREG(AUD_OUT_CWCAP),
+ DEFINEREG(AUD_GRP_CAP),
+
+#define DEFINEFENCE_915(i) \
+ { FENCE+i*4, "FENCE " #i, i810_debug_915_fence, 0 }
+#define DEFINEFENCE_945(i) \
+ { FENCE_NEW+(i - 8) * 4, "FENCE " #i, i810_debug_915_fence, 0 }
+
+ DEFINEFENCE_915(0),
+ DEFINEFENCE_915(1),
+ DEFINEFENCE_915(2),
+ DEFINEFENCE_915(3),
+ DEFINEFENCE_915(4),
+ DEFINEFENCE_915(5),
+ DEFINEFENCE_915(6),
+ DEFINEFENCE_915(7),
+ DEFINEFENCE_945(8),
+ DEFINEFENCE_945(9),
+ DEFINEFENCE_945(10),
+ DEFINEFENCE_945(11),
+ DEFINEFENCE_945(12),
+ DEFINEFENCE_945(13),
+ DEFINEFENCE_945(14),
+ DEFINEFENCE_945(15),
+
+#define DEFINEFENCE_965(i) \
+ { FENCE_NEW+i*8, "FENCE START " #i, i810_debug_965_fence_start, 0 }, \
+ { FENCE_NEW+i*8+4, "FENCE END " #i, i810_debug_965_fence_end, 0 }
+
+ DEFINEFENCE_965(0),
+ DEFINEFENCE_965(1),
+ DEFINEFENCE_965(2),
+ DEFINEFENCE_965(3),
+ DEFINEFENCE_965(4),
+ DEFINEFENCE_965(5),
+ DEFINEFENCE_965(6),
+ DEFINEFENCE_965(7),
+ DEFINEFENCE_965(8),
+ DEFINEFENCE_965(9),
+ DEFINEFENCE_965(10),
+ DEFINEFENCE_965(11),
+ DEFINEFENCE_965(12),
+ DEFINEFENCE_965(13),
+ DEFINEFENCE_965(14),
+ DEFINEFENCE_965(15),
+
+ DEFINEREG(INST_PM),
+};
+
+DEBUGSTRING(ironlake_debug_rr_hw_ctl)
+{
+ snprintf(result, len, "low %d, high %d", val & RR_HW_LOW_POWER_FRAMES_MASK,
+ (val & RR_HW_HIGH_POWER_FRAMES_MASK) >> 8);
+}
+
+DEBUGSTRING(ironlake_debug_m_tu)
+{
+ snprintf(result, len, "TU %d, val 0x%x %d", (val >> 25) + 1, val & 0xffffff,
+ val & 0xffffff);
+}
+
+DEBUGSTRING(ironlake_debug_n)
+{
+ snprintf(result, len, "val 0x%x %d", val & 0xffffff, val & 0xffffff);
+}
+
+DEBUGSTRING(ironlake_debug_fdi_tx_ctl)
+{
+ const char *train = NULL, *voltage = NULL, *pre_emphasis = NULL, *portw =
+ NULL;
+
+ switch (val & FDI_LINK_TRAIN_NONE) {
+ case FDI_LINK_TRAIN_PATTERN_1:
+ train = "pattern_1";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_2:
+ train = "pattern_2";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_IDLE:
+ train = "pattern_idle";
+ break;
+ case FDI_LINK_TRAIN_NONE:
+ train = "not train";
+ break;
+ }
+
+ if (HAS_CPT) {
+ /* SNB B0 */
+ switch (val & (0x3f << 22)) {
+ case FDI_LINK_TRAIN_400MV_0DB_SNB_B:
+ voltage = "0.4V";
+ pre_emphasis = "0dB";
+ break;
+ case FDI_LINK_TRAIN_400MV_6DB_SNB_B:
+ voltage = "0.4V";
+ pre_emphasis = "6dB";
+ break;
+ case FDI_LINK_TRAIN_600MV_3_5DB_SNB_B:
+ voltage = "0.6V";
+ pre_emphasis = "3.5dB";
+ break;
+ case FDI_LINK_TRAIN_800MV_0DB_SNB_B:
+ voltage = "0.8V";
+ pre_emphasis = "0dB";
+ break;
+ }
+
+ } else {
+
+ switch (val & (7 << 25)) {
+ case FDI_LINK_TRAIN_VOLTAGE_0_4V:
+ voltage = "0.4V";
+ break;
+ case FDI_LINK_TRAIN_VOLTAGE_0_6V:
+ voltage = "0.6V";
+ break;
+ case FDI_LINK_TRAIN_VOLTAGE_0_8V:
+ voltage = "0.8V";
+ break;
+ case FDI_LINK_TRAIN_VOLTAGE_1_2V:
+ voltage = "1.2V";
+ break;
+ default:
+ voltage = "reserved";
+ }
+
+ switch (val & (7 << 22)) {
+ case FDI_LINK_TRAIN_PRE_EMPHASIS_NONE:
+ pre_emphasis = "none";
+ break;
+ case FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X:
+ pre_emphasis = "1.5x";
+ break;
+ case FDI_LINK_TRAIN_PRE_EMPHASIS_2X:
+ pre_emphasis = "2x";
+ break;
+ case FDI_LINK_TRAIN_PRE_EMPHASIS_3X:
+ pre_emphasis = "3x";
+ break;
+ default:
+ pre_emphasis = "reserved";
+ }
+
+ }
+
+ switch (val & (7 << 19)) {
+ case FDI_DP_PORT_WIDTH_X1:
+ portw = "X1";
+ break;
+ case FDI_DP_PORT_WIDTH_X2:
+ portw = "X2";
+ break;
+ case FDI_DP_PORT_WIDTH_X3:
+ portw = "X3";
+ break;
+ case FDI_DP_PORT_WIDTH_X4:
+ portw = "X4";
+ break;
+ }
+
+ snprintf(result, len, "%s, train pattern %s, voltage swing %s,"
+ "pre-emphasis %s, port width %s, enhanced framing %s, FDI PLL %s, scrambing %s, master mode %s",
+ val & FDI_TX_ENABLE ? "enable" : "disable",
+ train, voltage, pre_emphasis, portw,
+ val & FDI_TX_ENHANCE_FRAME_ENABLE ? "enable" :
+ "disable",
+ val & FDI_TX_PLL_ENABLE ? "enable" : "disable",
+ val & (1 << 7) ? "disable" : "enable",
+ val & (1 << 0) ? "enable" : "disable");
+}
+
+DEBUGSTRING(ironlake_debug_fdi_rx_ctl)
+{
+ const char *train = NULL, *portw = NULL, *bpc = NULL;
+
+ if (HAS_CPT) {
+ switch (val & FDI_LINK_TRAIN_PATTERN_MASK_CPT) {
+ case FDI_LINK_TRAIN_PATTERN_1_CPT:
+ train = "pattern_1";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_2_CPT:
+ train = "pattern_2";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_IDLE_CPT:
+ train = "pattern_idle";
+ break;
+ case FDI_LINK_TRAIN_NORMAL_CPT:
+ train = "not train";
+ break;
+ }
+ } else {
+ switch (val & FDI_LINK_TRAIN_NONE) {
+ case FDI_LINK_TRAIN_PATTERN_1:
+ train = "pattern_1";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_2:
+ train = "pattern_2";
+ break;
+ case FDI_LINK_TRAIN_PATTERN_IDLE:
+ train = "pattern_idle";
+ break;
+ case FDI_LINK_TRAIN_NONE:
+ train = "not train";
+ break;
+ }
+ }
+
+ switch (val & (7 << 19)) {
+ case FDI_DP_PORT_WIDTH_X1:
+ portw = "X1";
+ break;
+ case FDI_DP_PORT_WIDTH_X2:
+ portw = "X2";
+ break;
+ case FDI_DP_PORT_WIDTH_X3:
+ portw = "X3";
+ break;
+ case FDI_DP_PORT_WIDTH_X4:
+ portw = "X4";
+ break;
+ }
+
+ switch (val & (7 << 16)) {
+ case FDI_8BPC:
+ bpc = "8bpc";
+ break;
+ case FDI_10BPC:
+ bpc = "10bpc";
+ break;
+ case FDI_6BPC:
+ bpc = "6bpc";
+ break;
+ case FDI_12BPC:
+ bpc = "12bpc";
+ break;
+ }
+
+ snprintf(result, len, "%s, train pattern %s, port width %s, %s,"
+ "link_reverse_strap_overwrite %s, dmi_link_reverse %s, FDI PLL %s,"
+ "FS ecc %s, FE ecc %s, FS err report %s, FE err report %s,"
+ "scrambing %s, enhanced framing %s, %s",
+ val & FDI_RX_ENABLE ? "enable" : "disable",
+ train, portw, bpc,
+ val & FDI_LINK_REVERSE_OVERWRITE ? "yes" : "no",
+ val & FDI_DMI_LINK_REVERSE_MASK ? "yes" : "no",
+ val & FDI_RX_PLL_ENABLE ? "enable" : "disable",
+ val & FDI_FS_ERR_CORRECT_ENABLE ? "enable" : "disable",
+ val & FDI_FE_ERR_CORRECT_ENABLE ? "enable" : "disable",
+ val & FDI_FS_ERR_REPORT_ENABLE ? "enable" : "disable",
+ val & FDI_FE_ERR_REPORT_ENABLE ? "enable" : "disable",
+ val & (1 << 7) ? "disable" : "enable",
+ val & FDI_RX_ENHANCE_FRAME_ENABLE ? "enable" :
+ "disable", val & FDI_SEL_PCDCLK ? "PCDClk" : "RawClk");
+}
+
+DEBUGSTRING(ironlake_debug_dspstride)
+{
+ snprintf(result, len, "%d", val >> 6);
+}
+
+DEBUGSTRING(ironlake_debug_pch_dpll)
+{
+ const char *enable = val & DPLL_VCO_ENABLE ? "enable" : "disable";
+ const char *highspeed = val & DPLL_DVO_HIGH_SPEED ? "yes" : "no";
+ const char *mode = NULL;
+ const char *p2 = NULL;
+ int fpa0_p1, fpa1_p1;
+ const char *refclk = NULL;
+ int sdvo_mul;
+
+ if ((val & DPLLB_MODE_LVDS) == DPLLB_MODE_LVDS) {
+ mode = "LVDS";
+ if (val & DPLLB_LVDS_P2_CLOCK_DIV_7)
+ p2 = "Div 7";
+ else
+ p2 = "Div 14";
+ } else if ((val & DPLLB_MODE_LVDS) == DPLLB_MODE_DAC_SERIAL) {
+ mode = "Non-LVDS";
+ if (val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5)
+ p2 = "Div 5";
+ else
+ p2 = "Div 10";
+ }
+ fpa0_p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >> 16);
+ fpa1_p1 = ffs((val & DPLL_FPA1_P1_POST_DIV_MASK));
+
+ switch (val & PLL_REF_INPUT_MASK) {
+ case PLL_REF_INPUT_DREFCLK:
+ refclk = "default 120Mhz";
+ break;
+ case PLL_REF_INPUT_SUPER_SSC:
+ refclk = "SuperSSC 120Mhz";
+ break;
+ case PLL_REF_INPUT_TVCLKINBC:
+ refclk = "SDVO TVClkIn";
+ break;
+ case PLLB_REF_INPUT_SPREADSPECTRUMIN:
+ refclk = "SSC";
+ break;
+ case PLL_REF_INPUT_DMICLK:
+ refclk = "DMI RefCLK";
+ break;
+ }
+
+ sdvo_mul = ((val & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) >> 9) + 1;
+
+ snprintf(result, len, "%s, sdvo high speed %s, mode %s, p2 %s, "
+ "FPA0 P1 %d, FPA1 P1 %d, refclk %s, sdvo/hdmi mul %d",
+ enable, highspeed, mode, p2, fpa0_p1, fpa1_p1, refclk,
+ sdvo_mul);
+}
+
+DEBUGSTRING(ironlake_debug_dref_ctl)
+{
+ const char *cpu_source;
+ const char *ssc_source = val & DREF_SSC_SOURCE_ENABLE ? "enable" : "disable";
+ const char *nonspread_source =
+ val & DREF_NONSPREAD_SOURCE_ENABLE ? "enable" : "disable";
+ const char *superspread_source =
+ val & DREF_SUPERSPREAD_SOURCE_ENABLE ? "enable" : "disable";
+ const char *ssc4_mode =
+ val & DREF_SSC4_CENTERSPREAD ? "centerspread" : "downspread";
+ const char *ssc1 = val & DREF_SSC1_ENABLE ? "enable" : "disable";
+ const char *ssc4 = val & DREF_SSC4_ENABLE ? "enable" : "disable";
+
+ switch (val & DREF_CPU_SOURCE_OUTPUT_NONSPREAD) {
+ case DREF_CPU_SOURCE_OUTPUT_DISABLE:
+ cpu_source = "disable";
+ break;
+ case DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD:
+ cpu_source = "downspread";
+ break;
+ case DREF_CPU_SOURCE_OUTPUT_NONSPREAD:
+ cpu_source = "nonspread";
+ break;
+ default:
+ cpu_source = "reserved";
+ }
+ snprintf(result, len, "cpu source %s, ssc_source %s, nonspread_source %s, "
+ "superspread_source %s, ssc4_mode %s, ssc1 %s, ssc4 %s",
+ cpu_source, ssc_source, nonspread_source,
+ superspread_source, ssc4_mode, ssc1, ssc4);
+}
+
+DEBUGSTRING(ironlake_debug_rawclk_freq)
+{
+ const char *tp1 = NULL, *tp2 = NULL;
+
+ switch (val & FDL_TP1_TIMER_MASK) {
+ case 0:
+ tp1 = "0.5us";
+ break;
+ case (1 << 12):
+ tp1 = "1.0us";
+ break;
+ case (2 << 12):
+ tp1 = "2.0us";
+ break;
+ case (3 << 12):
+ tp1 = "4.0us";
+ break;
+ }
+ switch (val & FDL_TP2_TIMER_MASK) {
+ case 0:
+ tp2 = "1.5us";
+ break;
+ case (1 << 10):
+ tp2 = "3.0us";
+ break;
+ case (2 << 10):
+ tp2 = "6.0us";
+ break;
+ case (3 << 10):
+ tp2 = "12.0us";
+ break;
+ }
+ snprintf(result, len, "FDL_TP1 timer %s, FDL_TP2 timer %s, freq %d",
+ tp1, tp2, val & RAWCLK_FREQ_MASK);
+
+}
+
+DEBUGSTRING(ironlake_debug_fdi_rx_misc)
+{
+ snprintf(result, len, "FDI Delay %d", val & ((1 << 13) - 1));
+}
+
+DEBUGSTRING(ironlake_debug_transconf)
+{
+ const char *enable = val & TRANS_ENABLE ? "enable" : "disable";
+ const char *state = val & TRANS_STATE_ENABLE ? "active" : "inactive";
+ const char *interlace;
+
+ switch ((val >> 21) & 7) {
+ case 0:
+ interlace = "progressive";
+ break;
+ case 2:
+ if (IS_GEN5(devid))
+ interlace = "interlaced sdvo";
+ else
+ interlace = "rsvd";
+ break;
+ case 3:
+ interlace = "interlaced";
+ break;
+ default:
+ interlace = "rsvd";
+ }
+
+ snprintf(result, len, "%s, %s, %s", enable, state, interlace);
+}
+
+DEBUGSTRING(ironlake_debug_panel_fitting)
+{
+ const char *vadapt = NULL, *filter_sel = NULL;
+
+ switch (val & (3 << 25)) {
+ case 0:
+ vadapt = "least";
+ break;
+ case (1 << 25):
+ vadapt = "moderate";
+ break;
+ case (2 << 25):
+ vadapt = "reserved";
+ break;
+ case (3 << 25):
+ vadapt = "most";
+ break;
+ }
+
+ switch (val & (3 << 23)) {
+ case 0:
+ filter_sel = "programmed";
+ break;
+ case (1 << 23):
+ filter_sel = "hardcoded";
+ break;
+ case (2 << 23):
+ filter_sel = "edge_enhance";
+ break;
+ case (3 << 23):
+ filter_sel = "edge_soften";
+ break;
+ }
+
+ snprintf(result, len,
+ "%s, auto_scale %s, auto_scale_cal %s, v_filter %s, vadapt %s, mode %s, filter_sel %s,"
+ "chroma pre-filter %s, vert3tap %s, v_inter_invert %s",
+ val & PF_ENABLE ? "enable" : "disable",
+ val & (1 << 30) ? "no" : "yes",
+ val & (1 << 29) ? "yes" : "no",
+ val & (1 << 28) ? "bypass" : "enable",
+ val & (1 << 27) ? "enable" : "disable",
+ vadapt,
+ filter_sel,
+ val & (1 << 22) ? "enable" : "disable",
+ val & (1 << 21) ? "force" : "auto",
+ val & (1 << 20) ? "field 0" : "field 1");
+}
+
+DEBUGSTRING(ironlake_debug_panel_fitting_2)
+{
+ snprintf(result, len,
+ "vscale %f",
+ val / (float) (1<<15));
+}
+
+DEBUGSTRING(ironlake_debug_panel_fitting_3)
+{
+ snprintf(result, len,
+ "vscale initial phase %f",
+ val / (float) (1<<15));
+}
+
+DEBUGSTRING(ironlake_debug_panel_fitting_4)
+{
+ snprintf(result, len,
+ "hscale %f",
+ val / (float) (1<<15));
+}
+
+DEBUGSTRING(ironlake_debug_pf_win)
+{
+ int a, b;
+
+ a = (val >> 16) & 0x1fff;
+ b = val & 0xfff;
+
+ snprintf(result, len, "%d, %d", a, b);
+}
+
+DEBUGSTRING(ironlake_debug_hdmi)
+{
+ int disp_pipe;
+ const char *enable, *bpc = NULL, *encoding;
+ const char *mode, *audio, *vsync, *hsync, *detect;
+
+ if (val & PORT_ENABLE)
+ enable = "enabled";
+ else
+ enable = "disabled";
+
+ if (HAS_CPT)
+ disp_pipe = (val & (3<<29)) >> 29;
+ else
+ disp_pipe = (val & TRANSCODER_B) >> 29;
+
+ switch (val & (7 << 26)) {
+ case COLOR_FORMAT_8bpc:
+ bpc = "8bpc";
+ break;
+ case COLOR_FORMAT_12bpc:
+ bpc = "12bpc";
+ break;
+ }
+
+ if ((val & (3 << 10)) == TMDS_ENCODING)
+ encoding = "TMDS";
+ else
+ encoding = "SDVO";
+
+ if (val & (1 << 9))
+ mode = "HDMI";
+ else
+ mode = "DVI";
+
+ if (val & AUDIO_ENABLE)
+ audio = "enabled";
+ else
+ audio = "disabled";
+
+ if (val & VSYNC_ACTIVE_HIGH)
+ vsync = "+vsync";
+ else
+ vsync = "-vsync";
+
+ if (val & HSYNC_ACTIVE_HIGH)
+ hsync = "+hsync";
+ else
+ hsync = "-hsync";
+
+ if (val & PORT_DETECTED)
+ detect = "detected";
+ else
+ detect = "non-detected";
+
+ snprintf(result, len, "%s pipe %c %s %s %s audio %s %s %s %s",
+ enable, disp_pipe + 'A', bpc, encoding, mode, audio, vsync, hsync, detect);
+}
+
+DEBUGSTRING(snb_debug_dpll_sel)
+{
+ const char *transa, *transb;
+ const char *dplla = NULL, *dpllb = NULL;
+
+ if (!HAS_CPT)
+ return;
+
+ if (val & TRANSA_DPLL_ENABLE) {
+ transa = "enable";
+ if (val & TRANSA_DPLLB_SEL)
+ dplla = "B";
+ else
+ dplla = "A";
+ } else
+ transa = "disable";
+
+ if (val & TRANSB_DPLL_ENABLE) {
+ transb = "enable";
+ if (val & TRANSB_DPLLB_SEL)
+ dpllb = "B";
+ else
+ dpllb = "A";
+ } else
+ transb = "disable";
+
+ snprintf(result, len, "TransA DPLL %s (DPLL %s), TransB DPLL %s (DPLL %s)",
+ transa, dplla, transb, dpllb);
+}
+
+DEBUGSTRING(snb_debug_trans_dp_ctl)
+{
+ const char *enable, *port = NULL, *bpc = NULL, *vsync, *hsync;
+
+ if (!HAS_CPT)
+ return;
+
+ if (val & TRANS_DP_OUTPUT_ENABLE)
+ enable = "enable";
+ else
+ enable = "disable";
+
+ switch (val & TRANS_DP_PORT_SEL_MASK) {
+ case TRANS_DP_PORT_SEL_B:
+ port = "B";
+ break;
+ case TRANS_DP_PORT_SEL_C:
+ port = "C";
+ break;
+ case TRANS_DP_PORT_SEL_D:
+ port = "D";
+ break;
+ default:
+ port = "none";
+ break;
+ }
+
+ switch (val & (7<<9)) {
+ case TRANS_DP_8BPC:
+ bpc = "8bpc";
+ break;
+ case TRANS_DP_10BPC:
+ bpc = "10bpc";
+ break;
+ case TRANS_DP_6BPC:
+ bpc = "6bpc";
+ break;
+ case TRANS_DP_12BPC:
+ bpc = "12bpc";
+ break;
+ }
+
+ if (val & TRANS_DP_VSYNC_ACTIVE_HIGH)
+ vsync = "+vsync";
+ else
+ vsync = "-vsync";
+
+ if (val & TRANS_DP_HSYNC_ACTIVE_HIGH)
+ hsync = "+hsync";
+ else
+ hsync = "-hsync";
+
+ snprintf(result, len, "%s port %s %s %s %s",
+ enable, port, bpc, vsync, hsync);
+}
+
+DEBUGSTRING(ilk_debug_pp_control)
+{
+ snprintf(result, len, "blacklight %s, %spower down on reset, panel %s",
+ (val & (1 << 2)) ? "enabled" : "disabled",
+ (val & (1 << 1)) ? "" : "do not ",
+ (val & (1 << 0)) ? "on" : "off");
+}
+
+static struct reg_debug ironlake_debug_regs[] = {
+ DEFINEREG(PGETBL_CTL),
+ DEFINEREG(GEN6_INSTDONE_1),
+ DEFINEREG(GEN6_INSTDONE_2),
+ DEFINEREG2(CPU_VGACNTRL, i830_debug_vgacntrl),
+ DEFINEREG(DIGITAL_PORT_HOTPLUG_CNTRL),
+
+ DEFINEREG2(RR_HW_CTL, ironlake_debug_rr_hw_ctl),
+
+ DEFINEREG(FDI_PLL_BIOS_0),
+ DEFINEREG(FDI_PLL_BIOS_1),
+ DEFINEREG(FDI_PLL_BIOS_2),
+
+ DEFINEREG(DISPLAY_PORT_PLL_BIOS_0),
+ DEFINEREG(DISPLAY_PORT_PLL_BIOS_1),
+ DEFINEREG(DISPLAY_PORT_PLL_BIOS_2),
+
+ DEFINEREG(FDI_PLL_FREQ_CTL),
+
+ /* pipe B */
+
+ DEFINEREG2(PIPEACONF, i830_debug_pipeconf),
+
+ DEFINEREG2(HTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG(VSYNCSHIFT_A),
+ DEFINEREG2(PIPEASRC, i830_debug_yxminus1),
+
+ DEFINEREG2(PIPEA_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEA_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEA_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEA_DATA_N2, ironlake_debug_n),
+
+ DEFINEREG2(PIPEA_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(PIPEA_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEA_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(PIPEA_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(DSPACNTR, i830_debug_dspcntr),
+ DEFINEREG(DSPABASE),
+ DEFINEREG2(DSPASTRIDE, ironlake_debug_dspstride),
+ DEFINEREG(DSPASURF),
+ DEFINEREG2(DSPATILEOFF, i830_debug_xy),
+
+ /* pipe B */
+
+ DEFINEREG2(PIPEBCONF, i830_debug_pipeconf),
+
+ DEFINEREG2(HTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG(VSYNCSHIFT_B),
+ DEFINEREG2(PIPEBSRC, i830_debug_yxminus1),
+
+ DEFINEREG2(PIPEB_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEB_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEB_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEB_DATA_N2, ironlake_debug_n),
+
+ DEFINEREG2(PIPEB_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(PIPEB_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEB_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(PIPEB_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(DSPBCNTR, i830_debug_dspcntr),
+ DEFINEREG(DSPBBASE),
+ DEFINEREG2(DSPBSTRIDE, ironlake_debug_dspstride),
+ DEFINEREG(DSPBSURF),
+ DEFINEREG2(DSPBTILEOFF, i830_debug_xy),
+
+ /* pipe C */
+
+ DEFINEREG2(PIPECCONF, i830_debug_pipeconf),
+
+ DEFINEREG2(HTOTAL_C, i830_debug_hvtotal),
+ DEFINEREG2(HBLANK_C, i830_debug_hvsyncblank),
+ DEFINEREG2(HSYNC_C, i830_debug_hvsyncblank),
+ DEFINEREG2(VTOTAL_C, i830_debug_hvtotal),
+ DEFINEREG2(VBLANK_C, i830_debug_hvsyncblank),
+ DEFINEREG2(VSYNC_C, i830_debug_hvsyncblank),
+ DEFINEREG(VSYNCSHIFT_C),
+ DEFINEREG2(PIPECSRC, i830_debug_yxminus1),
+
+ DEFINEREG2(PIPEC_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEC_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEC_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(PIPEC_DATA_N2, ironlake_debug_n),
+
+ DEFINEREG2(PIPEC_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(PIPEC_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(PIPEC_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(PIPEC_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(DSPCCNTR, i830_debug_dspcntr),
+ DEFINEREG(DSPCBASE),
+ DEFINEREG2(DSPCSTRIDE, ironlake_debug_dspstride),
+ DEFINEREG(DSPCSURF),
+ DEFINEREG2(DSPCTILEOFF, i830_debug_xy),
+
+ /* Panel fitter */
+
+ DEFINEREG2(PFA_CTL_1, ironlake_debug_panel_fitting),
+ DEFINEREG2(PFA_CTL_2, ironlake_debug_panel_fitting_2),
+ DEFINEREG2(PFA_CTL_3, ironlake_debug_panel_fitting_3),
+ DEFINEREG2(PFA_CTL_4, ironlake_debug_panel_fitting_4),
+ DEFINEREG2(PFA_WIN_POS, ironlake_debug_pf_win),
+ DEFINEREG2(PFA_WIN_SIZE, ironlake_debug_pf_win),
+ DEFINEREG2(PFB_CTL_1, ironlake_debug_panel_fitting),
+ DEFINEREG2(PFB_CTL_2, ironlake_debug_panel_fitting_2),
+ DEFINEREG2(PFB_CTL_3, ironlake_debug_panel_fitting_3),
+ DEFINEREG2(PFB_CTL_4, ironlake_debug_panel_fitting_4),
+ DEFINEREG2(PFB_WIN_POS, ironlake_debug_pf_win),
+ DEFINEREG2(PFB_WIN_SIZE, ironlake_debug_pf_win),
+ DEFINEREG2(PFC_CTL_1, ironlake_debug_panel_fitting),
+ DEFINEREG2(PFC_CTL_2, ironlake_debug_panel_fitting_2),
+ DEFINEREG2(PFC_CTL_3, ironlake_debug_panel_fitting_3),
+ DEFINEREG2(PFC_CTL_4, ironlake_debug_panel_fitting_4),
+ DEFINEREG2(PFC_WIN_POS, ironlake_debug_pf_win),
+ DEFINEREG2(PFC_WIN_SIZE, ironlake_debug_pf_win),
+
+ /* PCH */
+
+ DEFINEREG2(PCH_DREF_CONTROL, ironlake_debug_dref_ctl),
+ DEFINEREG2(PCH_RAWCLK_FREQ, ironlake_debug_rawclk_freq),
+ DEFINEREG(PCH_DPLL_TMR_CFG),
+ DEFINEREG(PCH_SSC4_PARMS),
+ DEFINEREG(PCH_SSC4_AUX_PARMS),
+ DEFINEREG2(PCH_DPLL_SEL, snb_debug_dpll_sel),
+ DEFINEREG(PCH_DPLL_ANALOG_CTL),
+
+ DEFINEREG2(PCH_DPLL_A, ironlake_debug_pch_dpll),
+ DEFINEREG2(PCH_DPLL_B, ironlake_debug_pch_dpll),
+ DEFINEREG2(PCH_FPA0, i830_debug_fp),
+ DEFINEREG2(PCH_FPA1, i830_debug_fp),
+ DEFINEREG2(PCH_FPB0, i830_debug_fp),
+ DEFINEREG2(PCH_FPB1, i830_debug_fp),
+
+ DEFINEREG2(TRANS_HTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_HBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_HSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VTOTAL_A, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_VBLANK_A, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VSYNC_A, i830_debug_hvsyncblank),
+ DEFINEREG(TRANS_VSYNCSHIFT_A),
+
+ DEFINEREG2(TRANSA_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSA_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSA_DATA_N2, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DP_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DP_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DP_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(TRANSA_DP_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(TRANS_HTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_HBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_HSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VTOTAL_B, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_VBLANK_B, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VSYNC_B, i830_debug_hvsyncblank),
+ DEFINEREG(TRANS_VSYNCSHIFT_B),
+
+ DEFINEREG2(TRANSB_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSB_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSB_DATA_N2, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DP_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DP_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DP_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(TRANSB_DP_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(TRANS_HTOTAL_C, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_HBLANK_C, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_HSYNC_C, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VTOTAL_C, i830_debug_hvtotal),
+ DEFINEREG2(TRANS_VBLANK_C, i830_debug_hvsyncblank),
+ DEFINEREG2(TRANS_VSYNC_C, i830_debug_hvsyncblank),
+ DEFINEREG(TRANS_VSYNCSHIFT_C),
+
+ DEFINEREG2(TRANSC_DATA_M1, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSC_DATA_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DATA_M2, ironlake_debug_m_tu),
+ DEFINEREG2(TRANSC_DATA_N2, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DP_LINK_M1, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DP_LINK_N1, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DP_LINK_M2, ironlake_debug_n),
+ DEFINEREG2(TRANSC_DP_LINK_N2, ironlake_debug_n),
+
+ DEFINEREG2(TRANSACONF, ironlake_debug_transconf),
+ DEFINEREG2(TRANSBCONF, ironlake_debug_transconf),
+ DEFINEREG2(TRANSCCONF, ironlake_debug_transconf),
+
+ DEFINEREG2(FDI_TXA_CTL, ironlake_debug_fdi_tx_ctl),
+ DEFINEREG2(FDI_TXB_CTL, ironlake_debug_fdi_tx_ctl),
+ DEFINEREG2(FDI_TXC_CTL, ironlake_debug_fdi_tx_ctl),
+ DEFINEREG2(FDI_RXA_CTL, ironlake_debug_fdi_rx_ctl),
+ DEFINEREG2(FDI_RXB_CTL, ironlake_debug_fdi_rx_ctl),
+ DEFINEREG2(FDI_RXC_CTL, ironlake_debug_fdi_rx_ctl),
+
+ DEFINEREG2(FDI_RXA_MISC, ironlake_debug_fdi_rx_misc),
+ DEFINEREG2(FDI_RXB_MISC, ironlake_debug_fdi_rx_misc),
+ DEFINEREG2(FDI_RXC_MISC, ironlake_debug_fdi_rx_misc),
+ DEFINEREG(FDI_RXA_TUSIZE1),
+ DEFINEREG(FDI_RXA_TUSIZE2),
+ DEFINEREG(FDI_RXB_TUSIZE1),
+ DEFINEREG(FDI_RXB_TUSIZE2),
+ DEFINEREG(FDI_RXC_TUSIZE1),
+ DEFINEREG(FDI_RXC_TUSIZE2),
+
+ DEFINEREG(FDI_PLL_CTL_1),
+ DEFINEREG(FDI_PLL_CTL_2),
+
+ DEFINEREG(FDI_RXA_IIR),
+ DEFINEREG(FDI_RXA_IMR),
+ DEFINEREG(FDI_RXB_IIR),
+ DEFINEREG(FDI_RXB_IMR),
+
+ DEFINEREG2(PCH_ADPA, i830_debug_adpa),
+ DEFINEREG2(HDMIB, ironlake_debug_hdmi),
+ DEFINEREG2(HDMIC, ironlake_debug_hdmi),
+ DEFINEREG2(HDMID, ironlake_debug_hdmi),
+ DEFINEREG2(PCH_LVDS, i830_debug_lvds),
+ DEFINEREG(CPU_eDP_A),
+ DEFINEREG(PCH_DP_B),
+ DEFINEREG(PCH_DP_C),
+ DEFINEREG(PCH_DP_D),
+ DEFINEREG2(TRANS_DP_CTL_A, snb_debug_trans_dp_ctl),
+ DEFINEREG2(TRANS_DP_CTL_B, snb_debug_trans_dp_ctl),
+ DEFINEREG2(TRANS_DP_CTL_C, snb_debug_trans_dp_ctl),
+
+ DEFINEREG(BLC_PWM_CPU_CTL2),
+ DEFINEREG(BLC_PWM_CPU_CTL),
+ DEFINEREG(BLC_PWM_PCH_CTL1),
+ DEFINEREG(BLC_PWM_PCH_CTL2),
+
+ DEFINEREG2(PCH_PP_STATUS, i830_debug_pp_status),
+ DEFINEREG2(PCH_PP_CONTROL, ilk_debug_pp_control),
+ DEFINEREG(PCH_PP_ON_DELAYS),
+ DEFINEREG(PCH_PP_OFF_DELAYS),
+ DEFINEREG(PCH_PP_DIVISOR),
+
+ DEFINEREG2(PORT_DBG, ivb_debug_port),
+
+ DEFINEREG(RC6_RESIDENCY_TIME),
+ DEFINEREG(RC6p_RESIDENCY_TIME),
+ DEFINEREG(RC6pp_RESIDENCY_TIME),
+};
+
+static struct reg_debug haswell_debug_regs[] = {
+ /* Power wells */
+ DEFINEREG(HSW_PWR_WELL_CTL1),
+ DEFINEREG(HSW_PWR_WELL_CTL2),
+ DEFINEREG(HSW_PWR_WELL_CTL3),
+ DEFINEREG(HSW_PWR_WELL_CTL4),
+ DEFINEREG(HSW_PWR_WELL_CTL5),
+ DEFINEREG(HSW_PWR_WELL_CTL6),
+
+ /* DDI pipe function */
+ DEFINEREG(PIPE_DDI_FUNC_CTL_A),
+ DEFINEREG(PIPE_DDI_FUNC_CTL_B),
+ DEFINEREG(PIPE_DDI_FUNC_CTL_C),
+ DEFINEREG(PIPE_DDI_FUNC_CTL_EDP),
+
+ /* DP transport control */
+ DEFINEREG(DP_TP_CTL_A),
+ DEFINEREG(DP_TP_CTL_B),
+ DEFINEREG(DP_TP_CTL_C),
+ DEFINEREG(DP_TP_CTL_D),
+ DEFINEREG(DP_TP_CTL_E),
+
+ /* DP status */
+ DEFINEREG(DP_TP_STATUS_A),
+ DEFINEREG(DP_TP_STATUS_B),
+ DEFINEREG(DP_TP_STATUS_C),
+ DEFINEREG(DP_TP_STATUS_D),
+ DEFINEREG(DP_TP_STATUS_E),
+
+ /* DDI buffer control */
+ DEFINEREG(DDI_BUF_CTL_A),
+ DEFINEREG(DDI_BUF_CTL_B),
+ DEFINEREG(DDI_BUF_CTL_C),
+ DEFINEREG(DDI_BUF_CTL_D),
+ DEFINEREG(DDI_BUF_CTL_E),
+
+ /* Clocks */
+ DEFINEREG(PIXCLK_GATE),
+ DEFINEREG(SPLL_CTL),
+ DEFINEREG(LCPLL_CTL),
+ DEFINEREG(WRPLL_CTL1),
+ DEFINEREG(WRPLL_CTL2),
+
+ /* DDI port clock control */
+ DEFINEREG(PORT_CLK_SEL_A),
+ DEFINEREG(PORT_CLK_SEL_B),
+ DEFINEREG(PORT_CLK_SEL_C),
+ DEFINEREG(PORT_CLK_SEL_D),
+ DEFINEREG(PORT_CLK_SEL_E),
+
+ /* Pipe clock control */
+ DEFINEREG(PIPE_CLK_SEL_A),
+ DEFINEREG(PIPE_CLK_SEL_B),
+ DEFINEREG(PIPE_CLK_SEL_C),
+
+ /* Pipe line time */
+ DEFINEREG(PIPE_WM_LINETIME_A),
+ DEFINEREG(PIPE_WM_LINETIME_B),
+ DEFINEREG(PIPE_WM_LINETIME_C),
+
+ /* Fuses */
+ DEFINEREG(SFUSE_STRAP),
+
+};
+
+static struct reg_debug i945gm_mi_regs[] = {
+ DEFINEREG(PGETBL_CTL),
+ DEFINEREG(PGTBL_ER),
+ DEFINEREG(EXCC),
+ DEFINEREG(HWS_PGA),
+ DEFINEREG(IPEIR),
+ DEFINEREG(IPEHR),
+ DEFINEREG(INST_DONE),
+ DEFINEREG(NOP_ID),
+ DEFINEREG(HWSTAM),
+ DEFINEREG(SCPD0),
+ DEFINEREG(IER),
+ DEFINEREG(IIR),
+ DEFINEREG(IMR),
+ DEFINEREG(ISR),
+ DEFINEREG(EIR),
+ DEFINEREG(EMR),
+ DEFINEREG(ESR),
+ DEFINEREG(INST_PM),
+ DEFINEREG(ECOSKPD),
+};
+
+#define intel_dump_regs(regs) _intel_dump_regs(regs, ARRAY_SIZE(regs))
+
+static void
+_intel_dump_regs(struct reg_debug *regs, int count)
+{
+ char debug[1024];
+ int i;
+
+ for (i = 0; i < count; i++) {
+ uint32_t val = INREG(regs[i].reg);
+
+ if (regs[i].debug_output != NULL) {
+ regs[i].debug_output(debug, sizeof(debug), regs[i].reg, val);
+ printf("%30.30s: 0x%08x (%s)\n",
+ regs[i].name,
+ (unsigned int)val, debug);
+ } else {
+ printf("%30.30s: 0x%08x\n", regs[i].name,
+ (unsigned int)val);
+ }
+ }
+}
+
+DEBUGSTRING(gen6_rp_control)
+{
+ snprintf(result, len, "%s",
+ (val & (1 << 7)) ? "enabled" : "disabled");
+}
+
+static struct reg_debug gen6_rp_debug_regs[] = {
+ DEFINEREG2(GEN6_RP_CONTROL, gen6_rp_control),
+ DEFINEREG(GEN6_RPNSWREQ),
+ DEFINEREG(GEN6_RP_DOWN_TIMEOUT),
+ DEFINEREG(GEN6_RP_INTERRUPT_LIMITS),
+ DEFINEREG(GEN6_RP_UP_THRESHOLD),
+ DEFINEREG(GEN6_RP_UP_EI),
+ DEFINEREG(GEN6_RP_DOWN_EI),
+ DEFINEREG(GEN6_RP_IDLE_HYSTERSIS),
+ DEFINEREG(GEN6_RC_STATE),
+ DEFINEREG(GEN6_RC_CONTROL),
+ DEFINEREG(GEN6_RC1_WAKE_RATE_LIMIT),
+ DEFINEREG(GEN6_RC6_WAKE_RATE_LIMIT),
+ DEFINEREG(GEN6_RC_EVALUATION_INTERVAL),
+ DEFINEREG(GEN6_RC_IDLE_HYSTERSIS),
+ DEFINEREG(GEN6_RC_SLEEP),
+ DEFINEREG(GEN6_RC1e_THRESHOLD),
+ DEFINEREG(GEN6_RC6_THRESHOLD),
+ DEFINEREG(GEN6_RC_VIDEO_FREQ),
+ DEFINEREG(GEN6_PMIER),
+ DEFINEREG(GEN6_PMIMR),
+ DEFINEREG(GEN6_PMINTRMSK),
+};
+
+static void
+intel_dump_other_regs(void)
+{
+ int i;
+ int fp, dpll;
+ int disp_pipe;
+ int n, m1, m2, m, p1, p2;
+ int ref;
+ int dot;
+ int phase;
+#if 0
+ int msr;
+ int crt;
+#endif
+
+#if 0
+ i830DumpIndexed(pScrn, "SR", 0x3c4, 0x3c5, 0, 7);
+ msr = INREG8(0x3cc);
+ printf("%20.20s: 0x%02x\n",
+ "MSR", (unsigned int)msr);
+
+ i830DumpAR(pScrn);
+ if (msr & 1)
+ crt = 0x3d0;
+ else
+ crt = 0x3b0;
+ i830DumpIndexed(pScrn, "CR", crt + 4, crt + 5, 0, 0x24);
+#endif
+ for (disp_pipe = 0; disp_pipe <= 1; disp_pipe++) {
+ fp = INREG(disp_pipe == 0 ? FPA0 : FPB0);
+ dpll = INREG(disp_pipe == 0 ? DPLL_A : DPLL_B);
+ if (IS_GEN2(devid)) {
+ uint32_t lvds = INREG(LVDS);
+ if (devid == PCI_CHIP_I855_GM &&
+ (lvds & LVDS_PORT_EN) &&
+ (lvds & LVDS_PIPEB_SELECT) == (disp_pipe << 30)) {
+ if ((lvds & LVDS_CLKB_POWER_MASK) ==
+ LVDS_CLKB_POWER_UP)
+ p2 = 7;
+ else
+ p2 = 14;
+ switch ((dpll >> 16) & 0x3f) {
+ case 0x01:
+ p1 = 1;
+ break;
+ case 0x02:
+ p1 = 2;
+ break;
+ case 0x04:
+ p1 = 3;
+ break;
+ case 0x08:
+ p1 = 4;
+ break;
+ case 0x10:
+ p1 = 5;
+ break;
+ case 0x20:
+ p1 = 6;
+ break;
+ default:
+ p1 = 1;
+ printf("LVDS P1 0x%x invalid encoding\n",
+ (dpll >> 16) & 0x3f);
+ break;
+ }
+ } else {
+ if (dpll & (1 << 23))
+ p2 = 4;
+ else
+ p2 = 2;
+ if (dpll & PLL_P1_DIVIDE_BY_TWO)
+ p1 = 2;
+ else
+ p1 = ((dpll >> 16) & 0x3f) + 2;
+ }
+
+ switch ((dpll >> 13) & 0x3) {
+ case 0:
+ ref = 48000;
+ break;
+ case 3:
+ ref = 66000;
+ break;
+ default:
+ ref = 0;
+ printf("ref out of range\n");
+ break;
+ }
+ } else {
+ uint32_t lvds = INREG(LVDS);
+ if ((lvds & LVDS_PORT_EN) &&
+ (lvds & LVDS_PIPEB_SELECT) == (disp_pipe << 30)) {
+ if ((lvds & LVDS_CLKB_POWER_MASK) ==
+ LVDS_CLKB_POWER_UP)
+ p2 = 7;
+ else
+ p2 = 14;
+ } else {
+ switch ((dpll >> 24) & 0x3) {
+ case 0:
+ p2 = 10;
+ break;
+ case 1:
+ p2 = 5;
+ break;
+ default:
+ p2 = 1;
+ printf("p2 out of range\n");
+ break;
+ }
+ }
+ if (IS_IGD(devid))
+ i = (dpll >> DPLL_FPA01_P1_POST_DIV_SHIFT_IGD) &
+ 0x1ff;
+ else
+ i = (dpll >> DPLL_FPA01_P1_POST_DIV_SHIFT) &
+ 0xff;
+ switch (i) {
+ case 1:
+ p1 = 1;
+ break;
+ case 2:
+ p1 = 2;
+ break;
+ case 4:
+ p1 = 3;
+ break;
+ case 8:
+ p1 = 4;
+ break;
+ case 16:
+ p1 = 5;
+ break;
+ case 32:
+ p1 = 6;
+ break;
+ case 64:
+ p1 = 7;
+ break;
+ case 128:
+ p1 = 8;
+ break;
+ case 256:
+ if (IS_IGD(devid)) {
+ p1 = 9;
+ break;
+ } /* fallback */
+ default:
+ p1 = 1;
+ printf("p1 out of range\n");
+ break;
+ }
+
+ switch ((dpll >> 13) & 0x3) {
+ case 0:
+ ref = 96000;
+ break;
+ case 3:
+ ref = 100000;
+ break;
+ default:
+ ref = 0;
+ printf("ref out of range\n");
+ break;
+ }
+ }
+ if (IS_965(devid)) {
+ phase = (dpll >> 9) & 0xf;
+ switch (phase) {
+ case 6:
+ break;
+ default:
+ printf("SDVO phase shift %d out of range -- probobly not "
+ "an issue.\n", phase);
+ break;
+ }
+ }
+ switch ((dpll >> 8) & 1) {
+ case 0:
+ break;
+ default:
+ printf("fp select out of range\n");
+ break;
+ }
+ m1 = ((fp >> 8) & 0x3f);
+ if (IS_IGD(devid)) {
+ n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
+ m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT;
+ m = m2 + 2;
+ dot = (ref * m) / n / (p1 * p2);
+ } else {
+ n = ((fp >> 16) & 0x3f);
+ m2 = ((fp >> 0) & 0x3f);
+ m = 5 * (m1 + 2) + (m2 + 2);
+ dot =
+ (ref * (5 * (m1 + 2) + (m2 + 2)) / (n + 2)) / (p1 *
+ p2);
+ }
+
+ printf("pipe %s dot %d n %d m1 %d m2 %d p1 %d p2 %d\n",
+ disp_pipe == 0 ? "A" : "B", dot, n, m1, m2, p1, p2);
+ }
+}
+
+static void print_usage(void)
+{
+ printf("Usage: intel_reg_dumper [options] [file]\n"
+ "Options:\n"
+ " -d id when a dump file is used, use 'id' as device id (in "
+ "hex)\n"
+ " -h prints this help\n");
+}
+
+int main(int argc, char** argv)
+{
+ struct pci_device *pci_dev;
+ int opt;
+ char *file = NULL;
+
+ while ((opt = getopt(argc, argv, "d:h")) != -1) {
+ switch (opt) {
+ case 'd':
+ devid = strtol(optarg, NULL, 16);
+ break;
+ case 'h':
+ print_usage();
+ return 0;
+ default:
+ print_usage();
+ return 1;
+ }
+ }
+ if (optind < argc)
+ file = argv[optind];
+
+ if (file) {
+ intel_map_file(file);
+ if (devid) {
+ if (IS_GEN5(devid))
+ pch = PCH_IBX;
+ else
+ pch = PCH_CPT;
+ } else {
+ printf("Dumping from file without -d argument. "
+ "Assuming Ironlake machine.\n");
+ devid = 0x0042;
+ pch = PCH_IBX;
+ }
+ } else {
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id;
+
+ intel_register_access_init(pci_dev, 1);
+
+ if (HAS_PCH_SPLIT(devid))
+ intel_check_pch();
+ }
+
+ if (HAS_PCH_SPLIT(devid)) {
+ intel_dump_regs(ironlake_debug_regs);
+ } else if (IS_945GM(devid)) {
+ intel_dump_regs(i945gm_mi_regs);
+ intel_dump_regs(intel_debug_regs);
+ intel_dump_other_regs();
+ } else {
+ intel_dump_regs(intel_debug_regs);
+ intel_dump_other_regs();
+ }
+
+ if (IS_GEN6(devid) || IS_GEN7(devid))
+ intel_dump_regs(gen6_rp_debug_regs);
+
+ if (IS_HASWELL(devid))
+ intel_dump_regs(haswell_debug_regs);
+
+
+ intel_register_access_fini();
+ return 0;
+}
diff --git a/tools/intel_reg_read.c b/tools/intel_reg_read.c
new file mode 100644
index 00000000..ae631be0
--- /dev/null
+++ b/tools/intel_reg_read.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Zhenyu Wang <zhenyuw@linux.intel.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include "intel_gpu_tools.h"
+
+static void bit_decode(uint32_t reg)
+{
+ int i;
+
+ for (i=31; i >= 0; i--)
+ printf(" %2d", i);
+ printf("\n");
+
+ for (i=31; i >= 0; i--)
+ printf(" %2d", (reg & (1 << i)) && 1);
+ printf("\n");
+}
+
+static void dump_range(uint32_t start, uint32_t end)
+{
+ int i;
+
+ for (i = start; i < end; i += 4)
+ printf("0x%X : 0x%X\n", i,
+ *(volatile uint32_t *)((volatile char*)mmio + i));
+}
+
+static void usage(char *cmdname)
+{
+ printf("Usage: %s [-f|-d] [addr1] [addr2] .. [addrN]\n", cmdname);
+ printf("\t -f : read back full range of registers.\n");
+ printf("\t WARNING! This option may result in a machine hang!\n");
+ printf("\t -d : decode register bits.\n");
+ printf("\t -c : number of dwords to dump (can't be used with -f/-d).\n");
+ printf("\t addr : in 0xXXXX format\n");
+}
+
+int main(int argc, char** argv)
+{
+ int ret = 0;
+ uint32_t reg;
+ int i, ch;
+ char *cmdname = strdup(argv[0]);
+ int full_dump = 0;
+ int decode_bits = 0;
+ int dwords = 1;
+
+ while ((ch = getopt(argc, argv, "dfhc:")) != -1) {
+ switch(ch) {
+ case 'd':
+ decode_bits = 1;
+ break;
+ case 'f':
+ full_dump = 1;
+ break;
+ case 'h':
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ case 'c':
+ dwords = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ }
+
+ if ((dwords > 1) && (argc != 1 || full_dump || decode_bits)) {
+ usage(cmdname);
+ ret = 1;
+ goto out;
+ }
+
+ intel_register_access_init(intel_get_pci_device(), 0);
+
+ if (full_dump) {
+ dump_range(0x00000, 0x00fff); /* VGA registers */
+ dump_range(0x02000, 0x02fff); /* instruction, memory, interrupt control registers */
+ dump_range(0x03000, 0x031ff); /* FENCE and PPGTT control registers */
+ dump_range(0x03200, 0x03fff); /* frame buffer compression registers */
+ dump_range(0x05000, 0x05fff); /* I/O control registers */
+ dump_range(0x06000, 0x06fff); /* clock control registers */
+ dump_range(0x07000, 0x07fff); /* 3D internal debug registers */
+ dump_range(0x07400, 0x088ff); /* GPE debug registers */
+ dump_range(0x0a000, 0x0afff); /* display palette registers */
+ dump_range(0x10000, 0x13fff); /* MMIO MCHBAR */
+ dump_range(0x30000, 0x3ffff); /* overlay registers */
+ dump_range(0x60000, 0x6ffff); /* display engine pipeline registers */
+ dump_range(0x70000, 0x72fff); /* display and cursor registers */
+ dump_range(0x73000, 0x73fff); /* performance counters */
+ } else {
+ for (i=0; i < argc; i++) {
+ sscanf(argv[i], "0x%x", &reg);
+ dump_range(reg, reg + (dwords * 4));
+
+ if (decode_bits)
+ bit_decode(*(volatile uint32_t *)((volatile char*)mmio + reg));
+ }
+ }
+
+ intel_register_access_fini();
+
+out:
+ free(cmdname);
+ return ret;
+}
+
diff --git a/tools/intel_reg_snapshot.c b/tools/intel_reg_snapshot.c
new file mode 100644
index 00000000..83e76e5c
--- /dev/null
+++ b/tools/intel_reg_snapshot.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2010 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Adam Jackson <ajax@redhat.com>
+ */
+
+#include <unistd.h>
+#include "intel_gpu_tools.h"
+
+int main(int argc, char** argv)
+{
+ struct pci_device *pci_dev;
+ uint32_t devid;
+ int mmio_bar;
+
+ pci_dev = intel_get_pci_device();
+ devid = pci_dev->device_id;
+ intel_get_mmio(pci_dev);
+
+ if (IS_GEN2(devid))
+ mmio_bar = 1;
+ else
+ mmio_bar = 0;
+
+ write(1, mmio, pci_dev->regions[mmio_bar].size);
+
+ return 0;
+}
diff --git a/tools/intel_reg_write.c b/tools/intel_reg_write.c
new file mode 100644
index 00000000..dd636f65
--- /dev/null
+++ b/tools/intel_reg_write.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Ben Gamari <bgamari.foss@gmail.com>
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include "intel_gpu_tools.h"
+
+int main(int argc, char** argv)
+{
+ uint32_t reg, value;
+ volatile uint32_t *ptr;
+
+ if (argc < 3) {
+ printf("Usage: %s addr value\n", argv[0]);
+ printf(" WARNING: This is dangerous to you and your system's health.\n");
+ printf(" Only for use in debugging.\n");
+ exit(1);
+ }
+
+ intel_register_access_init(intel_get_pci_device(), 0);
+ sscanf(argv[1], "0x%x", &reg);
+ sscanf(argv[2], "0x%x", &value);
+ ptr = (volatile uint32_t *)((volatile char *)mmio + reg);
+
+ printf("Value before: 0x%X\n", *ptr);
+ *ptr = value;
+ printf("Value after: 0x%X\n", *ptr);
+
+ intel_register_access_fini();
+ return 0;
+}
+
diff --git a/tools/intel_stepping.c b/tools/intel_stepping.c
new file mode 100644
index 00000000..f6f15d1a
--- /dev/null
+++ b/tools/intel_stepping.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <err.h>
+#include "intel_chipset.h"
+#include "intel_gpu_tools.h"
+
+static void
+print_clock(const char *name, int clock) {
+ if (clock == -1)
+ printf("%s clock: unknown", name);
+ else
+ printf("%s clock: %d Mhz", name, clock);
+}
+
+static int
+print_clock_info(struct pci_device *pci_dev)
+{
+ uint32_t devid = pci_dev->device_id;
+ uint16_t gcfgc;
+
+ if (IS_GM45(devid)) {
+ int core_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0xf) {
+ case 8:
+ core_clock = 266;
+ break;
+ case 9:
+ core_clock = 320;
+ break;
+ case 11:
+ core_clock = 400;
+ break;
+ case 13:
+ core_clock = 533;
+ break;
+ }
+ print_clock("core", core_clock);
+ } else if (IS_965(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, sampler_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0xf) {
+ case 2:
+ render_clock = 250; sampler_clock = 267;
+ break;
+ case 3:
+ render_clock = 320; sampler_clock = 333;
+ break;
+ case 4:
+ render_clock = 400; sampler_clock = 444;
+ break;
+ case 5:
+ render_clock = 500; sampler_clock = 533;
+ break;
+ }
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("sampler", sampler_clock);
+ } else if (IS_945(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, display_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0x7) {
+ case 0:
+ render_clock = 166;
+ break;
+ case 1:
+ render_clock = 200;
+ break;
+ case 3:
+ render_clock = 250;
+ break;
+ case 5:
+ render_clock = 400;
+ break;
+ }
+
+ switch (gcfgc & 0x70) {
+ case 0:
+ display_clock = 200;
+ break;
+ case 4:
+ display_clock = 320;
+ break;
+ }
+ if (gcfgc & (1 << 7))
+ display_clock = 133;
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("display", display_clock);
+ } else if (IS_915(devid) && IS_MOBILE(devid)) {
+ int render_clock = -1, display_clock = -1;
+
+ pci_device_cfg_read_u16(pci_dev, &gcfgc, I915_GCFGC);
+
+ switch (gcfgc & 0x7) {
+ case 0:
+ render_clock = 160;
+ break;
+ case 1:
+ render_clock = 190;
+ break;
+ case 4:
+ render_clock = 333;
+ break;
+ }
+ if (gcfgc & (1 << 13))
+ render_clock = 133;
+
+ switch (gcfgc & 0x70) {
+ case 0:
+ display_clock = 190;
+ break;
+ case 4:
+ display_clock = 333;
+ break;
+ }
+ if (gcfgc & (1 << 7))
+ display_clock = 133;
+
+ print_clock("render", render_clock);
+ printf(" ");
+ print_clock("display", display_clock);
+ }
+
+ printf("\n");
+ return -1;
+}
+
+int main(int argc, char **argv)
+{
+ struct pci_device *dev, *bridge;
+ int error;
+ uint8_t stepping;
+ const char *step_desc = "??";
+
+ error = pci_system_init();
+ if (error != 0) {
+ fprintf(stderr, "Couldn't initialize PCI system: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ /* Grab the graphics card */
+ dev = pci_device_find_by_slot(0, 0, 2, 0);
+ if (dev == NULL)
+ errx(1, "Couldn't find graphics card");
+
+ error = pci_device_probe(dev);
+ if (error != 0) {
+ fprintf(stderr, "Couldn't probe graphics card: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ if (dev->vendor_id != 0x8086)
+ errx(1, "Graphics card is non-intel");
+
+ bridge = pci_device_find_by_slot(0, 0, 0, 0);
+ if (dev == NULL)
+ errx(1, "Couldn't bridge");
+
+ error = pci_device_cfg_read_u8(bridge, &stepping, 8);
+ if (error != 0) {
+ fprintf(stderr, "Couldn't read revision ID: %s\n",
+ strerror(error));
+ exit(1);
+ }
+
+ switch (dev->device_id) {
+ case PCI_CHIP_I915_G:
+ if (stepping < 0x04)
+ step_desc = "<B1";
+ else if (stepping == 0x04)
+ step_desc = "B1";
+ else if (stepping == 0x0e)
+ step_desc = "C2";
+ else if (stepping > 0x0e)
+ step_desc = ">C2";
+ else
+ step_desc = ">B1 <C2";
+ break;
+ case PCI_CHIP_I915_GM:
+ if (stepping < 0x03)
+ step_desc = "<B1";
+ else if (stepping == 0x03)
+ step_desc = "B1/C0";
+ else if (stepping == 0x04)
+ step_desc = "C1/C2";
+ else
+ step_desc = ">C2";
+ break;
+ case PCI_CHIP_I945_GM:
+ if (stepping < 0x03)
+ step_desc = "<A3";
+ else if (stepping == 0x03)
+ step_desc = "A3";
+ else
+ step_desc = ">A3";
+ break;
+ case PCI_CHIP_I965_G:
+ case PCI_CHIP_I965_Q:
+ if (stepping < 0x02)
+ step_desc = "<C1";
+ else if (stepping == 0x02)
+ step_desc = "C1/C2";
+ else
+ step_desc = ">C2";
+ break;
+ case PCI_CHIP_I965_GM:
+ if (stepping < 0x03)
+ step_desc = "<C0";
+ else if (stepping == 0x03)
+ step_desc = "C0";
+ else
+ step_desc = ">C0";
+ break;
+ case PCI_CHIP_I965_G_1:
+ if (stepping < 0x03)
+ step_desc = "<E0";
+ else if (stepping == 0x03)
+ step_desc = "E0";
+ else
+ step_desc = ">E0";
+ break;
+ case PCI_CHIP_GM45_GM:
+ if (stepping < 0x07)
+ step_desc = "<B3";
+ else if (stepping == 0x03)
+ step_desc = "B3";
+ else
+ step_desc = ">B3";
+ break;
+ case PCI_CHIP_G45_G:
+ case PCI_CHIP_Q45_G:
+ case PCI_CHIP_G41_G:
+ if (stepping < 0x02)
+ step_desc = "<A2";
+ else if (stepping == 0x02)
+ step_desc = "A2";
+ else if (stepping == 0x03)
+ step_desc = "A3";
+ else
+ step_desc = ">A3";
+ break;
+ }
+
+ printf("Vendor: 0x%04x, Device: 0x%04x, Revision: 0x%02x (%s)\n",
+ dev->vendor_id,
+ dev->device_id,
+ stepping,
+ step_desc);
+
+ print_clock_info(dev);
+
+ return 0;
+}