Initial commit 2.0alpha accepted/tizen_common accepted/tizen_generic accepted/2.0alpha/20130131.230204 submit/2.0alpha/20130131.232756
authorGraydon, Tracy <tracy.graydon@intel.com>
Thu, 31 Jan 2013 23:14:28 +0000 (15:14 -0800)
committerGraydon, Tracy <tracy.graydon@intel.com>
Thu, 31 Jan 2013 23:14:28 +0000 (15:14 -0800)
199 files changed:
Android.mk [new file with mode: 0644]
COPYING [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
README [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
benchmarks/.gitignore [new file with mode: 0644]
benchmarks/Makefile.am [new file with mode: 0644]
benchmarks/intel_upload_blit_large.c [new file with mode: 0644]
benchmarks/intel_upload_blit_large_gtt.c [new file with mode: 0644]
benchmarks/intel_upload_blit_large_map.c [new file with mode: 0644]
benchmarks/intel_upload_blit_small.c [new file with mode: 0644]
configure.ac [new file with mode: 0644]
debugger/.gitignore [new file with mode: 0644]
debugger/Makefile.am [new file with mode: 0644]
debugger/debug_rdata.c [new file with mode: 0644]
debugger/eudb.c [new file with mode: 0644]
debugger/system_routine/.gitignore [new file with mode: 0644]
debugger/system_routine/Makefile.am [new file with mode: 0644]
debugger/system_routine/eviction_macro.c [new file with mode: 0644]
debugger/system_routine/pre_cpp.py [new file with mode: 0755]
debugger/system_routine/sr.g4a [new file with mode: 0644]
debugger/system_routine/test.g4a [new file with mode: 0644]
demos/.gitignore [new file with mode: 0644]
demos/Makefile.am [new file with mode: 0644]
demos/intel_sprite_on.c [new file with mode: 0644]
lib/Makefile.am [new file with mode: 0644]
lib/debug.h [new file with mode: 0644]
lib/drmtest.c [new file with mode: 0644]
lib/drmtest.h [new file with mode: 0644]
lib/gen6_render.h [new file with mode: 0644]
lib/gen7_render.h [new file with mode: 0644]
lib/i830_reg.h [new file with mode: 0644]
lib/i915_3d.h [new file with mode: 0644]
lib/i915_reg.h [new file with mode: 0644]
lib/instdone.c [new file with mode: 0644]
lib/instdone.h [new file with mode: 0644]
lib/intel_batchbuffer.c [new file with mode: 0644]
lib/intel_batchbuffer.h [new file with mode: 0644]
lib/intel_chipset.h [new file with mode: 0755]
lib/intel_dpio.c [new file with mode: 0644]
lib/intel_drm.c [new file with mode: 0644]
lib/intel_gpu_tools.h [new file with mode: 0644]
lib/intel_mmio.c [new file with mode: 0644]
lib/intel_pci.c [new file with mode: 0644]
lib/intel_reg.h [new file with mode: 0644]
lib/intel_reg_map.c [new file with mode: 0644]
lib/rendercopy.h [new file with mode: 0644]
lib/rendercopy_gen6.c [new file with mode: 0644]
lib/rendercopy_gen7.c [new file with mode: 0644]
lib/rendercopy_i830.c [new file with mode: 0644]
lib/rendercopy_i915.c [new file with mode: 0644]
man/Makefile.am [new file with mode: 0644]
man/intel_audio_dump.man [new file with mode: 0644]
man/intel_bios_dumper.man [new file with mode: 0644]
man/intel_bios_reader.man [new file with mode: 0644]
man/intel_error_decode.man [new file with mode: 0644]
man/intel_gpu_top.man [new file with mode: 0644]
man/intel_gtt.man [new file with mode: 0644]
man/intel_infoframes.man [new file with mode: 0644]
man/intel_lid.man [new file with mode: 0644]
man/intel_panel_fitter.man [new file with mode: 0644]
man/intel_reg_dumper.man [new file with mode: 0644]
man/intel_reg_read.man [new file with mode: 0644]
man/intel_reg_snapshot.man [new file with mode: 0644]
man/intel_reg_write.man [new file with mode: 0644]
man/intel_stepping.man [new file with mode: 0644]
man/intel_upload_blit_large.man [new file with mode: 0644]
man/intel_upload_blit_large_gtt.man [new file with mode: 0644]
man/intel_upload_blit_large_map.man [new file with mode: 0644]
man/intel_upload_blit_small.man [new file with mode: 0644]
packaging/intel-gpu-tools.changes [new file with mode: 0644]
packaging/intel-gpu-tools.spec [new file with mode: 0644]
scripts/Makefile.am [new file with mode: 0644]
scripts/convert_itp.py [new file with mode: 0755]
scripts/display_debug.sh [new file with mode: 0755]
scripts/throttle.py [new file with mode: 0755]
scripts/who.sh [new file with mode: 0755]
shaders/ps/README [new file with mode: 0644]
shaders/ps/blit.g7a [new file with mode: 0644]
shaders/ps/neg1_test.g7a [new file with mode: 0644]
tests/.gitignore [new file with mode: 0644]
tests/Makefile.am [new file with mode: 0644]
tests/ZZ_check_dmesg [new file with mode: 0755]
tests/ZZ_hangman [new file with mode: 0755]
tests/check_drm_clients [new file with mode: 0755]
tests/debugfs_emon_crash [new file with mode: 0755]
tests/debugfs_reader [new file with mode: 0755]
tests/debugfs_wedged [new file with mode: 0755]
tests/drm_lib.sh [new file with mode: 0755]
tests/drm_vma_limiter.c [new file with mode: 0644]
tests/drm_vma_limiter_cached.c [new file with mode: 0644]
tests/drm_vma_limiter_cpu.c [new file with mode: 0644]
tests/drm_vma_limiter_gtt.c [new file with mode: 0644]
tests/flip_test.c [new file with mode: 0644]
tests/gem_bad_address.c [new file with mode: 0644]
tests/gem_bad_batch.c [new file with mode: 0644]
tests/gem_bad_blit.c [new file with mode: 0644]
tests/gem_bad_length.c [new file with mode: 0644]
tests/gem_basic.c [new file with mode: 0644]
tests/gem_cpu_concurrent_blit.c [new file with mode: 0644]
tests/gem_cs_prefetch.c [new file with mode: 0644]
tests/gem_ctx_bad_destroy.c [new file with mode: 0644]
tests/gem_ctx_bad_exec.c [new file with mode: 0644]
tests/gem_ctx_basic.c [new file with mode: 0644]
tests/gem_ctx_create.c [new file with mode: 0644]
tests/gem_ctx_exec.c [new file with mode: 0644]
tests/gem_double_irq_loop.c [new file with mode: 0644]
tests/gem_dummy_reloc_loop.c [new file with mode: 0644]
tests/gem_exec_bad_domains.c [new file with mode: 0644]
tests/gem_exec_blt.c [new file with mode: 0644]
tests/gem_exec_faulting_reloc.c [new file with mode: 0644]
tests/gem_exec_nop.c [new file with mode: 0644]
tests/gem_fence_thrash.c [new file with mode: 0644]
tests/gem_fenced_exec_thrash.c [new file with mode: 0644]
tests/gem_flink.c [new file with mode: 0644]
tests/gem_gtt_concurrent_blit.c [new file with mode: 0644]
tests/gem_gtt_cpu_tlb.c [new file with mode: 0644]
tests/gem_gtt_speed.c [new file with mode: 0644]
tests/gem_hang.c [new file with mode: 0644]
tests/gem_hangcheck_forcewake.c [new file with mode: 0644]
tests/gem_largeobject.c [new file with mode: 0644]
tests/gem_linear_blits.c [new file with mode: 0644]
tests/gem_mmap.c [new file with mode: 0644]
tests/gem_mmap_gtt.c [new file with mode: 0644]
tests/gem_mmap_offset_exhaustion.c [new file with mode: 0644]
tests/gem_partial_pwrite_pread.c [new file with mode: 0644]
tests/gem_pipe_control_store_loop.c [new file with mode: 0644]
tests/gem_pread_after_blit.c [new file with mode: 0644]
tests/gem_pwrite.c [new file with mode: 0644]
tests/gem_readwrite.c [new file with mode: 0644]
tests/gem_reg_read.c [new file with mode: 0644]
tests/gem_reloc_vs_gpu.c [new file with mode: 0644]
tests/gem_ring_sync_loop.c [new file with mode: 0644]
tests/gem_ringfill.c [new file with mode: 0644]
tests/gem_set_tiling_vs_blt.c [new file with mode: 0644]
tests/gem_set_tiling_vs_gtt.c [new file with mode: 0644]
tests/gem_set_tiling_vs_pwrite.c [new file with mode: 0644]
tests/gem_storedw_batches_loop.c [new file with mode: 0644]
tests/gem_storedw_loop_blt.c [new file with mode: 0644]
tests/gem_storedw_loop_bsd.c [new file with mode: 0644]
tests/gem_storedw_loop_render.c [new file with mode: 0644]
tests/gem_stress.c [new file with mode: 0644]
tests/gem_tiled_blits.c [new file with mode: 0644]
tests/gem_tiled_fence_blits.c [new file with mode: 0644]
tests/gem_tiled_partial_pwrite_pread.c [new file with mode: 0644]
tests/gem_tiled_pread.c [new file with mode: 0644]
tests/gem_tiled_pread_pwrite.c [new file with mode: 0644]
tests/gem_tiled_swapping.c [new file with mode: 0644]
tests/gem_unfence_active_buffers.c [new file with mode: 0644]
tests/gem_unref_active_buffers.c [new file with mode: 0644]
tests/gem_vmap_blits.c [new file with mode: 0644]
tests/gem_wait_render_timeout.c [new file with mode: 0644]
tests/gen3_mixed_blits.c [new file with mode: 0644]
tests/gen3_render_linear_blits.c [new file with mode: 0644]
tests/gen3_render_mixed_blits.c [new file with mode: 0644]
tests/gen3_render_tiledx_blits.c [new file with mode: 0644]
tests/gen3_render_tiledy_blits.c [new file with mode: 0644]
tests/getclient.c [new file with mode: 0644]
tests/getstats.c [new file with mode: 0644]
tests/getversion.c [new file with mode: 0644]
tests/module_reload [new file with mode: 0755]
tests/pass.png [new file with mode: 0644]
tests/prime_nv_api.c [new file with mode: 0644]
tests/prime_nv_pcopy.c [new file with mode: 0644]
tests/prime_nv_test.c [new file with mode: 0644]
tests/prime_self_import.c [new file with mode: 0644]
tests/sysfs_edid_timing [new file with mode: 0755]
tests/sysfs_l3_parity [new file with mode: 0755]
tests/sysfs_rc6_residency.c [new file with mode: 0644]
tests/testdisplay.c [new file with mode: 0644]
tests/testdisplay.h [new file with mode: 0644]
tests/testdisplay_hotplug.c [new file with mode: 0644]
tools/.gitignore [new file with mode: 0644]
tools/Makefile.am [new file with mode: 0644]
tools/intel_audio_dump.c [new file with mode: 0644]
tools/intel_backlight.c [new file with mode: 0644]
tools/intel_bios.h [new file with mode: 0644]
tools/intel_bios_dumper.c [new file with mode: 0644]
tools/intel_bios_reader.c [new file with mode: 0644]
tools/intel_disable_clock_gating.c [new file with mode: 0644]
tools/intel_dpio_read.c [new file with mode: 0644]
tools/intel_dpio_write.c [new file with mode: 0644]
tools/intel_dump_decode.c [new file with mode: 0644]
tools/intel_error_decode.c [new file with mode: 0644]
tools/intel_forcewaked.c [new file with mode: 0644]
tools/intel_gpu_abrt [new file with mode: 0755]
tools/intel_gpu_time.c [new file with mode: 0644]
tools/intel_gpu_top.c [new file with mode: 0644]
tools/intel_gtt.c [new file with mode: 0644]
tools/intel_infoframes.c [new file with mode: 0644]
tools/intel_l3_parity.c [new file with mode: 0644]
tools/intel_lid.c [new file with mode: 0644]
tools/intel_panel_fitter.c [new file with mode: 0644]
tools/intel_reg_checker.c [new file with mode: 0644]
tools/intel_reg_dumper.c [new file with mode: 0644]
tools/intel_reg_read.c [new file with mode: 0644]
tools/intel_reg_snapshot.c [new file with mode: 0644]
tools/intel_reg_write.c [new file with mode: 0644]
tools/intel_stepping.c [new file with mode: 0644]

diff --git a/Android.mk b/Android.mk
new file mode 100644 (file)
index 0000000..3be3462
--- /dev/null
@@ -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 (file)
index 0000000..b8f6753
--- /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 (file)
index 0000000..5ea0fd8
--- /dev/null
@@ -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 (file)
index 0000000..92da60b
--- /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 (executable)
index 0000000..904cd67
--- /dev/null
@@ -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 (file)
index 0000000..ddea6f7
--- /dev/null
@@ -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 (file)
index 0000000..e2ad784
--- /dev/null
@@ -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 (file)
index 0000000..de0f668
--- /dev/null
@@ -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 (file)
index 0000000..dc2733e
--- /dev/null
@@ -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 (file)
index 0000000..0ca9e9d
--- /dev/null
@@ -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 (file)
index 0000000..8ad25ad
--- /dev/null
@@ -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 (file)
index 0000000..0ba7ce7
--- /dev/null
@@ -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 (file)
index 0000000..873cd27
--- /dev/null
@@ -0,0 +1,2 @@
+debug_rdata
+eudb
diff --git a/debugger/Makefile.am b/debugger/Makefile.am
new file mode 100644 (file)
index 0000000..d76e2ac
--- /dev/null
@@ -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 (file)
index 0000000..f7dc424
--- /dev/null
@@ -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 (file)
index 0000000..228a143
--- /dev/null
@@ -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 (file)
index 0000000..d19500c
--- /dev/null
@@ -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 (file)
index 0000000..2576e2a
--- /dev/null
@@ -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 (file)
index 0000000..1da2233
--- /dev/null
@@ -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 (executable)
index 0000000..effea0e
--- /dev/null
@@ -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 (file)
index 0000000..a70e771
--- /dev/null
@@ -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 (file)
index 0000000..e4296e0
--- /dev/null
@@ -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 (file)
index 0000000..cd80b0b
--- /dev/null
@@ -0,0 +1 @@
+intel_sprite_on
diff --git a/demos/Makefile.am b/demos/Makefile.am
new file mode 100644 (file)
index 0000000..49804d7
--- /dev/null
@@ -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 (file)
index 0000000..c1d0224
--- /dev/null
@@ -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 (file)
index 0000000..d8f081f
--- /dev/null
@@ -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 (file)
index 0000000..af9cf39
--- /dev/null
@@ -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 (file)
index 0000000..2101f6a
--- /dev/null
@@ -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 (file)
index 0000000..0cffa39
--- /dev/null
@@ -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 (file)
index 0000000..2c63c9e
--- /dev/null
@@ -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 (file)
index 0000000..6cd9475
--- /dev/null
@@ -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 (file)
index 0000000..93d03cf
--- /dev/null
@@ -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 (file)
index 0000000..04531f3
--- /dev/null
@@ -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 (file)
index 0000000..746a413
--- /dev/null
@@ -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 (file)
index 0000000..4679a9c
--- /dev/null
@@ -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 (file)
index 0000000..c86a54a
--- /dev/null
@@ -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 (file)
index 0000000..724e23d
--- /dev/null
@@ -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 (file)
index 0000000..ba0934c
--- /dev/null
@@ -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 (executable)
index 0000000..9dd4c94
--- /dev/null
@@ -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 (file)
index 0000000..acfd201
--- /dev/null
@@ -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 (file)
index 0000000..8d89d24
--- /dev/null
@@ -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 (file)
index 0000000..245d1de
--- /dev/null
@@ -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 (file)
index 0000000..ecb049b
--- /dev/null
@@ -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 (file)
index 0000000..7228dae
--- /dev/null
@@ -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 (file)
index 0000000..ae220b8
--- /dev/null
@@ -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 (file)
index 0000000..0c8d49c
--- /dev/null
@@ -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 (file)
index 0000000..5989d50
--- /dev/null
@@ -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 (file)
index 0000000..dafee88
--- /dev/null
@@ -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 (file)
index 0000000..56181ab
--- /dev/null
@@ -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 (file)
index 0000000..28c3e99
--- /dev/null
@@ -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 (file)
index 0000000..4b15dfe
--- /dev/null
@@ -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 (file)
index 0000000..0d04f93
--- /dev/null
@@ -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 (file)
index 0000000..89a81ec
--- /dev/null
@@ -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 (file)
index 0000000..c9acaa4
--- /dev/null
@@ -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 (file)
index 0000000..2f125fc
--- /dev/null
@@ -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 (file)
index 0000000..e53d898
--- /dev/null
@@ -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 (file)
index 0000000..b307a23
--- /dev/null
@@ -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 (file)
index 0000000..8b23f28
--- /dev/null
@@ -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 (file)
index 0000000..b015949
--- /dev/null
@@ -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 (file)
index 0000000..d06af79
--- /dev/null
@@ -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 (file)
index 0000000..9a46a2e
--- /dev/null
@@ -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 (file)
index 0000000..89f6b9f
--- /dev/null
@@ -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 (file)
index 0000000..cc2bf61
--- /dev/null
@@ -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 (file)
index 0000000..1930f61
--- /dev/null
@@ -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 (file)
index 0000000..cb1731c
--- /dev/null
@@ -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 (file)
index 0000000..fe17210
--- /dev/null
@@ -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 (file)
index 0000000..9c75e1a
--- /dev/null
@@ -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 (file)
index 0000000..fbe4623
--- /dev/null
@@ -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 (file)
index 0000000..04123f3
--- /dev/null
@@ -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 (file)
index 0000000..478bbfc
--- /dev/null
@@ -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 (file)
index 0000000..d0f8a26
--- /dev/null
@@ -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 (file)
index 0000000..596dbd3
--- /dev/null
@@ -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 (file)
index 0000000..baf3612
--- /dev/null
@@ -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 (executable)
index 0000000..4474f34
--- /dev/null
@@ -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 (executable)
index 0000000..f854f90
--- /dev/null
@@ -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 (executable)
index 0000000..126175c
--- /dev/null
@@ -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 (executable)
index 0000000..b221639
--- /dev/null
@@ -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 (file)
index 0000000..b196d02
--- /dev/null
@@ -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 (file)
index 0000000..deeedcc
--- /dev/null
@@ -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 (file)
index 0000000..744a769
--- /dev/null
@@ -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 (file)
index 0000000..1a6795b
--- /dev/null
@@ -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 (file)
index 0000000..e29a383
--- /dev/null
@@ -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 (executable)
index 0000000..e28ba35
--- /dev/null
@@ -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 (executable)
index 0000000..b8f4a68
--- /dev/null
@@ -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 (executable)
index 0000000..eb12416
--- /dev/null
@@ -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 (executable)
index 0000000..6e139a4
--- /dev/null
@@ -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 (executable)
index 0000000..80d5998
--- /dev/null
@@ -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 (executable)
index 0000000..80a32f6
--- /dev/null
@@ -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 (executable)
index 0000000..a76fd47
--- /dev/null
@@ -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 (file)
index 0000000..1971e2d
--- /dev/null
@@ -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 (file)
index 0000000..3797618
--- /dev/null
@@ -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 (file)
index 0000000..24ce188
--- /dev/null
@@ -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 (file)
index 0000000..540ea91
--- /dev/null
@@ -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 (file)
index 0000000..6710590
--- /dev/null
@@ -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 (file)
index 0000000..fbb9649
--- /dev/null
@@ -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 (file)
index 0000000..db6636a
--- /dev/null
@@ -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 (file)
index 0000000..2216527
--- /dev/null
@@ -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 (file)
index 0000000..41f44d7
--- /dev/null
@@ -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 (file)
index 0000000..24ad445
--- /dev/null
@@ -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 (file)
index 0000000..fd517d0
--- /dev/null
@@ -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 (file)
index 0000000..4fb2fc4
--- /dev/null
@@ -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 (file)
index 0000000..02d24eb
--- /dev/null
@@ -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 (file)
index 0000000..8a57fd4
--- /dev/null
@@ -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 (file)
index 0000000..632651a
--- /dev/null
@@ -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 (file)
index 0000000..def76d3
--- /dev/null
@@ -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 (file)
index 0000000..423f1ee
--- /dev/null
@@ -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 (file)
index 0000000..f2f8b1a
--- /dev/null
@@ -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 (file)
index 0000000..82d8f77
--- /dev/null
@@ -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 (file)
index 0000000..f3ee08b
--- /dev/null
@@ -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 (file)
index 0000000..eb5ae66
--- /dev/null
@@ -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 (file)
index 0000000..863a1b0
--- /dev/null
@@ -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 (file)
index 0000000..9dd055c
--- /dev/null
@@ -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 (file)
index 0000000..3d50e33
--- /dev/null
@@ -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 (file)
index 0000000..8281449
--- /dev/null
@@ -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 (file)
index 0000000..c869480
--- /dev/null
@@ -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 (file)
index 0000000..c68af7b
--- /dev/null
@@ -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 (file)
index 0000000..6853370
--- /dev/null
@@ -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 (file)
index 0000000..73a3c6d
--- /dev/null
@@ -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 (file)
index 0000000..f9db340
--- /dev/null
@@ -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 (file)
index 0000000..96a30fe
--- /dev/null
@@ -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 (file)
index 0000000..163bf10
--- /dev/null
@@ -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 (file)
index 0000000..fe15f1d
--- /dev/null
@@ -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 (file)
index 0000000..f9369f4
--- /dev/null
@@ -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 (file)
index 0000000..e7a4867
--- /dev/null
@@ -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 (file)
index 0000000..51ae599
--- /dev/null
@@ -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 (file)
index 0000000..5c8f6f5
--- /dev/null
@@ -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 (file)
index 0000000..e03cddd
--- /dev/null
@@ -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 (file)
index 0000000..c9c8b02
--- /dev/null
@@ -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 (file)
index 0000000..051ed3b
--- /dev/null
@@ -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 (file)
index 0000000..68c3ff2
--- /dev/null
@@ -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 (file)
index 0000000..1d6db1f
--- /dev/null
@@ -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 (file)
index 0000000..47681d5
--- /dev/null
@@ -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 (file)
index 0000000..b689bcd
--- /dev/null
@@ -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 (file)
index 0000000..5bae8f1
--- /dev/null
@@ -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 (file)
index 0000000..5fa90d4
--- /dev/null
@@ -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 (file)
index 0000000..1241b54
--- /dev/null
@@ -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 (file)
index 0000000..35ec5cd
--- /dev/null
@@ -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 (file)
index 0000000..8cf5f71
--- /dev/null
@@ -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 (file)
index 0000000..dda9b83
--- /dev/null
@@ -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 (file)
index 0000000..d7c6104
--- /dev/null
@@ -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 (file)
index 0000000..19a41b6
--- /dev/null
@@ -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 (file)
index 0000000..69239ac
--- /dev/null
@@ -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 (file)
index 0000000..86c9a88
--- /dev/null
@@ -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 (file)
index 0000000..dc65479
--- /dev/null
@@ -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 (file)
index 0000000..bd0d4e0
--- /dev/null
@@ -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 (file)
index 0000000..189affc
--- /dev/null
@@ -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 (file)
index 0000000..e2225c5
--- /dev/null
@@ -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 (file)
index 0000000..d1484f0
--- /dev/null
@@ -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 (file)
index 0000000..bffc62e
--- /dev/null
@@ -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 (file)
index 0000000..aa29c1d
--- /dev/null
@@ -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 (file)
index 0000000..b886821
--- /dev/null
@@ -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 (file)
index 0000000..c321d36
--- /dev/null
@@ -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 (file)
index 0000000..5bb6d86
--- /dev/null
@@ -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 (file)
index 0000000..529e23f
--- /dev/null
@@ -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 (file)
index 0000000..1353b9d
--- /dev/null
@@ -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 (file)
index 0000000..0e96e79
--- /dev/null
@@ -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 (file)
index 0000000..90fc7eb
--- /dev/null
@@ -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 (file)
index 0000000..481ce11
--- /dev/null
@@ -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 (file)
index 0000000..8a7d299
--- /dev/null
@@ -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 (file)
index 0000000..4847e79
--- /dev/null
@@ -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 (executable)
index 0000000..400fdd0
--- /dev/null
@@ -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 (file)
index 0000000..36a5236
Binary files /dev/null and b/tests/pass.png differ
diff --git a/tests/prime_nv_api.c b/tests/prime_nv_api.c
new file mode 100644 (file)
index 0000000..962e903
--- /dev/null
@@ -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 (file)
index 0000000..21dccf3
--- /dev/null
@@ -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 (file)
index 0000000..2269f84
--- /dev/null
@@ -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 (file)
index 0000000..111ed4d
--- /dev/null
@@ -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 (executable)
index 0000000..3a8c6c0
--- /dev/null
@@ -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 (executable)
index 0000000..6f814a1
--- /dev/null
@@ -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 (file)
index 0000000..2f33697
--- /dev/null
@@ -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 (file)
index 0000000..14d7da3
--- /dev/null
@@ -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 (file)
index 0000000..962e621
--- /dev/null
@@ -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 (file)
index 0000000..3f80dc7
--- /dev/null
@@ -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 (file)
index 0000000..c15e3c3
--- /dev/null
@@ -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 (file)
index 0000000..71fb087
--- /dev/null
@@ -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 (file)
index 0000000..8b9da30
--- /dev/null
@@ -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 (file)
index 0000000..bd7c813
--- /dev/null
@@ -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 (file)
index 0000000..1285020
--- /dev/null
@@ -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 (file)
index 0000000..6455689
--- /dev/null
@@ -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 (file)
index 0000000..493fb63
--- /dev/null
@@ -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 (file)
index 0000000..8dde3e1
--- /dev/null
@@ -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 (file)
index 0000000..c0c904a
--- /dev/null
@@ -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 (file)
index 0000000..f842999
--- /dev/null
@@ -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 (file)
index 0000000..a3cd2e5
--- /dev/null
@@ -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 (file)
index 0000000..e0ec8f6
--- /dev/null
@@ -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 (file)
index 0000000..3ab2d6f
--- /dev/null
@@ -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 (executable)
index 0000000..141a524
--- /dev/null
@@ -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 (file)
index 0000000..c30b84d
--- /dev/null
@@ -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 (file)
index 0000000..e561865
--- /dev/null
@@ -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 (file)
index 0000000..05d36d7
--- /dev/null
@@ -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 (file)
index 0000000..f5a4006
--- /dev/null
@@ -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 (file)
index 0000000..260c3d0
--- /dev/null
@@ -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 (file)
index 0000000..908224e
--- /dev/null
@@ -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 (file)
index 0000000..f6723d1
--- /dev/null
@@ -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 (file)
index 0000000..daa8d0f
--- /dev/null
@@ -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 (file)
index 0000000..b49d967
--- /dev/null
@@ -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 (file)
index 0000000..ae631be
--- /dev/null
@@ -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 (file)
index 0000000..83e76e5
--- /dev/null
@@ -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 (file)
index 0000000..dd636f6
--- /dev/null
@@ -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 (file)
index 0000000..f6f15d1
--- /dev/null
@@ -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;
+}