--- libdrm-2.3.0.orig/.gitignore
+++ libdrm-2.3.0/.gitignore
@@ -0,0 +1,99 @@
+*-core/linux
+*-core/drm.h
+*-core/drm_sarea.h
+*-core/i915_dma.c
+*-core/i915_drm.h
+*-core/i915_drv.h
+*-core/i915_irq.c
+*-core/i915_mem.c
+*-core/mach64_dma.c
+*-core/mach64_drm.h
+*-core/mach64_drv.h
+*-core/mach64_irq.c
+*-core/mach64_state.c
+*-core/mga_dma.c
+*-core/mga_drm.h
+*-core/mga_drv.h
+*-core/mga_irq.c
+*-core/mga_state.c
+*-core/mga_ucode.h
+*-core/mga_warp.c
+*-core/nv_drv.h
+*-core/r128_cce.c
+*-core/r128_drm.h
+*-core/r128_drv.h
+*-core/r128_irq.c
+*-core/r128_state.c
+*-core/r300_cmdbuf.c
+*-core/r300_reg.h
+*-core/radeon_cp.c
+*-core/radeon_drm.h
+*-core/radeon_drv.h
+*-core/radeon_irq.c
+*-core/radeon_mem.c
+*-core/radeon_state.c
+*-core/savage_bci.c
+*-core/savage_drm.h
+*-core/savage_drv.h
+*-core/savage_state.c
+*-core/sis_drm.h
+*-core/sis_drv.h
+*-core/tdfx_drv.h
+*-core/via_3d_reg.h
+*-core/via_dma.c
+*-core/via_drm.h
+*-core/via_drv.c
+*-core/via_drv.h
+*-core/via_irq.c
+*-core/via_map.c
+*-core/via_verifier.c
+*-core/via_verifier.h
+*-core/via_video.c
+*.flags
+*.ko
+*.ko.cmd
+*.la
+*.lo
+*.mod.c
+*.mod.o
+*.o
+*.o.cmd
+.depend
+.deps
+.libs
+.tmp_versions
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+bus_if.h
+compile
+config.guess
+config.h
+config.log
+config.status
+config.sub
+configure
+depcomp
+device_if.h
+drm.kld
+drm_pciids.h
+export_syms
+i915.kld
+install-sh
+libdrm.pc
+libtool
+ltmain.sh
+mach64.kld
+mga.kld
+missing
+mkinstalldirs
+opt_drm.h
+pci_if.h
+r128.kld
+radeon.kld
+savage.kld
+sis.kld
+stamp-h1
+tdfx.kld
+via.kld
--- libdrm-2.3.0.orig/config.sub
+++ libdrm-2.3.0/config.sub
@@ -1,9 +1,10 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
 
-timestamp='2005-07-08'
+timestamp='2006-09-20'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -119,8 +120,9 @@
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
-  kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
@@ -171,6 +173,10 @@
 	-hiux*)
 		os=-hiuxwe2
 		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
 	-sco5)
 		os=-sco3.2v5
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -187,6 +193,10 @@
 		# Don't forget version if it is 3.2v4 or newer.
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
 	-sco*)
 		os=-sco3.2v2
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -231,7 +241,7 @@
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 	| am33_2.0 \
-	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
 	| bfin \
 	| c4x | clipper \
 	| d10v | d30v | dlx | dsp16xx \
@@ -239,7 +249,8 @@
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 	| i370 | i860 | i960 | ia64 \
 	| ip2k | iq2000 \
-	| m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
@@ -257,28 +268,27 @@
 	| mipsisa64sr71k | mipsisa64sr71kel \
 	| mipstx39 | mipstx39el \
 	| mn10200 | mn10300 \
-	| ms1 \
+	| mt \
 	| msp430 \
+	| nios | nios2 \
 	| ns16k | ns32k \
 	| or32 \
 	| pdp10 | pdp11 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
 	| pyramid \
-	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
 	| sh64 | sh64le \
-	| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
-	| sparcv8 | sparcv9 | sparcv9b \
-	| strongarm \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
 	| tahoe | thumb | tic4x | tic80 | tron \
 	| v850 | v850e \
 	| we32k \
-	| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
 	| z8k)
 		basic_machine=$basic_machine-unknown
 		;;
-	m32c)
-		basic_machine=$basic_machine-unknown
-		;;
 	m6811 | m68hc11 | m6812 | m68hc12)
 		# Motorola 68HC11/12.
 		basic_machine=$basic_machine-unknown
@@ -286,6 +296,9 @@
 		;;
 	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
 		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
 
 	# We use `pc' rather than `unknown'
 	# because (1) that's what they normally are, and
@@ -305,7 +318,7 @@
 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
-	| avr-* \
+	| avr-* | avr32-* \
 	| bfin-* | bs2000-* \
 	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
 	| clipper-* | craynv-* | cydra-* \
@@ -316,7 +329,7 @@
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
 	| ip2k-* | iq2000-* \
-	| m32r-* | m32rle-* \
+	| m32c-* | m32r-* | m32rle-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
 	| m88110-* | m88k-* | maxq-* | mcore-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
@@ -336,31 +349,30 @@
 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
 	| mipstx39-* | mipstx39el-* \
 	| mmix-* \
-	| ms1-* \
+	| mt-* \
 	| msp430-* \
+	| nios-* | nios2-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
 	| pyramid-* \
 	| romp-* | rs6000-* \
-	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
-	| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
 	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
 	| tahoe-* | thumb-* \
 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
 	| tron-* \
 	| v850-* | v850e-* | vax-* \
 	| we32k-* \
-	| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
 	| xstormy16-* | xtensa-* \
 	| ymp-* \
 	| z8k-*)
 		;;
-	m32c-*)
-		;;
 	# Recognize the various machine names and aliases which stand
 	# for a CPU type and a company and sometimes even an OS.
 	386bsd)
@@ -696,6 +708,9 @@
 		basic_machine=i386-pc
 		os=-msdos
 		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
 	mvs)
 		basic_machine=i370-ibm
 		os=-mvs
@@ -803,6 +818,12 @@
 	pc532 | pc532-*)
 		basic_machine=ns32k-pc532
 		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	pentium | p5 | k5 | k6 | nexgen | viac3)
 		basic_machine=i586-pc
 		;;
@@ -859,6 +880,10 @@
 		basic_machine=i586-unknown
 		os=-pw32
 		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
 	rom68k)
 		basic_machine=m68k-rom68k
 		os=-coff
@@ -885,6 +910,10 @@
 	sb1el)
 		basic_machine=mipsisa64sb1el-unknown
 		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
 	sei)
 		basic_machine=mips-sei
 		os=-seiux
@@ -1101,7 +1130,7 @@
 	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
 		basic_machine=sh-unknown
 		;;
-	sparc | sparcv8 | sparcv9 | sparcv9b)
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
 		basic_machine=sparc-sun
 		;;
 	cydra)
@@ -1174,21 +1203,23 @@
 	      | -aos* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* \
 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku*)
+	      | -skyos* | -haiku* | -rdos* | -toppers*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1340,6 +1371,12 @@
 # system, and we'll never get to this point.
 
 case $basic_machine in
+        score-*)
+		os=-elf
+		;;
+        spu-*)
+		os=-elf
+		;;
 	*-acorn)
 		os=-riscix1.2
 		;;
@@ -1349,9 +1386,9 @@
 	arm*-semi)
 		os=-aout
 		;;
-    c4x-* | tic4x-*)
-        os=-coff
-        ;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
 	# This must come before the *-dec entry.
 	pdp10-*)
 		os=-tops20
--- libdrm-2.3.0.orig/autogen.sh
+++ libdrm-2.3.0/autogen.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
--- libdrm-2.3.0.orig/config.guess
+++ libdrm-2.3.0/config.guess
@@ -1,9 +1,10 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
 
-timestamp='2005-08-03'
+timestamp='2006-07-02'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -106,7 +107,7 @@
 trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
 trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
 : ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
  { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
  { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
  { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
@@ -206,8 +207,11 @@
     *:ekkoBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
 	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
     macppc:MirBSD:*:*)
-	echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
 	exit ;;
     *:MirBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
@@ -764,7 +768,14 @@
 	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
 	exit ;;
     *:FreeBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	case ${UNAME_MACHINE} in
+	    pc98)
+		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
 	exit ;;
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
@@ -779,8 +790,11 @@
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
 	exit ;;
-    x86:Interix*:[34]*)
-	echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+    x86:Interix*:[3456]*)
+	echo i586-pc-interix${UNAME_RELEASE}
+	exit ;;
+    EM64T:Interix*:[3456]*)
+	echo x86_64-unknown-interix${UNAME_RELEASE}
 	exit ;;
     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
 	echo i${UNAME_MACHINE}-pc-mks
@@ -817,6 +831,9 @@
     arm*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
     cris:Linux:*:*)
 	echo cris-axis-linux-gnu
 	exit ;;
@@ -851,7 +868,11 @@
 	#endif
 	#endif
 EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
 	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
 	;;
     mips64:Linux:*:*)
@@ -870,7 +891,11 @@
 	#endif
 	#endif
 EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
 	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
 	;;
     or32:Linux:*:*)
@@ -919,6 +944,9 @@
     sparc:Linux:*:* | sparc64:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
     x86_64:Linux:*:*)
 	echo x86_64-unknown-linux-gnu
 	exit ;;
@@ -964,7 +992,7 @@
 	LIBC=gnulibc1
 	# endif
 	#else
-	#ifdef __INTEL_COMPILER
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
 	LIBC=gnu
 	#else
 	LIBC=gnuaout
@@ -974,7 +1002,11 @@
 	LIBC=dietlibc
 	#endif
 EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^LIBC/{
+		s: ::g
+		p
+	    }'`"
 	test x"${LIBC}" != x && {
 		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
 		exit
@@ -1185,7 +1217,6 @@
     *:Darwin:*:*)
 	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
 	case $UNAME_PROCESSOR in
-	    *86) UNAME_PROCESSOR=i686 ;;
 	    unknown) UNAME_PROCESSOR=powerpc ;;
 	esac
 	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
@@ -1264,6 +1295,9 @@
     i*86:skyos:*:*)
 	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
 	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
--- libdrm-2.3.0.orig/shared-core/nv_drv.h
+++ libdrm-2.3.0/shared-core/nv_drv.h
@@ -0,0 +1,52 @@
+/* nv_drv.h -- NV DRM template customization -*- linux-c -*-
+ * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
+ *
+ * Copyright 2005 Lars Knoll <lars@trolltech.com>
+ * 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 AND/OR THEIR 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.
+ *
+ * Authors:
+ *    Lars Knoll <lars@trolltech.com>
+ */
+
+#ifndef __NV_H__
+#define __NV_H__
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR		"Lars Knoll"
+
+#define DRIVER_NAME		"nv"
+#define DRIVER_DESC		"NV"
+#define DRIVER_DATE		"20051006"
+
+#define DRIVER_MAJOR		0
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	1
+
+#define NV04 04
+#define NV10 10
+#define NV20 20
+#define NV30 30
+#define NV40 40
+
+#endif
--- libdrm-2.3.0.orig/shared-core/mga_drv.h
+++ libdrm-2.3.0/shared-core/mga_drv.h
@@ -0,0 +1,683 @@
+/* mga_drv.h -- Private header for the Matrox G200/G400 driver -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * VA LINUX SYSTEMS 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.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __MGA_DRV_H__
+#define __MGA_DRV_H__
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
+
+#define DRIVER_NAME		"mga"
+#define DRIVER_DESC		"Matrox G200/G400"
+#define DRIVER_DATE		"20060319"
+
+#define DRIVER_MAJOR		3
+#define DRIVER_MINOR		2
+#define DRIVER_PATCHLEVEL	2
+
+typedef struct drm_mga_primary_buffer {
+	u8 *start;
+	u8 *end;
+	int size;
+
+	u32 tail;
+	int space;
+	volatile long wrapped;
+
+	volatile u32 *status;
+
+	u32 last_flush;
+	u32 last_wrap;
+
+	u32 high_mark;
+} drm_mga_primary_buffer_t;
+
+typedef struct drm_mga_freelist {
+	struct drm_mga_freelist *next;
+	struct drm_mga_freelist *prev;
+	drm_mga_age_t age;
+	drm_buf_t *buf;
+} drm_mga_freelist_t;
+
+typedef struct {
+	drm_mga_freelist_t *list_entry;
+	int discard;
+	int dispatched;
+} drm_mga_buf_priv_t;
+
+typedef struct drm_mga_private {
+	drm_mga_primary_buffer_t prim;
+	drm_mga_sarea_t *sarea_priv;
+
+	drm_mga_freelist_t *head;
+	drm_mga_freelist_t *tail;
+
+	unsigned int warp_pipe;
+	unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES];
+
+	int chipset;
+	int usec_timeout;
+
+	/**
+	 * If set, the new DMA initialization sequence was used.  This is
+	 * primarilly used to select how the driver should uninitialized its
+	 * internal DMA structures.
+	 */
+	int used_new_dma_init;
+
+	/**
+	 * If AGP memory is used for DMA buffers, this will be the value
+	 * \c MGA_PAGPXFER.  Otherwise, it will be zero (for a PCI transfer).
+	 */
+	u32 dma_access;
+
+	/**
+	 * If AGP memory is used for DMA buffers, this will be the value
+	 * \c MGA_WAGP_ENABLE.  Otherwise, it will be zero (for a PCI
+	 * transfer).
+	 */
+	u32 wagp_enable;
+
+	/**
+	 * \name MMIO region parameters.
+	 * 
+	 * \sa drm_mga_private_t::mmio
+	 */
+	/*@{*/
+	u32 mmio_base;             /**< Bus address of base of MMIO. */
+	u32 mmio_size;             /**< Size of the MMIO region. */
+	/*@}*/
+
+	u32 clear_cmd;
+	u32 maccess;
+
+	wait_queue_head_t fence_queue;
+	atomic_t last_fence_retired;
+	u32 next_fence_to_post;
+
+	unsigned int fb_cpp;
+	unsigned int front_offset;
+	unsigned int front_pitch;
+	unsigned int back_offset;
+	unsigned int back_pitch;
+
+	unsigned int depth_cpp;
+	unsigned int depth_offset;
+	unsigned int depth_pitch;
+
+	unsigned int texture_offset;
+	unsigned int texture_size;
+
+	drm_local_map_t *sarea;
+	drm_local_map_t *mmio;
+	drm_local_map_t *status;
+	drm_local_map_t *warp;
+	drm_local_map_t *primary;
+	drm_local_map_t *agp_textures;
+	
+	unsigned long agp_handle;
+	unsigned int agp_size;
+} drm_mga_private_t;
+
+extern drm_ioctl_desc_t mga_ioctls[];
+extern int mga_max_ioctl;
+
+				/* mga_dma.c */
+extern int mga_dma_bootstrap(DRM_IOCTL_ARGS);
+extern int mga_dma_init(DRM_IOCTL_ARGS);
+extern int mga_dma_flush(DRM_IOCTL_ARGS);
+extern int mga_dma_reset(DRM_IOCTL_ARGS);
+extern int mga_dma_buffers(DRM_IOCTL_ARGS);
+extern int mga_driver_load(drm_device_t *dev, unsigned long flags);
+extern int mga_driver_unload(drm_device_t * dev);
+extern void mga_driver_lastclose(drm_device_t * dev);
+extern int mga_driver_dma_quiescent(drm_device_t * dev);
+
+extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
+
+extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
+extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
+extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
+
+extern int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf);
+
+				/* mga_warp.c */
+extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
+extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
+extern int mga_warp_init(drm_mga_private_t * dev_priv);
+
+				/* mga_irq.c */
+extern int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence);
+extern int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
+extern void mga_driver_irq_preinstall(drm_device_t * dev);
+extern void mga_driver_irq_postinstall(drm_device_t * dev);
+extern void mga_driver_irq_uninstall(drm_device_t * dev);
+extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
+			     unsigned long arg);
+
+#define mga_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
+
+#if defined(__linux__) && defined(__alpha__)
+#define MGA_BASE( reg )		((unsigned long)(dev_priv->mmio->handle))
+#define MGA_ADDR( reg )		(MGA_BASE(reg) + reg)
+
+#define MGA_DEREF( reg )	*(volatile u32 *)MGA_ADDR( reg )
+#define MGA_DEREF8( reg )	*(volatile u8 *)MGA_ADDR( reg )
+
+#define MGA_READ( reg )		(_MGA_READ((u32 *)MGA_ADDR(reg)))
+#define MGA_READ8( reg )	(_MGA_READ((u8 *)MGA_ADDR(reg)))
+#define MGA_WRITE( reg, val )	do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
+#define MGA_WRITE8( reg, val )  do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
+
+static inline u32 _MGA_READ(u32 * addr)
+{
+	DRM_MEMORYBARRIER();
+	return *(volatile u32 *)addr;
+}
+#else
+#define MGA_READ8( reg )	DRM_READ8(dev_priv->mmio, (reg))
+#define MGA_READ( reg )		DRM_READ32(dev_priv->mmio, (reg))
+#define MGA_WRITE8( reg, val )  DRM_WRITE8(dev_priv->mmio, (reg), (val))
+#define MGA_WRITE( reg, val )	DRM_WRITE32(dev_priv->mmio, (reg), (val))
+#endif
+
+#define DWGREG0 	0x1c00
+#define DWGREG0_END 	0x1dff
+#define DWGREG1		0x2c00
+#define DWGREG1_END	0x2dff
+
+#define ISREG0(r)	(r >= DWGREG0 && r <= DWGREG0_END)
+#define DMAREG0(r)	(u8)((r - DWGREG0) >> 2)
+#define DMAREG1(r)	(u8)(((r - DWGREG1) >> 2) | 0x80)
+#define DMAREG(r)	(ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
+
+/* ================================================================
+ * Helper macross...
+ */
+
+#define MGA_EMIT_STATE( dev_priv, dirty )				\
+do {									\
+	if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) {			\
+		if ( dev_priv->chipset >= MGA_CARD_TYPE_G400 ) {	\
+			mga_g400_emit_state( dev_priv );		\
+		} else {						\
+			mga_g200_emit_state( dev_priv );		\
+		}							\
+	}								\
+} while (0)
+
+#define WRAP_TEST_WITH_RETURN( dev_priv )				\
+do {									\
+	if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {			\
+		if ( mga_is_idle( dev_priv ) ) {			\
+			mga_do_dma_wrap_end( dev_priv );		\
+		} else if ( dev_priv->prim.space <			\
+			    dev_priv->prim.high_mark ) {		\
+			if ( MGA_DMA_DEBUG )				\
+				DRM_INFO( "%s: wrap...\n", __FUNCTION__ );	\
+			return DRM_ERR(EBUSY);			\
+		}							\
+	}								\
+} while (0)
+
+#define WRAP_WAIT_WITH_RETURN( dev_priv )				\
+do {									\
+	if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {			\
+		if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {		\
+			if ( MGA_DMA_DEBUG )				\
+				DRM_INFO( "%s: wrap...\n", __FUNCTION__ );	\
+			return DRM_ERR(EBUSY);			\
+		}							\
+		mga_do_dma_wrap_end( dev_priv );			\
+	}								\
+} while (0)
+
+/* ================================================================
+ * Primary DMA command stream
+ */
+
+#define MGA_VERBOSE	0
+
+#define DMA_LOCALS	unsigned int write; volatile u8 *prim;
+
+#define DMA_BLOCK_SIZE	(5 * sizeof(u32))
+
+#define BEGIN_DMA( n )							\
+do {									\
+	if ( MGA_VERBOSE ) {						\
+		DRM_INFO( "BEGIN_DMA( %d ) in %s\n",			\
+			  (n), __FUNCTION__ );				\
+		DRM_INFO( "   space=0x%x req=0x%Zx\n",			\
+			  dev_priv->prim.space, (n) * DMA_BLOCK_SIZE );	\
+	}								\
+	prim = dev_priv->prim.start;					\
+	write = dev_priv->prim.tail;					\
+} while (0)
+
+#define BEGIN_DMA_WRAP()						\
+do {									\
+	if ( MGA_VERBOSE ) {						\
+		DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ );		\
+		DRM_INFO( "   space=0x%x\n", dev_priv->prim.space );	\
+	}								\
+	prim = dev_priv->prim.start;					\
+	write = dev_priv->prim.tail;					\
+} while (0)
+
+#define ADVANCE_DMA()							\
+do {									\
+	dev_priv->prim.tail = write;					\
+	if ( MGA_VERBOSE ) {						\
+		DRM_INFO( "ADVANCE_DMA() tail=0x%05x sp=0x%x\n",	\
+			  write, dev_priv->prim.space );		\
+	}								\
+} while (0)
+
+#define FLUSH_DMA()							\
+do {									\
+	if ( 0 ) {							\
+		DRM_INFO( "%s:\n", __FUNCTION__ );				\
+		DRM_INFO( "   tail=0x%06x head=0x%06lx\n",		\
+			  dev_priv->prim.tail,				\
+			  MGA_READ( MGA_PRIMADDRESS ) -			\
+			  dev_priv->primary->offset );			\
+	}								\
+	if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) {		\
+		if ( dev_priv->prim.space <				\
+		     dev_priv->prim.high_mark ) {			\
+			mga_do_dma_wrap_start( dev_priv );		\
+		} else {						\
+			mga_do_dma_flush( dev_priv );			\
+		}							\
+	}								\
+} while (0)
+
+/* Never use this, always use DMA_BLOCK(...) for primary DMA output.
+ */
+#define DMA_WRITE( offset, val )					\
+do {									\
+	if ( MGA_VERBOSE ) {						\
+		DRM_INFO( "   DMA_WRITE( 0x%08x ) at 0x%04Zx\n",	\
+			  (u32)(val), write + (offset) * sizeof(u32) );	\
+	}								\
+	*(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val;	\
+} while (0)
+
+#define DMA_BLOCK( reg0, val0, reg1, val1, reg2, val2, reg3, val3 )	\
+do {									\
+	DMA_WRITE( 0, ((DMAREG( reg0 ) << 0) |				\
+		       (DMAREG( reg1 ) << 8) |				\
+		       (DMAREG( reg2 ) << 16) |				\
+		       (DMAREG( reg3 ) << 24)) );			\
+	DMA_WRITE( 1, val0 );						\
+	DMA_WRITE( 2, val1 );						\
+	DMA_WRITE( 3, val2 );						\
+	DMA_WRITE( 4, val3 );						\
+	write += DMA_BLOCK_SIZE;					\
+} while (0)
+
+/* Buffer aging via primary DMA stream head pointer.
+ */
+
+#define SET_AGE( age, h, w )						\
+do {									\
+	(age)->head = h;						\
+	(age)->wrap = w;						\
+} while (0)
+
+#define TEST_AGE( age, h, w )		( (age)->wrap < w ||		\
+					  ( (age)->wrap == w &&		\
+					    (age)->head < h ) )
+
+#define AGE_BUFFER( buf_priv )						\
+do {									\
+	drm_mga_freelist_t *entry = (buf_priv)->list_entry;		\
+	if ( (buf_priv)->dispatched ) {					\
+		entry->age.head = (dev_priv->prim.tail +		\
+				   dev_priv->primary->offset);		\
+		entry->age.wrap = dev_priv->sarea_priv->last_wrap;	\
+	} else {							\
+		entry->age.head = 0;					\
+		entry->age.wrap = 0;					\
+	}								\
+} while (0)
+
+#define MGA_ENGINE_IDLE_MASK		(MGA_SOFTRAPEN |		\
+					 MGA_DWGENGSTS |		\
+					 MGA_ENDPRDMASTS)
+#define MGA_DMA_IDLE_MASK		(MGA_SOFTRAPEN |		\
+					 MGA_ENDPRDMASTS)
+
+#define MGA_DMA_DEBUG			0
+
+/* A reduced set of the mga registers.
+ */
+#define MGA_CRTC_INDEX			0x1fd4
+#define MGA_CRTC_DATA			0x1fd5
+
+/* CRTC11 */
+#define MGA_VINTCLR			(1 << 4)
+#define MGA_VINTEN			(1 << 5)
+
+#define MGA_ALPHACTRL 			0x2c7c
+#define MGA_AR0 			0x1c60
+#define MGA_AR1 			0x1c64
+#define MGA_AR2 			0x1c68
+#define MGA_AR3 			0x1c6c
+#define MGA_AR4 			0x1c70
+#define MGA_AR5 			0x1c74
+#define MGA_AR6 			0x1c78
+
+#define MGA_CXBNDRY			0x1c80
+#define MGA_CXLEFT 			0x1ca0
+#define MGA_CXRIGHT			0x1ca4
+
+#define MGA_DMAPAD 			0x1c54
+#define MGA_DSTORG 			0x2cb8
+#define MGA_DWGCTL 			0x1c00
+#	define MGA_OPCOD_MASK			(15 << 0)
+#	define MGA_OPCOD_TRAP			(4 << 0)
+#	define MGA_OPCOD_TEXTURE_TRAP		(6 << 0)
+#	define MGA_OPCOD_BITBLT			(8 << 0)
+#	define MGA_OPCOD_ILOAD			(9 << 0)
+#	define MGA_ATYPE_MASK			(7 << 4)
+#	define MGA_ATYPE_RPL			(0 << 4)
+#	define MGA_ATYPE_RSTR			(1 << 4)
+#	define MGA_ATYPE_ZI			(3 << 4)
+#	define MGA_ATYPE_BLK			(4 << 4)
+#	define MGA_ATYPE_I			(7 << 4)
+#	define MGA_LINEAR			(1 << 7)
+#	define MGA_ZMODE_MASK			(7 << 8)
+#	define MGA_ZMODE_NOZCMP			(0 << 8)
+#	define MGA_ZMODE_ZE			(2 << 8)
+#	define MGA_ZMODE_ZNE			(3 << 8)
+#	define MGA_ZMODE_ZLT			(4 << 8)
+#	define MGA_ZMODE_ZLTE			(5 << 8)
+#	define MGA_ZMODE_ZGT			(6 << 8)
+#	define MGA_ZMODE_ZGTE			(7 << 8)
+#	define MGA_SOLID			(1 << 11)
+#	define MGA_ARZERO			(1 << 12)
+#	define MGA_SGNZERO			(1 << 13)
+#	define MGA_SHIFTZERO			(1 << 14)
+#	define MGA_BOP_MASK			(15 << 16)
+#	define MGA_BOP_ZERO			(0 << 16)
+#	define MGA_BOP_DST			(10 << 16)
+#	define MGA_BOP_SRC			(12 << 16)
+#	define MGA_BOP_ONE			(15 << 16)
+#	define MGA_TRANS_SHIFT			20
+#	define MGA_TRANS_MASK			(15 << 20)
+#	define MGA_BLTMOD_MASK			(15 << 25)
+#	define MGA_BLTMOD_BMONOLEF		(0 << 25)
+#	define MGA_BLTMOD_BMONOWF		(4 << 25)
+#	define MGA_BLTMOD_PLAN			(1 << 25)
+#	define MGA_BLTMOD_BFCOL			(2 << 25)
+#	define MGA_BLTMOD_BU32BGR		(3 << 25)
+#	define MGA_BLTMOD_BU32RGB		(7 << 25)
+#	define MGA_BLTMOD_BU24BGR		(11 << 25)
+#	define MGA_BLTMOD_BU24RGB		(15 << 25)
+#	define MGA_PATTERN			(1 << 29)
+#	define MGA_TRANSC			(1 << 30)
+#	define MGA_CLIPDIS			(1 << 31)
+#define MGA_DWGSYNC			0x2c4c
+
+#define MGA_FCOL 			0x1c24
+#define MGA_FIFOSTATUS 			0x1e10
+#define MGA_FOGCOL 			0x1cf4
+#define MGA_FXBNDRY			0x1c84
+#define MGA_FXLEFT 			0x1ca8
+#define MGA_FXRIGHT			0x1cac
+
+#define MGA_ICLEAR 			0x1e18
+#	define MGA_SOFTRAPICLR			(1 << 0)
+#	define MGA_VLINEICLR			(1 << 5)
+#define MGA_IEN 			0x1e1c
+#	define MGA_SOFTRAPIEN			(1 << 0)
+#	define MGA_VLINEIEN			(1 << 5)
+
+#define MGA_LEN 			0x1c5c
+
+#define MGA_MACCESS			0x1c04
+
+#define MGA_PITCH 			0x1c8c
+#define MGA_PLNWT 			0x1c1c
+#define MGA_PRIMADDRESS 		0x1e58
+#	define MGA_DMA_GENERAL			(0 << 0)
+#	define MGA_DMA_BLIT			(1 << 0)
+#	define MGA_DMA_VECTOR			(2 << 0)
+#	define MGA_DMA_VERTEX			(3 << 0)
+#define MGA_PRIMEND			0x1e5c
+#	define MGA_PRIMNOSTART			(1 << 0)
+#	define MGA_PAGPXFER			(1 << 1)
+#define MGA_PRIMPTR			0x1e50
+#	define MGA_PRIMPTREN0			(1 << 0)
+#	define MGA_PRIMPTREN1			(1 << 1)
+
+#define MGA_RST 			0x1e40
+#	define MGA_SOFTRESET			(1 << 0)
+#	define MGA_SOFTEXTRST			(1 << 1)
+
+#define MGA_SECADDRESS 			0x2c40
+#define MGA_SECEND 			0x2c44
+#define MGA_SETUPADDRESS 		0x2cd0
+#define MGA_SETUPEND 			0x2cd4
+#define MGA_SGN				0x1c58
+#define MGA_SOFTRAP			0x2c48
+#define MGA_SRCORG 			0x2cb4
+#	define MGA_SRMMAP_MASK			(1 << 0)
+#	define MGA_SRCMAP_FB			(0 << 0)
+#	define MGA_SRCMAP_SYSMEM		(1 << 0)
+#	define MGA_SRCACC_MASK			(1 << 1)
+#	define MGA_SRCACC_PCI			(0 << 1)
+#	define MGA_SRCACC_AGP			(1 << 1)
+#define MGA_STATUS 			0x1e14
+#	define MGA_SOFTRAPEN			(1 << 0)
+#	define MGA_VSYNCPEN			(1 << 4)
+#	define MGA_VLINEPEN			(1 << 5)
+#	define MGA_DWGENGSTS			(1 << 16)
+#	define MGA_ENDPRDMASTS			(1 << 17)
+#define MGA_STENCIL			0x2cc8
+#define MGA_STENCILCTL 			0x2ccc
+
+#define MGA_TDUALSTAGE0 		0x2cf8
+#define MGA_TDUALSTAGE1 		0x2cfc
+#define MGA_TEXBORDERCOL 		0x2c5c
+#define MGA_TEXCTL 			0x2c30
+#define MGA_TEXCTL2			0x2c3c
+#	define MGA_DUALTEX			(1 << 7)
+#	define MGA_G400_TC2_MAGIC		(1 << 15)
+#	define MGA_MAP1_ENABLE			(1 << 31)
+#define MGA_TEXFILTER 			0x2c58
+#define MGA_TEXHEIGHT 			0x2c2c
+#define MGA_TEXORG 			0x2c24
+#	define MGA_TEXORGMAP_MASK		(1 << 0)
+#	define MGA_TEXORGMAP_FB			(0 << 0)
+#	define MGA_TEXORGMAP_SYSMEM		(1 << 0)
+#	define MGA_TEXORGACC_MASK		(1 << 1)
+#	define MGA_TEXORGACC_PCI		(0 << 1)
+#	define MGA_TEXORGACC_AGP		(1 << 1)
+#define MGA_TEXORG1			0x2ca4
+#define MGA_TEXORG2			0x2ca8
+#define MGA_TEXORG3			0x2cac
+#define MGA_TEXORG4			0x2cb0
+#define MGA_TEXTRANS 			0x2c34
+#define MGA_TEXTRANSHIGH 		0x2c38
+#define MGA_TEXWIDTH 			0x2c28
+
+#define MGA_WACCEPTSEQ 			0x1dd4
+#define MGA_WCODEADDR 			0x1e6c
+#define MGA_WFLAG 			0x1dc4
+#define MGA_WFLAG1 			0x1de0
+#define MGA_WFLAGNB			0x1e64
+#define MGA_WFLAGNB1 			0x1e08
+#define MGA_WGETMSB			0x1dc8
+#define MGA_WIADDR 			0x1dc0
+#define MGA_WIADDR2			0x1dd8
+#	define MGA_WMODE_SUSPEND		(0 << 0)
+#	define MGA_WMODE_RESUME			(1 << 0)
+#	define MGA_WMODE_JUMP			(2 << 0)
+#	define MGA_WMODE_START			(3 << 0)
+#	define MGA_WAGP_ENABLE			(1 << 2)
+#define MGA_WMISC 			0x1e70
+#	define MGA_WUCODECACHE_ENABLE		(1 << 0)
+#	define MGA_WMASTER_ENABLE		(1 << 1)
+#	define MGA_WCACHEFLUSH_ENABLE		(1 << 3)
+#define MGA_WVRTXSZ			0x1dcc
+
+#define MGA_YBOT 			0x1c9c
+#define MGA_YDST 			0x1c90
+#define MGA_YDSTLEN			0x1c88
+#define MGA_YDSTORG			0x1c94
+#define MGA_YTOP 			0x1c98
+
+#define MGA_ZORG 			0x1c0c
+
+/* This finishes the current batch of commands
+ */
+#define MGA_EXEC 			0x0100
+
+/* AGP PLL encoding (for G200 only).
+ */
+#define MGA_AGP_PLL 			0x1e4c
+#	define MGA_AGP2XPLL_DISABLE		(0 << 0)
+#	define MGA_AGP2XPLL_ENABLE		(1 << 0)
+
+/* Warp registers
+ */
+#define MGA_WR0				0x2d00
+#define MGA_WR1				0x2d04
+#define MGA_WR2				0x2d08
+#define MGA_WR3				0x2d0c
+#define MGA_WR4				0x2d10
+#define MGA_WR5				0x2d14
+#define MGA_WR6				0x2d18
+#define MGA_WR7				0x2d1c
+#define MGA_WR8				0x2d20
+#define MGA_WR9				0x2d24
+#define MGA_WR10			0x2d28
+#define MGA_WR11			0x2d2c
+#define MGA_WR12			0x2d30
+#define MGA_WR13			0x2d34
+#define MGA_WR14			0x2d38
+#define MGA_WR15			0x2d3c
+#define MGA_WR16			0x2d40
+#define MGA_WR17			0x2d44
+#define MGA_WR18			0x2d48
+#define MGA_WR19			0x2d4c
+#define MGA_WR20			0x2d50
+#define MGA_WR21			0x2d54
+#define MGA_WR22			0x2d58
+#define MGA_WR23			0x2d5c
+#define MGA_WR24			0x2d60
+#define MGA_WR25			0x2d64
+#define MGA_WR26			0x2d68
+#define MGA_WR27			0x2d6c
+#define MGA_WR28			0x2d70
+#define MGA_WR29			0x2d74
+#define MGA_WR30			0x2d78
+#define MGA_WR31			0x2d7c
+#define MGA_WR32			0x2d80
+#define MGA_WR33			0x2d84
+#define MGA_WR34			0x2d88
+#define MGA_WR35			0x2d8c
+#define MGA_WR36			0x2d90
+#define MGA_WR37			0x2d94
+#define MGA_WR38			0x2d98
+#define MGA_WR39			0x2d9c
+#define MGA_WR40			0x2da0
+#define MGA_WR41			0x2da4
+#define MGA_WR42			0x2da8
+#define MGA_WR43			0x2dac
+#define MGA_WR44			0x2db0
+#define MGA_WR45			0x2db4
+#define MGA_WR46			0x2db8
+#define MGA_WR47			0x2dbc
+#define MGA_WR48			0x2dc0
+#define MGA_WR49			0x2dc4
+#define MGA_WR50			0x2dc8
+#define MGA_WR51			0x2dcc
+#define MGA_WR52			0x2dd0
+#define MGA_WR53			0x2dd4
+#define MGA_WR54			0x2dd8
+#define MGA_WR55			0x2ddc
+#define MGA_WR56			0x2de0
+#define MGA_WR57			0x2de4
+#define MGA_WR58			0x2de8
+#define MGA_WR59			0x2dec
+#define MGA_WR60			0x2df0
+#define MGA_WR61			0x2df4
+#define MGA_WR62			0x2df8
+#define MGA_WR63			0x2dfc
+#	define MGA_G400_WR_MAGIC		(1 << 6)
+#	define MGA_G400_WR56_MAGIC		0x46480000	/* 12800.0f */
+
+#define MGA_ILOAD_ALIGN		64
+#define MGA_ILOAD_MASK		(MGA_ILOAD_ALIGN - 1)
+
+#define MGA_DWGCTL_FLUSH	(MGA_OPCOD_TEXTURE_TRAP |		\
+				 MGA_ATYPE_I |				\
+				 MGA_ZMODE_NOZCMP |			\
+				 MGA_ARZERO |				\
+				 MGA_SGNZERO |				\
+				 MGA_BOP_SRC |				\
+				 (15 << MGA_TRANS_SHIFT))
+
+#define MGA_DWGCTL_CLEAR	(MGA_OPCOD_TRAP |			\
+				 MGA_ZMODE_NOZCMP |			\
+				 MGA_SOLID |				\
+				 MGA_ARZERO |				\
+				 MGA_SGNZERO |				\
+				 MGA_SHIFTZERO |			\
+				 MGA_BOP_SRC |				\
+				 (0 << MGA_TRANS_SHIFT) |		\
+				 MGA_BLTMOD_BMONOLEF |			\
+				 MGA_TRANSC |				\
+				 MGA_CLIPDIS)
+
+#define MGA_DWGCTL_COPY		(MGA_OPCOD_BITBLT |			\
+				 MGA_ATYPE_RPL |			\
+				 MGA_SGNZERO |				\
+				 MGA_SHIFTZERO |			\
+				 MGA_BOP_SRC |				\
+				 (0 << MGA_TRANS_SHIFT) |		\
+				 MGA_BLTMOD_BFCOL |			\
+				 MGA_CLIPDIS)
+
+/* Simple idle test.
+ */
+static __inline__ int mga_is_idle(drm_mga_private_t * dev_priv)
+{
+	u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
+	return (status == MGA_ENDPRDMASTS);
+}
+
+#endif
--- libdrm-2.3.0.orig/shared-core/via_map.c
+++ libdrm-2.3.0/shared-core/via_map.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 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 "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
+{
+	drm_via_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	DRM_GETSAREA();
+	if (!dev_priv->sarea) {
+		DRM_ERROR("could not find sarea!\n");
+		dev->dev_private = (void *)dev_priv;
+		via_do_cleanup_map(dev);
+		return -EINVAL;
+	}
+
+	dev_priv->fb = drm_core_findmap(dev, init->fb_offset);
+	if (!dev_priv->fb) {
+		DRM_ERROR("could not find framebuffer!\n");
+		dev->dev_private = (void *)dev_priv;
+		via_do_cleanup_map(dev);
+		return -EINVAL;
+	}
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+	if (!dev_priv->mmio) {
+		DRM_ERROR("could not find mmio region!\n");
+		dev->dev_private = (void *)dev_priv;
+		via_do_cleanup_map(dev);
+		return -EINVAL;
+	}
+
+	dev_priv->sarea_priv =
+	    (drm_via_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+				 init->sarea_priv_offset);
+
+	dev_priv->agpAddr = init->agpAddr;
+
+	via_init_futex( dev_priv );
+#ifdef VIA_HAVE_DMABLIT
+	via_init_dmablit( dev );
+#endif
+	dev->dev_private = (void *)dev_priv;
+	return 0;
+}
+
+int via_do_cleanup_map(drm_device_t * dev)
+{
+	via_dma_cleanup(dev);
+
+	return 0;
+}
+
+
+int via_map_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_via_init_t init;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t __user *) data,
+				 sizeof(init));
+
+	switch (init.func) {
+	case VIA_INIT_MAP:
+		return via_do_init_map(dev, &init);
+	case VIA_CLEANUP_MAP:
+		return via_do_cleanup_map(dev);
+	}
+
+	return -EINVAL;
+}
+
+int via_driver_load(drm_device_t *dev, unsigned long chipset)
+{
+	drm_via_private_t *dev_priv;
+	int ret = 0;
+
+	dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+	if (dev_priv == NULL)
+		return DRM_ERR(ENOMEM);
+
+	dev->dev_private = (void *)dev_priv;
+
+	if (chipset == VIA_PRO_GROUP_A)
+		dev_priv->pro_group_a = 1;
+
+#ifdef VIA_HAVE_CORE_MM
+	ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
+	if (ret) {
+		drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+	}
+#endif
+	return ret;
+}
+
+int via_driver_unload(drm_device_t *dev)
+{
+	drm_via_private_t *dev_priv = dev->dev_private;
+
+#ifdef VIA_HAVE_CORE_MM
+	drm_sman_takedown(&dev_priv->sman);
+#endif
+	drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+
+	return 0;
+}
+
--- libdrm-2.3.0.orig/shared-core/via_ds.h
+++ libdrm-2.3.0/shared-core/via_ds.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * 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
+ * VIA, S3 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 _via_ds_h_
+#define _via_ds_h_
+
+#include "drmP.h"
+
+/* Set Data Structure */
+#define SET_SIZE 5000
+typedef unsigned long ITEM_TYPE;
+
+typedef struct {
+	ITEM_TYPE val;
+	int alloc_next, free_next;
+} list_item_t;
+
+typedef struct {
+	int alloc;
+	int free;
+	int trace;
+	list_item_t list[SET_SIZE];
+} set_t;
+
+set_t *via_setInit(void);
+int via_setAdd(set_t * set, ITEM_TYPE item);
+int via_setDel(set_t * set, ITEM_TYPE item);
+int via_setFirst(set_t * set, ITEM_TYPE * item);
+int via_setNext(set_t * set, ITEM_TYPE * item);
+int via_setDestroy(set_t * set);
+
+#endif
+
+#ifndef MM_INC
+#define MM_INC
+
+struct mem_block_t {
+	struct mem_block_t *next;
+	struct mem_block_t *heap;
+	int ofs, size;
+	int align;
+	unsigned int free:1;
+	unsigned int reserved:1;
+};
+typedef struct mem_block_t TMemBlock;
+typedef struct mem_block_t *PMemBlock;
+
+/* a heap is just the first block in a chain */
+typedef struct mem_block_t memHeap_t;
+
+static __inline__ int mmBlockSize(PMemBlock b)
+{
+	return b->size;
+}
+
+static __inline__ int mmOffset(PMemBlock b)
+{
+	return b->ofs;
+}
+
+static __inline__ void mmMarkReserved(PMemBlock b)
+{
+	b->reserved = 1;
+}
+
+/*
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+memHeap_t *via_mmInit(int ofs, int size);
+
+PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
+			 int startSearch);
+
+/*
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+int via_mmFreeMem(PMemBlock b);
+
+#endif
--- libdrm-2.3.0.orig/shared-core/i915_drv.h
+++ libdrm-2.3.0/shared-core/i915_drv.h
@@ -0,0 +1,342 @@
+/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
+ */
+/*
+ * 
+ * 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_DRV_H_
+#define _I915_DRV_H_
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR		"Tungsten Graphics, Inc."
+
+#define DRIVER_NAME		"i915-mm"
+#define DRIVER_DESC		"Intel Graphics"
+#define DRIVER_DATE		"20060929"
+
+/* Interface history:
+ *
+ * 1.1: Original.
+ * 1.2: Add Power Management
+ * 1.3: Add vblank support
+ * 1.4: Fix cmdbuffer path, add heap destroy
+ * 1.5: Add vblank pipe configuration
+ * 1.6: - New ioctl for scheduling buffer swaps on vertical blank
+ *      - Support vertical blank on secondary display pipe
+ */
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		7
+#define DRIVER_PATCHLEVEL	0
+
+#if defined(__linux__)
+#define I915_HAVE_FENCE
+#define I915_HAVE_BUFFER
+#endif
+
+typedef struct _drm_i915_ring_buffer {
+	int tail_mask;
+	unsigned long Start;
+	unsigned long End;
+	unsigned long Size;
+	u8 *virtual_start;
+	int head;
+	int tail;
+	int space;
+	drm_local_map_t map;
+} drm_i915_ring_buffer_t;
+
+struct mem_block {
+	struct mem_block *next;
+	struct mem_block *prev;
+	int start;
+	int size;
+	DRMFILE filp;		/* 0: free, -1: heap, other: real files */
+};
+
+typedef struct _drm_i915_vbl_swap {
+	struct list_head head;
+	drm_drawable_t drw_id;
+	unsigned int pipe;
+	unsigned int sequence;
+} drm_i915_vbl_swap_t;
+
+typedef struct drm_i915_private {
+	drm_local_map_t *sarea;
+	drm_local_map_t *mmio_map;
+
+	drm_i915_sarea_t *sarea_priv;
+	drm_i915_ring_buffer_t ring;
+
+	drm_dma_handle_t *status_page_dmah;
+	void *hw_status_page;
+	dma_addr_t dma_status_page;
+	uint32_t counter;
+
+	unsigned int cpp;
+	int back_offset;
+	int front_offset;
+	int current_page;
+	int page_flipping;
+	int use_mi_batchbuffer_start;
+
+	wait_queue_head_t irq_queue;
+	atomic_t irq_received;
+	atomic_t irq_emitted;
+
+	int tex_lru_log_granularity;
+	int allow_batchbuffer;
+	struct mem_block *agp_heap;
+	unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
+	int vblank_pipe;
+        spinlock_t user_irq_lock;
+        int user_irq_refcount;
+        int fence_irq_on;
+        uint32_t irq_enable_reg;
+        int irq_enabled;
+
+#ifdef I915_HAVE_FENCE
+        uint32_t flush_sequence;
+	uint32_t flush_flags;
+	uint32_t flush_pending;
+	uint32_t saved_flush_status;
+#endif
+
+	spinlock_t swaps_lock;
+	drm_i915_vbl_swap_t vbl_swaps;
+	unsigned int swaps_pending;
+} drm_i915_private_t;
+
+extern drm_ioctl_desc_t i915_ioctls[];
+extern int i915_max_ioctl;
+
+				/* i915_dma.c */
+extern void i915_kernel_lost_context(drm_device_t * dev);
+extern int i915_driver_load(struct drm_device *, unsigned long flags);
+extern void i915_driver_lastclose(drm_device_t * dev);
+extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern int i915_driver_device_is_agp(drm_device_t * dev);
+extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+			      unsigned long arg);
+extern int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush);
+
+
+/* i915_irq.c */
+extern int i915_irq_emit(DRM_IOCTL_ARGS);
+extern int i915_irq_wait(DRM_IOCTL_ARGS);
+
+extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
+extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
+extern void i915_driver_irq_preinstall(drm_device_t * dev);
+extern void i915_driver_irq_postinstall(drm_device_t * dev);
+extern void i915_driver_irq_uninstall(drm_device_t * dev);
+extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
+extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
+extern int i915_emit_irq(drm_device_t * dev);
+extern void i915_user_irq_on(drm_i915_private_t *dev_priv);
+extern void i915_user_irq_off(drm_i915_private_t *dev_priv);
+extern int i915_vblank_swap(DRM_IOCTL_ARGS);
+
+/* i915_mem.c */
+extern int i915_mem_alloc(DRM_IOCTL_ARGS);
+extern int i915_mem_free(DRM_IOCTL_ARGS);
+extern int i915_mem_init_heap(DRM_IOCTL_ARGS);
+extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS);
+extern void i915_mem_takedown(struct mem_block **heap);
+extern void i915_mem_release(drm_device_t * dev,
+			     DRMFILE filp, struct mem_block *heap);
+#ifdef I915_HAVE_FENCE
+/* i915_fence.c */
+
+
+extern void i915_fence_handler(drm_device_t *dev);
+extern int i915_fence_emit_sequence(drm_device_t *dev, uint32_t flags,
+				    uint32_t *sequence, 
+				    uint32_t *native_type);
+extern void i915_poke_flush(drm_device_t *dev);
+#endif
+
+#ifdef I915_HAVE_BUFFER
+/* i915_buffer.c */
+extern drm_ttm_backend_t *i915_create_ttm_backend_entry(drm_device_t *dev);
+extern int i915_fence_types(uint32_t buffer_flags, uint32_t *class, uint32_t *type);
+extern int i915_invalidate_caches(drm_device_t *dev, uint32_t buffer_flags);
+#endif
+
+#define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
+#define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
+#define I915_READ16(reg) 	DRM_READ16(dev_priv->mmio_map, (reg))
+#define I915_WRITE16(reg,val)	DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
+
+#define I915_VERBOSE 0
+
+#define RING_LOCALS	unsigned int outring, ringmask, outcount; \
+			volatile char *virt;
+
+#define BEGIN_LP_RING(n) do {				\
+	if (I915_VERBOSE)				\
+		DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n",	\
+	                         (n), __FUNCTION__);           \
+	if (dev_priv->ring.space < (n)*4)                      \
+		i915_wait_ring(dev, (n)*4, __FUNCTION__);      \
+	outcount = 0;					\
+	outring = dev_priv->ring.tail;			\
+	ringmask = dev_priv->ring.tail_mask;		\
+	virt = dev_priv->ring.virtual_start;		\
+} while (0)
+
+#define OUT_RING(n) do {					\
+	if (I915_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));	\
+	*(volatile unsigned int *)(virt + outring) = (n);		\
+	outcount++;						\
+	outring += 4;						\
+	outring &= ringmask;					\
+} while (0)
+
+#define ADVANCE_LP_RING() do {						\
+	if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring);	\
+	dev_priv->ring.tail = outring;					\
+	dev_priv->ring.space -= outcount * 4;				\
+	I915_WRITE(LP_RING + RING_TAIL, outring);			\
+} while(0)
+
+extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
+
+#define GFX_OP_USER_INTERRUPT 		((0<<29)|(2<<23))
+#define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
+#define CMD_REPORT_HEAD			(7<<23)
+#define CMD_STORE_DWORD_IDX		((0x21<<23) | 0x1)
+#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
+
+#define INST_PARSER_CLIENT   0x00000000
+#define INST_OP_FLUSH        0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+#define CMD_MI_FLUSH         (0x04 << 23)
+#define MI_NO_WRITE_FLUSH    (1 << 2)
+#define MI_READ_FLUSH        (1 << 0)
+#define MI_EXE_FLUSH         (1 << 1)
+
+#define BB1_START_ADDR_MASK   (~0x7)
+#define BB1_PROTECTED         (1<<0)
+#define BB1_UNPROTECTED       (0<<0)
+#define BB2_END_ADDR_MASK     (~0x7)
+
+#define I915REG_HWSTAM		0x02098
+#define I915REG_INT_IDENTITY_R	0x020a4
+#define I915REG_INT_MASK_R 	0x020a8
+#define I915REG_INT_ENABLE_R	0x020a0
+#define I915REG_INSTPM	        0x020c0
+
+#define SRX_INDEX		0x3c4
+#define SRX_DATA		0x3c5
+#define SR01			1
+#define SR01_SCREEN_OFF 	(1<<5)
+
+#define PPCR			0x61204
+#define PPCR_ON			(1<<0)
+
+#define DVOB			0x61140
+#define DVOB_ON			(1<<31)
+#define DVOC			0x61160
+#define DVOC_ON			(1<<31)
+#define LVDS			0x61180
+#define LVDS_ON			(1<<31)
+
+#define ADPA			0x61100
+#define ADPA_DPMS_MASK		(~(3<<10))
+#define ADPA_DPMS_ON		(0<<10)
+#define ADPA_DPMS_SUSPEND	(1<<10)
+#define ADPA_DPMS_STANDBY	(2<<10)
+#define ADPA_DPMS_OFF		(3<<10)
+
+#define NOPID                   0x2094
+#define LP_RING     		0x2030
+#define HP_RING     		0x2040
+#define RING_TAIL      		0x00
+#define TAIL_ADDR		0x001FFFF8
+#define RING_HEAD      		0x04
+#define HEAD_WRAP_COUNT     	0xFFE00000
+#define HEAD_WRAP_ONE       	0x00200000
+#define HEAD_ADDR           	0x001FFFFC
+#define RING_START     		0x08
+#define START_ADDR          	0x0xFFFFF000
+#define RING_LEN       		0x0C
+#define 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
+
+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define SC_UPDATE_SCISSOR       (0x1<<1)
+#define SC_ENABLE_MASK          (0x1<<0)
+#define SC_ENABLE               (0x1<<0)
+
+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define SCI_YMIN_MASK      (0xffff<<16)
+#define SCI_XMIN_MASK      (0xffff<<0)
+#define SCI_YMAX_MASK      (0xffff<<16)
+#define SCI_XMAX_MASK      (0xffff<<0)
+
+#define GFX_OP_SCISSOR_ENABLE	 ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define GFX_OP_SCISSOR_RECT	 ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+
+#define GFX_OP_DRAWRECT_INFO_I965  ((0x7900<<16)|0x2)
+
+#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 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_WAIT_FOR_EVENT       ((0x3<<23))
+#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
+#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+
+#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
+
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define ASYNC_FLIP                (1<<22)
+
+#define CMD_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+
+#define READ_BREADCRUMB(dev_priv)  (((volatile u32*)(dev_priv->hw_status_page))[5])
+#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
+#endif
--- libdrm-2.3.0.orig/shared-core/via_video.c
+++ libdrm-2.3.0/shared-core/via_video.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2005 Thomas Hellstrom. 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
+ * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Thomas Hellstrom 2005.
+ *
+ * Video and XvMC related functions.
+ */
+
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+void via_init_futex(drm_via_private_t * dev_priv)
+{
+	unsigned int i;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
+		DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i]));
+		XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0;
+	}
+}
+
+void via_cleanup_futex(drm_via_private_t * dev_priv)
+{
+}
+
+void via_release_futex(drm_via_private_t * dev_priv, int context)
+{
+	unsigned int i;
+	volatile int *lock;
+
+	if (!dev_priv->sarea_priv)
+		return;
+
+	for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
+		lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
+		if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
+			if (_DRM_LOCK_IS_HELD(*lock)
+			    && (*lock & _DRM_LOCK_CONT)) {
+				DRM_WAKEUP(&(dev_priv->decoder_queue[i]));
+			}
+			*lock = 0;
+		}
+	}
+}
+
+int via_decoder_futex(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_via_futex_t fx;
+	volatile int *lock;
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	drm_via_sarea_t *sAPriv = dev_priv->sarea_priv;
+	int ret = 0;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t __user *) data,
+				 sizeof(fx));
+
+	if (fx.lock > VIA_NR_XVMC_LOCKS)
+		return -EFAULT;
+
+	lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx.lock);
+
+	switch (fx.func) {
+	case VIA_FUTEX_WAIT:
+		DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx.lock],
+			    (fx.ms / 10) * (DRM_HZ / 100), *lock != fx.val);
+		return ret;
+	case VIA_FUTEX_WAKE:
+		DRM_WAKEUP(&(dev_priv->decoder_queue[fx.lock]));
+		return 0;
+	}
+	return 0;
+}
--- libdrm-2.3.0.orig/shared-core/sis_ds.h
+++ libdrm-2.3.0/shared-core/sis_ds.h
@@ -0,0 +1,146 @@
+/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+ */
+/*
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Sung-Ching Lin <sclin@sis.com.tw>
+ *
+ */
+
+#ifndef __SIS_DS_H__
+#define __SIS_DS_H__
+
+/* Set Data Structure */
+
+#define SET_SIZE 5000
+
+typedef unsigned long ITEM_TYPE;
+
+typedef struct {
+	ITEM_TYPE val;
+	int alloc_next, free_next;
+} list_item_t;
+
+typedef struct {
+	int alloc;
+	int free;
+	int trace;
+	list_item_t list[SET_SIZE];
+} set_t;
+
+set_t *setInit(void);
+int setAdd(set_t * set, ITEM_TYPE item);
+int setDel(set_t * set, ITEM_TYPE item);
+int setFirst(set_t * set, ITEM_TYPE * item);
+int setNext(set_t * set, ITEM_TYPE * item);
+int setDestroy(set_t * set);
+
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Wittawat Yamwong
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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
+ * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+struct mem_block_t {
+	struct mem_block_t *next;
+	struct mem_block_t *heap;
+	int ofs, size;
+	int align;
+	unsigned int free:1;
+	unsigned int reserved:1;
+};
+typedef struct mem_block_t TMemBlock;
+typedef struct mem_block_t *PMemBlock;
+
+/* a heap is just the first block in a chain */
+typedef struct mem_block_t memHeap_t;
+
+static __inline__ int mmBlockSize(PMemBlock b)
+{
+	return b->size;
+}
+
+static __inline__ int mmOffset(PMemBlock b)
+{
+	return b->ofs;
+}
+
+static __inline__ void mmMarkReserved(PMemBlock b)
+{
+	b->reserved = 1;
+}
+
+/*
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+memHeap_t *mmInit(int ofs, int size);
+
+/*
+ * Allocate 'size' bytes with 2^align2 bytes alignment,
+ * restrict the search to free memory after 'startSearch'
+ * depth and back buffers should be in different 4mb banks
+ * to get better page hits if possible
+ * input:	size = size of block
+ *       	align2 = 2^align2 bytes alignment
+ *		startSearch = linear offset from start of heap to begin search
+ * return: pointer to the allocated block, 0 if error
+ */
+PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch);
+
+/*
+ * Returns 1 if the block 'b' is part of the heap 'heap'
+ */
+int mmBlockInHeap(PMemBlock heap, PMemBlock b);
+
+/*
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+int mmFreeMem(PMemBlock b);
+
+/* For debuging purpose. */
+void mmDumpMemInfo(memHeap_t * mmInit);
+
+#endif				/* __SIS_DS_H__ */
--- libdrm-2.3.0.orig/shared-core/drm_drawable.c
+++ libdrm-2.3.0/shared-core/drm_drawable.c
@@ -0,0 +1,330 @@
+/**
+ * \file drm_drawable.c
+ * IOCTLs for drawables
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ * \author Michel Dänzer <michel@tungstengraphics.com>
+ */
+
+/*
+ * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota.
+ * 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
+ * VA LINUX SYSTEMS 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 "drmP.h"
+
+/**
+ * Allocate drawable ID and memory to store information about it.
+ */
+int drm_adddraw(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	unsigned long irqflags;
+	int i, j;
+	u32 *bitfield = dev->drw_bitfield;
+	unsigned int bitfield_length = dev->drw_bitfield_length;
+	drm_drawable_info_t **info = dev->drw_info;
+	unsigned int info_length = dev->drw_info_length;
+	drm_draw_t draw;
+
+	for (i = 0, j = 0; i < bitfield_length; i++) {
+		if (bitfield[i] == ~0)
+			continue;
+
+		for (; j < 8 * sizeof(*bitfield); j++)
+			if (!(bitfield[i] & (1 << j)))
+				goto done;
+	}
+done:
+
+	if (i == bitfield_length) {
+		bitfield_length++;
+
+		bitfield = drm_alloc(bitfield_length * sizeof(*bitfield),
+				     DRM_MEM_BUFS);
+
+		if (!bitfield) {
+			DRM_ERROR("Failed to allocate new drawable bitfield\n");
+			return DRM_ERR(ENOMEM);
+		}
+
+		if (8 * sizeof(*bitfield) * bitfield_length > info_length) {
+			info_length += 8 * sizeof(*bitfield);
+
+			info = drm_alloc(info_length * sizeof(*info),
+					 DRM_MEM_BUFS);
+
+			if (!info) {
+				DRM_ERROR("Failed to allocate new drawable info"
+					  " array\n");
+
+				drm_free(bitfield,
+					 bitfield_length * sizeof(*bitfield),
+					 DRM_MEM_BUFS);
+				return DRM_ERR(ENOMEM);
+			}
+		}
+
+		bitfield[i] = 0;
+	}
+
+	draw.handle = i * 8 * sizeof(*bitfield) + j + 1;
+	DRM_DEBUG("%d\n", draw.handle);
+
+	spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+	bitfield[i] |= 1 << j;
+	info[draw.handle - 1] = NULL;
+
+	if (bitfield != dev->drw_bitfield) {
+		memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length *
+		       sizeof(*bitfield));
+		drm_free(dev->drw_bitfield, sizeof(*bitfield) *
+			 dev->drw_bitfield_length, DRM_MEM_BUFS);
+		dev->drw_bitfield = bitfield;
+		dev->drw_bitfield_length = bitfield_length;
+	}
+
+	if (info != dev->drw_info) {
+		memcpy(info, dev->drw_info, dev->drw_info_length *
+		       sizeof(*info));
+		drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length,
+			 DRM_MEM_BUFS);
+		dev->drw_info = info;
+		dev->drw_info_length = info_length;
+	}
+
+	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+	DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw));
+
+	return 0;
+}
+
+/**
+ * Free drawable ID and memory to store information about it.
+ */
+int drm_rmdraw(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_draw_t draw;
+	int id, idx;
+	unsigned int shift;
+	unsigned long irqflags;
+	u32 *bitfield = dev->drw_bitfield;
+	unsigned int bitfield_length = dev->drw_bitfield_length;
+	drm_drawable_info_t **info = dev->drw_info;
+	unsigned int info_length = dev->drw_info_length;
+
+	DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,
+				 sizeof(draw));
+
+	id = draw.handle - 1;
+	idx = id / (8 * sizeof(*bitfield));
+	shift = id % (8 * sizeof(*bitfield));
+
+	if (idx < 0 || idx >= bitfield_length ||
+	    !(bitfield[idx] & (1 << shift))) {
+		DRM_DEBUG("No such drawable %d\n", draw.handle);
+		return 0;
+	}
+
+	spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+	bitfield[idx] &= ~(1 << shift);
+
+	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+	if (info[id]) {
+		drm_free(info[id]->rects, info[id]->num_rects *
+			 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+		drm_free(info[id], sizeof(**info), DRM_MEM_BUFS);
+	}
+
+	/* Can we shrink the arrays? */
+	if (idx == bitfield_length - 1) {
+		while (idx >= 0 && !bitfield[idx])
+			--idx;
+
+		bitfield_length = idx + 1;
+
+		if (idx != id / (8 * sizeof(*bitfield)))
+			bitfield = drm_alloc(bitfield_length *
+					     sizeof(*bitfield), DRM_MEM_BUFS);
+
+		if (!bitfield && bitfield_length) {
+			bitfield = dev->drw_bitfield;
+			bitfield_length = dev->drw_bitfield_length;
+		}
+	}
+
+	if (bitfield != dev->drw_bitfield) {
+		info_length = 8 * sizeof(*bitfield) * bitfield_length;
+
+		info = drm_alloc(info_length * sizeof(*info), DRM_MEM_BUFS);
+
+		if (!info && info_length) {
+			info = dev->drw_info;
+			info_length = dev->drw_info_length;
+		}
+
+		spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+		memcpy(bitfield, dev->drw_bitfield, bitfield_length *
+		       sizeof(*bitfield));
+		drm_free(dev->drw_bitfield, sizeof(*bitfield) *
+			 dev->drw_bitfield_length, DRM_MEM_BUFS);
+		dev->drw_bitfield = bitfield;
+		dev->drw_bitfield_length = bitfield_length;
+
+		if (info != dev->drw_info) {
+			memcpy(info, dev->drw_info, info_length *
+			       sizeof(*info));
+			drm_free(dev->drw_info, sizeof(*info) *
+				 dev->drw_info_length, DRM_MEM_BUFS);
+			dev->drw_info = info;
+			dev->drw_info_length = info_length;
+		}
+
+		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+	}
+
+	DRM_DEBUG("%d\n", draw.handle);
+	return 0;
+}
+
+int drm_update_drawable_info(DRM_IOCTL_ARGS) {
+	DRM_DEVICE;
+	drm_update_draw_t update;
+	unsigned int id, idx, shift, bitfield_length = dev->drw_bitfield_length;
+	u32 *bitfield = dev->drw_bitfield;
+	unsigned long irqflags;
+	drm_drawable_info_t *info;
+	drm_clip_rect_t *rects;
+	int err;
+
+	DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data,
+				 sizeof(update));
+
+	id = update.handle - 1;
+	idx = id / (8 * sizeof(*bitfield));
+	shift = id % (8 * sizeof(*bitfield));
+
+	if (idx < 0 || idx >= bitfield_length ||
+	    !(bitfield[idx] & (1 << shift))) {
+		DRM_ERROR("No such drawable %d\n", update.handle);
+		return DRM_ERR(EINVAL);
+	}
+
+	info = dev->drw_info[id];
+
+	if (!info) {
+		info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS);
+
+		if (!info) {
+			DRM_ERROR("Failed to allocate drawable info memory\n");
+			return DRM_ERR(ENOMEM);
+		}
+	}
+
+	switch (update.type) {
+	case DRM_DRAWABLE_CLIPRECTS:
+		if (update.num != info->num_rects) {
+			rects = drm_alloc(update.num * sizeof(drm_clip_rect_t),
+					 DRM_MEM_BUFS);
+		} else
+			rects = info->rects;
+
+		if (update.num && !rects) {
+			DRM_ERROR("Failed to allocate cliprect memory\n");
+			err = DRM_ERR(ENOMEM);
+			goto error;
+		}
+
+		if (update.num && DRM_COPY_FROM_USER(rects,
+						     (drm_clip_rect_t __user *)
+						     (unsigned long)update.data,
+						     update.num *
+						     sizeof(*rects))) {
+			DRM_ERROR("Failed to copy cliprects from userspace\n");
+			err = DRM_ERR(EFAULT);
+			goto error;
+		}
+
+		spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+		if (rects != info->rects) {
+			drm_free(info->rects, info->num_rects *
+				 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+		}
+
+		info->rects = rects;
+		info->num_rects = update.num;
+		dev->drw_info[id] = info;
+
+		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+		DRM_DEBUG("Updated %d cliprects for drawable %d\n",
+			  info->num_rects, id);
+		break;
+	default:
+		DRM_ERROR("Invalid update type %d\n", update.type);
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+
+error:
+	if (!dev->drw_info[id])
+		drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+	else if (rects != dev->drw_info[id]->rects)
+		drm_free(rects, update.num *
+			 sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+
+	return err;
+}
+
+/**
+ * Caller must hold the drawable spinlock!
+ */
+drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
+	u32 *bitfield = dev->drw_bitfield;
+	unsigned int idx, shift;
+
+	id--;
+	idx = id / (8 * sizeof(*bitfield));
+	shift = id % (8 * sizeof(*bitfield));
+
+	if (idx < 0 || idx >= dev->drw_bitfield_length ||
+	    !(bitfield[idx] & (1 << shift))) {
+		DRM_DEBUG("No such drawable %d\n", id);
+		return NULL;
+	}
+
+	return dev->drw_info[id];
+}
+EXPORT_SYMBOL(drm_get_drawable_info);
--- libdrm-2.3.0.orig/shared-core/savage_state.c
+++ libdrm-2.3.0/shared-core/savage_state.c
@@ -0,0 +1,1164 @@
+/* savage_state.c -- State and drawing support for Savage
+ *
+ * Copyright 2004  Felix Kuehling
+ * 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 FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 "drmP.h"
+#include "savage_drm.h"
+#include "savage_drv.h"
+
+void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
+			       const drm_clip_rect_t *pbox)
+{
+	uint32_t scstart = dev_priv->state.s3d.new_scstart;
+	uint32_t scend   = dev_priv->state.s3d.new_scend;
+	scstart = (scstart & ~SAVAGE_SCISSOR_MASK_S3D) |
+		((uint32_t)pbox->x1 & 0x000007ff) | 
+		(((uint32_t)pbox->y1 << 16) & 0x07ff0000);
+	scend   = (scend   & ~SAVAGE_SCISSOR_MASK_S3D) |
+		(((uint32_t)pbox->x2-1) & 0x000007ff) |
+		((((uint32_t)pbox->y2-1) << 16) & 0x07ff0000);
+	if (scstart != dev_priv->state.s3d.scstart ||
+	    scend   != dev_priv->state.s3d.scend) {
+		DMA_LOCALS;
+		BEGIN_DMA(4);
+		DMA_WRITE(BCI_CMD_WAIT|BCI_CMD_WAIT_3D);
+		DMA_SET_REGISTERS(SAVAGE_SCSTART_S3D, 2);
+		DMA_WRITE(scstart);
+		DMA_WRITE(scend);
+		dev_priv->state.s3d.scstart = scstart;
+		dev_priv->state.s3d.scend   = scend;
+		dev_priv->waiting = 1;
+		DMA_COMMIT();
+	}
+}
+
+void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
+			      const drm_clip_rect_t *pbox)
+{
+	uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
+	uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
+	drawctrl0 = (drawctrl0 & ~SAVAGE_SCISSOR_MASK_S4) |
+		((uint32_t)pbox->x1 & 0x000007ff) |
+		(((uint32_t)pbox->y1 << 12) & 0x00fff000);
+	drawctrl1 = (drawctrl1 & ~SAVAGE_SCISSOR_MASK_S4) |
+		(((uint32_t)pbox->x2-1) & 0x000007ff) |
+		((((uint32_t)pbox->y2-1) << 12) & 0x00fff000);
+	if (drawctrl0 != dev_priv->state.s4.drawctrl0 ||
+	    drawctrl1 != dev_priv->state.s4.drawctrl1) {
+		DMA_LOCALS;
+		BEGIN_DMA(4);
+		DMA_WRITE(BCI_CMD_WAIT|BCI_CMD_WAIT_3D);
+		DMA_SET_REGISTERS(SAVAGE_DRAWCTRL0_S4, 2);
+		DMA_WRITE(drawctrl0);
+		DMA_WRITE(drawctrl1);
+		dev_priv->state.s4.drawctrl0 = drawctrl0;
+		dev_priv->state.s4.drawctrl1 = drawctrl1;
+		dev_priv->waiting = 1;
+		DMA_COMMIT();
+	}
+}
+
+static int savage_verify_texaddr(drm_savage_private_t *dev_priv, int unit,
+				 uint32_t addr)
+{
+	if ((addr & 6) != 2) { /* reserved bits */
+		DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr);
+		return DRM_ERR(EINVAL);
+	}
+	if (!(addr & 1)) { /* local */
+		addr &= ~7;
+		if (addr <  dev_priv->texture_offset ||
+		    addr >= dev_priv->texture_offset+dev_priv->texture_size) {
+			DRM_ERROR
+			    ("bad texAddr%d %08x (local addr out of range)\n",
+			     unit, addr);
+			return DRM_ERR(EINVAL);
+		}
+	} else { /* AGP */
+		if (!dev_priv->agp_textures) {
+			DRM_ERROR("bad texAddr%d %08x (AGP not available)\n",
+				  unit, addr);
+			return DRM_ERR(EINVAL);
+		}
+		addr &= ~7;
+		if (addr < dev_priv->agp_textures->offset ||
+		    addr >= (dev_priv->agp_textures->offset +
+			     dev_priv->agp_textures->size)) {
+			DRM_ERROR
+			    ("bad texAddr%d %08x (AGP addr out of range)\n",
+			     unit, addr);
+			return DRM_ERR(EINVAL);
+		}
+	}
+	return 0;
+}
+
+#define SAVE_STATE(reg,where)			\
+	if(start <= reg && start+count > reg)	\
+		dev_priv->state.where = regs[reg - start]
+#define SAVE_STATE_MASK(reg,where,mask) do {			\
+	if(start <= reg && start+count > reg) {			\
+		uint32_t tmp;					\
+		tmp = regs[reg - start];			\
+		dev_priv->state.where = (tmp & (mask)) |	\
+			(dev_priv->state.where & ~(mask));	\
+	}							\
+} while (0)
+static int savage_verify_state_s3d(drm_savage_private_t *dev_priv,
+				   unsigned int start, unsigned int count,
+				   const uint32_t *regs)
+{
+	if (start < SAVAGE_TEXPALADDR_S3D ||
+	    start+count-1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
+		DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+			  start, start+count-1);
+		return DRM_ERR(EINVAL);
+	}
+
+	SAVE_STATE_MASK(SAVAGE_SCSTART_S3D, s3d.new_scstart,
+			~SAVAGE_SCISSOR_MASK_S3D);
+	SAVE_STATE_MASK(SAVAGE_SCEND_S3D, s3d.new_scend,
+			~SAVAGE_SCISSOR_MASK_S3D);
+
+	/* if any texture regs were changed ... */
+	if (start <= SAVAGE_TEXCTRL_S3D &&
+	    start+count > SAVAGE_TEXPALADDR_S3D) {
+		/* ... check texture state */
+		SAVE_STATE(SAVAGE_TEXCTRL_S3D, s3d.texctrl);
+		SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr);
+		if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK)
+			return savage_verify_texaddr(dev_priv, 0,
+						dev_priv->state.s3d.texaddr);
+	}
+
+	return 0;
+}
+
+static int savage_verify_state_s4(drm_savage_private_t *dev_priv,
+				  unsigned int start, unsigned int count,
+				  const uint32_t *regs)
+{
+	int ret = 0;
+
+	if (start < SAVAGE_DRAWLOCALCTRL_S4 ||
+	    start+count-1 > SAVAGE_TEXBLENDCOLOR_S4) {
+		DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+			  start, start+count-1);
+		return DRM_ERR(EINVAL);
+	}
+
+	SAVE_STATE_MASK(SAVAGE_DRAWCTRL0_S4, s4.new_drawctrl0,
+			~SAVAGE_SCISSOR_MASK_S4);
+	SAVE_STATE_MASK(SAVAGE_DRAWCTRL1_S4, s4.new_drawctrl1,
+			~SAVAGE_SCISSOR_MASK_S4);
+
+	/* if any texture regs were changed ... */
+	if (start <= SAVAGE_TEXDESCR_S4 &&
+	    start + count > SAVAGE_TEXPALADDR_S4) {
+		/* ... check texture state */
+		SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr);
+		SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0);
+		SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1);
+		if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK)
+			ret |= savage_verify_texaddr(dev_priv, 0,
+						dev_priv->state.s4.texaddr0);
+		if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK)
+			ret |= savage_verify_texaddr(dev_priv, 1,
+						dev_priv->state.s4.texaddr1);
+	}
+
+	return ret;
+}
+#undef SAVE_STATE
+#undef SAVE_STATE_MASK
+
+static int savage_dispatch_state(drm_savage_private_t *dev_priv,
+				 const drm_savage_cmd_header_t *cmd_header,
+				 const uint32_t *regs)
+{
+	unsigned int count = cmd_header->state.count;
+	unsigned int start = cmd_header->state.start;
+	unsigned int count2 = 0;
+	unsigned int bci_size;
+	int ret;
+	DMA_LOCALS;
+
+	if (!count)
+		return 0;
+
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+		ret = savage_verify_state_s3d(dev_priv, start, count, regs);
+		if (ret != 0)
+			return ret;
+		/* scissor regs are emitted in savage_dispatch_draw */
+		if (start < SAVAGE_SCSTART_S3D) {
+			if (start+count > SAVAGE_SCEND_S3D+1)
+				count2 = count - (SAVAGE_SCEND_S3D+1 - start);
+			if (start+count > SAVAGE_SCSTART_S3D)
+				count = SAVAGE_SCSTART_S3D - start;
+		} else if (start <= SAVAGE_SCEND_S3D) {
+			if (start+count > SAVAGE_SCEND_S3D+1) {
+				count -= SAVAGE_SCEND_S3D+1 - start;
+				start = SAVAGE_SCEND_S3D+1;
+			} else
+				return 0;
+		}
+	} else {
+		ret = savage_verify_state_s4(dev_priv, start, count, regs);
+		if (ret != 0)
+			return ret;
+		/* scissor regs are emitted in savage_dispatch_draw */
+		if (start < SAVAGE_DRAWCTRL0_S4) {
+			if (start+count > SAVAGE_DRAWCTRL1_S4+1)
+				count2 = count -
+					 (SAVAGE_DRAWCTRL1_S4 + 1 - start);
+			if (start+count > SAVAGE_DRAWCTRL0_S4)
+				count = SAVAGE_DRAWCTRL0_S4 - start;
+		} else if (start <= SAVAGE_DRAWCTRL1_S4) {
+			if (start+count > SAVAGE_DRAWCTRL1_S4+1) {
+				count -= SAVAGE_DRAWCTRL1_S4+1 - start;
+				start = SAVAGE_DRAWCTRL1_S4+1;
+			} else
+				return 0;
+		}
+	}
+
+	bci_size = count + (count+254)/255 + count2 + (count2+254)/255;
+
+	if (cmd_header->state.global) {
+		BEGIN_DMA(bci_size+1);
+		DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+		dev_priv->waiting = 1;
+	} else {
+		BEGIN_DMA(bci_size);
+	}
+
+	do {
+		while (count > 0) {
+			unsigned int n = count < 255 ? count : 255;
+			DMA_SET_REGISTERS(start, n);
+			DMA_COPY(regs, n);
+			count -= n;
+			start += n;
+			regs += n;
+		}
+		start += 2;
+		regs += 2;
+		count = count2;
+		count2 = 0;
+	} while (count);
+
+	DMA_COMMIT();
+
+	return 0;
+}
+
+static int savage_dispatch_dma_prim(drm_savage_private_t *dev_priv,
+				    const drm_savage_cmd_header_t *cmd_header,
+				    const drm_buf_t *dmabuf)
+{
+	unsigned char reorder = 0;
+	unsigned int prim = cmd_header->prim.prim;
+	unsigned int skip = cmd_header->prim.skip;
+	unsigned int n = cmd_header->prim.count;
+	unsigned int start = cmd_header->prim.start;
+	unsigned int i;
+	BCI_LOCALS;
+
+	if (!dmabuf) {
+	    DRM_ERROR("called without dma buffers!\n");
+	    return DRM_ERR(EINVAL);
+	}
+
+	if (!n)
+		return 0;
+
+	switch (prim) {
+	case SAVAGE_PRIM_TRILIST_201:
+		reorder = 1;
+		prim = SAVAGE_PRIM_TRILIST;
+	case SAVAGE_PRIM_TRILIST:
+		if (n % 3 != 0) {
+			DRM_ERROR("wrong number of vertices %u in TRILIST\n",
+				  n);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+	case SAVAGE_PRIM_TRISTRIP:
+	case SAVAGE_PRIM_TRIFAN:
+		if (n < 3) {
+			DRM_ERROR
+			   ("wrong number of vertices %u in TRIFAN/STRIP\n",
+			    n);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+	default:
+		DRM_ERROR("invalid primitive type %u\n", prim);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+		if (skip != 0) {
+			DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+			return DRM_ERR(EINVAL);
+		}
+	} else {
+		unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+			(skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+			(skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+		if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+			DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+			return DRM_ERR(EINVAL);
+		}
+		if (reorder) {
+			DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
+			return DRM_ERR(EINVAL);
+		}
+	}
+
+	if (start + n > dmabuf->total/32) {
+		DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+			  start, start + n - 1, dmabuf->total/32);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* Vertex DMA doesn't work with command DMA at the same time,
+	 * so we use BCI_... to submit commands here. Flush buffered
+	 * faked DMA first. */
+	DMA_FLUSH();
+
+	if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
+		BEGIN_BCI(2);
+		BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
+		BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
+		dev_priv->state.common.vbaddr = dmabuf->bus_address;
+	}
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
+		/* Workaround for what looks like a hardware bug. If a
+		 * WAIT_3D_IDLE was emitted some time before the
+		 * indexed drawing command then the engine will lock
+		 * up. There are two known workarounds:
+		 * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
+		BEGIN_BCI(63);
+		for (i = 0; i < 63; ++i)
+			BCI_WRITE(BCI_CMD_WAIT);
+		dev_priv->waiting = 0;
+	}
+
+	prim <<= 25;
+	while (n != 0) {
+		/* Can emit up to 255 indices (85 triangles) at once. */
+		unsigned int count = n > 255 ? 255 : n;
+		if (reorder) {
+			/* Need to reorder indices for correct flat
+			 * shading while preserving the clock sense
+			 * for correct culling. Only on Savage3D. */
+			int reorder[3] = {-1, -1, -1};
+			reorder[start%3] = 2;
+
+			BEGIN_BCI((count+1+1)/2);
+			BCI_DRAW_INDICES_S3D(count, prim, start+2);
+
+			for (i = start+1; i+1 < start+count; i += 2)
+				BCI_WRITE((i + reorder[i % 3]) |
+					  ((i + 1 +
+					    reorder[(i + 1) % 3]) << 16));
+			if (i < start+count)
+				BCI_WRITE(i + reorder[i%3]);
+		} else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+			BEGIN_BCI((count+1+1)/2);
+			BCI_DRAW_INDICES_S3D(count, prim, start);
+
+			for (i = start+1; i+1 < start+count; i += 2)
+				BCI_WRITE(i | ((i+1) << 16));
+			if (i < start+count)
+				BCI_WRITE(i);
+		} else {
+			BEGIN_BCI((count+2+1)/2);
+			BCI_DRAW_INDICES_S4(count, prim, skip);
+
+			for (i = start; i+1 < start+count; i += 2)
+				BCI_WRITE(i | ((i+1) << 16));
+			if (i < start+count)
+				BCI_WRITE(i);
+		}
+
+		start += count;
+		n -= count;
+
+		prim |= BCI_CMD_DRAW_CONT;
+	}
+
+	return 0;
+}
+
+static int savage_dispatch_vb_prim(drm_savage_private_t *dev_priv,
+				   const drm_savage_cmd_header_t *cmd_header,
+				   const uint32_t *vtxbuf, unsigned int vb_size,
+				   unsigned int vb_stride)
+{
+	unsigned char reorder = 0;
+	unsigned int prim = cmd_header->prim.prim;
+	unsigned int skip = cmd_header->prim.skip;
+	unsigned int n = cmd_header->prim.count;
+	unsigned int start = cmd_header->prim.start;
+	unsigned int vtx_size;
+	unsigned int i;
+	DMA_LOCALS;
+
+	if (!n)
+		return 0;
+
+	switch (prim) {
+	case SAVAGE_PRIM_TRILIST_201:
+		reorder = 1;
+		prim = SAVAGE_PRIM_TRILIST;
+	case SAVAGE_PRIM_TRILIST:
+		if (n % 3 != 0) {
+			DRM_ERROR("wrong number of vertices %u in TRILIST\n",
+				  n);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+	case SAVAGE_PRIM_TRISTRIP:
+	case SAVAGE_PRIM_TRIFAN:
+		if (n < 3) {
+			DRM_ERROR
+			    ("wrong number of vertices %u in TRIFAN/STRIP\n",
+			     n);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+	default:
+		DRM_ERROR("invalid primitive type %u\n", prim);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+		if (skip > SAVAGE_SKIP_ALL_S3D) {
+			DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+			return DRM_ERR(EINVAL);
+		}
+		vtx_size = 8; /* full vertex */
+	} else {
+		if (skip > SAVAGE_SKIP_ALL_S4) {
+			DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+			return DRM_ERR(EINVAL);
+		}
+		vtx_size = 10; /* full vertex */
+	}
+
+	vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+		(skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+		(skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+	if (vtx_size > vb_stride) {
+		DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+			  vtx_size, vb_stride);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (start + n > vb_size / (vb_stride*4)) {
+		DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+			  start, start + n - 1, vb_size / (vb_stride*4));
+		return DRM_ERR(EINVAL);
+	}
+
+	prim <<= 25;
+	while (n != 0) {
+		/* Can emit up to 255 vertices (85 triangles) at once. */
+		unsigned int count = n > 255 ? 255 : n;
+		if (reorder) {
+			/* Need to reorder vertices for correct flat
+			 * shading while preserving the clock sense
+			 * for correct culling. Only on Savage3D. */
+			int reorder[3] = {-1, -1, -1};
+			reorder[start%3] = 2;
+
+			BEGIN_DMA(count*vtx_size+1);
+			DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+			for (i = start; i < start+count; ++i) {
+				unsigned int j = i + reorder[i % 3];
+				DMA_COPY(&vtxbuf[vb_stride*j], vtx_size);
+			}
+
+			DMA_COMMIT();
+		} else {
+			BEGIN_DMA(count*vtx_size+1);
+			DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+			if (vb_stride == vtx_size) {
+				DMA_COPY(&vtxbuf[vb_stride*start],
+					 vtx_size*count);
+			} else {
+				for (i = start; i < start+count; ++i) {
+					DMA_COPY(&vtxbuf[vb_stride*i],
+						 vtx_size);
+				}
+			}
+
+			DMA_COMMIT();
+		}
+
+		start += count;
+		n -= count;
+
+		prim |= BCI_CMD_DRAW_CONT;
+	}
+
+	return 0;
+}
+
+static int savage_dispatch_dma_idx(drm_savage_private_t *dev_priv,
+				   const drm_savage_cmd_header_t *cmd_header,
+				   const uint16_t *idx,
+				   const drm_buf_t *dmabuf)
+{
+	unsigned char reorder = 0;
+	unsigned int prim = cmd_header->idx.prim;
+	unsigned int skip = cmd_header->idx.skip;
+	unsigned int n = cmd_header->idx.count;
+	unsigned int i;
+	BCI_LOCALS;
+
+	if (!dmabuf) {
+	    DRM_ERROR("called without dma buffers!\n");
+	    return DRM_ERR(EINVAL);
+	}
+
+	if (!n)
+		return 0;
+
+	switch (prim) {
+	case SAVAGE_PRIM_TRILIST_201:
+		reorder = 1;
+		prim = SAVAGE_PRIM_TRILIST;
+	case SAVAGE_PRIM_TRILIST:
+		if (n % 3 != 0) {
+			DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+	case SAVAGE_PRIM_TRISTRIP:
+	case SAVAGE_PRIM_TRIFAN:
+		if (n < 3) {
+			DRM_ERROR
+			    ("wrong number of indices %u in TRIFAN/STRIP\n", n);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+	default:
+		DRM_ERROR("invalid primitive type %u\n", prim);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+		if (skip != 0) {
+			DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+			return DRM_ERR(EINVAL);
+		}
+	} else {
+		unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+			(skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+			(skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+		if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+			DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+			return DRM_ERR(EINVAL);
+		}
+		if (reorder) {
+			DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
+			return DRM_ERR(EINVAL);
+		}
+	}
+
+	/* Vertex DMA doesn't work with command DMA at the same time,
+	 * so we use BCI_... to submit commands here. Flush buffered
+	 * faked DMA first. */
+	DMA_FLUSH();
+
+	if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
+		BEGIN_BCI(2);
+		BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
+		BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
+		dev_priv->state.common.vbaddr = dmabuf->bus_address;
+	}
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
+		/* Workaround for what looks like a hardware bug. If a
+		 * WAIT_3D_IDLE was emitted some time before the
+		 * indexed drawing command then the engine will lock
+		 * up. There are two known workarounds:
+		 * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
+		BEGIN_BCI(63);
+		for (i = 0; i < 63; ++i)
+			BCI_WRITE(BCI_CMD_WAIT);
+		dev_priv->waiting = 0;
+	}
+
+	prim <<= 25;
+	while (n != 0) {
+		/* Can emit up to 255 indices (85 triangles) at once. */
+		unsigned int count = n > 255 ? 255 : n;
+
+		/* check indices */
+		for (i = 0; i < count; ++i) {
+			if (idx[i] > dmabuf->total/32) {
+				DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+					  i, idx[i], dmabuf->total/32);
+				return DRM_ERR(EINVAL);
+			}
+		}
+
+		if (reorder) {
+			/* Need to reorder indices for correct flat
+			 * shading while preserving the clock sense
+			 * for correct culling. Only on Savage3D. */
+			int reorder[3] = {2, -1, -1};
+
+			BEGIN_BCI((count+1+1)/2);
+			BCI_DRAW_INDICES_S3D(count, prim, idx[2]);
+
+			for (i = 1; i+1 < count; i += 2)
+				BCI_WRITE(idx[i + reorder[i % 3]] |
+					  (idx[i + 1 +
+					   reorder[(i + 1) % 3]] << 16));
+			if (i < count)
+				BCI_WRITE(idx[i + reorder[i%3]]);
+		} else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+			BEGIN_BCI((count+1+1)/2);
+			BCI_DRAW_INDICES_S3D(count, prim, idx[0]);
+
+			for (i = 1; i+1 < count; i += 2)
+				BCI_WRITE(idx[i] | (idx[i+1] << 16));
+			if (i < count)
+				BCI_WRITE(idx[i]);
+		} else {
+			BEGIN_BCI((count+2+1)/2);
+			BCI_DRAW_INDICES_S4(count, prim, skip);
+
+			for (i = 0; i+1 < count; i += 2)
+				BCI_WRITE(idx[i] | (idx[i+1] << 16));
+			if (i < count)
+				BCI_WRITE(idx[i]);
+		}
+
+		idx += count;
+		n -= count;
+
+		prim |= BCI_CMD_DRAW_CONT;
+	}
+
+	return 0;
+}
+
+static int savage_dispatch_vb_idx(drm_savage_private_t *dev_priv,
+				  const drm_savage_cmd_header_t *cmd_header,
+				  const uint16_t *idx,
+				  const uint32_t *vtxbuf,
+				  unsigned int vb_size, unsigned int vb_stride)
+{
+	unsigned char reorder = 0;
+	unsigned int prim = cmd_header->idx.prim;
+	unsigned int skip = cmd_header->idx.skip;
+	unsigned int n = cmd_header->idx.count;
+	unsigned int vtx_size;
+	unsigned int i;
+	DMA_LOCALS;
+
+	if (!n)
+		return 0;
+
+	switch (prim) {
+	case SAVAGE_PRIM_TRILIST_201:
+		reorder = 1;
+		prim = SAVAGE_PRIM_TRILIST;
+	case SAVAGE_PRIM_TRILIST:
+		if (n % 3 != 0) {
+			DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+	case SAVAGE_PRIM_TRISTRIP:
+	case SAVAGE_PRIM_TRIFAN:
+		if (n < 3) {
+			DRM_ERROR
+			    ("wrong number of indices %u in TRIFAN/STRIP\n", n);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+	default:
+		DRM_ERROR("invalid primitive type %u\n", prim);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+		if (skip > SAVAGE_SKIP_ALL_S3D) {
+			DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+			return DRM_ERR(EINVAL);
+		}
+		vtx_size = 8; /* full vertex */
+	} else {
+		if (skip > SAVAGE_SKIP_ALL_S4) {
+			DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+			return DRM_ERR(EINVAL);
+		}
+		vtx_size = 10; /* full vertex */
+	}
+
+	vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+		(skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+		(skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+	if (vtx_size > vb_stride) {
+		DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+			  vtx_size, vb_stride);
+		return DRM_ERR(EINVAL);
+	}
+
+	prim <<= 25;
+	while (n != 0) {
+		/* Can emit up to 255 vertices (85 triangles) at once. */
+		unsigned int count = n > 255 ? 255 : n;
+
+		/* Check indices */
+		for (i = 0; i < count; ++i) {
+			if (idx[i] > vb_size / (vb_stride*4)) {
+				DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+					  i, idx[i],  vb_size / (vb_stride*4));
+				return DRM_ERR(EINVAL);
+			}
+		}
+
+		if (reorder) {
+			/* Need to reorder vertices for correct flat
+			 * shading while preserving the clock sense
+			 * for correct culling. Only on Savage3D. */
+			int reorder[3] = {2, -1, -1};
+
+			BEGIN_DMA(count*vtx_size+1);
+			DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+			for (i = 0; i < count; ++i) {
+				unsigned int j = idx[i + reorder[i % 3]];
+				DMA_COPY(&vtxbuf[vb_stride*j], vtx_size);
+			}
+
+			DMA_COMMIT();
+		} else {
+			BEGIN_DMA(count*vtx_size+1);
+			DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+			for (i = 0; i < count; ++i) {
+				unsigned int j = idx[i];
+				DMA_COPY(&vtxbuf[vb_stride*j], vtx_size);
+			}
+
+			DMA_COMMIT();
+		}
+
+		idx += count;
+		n -= count;
+
+		prim |= BCI_CMD_DRAW_CONT;
+	}
+
+	return 0;
+}
+
+static int savage_dispatch_clear(drm_savage_private_t *dev_priv,
+				 const drm_savage_cmd_header_t *cmd_header,
+				 const drm_savage_cmd_header_t *data,
+				 unsigned int nbox,
+				 const drm_clip_rect_t *boxes)
+{
+	unsigned int flags = cmd_header->clear0.flags;
+	unsigned int clear_cmd;
+	unsigned int i, nbufs;
+	DMA_LOCALS;
+
+	if (nbox == 0)
+		return 0;
+
+	clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+		BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW;
+	BCI_CMD_SET_ROP(clear_cmd,0xCC);
+
+	nbufs = ((flags & SAVAGE_FRONT) ? 1 : 0) +
+	    ((flags & SAVAGE_BACK) ? 1 : 0) + ((flags & SAVAGE_DEPTH) ? 1 : 0);
+	if (nbufs == 0)
+		return 0;
+
+	if (data->clear1.mask != 0xffffffff) {
+		/* set mask */
+		BEGIN_DMA(2);
+		DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
+		DMA_WRITE(data->clear1.mask);
+		DMA_COMMIT();
+	}
+	for (i = 0; i < nbox; ++i) {
+		unsigned int x, y, w, h;
+		unsigned int buf;
+
+		x = boxes[i].x1, y = boxes[i].y1;
+		w = boxes[i].x2 - boxes[i].x1;
+		h = boxes[i].y2 - boxes[i].y1;
+		BEGIN_DMA(nbufs*6);
+		for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {
+			if (!(flags & buf))
+				continue;
+			DMA_WRITE(clear_cmd);
+			switch(buf) {
+			case SAVAGE_FRONT:
+				DMA_WRITE(dev_priv->front_offset);
+				DMA_WRITE(dev_priv->front_bd);
+				break;
+			case SAVAGE_BACK:
+				DMA_WRITE(dev_priv->back_offset);
+				DMA_WRITE(dev_priv->back_bd);
+				break;
+			case SAVAGE_DEPTH:
+				DMA_WRITE(dev_priv->depth_offset);
+				DMA_WRITE(dev_priv->depth_bd);
+				break;
+			}
+			DMA_WRITE(data->clear1.value);
+			DMA_WRITE(BCI_X_Y(x, y));
+			DMA_WRITE(BCI_W_H(w, h));
+		}
+		DMA_COMMIT();
+	}
+	if (data->clear1.mask != 0xffffffff) {
+		/* reset mask */
+		BEGIN_DMA(2);
+		DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
+		DMA_WRITE(0xffffffff);
+		DMA_COMMIT();
+	}
+
+	return 0;
+}
+
+static int savage_dispatch_swap(drm_savage_private_t *dev_priv,
+				unsigned int nbox, const drm_clip_rect_t *boxes)
+{
+	unsigned int swap_cmd;
+	unsigned int i;
+	DMA_LOCALS;
+
+	if (nbox == 0)
+		return 0;
+
+	swap_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+		BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD;
+	BCI_CMD_SET_ROP(swap_cmd,0xCC);
+
+	for (i = 0; i < nbox; ++i) {
+		BEGIN_DMA(6);
+		DMA_WRITE(swap_cmd);
+		DMA_WRITE(dev_priv->back_offset);
+		DMA_WRITE(dev_priv->back_bd);
+		DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
+		DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
+		DMA_WRITE(BCI_W_H(boxes[i].x2-boxes[i].x1,
+				  boxes[i].y2-boxes[i].y1));
+		DMA_COMMIT();
+	}
+
+	return 0;
+}
+
+static int savage_dispatch_draw(drm_savage_private_t *dev_priv,
+				const drm_savage_cmd_header_t *start,
+				const drm_savage_cmd_header_t *end,
+				const drm_buf_t *dmabuf,
+				const unsigned int *vtxbuf,
+				unsigned int vb_size, unsigned int vb_stride,
+				unsigned int nbox,
+				const drm_clip_rect_t *boxes)
+{
+	unsigned int i, j;
+	int ret;
+
+	for (i = 0; i < nbox; ++i) {
+		const drm_savage_cmd_header_t *cmdbuf;
+		dev_priv->emit_clip_rect(dev_priv, &boxes[i]);
+
+		cmdbuf = start;
+		while (cmdbuf < end) {
+			drm_savage_cmd_header_t cmd_header;
+			cmd_header = *cmdbuf;
+			cmdbuf++;
+			switch (cmd_header.cmd.cmd) {
+			case SAVAGE_CMD_DMA_PRIM:
+				ret = savage_dispatch_dma_prim(
+					dev_priv, &cmd_header, dmabuf);
+				break;
+			case SAVAGE_CMD_VB_PRIM:
+				ret = savage_dispatch_vb_prim(
+					dev_priv, &cmd_header,
+					vtxbuf, vb_size, vb_stride);
+				break;
+			case SAVAGE_CMD_DMA_IDX:
+				j = (cmd_header.idx.count + 3) / 4;
+				/* j was check in savage_bci_cmdbuf */
+				ret = savage_dispatch_dma_idx(dev_priv,
+					&cmd_header, (const uint16_t *)cmdbuf,
+					dmabuf);
+				cmdbuf += j;
+				break;
+			case SAVAGE_CMD_VB_IDX:
+				j = (cmd_header.idx.count + 3) / 4;
+				/* j was check in savage_bci_cmdbuf */
+				ret = savage_dispatch_vb_idx(dev_priv,
+					&cmd_header, (const uint16_t *)cmdbuf,
+					(const uint32_t *)vtxbuf, vb_size,
+					vb_stride);
+				cmdbuf += j;
+				break;
+			default:
+				/* What's the best return code? EFAULT? */
+				DRM_ERROR("IMPLEMENTATION ERROR: "
+					  "non-drawing-command %d\n",
+					  cmd_header.cmd.cmd);
+				return DRM_ERR(EINVAL);
+			}
+
+			if (ret != 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_savage_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *dmabuf;
+	drm_savage_cmdbuf_t cmdbuf;
+	drm_savage_cmd_header_t *kcmd_addr = NULL;
+	drm_savage_cmd_header_t *first_draw_cmd;
+	unsigned int *kvb_addr = NULL;
+	drm_clip_rect_t *kbox_addr = NULL;
+	unsigned int i, j;
+	int ret = 0;
+
+	DRM_DEBUG("\n");
+	
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *)data,
+				 sizeof(cmdbuf));
+
+	if (dma && dma->buflist) {
+		if (cmdbuf.dma_idx > dma->buf_count) {
+			DRM_ERROR
+			    ("vertex buffer index %u out of range (0-%u)\n",
+			     cmdbuf.dma_idx, dma->buf_count-1);
+			return DRM_ERR(EINVAL);
+		}
+		dmabuf = dma->buflist[cmdbuf.dma_idx];
+	} else {
+		dmabuf = NULL;
+	}
+
+	/* Copy the user buffers into kernel temporary areas.  This hasn't been
+	 * a performance loss compared to VERIFYAREA_READ/
+	 * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct
+	 * for locking on FreeBSD.
+	 */
+	if (cmdbuf.size) {
+		kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER);
+		if (kcmd_addr == NULL)
+			return ENOMEM;
+
+		if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr,
+				       cmdbuf.size * 8))
+		{
+			drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
+			return DRM_ERR(EFAULT);
+		}
+		cmdbuf.cmd_addr = kcmd_addr;
+	}
+	if (cmdbuf.vb_size) {
+		kvb_addr = drm_alloc(cmdbuf.vb_size, DRM_MEM_DRIVER);
+		if (kvb_addr == NULL) {
+			ret = DRM_ERR(ENOMEM);
+			goto done;
+		}
+
+		if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf.vb_addr,
+				       cmdbuf.vb_size)) {
+			ret = DRM_ERR(EFAULT);
+			goto done;
+		}
+		cmdbuf.vb_addr = kvb_addr;
+	}
+	if (cmdbuf.nbox) {
+		kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t),
+				       DRM_MEM_DRIVER);
+		if (kbox_addr == NULL) {
+			ret = DRM_ERR(ENOMEM);
+			goto done;
+		}
+
+		if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr,
+				       cmdbuf.nbox * sizeof(drm_clip_rect_t))) {
+			ret = DRM_ERR(EFAULT);
+			goto done;
+		}
+		cmdbuf.box_addr = kbox_addr;
+	}
+
+	/* Make sure writes to DMA buffers are finished before sending
+	 * DMA commands to the graphics hardware. */
+	DRM_MEMORYBARRIER();
+
+	/* Coming from user space. Don't know if the Xserver has
+	 * emitted wait commands. Assuming the worst. */
+	dev_priv->waiting = 1;
+
+	i = 0;
+	first_draw_cmd = NULL;
+	while (i < cmdbuf.size) {
+		drm_savage_cmd_header_t cmd_header;
+		cmd_header = *(drm_savage_cmd_header_t *)cmdbuf.cmd_addr;
+		cmdbuf.cmd_addr++;
+		i++;
+
+		/* Group drawing commands with same state to minimize
+		 * iterations over clip rects. */
+		j = 0;
+		switch (cmd_header.cmd.cmd) {
+		case SAVAGE_CMD_DMA_IDX:
+		case SAVAGE_CMD_VB_IDX:
+			j = (cmd_header.idx.count + 3) / 4;
+			if (i + j > cmdbuf.size) {
+				DRM_ERROR("indexed drawing command extends "
+					  "beyond end of command buffer\n");
+				DMA_FLUSH();
+				return DRM_ERR(EINVAL);
+			}
+			/* fall through */
+		case SAVAGE_CMD_DMA_PRIM:
+		case SAVAGE_CMD_VB_PRIM:
+			if (!first_draw_cmd)
+				first_draw_cmd = cmdbuf.cmd_addr-1;
+			cmdbuf.cmd_addr += j;
+			i += j;
+			break;
+		default:
+			if (first_draw_cmd) {
+				ret = savage_dispatch_draw (
+					dev_priv, first_draw_cmd,
+					cmdbuf.cmd_addr-1,
+					dmabuf, cmdbuf.vb_addr, cmdbuf.vb_size,
+					cmdbuf.vb_stride,
+					cmdbuf.nbox, cmdbuf.box_addr);
+				if (ret != 0)
+					return ret;
+				first_draw_cmd = NULL;
+			}
+		}
+		if (first_draw_cmd)
+			continue;
+
+		switch (cmd_header.cmd.cmd) {
+		case SAVAGE_CMD_STATE:
+			j = (cmd_header.state.count + 1) / 2;
+			if (i + j > cmdbuf.size) {
+				DRM_ERROR("command SAVAGE_CMD_STATE extends "
+					  "beyond end of command buffer\n");
+				DMA_FLUSH();
+				ret = DRM_ERR(EINVAL);
+				goto done;
+			}
+			ret = savage_dispatch_state(dev_priv, &cmd_header,
+				(const uint32_t *)cmdbuf.cmd_addr);
+			cmdbuf.cmd_addr += j;
+			i += j;
+			break;
+		case SAVAGE_CMD_CLEAR:
+			if (i + 1 > cmdbuf.size) {
+				DRM_ERROR("command SAVAGE_CMD_CLEAR extends "
+					  "beyond end of command buffer\n");
+				DMA_FLUSH();
+				ret = DRM_ERR(EINVAL);
+				goto done;
+			}
+			ret = savage_dispatch_clear(dev_priv, &cmd_header,
+						    cmdbuf.cmd_addr,
+						    cmdbuf.nbox, cmdbuf.box_addr);
+			cmdbuf.cmd_addr++;
+			i++;
+			break;
+		case SAVAGE_CMD_SWAP:
+			ret = savage_dispatch_swap(dev_priv, cmdbuf.nbox,
+						   cmdbuf.box_addr);
+			break;
+		default:
+			DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd);
+			DMA_FLUSH();
+			ret = DRM_ERR(EINVAL);
+			goto done;
+		}
+
+		if (ret != 0) {
+			DMA_FLUSH();
+			goto done;
+		}
+	}
+
+	if (first_draw_cmd) {
+		ret = savage_dispatch_draw (
+			dev_priv, first_draw_cmd, cmdbuf.cmd_addr, dmabuf,
+			cmdbuf.vb_addr, cmdbuf.vb_size, cmdbuf.vb_stride,
+			cmdbuf.nbox, cmdbuf.box_addr);
+		if (ret != 0) {
+			DMA_FLUSH();
+			goto done;
+		}
+	}
+
+	DMA_FLUSH();
+
+	if (dmabuf && cmdbuf.discard) {
+		drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private;
+		uint16_t event;
+		event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
+		SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
+		savage_freelist_put(dev, dmabuf);
+	}
+
+done:
+	/* If we didn't need to allocate them, these'll be NULL */
+	drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
+	drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER);
+	drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t),
+		 DRM_MEM_DRIVER);
+
+	return ret;
+}
--- libdrm-2.3.0.orig/shared-core/mga_ucode.h
+++ libdrm-2.3.0/shared-core/mga_ucode.h
@@ -0,0 +1,11645 @@
+/* mga_ucode.h -- Matrox G200/G400 WARP engine microcode -*- linux-c -*-
+ * Created: Thu Jan 11 21:20:43 2001 by gareth@valinux.com
+ *
+ * Copyright 1999 Matrox Graphics Inc.
+ * 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 shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS 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
+ * MATROX GRAPHICS INC., OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Kernel-based WARP engine management:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * WARP pipes are named according to the functions they perform, where:
+ *
+ *   - T stands for computation of texture stage 0
+ *   - T2 stands for computation of both texture stage 0 and texture stage 1
+ *   - G stands for computation of triangle intensity (Gouraud interpolation)
+ *   - Z stands for computation of Z buffer interpolation
+ *   - S stands for computation of specular highlight
+ *   - A stands for computation of the alpha channel
+ *   - F stands for computation of vertex fog interpolation
+ */
+
+static unsigned char warp_g200_tgz[] = {
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x98, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x81, 0x04,
+	0x89, 0x04,
+	0x01, 0x04,
+	0x09, 0x04,
+
+	0xC9, 0x41, 0xC0, 0xEC,
+	0x11, 0x04,
+	0x00, 0xE0,
+
+	0x41, 0xCC, 0x41, 0xCD,
+	0x49, 0xCC, 0x49, 0xCD,
+
+	0xD1, 0x41, 0xC0, 0xEC,
+	0x51, 0xCC, 0x51, 0xCD,
+
+	0x80, 0x04,
+	0x10, 0x04,
+	0x08, 0x04,
+	0x00, 0xE0,
+
+	0x00, 0xCC, 0xC0, 0xCD,
+	0xD1, 0x49, 0xC0, 0xEC,
+
+	0x8A, 0x1F, 0x20, 0xE9,
+	0x8B, 0x3F, 0x20, 0xE9,
+
+	0x41, 0x3C, 0x41, 0xAD,
+	0x49, 0x3C, 0x49, 0xAD,
+
+	0x10, 0xCC, 0x10, 0xCD,
+	0x08, 0xCC, 0x08, 0xCD,
+
+	0xB9, 0x41, 0x49, 0xBB,
+	0x1F, 0xF0, 0x41, 0xCD,
+
+	0x51, 0x3C, 0x51, 0xAD,
+	0x00, 0x98, 0x80, 0xE9,
+
+	0x72, 0x80, 0x07, 0xEA,
+	0x24, 0x1F, 0x20, 0xE9,
+
+	0x15, 0x41, 0x49, 0xBD,
+	0x1D, 0x41, 0x51, 0xBD,
+
+	0x2E, 0x41, 0x2A, 0xB8,
+	0x34, 0x53, 0xA0, 0xE8,
+
+	0x15, 0x30,
+	0x1D, 0x30,
+	0x58, 0xE3,
+	0x00, 0xE0,
+
+	0xB5, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x24, 0x43, 0xA0, 0xE8,
+	0x2C, 0x4B, 0xA0, 0xE8,
+
+	0x15, 0x72,
+	0x09, 0xE3,
+	0x00, 0xE0,
+	0x1D, 0x72,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0x97, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6C, 0x64, 0xC8, 0xEC,
+	0x98, 0xE1,
+	0xB5, 0x05,
+
+	0xBD, 0x05,
+	0x2E, 0x30,
+	0x32, 0xC0, 0xA0, 0xE8,
+
+	0x33, 0xC0, 0xA0, 0xE8,
+	0x74, 0x64, 0xC8, 0xEC,
+
+	0x40, 0x3C, 0x40, 0xAD,
+	0x32, 0x6A,
+	0x2A, 0x30,
+
+	0x20, 0x73,
+	0x33, 0x6A,
+	0x00, 0xE0,
+	0x28, 0x73,
+
+	0x1C, 0x72,
+	0x83, 0xE2,
+	0x60, 0x80, 0x15, 0xEA,
+
+	0xB8, 0x3D, 0x28, 0xDF,
+	0x30, 0x35, 0x20, 0xDF,
+
+	0x40, 0x30,
+	0x00, 0xE0,
+	0xCC, 0xE2,
+	0x64, 0x72,
+
+	0x25, 0x42, 0x52, 0xBF,
+	0x2D, 0x42, 0x4A, 0xBF,
+
+	0x30, 0x2E, 0x30, 0xDF,
+	0x38, 0x2E, 0x38, 0xDF,
+
+	0x18, 0x1D, 0x45, 0xE9,
+	0x1E, 0x15, 0x45, 0xE9,
+
+	0x2B, 0x49, 0x51, 0xBD,
+	0x00, 0xE0,
+	0x1F, 0x73,
+
+	0x38, 0x38, 0x40, 0xAF,
+	0x30, 0x30, 0x40, 0xAF,
+
+	0x24, 0x1F, 0x24, 0xDF,
+	0x1D, 0x32, 0x20, 0xE9,
+
+	0x2C, 0x1F, 0x2C, 0xDF,
+	0x1A, 0x33, 0x20, 0xE9,
+
+	0xB0, 0x10,
+	0x08, 0xE3,
+	0x40, 0x10,
+	0xB8, 0x10,
+
+	0x26, 0xF0, 0x30, 0xCD,
+	0x2F, 0xF0, 0x38, 0xCD,
+
+	0x2B, 0x80, 0x20, 0xE9,
+	0x2A, 0x80, 0x20, 0xE9,
+
+	0xA6, 0x20,
+	0x88, 0xE2,
+	0x00, 0xE0,
+	0xAF, 0x20,
+
+	0x28, 0x2A, 0x26, 0xAF,
+	0x20, 0x2A, 0xC0, 0xAF,
+
+	0x34, 0x1F, 0x34, 0xDF,
+	0x46, 0x24, 0x46, 0xDF,
+
+	0x28, 0x30, 0x80, 0xBF,
+	0x20, 0x38, 0x80, 0xBF,
+
+	0x47, 0x24, 0x47, 0xDF,
+	0x4E, 0x2C, 0x4E, 0xDF,
+
+	0x4F, 0x2C, 0x4F, 0xDF,
+	0x56, 0x34, 0x56, 0xDF,
+
+	0x28, 0x15, 0x28, 0xDF,
+	0x20, 0x1D, 0x20, 0xDF,
+
+	0x57, 0x34, 0x57, 0xDF,
+	0x00, 0xE0,
+	0x1D, 0x05,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x89, 0xE2,
+	0x2B, 0x30,
+
+	0x3F, 0xC1, 0x1D, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x68,
+	0xBF, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x20, 0xC0, 0x20, 0xAF,
+	0x28, 0x05,
+	0x97, 0x74,
+
+	0x00, 0xE0,
+	0x2A, 0x10,
+	0x16, 0xC0, 0x20, 0xE9,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x8C, 0xE2,
+	0x95, 0x05,
+
+	0x28, 0xC1, 0x28, 0xAD,
+	0x1F, 0xC1, 0x15, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA8, 0x67,
+	0x9F, 0x6B,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x28, 0xC0, 0x28, 0xAD,
+	0x1D, 0x25,
+	0x20, 0x05,
+
+	0x28, 0x32, 0x80, 0xAD,
+	0x40, 0x2A, 0x40, 0xBD,
+
+	0x1C, 0x80, 0x20, 0xE9,
+	0x20, 0x33, 0x20, 0xAD,
+
+	0x20, 0x73,
+	0x00, 0xE0,
+	0xB6, 0x49, 0x51, 0xBB,
+
+	0x26, 0x2F, 0xB0, 0xE8,
+	0x19, 0x20, 0x20, 0xE9,
+
+	0x35, 0x20, 0x35, 0xDF,
+	0x3D, 0x20, 0x3D, 0xDF,
+
+	0x15, 0x20, 0x15, 0xDF,
+	0x1D, 0x20, 0x1D, 0xDF,
+
+	0x26, 0xD0, 0x26, 0xCD,
+	0x29, 0x49, 0x2A, 0xB8,
+
+	0x26, 0x40, 0x80, 0xBD,
+	0x3B, 0x48, 0x50, 0xBD,
+
+	0x3E, 0x54, 0x57, 0x9F,
+	0x00, 0xE0,
+	0x82, 0xE1,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x26, 0x30,
+	0x29, 0x30,
+	0x48, 0x3C, 0x48, 0xAD,
+
+	0x2B, 0x72,
+	0xC2, 0xE1,
+	0x2C, 0xC0, 0x44, 0xC2,
+
+	0x05, 0x24, 0x34, 0xBF,
+	0x0D, 0x24, 0x2C, 0xBF,
+
+	0x2D, 0x46, 0x4E, 0xBF,
+	0x25, 0x46, 0x56, 0xBF,
+
+	0x20, 0x1D, 0x6F, 0x8F,
+	0x32, 0x3E, 0x5F, 0xE9,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x30,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x33, 0x1E, 0x5F, 0xE9,
+
+	0x05, 0x44, 0x54, 0xB2,
+	0x0D, 0x44, 0x4C, 0xB2,
+
+	0x19, 0xC0, 0xB0, 0xE8,
+	0x34, 0xC0, 0x44, 0xC4,
+
+	0x33, 0x73,
+	0x00, 0xE0,
+	0x3E, 0x62, 0x57, 0x9F,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0xE0,
+	0x0D, 0x20,
+
+	0x84, 0x3E, 0x58, 0xE9,
+	0x28, 0x1D, 0x6F, 0x8F,
+
+	0x05, 0x20,
+	0x00, 0xE0,
+	0x85, 0x1E, 0x58, 0xE9,
+
+	0x9B, 0x3B, 0x33, 0xDF,
+	0x20, 0x20, 0x42, 0xAF,
+
+	0x30, 0x42, 0x56, 0x9F,
+	0x80, 0x3E, 0x57, 0xE9,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x30, 0x80, 0x5F, 0xE9,
+
+	0x28, 0x28, 0x24, 0xAF,
+	0x81, 0x1E, 0x57, 0xE9,
+
+	0x05, 0x47, 0x57, 0xBF,
+	0x0D, 0x47, 0x4F, 0xBF,
+
+	0x88, 0x80, 0x58, 0xE9,
+	0x1B, 0x29, 0x1B, 0xDF,
+
+	0x30, 0x1D, 0x6F, 0x8F,
+	0x3A, 0x30, 0x4F, 0xE9,
+
+	0x1C, 0x30, 0x26, 0xDF,
+	0x09, 0xE3,
+	0x3B, 0x05,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x3B, 0x3F, 0x4F, 0xE9,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x00, 0xE0,
+	0xAC, 0x20,
+
+	0x2D, 0x44, 0x4C, 0xB4,
+	0x2C, 0x1C, 0xC0, 0xAF,
+
+	0x25, 0x44, 0x54, 0xB4,
+	0x00, 0xE0,
+	0xC8, 0x30,
+
+	0x30, 0x46, 0x30, 0xAF,
+	0x1B, 0x1B, 0x48, 0xAF,
+
+	0x00, 0xE0,
+	0x25, 0x20,
+	0x38, 0x2C, 0x4F, 0xE9,
+
+	0x86, 0x80, 0x57, 0xE9,
+	0x38, 0x1D, 0x6F, 0x8F,
+
+	0x28, 0x74,
+	0x00, 0xE0,
+	0x0D, 0x44, 0x4C, 0xB0,
+
+	0x05, 0x44, 0x54, 0xB0,
+	0x2D, 0x20,
+	0x9B, 0x10,
+
+	0x82, 0x3E, 0x57, 0xE9,
+	0x32, 0xF0, 0x1B, 0xCD,
+
+	0x1E, 0xBD, 0x59, 0x9F,
+	0x83, 0x1E, 0x57, 0xE9,
+
+	0x38, 0x47, 0x38, 0xAF,
+	0x34, 0x20,
+	0x2A, 0x30,
+
+	0x00, 0xE0,
+	0x0D, 0x20,
+	0x32, 0x20,
+	0x05, 0x20,
+
+	0x87, 0x80, 0x57, 0xE9,
+	0x1F, 0x54, 0x57, 0x9F,
+
+	0x17, 0x42, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x6A,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x37, 0x1E, 0x4F, 0xE9,
+
+	0x37, 0x32, 0x2A, 0xAF,
+	0x00, 0xE0,
+	0x32, 0x00,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x27, 0xC0, 0x44, 0xC0,
+
+	0x36, 0x1F, 0x4F, 0xE9,
+	0x1F, 0x1F, 0x26, 0xDF,
+
+	0x37, 0x1B, 0x37, 0xBF,
+	0x17, 0x26, 0x17, 0xDF,
+
+	0x3E, 0x17, 0x4F, 0xE9,
+	0x3F, 0x3F, 0x4F, 0xE9,
+
+	0x34, 0x1F, 0x34, 0xAF,
+	0x2B, 0x05,
+	0xA7, 0x20,
+
+	0x33, 0x2B, 0x37, 0xDF,
+	0x27, 0x17, 0xC0, 0xAF,
+
+	0x34, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x03, 0x80, 0x0A, 0xEA,
+	0x17, 0xC1, 0x2B, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xB3, 0x68,
+	0x97, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0xC0, 0x33, 0xAF,
+	0x3C, 0x27, 0x4F, 0xE9,
+
+	0x57, 0x39, 0x20, 0xE9,
+	0x28, 0x19, 0x60, 0xEC,
+
+	0x2B, 0x32, 0x20, 0xE9,
+	0x1D, 0x3B, 0x20, 0xE9,
+
+	0xB3, 0x05,
+	0x00, 0xE0,
+	0x16, 0x28, 0x20, 0xE9,
+
+	0x23, 0x3B, 0x33, 0xAD,
+	0x1E, 0x2B, 0x20, 0xE9,
+
+	0x1C, 0x80, 0x20, 0xE9,
+	0x57, 0x36, 0x20, 0xE9,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x90, 0xE2,
+	0x00, 0xE0,
+
+	0x85, 0xFF, 0x20, 0xEA,
+	0x19, 0xC8, 0xC1, 0xCD,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x9F, 0x41, 0x49, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x41, 0x49, 0xBD,
+	0x2D, 0x41, 0x51, 0xBD,
+
+	0x0D, 0x80, 0x07, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x35, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x25, 0x30,
+	0x2D, 0x30,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0xA7, 0x5B, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x84, 0xFF, 0x0A, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC9, 0x41, 0xC8, 0xEC,
+	0x42, 0xE1,
+	0x00, 0xE0,
+
+	0x82, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC8, 0x40, 0xC0, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x7F, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgza[] = {
+
+	0x00, 0x98, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x81, 0x04,
+	0x89, 0x04,
+	0x01, 0x04,
+	0x09, 0x04,
+
+	0xC9, 0x41, 0xC0, 0xEC,
+	0x11, 0x04,
+	0x00, 0xE0,
+
+	0x41, 0xCC, 0x41, 0xCD,
+	0x49, 0xCC, 0x49, 0xCD,
+
+	0xD1, 0x41, 0xC0, 0xEC,
+	0x51, 0xCC, 0x51, 0xCD,
+
+	0x80, 0x04,
+	0x10, 0x04,
+	0x08, 0x04,
+	0x00, 0xE0,
+
+	0x00, 0xCC, 0xC0, 0xCD,
+	0xD1, 0x49, 0xC0, 0xEC,
+
+	0x8A, 0x1F, 0x20, 0xE9,
+	0x8B, 0x3F, 0x20, 0xE9,
+
+	0x41, 0x3C, 0x41, 0xAD,
+	0x49, 0x3C, 0x49, 0xAD,
+
+	0x10, 0xCC, 0x10, 0xCD,
+	0x08, 0xCC, 0x08, 0xCD,
+
+	0xB9, 0x41, 0x49, 0xBB,
+	0x1F, 0xF0, 0x41, 0xCD,
+
+	0x51, 0x3C, 0x51, 0xAD,
+	0x00, 0x98, 0x80, 0xE9,
+
+	0x7D, 0x80, 0x07, 0xEA,
+	0x24, 0x1F, 0x20, 0xE9,
+
+	0x15, 0x41, 0x49, 0xBD,
+	0x1D, 0x41, 0x51, 0xBD,
+
+	0x2E, 0x41, 0x2A, 0xB8,
+	0x34, 0x53, 0xA0, 0xE8,
+
+	0x15, 0x30,
+	0x1D, 0x30,
+	0x58, 0xE3,
+	0x00, 0xE0,
+
+	0xB5, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x24, 0x43, 0xA0, 0xE8,
+	0x2C, 0x4B, 0xA0, 0xE8,
+
+	0x15, 0x72,
+	0x09, 0xE3,
+	0x00, 0xE0,
+	0x1D, 0x72,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0x97, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6C, 0x64, 0xC8, 0xEC,
+	0x98, 0xE1,
+	0xB5, 0x05,
+
+	0xBD, 0x05,
+	0x2E, 0x30,
+	0x32, 0xC0, 0xA0, 0xE8,
+
+	0x33, 0xC0, 0xA0, 0xE8,
+	0x74, 0x64, 0xC8, 0xEC,
+
+	0x40, 0x3C, 0x40, 0xAD,
+	0x32, 0x6A,
+	0x2A, 0x30,
+
+	0x20, 0x73,
+	0x33, 0x6A,
+	0x00, 0xE0,
+	0x28, 0x73,
+
+	0x1C, 0x72,
+	0x83, 0xE2,
+	0x6B, 0x80, 0x15, 0xEA,
+
+	0xB8, 0x3D, 0x28, 0xDF,
+	0x30, 0x35, 0x20, 0xDF,
+
+	0x40, 0x30,
+	0x00, 0xE0,
+	0xCC, 0xE2,
+	0x64, 0x72,
+
+	0x25, 0x42, 0x52, 0xBF,
+	0x2D, 0x42, 0x4A, 0xBF,
+
+	0x30, 0x2E, 0x30, 0xDF,
+	0x38, 0x2E, 0x38, 0xDF,
+
+	0x18, 0x1D, 0x45, 0xE9,
+	0x1E, 0x15, 0x45, 0xE9,
+
+	0x2B, 0x49, 0x51, 0xBD,
+	0x00, 0xE0,
+	0x1F, 0x73,
+
+	0x38, 0x38, 0x40, 0xAF,
+	0x30, 0x30, 0x40, 0xAF,
+
+	0x24, 0x1F, 0x24, 0xDF,
+	0x1D, 0x32, 0x20, 0xE9,
+
+	0x2C, 0x1F, 0x2C, 0xDF,
+	0x1A, 0x33, 0x20, 0xE9,
+
+	0xB0, 0x10,
+	0x08, 0xE3,
+	0x40, 0x10,
+	0xB8, 0x10,
+
+	0x26, 0xF0, 0x30, 0xCD,
+	0x2F, 0xF0, 0x38, 0xCD,
+
+	0x2B, 0x80, 0x20, 0xE9,
+	0x2A, 0x80, 0x20, 0xE9,
+
+	0xA6, 0x20,
+	0x88, 0xE2,
+	0x00, 0xE0,
+	0xAF, 0x20,
+
+	0x28, 0x2A, 0x26, 0xAF,
+	0x20, 0x2A, 0xC0, 0xAF,
+
+	0x34, 0x1F, 0x34, 0xDF,
+	0x46, 0x24, 0x46, 0xDF,
+
+	0x28, 0x30, 0x80, 0xBF,
+	0x20, 0x38, 0x80, 0xBF,
+
+	0x47, 0x24, 0x47, 0xDF,
+	0x4E, 0x2C, 0x4E, 0xDF,
+
+	0x4F, 0x2C, 0x4F, 0xDF,
+	0x56, 0x34, 0x56, 0xDF,
+
+	0x28, 0x15, 0x28, 0xDF,
+	0x20, 0x1D, 0x20, 0xDF,
+
+	0x57, 0x34, 0x57, 0xDF,
+	0x00, 0xE0,
+	0x1D, 0x05,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x89, 0xE2,
+	0x2B, 0x30,
+
+	0x3F, 0xC1, 0x1D, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x68,
+	0xBF, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x20, 0xC0, 0x20, 0xAF,
+	0x28, 0x05,
+	0x97, 0x74,
+
+	0x00, 0xE0,
+	0x2A, 0x10,
+	0x16, 0xC0, 0x20, 0xE9,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x8C, 0xE2,
+	0x95, 0x05,
+
+	0x28, 0xC1, 0x28, 0xAD,
+	0x1F, 0xC1, 0x15, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA8, 0x67,
+	0x9F, 0x6B,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x28, 0xC0, 0x28, 0xAD,
+	0x1D, 0x25,
+	0x20, 0x05,
+
+	0x28, 0x32, 0x80, 0xAD,
+	0x40, 0x2A, 0x40, 0xBD,
+
+	0x1C, 0x80, 0x20, 0xE9,
+	0x20, 0x33, 0x20, 0xAD,
+
+	0x20, 0x73,
+	0x00, 0xE0,
+	0xB6, 0x49, 0x51, 0xBB,
+
+	0x26, 0x2F, 0xB0, 0xE8,
+	0x19, 0x20, 0x20, 0xE9,
+
+	0x35, 0x20, 0x35, 0xDF,
+	0x3D, 0x20, 0x3D, 0xDF,
+
+	0x15, 0x20, 0x15, 0xDF,
+	0x1D, 0x20, 0x1D, 0xDF,
+
+	0x26, 0xD0, 0x26, 0xCD,
+	0x29, 0x49, 0x2A, 0xB8,
+
+	0x26, 0x40, 0x80, 0xBD,
+	0x3B, 0x48, 0x50, 0xBD,
+
+	0x3E, 0x54, 0x57, 0x9F,
+	0x00, 0xE0,
+	0x82, 0xE1,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x26, 0x30,
+	0x29, 0x30,
+	0x48, 0x3C, 0x48, 0xAD,
+
+	0x2B, 0x72,
+	0xC2, 0xE1,
+	0x2C, 0xC0, 0x44, 0xC2,
+
+	0x05, 0x24, 0x34, 0xBF,
+	0x0D, 0x24, 0x2C, 0xBF,
+
+	0x2D, 0x46, 0x4E, 0xBF,
+	0x25, 0x46, 0x56, 0xBF,
+
+	0x20, 0x1D, 0x6F, 0x8F,
+	0x32, 0x3E, 0x5F, 0xE9,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x30,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x33, 0x1E, 0x5F, 0xE9,
+
+	0x05, 0x44, 0x54, 0xB2,
+	0x0D, 0x44, 0x4C, 0xB2,
+
+	0x19, 0xC0, 0xB0, 0xE8,
+	0x34, 0xC0, 0x44, 0xC4,
+
+	0x33, 0x73,
+	0x00, 0xE0,
+	0x3E, 0x62, 0x57, 0x9F,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0xE0,
+	0x0D, 0x20,
+
+	0x84, 0x3E, 0x58, 0xE9,
+	0x28, 0x1D, 0x6F, 0x8F,
+
+	0x05, 0x20,
+	0x00, 0xE0,
+	0x85, 0x1E, 0x58, 0xE9,
+
+	0x9B, 0x3B, 0x33, 0xDF,
+	0x20, 0x20, 0x42, 0xAF,
+
+	0x30, 0x42, 0x56, 0x9F,
+	0x80, 0x3E, 0x57, 0xE9,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x30, 0x80, 0x5F, 0xE9,
+
+	0x28, 0x28, 0x24, 0xAF,
+	0x81, 0x1E, 0x57, 0xE9,
+
+	0x05, 0x47, 0x57, 0xBF,
+	0x0D, 0x47, 0x4F, 0xBF,
+
+	0x88, 0x80, 0x58, 0xE9,
+	0x1B, 0x29, 0x1B, 0xDF,
+
+	0x30, 0x1D, 0x6F, 0x8F,
+	0x3A, 0x30, 0x4F, 0xE9,
+
+	0x1C, 0x30, 0x26, 0xDF,
+	0x09, 0xE3,
+	0x3B, 0x05,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x3B, 0x3F, 0x4F, 0xE9,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x00, 0xE0,
+	0xAC, 0x20,
+
+	0x2D, 0x44, 0x4C, 0xB4,
+	0x2C, 0x1C, 0xC0, 0xAF,
+
+	0x25, 0x44, 0x54, 0xB4,
+	0x00, 0xE0,
+	0xC8, 0x30,
+
+	0x30, 0x46, 0x30, 0xAF,
+	0x1B, 0x1B, 0x48, 0xAF,
+
+	0x00, 0xE0,
+	0x25, 0x20,
+	0x38, 0x2C, 0x4F, 0xE9,
+
+	0x86, 0x80, 0x57, 0xE9,
+	0x38, 0x1D, 0x6F, 0x8F,
+
+	0x28, 0x74,
+	0x00, 0xE0,
+	0x0D, 0x44, 0x4C, 0xB0,
+
+	0x05, 0x44, 0x54, 0xB0,
+	0x2D, 0x20,
+	0x9B, 0x10,
+
+	0x82, 0x3E, 0x57, 0xE9,
+	0x32, 0xF0, 0x1B, 0xCD,
+
+	0x1E, 0xBD, 0x59, 0x9F,
+	0x83, 0x1E, 0x57, 0xE9,
+
+	0x38, 0x47, 0x38, 0xAF,
+	0x34, 0x20,
+	0x2A, 0x30,
+
+	0x00, 0xE0,
+	0x0D, 0x20,
+	0x32, 0x20,
+	0x05, 0x20,
+
+	0x87, 0x80, 0x57, 0xE9,
+	0x1F, 0x54, 0x57, 0x9F,
+
+	0x17, 0x42, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x6A,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x37, 0x1E, 0x4F, 0xE9,
+
+	0x37, 0x32, 0x2A, 0xAF,
+	0x00, 0xE0,
+	0x32, 0x00,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x27, 0xC0, 0x44, 0xC0,
+
+	0x36, 0x1F, 0x4F, 0xE9,
+	0x1F, 0x1F, 0x26, 0xDF,
+
+	0x37, 0x1B, 0x37, 0xBF,
+	0x17, 0x26, 0x17, 0xDF,
+
+	0x3E, 0x17, 0x4F, 0xE9,
+	0x3F, 0x3F, 0x4F, 0xE9,
+
+	0x34, 0x1F, 0x34, 0xAF,
+	0x2B, 0x05,
+	0xA7, 0x20,
+
+	0x33, 0x2B, 0x37, 0xDF,
+	0x27, 0x17, 0xC0, 0xAF,
+
+	0x34, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x2D, 0x44, 0x4C, 0xB6,
+	0x25, 0x44, 0x54, 0xB6,
+
+	0x03, 0x80, 0x2A, 0xEA,
+	0x17, 0xC1, 0x2B, 0xBD,
+
+	0x2D, 0x20,
+	0x25, 0x20,
+	0x07, 0xC0, 0x44, 0xC6,
+
+	0xB3, 0x68,
+	0x97, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0xC0, 0x33, 0xAF,
+	0x3C, 0x27, 0x4F, 0xE9,
+
+	0x1F, 0x62, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x3F, 0x3D, 0x5D, 0x9F,
+	0x00, 0xE0,
+	0x07, 0x20,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x28, 0x19, 0x60, 0xEC,
+
+	0xB3, 0x05,
+	0x00, 0xE0,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x23, 0x3B, 0x33, 0xAD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1F, 0x26, 0x1F, 0xDF,
+	0x9D, 0x1F, 0x4F, 0xE9,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x9E, 0x3F, 0x4F, 0xE9,
+
+	0x07, 0x07, 0x1F, 0xAF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x9C, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x57, 0x39, 0x20, 0xE9,
+
+	0x16, 0x28, 0x20, 0xE9,
+	0x1D, 0x3B, 0x20, 0xE9,
+
+	0x1E, 0x2B, 0x20, 0xE9,
+	0x2B, 0x32, 0x20, 0xE9,
+
+	0x1C, 0x23, 0x20, 0xE9,
+	0x57, 0x36, 0x20, 0xE9,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x90, 0xE2,
+	0x00, 0xE0,
+
+	0x7A, 0xFF, 0x20, 0xEA,
+	0x19, 0xC8, 0xC1, 0xCD,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x9F, 0x41, 0x49, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x41, 0x49, 0xBD,
+	0x2D, 0x41, 0x51, 0xBD,
+
+	0x0D, 0x80, 0x07, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x35, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x25, 0x30,
+	0x2D, 0x30,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0xA7, 0x5B, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x79, 0xFF, 0x0A, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC9, 0x41, 0xC8, 0xEC,
+	0x42, 0xE1,
+	0x00, 0xE0,
+
+	0x77, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC8, 0x40, 0xC0, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x74, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzaf[] = {
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x98, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x81, 0x04,
+	0x89, 0x04,
+	0x01, 0x04,
+	0x09, 0x04,
+
+	0xC9, 0x41, 0xC0, 0xEC,
+	0x11, 0x04,
+	0x00, 0xE0,
+
+	0x41, 0xCC, 0x41, 0xCD,
+	0x49, 0xCC, 0x49, 0xCD,
+
+	0xD1, 0x41, 0xC0, 0xEC,
+	0x51, 0xCC, 0x51, 0xCD,
+
+	0x80, 0x04,
+	0x10, 0x04,
+	0x08, 0x04,
+	0x00, 0xE0,
+
+	0x00, 0xCC, 0xC0, 0xCD,
+	0xD1, 0x49, 0xC0, 0xEC,
+
+	0x8A, 0x1F, 0x20, 0xE9,
+	0x8B, 0x3F, 0x20, 0xE9,
+
+	0x41, 0x3C, 0x41, 0xAD,
+	0x49, 0x3C, 0x49, 0xAD,
+
+	0x10, 0xCC, 0x10, 0xCD,
+	0x08, 0xCC, 0x08, 0xCD,
+
+	0xB9, 0x41, 0x49, 0xBB,
+	0x1F, 0xF0, 0x41, 0xCD,
+
+	0x51, 0x3C, 0x51, 0xAD,
+	0x00, 0x98, 0x80, 0xE9,
+
+	0x83, 0x80, 0x07, 0xEA,
+	0x24, 0x1F, 0x20, 0xE9,
+
+	0x21, 0x45, 0x80, 0xE8,
+	0x1A, 0x4D, 0x80, 0xE8,
+
+	0x31, 0x55, 0x80, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0x41, 0x49, 0xBD,
+	0x1D, 0x41, 0x51, 0xBD,
+
+	0x2E, 0x41, 0x2A, 0xB8,
+	0x34, 0x53, 0xA0, 0xE8,
+
+	0x15, 0x30,
+	0x1D, 0x30,
+	0x58, 0xE3,
+	0x00, 0xE0,
+
+	0xB5, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x24, 0x43, 0xA0, 0xE8,
+	0x2C, 0x4B, 0xA0, 0xE8,
+
+	0x15, 0x72,
+	0x09, 0xE3,
+	0x00, 0xE0,
+	0x1D, 0x72,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0x97, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6C, 0x64, 0xC8, 0xEC,
+	0x98, 0xE1,
+	0xB5, 0x05,
+
+	0xBD, 0x05,
+	0x2E, 0x30,
+	0x32, 0xC0, 0xA0, 0xE8,
+
+	0x33, 0xC0, 0xA0, 0xE8,
+	0x74, 0x64, 0xC8, 0xEC,
+
+	0x40, 0x3C, 0x40, 0xAD,
+	0x32, 0x6A,
+	0x2A, 0x30,
+
+	0x20, 0x73,
+	0x33, 0x6A,
+	0x00, 0xE0,
+	0x28, 0x73,
+
+	0x1C, 0x72,
+	0x83, 0xE2,
+	0x6F, 0x80, 0x15, 0xEA,
+
+	0xB8, 0x3D, 0x28, 0xDF,
+	0x30, 0x35, 0x20, 0xDF,
+
+	0x40, 0x30,
+	0x00, 0xE0,
+	0xCC, 0xE2,
+	0x64, 0x72,
+
+	0x25, 0x42, 0x52, 0xBF,
+	0x2D, 0x42, 0x4A, 0xBF,
+
+	0x30, 0x2E, 0x30, 0xDF,
+	0x38, 0x2E, 0x38, 0xDF,
+
+	0x18, 0x1D, 0x45, 0xE9,
+	0x1E, 0x15, 0x45, 0xE9,
+
+	0x2B, 0x49, 0x51, 0xBD,
+	0x00, 0xE0,
+	0x1F, 0x73,
+
+	0x38, 0x38, 0x40, 0xAF,
+	0x30, 0x30, 0x40, 0xAF,
+
+	0x24, 0x1F, 0x24, 0xDF,
+	0x1D, 0x32, 0x20, 0xE9,
+
+	0x2C, 0x1F, 0x2C, 0xDF,
+	0x1A, 0x33, 0x20, 0xE9,
+
+	0xB0, 0x10,
+	0x08, 0xE3,
+	0x40, 0x10,
+	0xB8, 0x10,
+
+	0x26, 0xF0, 0x30, 0xCD,
+	0x2F, 0xF0, 0x38, 0xCD,
+
+	0x2B, 0x80, 0x20, 0xE9,
+	0x2A, 0x80, 0x20, 0xE9,
+
+	0xA6, 0x20,
+	0x88, 0xE2,
+	0x00, 0xE0,
+	0xAF, 0x20,
+
+	0x28, 0x2A, 0x26, 0xAF,
+	0x20, 0x2A, 0xC0, 0xAF,
+
+	0x34, 0x1F, 0x34, 0xDF,
+	0x46, 0x24, 0x46, 0xDF,
+
+	0x28, 0x30, 0x80, 0xBF,
+	0x20, 0x38, 0x80, 0xBF,
+
+	0x47, 0x24, 0x47, 0xDF,
+	0x4E, 0x2C, 0x4E, 0xDF,
+
+	0x4F, 0x2C, 0x4F, 0xDF,
+	0x56, 0x34, 0x56, 0xDF,
+
+	0x28, 0x15, 0x28, 0xDF,
+	0x20, 0x1D, 0x20, 0xDF,
+
+	0x57, 0x34, 0x57, 0xDF,
+	0x00, 0xE0,
+	0x1D, 0x05,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x89, 0xE2,
+	0x2B, 0x30,
+
+	0x3F, 0xC1, 0x1D, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x68,
+	0xBF, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x20, 0xC0, 0x20, 0xAF,
+	0x28, 0x05,
+	0x97, 0x74,
+
+	0x00, 0xE0,
+	0x2A, 0x10,
+	0x16, 0xC0, 0x20, 0xE9,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x8C, 0xE2,
+	0x95, 0x05,
+
+	0x28, 0xC1, 0x28, 0xAD,
+	0x1F, 0xC1, 0x15, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA8, 0x67,
+	0x9F, 0x6B,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x28, 0xC0, 0x28, 0xAD,
+	0x1D, 0x25,
+	0x20, 0x05,
+
+	0x28, 0x32, 0x80, 0xAD,
+	0x40, 0x2A, 0x40, 0xBD,
+
+	0x1C, 0x80, 0x20, 0xE9,
+	0x20, 0x33, 0x20, 0xAD,
+
+	0x20, 0x73,
+	0x00, 0xE0,
+	0xB6, 0x49, 0x51, 0xBB,
+
+	0x26, 0x2F, 0xB0, 0xE8,
+	0x19, 0x20, 0x20, 0xE9,
+
+	0x35, 0x20, 0x35, 0xDF,
+	0x3D, 0x20, 0x3D, 0xDF,
+
+	0x15, 0x20, 0x15, 0xDF,
+	0x1D, 0x20, 0x1D, 0xDF,
+
+	0x26, 0xD0, 0x26, 0xCD,
+	0x29, 0x49, 0x2A, 0xB8,
+
+	0x26, 0x40, 0x80, 0xBD,
+	0x3B, 0x48, 0x50, 0xBD,
+
+	0x3E, 0x54, 0x57, 0x9F,
+	0x00, 0xE0,
+	0x82, 0xE1,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x26, 0x30,
+	0x29, 0x30,
+	0x48, 0x3C, 0x48, 0xAD,
+
+	0x2B, 0x72,
+	0xC2, 0xE1,
+	0x2C, 0xC0, 0x44, 0xC2,
+
+	0x05, 0x24, 0x34, 0xBF,
+	0x0D, 0x24, 0x2C, 0xBF,
+
+	0x2D, 0x46, 0x4E, 0xBF,
+	0x25, 0x46, 0x56, 0xBF,
+
+	0x20, 0x1D, 0x6F, 0x8F,
+	0x32, 0x3E, 0x5F, 0xE9,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x30,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x33, 0x1E, 0x5F, 0xE9,
+
+	0x05, 0x44, 0x54, 0xB2,
+	0x0D, 0x44, 0x4C, 0xB2,
+
+	0x19, 0xC0, 0xB0, 0xE8,
+	0x34, 0xC0, 0x44, 0xC4,
+
+	0x33, 0x73,
+	0x00, 0xE0,
+	0x3E, 0x62, 0x57, 0x9F,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0xE0,
+	0x0D, 0x20,
+
+	0x84, 0x3E, 0x58, 0xE9,
+	0x28, 0x1D, 0x6F, 0x8F,
+
+	0x05, 0x20,
+	0x00, 0xE0,
+	0x85, 0x1E, 0x58, 0xE9,
+
+	0x9B, 0x3B, 0x33, 0xDF,
+	0x20, 0x20, 0x42, 0xAF,
+
+	0x30, 0x42, 0x56, 0x9F,
+	0x80, 0x3E, 0x57, 0xE9,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x30, 0x80, 0x5F, 0xE9,
+
+	0x28, 0x28, 0x24, 0xAF,
+	0x81, 0x1E, 0x57, 0xE9,
+
+	0x05, 0x47, 0x57, 0xBF,
+	0x0D, 0x47, 0x4F, 0xBF,
+
+	0x88, 0x80, 0x58, 0xE9,
+	0x1B, 0x29, 0x1B, 0xDF,
+
+	0x30, 0x1D, 0x6F, 0x8F,
+	0x3A, 0x30, 0x4F, 0xE9,
+
+	0x1C, 0x30, 0x26, 0xDF,
+	0x09, 0xE3,
+	0x3B, 0x05,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x3B, 0x3F, 0x4F, 0xE9,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x00, 0xE0,
+	0xAC, 0x20,
+
+	0x2D, 0x44, 0x4C, 0xB4,
+	0x2C, 0x1C, 0xC0, 0xAF,
+
+	0x25, 0x44, 0x54, 0xB4,
+	0x00, 0xE0,
+	0xC8, 0x30,
+
+	0x30, 0x46, 0x30, 0xAF,
+	0x1B, 0x1B, 0x48, 0xAF,
+
+	0x00, 0xE0,
+	0x25, 0x20,
+	0x38, 0x2C, 0x4F, 0xE9,
+
+	0x86, 0x80, 0x57, 0xE9,
+	0x38, 0x1D, 0x6F, 0x8F,
+
+	0x28, 0x74,
+	0x00, 0xE0,
+	0x0D, 0x44, 0x4C, 0xB0,
+
+	0x05, 0x44, 0x54, 0xB0,
+	0x2D, 0x20,
+	0x9B, 0x10,
+
+	0x82, 0x3E, 0x57, 0xE9,
+	0x32, 0xF0, 0x1B, 0xCD,
+
+	0x1E, 0xBD, 0x59, 0x9F,
+	0x83, 0x1E, 0x57, 0xE9,
+
+	0x38, 0x47, 0x38, 0xAF,
+	0x34, 0x20,
+	0x2A, 0x30,
+
+	0x00, 0xE0,
+	0x0D, 0x20,
+	0x32, 0x20,
+	0x05, 0x20,
+
+	0x87, 0x80, 0x57, 0xE9,
+	0x1F, 0x54, 0x57, 0x9F,
+
+	0x17, 0x42, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x6A,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x37, 0x1E, 0x4F, 0xE9,
+
+	0x37, 0x32, 0x2A, 0xAF,
+	0x00, 0xE0,
+	0x32, 0x00,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x27, 0xC0, 0x44, 0xC0,
+
+	0x36, 0x1F, 0x4F, 0xE9,
+	0x1F, 0x1F, 0x26, 0xDF,
+
+	0x37, 0x1B, 0x37, 0xBF,
+	0x17, 0x26, 0x17, 0xDF,
+
+	0x3E, 0x17, 0x4F, 0xE9,
+	0x3F, 0x3F, 0x4F, 0xE9,
+
+	0x34, 0x1F, 0x34, 0xAF,
+	0x2B, 0x05,
+	0xA7, 0x20,
+
+	0x33, 0x2B, 0x37, 0xDF,
+	0x27, 0x17, 0xC0, 0xAF,
+
+	0x34, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0D, 0x21, 0x1A, 0xB6,
+	0x05, 0x21, 0x31, 0xB6,
+
+	0x2D, 0x44, 0x4C, 0xB6,
+	0x25, 0x44, 0x54, 0xB6,
+
+	0x03, 0x80, 0x2A, 0xEA,
+	0x17, 0xC1, 0x2B, 0xBD,
+
+	0x0D, 0x20,
+	0x05, 0x20,
+	0x2F, 0xC0, 0x21, 0xC6,
+
+	0xB3, 0x68,
+	0x97, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0xC0, 0x33, 0xAF,
+	0x3C, 0x27, 0x4F, 0xE9,
+
+	0x00, 0xE0,
+	0x25, 0x20,
+	0x07, 0xC0, 0x44, 0xC6,
+
+	0x17, 0x50, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x2D, 0x20,
+
+	0x37, 0x0F, 0x5C, 0x9F,
+	0x00, 0xE0,
+	0x2F, 0x20,
+
+	0x1F, 0x62, 0x57, 0x9F,
+	0x00, 0xE0,
+	0x07, 0x20,
+
+	0x3F, 0x3D, 0x5D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x28, 0x19, 0x60, 0xEC,
+
+	0xB3, 0x05,
+	0x00, 0xE0,
+	0x17, 0x26, 0x17, 0xDF,
+
+	0x23, 0x3B, 0x33, 0xAD,
+	0x35, 0x17, 0x4F, 0xE9,
+
+	0x1F, 0x26, 0x1F, 0xDF,
+	0x9D, 0x1F, 0x4F, 0xE9,
+
+	0x9E, 0x3F, 0x4F, 0xE9,
+	0x39, 0x37, 0x4F, 0xE9,
+
+	0x2F, 0x2F, 0x17, 0xAF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x07, 0x07, 0x1F, 0xAF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x31, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x9C, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x57, 0x39, 0x20, 0xE9,
+
+	0x16, 0x28, 0x20, 0xE9,
+	0x1D, 0x3B, 0x20, 0xE9,
+
+	0x1E, 0x2B, 0x20, 0xE9,
+	0x2B, 0x32, 0x20, 0xE9,
+
+	0x1C, 0x23, 0x20, 0xE9,
+	0x57, 0x36, 0x20, 0xE9,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x90, 0xE2,
+	0x00, 0xE0,
+
+	0x74, 0xFF, 0x20, 0xEA,
+	0x19, 0xC8, 0xC1, 0xCD,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x9F, 0x41, 0x49, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x41, 0x49, 0xBD,
+	0x2D, 0x41, 0x51, 0xBD,
+
+	0x0D, 0x80, 0x07, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x35, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x25, 0x30,
+	0x2D, 0x30,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0xA7, 0x5B, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x73, 0xFF, 0x0A, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC9, 0x41, 0xC8, 0xEC,
+	0x42, 0xE1,
+	0x00, 0xE0,
+
+	0x71, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC8, 0x40, 0xC0, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6E, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzf[] = {
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x98, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x81, 0x04,
+	0x89, 0x04,
+	0x01, 0x04,
+	0x09, 0x04,
+
+	0xC9, 0x41, 0xC0, 0xEC,
+	0x11, 0x04,
+	0x00, 0xE0,
+
+	0x41, 0xCC, 0x41, 0xCD,
+	0x49, 0xCC, 0x49, 0xCD,
+
+	0xD1, 0x41, 0xC0, 0xEC,
+	0x51, 0xCC, 0x51, 0xCD,
+
+	0x80, 0x04,
+	0x10, 0x04,
+	0x08, 0x04,
+	0x00, 0xE0,
+
+	0x00, 0xCC, 0xC0, 0xCD,
+	0xD1, 0x49, 0xC0, 0xEC,
+
+	0x8A, 0x1F, 0x20, 0xE9,
+	0x8B, 0x3F, 0x20, 0xE9,
+
+	0x41, 0x3C, 0x41, 0xAD,
+	0x49, 0x3C, 0x49, 0xAD,
+
+	0x10, 0xCC, 0x10, 0xCD,
+	0x08, 0xCC, 0x08, 0xCD,
+
+	0xB9, 0x41, 0x49, 0xBB,
+	0x1F, 0xF0, 0x41, 0xCD,
+
+	0x51, 0x3C, 0x51, 0xAD,
+	0x00, 0x98, 0x80, 0xE9,
+
+	0x7F, 0x80, 0x07, 0xEA,
+	0x24, 0x1F, 0x20, 0xE9,
+
+	0x21, 0x45, 0x80, 0xE8,
+	0x1A, 0x4D, 0x80, 0xE8,
+
+	0x31, 0x55, 0x80, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0x41, 0x49, 0xBD,
+	0x1D, 0x41, 0x51, 0xBD,
+
+	0x2E, 0x41, 0x2A, 0xB8,
+	0x34, 0x53, 0xA0, 0xE8,
+
+	0x15, 0x30,
+	0x1D, 0x30,
+	0x58, 0xE3,
+	0x00, 0xE0,
+
+	0xB5, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x24, 0x43, 0xA0, 0xE8,
+	0x2C, 0x4B, 0xA0, 0xE8,
+
+	0x15, 0x72,
+	0x09, 0xE3,
+	0x00, 0xE0,
+	0x1D, 0x72,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0x97, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6C, 0x64, 0xC8, 0xEC,
+	0x98, 0xE1,
+	0xB5, 0x05,
+
+	0xBD, 0x05,
+	0x2E, 0x30,
+	0x32, 0xC0, 0xA0, 0xE8,
+
+	0x33, 0xC0, 0xA0, 0xE8,
+	0x74, 0x64, 0xC8, 0xEC,
+
+	0x40, 0x3C, 0x40, 0xAD,
+	0x32, 0x6A,
+	0x2A, 0x30,
+
+	0x20, 0x73,
+	0x33, 0x6A,
+	0x00, 0xE0,
+	0x28, 0x73,
+
+	0x1C, 0x72,
+	0x83, 0xE2,
+	0x6B, 0x80, 0x15, 0xEA,
+
+	0xB8, 0x3D, 0x28, 0xDF,
+	0x30, 0x35, 0x20, 0xDF,
+
+	0x40, 0x30,
+	0x00, 0xE0,
+	0xCC, 0xE2,
+	0x64, 0x72,
+
+	0x25, 0x42, 0x52, 0xBF,
+	0x2D, 0x42, 0x4A, 0xBF,
+
+	0x30, 0x2E, 0x30, 0xDF,
+	0x38, 0x2E, 0x38, 0xDF,
+
+	0x18, 0x1D, 0x45, 0xE9,
+	0x1E, 0x15, 0x45, 0xE9,
+
+	0x2B, 0x49, 0x51, 0xBD,
+	0x00, 0xE0,
+	0x1F, 0x73,
+
+	0x38, 0x38, 0x40, 0xAF,
+	0x30, 0x30, 0x40, 0xAF,
+
+	0x24, 0x1F, 0x24, 0xDF,
+	0x1D, 0x32, 0x20, 0xE9,
+
+	0x2C, 0x1F, 0x2C, 0xDF,
+	0x1A, 0x33, 0x20, 0xE9,
+
+	0xB0, 0x10,
+	0x08, 0xE3,
+	0x40, 0x10,
+	0xB8, 0x10,
+
+	0x26, 0xF0, 0x30, 0xCD,
+	0x2F, 0xF0, 0x38, 0xCD,
+
+	0x2B, 0x80, 0x20, 0xE9,
+	0x2A, 0x80, 0x20, 0xE9,
+
+	0xA6, 0x20,
+	0x88, 0xE2,
+	0x00, 0xE0,
+	0xAF, 0x20,
+
+	0x28, 0x2A, 0x26, 0xAF,
+	0x20, 0x2A, 0xC0, 0xAF,
+
+	0x34, 0x1F, 0x34, 0xDF,
+	0x46, 0x24, 0x46, 0xDF,
+
+	0x28, 0x30, 0x80, 0xBF,
+	0x20, 0x38, 0x80, 0xBF,
+
+	0x47, 0x24, 0x47, 0xDF,
+	0x4E, 0x2C, 0x4E, 0xDF,
+
+	0x4F, 0x2C, 0x4F, 0xDF,
+	0x56, 0x34, 0x56, 0xDF,
+
+	0x28, 0x15, 0x28, 0xDF,
+	0x20, 0x1D, 0x20, 0xDF,
+
+	0x57, 0x34, 0x57, 0xDF,
+	0x00, 0xE0,
+	0x1D, 0x05,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x89, 0xE2,
+	0x2B, 0x30,
+
+	0x3F, 0xC1, 0x1D, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x68,
+	0xBF, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x20, 0xC0, 0x20, 0xAF,
+	0x28, 0x05,
+	0x97, 0x74,
+
+	0x00, 0xE0,
+	0x2A, 0x10,
+	0x16, 0xC0, 0x20, 0xE9,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x8C, 0xE2,
+	0x95, 0x05,
+
+	0x28, 0xC1, 0x28, 0xAD,
+	0x1F, 0xC1, 0x15, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA8, 0x67,
+	0x9F, 0x6B,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x28, 0xC0, 0x28, 0xAD,
+	0x1D, 0x25,
+	0x20, 0x05,
+
+	0x28, 0x32, 0x80, 0xAD,
+	0x40, 0x2A, 0x40, 0xBD,
+
+	0x1C, 0x80, 0x20, 0xE9,
+	0x20, 0x33, 0x20, 0xAD,
+
+	0x20, 0x73,
+	0x00, 0xE0,
+	0xB6, 0x49, 0x51, 0xBB,
+
+	0x26, 0x2F, 0xB0, 0xE8,
+	0x19, 0x20, 0x20, 0xE9,
+
+	0x35, 0x20, 0x35, 0xDF,
+	0x3D, 0x20, 0x3D, 0xDF,
+
+	0x15, 0x20, 0x15, 0xDF,
+	0x1D, 0x20, 0x1D, 0xDF,
+
+	0x26, 0xD0, 0x26, 0xCD,
+	0x29, 0x49, 0x2A, 0xB8,
+
+	0x26, 0x40, 0x80, 0xBD,
+	0x3B, 0x48, 0x50, 0xBD,
+
+	0x3E, 0x54, 0x57, 0x9F,
+	0x00, 0xE0,
+	0x82, 0xE1,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x26, 0x30,
+	0x29, 0x30,
+	0x48, 0x3C, 0x48, 0xAD,
+
+	0x2B, 0x72,
+	0xC2, 0xE1,
+	0x2C, 0xC0, 0x44, 0xC2,
+
+	0x05, 0x24, 0x34, 0xBF,
+	0x0D, 0x24, 0x2C, 0xBF,
+
+	0x2D, 0x46, 0x4E, 0xBF,
+	0x25, 0x46, 0x56, 0xBF,
+
+	0x20, 0x1D, 0x6F, 0x8F,
+	0x32, 0x3E, 0x5F, 0xE9,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x30,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x33, 0x1E, 0x5F, 0xE9,
+
+	0x05, 0x44, 0x54, 0xB2,
+	0x0D, 0x44, 0x4C, 0xB2,
+
+	0x19, 0xC0, 0xB0, 0xE8,
+	0x34, 0xC0, 0x44, 0xC4,
+
+	0x33, 0x73,
+	0x00, 0xE0,
+	0x3E, 0x62, 0x57, 0x9F,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0xE0,
+	0x0D, 0x20,
+
+	0x84, 0x3E, 0x58, 0xE9,
+	0x28, 0x1D, 0x6F, 0x8F,
+
+	0x05, 0x20,
+	0x00, 0xE0,
+	0x85, 0x1E, 0x58, 0xE9,
+
+	0x9B, 0x3B, 0x33, 0xDF,
+	0x20, 0x20, 0x42, 0xAF,
+
+	0x30, 0x42, 0x56, 0x9F,
+	0x80, 0x3E, 0x57, 0xE9,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x30, 0x80, 0x5F, 0xE9,
+
+	0x28, 0x28, 0x24, 0xAF,
+	0x81, 0x1E, 0x57, 0xE9,
+
+	0x05, 0x47, 0x57, 0xBF,
+	0x0D, 0x47, 0x4F, 0xBF,
+
+	0x88, 0x80, 0x58, 0xE9,
+	0x1B, 0x29, 0x1B, 0xDF,
+
+	0x30, 0x1D, 0x6F, 0x8F,
+	0x3A, 0x30, 0x4F, 0xE9,
+
+	0x1C, 0x30, 0x26, 0xDF,
+	0x09, 0xE3,
+	0x3B, 0x05,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x3B, 0x3F, 0x4F, 0xE9,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x00, 0xE0,
+	0xAC, 0x20,
+
+	0x2D, 0x44, 0x4C, 0xB4,
+	0x2C, 0x1C, 0xC0, 0xAF,
+
+	0x25, 0x44, 0x54, 0xB4,
+	0x00, 0xE0,
+	0xC8, 0x30,
+
+	0x30, 0x46, 0x30, 0xAF,
+	0x1B, 0x1B, 0x48, 0xAF,
+
+	0x00, 0xE0,
+	0x25, 0x20,
+	0x38, 0x2C, 0x4F, 0xE9,
+
+	0x86, 0x80, 0x57, 0xE9,
+	0x38, 0x1D, 0x6F, 0x8F,
+
+	0x28, 0x74,
+	0x00, 0xE0,
+	0x0D, 0x44, 0x4C, 0xB0,
+
+	0x05, 0x44, 0x54, 0xB0,
+	0x2D, 0x20,
+	0x9B, 0x10,
+
+	0x82, 0x3E, 0x57, 0xE9,
+	0x32, 0xF0, 0x1B, 0xCD,
+
+	0x1E, 0xBD, 0x59, 0x9F,
+	0x83, 0x1E, 0x57, 0xE9,
+
+	0x38, 0x47, 0x38, 0xAF,
+	0x34, 0x20,
+	0x2A, 0x30,
+
+	0x00, 0xE0,
+	0x0D, 0x20,
+	0x32, 0x20,
+	0x05, 0x20,
+
+	0x87, 0x80, 0x57, 0xE9,
+	0x1F, 0x54, 0x57, 0x9F,
+
+	0x17, 0x42, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x6A,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x37, 0x1E, 0x4F, 0xE9,
+
+	0x37, 0x32, 0x2A, 0xAF,
+	0x00, 0xE0,
+	0x32, 0x00,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x27, 0xC0, 0x44, 0xC0,
+
+	0x36, 0x1F, 0x4F, 0xE9,
+	0x1F, 0x1F, 0x26, 0xDF,
+
+	0x37, 0x1B, 0x37, 0xBF,
+	0x17, 0x26, 0x17, 0xDF,
+
+	0x3E, 0x17, 0x4F, 0xE9,
+	0x3F, 0x3F, 0x4F, 0xE9,
+
+	0x34, 0x1F, 0x34, 0xAF,
+	0x2B, 0x05,
+	0xA7, 0x20,
+
+	0x33, 0x2B, 0x37, 0xDF,
+	0x27, 0x17, 0xC0, 0xAF,
+
+	0x34, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0D, 0x21, 0x1A, 0xB6,
+	0x05, 0x21, 0x31, 0xB6,
+
+	0x03, 0x80, 0x2A, 0xEA,
+	0x17, 0xC1, 0x2B, 0xBD,
+
+	0x0D, 0x20,
+	0x05, 0x20,
+	0x2F, 0xC0, 0x21, 0xC6,
+
+	0xB3, 0x68,
+	0x97, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0xC0, 0x33, 0xAF,
+	0x3C, 0x27, 0x4F, 0xE9,
+
+	0x17, 0x50, 0x56, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x37, 0x0F, 0x5C, 0x9F,
+	0x00, 0xE0,
+	0x2F, 0x20,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x28, 0x19, 0x60, 0xEC,
+
+	0xB3, 0x05,
+	0x00, 0xE0,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x23, 0x3B, 0x33, 0xAD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x17, 0x26, 0x17, 0xDF,
+	0x35, 0x17, 0x4F, 0xE9,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x39, 0x37, 0x4F, 0xE9,
+
+	0x2F, 0x2F, 0x17, 0xAF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x31, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x57, 0x39, 0x20, 0xE9,
+
+	0x16, 0x28, 0x20, 0xE9,
+	0x1D, 0x3B, 0x20, 0xE9,
+
+	0x1E, 0x2B, 0x20, 0xE9,
+	0x2B, 0x32, 0x20, 0xE9,
+
+	0x1C, 0x23, 0x20, 0xE9,
+	0x57, 0x36, 0x20, 0xE9,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x90, 0xE2,
+	0x00, 0xE0,
+
+	0x78, 0xFF, 0x20, 0xEA,
+	0x19, 0xC8, 0xC1, 0xCD,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x9F, 0x41, 0x49, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x41, 0x49, 0xBD,
+	0x2D, 0x41, 0x51, 0xBD,
+
+	0x0D, 0x80, 0x07, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x35, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x25, 0x30,
+	0x2D, 0x30,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0xA7, 0x5B, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x77, 0xFF, 0x0A, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC9, 0x41, 0xC8, 0xEC,
+	0x42, 0xE1,
+	0x00, 0xE0,
+
+	0x75, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC8, 0x40, 0xC0, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x72, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzs[] = {
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x98, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x81, 0x04,
+	0x89, 0x04,
+	0x01, 0x04,
+	0x09, 0x04,
+
+	0xC9, 0x41, 0xC0, 0xEC,
+	0x11, 0x04,
+	0x00, 0xE0,
+
+	0x41, 0xCC, 0x41, 0xCD,
+	0x49, 0xCC, 0x49, 0xCD,
+
+	0xD1, 0x41, 0xC0, 0xEC,
+	0x51, 0xCC, 0x51, 0xCD,
+
+	0x80, 0x04,
+	0x10, 0x04,
+	0x08, 0x04,
+	0x00, 0xE0,
+
+	0x00, 0xCC, 0xC0, 0xCD,
+	0xD1, 0x49, 0xC0, 0xEC,
+
+	0x8A, 0x1F, 0x20, 0xE9,
+	0x8B, 0x3F, 0x20, 0xE9,
+
+	0x41, 0x3C, 0x41, 0xAD,
+	0x49, 0x3C, 0x49, 0xAD,
+
+	0x10, 0xCC, 0x10, 0xCD,
+	0x08, 0xCC, 0x08, 0xCD,
+
+	0xB9, 0x41, 0x49, 0xBB,
+	0x1F, 0xF0, 0x41, 0xCD,
+
+	0x51, 0x3C, 0x51, 0xAD,
+	0x00, 0x98, 0x80, 0xE9,
+
+	0x8B, 0x80, 0x07, 0xEA,
+	0x24, 0x1F, 0x20, 0xE9,
+
+	0x21, 0x45, 0x80, 0xE8,
+	0x1A, 0x4D, 0x80, 0xE8,
+
+	0x31, 0x55, 0x80, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0x41, 0x49, 0xBD,
+	0x1D, 0x41, 0x51, 0xBD,
+
+	0x2E, 0x41, 0x2A, 0xB8,
+	0x34, 0x53, 0xA0, 0xE8,
+
+	0x15, 0x30,
+	0x1D, 0x30,
+	0x58, 0xE3,
+	0x00, 0xE0,
+
+	0xB5, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x24, 0x43, 0xA0, 0xE8,
+	0x2C, 0x4B, 0xA0, 0xE8,
+
+	0x15, 0x72,
+	0x09, 0xE3,
+	0x00, 0xE0,
+	0x1D, 0x72,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0x97, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6C, 0x64, 0xC8, 0xEC,
+	0x98, 0xE1,
+	0xB5, 0x05,
+
+	0xBD, 0x05,
+	0x2E, 0x30,
+	0x32, 0xC0, 0xA0, 0xE8,
+
+	0x33, 0xC0, 0xA0, 0xE8,
+	0x74, 0x64, 0xC8, 0xEC,
+
+	0x40, 0x3C, 0x40, 0xAD,
+	0x32, 0x6A,
+	0x2A, 0x30,
+
+	0x20, 0x73,
+	0x33, 0x6A,
+	0x00, 0xE0,
+	0x28, 0x73,
+
+	0x1C, 0x72,
+	0x83, 0xE2,
+	0x77, 0x80, 0x15, 0xEA,
+
+	0xB8, 0x3D, 0x28, 0xDF,
+	0x30, 0x35, 0x20, 0xDF,
+
+	0x40, 0x30,
+	0x00, 0xE0,
+	0xCC, 0xE2,
+	0x64, 0x72,
+
+	0x25, 0x42, 0x52, 0xBF,
+	0x2D, 0x42, 0x4A, 0xBF,
+
+	0x30, 0x2E, 0x30, 0xDF,
+	0x38, 0x2E, 0x38, 0xDF,
+
+	0x18, 0x1D, 0x45, 0xE9,
+	0x1E, 0x15, 0x45, 0xE9,
+
+	0x2B, 0x49, 0x51, 0xBD,
+	0x00, 0xE0,
+	0x1F, 0x73,
+
+	0x38, 0x38, 0x40, 0xAF,
+	0x30, 0x30, 0x40, 0xAF,
+
+	0x24, 0x1F, 0x24, 0xDF,
+	0x1D, 0x32, 0x20, 0xE9,
+
+	0x2C, 0x1F, 0x2C, 0xDF,
+	0x1A, 0x33, 0x20, 0xE9,
+
+	0xB0, 0x10,
+	0x08, 0xE3,
+	0x40, 0x10,
+	0xB8, 0x10,
+
+	0x26, 0xF0, 0x30, 0xCD,
+	0x2F, 0xF0, 0x38, 0xCD,
+
+	0x2B, 0x80, 0x20, 0xE9,
+	0x2A, 0x80, 0x20, 0xE9,
+
+	0xA6, 0x20,
+	0x88, 0xE2,
+	0x00, 0xE0,
+	0xAF, 0x20,
+
+	0x28, 0x2A, 0x26, 0xAF,
+	0x20, 0x2A, 0xC0, 0xAF,
+
+	0x34, 0x1F, 0x34, 0xDF,
+	0x46, 0x24, 0x46, 0xDF,
+
+	0x28, 0x30, 0x80, 0xBF,
+	0x20, 0x38, 0x80, 0xBF,
+
+	0x47, 0x24, 0x47, 0xDF,
+	0x4E, 0x2C, 0x4E, 0xDF,
+
+	0x4F, 0x2C, 0x4F, 0xDF,
+	0x56, 0x34, 0x56, 0xDF,
+
+	0x28, 0x15, 0x28, 0xDF,
+	0x20, 0x1D, 0x20, 0xDF,
+
+	0x57, 0x34, 0x57, 0xDF,
+	0x00, 0xE0,
+	0x1D, 0x05,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x89, 0xE2,
+	0x2B, 0x30,
+
+	0x3F, 0xC1, 0x1D, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x68,
+	0xBF, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x20, 0xC0, 0x20, 0xAF,
+	0x28, 0x05,
+	0x97, 0x74,
+
+	0x00, 0xE0,
+	0x2A, 0x10,
+	0x16, 0xC0, 0x20, 0xE9,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x8C, 0xE2,
+	0x95, 0x05,
+
+	0x28, 0xC1, 0x28, 0xAD,
+	0x1F, 0xC1, 0x15, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA8, 0x67,
+	0x9F, 0x6B,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x28, 0xC0, 0x28, 0xAD,
+	0x1D, 0x25,
+	0x20, 0x05,
+
+	0x28, 0x32, 0x80, 0xAD,
+	0x40, 0x2A, 0x40, 0xBD,
+
+	0x1C, 0x80, 0x20, 0xE9,
+	0x20, 0x33, 0x20, 0xAD,
+
+	0x20, 0x73,
+	0x00, 0xE0,
+	0xB6, 0x49, 0x51, 0xBB,
+
+	0x26, 0x2F, 0xB0, 0xE8,
+	0x19, 0x20, 0x20, 0xE9,
+
+	0x35, 0x20, 0x35, 0xDF,
+	0x3D, 0x20, 0x3D, 0xDF,
+
+	0x15, 0x20, 0x15, 0xDF,
+	0x1D, 0x20, 0x1D, 0xDF,
+
+	0x26, 0xD0, 0x26, 0xCD,
+	0x29, 0x49, 0x2A, 0xB8,
+
+	0x26, 0x40, 0x80, 0xBD,
+	0x3B, 0x48, 0x50, 0xBD,
+
+	0x3E, 0x54, 0x57, 0x9F,
+	0x00, 0xE0,
+	0x82, 0xE1,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x26, 0x30,
+	0x29, 0x30,
+	0x48, 0x3C, 0x48, 0xAD,
+
+	0x2B, 0x72,
+	0xC2, 0xE1,
+	0x2C, 0xC0, 0x44, 0xC2,
+
+	0x05, 0x24, 0x34, 0xBF,
+	0x0D, 0x24, 0x2C, 0xBF,
+
+	0x2D, 0x46, 0x4E, 0xBF,
+	0x25, 0x46, 0x56, 0xBF,
+
+	0x20, 0x1D, 0x6F, 0x8F,
+	0x32, 0x3E, 0x5F, 0xE9,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x30,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x33, 0x1E, 0x5F, 0xE9,
+
+	0x05, 0x44, 0x54, 0xB2,
+	0x0D, 0x44, 0x4C, 0xB2,
+
+	0x19, 0xC0, 0xB0, 0xE8,
+	0x34, 0xC0, 0x44, 0xC4,
+
+	0x33, 0x73,
+	0x00, 0xE0,
+	0x3E, 0x62, 0x57, 0x9F,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0xE0,
+	0x0D, 0x20,
+
+	0x84, 0x3E, 0x58, 0xE9,
+	0x28, 0x1D, 0x6F, 0x8F,
+
+	0x05, 0x20,
+	0x00, 0xE0,
+	0x85, 0x1E, 0x58, 0xE9,
+
+	0x9B, 0x3B, 0x33, 0xDF,
+	0x20, 0x20, 0x42, 0xAF,
+
+	0x30, 0x42, 0x56, 0x9F,
+	0x80, 0x3E, 0x57, 0xE9,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x30, 0x80, 0x5F, 0xE9,
+
+	0x28, 0x28, 0x24, 0xAF,
+	0x81, 0x1E, 0x57, 0xE9,
+
+	0x05, 0x47, 0x57, 0xBF,
+	0x0D, 0x47, 0x4F, 0xBF,
+
+	0x88, 0x80, 0x58, 0xE9,
+	0x1B, 0x29, 0x1B, 0xDF,
+
+	0x30, 0x1D, 0x6F, 0x8F,
+	0x3A, 0x30, 0x4F, 0xE9,
+
+	0x1C, 0x30, 0x26, 0xDF,
+	0x09, 0xE3,
+	0x3B, 0x05,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x3B, 0x3F, 0x4F, 0xE9,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x00, 0xE0,
+	0xAC, 0x20,
+
+	0x2D, 0x44, 0x4C, 0xB4,
+	0x2C, 0x1C, 0xC0, 0xAF,
+
+	0x25, 0x44, 0x54, 0xB4,
+	0x00, 0xE0,
+	0xC8, 0x30,
+
+	0x30, 0x46, 0x30, 0xAF,
+	0x1B, 0x1B, 0x48, 0xAF,
+
+	0x00, 0xE0,
+	0x25, 0x20,
+	0x38, 0x2C, 0x4F, 0xE9,
+
+	0x86, 0x80, 0x57, 0xE9,
+	0x38, 0x1D, 0x6F, 0x8F,
+
+	0x28, 0x74,
+	0x00, 0xE0,
+	0x0D, 0x44, 0x4C, 0xB0,
+
+	0x05, 0x44, 0x54, 0xB0,
+	0x2D, 0x20,
+	0x9B, 0x10,
+
+	0x82, 0x3E, 0x57, 0xE9,
+	0x32, 0xF0, 0x1B, 0xCD,
+
+	0x1E, 0xBD, 0x59, 0x9F,
+	0x83, 0x1E, 0x57, 0xE9,
+
+	0x38, 0x47, 0x38, 0xAF,
+	0x34, 0x20,
+	0x2A, 0x30,
+
+	0x00, 0xE0,
+	0x0D, 0x20,
+	0x32, 0x20,
+	0x05, 0x20,
+
+	0x87, 0x80, 0x57, 0xE9,
+	0x1F, 0x54, 0x57, 0x9F,
+
+	0x17, 0x42, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x6A,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x37, 0x1E, 0x4F, 0xE9,
+
+	0x37, 0x32, 0x2A, 0xAF,
+	0x00, 0xE0,
+	0x32, 0x00,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x27, 0xC0, 0x44, 0xC0,
+
+	0x36, 0x1F, 0x4F, 0xE9,
+	0x1F, 0x1F, 0x26, 0xDF,
+
+	0x37, 0x1B, 0x37, 0xBF,
+	0x17, 0x26, 0x17, 0xDF,
+
+	0x3E, 0x17, 0x4F, 0xE9,
+	0x3F, 0x3F, 0x4F, 0xE9,
+
+	0x34, 0x1F, 0x34, 0xAF,
+	0x2B, 0x05,
+	0xA7, 0x20,
+
+	0x33, 0x2B, 0x37, 0xDF,
+	0x27, 0x17, 0xC0, 0xAF,
+
+	0x34, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x2D, 0x21, 0x1A, 0xB0,
+	0x25, 0x21, 0x31, 0xB0,
+
+	0x0D, 0x21, 0x1A, 0xB2,
+	0x05, 0x21, 0x31, 0xB2,
+
+	0x03, 0x80, 0x2A, 0xEA,
+	0x17, 0xC1, 0x2B, 0xBD,
+
+	0x2D, 0x20,
+	0x25, 0x20,
+	0x05, 0x20,
+	0x0D, 0x20,
+
+	0xB3, 0x68,
+	0x97, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0xC0, 0x33, 0xAF,
+	0x2F, 0xC0, 0x21, 0xC0,
+
+	0x16, 0x42, 0x56, 0x9F,
+	0x3C, 0x27, 0x4F, 0xE9,
+
+	0x1E, 0x62, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x21, 0x31, 0xB4,
+	0x2D, 0x21, 0x1A, 0xB4,
+
+	0x3F, 0x2F, 0x5D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0x05,
+	0x00, 0xE0,
+	0x28, 0x19, 0x60, 0xEC,
+
+	0x37, 0x0F, 0x5C, 0x9F,
+	0x00, 0xE0,
+	0x2F, 0x20,
+
+	0x23, 0x3B, 0x33, 0xAD,
+	0x1E, 0x26, 0x1E, 0xDF,
+
+	0xA7, 0x1E, 0x4F, 0xE9,
+	0x17, 0x26, 0x16, 0xDF,
+
+	0x2D, 0x20,
+	0x00, 0xE0,
+	0xA8, 0x3F, 0x4F, 0xE9,
+
+	0x2F, 0x2F, 0x1E, 0xAF,
+	0x25, 0x20,
+	0x00, 0xE0,
+
+	0xA4, 0x16, 0x4F, 0xE9,
+	0x0F, 0xC0, 0x21, 0xC2,
+
+	0xA6, 0x80, 0x4F, 0xE9,
+	0x1F, 0x62, 0x57, 0x9F,
+
+	0x3F, 0x2F, 0x5D, 0x9F,
+	0x00, 0xE0,
+	0x8F, 0x20,
+
+	0xA5, 0x37, 0x4F, 0xE9,
+	0x0F, 0x17, 0x0F, 0xAF,
+
+	0x06, 0xC0, 0x21, 0xC4,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0xA3, 0x80, 0x4F, 0xE9,
+
+	0x06, 0x20,
+	0x00, 0xE0,
+	0x1F, 0x26, 0x1F, 0xDF,
+
+	0xA1, 0x1F, 0x4F, 0xE9,
+	0xA2, 0x3F, 0x4F, 0xE9,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x06, 0x06, 0x1F, 0xAF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x57, 0x39, 0x20, 0xE9,
+
+	0x16, 0x28, 0x20, 0xE9,
+	0x1D, 0x3B, 0x20, 0xE9,
+
+	0x1E, 0x2B, 0x20, 0xE9,
+	0x2B, 0x32, 0x20, 0xE9,
+
+	0x1C, 0x23, 0x20, 0xE9,
+	0x57, 0x36, 0x20, 0xE9,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x90, 0xE2,
+	0x00, 0xE0,
+
+	0x6C, 0xFF, 0x20, 0xEA,
+	0x19, 0xC8, 0xC1, 0xCD,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x9F, 0x41, 0x49, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x41, 0x49, 0xBD,
+	0x2D, 0x41, 0x51, 0xBD,
+
+	0x0D, 0x80, 0x07, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x35, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x25, 0x30,
+	0x2D, 0x30,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0xA7, 0x5B, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6B, 0xFF, 0x0A, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC9, 0x41, 0xC8, 0xEC,
+	0x42, 0xE1,
+	0x00, 0xE0,
+
+	0x69, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC8, 0x40, 0xC0, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x66, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsa[] = {
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x98, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x81, 0x04,
+	0x89, 0x04,
+	0x01, 0x04,
+	0x09, 0x04,
+
+	0xC9, 0x41, 0xC0, 0xEC,
+	0x11, 0x04,
+	0x00, 0xE0,
+
+	0x41, 0xCC, 0x41, 0xCD,
+	0x49, 0xCC, 0x49, 0xCD,
+
+	0xD1, 0x41, 0xC0, 0xEC,
+	0x51, 0xCC, 0x51, 0xCD,
+
+	0x80, 0x04,
+	0x10, 0x04,
+	0x08, 0x04,
+	0x00, 0xE0,
+
+	0x00, 0xCC, 0xC0, 0xCD,
+	0xD1, 0x49, 0xC0, 0xEC,
+
+	0x8A, 0x1F, 0x20, 0xE9,
+	0x8B, 0x3F, 0x20, 0xE9,
+
+	0x41, 0x3C, 0x41, 0xAD,
+	0x49, 0x3C, 0x49, 0xAD,
+
+	0x10, 0xCC, 0x10, 0xCD,
+	0x08, 0xCC, 0x08, 0xCD,
+
+	0xB9, 0x41, 0x49, 0xBB,
+	0x1F, 0xF0, 0x41, 0xCD,
+
+	0x51, 0x3C, 0x51, 0xAD,
+	0x00, 0x98, 0x80, 0xE9,
+
+	0x8F, 0x80, 0x07, 0xEA,
+	0x24, 0x1F, 0x20, 0xE9,
+
+	0x21, 0x45, 0x80, 0xE8,
+	0x1A, 0x4D, 0x80, 0xE8,
+
+	0x31, 0x55, 0x80, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0x41, 0x49, 0xBD,
+	0x1D, 0x41, 0x51, 0xBD,
+
+	0x2E, 0x41, 0x2A, 0xB8,
+	0x34, 0x53, 0xA0, 0xE8,
+
+	0x15, 0x30,
+	0x1D, 0x30,
+	0x58, 0xE3,
+	0x00, 0xE0,
+
+	0xB5, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x24, 0x43, 0xA0, 0xE8,
+	0x2C, 0x4B, 0xA0, 0xE8,
+
+	0x15, 0x72,
+	0x09, 0xE3,
+	0x00, 0xE0,
+	0x1D, 0x72,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0x97, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6C, 0x64, 0xC8, 0xEC,
+	0x98, 0xE1,
+	0xB5, 0x05,
+
+	0xBD, 0x05,
+	0x2E, 0x30,
+	0x32, 0xC0, 0xA0, 0xE8,
+
+	0x33, 0xC0, 0xA0, 0xE8,
+	0x74, 0x64, 0xC8, 0xEC,
+
+	0x40, 0x3C, 0x40, 0xAD,
+	0x32, 0x6A,
+	0x2A, 0x30,
+
+	0x20, 0x73,
+	0x33, 0x6A,
+	0x00, 0xE0,
+	0x28, 0x73,
+
+	0x1C, 0x72,
+	0x83, 0xE2,
+	0x7B, 0x80, 0x15, 0xEA,
+
+	0xB8, 0x3D, 0x28, 0xDF,
+	0x30, 0x35, 0x20, 0xDF,
+
+	0x40, 0x30,
+	0x00, 0xE0,
+	0xCC, 0xE2,
+	0x64, 0x72,
+
+	0x25, 0x42, 0x52, 0xBF,
+	0x2D, 0x42, 0x4A, 0xBF,
+
+	0x30, 0x2E, 0x30, 0xDF,
+	0x38, 0x2E, 0x38, 0xDF,
+
+	0x18, 0x1D, 0x45, 0xE9,
+	0x1E, 0x15, 0x45, 0xE9,
+
+	0x2B, 0x49, 0x51, 0xBD,
+	0x00, 0xE0,
+	0x1F, 0x73,
+
+	0x38, 0x38, 0x40, 0xAF,
+	0x30, 0x30, 0x40, 0xAF,
+
+	0x24, 0x1F, 0x24, 0xDF,
+	0x1D, 0x32, 0x20, 0xE9,
+
+	0x2C, 0x1F, 0x2C, 0xDF,
+	0x1A, 0x33, 0x20, 0xE9,
+
+	0xB0, 0x10,
+	0x08, 0xE3,
+	0x40, 0x10,
+	0xB8, 0x10,
+
+	0x26, 0xF0, 0x30, 0xCD,
+	0x2F, 0xF0, 0x38, 0xCD,
+
+	0x2B, 0x80, 0x20, 0xE9,
+	0x2A, 0x80, 0x20, 0xE9,
+
+	0xA6, 0x20,
+	0x88, 0xE2,
+	0x00, 0xE0,
+	0xAF, 0x20,
+
+	0x28, 0x2A, 0x26, 0xAF,
+	0x20, 0x2A, 0xC0, 0xAF,
+
+	0x34, 0x1F, 0x34, 0xDF,
+	0x46, 0x24, 0x46, 0xDF,
+
+	0x28, 0x30, 0x80, 0xBF,
+	0x20, 0x38, 0x80, 0xBF,
+
+	0x47, 0x24, 0x47, 0xDF,
+	0x4E, 0x2C, 0x4E, 0xDF,
+
+	0x4F, 0x2C, 0x4F, 0xDF,
+	0x56, 0x34, 0x56, 0xDF,
+
+	0x28, 0x15, 0x28, 0xDF,
+	0x20, 0x1D, 0x20, 0xDF,
+
+	0x57, 0x34, 0x57, 0xDF,
+	0x00, 0xE0,
+	0x1D, 0x05,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x89, 0xE2,
+	0x2B, 0x30,
+
+	0x3F, 0xC1, 0x1D, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x68,
+	0xBF, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x20, 0xC0, 0x20, 0xAF,
+	0x28, 0x05,
+	0x97, 0x74,
+
+	0x00, 0xE0,
+	0x2A, 0x10,
+	0x16, 0xC0, 0x20, 0xE9,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x8C, 0xE2,
+	0x95, 0x05,
+
+	0x28, 0xC1, 0x28, 0xAD,
+	0x1F, 0xC1, 0x15, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA8, 0x67,
+	0x9F, 0x6B,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x28, 0xC0, 0x28, 0xAD,
+	0x1D, 0x25,
+	0x20, 0x05,
+
+	0x28, 0x32, 0x80, 0xAD,
+	0x40, 0x2A, 0x40, 0xBD,
+
+	0x1C, 0x80, 0x20, 0xE9,
+	0x20, 0x33, 0x20, 0xAD,
+
+	0x20, 0x73,
+	0x00, 0xE0,
+	0xB6, 0x49, 0x51, 0xBB,
+
+	0x26, 0x2F, 0xB0, 0xE8,
+	0x19, 0x20, 0x20, 0xE9,
+
+	0x35, 0x20, 0x35, 0xDF,
+	0x3D, 0x20, 0x3D, 0xDF,
+
+	0x15, 0x20, 0x15, 0xDF,
+	0x1D, 0x20, 0x1D, 0xDF,
+
+	0x26, 0xD0, 0x26, 0xCD,
+	0x29, 0x49, 0x2A, 0xB8,
+
+	0x26, 0x40, 0x80, 0xBD,
+	0x3B, 0x48, 0x50, 0xBD,
+
+	0x3E, 0x54, 0x57, 0x9F,
+	0x00, 0xE0,
+	0x82, 0xE1,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x26, 0x30,
+	0x29, 0x30,
+	0x48, 0x3C, 0x48, 0xAD,
+
+	0x2B, 0x72,
+	0xC2, 0xE1,
+	0x2C, 0xC0, 0x44, 0xC2,
+
+	0x05, 0x24, 0x34, 0xBF,
+	0x0D, 0x24, 0x2C, 0xBF,
+
+	0x2D, 0x46, 0x4E, 0xBF,
+	0x25, 0x46, 0x56, 0xBF,
+
+	0x20, 0x1D, 0x6F, 0x8F,
+	0x32, 0x3E, 0x5F, 0xE9,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x30,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x33, 0x1E, 0x5F, 0xE9,
+
+	0x05, 0x44, 0x54, 0xB2,
+	0x0D, 0x44, 0x4C, 0xB2,
+
+	0x19, 0xC0, 0xB0, 0xE8,
+	0x34, 0xC0, 0x44, 0xC4,
+
+	0x33, 0x73,
+	0x00, 0xE0,
+	0x3E, 0x62, 0x57, 0x9F,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0xE0,
+	0x0D, 0x20,
+
+	0x84, 0x3E, 0x58, 0xE9,
+	0x28, 0x1D, 0x6F, 0x8F,
+
+	0x05, 0x20,
+	0x00, 0xE0,
+	0x85, 0x1E, 0x58, 0xE9,
+
+	0x9B, 0x3B, 0x33, 0xDF,
+	0x20, 0x20, 0x42, 0xAF,
+
+	0x30, 0x42, 0x56, 0x9F,
+	0x80, 0x3E, 0x57, 0xE9,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x30, 0x80, 0x5F, 0xE9,
+
+	0x28, 0x28, 0x24, 0xAF,
+	0x81, 0x1E, 0x57, 0xE9,
+
+	0x05, 0x47, 0x57, 0xBF,
+	0x0D, 0x47, 0x4F, 0xBF,
+
+	0x88, 0x80, 0x58, 0xE9,
+	0x1B, 0x29, 0x1B, 0xDF,
+
+	0x30, 0x1D, 0x6F, 0x8F,
+	0x3A, 0x30, 0x4F, 0xE9,
+
+	0x1C, 0x30, 0x26, 0xDF,
+	0x09, 0xE3,
+	0x3B, 0x05,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x3B, 0x3F, 0x4F, 0xE9,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x00, 0xE0,
+	0xAC, 0x20,
+
+	0x2D, 0x44, 0x4C, 0xB4,
+	0x2C, 0x1C, 0xC0, 0xAF,
+
+	0x25, 0x44, 0x54, 0xB4,
+	0x00, 0xE0,
+	0xC8, 0x30,
+
+	0x30, 0x46, 0x30, 0xAF,
+	0x1B, 0x1B, 0x48, 0xAF,
+
+	0x00, 0xE0,
+	0x25, 0x20,
+	0x38, 0x2C, 0x4F, 0xE9,
+
+	0x86, 0x80, 0x57, 0xE9,
+	0x38, 0x1D, 0x6F, 0x8F,
+
+	0x28, 0x74,
+	0x00, 0xE0,
+	0x0D, 0x44, 0x4C, 0xB0,
+
+	0x05, 0x44, 0x54, 0xB0,
+	0x2D, 0x20,
+	0x9B, 0x10,
+
+	0x82, 0x3E, 0x57, 0xE9,
+	0x32, 0xF0, 0x1B, 0xCD,
+
+	0x1E, 0xBD, 0x59, 0x9F,
+	0x83, 0x1E, 0x57, 0xE9,
+
+	0x38, 0x47, 0x38, 0xAF,
+	0x34, 0x20,
+	0x2A, 0x30,
+
+	0x00, 0xE0,
+	0x0D, 0x20,
+	0x32, 0x20,
+	0x05, 0x20,
+
+	0x87, 0x80, 0x57, 0xE9,
+	0x1F, 0x54, 0x57, 0x9F,
+
+	0x17, 0x42, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x6A,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x37, 0x1E, 0x4F, 0xE9,
+
+	0x37, 0x32, 0x2A, 0xAF,
+	0x00, 0xE0,
+	0x32, 0x00,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x27, 0xC0, 0x44, 0xC0,
+
+	0x36, 0x1F, 0x4F, 0xE9,
+	0x1F, 0x1F, 0x26, 0xDF,
+
+	0x37, 0x1B, 0x37, 0xBF,
+	0x17, 0x26, 0x17, 0xDF,
+
+	0x3E, 0x17, 0x4F, 0xE9,
+	0x3F, 0x3F, 0x4F, 0xE9,
+
+	0x34, 0x1F, 0x34, 0xAF,
+	0x2B, 0x05,
+	0xA7, 0x20,
+
+	0x33, 0x2B, 0x37, 0xDF,
+	0x27, 0x17, 0xC0, 0xAF,
+
+	0x34, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x2D, 0x21, 0x1A, 0xB0,
+	0x25, 0x21, 0x31, 0xB0,
+
+	0x0D, 0x21, 0x1A, 0xB2,
+	0x05, 0x21, 0x31, 0xB2,
+
+	0x03, 0x80, 0x2A, 0xEA,
+	0x17, 0xC1, 0x2B, 0xBD,
+
+	0x2D, 0x20,
+	0x25, 0x20,
+	0x05, 0x20,
+	0x0D, 0x20,
+
+	0xB3, 0x68,
+	0x97, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0xC0, 0x33, 0xAF,
+	0x2F, 0xC0, 0x21, 0xC0,
+
+	0x16, 0x42, 0x56, 0x9F,
+	0x3C, 0x27, 0x4F, 0xE9,
+
+	0x1E, 0x62, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x21, 0x31, 0xB4,
+	0x2D, 0x21, 0x1A, 0xB4,
+
+	0x3F, 0x2F, 0x5D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0x05,
+	0x00, 0xE0,
+	0x28, 0x19, 0x60, 0xEC,
+
+	0x0D, 0x44, 0x4C, 0xB6,
+	0x05, 0x44, 0x54, 0xB6,
+
+	0x37, 0x0F, 0x5C, 0x9F,
+	0x00, 0xE0,
+	0x2F, 0x20,
+
+	0x23, 0x3B, 0x33, 0xAD,
+	0x1E, 0x26, 0x1E, 0xDF,
+
+	0xA7, 0x1E, 0x4F, 0xE9,
+	0x17, 0x26, 0x16, 0xDF,
+
+	0x2D, 0x20,
+	0x00, 0xE0,
+	0xA8, 0x3F, 0x4F, 0xE9,
+
+	0x2F, 0x2F, 0x1E, 0xAF,
+	0x25, 0x20,
+	0x00, 0xE0,
+
+	0xA4, 0x16, 0x4F, 0xE9,
+	0x0F, 0xC0, 0x21, 0xC2,
+
+	0xA6, 0x80, 0x4F, 0xE9,
+	0x1F, 0x62, 0x57, 0x9F,
+
+	0x0D, 0x20,
+	0x05, 0x20,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x3F, 0x2F, 0x5D, 0x9F,
+	0x00, 0xE0,
+	0x0F, 0x20,
+
+	0x17, 0x50, 0x56, 0x9F,
+	0xA5, 0x37, 0x4F, 0xE9,
+
+	0x06, 0xC0, 0x21, 0xC4,
+	0x0F, 0x17, 0x0F, 0xAF,
+
+	0x37, 0x0F, 0x5C, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x2F, 0xC0, 0x44, 0xC6,
+	0xA3, 0x80, 0x4F, 0xE9,
+
+	0x06, 0x20,
+	0x00, 0xE0,
+	0x1F, 0x26, 0x1F, 0xDF,
+
+	0x17, 0x26, 0x17, 0xDF,
+	0x9D, 0x17, 0x4F, 0xE9,
+
+	0xA1, 0x1F, 0x4F, 0xE9,
+	0xA2, 0x3F, 0x4F, 0xE9,
+
+	0x06, 0x06, 0x1F, 0xAF,
+	0x00, 0xE0,
+	0xAF, 0x20,
+
+	0x9E, 0x37, 0x4F, 0xE9,
+	0x2F, 0x17, 0x2F, 0xAF,
+
+	0xA0, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x9C, 0x80, 0x4F, 0xE9,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x57, 0x39, 0x20, 0xE9,
+
+	0x16, 0x28, 0x20, 0xE9,
+	0x1D, 0x3B, 0x20, 0xE9,
+
+	0x1E, 0x2B, 0x20, 0xE9,
+	0x2B, 0x32, 0x20, 0xE9,
+
+	0x1C, 0x23, 0x20, 0xE9,
+	0x57, 0x36, 0x20, 0xE9,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x90, 0xE2,
+	0x00, 0xE0,
+
+	0x68, 0xFF, 0x20, 0xEA,
+	0x19, 0xC8, 0xC1, 0xCD,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x9F, 0x41, 0x49, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x41, 0x49, 0xBD,
+	0x2D, 0x41, 0x51, 0xBD,
+
+	0x0D, 0x80, 0x07, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x35, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x25, 0x30,
+	0x2D, 0x30,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0xA7, 0x5B, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x67, 0xFF, 0x0A, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC9, 0x41, 0xC8, 0xEC,
+	0x42, 0xE1,
+	0x00, 0xE0,
+
+	0x65, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC8, 0x40, 0xC0, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x62, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsaf[] = {
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x98, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x81, 0x04,
+	0x89, 0x04,
+	0x01, 0x04,
+	0x09, 0x04,
+
+	0xC9, 0x41, 0xC0, 0xEC,
+	0x11, 0x04,
+	0x00, 0xE0,
+
+	0x41, 0xCC, 0x41, 0xCD,
+	0x49, 0xCC, 0x49, 0xCD,
+
+	0xD1, 0x41, 0xC0, 0xEC,
+	0x51, 0xCC, 0x51, 0xCD,
+
+	0x80, 0x04,
+	0x10, 0x04,
+	0x08, 0x04,
+	0x00, 0xE0,
+
+	0x00, 0xCC, 0xC0, 0xCD,
+	0xD1, 0x49, 0xC0, 0xEC,
+
+	0x8A, 0x1F, 0x20, 0xE9,
+	0x8B, 0x3F, 0x20, 0xE9,
+
+	0x41, 0x3C, 0x41, 0xAD,
+	0x49, 0x3C, 0x49, 0xAD,
+
+	0x10, 0xCC, 0x10, 0xCD,
+	0x08, 0xCC, 0x08, 0xCD,
+
+	0xB9, 0x41, 0x49, 0xBB,
+	0x1F, 0xF0, 0x41, 0xCD,
+
+	0x51, 0x3C, 0x51, 0xAD,
+	0x00, 0x98, 0x80, 0xE9,
+
+	0x94, 0x80, 0x07, 0xEA,
+	0x24, 0x1F, 0x20, 0xE9,
+
+	0x21, 0x45, 0x80, 0xE8,
+	0x1A, 0x4D, 0x80, 0xE8,
+
+	0x31, 0x55, 0x80, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0x41, 0x49, 0xBD,
+	0x1D, 0x41, 0x51, 0xBD,
+
+	0x2E, 0x41, 0x2A, 0xB8,
+	0x34, 0x53, 0xA0, 0xE8,
+
+	0x15, 0x30,
+	0x1D, 0x30,
+	0x58, 0xE3,
+	0x00, 0xE0,
+
+	0xB5, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x24, 0x43, 0xA0, 0xE8,
+	0x2C, 0x4B, 0xA0, 0xE8,
+
+	0x15, 0x72,
+	0x09, 0xE3,
+	0x00, 0xE0,
+	0x1D, 0x72,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0x97, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6C, 0x64, 0xC8, 0xEC,
+	0x98, 0xE1,
+	0xB5, 0x05,
+
+	0xBD, 0x05,
+	0x2E, 0x30,
+	0x32, 0xC0, 0xA0, 0xE8,
+
+	0x33, 0xC0, 0xA0, 0xE8,
+	0x74, 0x64, 0xC8, 0xEC,
+
+	0x40, 0x3C, 0x40, 0xAD,
+	0x32, 0x6A,
+	0x2A, 0x30,
+
+	0x20, 0x73,
+	0x33, 0x6A,
+	0x00, 0xE0,
+	0x28, 0x73,
+
+	0x1C, 0x72,
+	0x83, 0xE2,
+	0x80, 0x80, 0x15, 0xEA,
+
+	0xB8, 0x3D, 0x28, 0xDF,
+	0x30, 0x35, 0x20, 0xDF,
+
+	0x40, 0x30,
+	0x00, 0xE0,
+	0xCC, 0xE2,
+	0x64, 0x72,
+
+	0x25, 0x42, 0x52, 0xBF,
+	0x2D, 0x42, 0x4A, 0xBF,
+
+	0x30, 0x2E, 0x30, 0xDF,
+	0x38, 0x2E, 0x38, 0xDF,
+
+	0x18, 0x1D, 0x45, 0xE9,
+	0x1E, 0x15, 0x45, 0xE9,
+
+	0x2B, 0x49, 0x51, 0xBD,
+	0x00, 0xE0,
+	0x1F, 0x73,
+
+	0x38, 0x38, 0x40, 0xAF,
+	0x30, 0x30, 0x40, 0xAF,
+
+	0x24, 0x1F, 0x24, 0xDF,
+	0x1D, 0x32, 0x20, 0xE9,
+
+	0x2C, 0x1F, 0x2C, 0xDF,
+	0x1A, 0x33, 0x20, 0xE9,
+
+	0xB0, 0x10,
+	0x08, 0xE3,
+	0x40, 0x10,
+	0xB8, 0x10,
+
+	0x26, 0xF0, 0x30, 0xCD,
+	0x2F, 0xF0, 0x38, 0xCD,
+
+	0x2B, 0x80, 0x20, 0xE9,
+	0x2A, 0x80, 0x20, 0xE9,
+
+	0xA6, 0x20,
+	0x88, 0xE2,
+	0x00, 0xE0,
+	0xAF, 0x20,
+
+	0x28, 0x2A, 0x26, 0xAF,
+	0x20, 0x2A, 0xC0, 0xAF,
+
+	0x34, 0x1F, 0x34, 0xDF,
+	0x46, 0x24, 0x46, 0xDF,
+
+	0x28, 0x30, 0x80, 0xBF,
+	0x20, 0x38, 0x80, 0xBF,
+
+	0x47, 0x24, 0x47, 0xDF,
+	0x4E, 0x2C, 0x4E, 0xDF,
+
+	0x4F, 0x2C, 0x4F, 0xDF,
+	0x56, 0x34, 0x56, 0xDF,
+
+	0x28, 0x15, 0x28, 0xDF,
+	0x20, 0x1D, 0x20, 0xDF,
+
+	0x57, 0x34, 0x57, 0xDF,
+	0x00, 0xE0,
+	0x1D, 0x05,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x89, 0xE2,
+	0x2B, 0x30,
+
+	0x3F, 0xC1, 0x1D, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x68,
+	0xBF, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x20, 0xC0, 0x20, 0xAF,
+	0x28, 0x05,
+	0x97, 0x74,
+
+	0x00, 0xE0,
+	0x2A, 0x10,
+	0x16, 0xC0, 0x20, 0xE9,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x8C, 0xE2,
+	0x95, 0x05,
+
+	0x28, 0xC1, 0x28, 0xAD,
+	0x1F, 0xC1, 0x15, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA8, 0x67,
+	0x9F, 0x6B,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x28, 0xC0, 0x28, 0xAD,
+	0x1D, 0x25,
+	0x20, 0x05,
+
+	0x28, 0x32, 0x80, 0xAD,
+	0x40, 0x2A, 0x40, 0xBD,
+
+	0x1C, 0x80, 0x20, 0xE9,
+	0x20, 0x33, 0x20, 0xAD,
+
+	0x20, 0x73,
+	0x00, 0xE0,
+	0xB6, 0x49, 0x51, 0xBB,
+
+	0x26, 0x2F, 0xB0, 0xE8,
+	0x19, 0x20, 0x20, 0xE9,
+
+	0x35, 0x20, 0x35, 0xDF,
+	0x3D, 0x20, 0x3D, 0xDF,
+
+	0x15, 0x20, 0x15, 0xDF,
+	0x1D, 0x20, 0x1D, 0xDF,
+
+	0x26, 0xD0, 0x26, 0xCD,
+	0x29, 0x49, 0x2A, 0xB8,
+
+	0x26, 0x40, 0x80, 0xBD,
+	0x3B, 0x48, 0x50, 0xBD,
+
+	0x3E, 0x54, 0x57, 0x9F,
+	0x00, 0xE0,
+	0x82, 0xE1,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x26, 0x30,
+	0x29, 0x30,
+	0x48, 0x3C, 0x48, 0xAD,
+
+	0x2B, 0x72,
+	0xC2, 0xE1,
+	0x2C, 0xC0, 0x44, 0xC2,
+
+	0x05, 0x24, 0x34, 0xBF,
+	0x0D, 0x24, 0x2C, 0xBF,
+
+	0x2D, 0x46, 0x4E, 0xBF,
+	0x25, 0x46, 0x56, 0xBF,
+
+	0x20, 0x1D, 0x6F, 0x8F,
+	0x32, 0x3E, 0x5F, 0xE9,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x30,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x33, 0x1E, 0x5F, 0xE9,
+
+	0x05, 0x44, 0x54, 0xB2,
+	0x0D, 0x44, 0x4C, 0xB2,
+
+	0x19, 0xC0, 0xB0, 0xE8,
+	0x34, 0xC0, 0x44, 0xC4,
+
+	0x33, 0x73,
+	0x00, 0xE0,
+	0x3E, 0x62, 0x57, 0x9F,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0xE0,
+	0x0D, 0x20,
+
+	0x84, 0x3E, 0x58, 0xE9,
+	0x28, 0x1D, 0x6F, 0x8F,
+
+	0x05, 0x20,
+	0x00, 0xE0,
+	0x85, 0x1E, 0x58, 0xE9,
+
+	0x9B, 0x3B, 0x33, 0xDF,
+	0x20, 0x20, 0x42, 0xAF,
+
+	0x30, 0x42, 0x56, 0x9F,
+	0x80, 0x3E, 0x57, 0xE9,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x30, 0x80, 0x5F, 0xE9,
+
+	0x28, 0x28, 0x24, 0xAF,
+	0x81, 0x1E, 0x57, 0xE9,
+
+	0x05, 0x47, 0x57, 0xBF,
+	0x0D, 0x47, 0x4F, 0xBF,
+
+	0x88, 0x80, 0x58, 0xE9,
+	0x1B, 0x29, 0x1B, 0xDF,
+
+	0x30, 0x1D, 0x6F, 0x8F,
+	0x3A, 0x30, 0x4F, 0xE9,
+
+	0x1C, 0x30, 0x26, 0xDF,
+	0x09, 0xE3,
+	0x3B, 0x05,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x3B, 0x3F, 0x4F, 0xE9,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x00, 0xE0,
+	0xAC, 0x20,
+
+	0x2D, 0x44, 0x4C, 0xB4,
+	0x2C, 0x1C, 0xC0, 0xAF,
+
+	0x25, 0x44, 0x54, 0xB4,
+	0x00, 0xE0,
+	0xC8, 0x30,
+
+	0x30, 0x46, 0x30, 0xAF,
+	0x1B, 0x1B, 0x48, 0xAF,
+
+	0x00, 0xE0,
+	0x25, 0x20,
+	0x38, 0x2C, 0x4F, 0xE9,
+
+	0x86, 0x80, 0x57, 0xE9,
+	0x38, 0x1D, 0x6F, 0x8F,
+
+	0x28, 0x74,
+	0x00, 0xE0,
+	0x0D, 0x44, 0x4C, 0xB0,
+
+	0x05, 0x44, 0x54, 0xB0,
+	0x2D, 0x20,
+	0x9B, 0x10,
+
+	0x82, 0x3E, 0x57, 0xE9,
+	0x32, 0xF0, 0x1B, 0xCD,
+
+	0x1E, 0xBD, 0x59, 0x9F,
+	0x83, 0x1E, 0x57, 0xE9,
+
+	0x38, 0x47, 0x38, 0xAF,
+	0x34, 0x20,
+	0x2A, 0x30,
+
+	0x00, 0xE0,
+	0x0D, 0x20,
+	0x32, 0x20,
+	0x05, 0x20,
+
+	0x87, 0x80, 0x57, 0xE9,
+	0x1F, 0x54, 0x57, 0x9F,
+
+	0x17, 0x42, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x6A,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x37, 0x1E, 0x4F, 0xE9,
+
+	0x37, 0x32, 0x2A, 0xAF,
+	0x00, 0xE0,
+	0x32, 0x00,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x27, 0xC0, 0x44, 0xC0,
+
+	0x36, 0x1F, 0x4F, 0xE9,
+	0x1F, 0x1F, 0x26, 0xDF,
+
+	0x37, 0x1B, 0x37, 0xBF,
+	0x17, 0x26, 0x17, 0xDF,
+
+	0x3E, 0x17, 0x4F, 0xE9,
+	0x3F, 0x3F, 0x4F, 0xE9,
+
+	0x34, 0x1F, 0x34, 0xAF,
+	0x2B, 0x05,
+	0xA7, 0x20,
+
+	0x33, 0x2B, 0x37, 0xDF,
+	0x27, 0x17, 0xC0, 0xAF,
+
+	0x34, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x2D, 0x21, 0x1A, 0xB0,
+	0x25, 0x21, 0x31, 0xB0,
+
+	0x0D, 0x21, 0x1A, 0xB2,
+	0x05, 0x21, 0x31, 0xB2,
+
+	0x03, 0x80, 0x2A, 0xEA,
+	0x17, 0xC1, 0x2B, 0xBD,
+
+	0x2D, 0x20,
+	0x25, 0x20,
+	0x05, 0x20,
+	0x0D, 0x20,
+
+	0xB3, 0x68,
+	0x97, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0xC0, 0x33, 0xAF,
+	0x2F, 0xC0, 0x21, 0xC0,
+
+	0x16, 0x42, 0x56, 0x9F,
+	0x3C, 0x27, 0x4F, 0xE9,
+
+	0x1E, 0x62, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x21, 0x31, 0xB4,
+	0x2D, 0x21, 0x1A, 0xB4,
+
+	0x3F, 0x2F, 0x5D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0x05,
+	0x00, 0xE0,
+	0x28, 0x19, 0x60, 0xEC,
+
+	0x0D, 0x21, 0x1A, 0xB6,
+	0x05, 0x21, 0x31, 0xB6,
+
+	0x37, 0x0F, 0x5C, 0x9F,
+	0x00, 0xE0,
+	0x2F, 0x20,
+
+	0x23, 0x3B, 0x33, 0xAD,
+	0x1E, 0x26, 0x1E, 0xDF,
+
+	0xA7, 0x1E, 0x4F, 0xE9,
+	0x17, 0x26, 0x16, 0xDF,
+
+	0x2D, 0x20,
+	0x00, 0xE0,
+	0xA8, 0x3F, 0x4F, 0xE9,
+
+	0x2F, 0x2F, 0x1E, 0xAF,
+	0x25, 0x20,
+	0x00, 0xE0,
+
+	0xA4, 0x16, 0x4F, 0xE9,
+	0x0F, 0xC0, 0x21, 0xC2,
+
+	0xA6, 0x80, 0x4F, 0xE9,
+	0x1F, 0x62, 0x57, 0x9F,
+
+	0x0D, 0x20,
+	0x05, 0x20,
+	0x2F, 0xC0, 0x21, 0xC6,
+
+	0x2D, 0x44, 0x4C, 0xB6,
+	0x25, 0x44, 0x54, 0xB6,
+
+	0x3F, 0x2F, 0x5D, 0x9F,
+	0x00, 0xE0,
+	0x0F, 0x20,
+
+	0x2D, 0x20,
+	0x25, 0x20,
+	0x07, 0xC0, 0x44, 0xC6,
+
+	0x17, 0x50, 0x56, 0x9F,
+	0xA5, 0x37, 0x4F, 0xE9,
+
+	0x06, 0xC0, 0x21, 0xC4,
+	0x0F, 0x17, 0x0F, 0xAF,
+
+	0x37, 0x0F, 0x5C, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1E, 0x62, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x3E, 0x3D, 0x5D, 0x9F,
+	0x00, 0xE0,
+	0x07, 0x20,
+
+	0x2F, 0x20,
+	0x00, 0xE0,
+	0xA3, 0x0F, 0x4F, 0xE9,
+
+	0x06, 0x20,
+	0x00, 0xE0,
+	0x1F, 0x26, 0x1F, 0xDF,
+
+	0x17, 0x26, 0x17, 0xDF,
+	0xA1, 0x1F, 0x4F, 0xE9,
+
+	0x1E, 0x26, 0x1E, 0xDF,
+	0x9D, 0x1E, 0x4F, 0xE9,
+
+	0x35, 0x17, 0x4F, 0xE9,
+	0xA2, 0x3F, 0x4F, 0xE9,
+
+	0x06, 0x06, 0x1F, 0xAF,
+	0x39, 0x37, 0x4F, 0xE9,
+
+	0x2F, 0x2F, 0x17, 0xAF,
+	0x07, 0x07, 0x1E, 0xAF,
+
+	0xA0, 0x80, 0x4F, 0xE9,
+	0x9E, 0x3E, 0x4F, 0xE9,
+
+	0x31, 0x80, 0x4F, 0xE9,
+	0x9C, 0x80, 0x4F, 0xE9,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x57, 0x39, 0x20, 0xE9,
+
+	0x16, 0x28, 0x20, 0xE9,
+	0x1D, 0x3B, 0x20, 0xE9,
+
+	0x1E, 0x2B, 0x20, 0xE9,
+	0x2B, 0x32, 0x20, 0xE9,
+
+	0x1C, 0x23, 0x20, 0xE9,
+	0x57, 0x36, 0x20, 0xE9,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x90, 0xE2,
+	0x00, 0xE0,
+
+	0x63, 0xFF, 0x20, 0xEA,
+	0x19, 0xC8, 0xC1, 0xCD,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x9F, 0x41, 0x49, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x41, 0x49, 0xBD,
+	0x2D, 0x41, 0x51, 0xBD,
+
+	0x0D, 0x80, 0x07, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x35, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x25, 0x30,
+	0x2D, 0x30,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0xA7, 0x5B, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x62, 0xFF, 0x0A, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC9, 0x41, 0xC8, 0xEC,
+	0x42, 0xE1,
+	0x00, 0xE0,
+
+	0x60, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC8, 0x40, 0xC0, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x5D, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsf[] = {
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x98, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x81, 0x04,
+	0x89, 0x04,
+	0x01, 0x04,
+	0x09, 0x04,
+
+	0xC9, 0x41, 0xC0, 0xEC,
+	0x11, 0x04,
+	0x00, 0xE0,
+
+	0x41, 0xCC, 0x41, 0xCD,
+	0x49, 0xCC, 0x49, 0xCD,
+
+	0xD1, 0x41, 0xC0, 0xEC,
+	0x51, 0xCC, 0x51, 0xCD,
+
+	0x80, 0x04,
+	0x10, 0x04,
+	0x08, 0x04,
+	0x00, 0xE0,
+
+	0x00, 0xCC, 0xC0, 0xCD,
+	0xD1, 0x49, 0xC0, 0xEC,
+
+	0x8A, 0x1F, 0x20, 0xE9,
+	0x8B, 0x3F, 0x20, 0xE9,
+
+	0x41, 0x3C, 0x41, 0xAD,
+	0x49, 0x3C, 0x49, 0xAD,
+
+	0x10, 0xCC, 0x10, 0xCD,
+	0x08, 0xCC, 0x08, 0xCD,
+
+	0xB9, 0x41, 0x49, 0xBB,
+	0x1F, 0xF0, 0x41, 0xCD,
+
+	0x51, 0x3C, 0x51, 0xAD,
+	0x00, 0x98, 0x80, 0xE9,
+
+	0x8F, 0x80, 0x07, 0xEA,
+	0x24, 0x1F, 0x20, 0xE9,
+
+	0x21, 0x45, 0x80, 0xE8,
+	0x1A, 0x4D, 0x80, 0xE8,
+
+	0x31, 0x55, 0x80, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0x41, 0x49, 0xBD,
+	0x1D, 0x41, 0x51, 0xBD,
+
+	0x2E, 0x41, 0x2A, 0xB8,
+	0x34, 0x53, 0xA0, 0xE8,
+
+	0x15, 0x30,
+	0x1D, 0x30,
+	0x58, 0xE3,
+	0x00, 0xE0,
+
+	0xB5, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x24, 0x43, 0xA0, 0xE8,
+	0x2C, 0x4B, 0xA0, 0xE8,
+
+	0x15, 0x72,
+	0x09, 0xE3,
+	0x00, 0xE0,
+	0x1D, 0x72,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0x97, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x6C, 0x64, 0xC8, 0xEC,
+	0x98, 0xE1,
+	0xB5, 0x05,
+
+	0xBD, 0x05,
+	0x2E, 0x30,
+	0x32, 0xC0, 0xA0, 0xE8,
+
+	0x33, 0xC0, 0xA0, 0xE8,
+	0x74, 0x64, 0xC8, 0xEC,
+
+	0x40, 0x3C, 0x40, 0xAD,
+	0x32, 0x6A,
+	0x2A, 0x30,
+
+	0x20, 0x73,
+	0x33, 0x6A,
+	0x00, 0xE0,
+	0x28, 0x73,
+
+	0x1C, 0x72,
+	0x83, 0xE2,
+	0x7B, 0x80, 0x15, 0xEA,
+
+	0xB8, 0x3D, 0x28, 0xDF,
+	0x30, 0x35, 0x20, 0xDF,
+
+	0x40, 0x30,
+	0x00, 0xE0,
+	0xCC, 0xE2,
+	0x64, 0x72,
+
+	0x25, 0x42, 0x52, 0xBF,
+	0x2D, 0x42, 0x4A, 0xBF,
+
+	0x30, 0x2E, 0x30, 0xDF,
+	0x38, 0x2E, 0x38, 0xDF,
+
+	0x18, 0x1D, 0x45, 0xE9,
+	0x1E, 0x15, 0x45, 0xE9,
+
+	0x2B, 0x49, 0x51, 0xBD,
+	0x00, 0xE0,
+	0x1F, 0x73,
+
+	0x38, 0x38, 0x40, 0xAF,
+	0x30, 0x30, 0x40, 0xAF,
+
+	0x24, 0x1F, 0x24, 0xDF,
+	0x1D, 0x32, 0x20, 0xE9,
+
+	0x2C, 0x1F, 0x2C, 0xDF,
+	0x1A, 0x33, 0x20, 0xE9,
+
+	0xB0, 0x10,
+	0x08, 0xE3,
+	0x40, 0x10,
+	0xB8, 0x10,
+
+	0x26, 0xF0, 0x30, 0xCD,
+	0x2F, 0xF0, 0x38, 0xCD,
+
+	0x2B, 0x80, 0x20, 0xE9,
+	0x2A, 0x80, 0x20, 0xE9,
+
+	0xA6, 0x20,
+	0x88, 0xE2,
+	0x00, 0xE0,
+	0xAF, 0x20,
+
+	0x28, 0x2A, 0x26, 0xAF,
+	0x20, 0x2A, 0xC0, 0xAF,
+
+	0x34, 0x1F, 0x34, 0xDF,
+	0x46, 0x24, 0x46, 0xDF,
+
+	0x28, 0x30, 0x80, 0xBF,
+	0x20, 0x38, 0x80, 0xBF,
+
+	0x47, 0x24, 0x47, 0xDF,
+	0x4E, 0x2C, 0x4E, 0xDF,
+
+	0x4F, 0x2C, 0x4F, 0xDF,
+	0x56, 0x34, 0x56, 0xDF,
+
+	0x28, 0x15, 0x28, 0xDF,
+	0x20, 0x1D, 0x20, 0xDF,
+
+	0x57, 0x34, 0x57, 0xDF,
+	0x00, 0xE0,
+	0x1D, 0x05,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x89, 0xE2,
+	0x2B, 0x30,
+
+	0x3F, 0xC1, 0x1D, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x68,
+	0xBF, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x20, 0xC0, 0x20, 0xAF,
+	0x28, 0x05,
+	0x97, 0x74,
+
+	0x00, 0xE0,
+	0x2A, 0x10,
+	0x16, 0xC0, 0x20, 0xE9,
+
+	0x04, 0x80, 0x10, 0xEA,
+	0x8C, 0xE2,
+	0x95, 0x05,
+
+	0x28, 0xC1, 0x28, 0xAD,
+	0x1F, 0xC1, 0x15, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA8, 0x67,
+	0x9F, 0x6B,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x28, 0xC0, 0x28, 0xAD,
+	0x1D, 0x25,
+	0x20, 0x05,
+
+	0x28, 0x32, 0x80, 0xAD,
+	0x40, 0x2A, 0x40, 0xBD,
+
+	0x1C, 0x80, 0x20, 0xE9,
+	0x20, 0x33, 0x20, 0xAD,
+
+	0x20, 0x73,
+	0x00, 0xE0,
+	0xB6, 0x49, 0x51, 0xBB,
+
+	0x26, 0x2F, 0xB0, 0xE8,
+	0x19, 0x20, 0x20, 0xE9,
+
+	0x35, 0x20, 0x35, 0xDF,
+	0x3D, 0x20, 0x3D, 0xDF,
+
+	0x15, 0x20, 0x15, 0xDF,
+	0x1D, 0x20, 0x1D, 0xDF,
+
+	0x26, 0xD0, 0x26, 0xCD,
+	0x29, 0x49, 0x2A, 0xB8,
+
+	0x26, 0x40, 0x80, 0xBD,
+	0x3B, 0x48, 0x50, 0xBD,
+
+	0x3E, 0x54, 0x57, 0x9F,
+	0x00, 0xE0,
+	0x82, 0xE1,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x26, 0x30,
+	0x29, 0x30,
+	0x48, 0x3C, 0x48, 0xAD,
+
+	0x2B, 0x72,
+	0xC2, 0xE1,
+	0x2C, 0xC0, 0x44, 0xC2,
+
+	0x05, 0x24, 0x34, 0xBF,
+	0x0D, 0x24, 0x2C, 0xBF,
+
+	0x2D, 0x46, 0x4E, 0xBF,
+	0x25, 0x46, 0x56, 0xBF,
+
+	0x20, 0x1D, 0x6F, 0x8F,
+	0x32, 0x3E, 0x5F, 0xE9,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x30,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x33, 0x1E, 0x5F, 0xE9,
+
+	0x05, 0x44, 0x54, 0xB2,
+	0x0D, 0x44, 0x4C, 0xB2,
+
+	0x19, 0xC0, 0xB0, 0xE8,
+	0x34, 0xC0, 0x44, 0xC4,
+
+	0x33, 0x73,
+	0x00, 0xE0,
+	0x3E, 0x62, 0x57, 0x9F,
+
+	0x1E, 0xAF, 0x59, 0x9F,
+	0x00, 0xE0,
+	0x0D, 0x20,
+
+	0x84, 0x3E, 0x58, 0xE9,
+	0x28, 0x1D, 0x6F, 0x8F,
+
+	0x05, 0x20,
+	0x00, 0xE0,
+	0x85, 0x1E, 0x58, 0xE9,
+
+	0x9B, 0x3B, 0x33, 0xDF,
+	0x20, 0x20, 0x42, 0xAF,
+
+	0x30, 0x42, 0x56, 0x9F,
+	0x80, 0x3E, 0x57, 0xE9,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x30, 0x80, 0x5F, 0xE9,
+
+	0x28, 0x28, 0x24, 0xAF,
+	0x81, 0x1E, 0x57, 0xE9,
+
+	0x05, 0x47, 0x57, 0xBF,
+	0x0D, 0x47, 0x4F, 0xBF,
+
+	0x88, 0x80, 0x58, 0xE9,
+	0x1B, 0x29, 0x1B, 0xDF,
+
+	0x30, 0x1D, 0x6F, 0x8F,
+	0x3A, 0x30, 0x4F, 0xE9,
+
+	0x1C, 0x30, 0x26, 0xDF,
+	0x09, 0xE3,
+	0x3B, 0x05,
+
+	0x3E, 0x50, 0x56, 0x9F,
+	0x3B, 0x3F, 0x4F, 0xE9,
+
+	0x1E, 0x8F, 0x51, 0x9F,
+	0x00, 0xE0,
+	0xAC, 0x20,
+
+	0x2D, 0x44, 0x4C, 0xB4,
+	0x2C, 0x1C, 0xC0, 0xAF,
+
+	0x25, 0x44, 0x54, 0xB4,
+	0x00, 0xE0,
+	0xC8, 0x30,
+
+	0x30, 0x46, 0x30, 0xAF,
+	0x1B, 0x1B, 0x48, 0xAF,
+
+	0x00, 0xE0,
+	0x25, 0x20,
+	0x38, 0x2C, 0x4F, 0xE9,
+
+	0x86, 0x80, 0x57, 0xE9,
+	0x38, 0x1D, 0x6F, 0x8F,
+
+	0x28, 0x74,
+	0x00, 0xE0,
+	0x0D, 0x44, 0x4C, 0xB0,
+
+	0x05, 0x44, 0x54, 0xB0,
+	0x2D, 0x20,
+	0x9B, 0x10,
+
+	0x82, 0x3E, 0x57, 0xE9,
+	0x32, 0xF0, 0x1B, 0xCD,
+
+	0x1E, 0xBD, 0x59, 0x9F,
+	0x83, 0x1E, 0x57, 0xE9,
+
+	0x38, 0x47, 0x38, 0xAF,
+	0x34, 0x20,
+	0x2A, 0x30,
+
+	0x00, 0xE0,
+	0x0D, 0x20,
+	0x32, 0x20,
+	0x05, 0x20,
+
+	0x87, 0x80, 0x57, 0xE9,
+	0x1F, 0x54, 0x57, 0x9F,
+
+	0x17, 0x42, 0x56, 0x9F,
+	0x00, 0xE0,
+	0x3B, 0x6A,
+
+	0x3F, 0x8F, 0x51, 0x9F,
+	0x37, 0x1E, 0x4F, 0xE9,
+
+	0x37, 0x32, 0x2A, 0xAF,
+	0x00, 0xE0,
+	0x32, 0x00,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x27, 0xC0, 0x44, 0xC0,
+
+	0x36, 0x1F, 0x4F, 0xE9,
+	0x1F, 0x1F, 0x26, 0xDF,
+
+	0x37, 0x1B, 0x37, 0xBF,
+	0x17, 0x26, 0x17, 0xDF,
+
+	0x3E, 0x17, 0x4F, 0xE9,
+	0x3F, 0x3F, 0x4F, 0xE9,
+
+	0x34, 0x1F, 0x34, 0xAF,
+	0x2B, 0x05,
+	0xA7, 0x20,
+
+	0x33, 0x2B, 0x37, 0xDF,
+	0x27, 0x17, 0xC0, 0xAF,
+
+	0x34, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x2D, 0x21, 0x1A, 0xB0,
+	0x25, 0x21, 0x31, 0xB0,
+
+	0x0D, 0x21, 0x1A, 0xB2,
+	0x05, 0x21, 0x31, 0xB2,
+
+	0x03, 0x80, 0x2A, 0xEA,
+	0x17, 0xC1, 0x2B, 0xBD,
+
+	0x2D, 0x20,
+	0x25, 0x20,
+	0x05, 0x20,
+	0x0D, 0x20,
+
+	0xB3, 0x68,
+	0x97, 0x25,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0xC0, 0x33, 0xAF,
+	0x2F, 0xC0, 0x21, 0xC0,
+
+	0x16, 0x42, 0x56, 0x9F,
+	0x3C, 0x27, 0x4F, 0xE9,
+
+	0x1E, 0x62, 0x57, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x21, 0x31, 0xB4,
+	0x2D, 0x21, 0x1A, 0xB4,
+
+	0x3F, 0x2F, 0x5D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x33, 0x05,
+	0x00, 0xE0,
+	0x28, 0x19, 0x60, 0xEC,
+
+	0x0D, 0x21, 0x1A, 0xB6,
+	0x05, 0x21, 0x31, 0xB6,
+
+	0x37, 0x0F, 0x5C, 0x9F,
+	0x00, 0xE0,
+	0x2F, 0x20,
+
+	0x23, 0x3B, 0x33, 0xAD,
+	0x1E, 0x26, 0x1E, 0xDF,
+
+	0xA7, 0x1E, 0x4F, 0xE9,
+	0x17, 0x26, 0x16, 0xDF,
+
+	0x2D, 0x20,
+	0x00, 0xE0,
+	0xA8, 0x3F, 0x4F, 0xE9,
+
+	0x2F, 0x2F, 0x1E, 0xAF,
+	0x25, 0x20,
+	0x00, 0xE0,
+
+	0xA4, 0x16, 0x4F, 0xE9,
+	0x0F, 0xC0, 0x21, 0xC2,
+
+	0xA6, 0x80, 0x4F, 0xE9,
+	0x1F, 0x62, 0x57, 0x9F,
+
+	0x0D, 0x20,
+	0x05, 0x20,
+	0x2F, 0xC0, 0x21, 0xC6,
+
+	0x3F, 0x2F, 0x5D, 0x9F,
+	0x00, 0xE0,
+	0x0F, 0x20,
+
+	0x17, 0x50, 0x56, 0x9F,
+	0xA5, 0x37, 0x4F, 0xE9,
+
+	0x06, 0xC0, 0x21, 0xC4,
+	0x0F, 0x17, 0x0F, 0xAF,
+
+	0x37, 0x0F, 0x5C, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x2F, 0x20,
+	0x00, 0xE0,
+	0xA3, 0x80, 0x4F, 0xE9,
+
+	0x06, 0x20,
+	0x00, 0xE0,
+	0x1F, 0x26, 0x1F, 0xDF,
+
+	0x17, 0x26, 0x17, 0xDF,
+	0x35, 0x17, 0x4F, 0xE9,
+
+	0xA1, 0x1F, 0x4F, 0xE9,
+	0xA2, 0x3F, 0x4F, 0xE9,
+
+	0x06, 0x06, 0x1F, 0xAF,
+	0x39, 0x37, 0x4F, 0xE9,
+
+	0x2F, 0x2F, 0x17, 0xAF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xA0, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x31, 0x80, 0x4F, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x57, 0x39, 0x20, 0xE9,
+
+	0x16, 0x28, 0x20, 0xE9,
+	0x1D, 0x3B, 0x20, 0xE9,
+
+	0x1E, 0x2B, 0x20, 0xE9,
+	0x2B, 0x32, 0x20, 0xE9,
+
+	0x1C, 0x23, 0x20, 0xE9,
+	0x57, 0x36, 0x20, 0xE9,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x40, 0x40, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x90, 0xE2,
+	0x00, 0xE0,
+
+	0x68, 0xFF, 0x20, 0xEA,
+	0x19, 0xC8, 0xC1, 0xCD,
+
+	0x1F, 0xD7, 0x18, 0xBD,
+	0x3F, 0xD7, 0x22, 0xBD,
+
+	0x9F, 0x41, 0x49, 0xBD,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x25, 0x41, 0x49, 0xBD,
+	0x2D, 0x41, 0x51, 0xBD,
+
+	0x0D, 0x80, 0x07, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x35, 0x40, 0x48, 0xBD,
+	0x3D, 0x40, 0x50, 0xBD,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x25, 0x30,
+	0x2D, 0x30,
+
+	0x35, 0x30,
+	0xB5, 0x30,
+	0xBD, 0x30,
+	0x3D, 0x30,
+
+	0x9C, 0xA7, 0x5B, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x67, 0xFF, 0x0A, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC9, 0x41, 0xC8, 0xEC,
+	0x42, 0xE1,
+	0x00, 0xE0,
+
+	0x65, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xC8, 0x40, 0xC0, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x62, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g400_t2gz[] = {
+
+	0x00, 0x8A, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0A, 0x40, 0x50, 0xBF,
+	0x2A, 0x40, 0x60, 0xBF,
+
+	0x32, 0x41, 0x51, 0xBF,
+	0x3A, 0x41, 0x61, 0xBF,
+
+	0xC3, 0x6B,
+	0xD3, 0x6B,
+	0x00, 0x8A, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x23, 0x9F,
+	0x00, 0xE0,
+	0x51, 0x04,
+
+	0x90, 0xE2,
+	0x61, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x51, 0x41, 0xE0, 0xEC,
+	0x39, 0x67, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x63, 0xA0, 0xE8,
+
+	0x61, 0x41, 0xE0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x78, 0x80, 0x15, 0xEA,
+	0x10, 0x04,
+	0x20, 0x04,
+
+	0x61, 0x51, 0xE0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x52, 0xBF,
+	0x0F, 0x52, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x62, 0xBF,
+	0x1E, 0x51, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x0E, 0x61, 0x60, 0xEA,
+
+	0x32, 0x40, 0x50, 0xBD,
+	0x22, 0x40, 0x60, 0xBD,
+
+	0x12, 0x41, 0x51, 0xBD,
+	0x3A, 0x41, 0x61, 0xBD,
+
+	0xBF, 0x2F, 0x0E, 0xBD,
+	0x97, 0xE2,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x35, 0x48, 0xB1, 0xE8,
+	0x3D, 0x59, 0xB1, 0xE8,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x56, 0x31, 0x56, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x66, 0x31, 0x66, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x57, 0x39, 0x57, 0xBF,
+	0x67, 0x39, 0x67, 0xBF,
+
+	0x69, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x35, 0x00,
+	0x3D, 0x00,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0x8D, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x75, 0xF8, 0xEC,
+	0x35, 0x20,
+	0x3D, 0x20,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x53, 0x53, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x0E, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x48, 0x35, 0x48, 0xBF,
+	0x58, 0x35, 0x58, 0xBF,
+
+	0x68, 0x35, 0x68, 0xBF,
+	0x49, 0x3D, 0x49, 0xBF,
+
+	0x59, 0x3D, 0x59, 0xBF,
+	0x69, 0x3D, 0x69, 0xBF,
+
+	0x63, 0x63, 0x2D, 0xDF,
+	0x4D, 0x7D, 0xF8, 0xEC,
+
+	0x59, 0xE3,
+	0x00, 0xE0,
+	0xB8, 0x38, 0x33, 0xBF,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x18, 0x3A, 0x41, 0xE9,
+
+	0x3F, 0x53, 0xA0, 0xE8,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x63, 0xA0, 0xE8,
+
+	0x50, 0x70, 0xF8, 0xEC,
+	0x2B, 0x50, 0x3C, 0xE9,
+
+	0x1F, 0x0F, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x59, 0x78, 0xF8, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x56, 0x3F, 0x56, 0xDF,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x66, 0x3D, 0x66, 0xDF,
+
+	0x1D, 0x32, 0x41, 0xE9,
+	0x67, 0x3D, 0x67, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3F, 0x57, 0xDF,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x59, 0x3F, 0x59, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x69, 0x3D, 0x69, 0xDF,
+
+	0x48, 0x37, 0x48, 0xDF,
+	0x58, 0x3F, 0x58, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x68, 0x3D, 0x68, 0xDF,
+	0x49, 0x37, 0x49, 0xDF,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x34, 0x80, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x54, 0xB0,
+	0x02, 0x44, 0x64, 0xB0,
+
+	0x2A, 0x44, 0x54, 0xB2,
+	0x1A, 0x44, 0x64, 0xB2,
+
+	0x25, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x3D, 0xCF, 0x74, 0xC2,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x2A, 0x44, 0x54, 0xB4,
+	0x1A, 0x44, 0x64, 0xB4,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x38, 0x3D, 0x20, 0xE9,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x2A, 0x46, 0x56, 0xBF,
+	0x1A, 0x46, 0x66, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x0A, 0x47, 0x57, 0xBF,
+	0x02, 0x47, 0x67, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x53, 0xBF,
+	0x1A, 0x43, 0x63, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x48, 0x58, 0xBF,
+	0x02, 0x48, 0x68, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x2A, 0x49, 0x59, 0xBF,
+	0x1A, 0x49, 0x69, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x82, 0x30, 0x57, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x83, 0x38, 0x57, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x84, 0x31, 0x5E, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x85, 0x39, 0x5E, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x87, 0x77, 0x57, 0xE9,
+	0x8B, 0x3E, 0xBF, 0xEA,
+
+	0x80, 0x30, 0x57, 0xE9,
+	0x81, 0x38, 0x57, 0xE9,
+
+	0x82, 0x31, 0x57, 0xE9,
+	0x86, 0x78, 0x57, 0xE9,
+
+	0x83, 0x39, 0x57, 0xE9,
+	0x87, 0x79, 0x57, 0xE9,
+
+	0x30, 0x1F, 0x5F, 0xE9,
+	0x8A, 0x34, 0x20, 0xE9,
+
+	0x8B, 0x3C, 0x20, 0xE9,
+	0x37, 0x50, 0x60, 0xBD,
+
+	0x57, 0x0D, 0x20, 0xE9,
+	0x35, 0x51, 0x61, 0xBD,
+
+	0x2B, 0x50, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x0E, 0x77,
+
+	0x24, 0x51, 0x20, 0xE9,
+	0x9F, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x0E, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x0B, 0x46, 0xA0, 0xE8,
+	0x1B, 0x56, 0xA0, 0xE8,
+
+	0x2B, 0x66, 0xA0, 0xE8,
+	0x0C, 0x47, 0xA0, 0xE8,
+
+	0x1C, 0x57, 0xA0, 0xE8,
+	0x2C, 0x67, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x57, 0x80, 0x57, 0xCF,
+
+	0x66, 0x33, 0x66, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x67, 0x3B, 0x67, 0xCF,
+
+	0x0B, 0x48, 0xA0, 0xE8,
+	0x1B, 0x58, 0xA0, 0xE8,
+
+	0x2B, 0x68, 0xA0, 0xE8,
+	0x0C, 0x49, 0xA0, 0xE8,
+
+	0x1C, 0x59, 0xA0, 0xE8,
+	0x2C, 0x69, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x34, 0xD7, 0x34, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3C, 0xD7, 0x3C, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x34, 0x80, 0x34, 0xBD,
+	0x3C, 0x80, 0x3C, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x48, 0x80, 0x48, 0xCF,
+	0x59, 0x80, 0x59, 0xCF,
+
+	0x68, 0x33, 0x68, 0xCF,
+	0x49, 0x3B, 0x49, 0xCF,
+
+	0xBE, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x58, 0x33, 0x58, 0xCF,
+	0x69, 0x3B, 0x69, 0xCF,
+
+	0x7D, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gza[] = {
+
+	0x00, 0x8A, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0A, 0x40, 0x50, 0xBF,
+	0x2A, 0x40, 0x60, 0xBF,
+
+	0x32, 0x41, 0x51, 0xBF,
+	0x3A, 0x41, 0x61, 0xBF,
+
+	0xC3, 0x6B,
+	0xD3, 0x6B,
+	0x00, 0x8A, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x23, 0x9F,
+	0x00, 0xE0,
+	0x51, 0x04,
+
+	0x90, 0xE2,
+	0x61, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x51, 0x41, 0xE0, 0xEC,
+	0x39, 0x67, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x63, 0xA0, 0xE8,
+
+	0x61, 0x41, 0xE0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x7C, 0x80, 0x15, 0xEA,
+	0x10, 0x04,
+	0x20, 0x04,
+
+	0x61, 0x51, 0xE0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x52, 0xBF,
+	0x0F, 0x52, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x62, 0xBF,
+	0x1E, 0x51, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x0E, 0x61, 0x60, 0xEA,
+
+	0x32, 0x40, 0x50, 0xBD,
+	0x22, 0x40, 0x60, 0xBD,
+
+	0x12, 0x41, 0x51, 0xBD,
+	0x3A, 0x41, 0x61, 0xBD,
+
+	0xBF, 0x2F, 0x0E, 0xBD,
+	0x97, 0xE2,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x35, 0x48, 0xB1, 0xE8,
+	0x3D, 0x59, 0xB1, 0xE8,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x56, 0x31, 0x56, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x66, 0x31, 0x66, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x57, 0x39, 0x57, 0xBF,
+	0x67, 0x39, 0x67, 0xBF,
+
+	0x6D, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x35, 0x00,
+	0x3D, 0x00,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0x8D, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x75, 0xF8, 0xEC,
+	0x35, 0x20,
+	0x3D, 0x20,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x53, 0x53, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x0E, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x48, 0x35, 0x48, 0xBF,
+	0x58, 0x35, 0x58, 0xBF,
+
+	0x68, 0x35, 0x68, 0xBF,
+	0x49, 0x3D, 0x49, 0xBF,
+
+	0x59, 0x3D, 0x59, 0xBF,
+	0x69, 0x3D, 0x69, 0xBF,
+
+	0x63, 0x63, 0x2D, 0xDF,
+	0x4D, 0x7D, 0xF8, 0xEC,
+
+	0x59, 0xE3,
+	0x00, 0xE0,
+	0xB8, 0x38, 0x33, 0xBF,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x18, 0x3A, 0x41, 0xE9,
+
+	0x3F, 0x53, 0xA0, 0xE8,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x63, 0xA0, 0xE8,
+
+	0x50, 0x70, 0xF8, 0xEC,
+	0x2B, 0x50, 0x3C, 0xE9,
+
+	0x1F, 0x0F, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x59, 0x78, 0xF8, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x56, 0x3F, 0x56, 0xDF,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x66, 0x3D, 0x66, 0xDF,
+
+	0x1D, 0x32, 0x41, 0xE9,
+	0x67, 0x3D, 0x67, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3F, 0x57, 0xDF,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x59, 0x3F, 0x59, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x69, 0x3D, 0x69, 0xDF,
+
+	0x48, 0x37, 0x48, 0xDF,
+	0x58, 0x3F, 0x58, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x68, 0x3D, 0x68, 0xDF,
+	0x49, 0x37, 0x49, 0xDF,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x34, 0x80, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x54, 0xB0,
+	0x02, 0x44, 0x64, 0xB0,
+
+	0x2A, 0x44, 0x54, 0xB2,
+	0x1A, 0x44, 0x64, 0xB2,
+
+	0x29, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x0F, 0xCF, 0x74, 0xC6,
+	0x3D, 0xCF, 0x74, 0xC2,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9C, 0x0F, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x54, 0xB4,
+	0x02, 0x44, 0x64, 0xB4,
+
+	0x2A, 0x44, 0x54, 0xB6,
+	0x1A, 0x44, 0x64, 0xB6,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x38, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x20,
+	0x02, 0x20,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x0A, 0x47, 0x57, 0xBF,
+	0x02, 0x47, 0x67, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x46, 0x56, 0xBF,
+	0x1A, 0x46, 0x66, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x36, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x37, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x53, 0xBF,
+	0x1A, 0x43, 0x63, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x9D, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x9E, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x48, 0x58, 0xBF,
+	0x02, 0x48, 0x68, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x2A, 0x49, 0x59, 0xBF,
+	0x1A, 0x49, 0x69, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x82, 0x30, 0x57, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x83, 0x38, 0x57, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x84, 0x31, 0x5E, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x85, 0x39, 0x5E, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x87, 0x77, 0x57, 0xE9,
+	0x8B, 0x3E, 0xBF, 0xEA,
+
+	0x80, 0x30, 0x57, 0xE9,
+	0x81, 0x38, 0x57, 0xE9,
+
+	0x82, 0x31, 0x57, 0xE9,
+	0x86, 0x78, 0x57, 0xE9,
+
+	0x83, 0x39, 0x57, 0xE9,
+	0x87, 0x79, 0x57, 0xE9,
+
+	0x30, 0x1F, 0x5F, 0xE9,
+	0x8A, 0x34, 0x20, 0xE9,
+
+	0x8B, 0x3C, 0x20, 0xE9,
+	0x37, 0x50, 0x60, 0xBD,
+
+	0x57, 0x0D, 0x20, 0xE9,
+	0x35, 0x51, 0x61, 0xBD,
+
+	0x2B, 0x50, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x0E, 0x77,
+
+	0x24, 0x51, 0x20, 0xE9,
+	0x9B, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x0E, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x0B, 0x46, 0xA0, 0xE8,
+	0x1B, 0x56, 0xA0, 0xE8,
+
+	0x2B, 0x66, 0xA0, 0xE8,
+	0x0C, 0x47, 0xA0, 0xE8,
+
+	0x1C, 0x57, 0xA0, 0xE8,
+	0x2C, 0x67, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x57, 0x80, 0x57, 0xCF,
+
+	0x66, 0x33, 0x66, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x67, 0x3B, 0x67, 0xCF,
+
+	0x0B, 0x48, 0xA0, 0xE8,
+	0x1B, 0x58, 0xA0, 0xE8,
+
+	0x2B, 0x68, 0xA0, 0xE8,
+	0x0C, 0x49, 0xA0, 0xE8,
+
+	0x1C, 0x59, 0xA0, 0xE8,
+	0x2C, 0x69, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x34, 0xD7, 0x34, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3C, 0xD7, 0x3C, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x34, 0x80, 0x34, 0xBD,
+	0x3C, 0x80, 0x3C, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x48, 0x80, 0x48, 0xCF,
+	0x59, 0x80, 0x59, 0xCF,
+
+	0x68, 0x33, 0x68, 0xCF,
+	0x49, 0x3B, 0x49, 0xCF,
+
+	0xBA, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x58, 0x33, 0x58, 0xCF,
+	0x69, 0x3B, 0x69, 0xCF,
+
+	0x79, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzaf[] = {
+
+	0x00, 0x8A, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0A, 0x40, 0x50, 0xBF,
+	0x2A, 0x40, 0x60, 0xBF,
+
+	0x32, 0x41, 0x51, 0xBF,
+	0x3A, 0x41, 0x61, 0xBF,
+
+	0xC3, 0x6B,
+	0xD3, 0x6B,
+	0x00, 0x8A, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x23, 0x9F,
+	0x00, 0xE0,
+	0x51, 0x04,
+
+	0x90, 0xE2,
+	0x61, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x51, 0x41, 0xE0, 0xEC,
+	0x39, 0x67, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x63, 0xA0, 0xE8,
+
+	0x61, 0x41, 0xE0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x81, 0x80, 0x15, 0xEA,
+	0x10, 0x04,
+	0x20, 0x04,
+
+	0x61, 0x51, 0xE0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x52, 0xBF,
+	0x0F, 0x52, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x62, 0xBF,
+	0x1E, 0x51, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x0E, 0x61, 0x60, 0xEA,
+
+	0x32, 0x40, 0x50, 0xBD,
+	0x22, 0x40, 0x60, 0xBD,
+
+	0x12, 0x41, 0x51, 0xBD,
+	0x3A, 0x41, 0x61, 0xBD,
+
+	0xBF, 0x2F, 0x0E, 0xBD,
+	0x97, 0xE2,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x35, 0x48, 0xB1, 0xE8,
+	0x3D, 0x59, 0xB1, 0xE8,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x56, 0x31, 0x56, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x66, 0x31, 0x66, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x57, 0x39, 0x57, 0xBF,
+	0x67, 0x39, 0x67, 0xBF,
+
+	0x72, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x35, 0x00,
+	0x3D, 0x00,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0x8D, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x75, 0xF8, 0xEC,
+	0x35, 0x20,
+	0x3D, 0x20,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x53, 0x53, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x0E, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x48, 0x35, 0x48, 0xBF,
+	0x58, 0x35, 0x58, 0xBF,
+
+	0x68, 0x35, 0x68, 0xBF,
+	0x49, 0x3D, 0x49, 0xBF,
+
+	0x59, 0x3D, 0x59, 0xBF,
+	0x69, 0x3D, 0x69, 0xBF,
+
+	0x63, 0x63, 0x2D, 0xDF,
+	0x4D, 0x7D, 0xF8, 0xEC,
+
+	0x59, 0xE3,
+	0x00, 0xE0,
+	0xB8, 0x38, 0x33, 0xBF,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x18, 0x3A, 0x41, 0xE9,
+
+	0x3F, 0x53, 0xA0, 0xE8,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x63, 0xA0, 0xE8,
+
+	0x50, 0x70, 0xF8, 0xEC,
+	0x2B, 0x50, 0x3C, 0xE9,
+
+	0x1F, 0x0F, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x59, 0x78, 0xF8, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x56, 0x3F, 0x56, 0xDF,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x66, 0x3D, 0x66, 0xDF,
+
+	0x1D, 0x32, 0x41, 0xE9,
+	0x67, 0x3D, 0x67, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3F, 0x57, 0xDF,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x59, 0x3F, 0x59, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x69, 0x3D, 0x69, 0xDF,
+
+	0x48, 0x37, 0x48, 0xDF,
+	0x58, 0x3F, 0x58, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x68, 0x3D, 0x68, 0xDF,
+	0x49, 0x37, 0x49, 0xDF,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x54, 0xB0,
+	0x02, 0x44, 0x64, 0xB0,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB2,
+	0x1A, 0x44, 0x64, 0xB2,
+
+	0x2E, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x3D, 0xCF, 0x74, 0xC2,
+	0x0F, 0xCF, 0x74, 0xC6,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9C, 0x0F, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x54, 0xB4,
+	0x02, 0x44, 0x64, 0xB4,
+
+	0x2A, 0x44, 0x54, 0xB6,
+	0x1A, 0x44, 0x64, 0xB6,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x38, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x20,
+	0x02, 0x20,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x3D, 0xCF, 0x75, 0xC6,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x0A, 0x45, 0x55, 0xB6,
+	0x02, 0x45, 0x65, 0xB6,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x3D, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x2A, 0x46, 0x56, 0xBF,
+	0x1A, 0x46, 0x66, 0xBF,
+
+	0x0A, 0x47, 0x57, 0xBF,
+	0x02, 0x47, 0x67, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x38, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9D, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x9E, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x53, 0xBF,
+	0x1A, 0x43, 0x63, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x35, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x39, 0x38, 0x4F, 0xE9,
+
+	0x0A, 0x48, 0x58, 0xBF,
+	0x02, 0x48, 0x68, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x2A, 0x49, 0x59, 0xBF,
+	0x1A, 0x49, 0x69, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x82, 0x30, 0x57, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x83, 0x38, 0x57, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x84, 0x31, 0x5E, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x85, 0x39, 0x5E, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x87, 0x77, 0x57, 0xE9,
+	0x8B, 0x3E, 0xBF, 0xEA,
+
+	0x80, 0x30, 0x57, 0xE9,
+	0x81, 0x38, 0x57, 0xE9,
+
+	0x82, 0x31, 0x57, 0xE9,
+	0x86, 0x78, 0x57, 0xE9,
+
+	0x83, 0x39, 0x57, 0xE9,
+	0x87, 0x79, 0x57, 0xE9,
+
+	0x30, 0x1F, 0x5F, 0xE9,
+	0x8A, 0x34, 0x20, 0xE9,
+
+	0x8B, 0x3C, 0x20, 0xE9,
+	0x37, 0x50, 0x60, 0xBD,
+
+	0x57, 0x0D, 0x20, 0xE9,
+	0x35, 0x51, 0x61, 0xBD,
+
+	0x2B, 0x50, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x0E, 0x77,
+
+	0x24, 0x51, 0x20, 0xE9,
+	0x96, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x0E, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x0B, 0x46, 0xA0, 0xE8,
+	0x1B, 0x56, 0xA0, 0xE8,
+
+	0x2B, 0x66, 0xA0, 0xE8,
+	0x0C, 0x47, 0xA0, 0xE8,
+
+	0x1C, 0x57, 0xA0, 0xE8,
+	0x2C, 0x67, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x57, 0x80, 0x57, 0xCF,
+
+	0x66, 0x33, 0x66, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x67, 0x3B, 0x67, 0xCF,
+
+	0x0B, 0x48, 0xA0, 0xE8,
+	0x1B, 0x58, 0xA0, 0xE8,
+
+	0x2B, 0x68, 0xA0, 0xE8,
+	0x0C, 0x49, 0xA0, 0xE8,
+
+	0x1C, 0x59, 0xA0, 0xE8,
+	0x2C, 0x69, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x34, 0xD7, 0x34, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3C, 0xD7, 0x3C, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x34, 0x80, 0x34, 0xBD,
+	0x3C, 0x80, 0x3C, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x48, 0x80, 0x48, 0xCF,
+	0x59, 0x80, 0x59, 0xCF,
+
+	0x68, 0x33, 0x68, 0xCF,
+	0x49, 0x3B, 0x49, 0xCF,
+
+	0xB5, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x58, 0x33, 0x58, 0xCF,
+	0x69, 0x3B, 0x69, 0xCF,
+
+	0x74, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzf[] = {
+
+	0x00, 0x8A, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0A, 0x40, 0x50, 0xBF,
+	0x2A, 0x40, 0x60, 0xBF,
+
+	0x32, 0x41, 0x51, 0xBF,
+	0x3A, 0x41, 0x61, 0xBF,
+
+	0xC3, 0x6B,
+	0xD3, 0x6B,
+	0x00, 0x8A, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x23, 0x9F,
+	0x00, 0xE0,
+	0x51, 0x04,
+
+	0x90, 0xE2,
+	0x61, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x51, 0x41, 0xE0, 0xEC,
+	0x39, 0x67, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x63, 0xA0, 0xE8,
+
+	0x61, 0x41, 0xE0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x7D, 0x80, 0x15, 0xEA,
+	0x10, 0x04,
+	0x20, 0x04,
+
+	0x61, 0x51, 0xE0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x52, 0xBF,
+	0x0F, 0x52, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x62, 0xBF,
+	0x1E, 0x51, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x0E, 0x61, 0x60, 0xEA,
+
+	0x32, 0x40, 0x50, 0xBD,
+	0x22, 0x40, 0x60, 0xBD,
+
+	0x12, 0x41, 0x51, 0xBD,
+	0x3A, 0x41, 0x61, 0xBD,
+
+	0xBF, 0x2F, 0x0E, 0xBD,
+	0x97, 0xE2,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x35, 0x48, 0xB1, 0xE8,
+	0x3D, 0x59, 0xB1, 0xE8,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x56, 0x31, 0x56, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x66, 0x31, 0x66, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x57, 0x39, 0x57, 0xBF,
+	0x67, 0x39, 0x67, 0xBF,
+
+	0x6E, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x35, 0x00,
+	0x3D, 0x00,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0x8D, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x75, 0xF8, 0xEC,
+	0x35, 0x20,
+	0x3D, 0x20,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x53, 0x53, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x0E, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x48, 0x35, 0x48, 0xBF,
+	0x58, 0x35, 0x58, 0xBF,
+
+	0x68, 0x35, 0x68, 0xBF,
+	0x49, 0x3D, 0x49, 0xBF,
+
+	0x59, 0x3D, 0x59, 0xBF,
+	0x69, 0x3D, 0x69, 0xBF,
+
+	0x63, 0x63, 0x2D, 0xDF,
+	0x4D, 0x7D, 0xF8, 0xEC,
+
+	0x59, 0xE3,
+	0x00, 0xE0,
+	0xB8, 0x38, 0x33, 0xBF,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x18, 0x3A, 0x41, 0xE9,
+
+	0x3F, 0x53, 0xA0, 0xE8,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x63, 0xA0, 0xE8,
+
+	0x50, 0x70, 0xF8, 0xEC,
+	0x2B, 0x50, 0x3C, 0xE9,
+
+	0x1F, 0x0F, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x59, 0x78, 0xF8, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x56, 0x3F, 0x56, 0xDF,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x66, 0x3D, 0x66, 0xDF,
+
+	0x1D, 0x32, 0x41, 0xE9,
+	0x67, 0x3D, 0x67, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3F, 0x57, 0xDF,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x59, 0x3F, 0x59, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x69, 0x3D, 0x69, 0xDF,
+
+	0x48, 0x37, 0x48, 0xDF,
+	0x58, 0x3F, 0x58, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x68, 0x3D, 0x68, 0xDF,
+	0x49, 0x37, 0x49, 0xDF,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x34, 0x80, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0F, 0xCF, 0x75, 0xC6,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x54, 0xB0,
+	0x02, 0x44, 0x64, 0xB0,
+
+	0x2A, 0x44, 0x54, 0xB2,
+	0x1A, 0x44, 0x64, 0xB2,
+
+	0x28, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x3D, 0xCF, 0x74, 0xC2,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x31, 0x0F, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x54, 0xB4,
+	0x02, 0x44, 0x64, 0xB4,
+
+	0x2A, 0x45, 0x55, 0xB6,
+	0x1A, 0x45, 0x65, 0xB6,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x38, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x20,
+	0x02, 0x20,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x0A, 0x47, 0x57, 0xBF,
+	0x02, 0x47, 0x67, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x46, 0x56, 0xBF,
+	0x1A, 0x46, 0x66, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x36, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x37, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x53, 0xBF,
+	0x1A, 0x43, 0x63, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x35, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x39, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x48, 0x58, 0xBF,
+	0x02, 0x48, 0x68, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x2A, 0x49, 0x59, 0xBF,
+	0x1A, 0x49, 0x69, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x82, 0x30, 0x57, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x83, 0x38, 0x57, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x84, 0x31, 0x5E, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x85, 0x39, 0x5E, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x87, 0x77, 0x57, 0xE9,
+	0x8B, 0x3E, 0xBF, 0xEA,
+
+	0x80, 0x30, 0x57, 0xE9,
+	0x81, 0x38, 0x57, 0xE9,
+
+	0x82, 0x31, 0x57, 0xE9,
+	0x86, 0x78, 0x57, 0xE9,
+
+	0x83, 0x39, 0x57, 0xE9,
+	0x87, 0x79, 0x57, 0xE9,
+
+	0x30, 0x1F, 0x5F, 0xE9,
+	0x8A, 0x34, 0x20, 0xE9,
+
+	0x8B, 0x3C, 0x20, 0xE9,
+	0x37, 0x50, 0x60, 0xBD,
+
+	0x57, 0x0D, 0x20, 0xE9,
+	0x35, 0x51, 0x61, 0xBD,
+
+	0x2B, 0x50, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x0E, 0x77,
+
+	0x24, 0x51, 0x20, 0xE9,
+	0x9A, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x0E, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x0B, 0x46, 0xA0, 0xE8,
+	0x1B, 0x56, 0xA0, 0xE8,
+
+	0x2B, 0x66, 0xA0, 0xE8,
+	0x0C, 0x47, 0xA0, 0xE8,
+
+	0x1C, 0x57, 0xA0, 0xE8,
+	0x2C, 0x67, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x57, 0x80, 0x57, 0xCF,
+
+	0x66, 0x33, 0x66, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x67, 0x3B, 0x67, 0xCF,
+
+	0x0B, 0x48, 0xA0, 0xE8,
+	0x1B, 0x58, 0xA0, 0xE8,
+
+	0x2B, 0x68, 0xA0, 0xE8,
+	0x0C, 0x49, 0xA0, 0xE8,
+
+	0x1C, 0x59, 0xA0, 0xE8,
+	0x2C, 0x69, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x34, 0xD7, 0x34, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3C, 0xD7, 0x3C, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x34, 0x80, 0x34, 0xBD,
+	0x3C, 0x80, 0x3C, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x48, 0x80, 0x48, 0xCF,
+	0x59, 0x80, 0x59, 0xCF,
+
+	0x68, 0x33, 0x68, 0xCF,
+	0x49, 0x3B, 0x49, 0xCF,
+
+	0xBB, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x58, 0x33, 0x58, 0xCF,
+	0x69, 0x3B, 0x69, 0xCF,
+
+	0x78, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzs[] = {
+
+	0x00, 0x8A, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0A, 0x40, 0x50, 0xBF,
+	0x2A, 0x40, 0x60, 0xBF,
+
+	0x32, 0x41, 0x51, 0xBF,
+	0x3A, 0x41, 0x61, 0xBF,
+
+	0xC3, 0x6B,
+	0xD3, 0x6B,
+	0x00, 0x8A, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x23, 0x9F,
+	0x00, 0xE0,
+	0x51, 0x04,
+
+	0x90, 0xE2,
+	0x61, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x51, 0x41, 0xE0, 0xEC,
+	0x39, 0x67, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x63, 0xA0, 0xE8,
+
+	0x61, 0x41, 0xE0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x85, 0x80, 0x15, 0xEA,
+	0x10, 0x04,
+	0x20, 0x04,
+
+	0x61, 0x51, 0xE0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x52, 0xBF,
+	0x0F, 0x52, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x62, 0xBF,
+	0x1E, 0x51, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x0E, 0x61, 0x60, 0xEA,
+
+	0x32, 0x40, 0x50, 0xBD,
+	0x22, 0x40, 0x60, 0xBD,
+
+	0x12, 0x41, 0x51, 0xBD,
+	0x3A, 0x41, 0x61, 0xBD,
+
+	0xBF, 0x2F, 0x0E, 0xBD,
+	0x97, 0xE2,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x35, 0x48, 0xB1, 0xE8,
+	0x3D, 0x59, 0xB1, 0xE8,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x56, 0x31, 0x56, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x66, 0x31, 0x66, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x57, 0x39, 0x57, 0xBF,
+	0x67, 0x39, 0x67, 0xBF,
+
+	0x76, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x35, 0x00,
+	0x3D, 0x00,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0x8D, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x75, 0xF8, 0xEC,
+	0x35, 0x20,
+	0x3D, 0x20,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x53, 0x53, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x0E, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x48, 0x35, 0x48, 0xBF,
+	0x58, 0x35, 0x58, 0xBF,
+
+	0x68, 0x35, 0x68, 0xBF,
+	0x49, 0x3D, 0x49, 0xBF,
+
+	0x59, 0x3D, 0x59, 0xBF,
+	0x69, 0x3D, 0x69, 0xBF,
+
+	0x63, 0x63, 0x2D, 0xDF,
+	0x4D, 0x7D, 0xF8, 0xEC,
+
+	0x59, 0xE3,
+	0x00, 0xE0,
+	0xB8, 0x38, 0x33, 0xBF,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x18, 0x3A, 0x41, 0xE9,
+
+	0x3F, 0x53, 0xA0, 0xE8,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x63, 0xA0, 0xE8,
+
+	0x50, 0x70, 0xF8, 0xEC,
+	0x2B, 0x50, 0x3C, 0xE9,
+
+	0x1F, 0x0F, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x59, 0x78, 0xF8, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x56, 0x3F, 0x56, 0xDF,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x66, 0x3D, 0x66, 0xDF,
+
+	0x1D, 0x32, 0x41, 0xE9,
+	0x67, 0x3D, 0x67, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3F, 0x57, 0xDF,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x59, 0x3F, 0x59, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x69, 0x3D, 0x69, 0xDF,
+
+	0x48, 0x37, 0x48, 0xDF,
+	0x58, 0x3F, 0x58, 0xDF,
+
+	0x68, 0x3D, 0x68, 0xDF,
+	0x49, 0x37, 0x49, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x0F, 0xCF, 0x74, 0xC2,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x54, 0xB0,
+	0x02, 0x44, 0x64, 0xB0,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x38, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB2,
+	0x1A, 0x44, 0x64, 0xB2,
+
+	0x31, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x0F, 0xCF, 0x75, 0xC0,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x3D, 0xCF, 0x75, 0xC2,
+	0x37, 0xCF, 0x75, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA6, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA3, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB4,
+	0x1A, 0x44, 0x64, 0xB4,
+
+	0x0A, 0x45, 0x55, 0xB0,
+	0x02, 0x45, 0x65, 0xB0,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA0, 0x37, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x55, 0xB2,
+	0x1A, 0x45, 0x65, 0xB2,
+
+	0x0A, 0x45, 0x55, 0xB4,
+	0x02, 0x45, 0x65, 0xB4,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x20,
+	0x1A, 0x20,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x2A, 0x46, 0x56, 0xBF,
+	0x1A, 0x46, 0x66, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0xA7, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0xA8, 0x38, 0x4F, 0xE9,
+
+	0x0A, 0x47, 0x57, 0xBF,
+	0x02, 0x47, 0x67, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA4, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA5, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x53, 0xBF,
+	0x1A, 0x43, 0x63, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0xA1, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0xA2, 0x38, 0x4F, 0xE9,
+
+	0x0A, 0x48, 0x58, 0xBF,
+	0x02, 0x48, 0x68, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x2A, 0x49, 0x59, 0xBF,
+	0x1A, 0x49, 0x69, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x82, 0x30, 0x57, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x83, 0x38, 0x57, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x84, 0x31, 0x5E, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x85, 0x39, 0x5E, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x87, 0x77, 0x57, 0xE9,
+	0x8B, 0x3E, 0xBF, 0xEA,
+
+	0x80, 0x30, 0x57, 0xE9,
+	0x81, 0x38, 0x57, 0xE9,
+
+	0x82, 0x31, 0x57, 0xE9,
+	0x86, 0x78, 0x57, 0xE9,
+
+	0x83, 0x39, 0x57, 0xE9,
+	0x87, 0x79, 0x57, 0xE9,
+
+	0x30, 0x1F, 0x5F, 0xE9,
+	0x8A, 0x34, 0x20, 0xE9,
+
+	0x8B, 0x3C, 0x20, 0xE9,
+	0x37, 0x50, 0x60, 0xBD,
+
+	0x57, 0x0D, 0x20, 0xE9,
+	0x35, 0x51, 0x61, 0xBD,
+
+	0x2B, 0x50, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x0E, 0x77,
+
+	0x24, 0x51, 0x20, 0xE9,
+	0x92, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x0E, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x0B, 0x46, 0xA0, 0xE8,
+	0x1B, 0x56, 0xA0, 0xE8,
+
+	0x2B, 0x66, 0xA0, 0xE8,
+	0x0C, 0x47, 0xA0, 0xE8,
+
+	0x1C, 0x57, 0xA0, 0xE8,
+	0x2C, 0x67, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x57, 0x80, 0x57, 0xCF,
+
+	0x66, 0x33, 0x66, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x67, 0x3B, 0x67, 0xCF,
+
+	0x0B, 0x48, 0xA0, 0xE8,
+	0x1B, 0x58, 0xA0, 0xE8,
+
+	0x2B, 0x68, 0xA0, 0xE8,
+	0x0C, 0x49, 0xA0, 0xE8,
+
+	0x1C, 0x59, 0xA0, 0xE8,
+	0x2C, 0x69, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x34, 0xD7, 0x34, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3C, 0xD7, 0x3C, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x34, 0x80, 0x34, 0xBD,
+	0x3C, 0x80, 0x3C, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x48, 0x80, 0x48, 0xCF,
+	0x59, 0x80, 0x59, 0xCF,
+
+	0x68, 0x33, 0x68, 0xCF,
+	0x49, 0x3B, 0x49, 0xCF,
+
+	0xB2, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x58, 0x33, 0x58, 0xCF,
+	0x69, 0x3B, 0x69, 0xCF,
+
+	0x70, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsa[] = {
+
+	0x00, 0x8A, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0A, 0x40, 0x50, 0xBF,
+	0x2A, 0x40, 0x60, 0xBF,
+
+	0x32, 0x41, 0x51, 0xBF,
+	0x3A, 0x41, 0x61, 0xBF,
+
+	0xC3, 0x6B,
+	0xD3, 0x6B,
+	0x00, 0x8A, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x23, 0x9F,
+	0x00, 0xE0,
+	0x51, 0x04,
+
+	0x90, 0xE2,
+	0x61, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x51, 0x41, 0xE0, 0xEC,
+	0x39, 0x67, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x63, 0xA0, 0xE8,
+
+	0x61, 0x41, 0xE0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x8A, 0x80, 0x15, 0xEA,
+	0x10, 0x04,
+	0x20, 0x04,
+
+	0x61, 0x51, 0xE0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x52, 0xBF,
+	0x0F, 0x52, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x62, 0xBF,
+	0x1E, 0x51, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x0E, 0x61, 0x60, 0xEA,
+
+	0x32, 0x40, 0x50, 0xBD,
+	0x22, 0x40, 0x60, 0xBD,
+
+	0x12, 0x41, 0x51, 0xBD,
+	0x3A, 0x41, 0x61, 0xBD,
+
+	0xBF, 0x2F, 0x0E, 0xBD,
+	0x97, 0xE2,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x35, 0x48, 0xB1, 0xE8,
+	0x3D, 0x59, 0xB1, 0xE8,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x56, 0x31, 0x56, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x66, 0x31, 0x66, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x57, 0x39, 0x57, 0xBF,
+	0x67, 0x39, 0x67, 0xBF,
+
+	0x7B, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x35, 0x00,
+	0x3D, 0x00,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0x8D, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x75, 0xF8, 0xEC,
+	0x35, 0x20,
+	0x3D, 0x20,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x53, 0x53, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x0E, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x48, 0x35, 0x48, 0xBF,
+	0x58, 0x35, 0x58, 0xBF,
+
+	0x68, 0x35, 0x68, 0xBF,
+	0x49, 0x3D, 0x49, 0xBF,
+
+	0x59, 0x3D, 0x59, 0xBF,
+	0x69, 0x3D, 0x69, 0xBF,
+
+	0x63, 0x63, 0x2D, 0xDF,
+	0x4D, 0x7D, 0xF8, 0xEC,
+
+	0x59, 0xE3,
+	0x00, 0xE0,
+	0xB8, 0x38, 0x33, 0xBF,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x18, 0x3A, 0x41, 0xE9,
+
+	0x3F, 0x53, 0xA0, 0xE8,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x63, 0xA0, 0xE8,
+
+	0x50, 0x70, 0xF8, 0xEC,
+	0x2B, 0x50, 0x3C, 0xE9,
+
+	0x1F, 0x0F, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x59, 0x78, 0xF8, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x56, 0x3F, 0x56, 0xDF,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x66, 0x3D, 0x66, 0xDF,
+
+	0x1D, 0x32, 0x41, 0xE9,
+	0x67, 0x3D, 0x67, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3F, 0x57, 0xDF,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x59, 0x3F, 0x59, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x69, 0x3D, 0x69, 0xDF,
+
+	0x48, 0x37, 0x48, 0xDF,
+	0x58, 0x3F, 0x58, 0xDF,
+
+	0x68, 0x3D, 0x68, 0xDF,
+	0x49, 0x37, 0x49, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x0F, 0xCF, 0x74, 0xC2,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x54, 0xB0,
+	0x02, 0x44, 0x64, 0xB0,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x38, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB2,
+	0x1A, 0x44, 0x64, 0xB2,
+
+	0x36, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x0F, 0xCF, 0x75, 0xC0,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x3D, 0xCF, 0x75, 0xC2,
+	0x37, 0xCF, 0x75, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA6, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA3, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB4,
+	0x1A, 0x44, 0x64, 0xB4,
+
+	0x0A, 0x45, 0x55, 0xB0,
+	0x02, 0x45, 0x65, 0xB0,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA0, 0x37, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x55, 0xB2,
+	0x1A, 0x45, 0x65, 0xB2,
+
+	0x0A, 0x45, 0x55, 0xB4,
+	0x02, 0x45, 0x65, 0xB4,
+
+	0x0F, 0xCF, 0x74, 0xC6,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA7, 0x30, 0x4F, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9C, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA8, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB6,
+	0x1A, 0x44, 0x64, 0xB6,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x2A, 0x46, 0x56, 0xBF,
+	0x1A, 0x46, 0x66, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA4, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA5, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x47, 0x57, 0xBF,
+	0x02, 0x47, 0x67, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA1, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA2, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x53, 0xBF,
+	0x1A, 0x43, 0x63, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x9D, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x9E, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x48, 0x58, 0xBF,
+	0x02, 0x48, 0x68, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x2A, 0x49, 0x59, 0xBF,
+	0x1A, 0x49, 0x69, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x82, 0x30, 0x57, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x83, 0x38, 0x57, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x84, 0x31, 0x5E, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x85, 0x39, 0x5E, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x87, 0x77, 0x57, 0xE9,
+	0x8B, 0x3E, 0xBF, 0xEA,
+
+	0x80, 0x30, 0x57, 0xE9,
+	0x81, 0x38, 0x57, 0xE9,
+
+	0x82, 0x31, 0x57, 0xE9,
+	0x86, 0x78, 0x57, 0xE9,
+
+	0x83, 0x39, 0x57, 0xE9,
+	0x87, 0x79, 0x57, 0xE9,
+
+	0x30, 0x1F, 0x5F, 0xE9,
+	0x8A, 0x34, 0x20, 0xE9,
+
+	0x8B, 0x3C, 0x20, 0xE9,
+	0x37, 0x50, 0x60, 0xBD,
+
+	0x57, 0x0D, 0x20, 0xE9,
+	0x35, 0x51, 0x61, 0xBD,
+
+	0x2B, 0x50, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x0E, 0x77,
+
+	0x24, 0x51, 0x20, 0xE9,
+	0x8D, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x0E, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x0B, 0x46, 0xA0, 0xE8,
+	0x1B, 0x56, 0xA0, 0xE8,
+
+	0x2B, 0x66, 0xA0, 0xE8,
+	0x0C, 0x47, 0xA0, 0xE8,
+
+	0x1C, 0x57, 0xA0, 0xE8,
+	0x2C, 0x67, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x57, 0x80, 0x57, 0xCF,
+
+	0x66, 0x33, 0x66, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x67, 0x3B, 0x67, 0xCF,
+
+	0x0B, 0x48, 0xA0, 0xE8,
+	0x1B, 0x58, 0xA0, 0xE8,
+
+	0x2B, 0x68, 0xA0, 0xE8,
+	0x0C, 0x49, 0xA0, 0xE8,
+
+	0x1C, 0x59, 0xA0, 0xE8,
+	0x2C, 0x69, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x34, 0xD7, 0x34, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3C, 0xD7, 0x3C, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x34, 0x80, 0x34, 0xBD,
+	0x3C, 0x80, 0x3C, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x48, 0x80, 0x48, 0xCF,
+	0x59, 0x80, 0x59, 0xCF,
+
+	0x68, 0x33, 0x68, 0xCF,
+	0x49, 0x3B, 0x49, 0xCF,
+
+	0xAD, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x58, 0x33, 0x58, 0xCF,
+	0x69, 0x3B, 0x69, 0xCF,
+
+	0x6B, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsaf[] = {
+
+	0x00, 0x8A, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0A, 0x40, 0x50, 0xBF,
+	0x2A, 0x40, 0x60, 0xBF,
+
+	0x32, 0x41, 0x51, 0xBF,
+	0x3A, 0x41, 0x61, 0xBF,
+
+	0xC3, 0x6B,
+	0xD3, 0x6B,
+	0x00, 0x8A, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x23, 0x9F,
+	0x00, 0xE0,
+	0x51, 0x04,
+
+	0x90, 0xE2,
+	0x61, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x51, 0x41, 0xE0, 0xEC,
+	0x39, 0x67, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x63, 0xA0, 0xE8,
+
+	0x61, 0x41, 0xE0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x8E, 0x80, 0x15, 0xEA,
+	0x10, 0x04,
+	0x20, 0x04,
+
+	0x61, 0x51, 0xE0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x52, 0xBF,
+	0x0F, 0x52, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x62, 0xBF,
+	0x1E, 0x51, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x0E, 0x61, 0x60, 0xEA,
+
+	0x32, 0x40, 0x50, 0xBD,
+	0x22, 0x40, 0x60, 0xBD,
+
+	0x12, 0x41, 0x51, 0xBD,
+	0x3A, 0x41, 0x61, 0xBD,
+
+	0xBF, 0x2F, 0x0E, 0xBD,
+	0x97, 0xE2,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x35, 0x48, 0xB1, 0xE8,
+	0x3D, 0x59, 0xB1, 0xE8,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x56, 0x31, 0x56, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x66, 0x31, 0x66, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x57, 0x39, 0x57, 0xBF,
+	0x67, 0x39, 0x67, 0xBF,
+
+	0x7F, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x35, 0x00,
+	0x3D, 0x00,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0x8D, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x75, 0xF8, 0xEC,
+	0x35, 0x20,
+	0x3D, 0x20,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x53, 0x53, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x0E, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x48, 0x35, 0x48, 0xBF,
+	0x58, 0x35, 0x58, 0xBF,
+
+	0x68, 0x35, 0x68, 0xBF,
+	0x49, 0x3D, 0x49, 0xBF,
+
+	0x59, 0x3D, 0x59, 0xBF,
+	0x69, 0x3D, 0x69, 0xBF,
+
+	0x63, 0x63, 0x2D, 0xDF,
+	0x4D, 0x7D, 0xF8, 0xEC,
+
+	0x59, 0xE3,
+	0x00, 0xE0,
+	0xB8, 0x38, 0x33, 0xBF,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x18, 0x3A, 0x41, 0xE9,
+
+	0x3F, 0x53, 0xA0, 0xE8,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x63, 0xA0, 0xE8,
+
+	0x50, 0x70, 0xF8, 0xEC,
+	0x2B, 0x50, 0x3C, 0xE9,
+
+	0x1F, 0x0F, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x59, 0x78, 0xF8, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x56, 0x3F, 0x56, 0xDF,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x66, 0x3D, 0x66, 0xDF,
+
+	0x1D, 0x32, 0x41, 0xE9,
+	0x67, 0x3D, 0x67, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3F, 0x57, 0xDF,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x59, 0x3F, 0x59, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x69, 0x3D, 0x69, 0xDF,
+
+	0x48, 0x37, 0x48, 0xDF,
+	0x58, 0x3F, 0x58, 0xDF,
+
+	0x68, 0x3D, 0x68, 0xDF,
+	0x49, 0x37, 0x49, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x0F, 0xCF, 0x74, 0xC2,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x54, 0xB0,
+	0x02, 0x44, 0x64, 0xB0,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x38, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB2,
+	0x1A, 0x44, 0x64, 0xB2,
+
+	0x3A, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x0F, 0xCF, 0x75, 0xC0,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x3D, 0xCF, 0x75, 0xC2,
+	0x37, 0xCF, 0x75, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA6, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA3, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB4,
+	0x1A, 0x44, 0x64, 0xB4,
+
+	0x0A, 0x45, 0x55, 0xB0,
+	0x02, 0x45, 0x65, 0xB0,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA0, 0x37, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x55, 0xB2,
+	0x1A, 0x45, 0x65, 0xB2,
+
+	0x0A, 0x45, 0x55, 0xB4,
+	0x02, 0x45, 0x65, 0xB4,
+
+	0x0F, 0xCF, 0x74, 0xC6,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA7, 0x30, 0x4F, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9C, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA8, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB6,
+	0x1A, 0x44, 0x64, 0xB6,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x45, 0x55, 0xB6,
+	0x02, 0x45, 0x65, 0xB6,
+
+	0x3D, 0xCF, 0x75, 0xC6,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x2A, 0x46, 0x56, 0xBF,
+	0x1A, 0x46, 0x66, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA4, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA5, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x3D, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x0A, 0x47, 0x57, 0xBF,
+	0x02, 0x47, 0x67, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0xA1, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0xA2, 0x38, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9D, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x9E, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x53, 0xBF,
+	0x1A, 0x43, 0x63, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x35, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x39, 0x38, 0x4F, 0xE9,
+
+	0x0A, 0x48, 0x58, 0xBF,
+	0x02, 0x48, 0x68, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x2A, 0x49, 0x59, 0xBF,
+	0x1A, 0x49, 0x69, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x82, 0x30, 0x57, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x83, 0x38, 0x57, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x84, 0x31, 0x5E, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x85, 0x39, 0x5E, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x87, 0x77, 0x57, 0xE9,
+	0x8B, 0x3E, 0xBF, 0xEA,
+
+	0x80, 0x30, 0x57, 0xE9,
+	0x81, 0x38, 0x57, 0xE9,
+
+	0x82, 0x31, 0x57, 0xE9,
+	0x86, 0x78, 0x57, 0xE9,
+
+	0x83, 0x39, 0x57, 0xE9,
+	0x87, 0x79, 0x57, 0xE9,
+
+	0x30, 0x1F, 0x5F, 0xE9,
+	0x8A, 0x34, 0x20, 0xE9,
+
+	0x8B, 0x3C, 0x20, 0xE9,
+	0x37, 0x50, 0x60, 0xBD,
+
+	0x57, 0x0D, 0x20, 0xE9,
+	0x35, 0x51, 0x61, 0xBD,
+
+	0x2B, 0x50, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x0E, 0x77,
+
+	0x24, 0x51, 0x20, 0xE9,
+	0x89, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x0E, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x0B, 0x46, 0xA0, 0xE8,
+	0x1B, 0x56, 0xA0, 0xE8,
+
+	0x2B, 0x66, 0xA0, 0xE8,
+	0x0C, 0x47, 0xA0, 0xE8,
+
+	0x1C, 0x57, 0xA0, 0xE8,
+	0x2C, 0x67, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x57, 0x80, 0x57, 0xCF,
+
+	0x66, 0x33, 0x66, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x67, 0x3B, 0x67, 0xCF,
+
+	0x0B, 0x48, 0xA0, 0xE8,
+	0x1B, 0x58, 0xA0, 0xE8,
+
+	0x2B, 0x68, 0xA0, 0xE8,
+	0x0C, 0x49, 0xA0, 0xE8,
+
+	0x1C, 0x59, 0xA0, 0xE8,
+	0x2C, 0x69, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x34, 0xD7, 0x34, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3C, 0xD7, 0x3C, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x34, 0x80, 0x34, 0xBD,
+	0x3C, 0x80, 0x3C, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x48, 0x80, 0x48, 0xCF,
+	0x59, 0x80, 0x59, 0xCF,
+
+	0x68, 0x33, 0x68, 0xCF,
+	0x49, 0x3B, 0x49, 0xCF,
+
+	0xA9, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x58, 0x33, 0x58, 0xCF,
+	0x69, 0x3B, 0x69, 0xCF,
+
+	0x67, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsf[] = {
+
+	0x00, 0x8A, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x0A, 0x40, 0x50, 0xBF,
+	0x2A, 0x40, 0x60, 0xBF,
+
+	0x32, 0x41, 0x51, 0xBF,
+	0x3A, 0x41, 0x61, 0xBF,
+
+	0xC3, 0x6B,
+	0xD3, 0x6B,
+	0x00, 0x8A, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x23, 0x9F,
+	0x00, 0xE0,
+	0x51, 0x04,
+
+	0x90, 0xE2,
+	0x61, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x51, 0x41, 0xE0, 0xEC,
+	0x39, 0x67, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x63, 0xA0, 0xE8,
+
+	0x61, 0x41, 0xE0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x8A, 0x80, 0x15, 0xEA,
+	0x10, 0x04,
+	0x20, 0x04,
+
+	0x61, 0x51, 0xE0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x52, 0xBF,
+	0x0F, 0x52, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x62, 0xBF,
+	0x1E, 0x51, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x0E, 0x61, 0x60, 0xEA,
+
+	0x32, 0x40, 0x50, 0xBD,
+	0x22, 0x40, 0x60, 0xBD,
+
+	0x12, 0x41, 0x51, 0xBD,
+	0x3A, 0x41, 0x61, 0xBD,
+
+	0xBF, 0x2F, 0x0E, 0xBD,
+	0x97, 0xE2,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x35, 0x48, 0xB1, 0xE8,
+	0x3D, 0x59, 0xB1, 0xE8,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x56, 0x31, 0x56, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x66, 0x31, 0x66, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x57, 0x39, 0x57, 0xBF,
+	0x67, 0x39, 0x67, 0xBF,
+
+	0x7B, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x35, 0x00,
+	0x3D, 0x00,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0x8D, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x75, 0xF8, 0xEC,
+	0x35, 0x20,
+	0x3D, 0x20,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x53, 0x53, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x0E, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x48, 0x35, 0x48, 0xBF,
+	0x58, 0x35, 0x58, 0xBF,
+
+	0x68, 0x35, 0x68, 0xBF,
+	0x49, 0x3D, 0x49, 0xBF,
+
+	0x59, 0x3D, 0x59, 0xBF,
+	0x69, 0x3D, 0x69, 0xBF,
+
+	0x63, 0x63, 0x2D, 0xDF,
+	0x4D, 0x7D, 0xF8, 0xEC,
+
+	0x59, 0xE3,
+	0x00, 0xE0,
+	0xB8, 0x38, 0x33, 0xBF,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x18, 0x3A, 0x41, 0xE9,
+
+	0x3F, 0x53, 0xA0, 0xE8,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x63, 0xA0, 0xE8,
+
+	0x50, 0x70, 0xF8, 0xEC,
+	0x2B, 0x50, 0x3C, 0xE9,
+
+	0x1F, 0x0F, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x59, 0x78, 0xF8, 0xEC,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x56, 0x3F, 0x56, 0xDF,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x66, 0x3D, 0x66, 0xDF,
+
+	0x1D, 0x32, 0x41, 0xE9,
+	0x67, 0x3D, 0x67, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3F, 0x57, 0xDF,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x59, 0x3F, 0x59, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x69, 0x3D, 0x69, 0xDF,
+
+	0x48, 0x37, 0x48, 0xDF,
+	0x58, 0x3F, 0x58, 0xDF,
+
+	0x68, 0x3D, 0x68, 0xDF,
+	0x49, 0x37, 0x49, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x0F, 0xCF, 0x74, 0xC2,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x54, 0xB0,
+	0x02, 0x44, 0x64, 0xB0,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x38, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB2,
+	0x1A, 0x44, 0x64, 0xB2,
+
+	0x36, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x0F, 0xCF, 0x75, 0xC0,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x3D, 0xCF, 0x75, 0xC2,
+	0x37, 0xCF, 0x75, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA6, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA3, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x54, 0xB4,
+	0x1A, 0x44, 0x64, 0xB4,
+
+	0x0A, 0x45, 0x55, 0xB0,
+	0x02, 0x45, 0x65, 0xB0,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA0, 0x37, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x55, 0xB2,
+	0x1A, 0x45, 0x65, 0xB2,
+
+	0x0A, 0x45, 0x55, 0xB4,
+	0x02, 0x45, 0x65, 0xB4,
+
+	0x0F, 0xCF, 0x75, 0xC6,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA7, 0x30, 0x4F, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x31, 0x0F, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA8, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x55, 0xB6,
+	0x1A, 0x45, 0x65, 0xB6,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x2A, 0x46, 0x56, 0xBF,
+	0x1A, 0x46, 0x66, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA4, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA5, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x47, 0x57, 0xBF,
+	0x02, 0x47, 0x67, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA1, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA2, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x53, 0xBF,
+	0x1A, 0x43, 0x63, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x35, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x39, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x48, 0x58, 0xBF,
+	0x02, 0x48, 0x68, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x2A, 0x49, 0x59, 0xBF,
+	0x1A, 0x49, 0x69, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x82, 0x30, 0x57, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x83, 0x38, 0x57, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x84, 0x31, 0x5E, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x85, 0x39, 0x5E, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x87, 0x77, 0x57, 0xE9,
+	0x8B, 0x3E, 0xBF, 0xEA,
+
+	0x80, 0x30, 0x57, 0xE9,
+	0x81, 0x38, 0x57, 0xE9,
+
+	0x82, 0x31, 0x57, 0xE9,
+	0x86, 0x78, 0x57, 0xE9,
+
+	0x83, 0x39, 0x57, 0xE9,
+	0x87, 0x79, 0x57, 0xE9,
+
+	0x30, 0x1F, 0x5F, 0xE9,
+	0x8A, 0x34, 0x20, 0xE9,
+
+	0x8B, 0x3C, 0x20, 0xE9,
+	0x37, 0x50, 0x60, 0xBD,
+
+	0x57, 0x0D, 0x20, 0xE9,
+	0x35, 0x51, 0x61, 0xBD,
+
+	0x2B, 0x50, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x0E, 0x77,
+
+	0x24, 0x51, 0x20, 0xE9,
+	0x8D, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x0E, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x0B, 0x46, 0xA0, 0xE8,
+	0x1B, 0x56, 0xA0, 0xE8,
+
+	0x2B, 0x66, 0xA0, 0xE8,
+	0x0C, 0x47, 0xA0, 0xE8,
+
+	0x1C, 0x57, 0xA0, 0xE8,
+	0x2C, 0x67, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x57, 0x80, 0x57, 0xCF,
+
+	0x66, 0x33, 0x66, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x67, 0x3B, 0x67, 0xCF,
+
+	0x0B, 0x48, 0xA0, 0xE8,
+	0x1B, 0x58, 0xA0, 0xE8,
+
+	0x2B, 0x68, 0xA0, 0xE8,
+	0x0C, 0x49, 0xA0, 0xE8,
+
+	0x1C, 0x59, 0xA0, 0xE8,
+	0x2C, 0x69, 0xA0, 0xE8,
+
+	0x0B, 0x00,
+	0x1B, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x0C, 0x00,
+	0x1C, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x0B, 0x65,
+	0x1B, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x0C, 0x65,
+	0x1C, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x0B, 0x1B, 0x60, 0xEC,
+	0x34, 0xD7, 0x34, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x0C, 0x1C, 0x60, 0xEC,
+
+	0x3C, 0xD7, 0x3C, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x0B, 0x2B, 0xDE, 0xE8,
+	0x1B, 0x80, 0xDE, 0xE8,
+
+	0x34, 0x80, 0x34, 0xBD,
+	0x3C, 0x80, 0x3C, 0xBD,
+
+	0x33, 0xD7, 0x0B, 0xBD,
+	0x3B, 0xD7, 0x1B, 0xBD,
+
+	0x48, 0x80, 0x48, 0xCF,
+	0x59, 0x80, 0x59, 0xCF,
+
+	0x68, 0x33, 0x68, 0xCF,
+	0x49, 0x3B, 0x49, 0xCF,
+
+	0xAD, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x58, 0x33, 0x58, 0xCF,
+	0x69, 0x3B, 0x69, 0xCF,
+
+	0x6B, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgz[] = {
+
+	0x00, 0x88, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x22, 0x40, 0x48, 0xBF,
+	0x2A, 0x40, 0x50, 0xBF,
+
+	0x32, 0x41, 0x49, 0xBF,
+	0x3A, 0x41, 0x51, 0xBF,
+
+	0xC3, 0x6B,
+	0xCB, 0x6B,
+	0x00, 0x88, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x4B, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x29, 0x9F,
+	0x00, 0xE0,
+	0x49, 0x04,
+
+	0x90, 0xE2,
+	0x51, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x49, 0x41, 0xC0, 0xEC,
+	0x39, 0x57, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0x51, 0x41, 0xC0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x58, 0x80, 0x15, 0xEA,
+	0x08, 0x04,
+	0x10, 0x04,
+
+	0x51, 0x49, 0xC0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x4A, 0xBF,
+	0x27, 0x4A, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x52, 0xBF,
+	0x1E, 0x49, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x26, 0x51, 0x60, 0xEA,
+
+	0x32, 0x40, 0x48, 0xBD,
+	0x22, 0x40, 0x50, 0xBD,
+
+	0x12, 0x41, 0x49, 0xBD,
+	0x3A, 0x41, 0x51, 0xBD,
+
+	0xBF, 0x2F, 0x26, 0xBD,
+	0x00, 0xE0,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x4E, 0x31, 0x4E, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x56, 0x31, 0x56, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x4F, 0x39, 0x4F, 0xBF,
+	0x57, 0x39, 0x57, 0xBF,
+
+	0x4A, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x42, 0x73, 0xF8, 0xEC,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0xA5, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x4B, 0x4B, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x26, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x53, 0x53, 0x2D, 0xDF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xB8, 0x38, 0x33, 0xBF,
+	0x00, 0xE0,
+	0x59, 0xE3,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x3F, 0x4B, 0xA0, 0xE8,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x53, 0xA0, 0xE8,
+
+	0x48, 0x70, 0xF8, 0xEC,
+	0x2B, 0x48, 0x3C, 0xE9,
+
+	0x1F, 0x27, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x18, 0x3A, 0x41, 0xE9,
+	0x1D, 0x32, 0x41, 0xE9,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x56, 0x3D, 0x56, 0xDF,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x4E, 0x3F, 0x4E, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x4F, 0x3F, 0x4F, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3D, 0x57, 0xDF,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x34, 0x80, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x4C, 0xB0,
+	0x02, 0x44, 0x54, 0xB0,
+
+	0x2A, 0x44, 0x4C, 0xB2,
+	0x1A, 0x44, 0x54, 0xB2,
+
+	0x1D, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x3D, 0xCF, 0x74, 0xC2,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x2A, 0x44, 0x4C, 0xB4,
+	0x1A, 0x44, 0x54, 0xB4,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x38, 0x3D, 0x20, 0xE9,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x2A, 0x46, 0x4E, 0xBF,
+	0x1A, 0x46, 0x56, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x0A, 0x47, 0x4F, 0xBF,
+	0x02, 0x47, 0x57, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x4B, 0xBF,
+	0x1A, 0x43, 0x53, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x37, 0x48, 0x50, 0xBD,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8B, 0x3E, 0x20, 0xE9,
+
+	0x82, 0x30, 0x57, 0xE9,
+	0x87, 0x77, 0x57, 0xE9,
+
+	0x83, 0x38, 0x57, 0xE9,
+	0x35, 0x49, 0x51, 0xBD,
+
+	0x84, 0x31, 0x5E, 0xE9,
+	0x30, 0x1F, 0x5F, 0xE9,
+
+	0x85, 0x39, 0x5E, 0xE9,
+	0x57, 0x25, 0x20, 0xE9,
+
+	0x2B, 0x48, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x26, 0x77,
+
+	0x24, 0x49, 0x20, 0xE9,
+	0xAF, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x26, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x1C, 0x46, 0xA0, 0xE8,
+	0x23, 0x4E, 0xA0, 0xE8,
+
+	0x2B, 0x56, 0xA0, 0xE8,
+	0x1D, 0x47, 0xA0, 0xE8,
+
+	0x24, 0x4F, 0xA0, 0xE8,
+	0x2C, 0x57, 0xA0, 0xE8,
+
+	0x1C, 0x00,
+	0x23, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x1D, 0x00,
+	0x24, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x1C, 0x65,
+	0x23, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x1D, 0x65,
+	0x24, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x1C, 0x23, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x1D, 0x24, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x1C, 0x2B, 0xDE, 0xE8,
+	0x23, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x1C, 0xBD,
+	0x3B, 0xD7, 0x23, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x4F, 0x80, 0x4F, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0xD6, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x4E, 0x33, 0x4E, 0xCF,
+	0x57, 0x3B, 0x57, 0xCF,
+
+	0x9D, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgza[] = {
+
+	0x00, 0x88, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x22, 0x40, 0x48, 0xBF,
+	0x2A, 0x40, 0x50, 0xBF,
+
+	0x32, 0x41, 0x49, 0xBF,
+	0x3A, 0x41, 0x51, 0xBF,
+
+	0xC3, 0x6B,
+	0xCB, 0x6B,
+	0x00, 0x88, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x4B, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x29, 0x9F,
+	0x00, 0xE0,
+	0x49, 0x04,
+
+	0x90, 0xE2,
+	0x51, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x49, 0x41, 0xC0, 0xEC,
+	0x39, 0x57, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0x51, 0x41, 0xC0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x5C, 0x80, 0x15, 0xEA,
+	0x08, 0x04,
+	0x10, 0x04,
+
+	0x51, 0x49, 0xC0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x4A, 0xBF,
+	0x27, 0x4A, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x52, 0xBF,
+	0x1E, 0x49, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x26, 0x51, 0x60, 0xEA,
+
+	0x32, 0x40, 0x48, 0xBD,
+	0x22, 0x40, 0x50, 0xBD,
+
+	0x12, 0x41, 0x49, 0xBD,
+	0x3A, 0x41, 0x51, 0xBD,
+
+	0xBF, 0x2F, 0x26, 0xBD,
+	0x00, 0xE0,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x4E, 0x31, 0x4E, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x56, 0x31, 0x56, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x4F, 0x39, 0x4F, 0xBF,
+	0x57, 0x39, 0x57, 0xBF,
+
+	0x4E, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x42, 0x73, 0xF8, 0xEC,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0xA5, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x4B, 0x4B, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x26, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x53, 0x53, 0x2D, 0xDF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xB8, 0x38, 0x33, 0xBF,
+	0x00, 0xE0,
+	0x59, 0xE3,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x3F, 0x4B, 0xA0, 0xE8,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x53, 0xA0, 0xE8,
+
+	0x48, 0x70, 0xF8, 0xEC,
+	0x2B, 0x48, 0x3C, 0xE9,
+
+	0x1F, 0x27, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x18, 0x3A, 0x41, 0xE9,
+	0x1D, 0x32, 0x41, 0xE9,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x56, 0x3D, 0x56, 0xDF,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x4E, 0x3F, 0x4E, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x4F, 0x3F, 0x4F, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3D, 0x57, 0xDF,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x34, 0x80, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x27, 0xCF, 0x74, 0xC6,
+	0x3D, 0xCF, 0x74, 0xC2,
+
+	0x0A, 0x44, 0x4C, 0xB0,
+	0x02, 0x44, 0x54, 0xB0,
+
+	0x2A, 0x44, 0x4C, 0xB2,
+	0x1A, 0x44, 0x54, 0xB2,
+
+	0x20, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9C, 0x27, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x4C, 0xB4,
+	0x02, 0x44, 0x54, 0xB4,
+
+	0x2A, 0x44, 0x4C, 0xB6,
+	0x1A, 0x44, 0x54, 0xB6,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x38, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x20,
+	0x02, 0x20,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x0A, 0x47, 0x4F, 0xBF,
+	0x02, 0x47, 0x57, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x46, 0x4E, 0xBF,
+	0x1A, 0x46, 0x56, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x36, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x37, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x4B, 0xBF,
+	0x1A, 0x43, 0x53, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x9D, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x9E, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x37, 0x48, 0x50, 0xBD,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8B, 0x3E, 0x20, 0xE9,
+
+	0x82, 0x30, 0x57, 0xE9,
+	0x87, 0x77, 0x57, 0xE9,
+
+	0x83, 0x38, 0x57, 0xE9,
+	0x35, 0x49, 0x51, 0xBD,
+
+	0x84, 0x31, 0x5E, 0xE9,
+	0x30, 0x1F, 0x5F, 0xE9,
+
+	0x85, 0x39, 0x5E, 0xE9,
+	0x57, 0x25, 0x20, 0xE9,
+
+	0x2B, 0x48, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x26, 0x77,
+
+	0x24, 0x49, 0x20, 0xE9,
+	0xAB, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x26, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x1C, 0x46, 0xA0, 0xE8,
+	0x23, 0x4E, 0xA0, 0xE8,
+
+	0x2B, 0x56, 0xA0, 0xE8,
+	0x1D, 0x47, 0xA0, 0xE8,
+
+	0x24, 0x4F, 0xA0, 0xE8,
+	0x2C, 0x57, 0xA0, 0xE8,
+
+	0x1C, 0x00,
+	0x23, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x1D, 0x00,
+	0x24, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x1C, 0x65,
+	0x23, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x1D, 0x65,
+	0x24, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x1C, 0x23, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x1D, 0x24, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x1C, 0x2B, 0xDE, 0xE8,
+	0x23, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x1C, 0xBD,
+	0x3B, 0xD7, 0x23, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x4F, 0x80, 0x4F, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0xD3, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x4E, 0x33, 0x4E, 0xCF,
+	0x57, 0x3B, 0x57, 0xCF,
+
+	0x99, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzaf[] = {
+
+	0x00, 0x88, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x22, 0x40, 0x48, 0xBF,
+	0x2A, 0x40, 0x50, 0xBF,
+
+	0x32, 0x41, 0x49, 0xBF,
+	0x3A, 0x41, 0x51, 0xBF,
+
+	0xC3, 0x6B,
+	0xCB, 0x6B,
+	0x00, 0x88, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x4B, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x29, 0x9F,
+	0x00, 0xE0,
+	0x49, 0x04,
+
+	0x90, 0xE2,
+	0x51, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x49, 0x41, 0xC0, 0xEC,
+	0x39, 0x57, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0x51, 0x41, 0xC0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x61, 0x80, 0x15, 0xEA,
+	0x08, 0x04,
+	0x10, 0x04,
+
+	0x51, 0x49, 0xC0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x4A, 0xBF,
+	0x27, 0x4A, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x52, 0xBF,
+	0x1E, 0x49, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x26, 0x51, 0x60, 0xEA,
+
+	0x32, 0x40, 0x48, 0xBD,
+	0x22, 0x40, 0x50, 0xBD,
+
+	0x12, 0x41, 0x49, 0xBD,
+	0x3A, 0x41, 0x51, 0xBD,
+
+	0xBF, 0x2F, 0x26, 0xBD,
+	0x00, 0xE0,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x4E, 0x31, 0x4E, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x56, 0x31, 0x56, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x4F, 0x39, 0x4F, 0xBF,
+	0x57, 0x39, 0x57, 0xBF,
+
+	0x53, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x42, 0x73, 0xF8, 0xEC,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0xA5, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x4B, 0x4B, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x26, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x53, 0x53, 0x2D, 0xDF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xB8, 0x38, 0x33, 0xBF,
+	0x00, 0xE0,
+	0x59, 0xE3,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x3F, 0x4B, 0xA0, 0xE8,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x53, 0xA0, 0xE8,
+
+	0x48, 0x70, 0xF8, 0xEC,
+	0x2B, 0x48, 0x3C, 0xE9,
+
+	0x1F, 0x27, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x18, 0x3A, 0x41, 0xE9,
+	0x1D, 0x32, 0x41, 0xE9,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x56, 0x3D, 0x56, 0xDF,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x4E, 0x3F, 0x4E, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x4F, 0x3F, 0x4F, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3D, 0x57, 0xDF,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x4C, 0xB0,
+	0x02, 0x44, 0x54, 0xB0,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB2,
+	0x1A, 0x44, 0x54, 0xB2,
+
+	0x26, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x3D, 0xCF, 0x74, 0xC2,
+	0x27, 0xCF, 0x74, 0xC6,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9C, 0x27, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x4C, 0xB4,
+	0x02, 0x44, 0x54, 0xB4,
+
+	0x2A, 0x44, 0x4C, 0xB6,
+	0x1A, 0x44, 0x54, 0xB6,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x38, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x20,
+	0x02, 0x20,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x3D, 0xCF, 0x75, 0xC6,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x0A, 0x45, 0x4D, 0xB6,
+	0x02, 0x45, 0x55, 0xB6,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x3D, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x2A, 0x46, 0x4E, 0xBF,
+	0x1A, 0x46, 0x56, 0xBF,
+
+	0x0A, 0x47, 0x4F, 0xBF,
+	0x02, 0x47, 0x57, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x38, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9D, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x9E, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x4B, 0xBF,
+	0x1A, 0x43, 0x53, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x35, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x39, 0x38, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x37, 0x48, 0x50, 0xBD,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8B, 0x3E, 0x20, 0xE9,
+
+	0x82, 0x30, 0x57, 0xE9,
+	0x87, 0x77, 0x57, 0xE9,
+
+	0x83, 0x38, 0x57, 0xE9,
+	0x35, 0x49, 0x51, 0xBD,
+
+	0x84, 0x31, 0x5E, 0xE9,
+	0x30, 0x1F, 0x5F, 0xE9,
+
+	0x85, 0x39, 0x5E, 0xE9,
+	0x57, 0x25, 0x20, 0xE9,
+
+	0x2B, 0x48, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x26, 0x77,
+
+	0x24, 0x49, 0x20, 0xE9,
+	0xA6, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x26, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x1C, 0x46, 0xA0, 0xE8,
+	0x23, 0x4E, 0xA0, 0xE8,
+
+	0x2B, 0x56, 0xA0, 0xE8,
+	0x1D, 0x47, 0xA0, 0xE8,
+
+	0x24, 0x4F, 0xA0, 0xE8,
+	0x2C, 0x57, 0xA0, 0xE8,
+
+	0x1C, 0x00,
+	0x23, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x1D, 0x00,
+	0x24, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x1C, 0x65,
+	0x23, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x1D, 0x65,
+	0x24, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x1C, 0x23, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x1D, 0x24, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x1C, 0x2B, 0xDE, 0xE8,
+	0x23, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x1C, 0xBD,
+	0x3B, 0xD7, 0x23, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x4F, 0x80, 0x4F, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0xCD, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x4E, 0x33, 0x4E, 0xCF,
+	0x57, 0x3B, 0x57, 0xCF,
+
+	0x94, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzf[] = {
+
+	0x00, 0x88, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x22, 0x40, 0x48, 0xBF,
+	0x2A, 0x40, 0x50, 0xBF,
+
+	0x32, 0x41, 0x49, 0xBF,
+	0x3A, 0x41, 0x51, 0xBF,
+
+	0xC3, 0x6B,
+	0xCB, 0x6B,
+	0x00, 0x88, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x4B, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x29, 0x9F,
+	0x00, 0xE0,
+	0x49, 0x04,
+
+	0x90, 0xE2,
+	0x51, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x49, 0x41, 0xC0, 0xEC,
+	0x39, 0x57, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0x51, 0x41, 0xC0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x5D, 0x80, 0x15, 0xEA,
+	0x08, 0x04,
+	0x10, 0x04,
+
+	0x51, 0x49, 0xC0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x4A, 0xBF,
+	0x27, 0x4A, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x52, 0xBF,
+	0x1E, 0x49, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x26, 0x51, 0x60, 0xEA,
+
+	0x32, 0x40, 0x48, 0xBD,
+	0x22, 0x40, 0x50, 0xBD,
+
+	0x12, 0x41, 0x49, 0xBD,
+	0x3A, 0x41, 0x51, 0xBD,
+
+	0xBF, 0x2F, 0x26, 0xBD,
+	0x00, 0xE0,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x4E, 0x31, 0x4E, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x56, 0x31, 0x56, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x4F, 0x39, 0x4F, 0xBF,
+	0x57, 0x39, 0x57, 0xBF,
+
+	0x4F, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x42, 0x73, 0xF8, 0xEC,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0xA5, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x4B, 0x4B, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x26, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x53, 0x53, 0x2D, 0xDF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xB8, 0x38, 0x33, 0xBF,
+	0x00, 0xE0,
+	0x59, 0xE3,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x3F, 0x4B, 0xA0, 0xE8,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x53, 0xA0, 0xE8,
+
+	0x48, 0x70, 0xF8, 0xEC,
+	0x2B, 0x48, 0x3C, 0xE9,
+
+	0x1F, 0x27, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x18, 0x3A, 0x41, 0xE9,
+	0x1D, 0x32, 0x41, 0xE9,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x56, 0x3D, 0x56, 0xDF,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x4E, 0x3F, 0x4E, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x4F, 0x3F, 0x4F, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3D, 0x57, 0xDF,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x34, 0x80, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x27, 0xCF, 0x75, 0xC6,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x4C, 0xB0,
+	0x02, 0x44, 0x54, 0xB0,
+
+	0x2A, 0x44, 0x4C, 0xB2,
+	0x1A, 0x44, 0x54, 0xB2,
+
+	0x20, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x3D, 0xCF, 0x74, 0xC2,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x31, 0x27, 0x20, 0xE9,
+
+	0x0A, 0x44, 0x4C, 0xB4,
+	0x02, 0x44, 0x54, 0xB4,
+
+	0x2A, 0x45, 0x4D, 0xB6,
+	0x1A, 0x45, 0x55, 0xB6,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x38, 0x3D, 0x20, 0xE9,
+
+	0x0A, 0x20,
+	0x02, 0x20,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x0A, 0x47, 0x4F, 0xBF,
+	0x02, 0x47, 0x57, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x46, 0x4E, 0xBF,
+	0x1A, 0x46, 0x56, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x36, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x37, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x4B, 0xBF,
+	0x1A, 0x43, 0x53, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x35, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x39, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x37, 0x48, 0x50, 0xBD,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8B, 0x3E, 0x20, 0xE9,
+
+	0x82, 0x30, 0x57, 0xE9,
+	0x87, 0x77, 0x57, 0xE9,
+
+	0x83, 0x38, 0x57, 0xE9,
+	0x35, 0x49, 0x51, 0xBD,
+
+	0x84, 0x31, 0x5E, 0xE9,
+	0x30, 0x1F, 0x5F, 0xE9,
+
+	0x85, 0x39, 0x5E, 0xE9,
+	0x57, 0x25, 0x20, 0xE9,
+
+	0x2B, 0x48, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x26, 0x77,
+
+	0x24, 0x49, 0x20, 0xE9,
+	0xAA, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x26, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x1C, 0x46, 0xA0, 0xE8,
+	0x23, 0x4E, 0xA0, 0xE8,
+
+	0x2B, 0x56, 0xA0, 0xE8,
+	0x1D, 0x47, 0xA0, 0xE8,
+
+	0x24, 0x4F, 0xA0, 0xE8,
+	0x2C, 0x57, 0xA0, 0xE8,
+
+	0x1C, 0x00,
+	0x23, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x1D, 0x00,
+	0x24, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x1C, 0x65,
+	0x23, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x1D, 0x65,
+	0x24, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x1C, 0x23, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x1D, 0x24, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x1C, 0x2B, 0xDE, 0xE8,
+	0x23, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x1C, 0xBD,
+	0x3B, 0xD7, 0x23, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x4F, 0x80, 0x4F, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0xD3, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x4E, 0x33, 0x4E, 0xCF,
+	0x57, 0x3B, 0x57, 0xCF,
+
+	0x98, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzs[] = {
+
+	0x00, 0x88, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x22, 0x40, 0x48, 0xBF,
+	0x2A, 0x40, 0x50, 0xBF,
+
+	0x32, 0x41, 0x49, 0xBF,
+	0x3A, 0x41, 0x51, 0xBF,
+
+	0xC3, 0x6B,
+	0xCB, 0x6B,
+	0x00, 0x88, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x4B, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x29, 0x9F,
+	0x00, 0xE0,
+	0x49, 0x04,
+
+	0x90, 0xE2,
+	0x51, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x49, 0x41, 0xC0, 0xEC,
+	0x39, 0x57, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0x51, 0x41, 0xC0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x65, 0x80, 0x15, 0xEA,
+	0x08, 0x04,
+	0x10, 0x04,
+
+	0x51, 0x49, 0xC0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x4A, 0xBF,
+	0x27, 0x4A, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x52, 0xBF,
+	0x1E, 0x49, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x26, 0x51, 0x60, 0xEA,
+
+	0x32, 0x40, 0x48, 0xBD,
+	0x22, 0x40, 0x50, 0xBD,
+
+	0x12, 0x41, 0x49, 0xBD,
+	0x3A, 0x41, 0x51, 0xBD,
+
+	0xBF, 0x2F, 0x26, 0xBD,
+	0x00, 0xE0,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x4E, 0x31, 0x4E, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x56, 0x31, 0x56, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x4F, 0x39, 0x4F, 0xBF,
+	0x57, 0x39, 0x57, 0xBF,
+
+	0x57, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x42, 0x73, 0xF8, 0xEC,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0xA5, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x4B, 0x4B, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x26, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x53, 0x53, 0x2D, 0xDF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xB8, 0x38, 0x33, 0xBF,
+	0x00, 0xE0,
+	0x59, 0xE3,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x3F, 0x4B, 0xA0, 0xE8,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x53, 0xA0, 0xE8,
+
+	0x48, 0x70, 0xF8, 0xEC,
+	0x2B, 0x48, 0x3C, 0xE9,
+
+	0x1F, 0x27, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x18, 0x3A, 0x41, 0xE9,
+	0x1D, 0x32, 0x41, 0xE9,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x56, 0x3D, 0x56, 0xDF,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x4E, 0x3F, 0x4E, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x4F, 0x3F, 0x4F, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3D, 0x57, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x27, 0xCF, 0x74, 0xC2,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x4C, 0xB0,
+	0x02, 0x44, 0x54, 0xB0,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x38, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB2,
+	0x1A, 0x44, 0x54, 0xB2,
+
+	0x29, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x27, 0xCF, 0x75, 0xC0,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x3D, 0xCF, 0x75, 0xC2,
+	0x37, 0xCF, 0x75, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA6, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA3, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB4,
+	0x1A, 0x44, 0x54, 0xB4,
+
+	0x0A, 0x45, 0x4D, 0xB0,
+	0x02, 0x45, 0x55, 0xB0,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA0, 0x37, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x4D, 0xB2,
+	0x1A, 0x45, 0x55, 0xB2,
+
+	0x0A, 0x45, 0x4D, 0xB4,
+	0x02, 0x45, 0x55, 0xB4,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x20,
+	0x02, 0x20,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x2A, 0x46, 0x4E, 0xBF,
+	0x1A, 0x46, 0x56, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0xA7, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0xA8, 0x38, 0x4F, 0xE9,
+
+	0x0A, 0x47, 0x4F, 0xBF,
+	0x02, 0x47, 0x57, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA4, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA5, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x4B, 0xBF,
+	0x1A, 0x43, 0x53, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0xA1, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0xA2, 0x38, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x37, 0x48, 0x50, 0xBD,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8B, 0x3E, 0x20, 0xE9,
+
+	0x82, 0x30, 0x57, 0xE9,
+	0x87, 0x77, 0x57, 0xE9,
+
+	0x83, 0x38, 0x57, 0xE9,
+	0x35, 0x49, 0x51, 0xBD,
+
+	0x84, 0x31, 0x5E, 0xE9,
+	0x30, 0x1F, 0x5F, 0xE9,
+
+	0x85, 0x39, 0x5E, 0xE9,
+	0x57, 0x25, 0x20, 0xE9,
+
+	0x2B, 0x48, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x26, 0x77,
+
+	0x24, 0x49, 0x20, 0xE9,
+	0xA2, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x26, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x1C, 0x46, 0xA0, 0xE8,
+	0x23, 0x4E, 0xA0, 0xE8,
+
+	0x2B, 0x56, 0xA0, 0xE8,
+	0x1D, 0x47, 0xA0, 0xE8,
+
+	0x24, 0x4F, 0xA0, 0xE8,
+	0x2C, 0x57, 0xA0, 0xE8,
+
+	0x1C, 0x00,
+	0x23, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x1D, 0x00,
+	0x24, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x1C, 0x65,
+	0x23, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x1D, 0x65,
+	0x24, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x1C, 0x23, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x1D, 0x24, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x1C, 0x2B, 0xDE, 0xE8,
+	0x23, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x1C, 0xBD,
+	0x3B, 0xD7, 0x23, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x4F, 0x80, 0x4F, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0xCA, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x4E, 0x33, 0x4E, 0xCF,
+	0x57, 0x3B, 0x57, 0xCF,
+
+	0x90, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsa[] = {
+
+	0x00, 0x88, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x22, 0x40, 0x48, 0xBF,
+	0x2A, 0x40, 0x50, 0xBF,
+
+	0x32, 0x41, 0x49, 0xBF,
+	0x3A, 0x41, 0x51, 0xBF,
+
+	0xC3, 0x6B,
+	0xCB, 0x6B,
+	0x00, 0x88, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x4B, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x29, 0x9F,
+	0x00, 0xE0,
+	0x49, 0x04,
+
+	0x90, 0xE2,
+	0x51, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x49, 0x41, 0xC0, 0xEC,
+	0x39, 0x57, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0x51, 0x41, 0xC0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x6A, 0x80, 0x15, 0xEA,
+	0x08, 0x04,
+	0x10, 0x04,
+
+	0x51, 0x49, 0xC0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x4A, 0xBF,
+	0x27, 0x4A, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x52, 0xBF,
+	0x1E, 0x49, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x26, 0x51, 0x60, 0xEA,
+
+	0x32, 0x40, 0x48, 0xBD,
+	0x22, 0x40, 0x50, 0xBD,
+
+	0x12, 0x41, 0x49, 0xBD,
+	0x3A, 0x41, 0x51, 0xBD,
+
+	0xBF, 0x2F, 0x26, 0xBD,
+	0x00, 0xE0,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x4E, 0x31, 0x4E, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x56, 0x31, 0x56, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x4F, 0x39, 0x4F, 0xBF,
+	0x57, 0x39, 0x57, 0xBF,
+
+	0x5C, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x42, 0x73, 0xF8, 0xEC,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0xA5, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x4B, 0x4B, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x26, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x53, 0x53, 0x2D, 0xDF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xB8, 0x38, 0x33, 0xBF,
+	0x00, 0xE0,
+	0x59, 0xE3,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x3F, 0x4B, 0xA0, 0xE8,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x53, 0xA0, 0xE8,
+
+	0x48, 0x70, 0xF8, 0xEC,
+	0x2B, 0x48, 0x3C, 0xE9,
+
+	0x1F, 0x27, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x18, 0x3A, 0x41, 0xE9,
+	0x1D, 0x32, 0x41, 0xE9,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x56, 0x3D, 0x56, 0xDF,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x4E, 0x3F, 0x4E, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x4F, 0x3F, 0x4F, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3D, 0x57, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x27, 0xCF, 0x74, 0xC2,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x4C, 0xB0,
+	0x02, 0x44, 0x54, 0xB0,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x38, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB2,
+	0x1A, 0x44, 0x54, 0xB2,
+
+	0x2E, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x27, 0xCF, 0x75, 0xC0,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x3D, 0xCF, 0x75, 0xC2,
+	0x37, 0xCF, 0x75, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA6, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA3, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB4,
+	0x1A, 0x44, 0x54, 0xB4,
+
+	0x0A, 0x45, 0x4D, 0xB0,
+	0x02, 0x45, 0x55, 0xB0,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA0, 0x37, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x4D, 0xB2,
+	0x1A, 0x45, 0x55, 0xB2,
+
+	0x0A, 0x45, 0x4D, 0xB4,
+	0x02, 0x45, 0x55, 0xB4,
+
+	0x27, 0xCF, 0x74, 0xC6,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA7, 0x30, 0x4F, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9C, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA8, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB6,
+	0x1A, 0x44, 0x54, 0xB6,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x2A, 0x46, 0x4E, 0xBF,
+	0x1A, 0x46, 0x56, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA4, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA5, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x47, 0x4F, 0xBF,
+	0x02, 0x47, 0x57, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA1, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA2, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x4B, 0xBF,
+	0x1A, 0x43, 0x53, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x9D, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x9E, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x37, 0x48, 0x50, 0xBD,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8B, 0x3E, 0x20, 0xE9,
+
+	0x82, 0x30, 0x57, 0xE9,
+	0x87, 0x77, 0x57, 0xE9,
+
+	0x83, 0x38, 0x57, 0xE9,
+	0x35, 0x49, 0x51, 0xBD,
+
+	0x84, 0x31, 0x5E, 0xE9,
+	0x30, 0x1F, 0x5F, 0xE9,
+
+	0x85, 0x39, 0x5E, 0xE9,
+	0x57, 0x25, 0x20, 0xE9,
+
+	0x2B, 0x48, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x26, 0x77,
+
+	0x24, 0x49, 0x20, 0xE9,
+	0x9D, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x26, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x1C, 0x46, 0xA0, 0xE8,
+	0x23, 0x4E, 0xA0, 0xE8,
+
+	0x2B, 0x56, 0xA0, 0xE8,
+	0x1D, 0x47, 0xA0, 0xE8,
+
+	0x24, 0x4F, 0xA0, 0xE8,
+	0x2C, 0x57, 0xA0, 0xE8,
+
+	0x1C, 0x00,
+	0x23, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x1D, 0x00,
+	0x24, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x1C, 0x65,
+	0x23, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x1D, 0x65,
+	0x24, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x1C, 0x23, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x1D, 0x24, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x1C, 0x2B, 0xDE, 0xE8,
+	0x23, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x1C, 0xBD,
+	0x3B, 0xD7, 0x23, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x4F, 0x80, 0x4F, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0xC5, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x4E, 0x33, 0x4E, 0xCF,
+	0x57, 0x3B, 0x57, 0xCF,
+
+	0x8B, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsaf[] = {
+
+	0x00, 0x88, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x22, 0x40, 0x48, 0xBF,
+	0x2A, 0x40, 0x50, 0xBF,
+
+	0x32, 0x41, 0x49, 0xBF,
+	0x3A, 0x41, 0x51, 0xBF,
+
+	0xC3, 0x6B,
+	0xCB, 0x6B,
+	0x00, 0x88, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x4B, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x29, 0x9F,
+	0x00, 0xE0,
+	0x49, 0x04,
+
+	0x90, 0xE2,
+	0x51, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x49, 0x41, 0xC0, 0xEC,
+	0x39, 0x57, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0x51, 0x41, 0xC0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x6E, 0x80, 0x15, 0xEA,
+	0x08, 0x04,
+	0x10, 0x04,
+
+	0x51, 0x49, 0xC0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x4A, 0xBF,
+	0x27, 0x4A, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x52, 0xBF,
+	0x1E, 0x49, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x26, 0x51, 0x60, 0xEA,
+
+	0x32, 0x40, 0x48, 0xBD,
+	0x22, 0x40, 0x50, 0xBD,
+
+	0x12, 0x41, 0x49, 0xBD,
+	0x3A, 0x41, 0x51, 0xBD,
+
+	0xBF, 0x2F, 0x26, 0xBD,
+	0x00, 0xE0,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x4E, 0x31, 0x4E, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x56, 0x31, 0x56, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x4F, 0x39, 0x4F, 0xBF,
+	0x57, 0x39, 0x57, 0xBF,
+
+	0x60, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x42, 0x73, 0xF8, 0xEC,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0xA5, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x4B, 0x4B, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x26, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x53, 0x53, 0x2D, 0xDF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xB8, 0x38, 0x33, 0xBF,
+	0x00, 0xE0,
+	0x59, 0xE3,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x3F, 0x4B, 0xA0, 0xE8,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x53, 0xA0, 0xE8,
+
+	0x48, 0x70, 0xF8, 0xEC,
+	0x2B, 0x48, 0x3C, 0xE9,
+
+	0x1F, 0x27, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x18, 0x3A, 0x41, 0xE9,
+	0x1D, 0x32, 0x41, 0xE9,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x56, 0x3D, 0x56, 0xDF,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x4E, 0x3F, 0x4E, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x4F, 0x3F, 0x4F, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3D, 0x57, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x27, 0xCF, 0x74, 0xC2,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x4C, 0xB0,
+	0x02, 0x44, 0x54, 0xB0,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x38, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB2,
+	0x1A, 0x44, 0x54, 0xB2,
+
+	0x32, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x27, 0xCF, 0x75, 0xC0,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x3D, 0xCF, 0x75, 0xC2,
+	0x37, 0xCF, 0x75, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA6, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA3, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB4,
+	0x1A, 0x44, 0x54, 0xB4,
+
+	0x0A, 0x45, 0x4D, 0xB0,
+	0x02, 0x45, 0x55, 0xB0,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA0, 0x37, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x4D, 0xB2,
+	0x1A, 0x45, 0x55, 0xB2,
+
+	0x0A, 0x45, 0x4D, 0xB4,
+	0x02, 0x45, 0x55, 0xB4,
+
+	0x27, 0xCF, 0x74, 0xC6,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA7, 0x30, 0x4F, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9C, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA8, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB6,
+	0x1A, 0x44, 0x54, 0xB6,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x45, 0x4D, 0xB6,
+	0x02, 0x45, 0x55, 0xB6,
+
+	0x3D, 0xCF, 0x75, 0xC6,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x2A, 0x46, 0x4E, 0xBF,
+	0x1A, 0x46, 0x56, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA4, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA5, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x3D, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x0A, 0x47, 0x4F, 0xBF,
+	0x02, 0x47, 0x57, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0xA1, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0xA2, 0x38, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x9D, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x9E, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x4B, 0xBF,
+	0x1A, 0x43, 0x53, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x35, 0x30, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x39, 0x38, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x37, 0x48, 0x50, 0xBD,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8B, 0x3E, 0x20, 0xE9,
+
+	0x82, 0x30, 0x57, 0xE9,
+	0x87, 0x77, 0x57, 0xE9,
+
+	0x83, 0x38, 0x57, 0xE9,
+	0x35, 0x49, 0x51, 0xBD,
+
+	0x84, 0x31, 0x5E, 0xE9,
+	0x30, 0x1F, 0x5F, 0xE9,
+
+	0x85, 0x39, 0x5E, 0xE9,
+	0x57, 0x25, 0x20, 0xE9,
+
+	0x2B, 0x48, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x26, 0x77,
+
+	0x24, 0x49, 0x20, 0xE9,
+	0x99, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x26, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x1C, 0x46, 0xA0, 0xE8,
+	0x23, 0x4E, 0xA0, 0xE8,
+
+	0x2B, 0x56, 0xA0, 0xE8,
+	0x1D, 0x47, 0xA0, 0xE8,
+
+	0x24, 0x4F, 0xA0, 0xE8,
+	0x2C, 0x57, 0xA0, 0xE8,
+
+	0x1C, 0x00,
+	0x23, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x1D, 0x00,
+	0x24, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x1C, 0x65,
+	0x23, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x1D, 0x65,
+	0x24, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x1C, 0x23, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x1D, 0x24, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x1C, 0x2B, 0xDE, 0xE8,
+	0x23, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x1C, 0xBD,
+	0x3B, 0xD7, 0x23, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x4F, 0x80, 0x4F, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0xC1, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x4E, 0x33, 0x4E, 0xCF,
+	0x57, 0x3B, 0x57, 0xCF,
+
+	0x87, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsf[] = {
+
+	0x00, 0x88, 0x98, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+	0xFF, 0x80, 0xC0, 0xE9,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x22, 0x40, 0x48, 0xBF,
+	0x2A, 0x40, 0x50, 0xBF,
+
+	0x32, 0x41, 0x49, 0xBF,
+	0x3A, 0x41, 0x51, 0xBF,
+
+	0xC3, 0x6B,
+	0xCB, 0x6B,
+	0x00, 0x88, 0x98, 0xE9,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x96, 0xE2,
+	0x41, 0x04,
+
+	0x7B, 0x43, 0xA0, 0xE8,
+	0x73, 0x4B, 0xA0, 0xE8,
+
+	0xAD, 0xEE, 0x29, 0x9F,
+	0x00, 0xE0,
+	0x49, 0x04,
+
+	0x90, 0xE2,
+	0x51, 0x04,
+	0x31, 0x46, 0xB1, 0xE8,
+
+	0x49, 0x41, 0xC0, 0xEC,
+	0x39, 0x57, 0xB1, 0xE8,
+
+	0x00, 0x04,
+	0x46, 0xE2,
+	0x73, 0x53, 0xA0, 0xE8,
+
+	0x51, 0x41, 0xC0, 0xEC,
+	0x31, 0x00,
+	0x39, 0x00,
+
+	0x6A, 0x80, 0x15, 0xEA,
+	0x08, 0x04,
+	0x10, 0x04,
+
+	0x51, 0x49, 0xC0, 0xEC,
+	0x2F, 0x41, 0x60, 0xEA,
+
+	0x31, 0x20,
+	0x39, 0x20,
+	0x1F, 0x42, 0xA0, 0xE8,
+
+	0x2A, 0x42, 0x4A, 0xBF,
+	0x27, 0x4A, 0xA0, 0xE8,
+
+	0x1A, 0x42, 0x52, 0xBF,
+	0x1E, 0x49, 0x60, 0xEA,
+
+	0x73, 0x7B, 0xC8, 0xEC,
+	0x26, 0x51, 0x60, 0xEA,
+
+	0x32, 0x40, 0x48, 0xBD,
+	0x22, 0x40, 0x50, 0xBD,
+
+	0x12, 0x41, 0x49, 0xBD,
+	0x3A, 0x41, 0x51, 0xBD,
+
+	0xBF, 0x2F, 0x26, 0xBD,
+	0x00, 0xE0,
+	0x7B, 0x72,
+
+	0x32, 0x20,
+	0x22, 0x20,
+	0x12, 0x20,
+	0x3A, 0x20,
+
+	0x46, 0x31, 0x46, 0xBF,
+	0x4E, 0x31, 0x4E, 0xBF,
+
+	0xB3, 0xE2, 0x2D, 0x9F,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x56, 0x31, 0x56, 0xBF,
+	0x47, 0x39, 0x47, 0xBF,
+
+	0x4F, 0x39, 0x4F, 0xBF,
+	0x57, 0x39, 0x57, 0xBF,
+
+	0x5C, 0x80, 0x07, 0xEA,
+	0x24, 0x41, 0x20, 0xE9,
+
+	0x42, 0x73, 0xF8, 0xEC,
+	0x00, 0xE0,
+	0x2D, 0x73,
+
+	0x33, 0x72,
+	0x0C, 0xE3,
+	0xA5, 0x2F, 0x1E, 0xBD,
+
+	0x43, 0x43, 0x2D, 0xDF,
+	0x4B, 0x4B, 0x2D, 0xDF,
+
+	0xAE, 0x1E, 0x26, 0xBD,
+	0x58, 0xE3,
+	0x33, 0x66,
+
+	0x53, 0x53, 0x2D, 0xDF,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0xB8, 0x38, 0x33, 0xBF,
+	0x00, 0xE0,
+	0x59, 0xE3,
+
+	0x1E, 0x12, 0x41, 0xE9,
+	0x1A, 0x22, 0x41, 0xE9,
+
+	0x2B, 0x40, 0x3D, 0xE9,
+	0x3F, 0x4B, 0xA0, 0xE8,
+
+	0x2D, 0x73,
+	0x30, 0x76,
+	0x05, 0x80, 0x3D, 0xEA,
+
+	0x37, 0x43, 0xA0, 0xE8,
+	0x3D, 0x53, 0xA0, 0xE8,
+
+	0x48, 0x70, 0xF8, 0xEC,
+	0x2B, 0x48, 0x3C, 0xE9,
+
+	0x1F, 0x27, 0xBC, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x15, 0xC0, 0x20, 0xE9,
+	0x15, 0xC0, 0x20, 0xE9,
+
+	0x18, 0x3A, 0x41, 0xE9,
+	0x1D, 0x32, 0x41, 0xE9,
+
+	0x2A, 0x40, 0x20, 0xE9,
+	0x56, 0x3D, 0x56, 0xDF,
+
+	0x46, 0x37, 0x46, 0xDF,
+	0x4E, 0x3F, 0x4E, 0xDF,
+
+	0x16, 0x30, 0x20, 0xE9,
+	0x4F, 0x3F, 0x4F, 0xDF,
+
+	0x47, 0x37, 0x47, 0xDF,
+	0x57, 0x3D, 0x57, 0xDF,
+
+	0x32, 0x32, 0x2D, 0xDF,
+	0x22, 0x22, 0x2D, 0xDF,
+
+	0x12, 0x12, 0x2D, 0xDF,
+	0x3A, 0x3A, 0x2D, 0xDF,
+
+	0x27, 0xCF, 0x74, 0xC2,
+	0x37, 0xCF, 0x74, 0xC4,
+
+	0x0A, 0x44, 0x4C, 0xB0,
+	0x02, 0x44, 0x54, 0xB0,
+
+	0x3D, 0xCF, 0x74, 0xC0,
+	0x34, 0x37, 0x20, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x38, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3C, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB2,
+	0x1A, 0x44, 0x54, 0xB2,
+
+	0x2E, 0x80, 0x3A, 0xEA,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x27, 0xCF, 0x75, 0xC0,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x32, 0x31, 0x5F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x33, 0x39, 0x5F, 0xE9,
+
+	0x3D, 0xCF, 0x75, 0xC2,
+	0x37, 0xCF, 0x75, 0xC4,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA6, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA3, 0x3D, 0x20, 0xE9,
+
+	0x2A, 0x44, 0x4C, 0xB4,
+	0x1A, 0x44, 0x54, 0xB4,
+
+	0x0A, 0x45, 0x4D, 0xB0,
+	0x02, 0x45, 0x55, 0xB0,
+
+	0x88, 0x73, 0x5E, 0xE9,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA0, 0x37, 0x20, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x3E, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x3F, 0x38, 0x4F, 0xE9,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x3A, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x3B, 0x39, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x4D, 0xB2,
+	0x1A, 0x45, 0x55, 0xB2,
+
+	0x0A, 0x45, 0x4D, 0xB4,
+	0x02, 0x45, 0x55, 0xB4,
+
+	0x27, 0xCF, 0x75, 0xC6,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0xA7, 0x30, 0x4F, 0xE9,
+	0x0A, 0x20,
+	0x02, 0x20,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x31, 0x27, 0x20, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA8, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x45, 0x4D, 0xB6,
+	0x1A, 0x45, 0x55, 0xB6,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x36, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x37, 0x39, 0x4F, 0xE9,
+
+	0x00, 0x80, 0x00, 0xE8,
+	0x2A, 0x20,
+	0x1A, 0x20,
+
+	0x2A, 0x46, 0x4E, 0xBF,
+	0x1A, 0x46, 0x56, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA4, 0x31, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA5, 0x39, 0x4F, 0xE9,
+
+	0x0A, 0x47, 0x4F, 0xBF,
+	0x02, 0x47, 0x57, 0xBF,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0xA1, 0x30, 0x4F, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0xA2, 0x38, 0x4F, 0xE9,
+
+	0x2A, 0x43, 0x4B, 0xBF,
+	0x1A, 0x43, 0x53, 0xBF,
+
+	0x30, 0x50, 0x2E, 0x9F,
+	0x35, 0x31, 0x4F, 0xE9,
+
+	0x38, 0x21, 0x2C, 0x9F,
+	0x39, 0x39, 0x4F, 0xE9,
+
+	0x31, 0x53, 0x2F, 0x9F,
+	0x80, 0x31, 0x57, 0xE9,
+
+	0x39, 0xE5, 0x2C, 0x9F,
+	0x81, 0x39, 0x57, 0xE9,
+
+	0x37, 0x48, 0x50, 0xBD,
+	0x8A, 0x36, 0x20, 0xE9,
+
+	0x86, 0x76, 0x57, 0xE9,
+	0x8B, 0x3E, 0x20, 0xE9,
+
+	0x82, 0x30, 0x57, 0xE9,
+	0x87, 0x77, 0x57, 0xE9,
+
+	0x83, 0x38, 0x57, 0xE9,
+	0x35, 0x49, 0x51, 0xBD,
+
+	0x84, 0x31, 0x5E, 0xE9,
+	0x30, 0x1F, 0x5F, 0xE9,
+
+	0x85, 0x39, 0x5E, 0xE9,
+	0x57, 0x25, 0x20, 0xE9,
+
+	0x2B, 0x48, 0x20, 0xE9,
+	0x1D, 0x37, 0xE1, 0xEA,
+
+	0x1E, 0x35, 0xE1, 0xEA,
+	0x00, 0xE0,
+	0x26, 0x77,
+
+	0x24, 0x49, 0x20, 0xE9,
+	0x9D, 0xFF, 0x20, 0xEA,
+
+	0x16, 0x26, 0x20, 0xE9,
+	0x57, 0x2E, 0xBF, 0xEA,
+
+	0x1C, 0x46, 0xA0, 0xE8,
+	0x23, 0x4E, 0xA0, 0xE8,
+
+	0x2B, 0x56, 0xA0, 0xE8,
+	0x1D, 0x47, 0xA0, 0xE8,
+
+	0x24, 0x4F, 0xA0, 0xE8,
+	0x2C, 0x57, 0xA0, 0xE8,
+
+	0x1C, 0x00,
+	0x23, 0x00,
+	0x2B, 0x00,
+	0x00, 0xE0,
+
+	0x1D, 0x00,
+	0x24, 0x00,
+	0x2C, 0x00,
+	0x00, 0xE0,
+
+	0x1C, 0x65,
+	0x23, 0x65,
+	0x2B, 0x65,
+	0x00, 0xE0,
+
+	0x1D, 0x65,
+	0x24, 0x65,
+	0x2C, 0x65,
+	0x00, 0xE0,
+
+	0x1C, 0x23, 0x60, 0xEC,
+	0x36, 0xD7, 0x36, 0xAD,
+
+	0x2B, 0x80, 0x60, 0xEC,
+	0x1D, 0x24, 0x60, 0xEC,
+
+	0x3E, 0xD7, 0x3E, 0xAD,
+	0x2C, 0x80, 0x60, 0xEC,
+
+	0x1C, 0x2B, 0xDE, 0xE8,
+	0x23, 0x80, 0xDE, 0xE8,
+
+	0x36, 0x80, 0x36, 0xBD,
+	0x3E, 0x80, 0x3E, 0xBD,
+
+	0x33, 0xD7, 0x1C, 0xBD,
+	0x3B, 0xD7, 0x23, 0xBD,
+
+	0x46, 0x80, 0x46, 0xCF,
+	0x4F, 0x80, 0x4F, 0xCF,
+
+	0x56, 0x33, 0x56, 0xCF,
+	0x47, 0x3B, 0x47, 0xCF,
+
+	0xC5, 0xFF, 0x20, 0xEA,
+	0x00, 0x80, 0x00, 0xE8,
+
+	0x4E, 0x33, 0x4E, 0xCF,
+	0x57, 0x3B, 0x57, 0xCF,
+
+	0x8B, 0xFF, 0x20, 0xEA,
+	0x57, 0xC0, 0xBF, 0xEA,
+
+	0x00, 0x80, 0xA0, 0xE9,
+	0x00, 0x00, 0xD8, 0xEC,
+
+};
--- libdrm-2.3.0.orig/shared-core/r128_cce.c
+++ libdrm-2.3.0/shared-core/r128_cce.c
@@ -0,0 +1,948 @@
+/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
+ * Created: Wed Apr  5 19:24:19 2000 by kevin@precisioninsight.com
+ */
+/*
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+#include "r128_drv.h"
+
+#define R128_FIFO_DEBUG		0
+
+/* CCE microcode (from ATI) */
+static u32 r128_cce_microcode[] = {
+	0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
+	1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0,
+	599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1,
+	11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11,
+	262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28,
+	1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9,
+	30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656,
+	1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1,
+	15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071,
+	12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2,
+	46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1,
+	459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
+	18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1,
+	15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2,
+	268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1,
+	15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82,
+	1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729,
+	3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008,
+	1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
+	15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1,
+	180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1,
+	114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0,
+	33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370,
+	1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1,
+	14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793,
+	1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
+	198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1,
+	114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1,
+	1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1,
+	1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894,
+	16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14,
+	174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1,
+	33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1,
+	33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1,
+	409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int R128_READ_PLL(drm_device_t * dev, int addr)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+
+	R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
+	return R128_READ(R128_CLOCK_CNTL_DATA);
+}
+
+#if R128_FIFO_DEBUG
+static void r128_status(drm_r128_private_t * dev_priv)
+{
+	printk("GUI_STAT           = 0x%08x\n",
+	       (unsigned int)R128_READ(R128_GUI_STAT));
+	printk("PM4_STAT           = 0x%08x\n",
+	       (unsigned int)R128_READ(R128_PM4_STAT));
+	printk("PM4_BUFFER_DL_WPTR = 0x%08x\n",
+	       (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR));
+	printk("PM4_BUFFER_DL_RPTR = 0x%08x\n",
+	       (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR));
+	printk("PM4_MICRO_CNTL     = 0x%08x\n",
+	       (unsigned int)R128_READ(R128_PM4_MICRO_CNTL));
+	printk("PM4_BUFFER_CNTL    = 0x%08x\n",
+	       (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL));
+}
+#endif
+
+/* ================================================================
+ * Engine, FIFO control
+ */
+
+static int r128_do_pixcache_flush(drm_r128_private_t * dev_priv)
+{
+	u32 tmp;
+	int i;
+
+	tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL;
+	R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp);
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+
+#if R128_FIFO_DEBUG
+	DRM_ERROR("failed!\n");
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries)
+{
+	int i;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
+		if (slots >= entries)
+			return 0;
+		DRM_UDELAY(1);
+	}
+
+#if R128_FIFO_DEBUG
+	DRM_ERROR("failed!\n");
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
+{
+	int i, ret;
+
+	ret = r128_do_wait_for_fifo(dev_priv, 64);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
+			r128_do_pixcache_flush(dev_priv);
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+
+#if R128_FIFO_DEBUG
+	DRM_ERROR("failed!\n");
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+/* ================================================================
+ * CCE control, initialization
+ */
+
+/* Load the microcode for the CCE */
+static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
+{
+	int i;
+
+	DRM_DEBUG("\n");
+
+	r128_do_wait_for_idle(dev_priv);
+
+	R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
+	for (i = 0; i < 256; i++) {
+		R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
+		R128_WRITE(R128_PM4_MICROCODE_DATAL,
+			   r128_cce_microcode[i * 2 + 1]);
+	}
+}
+
+/* Flush any pending commands to the CCE.  This should only be used just
+ * prior to a wait for idle, as it informs the engine that the command
+ * stream is ending.
+ */
+static void r128_do_cce_flush(drm_r128_private_t * dev_priv)
+{
+	u32 tmp;
+
+	tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE;
+	R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp);
+}
+
+/* Wait for the CCE to go idle.
+ */
+int r128_do_cce_idle(drm_r128_private_t * dev_priv)
+{
+	int i;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) {
+			int pm4stat = R128_READ(R128_PM4_STAT);
+			if (((pm4stat & R128_PM4_FIFOCNT_MASK) >=
+			     dev_priv->cce_fifo_size) &&
+			    !(pm4stat & (R128_PM4_BUSY |
+					 R128_PM4_GUI_ACTIVE))) {
+				return r128_do_pixcache_flush(dev_priv);
+			}
+		}
+		DRM_UDELAY(1);
+	}
+
+#if R128_FIFO_DEBUG
+	DRM_ERROR("failed!\n");
+	r128_status(dev_priv);
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+/* Start the Concurrent Command Engine.
+ */
+static void r128_do_cce_start(drm_r128_private_t * dev_priv)
+{
+	r128_do_wait_for_idle(dev_priv);
+
+	R128_WRITE(R128_PM4_BUFFER_CNTL,
+		   dev_priv->cce_mode | dev_priv->ring.size_l2qw
+		   | R128_PM4_BUFFER_CNTL_NOUPDATE);
+	R128_READ(R128_PM4_BUFFER_ADDR);	/* as per the sample code */
+	R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
+
+	dev_priv->cce_running = 1;
+}
+
+/* Reset the Concurrent Command Engine.  This will not flush any pending
+ * commands, so you must wait for the CCE command stream to complete
+ * before calling this routine.
+ */
+static void r128_do_cce_reset(drm_r128_private_t * dev_priv)
+{
+	R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
+	R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
+	dev_priv->ring.tail = 0;
+}
+
+/* Stop the Concurrent Command Engine.  This will not flush any pending
+ * commands, so you must flush the command stream and wait for the CCE
+ * to go idle before calling this routine.
+ */
+static void r128_do_cce_stop(drm_r128_private_t * dev_priv)
+{
+	R128_WRITE(R128_PM4_MICRO_CNTL, 0);
+	R128_WRITE(R128_PM4_BUFFER_CNTL,
+		   R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE);
+
+	dev_priv->cce_running = 0;
+}
+
+/* Reset the engine.  This will stop the CCE if it is running.
+ */
+static int r128_do_engine_reset(drm_device_t * dev)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
+
+	r128_do_pixcache_flush(dev_priv);
+
+	clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX);
+	mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL);
+
+	R128_WRITE_PLL(R128_MCLK_CNTL,
+		       mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
+
+	gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL);
+
+	/* Taken from the sample code - do not change */
+	R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
+	R128_READ(R128_GEN_RESET_CNTL);
+	R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
+	R128_READ(R128_GEN_RESET_CNTL);
+
+	R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
+	R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
+	R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
+
+	/* Reset the CCE ring */
+	r128_do_cce_reset(dev_priv);
+
+	/* The CCE is no longer running after an engine reset */
+	dev_priv->cce_running = 0;
+
+	/* Reset any pending vertex, indirect buffers */
+	r128_freelist_reset(dev);
+
+	return 0;
+}
+
+static void r128_cce_init_ring_buffer(drm_device_t * dev,
+				      drm_r128_private_t * dev_priv)
+{
+	u32 ring_start;
+	u32 tmp;
+
+	DRM_DEBUG("\n");
+
+	/* The manual (p. 2) says this address is in "VM space".  This
+	 * means it's an offset from the start of AGP space.
+	 */
+#if __OS_HAS_AGP
+	if (!dev_priv->is_pci)
+		ring_start = dev_priv->cce_ring->offset - dev->agp->base;
+	else
+#endif
+		ring_start = dev_priv->cce_ring->offset - 
+				(unsigned long)dev->sg->virtual;
+
+	R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET);
+
+	R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
+	R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
+
+	/* Set watermark control */
+	R128_WRITE(R128_PM4_BUFFER_WM_CNTL,
+		   ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT)
+		   | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT)
+		   | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT)
+		   | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT));
+
+	/* Force read.  Why?  Because it's in the examples... */
+	R128_READ(R128_PM4_BUFFER_ADDR);
+
+	/* Turn on bus mastering */
+	tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS;
+	R128_WRITE(R128_BUS_CNTL, tmp);
+}
+
+static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
+{
+	drm_r128_private_t *dev_priv;
+
+	DRM_DEBUG("\n");
+
+	dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
+	if (dev_priv == NULL)
+		return DRM_ERR(ENOMEM);
+
+	memset(dev_priv, 0, sizeof(drm_r128_private_t));
+
+	dev_priv->is_pci = init->is_pci;
+
+	if (dev_priv->is_pci && !dev->sg) {
+		DRM_ERROR("PCI GART memory not allocated!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->usec_timeout = init->usec_timeout;
+	if (dev_priv->usec_timeout < 1 ||
+	    dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
+		DRM_DEBUG("TIMEOUT problem!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->cce_mode = init->cce_mode;
+
+	/* GH: Simple idle check.
+	 */
+	atomic_set(&dev_priv->idle_count, 0);
+
+	/* We don't support anything other than bus-mastering ring mode,
+	 * but the ring can be in either AGP or PCI space for the ring
+	 * read pointer.
+	 */
+	if ((init->cce_mode != R128_PM4_192BM) &&
+	    (init->cce_mode != R128_PM4_128BM_64INDBM) &&
+	    (init->cce_mode != R128_PM4_64BM_128INDBM) &&
+	    (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) {
+		DRM_DEBUG("Bad cce_mode!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	switch (init->cce_mode) {
+	case R128_PM4_NONPM4:
+		dev_priv->cce_fifo_size = 0;
+		break;
+	case R128_PM4_192PIO:
+	case R128_PM4_192BM:
+		dev_priv->cce_fifo_size = 192;
+		break;
+	case R128_PM4_128PIO_64INDBM:
+	case R128_PM4_128BM_64INDBM:
+		dev_priv->cce_fifo_size = 128;
+		break;
+	case R128_PM4_64PIO_128INDBM:
+	case R128_PM4_64BM_128INDBM:
+	case R128_PM4_64PIO_64VCBM_64INDBM:
+	case R128_PM4_64BM_64VCBM_64INDBM:
+	case R128_PM4_64PIO_64VCPIO_64INDPIO:
+		dev_priv->cce_fifo_size = 64;
+		break;
+	}
+
+	switch (init->fb_bpp) {
+	case 16:
+		dev_priv->color_fmt = R128_DATATYPE_RGB565;
+		break;
+	case 32:
+	default:
+		dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
+		break;
+	}
+	dev_priv->front_offset = init->front_offset;
+	dev_priv->front_pitch = init->front_pitch;
+	dev_priv->back_offset = init->back_offset;
+	dev_priv->back_pitch = init->back_pitch;
+
+	switch (init->depth_bpp) {
+	case 16:
+		dev_priv->depth_fmt = R128_DATATYPE_RGB565;
+		break;
+	case 24:
+	case 32:
+	default:
+		dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
+		break;
+	}
+	dev_priv->depth_offset = init->depth_offset;
+	dev_priv->depth_pitch = init->depth_pitch;
+	dev_priv->span_offset = init->span_offset;
+
+	dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) |
+					  (dev_priv->front_offset >> 5));
+	dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) |
+					 (dev_priv->back_offset >> 5));
+	dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
+					  (dev_priv->depth_offset >> 5) |
+					  R128_DST_TILE);
+	dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
+					 (dev_priv->span_offset >> 5));
+
+	DRM_GETSAREA();
+
+	if (!dev_priv->sarea) {
+		DRM_ERROR("could not find sarea!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+	if (!dev_priv->mmio) {
+		DRM_ERROR("could not find mmio region!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce(dev);
+		return DRM_ERR(EINVAL);
+	}
+	dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
+	if (!dev_priv->cce_ring) {
+		DRM_ERROR("could not find cce ring region!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce(dev);
+		return DRM_ERR(EINVAL);
+	}
+	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
+	if (!dev_priv->ring_rptr) {
+		DRM_ERROR("could not find ring read pointer!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce(dev);
+		return DRM_ERR(EINVAL);
+	}
+	dev->agp_buffer_token = init->buffers_offset;
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if (!dev->agp_buffer_map) {
+		DRM_ERROR("could not find dma buffer region!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (!dev_priv->is_pci) {
+		dev_priv->agp_textures =
+		    drm_core_findmap(dev, init->agp_textures_offset);
+		if (!dev_priv->agp_textures) {
+			DRM_ERROR("could not find agp texture region!\n");
+			dev->dev_private = (void *)dev_priv;
+			r128_do_cleanup_cce(dev);
+			return DRM_ERR(EINVAL);
+		}
+	}
+
+	dev_priv->sarea_priv =
+	    (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+				  init->sarea_priv_offset);
+
+#if __OS_HAS_AGP
+	if (!dev_priv->is_pci) {
+		drm_core_ioremap(dev_priv->cce_ring, dev);
+		drm_core_ioremap(dev_priv->ring_rptr, dev);
+		drm_core_ioremap(dev->agp_buffer_map, dev);
+		if (!dev_priv->cce_ring->handle ||
+		    !dev_priv->ring_rptr->handle ||
+		    !dev->agp_buffer_map->handle) {
+			DRM_ERROR("Could not ioremap agp regions!\n");
+			dev->dev_private = (void *)dev_priv;
+			r128_do_cleanup_cce(dev);
+			return DRM_ERR(ENOMEM);
+		}
+	} else
+#endif
+	{
+		dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset;
+		dev_priv->ring_rptr->handle =
+		    (void *)dev_priv->ring_rptr->offset;
+		dev->agp_buffer_map->handle =
+		    (void *)dev->agp_buffer_map->offset;
+	}
+
+#if __OS_HAS_AGP
+	if (!dev_priv->is_pci)
+		dev_priv->cce_buffers_offset = dev->agp->base;
+	else
+#endif
+		dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual;
+
+	dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle;
+	dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle
+			      + init->ring_size / sizeof(u32));
+	dev_priv->ring.size = init->ring_size;
+	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+
+	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
+
+	dev_priv->ring.high_mark = 128;
+
+	dev_priv->sarea_priv->last_frame = 0;
+	R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
+
+	dev_priv->sarea_priv->last_dispatch = 0;
+	R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);
+
+#if __OS_HAS_AGP
+	if (dev_priv->is_pci) {
+#endif
+		dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
+		dev_priv->gart_info.addr = NULL;
+		dev_priv->gart_info.bus_addr = 0;
+		dev_priv->gart_info.is_pcie = 0;
+		if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
+			DRM_ERROR("failed to init PCI GART!\n");
+			dev->dev_private = (void *)dev_priv;
+			r128_do_cleanup_cce(dev);
+			return DRM_ERR(ENOMEM);
+		}
+		R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
+#if __OS_HAS_AGP
+	}
+#endif
+
+	r128_cce_init_ring_buffer(dev, dev_priv);
+	r128_cce_load_microcode(dev_priv);
+
+	dev->dev_private = (void *)dev_priv;
+
+	r128_do_engine_reset(dev);
+
+	return 0;
+}
+
+int r128_do_cleanup_cce(drm_device_t * dev)
+{
+
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if (dev->irq_enabled)
+		drm_irq_uninstall(dev);
+
+	if (dev->dev_private) {
+		drm_r128_private_t *dev_priv = dev->dev_private;
+
+#if __OS_HAS_AGP
+		if (!dev_priv->is_pci) {
+			if (dev_priv->cce_ring != NULL)
+				drm_core_ioremapfree(dev_priv->cce_ring, dev);
+			if (dev_priv->ring_rptr != NULL)
+				drm_core_ioremapfree(dev_priv->ring_rptr, dev);
+			if (dev->agp_buffer_map != NULL) {
+				drm_core_ioremapfree(dev->agp_buffer_map, dev);
+				dev->agp_buffer_map = NULL;
+			}
+		} else
+#endif
+		{
+			if (dev_priv->gart_info.bus_addr)
+				if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
+					DRM_ERROR("failed to cleanup PCI GART!\n");
+		}
+
+		drm_free(dev->dev_private, sizeof(drm_r128_private_t),
+			 DRM_MEM_DRIVER);
+		dev->dev_private = NULL;
+	}
+
+	return 0;
+}
+
+int r128_cce_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_init_t init;
+
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(init, (drm_r128_init_t __user *) data,
+				 sizeof(init));
+
+	switch (init.func) {
+	case R128_INIT_CCE:
+		return r128_do_init_cce(dev, &init);
+	case R128_CLEANUP_CCE:
+		return r128_do_cleanup_cce(dev);
+	}
+
+	return DRM_ERR(EINVAL);
+}
+
+int r128_cce_start(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
+		DRM_DEBUG("%s while CCE running\n", __FUNCTION__);
+		return 0;
+	}
+
+	r128_do_cce_start(dev_priv);
+
+	return 0;
+}
+
+/* Stop the CCE.  The engine must have been idled before calling this
+ * routine.
+ */
+int r128_cce_stop(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_cce_stop_t stop;
+	int ret;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *) data,
+				 sizeof(stop));
+
+	/* Flush any pending CCE commands.  This ensures any outstanding
+	 * commands are exectuted by the engine before we turn it off.
+	 */
+	if (stop.flush) {
+		r128_do_cce_flush(dev_priv);
+	}
+
+	/* If we fail to make the engine go idle, we return an error
+	 * code so that the DRM ioctl wrapper can try again.
+	 */
+	if (stop.idle) {
+		ret = r128_do_cce_idle(dev_priv);
+		if (ret)
+			return ret;
+	}
+
+	/* Finally, we can turn off the CCE.  If the engine isn't idle,
+	 * we will get some dropped triangles as they won't be fully
+	 * rendered before the CCE is shut down.
+	 */
+	r128_do_cce_stop(dev_priv);
+
+	/* Reset the engine */
+	r128_do_engine_reset(dev);
+
+	return 0;
+}
+
+/* Just reset the CCE ring.  Called as part of an X Server engine reset.
+ */
+int r128_cce_reset(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_DEBUG("%s called before init done\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	r128_do_cce_reset(dev_priv);
+
+	/* The CCE is no longer running after an engine reset */
+	dev_priv->cce_running = 0;
+
+	return 0;
+}
+
+int r128_cce_idle(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (dev_priv->cce_running) {
+		r128_do_cce_flush(dev_priv);
+	}
+
+	return r128_do_cce_idle(dev_priv);
+}
+
+int r128_engine_reset(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	return r128_do_engine_reset(dev);
+}
+
+int r128_fullscreen(DRM_IOCTL_ARGS)
+{
+	return DRM_ERR(EINVAL);
+}
+
+/* ================================================================
+ * Freelist management
+ */
+#define R128_BUFFER_USED	0xffffffff
+#define R128_BUFFER_FREE	0
+
+#if 0
+static int r128_freelist_init(drm_device_t * dev)
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_buf_t *buf;
+	drm_r128_buf_priv_t *buf_priv;
+	drm_r128_freelist_t *entry;
+	int i;
+
+	dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+	if (dev_priv->head == NULL)
+		return DRM_ERR(ENOMEM);
+
+	memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
+	dev_priv->head->age = R128_BUFFER_USED;
+
+	for (i = 0; i < dma->buf_count; i++) {
+		buf = dma->buflist[i];
+		buf_priv = buf->dev_private;
+
+		entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+		if (!entry)
+			return DRM_ERR(ENOMEM);
+
+		entry->age = R128_BUFFER_FREE;
+		entry->buf = buf;
+		entry->prev = dev_priv->head;
+		entry->next = dev_priv->head->next;
+		if (!entry->next)
+			dev_priv->tail = entry;
+
+		buf_priv->discard = 0;
+		buf_priv->dispatched = 0;
+		buf_priv->list_entry = entry;
+
+		dev_priv->head->next = entry;
+
+		if (dev_priv->head->next)
+			dev_priv->head->next->prev = entry;
+	}
+
+	return 0;
+
+}
+#endif
+
+static drm_buf_t *r128_freelist_get(drm_device_t * dev)
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_buf_priv_t *buf_priv;
+	drm_buf_t *buf;
+	int i, t;
+
+	/* FIXME: Optimize -- use freelist code */
+
+	for (i = 0; i < dma->buf_count; i++) {
+		buf = dma->buflist[i];
+		buf_priv = buf->dev_private;
+		if (buf->filp == 0)
+			return buf;
+	}
+
+	for (t = 0; t < dev_priv->usec_timeout; t++) {
+		u32 done_age = R128_READ(R128_LAST_DISPATCH_REG);
+
+		for (i = 0; i < dma->buf_count; i++) {
+			buf = dma->buflist[i];
+			buf_priv = buf->dev_private;
+			if (buf->pending && buf_priv->age <= done_age) {
+				/* The buffer has been processed, so it
+				 * can now be used.
+				 */
+				buf->pending = 0;
+				return buf;
+			}
+		}
+		DRM_UDELAY(1);
+	}
+
+	DRM_DEBUG("returning NULL!\n");
+	return NULL;
+}
+
+void r128_freelist_reset(drm_device_t * dev)
+{
+	drm_device_dma_t *dma = dev->dma;
+	int i;
+
+	for (i = 0; i < dma->buf_count; i++) {
+		drm_buf_t *buf = dma->buflist[i];
+		drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+		buf_priv->age = 0;
+	}
+}
+
+/* ================================================================
+ * CCE command submission
+ */
+
+int r128_wait_ring(drm_r128_private_t * dev_priv, int n)
+{
+	drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+	int i;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		r128_update_ring_snapshot(dev_priv);
+		if (ring->space >= n)
+			return 0;
+		DRM_UDELAY(1);
+	}
+
+	/* FIXME: This is being ignored... */
+	DRM_ERROR("failed!\n");
+	return DRM_ERR(EBUSY);
+}
+
+static int r128_cce_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+{
+	int i;
+	drm_buf_t *buf;
+
+	for (i = d->granted_count; i < d->request_count; i++) {
+		buf = r128_freelist_get(dev);
+		if (!buf)
+			return DRM_ERR(EAGAIN);
+
+		buf->filp = filp;
+
+		if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+				     sizeof(buf->idx)))
+			return DRM_ERR(EFAULT);
+		if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+				     sizeof(buf->total)))
+			return DRM_ERR(EFAULT);
+
+		d->granted_count++;
+	}
+	return 0;
+}
+
+int r128_cce_buffers(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_device_dma_t *dma = dev->dma;
+	int ret = 0;
+	drm_dma_t __user *argp = (void __user *)data;
+	drm_dma_t d;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
+
+	/* Please don't send us buffers.
+	 */
+	if (d.send_count != 0) {
+		DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+			  DRM_CURRENTPID, d.send_count);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* We'll send you buffers.
+	 */
+	if (d.request_count < 0 || d.request_count > dma->buf_count) {
+		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+			  DRM_CURRENTPID, d.request_count, dma->buf_count);
+		return DRM_ERR(EINVAL);
+	}
+
+	d.granted_count = 0;
+
+	if (d.request_count) {
+		ret = r128_cce_get_buffers(filp, dev, &d);
+	}
+
+	DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
+
+	return ret;
+}
--- libdrm-2.3.0.orig/shared-core/via_mm.c
+++ libdrm-2.3.0/shared-core/via_mm.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 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 "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+#include "via_ds.h"
+#include "via_mm.h"
+
+#define MAX_CONTEXT 100
+
+typedef struct {
+	int used;
+	int context;
+	set_t *sets[2];		/* 0 for frame buffer, 1 for AGP , 2 for System */
+} via_context_t;
+
+static via_context_t global_ppriv[MAX_CONTEXT];
+
+static int via_agp_alloc(drm_via_mem_t * mem);
+static int via_agp_free(drm_via_mem_t * mem);
+static int via_fb_alloc(drm_via_mem_t * mem);
+static int via_fb_free(drm_via_mem_t * mem);
+
+static int add_alloc_set(int context, int type, unsigned long val)
+{
+	int i, retval = 0;
+
+	for (i = 0; i < MAX_CONTEXT; i++) {
+		if (global_ppriv[i].used && global_ppriv[i].context == context) {
+			retval = via_setAdd(global_ppriv[i].sets[type], val);
+			break;
+		}
+	}
+
+	return retval;
+}
+
+static int del_alloc_set(int context, int type, unsigned long val)
+{
+	int i, retval = 0;
+
+	for (i = 0; i < MAX_CONTEXT; i++)
+		if (global_ppriv[i].used && global_ppriv[i].context == context) {
+			retval = via_setDel(global_ppriv[i].sets[type], val);
+			break;
+		}
+
+	return retval;
+}
+
+/* agp memory management */
+static memHeap_t *AgpHeap = NULL;
+
+int via_agp_init(DRM_IOCTL_ARGS)
+{
+	drm_via_agp_t agp;
+
+	DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data,
+				 sizeof(agp));
+
+	AgpHeap = via_mmInit(agp.offset, agp.size);
+
+	DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset,
+		  (unsigned long)agp.size);
+
+	return 0;
+}
+
+/* fb memory management */
+static memHeap_t *FBHeap = NULL;
+
+int via_fb_init(DRM_IOCTL_ARGS)
+{
+	drm_via_fb_t fb;
+
+	DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb));
+
+	FBHeap = via_mmInit(fb.offset, fb.size);
+
+	DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset,
+		  (unsigned long)fb.size);
+
+	return 0;
+}
+
+int via_init_context(struct drm_device *dev, int context)
+{
+	int i;
+
+	for (i = 0; i < MAX_CONTEXT; i++)
+		if (global_ppriv[i].used &&
+		    (global_ppriv[i].context == context))
+			break;
+
+	if (i >= MAX_CONTEXT) {
+		for (i = 0; i < MAX_CONTEXT; i++) {
+			if (!global_ppriv[i].used) {
+				global_ppriv[i].context = context;
+				global_ppriv[i].used = 1;
+				global_ppriv[i].sets[0] = via_setInit();
+				global_ppriv[i].sets[1] = via_setInit();
+				DRM_DEBUG("init allocation set, socket=%d,"
+					  " context = %d\n", i, context);
+				break;
+			}
+		}
+
+		if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
+		    (global_ppriv[i].sets[1] == NULL)) {
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+int via_final_context(struct drm_device *dev, int context)
+{	
+        int i;
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+	for (i = 0; i < MAX_CONTEXT; i++)
+		if (global_ppriv[i].used &&
+		    (global_ppriv[i].context == context))
+			break;
+
+	if (i < MAX_CONTEXT) {
+		set_t *set;
+		ITEM_TYPE item;
+		int retval;
+
+		DRM_DEBUG("find socket %d, context = %d\n", i, context);
+
+		/* Video Memory */
+		set = global_ppriv[i].sets[0];
+		retval = via_setFirst(set, &item);
+		while (retval) {
+			DRM_DEBUG("free video memory 0x%lx\n", item);
+			via_mmFreeMem((PMemBlock) item);
+			retval = via_setNext(set, &item);
+		}
+		via_setDestroy(set);
+
+		/* AGP Memory */
+		set = global_ppriv[i].sets[1];
+		retval = via_setFirst(set, &item);
+		while (retval) {
+			DRM_DEBUG("free agp memory 0x%lx\n", item);
+			via_mmFreeMem((PMemBlock) item);
+			retval = via_setNext(set, &item);
+		}
+		via_setDestroy(set);
+		global_ppriv[i].used = 0;
+	}
+	via_release_futex(dev_priv, context); 
+	
+#if defined(__linux__)
+	/* Linux specific until context tracking code gets ported to BSD */
+	/* Last context, perform cleanup */
+	if (dev->ctx_count == 1 && dev->dev_private) {
+	        DRM_DEBUG("Last Context\n");
+		if (dev->irq)
+			drm_irq_uninstall(dev);
+
+		via_cleanup_futex(dev_priv);
+		via_do_cleanup_map(dev);
+	}
+#endif
+
+	return 1;
+}
+
+int via_mem_alloc(DRM_IOCTL_ARGS)
+{
+	drm_via_mem_t mem;
+
+	DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
+				 sizeof(mem));
+
+	switch (mem.type) {
+	case VIA_MEM_VIDEO:
+		if (via_fb_alloc(&mem) < 0)
+			return -EFAULT;
+		DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
+				       sizeof(mem));
+		return 0;
+	case VIA_MEM_AGP:
+		if (via_agp_alloc(&mem) < 0)
+			return -EFAULT;
+		DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
+				       sizeof(mem));
+		return 0;
+	}
+
+	return -EFAULT;
+}
+
+static int via_fb_alloc(drm_via_mem_t * mem)
+{
+	drm_via_mm_t fb;
+	PMemBlock block;
+	int retval = 0;
+
+	if (!FBHeap)
+		return -1;
+
+	fb.size = mem->size;
+	fb.context = mem->context;
+
+	block = via_mmAllocMem(FBHeap, fb.size, 5, 0);
+	if (block) {
+		fb.offset = block->ofs;
+		fb.free = (unsigned long)block;
+		if (!add_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
+			DRM_DEBUG("adding to allocation set fails\n");
+			via_mmFreeMem((PMemBlock) fb.free);
+			retval = -1;
+		}
+	} else {
+		fb.offset = 0;
+		fb.size = 0;
+		fb.free = 0;
+		retval = -1;
+	}
+
+	mem->offset = fb.offset;
+	mem->index = fb.free;
+
+	DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size,
+		  (int)fb.offset);
+
+	return retval;
+}
+
+static int via_agp_alloc(drm_via_mem_t * mem)
+{
+	drm_via_mm_t agp;
+	PMemBlock block;
+	int retval = 0;
+
+	if (!AgpHeap)
+		return -1;
+
+	agp.size = mem->size;
+	agp.context = mem->context;
+
+	block = via_mmAllocMem(AgpHeap, agp.size, 5, 0);
+	if (block) {
+		agp.offset = block->ofs;
+		agp.free = (unsigned long)block;
+		if (!add_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
+			DRM_DEBUG("adding to allocation set fails\n");
+			via_mmFreeMem((PMemBlock) agp.free);
+			retval = -1;
+		}
+	} else {
+		agp.offset = 0;
+		agp.size = 0;
+		agp.free = 0;
+	}
+
+	mem->offset = agp.offset;
+	mem->index = agp.free;
+
+	DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size,
+		  (unsigned int)agp.offset);
+	return retval;
+}
+
+int via_mem_free(DRM_IOCTL_ARGS)
+{
+	drm_via_mem_t mem;
+
+	DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
+				 sizeof(mem));
+
+	switch (mem.type) {
+
+	case VIA_MEM_VIDEO:
+		if (via_fb_free(&mem) == 0)
+			return 0;
+		break;
+	case VIA_MEM_AGP:
+		if (via_agp_free(&mem) == 0)
+			return 0;
+		break;
+	}
+
+	return -EFAULT;
+}
+
+static int via_fb_free(drm_via_mem_t * mem)
+{
+	drm_via_mm_t fb;
+	int retval = 0;
+
+	if (!FBHeap) {
+		return -1;
+	}
+
+	fb.free = mem->index;
+	fb.context = mem->context;
+
+	if (!fb.free) {
+		return -1;
+
+	}
+
+	via_mmFreeMem((PMemBlock) fb.free);
+
+	if (!del_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
+		retval = -1;
+	}
+
+	DRM_DEBUG("free fb, free = %ld\n", fb.free);
+
+	return retval;
+}
+
+static int via_agp_free(drm_via_mem_t * mem)
+{
+	drm_via_mm_t agp;
+
+	int retval = 0;
+
+	agp.free = mem->index;
+	agp.context = mem->context;
+
+	if (!agp.free)
+		return -1;
+
+	via_mmFreeMem((PMemBlock) agp.free);
+
+	if (!del_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
+		retval = -1;
+	}
+
+	DRM_DEBUG("free agp, free = %ld\n", agp.free);
+
+	return retval;
+}
--- libdrm-2.3.0.orig/shared-core/i915_irq.c
+++ libdrm-2.3.0/shared-core/i915_irq.c
@@ -0,0 +1,578 @@
+/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
+ */
+/*
+ * 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.
+ * 
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#define USER_INT_FLAG (1<<1)
+#define VSYNC_PIPEB_FLAG (1<<5)
+#define VSYNC_PIPEA_FLAG (1<<7)
+
+#define MAX_NOPID ((u32)~0)
+
+/**
+ * Emit blits for scheduled buffer swaps.
+ *
+ * This function will be called with the HW lock held.
+ */
+static void i915_vblank_tasklet(drm_device_t *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	unsigned long irqflags;
+	struct list_head *list, *tmp;
+
+	DRM_DEBUG("\n");
+
+	spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+	list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
+		drm_i915_vbl_swap_t *vbl_swap =
+			list_entry(list, drm_i915_vbl_swap_t, head);
+		atomic_t *counter = vbl_swap->pipe ? &dev->vbl_received2 :
+			&dev->vbl_received;
+
+		if ((atomic_read(counter) - vbl_swap->sequence) <= (1<<23)) {
+			drm_drawable_info_t *drw;
+
+			spin_unlock(&dev_priv->swaps_lock);
+
+			spin_lock(&dev->drw_lock);
+
+			drw = drm_get_drawable_info(dev, vbl_swap->drw_id);
+				
+			if (drw) {
+				int i, num_rects = drw->num_rects;
+				drm_clip_rect_t *rect = drw->rects;
+				drm_i915_sarea_t *sarea_priv =
+				    dev_priv->sarea_priv;
+				u32 cpp = dev_priv->cpp;
+				u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
+							XY_SRC_COPY_BLT_WRITE_ALPHA |
+							XY_SRC_COPY_BLT_WRITE_RGB)
+						     : XY_SRC_COPY_BLT_CMD;
+				u32 pitchropcpp = (sarea_priv->pitch * cpp) |
+						  (0xcc << 16) | (cpp << 23) |
+						  (1 << 24);
+				RING_LOCALS;
+
+				i915_kernel_lost_context(dev);
+
+				BEGIN_LP_RING(6);
+
+				OUT_RING(GFX_OP_DRAWRECT_INFO);
+				OUT_RING(0);
+				OUT_RING(0);
+				OUT_RING(sarea_priv->width |
+					 sarea_priv->height << 16);
+				OUT_RING(sarea_priv->width |
+					 sarea_priv->height << 16);
+				OUT_RING(0);
+
+				ADVANCE_LP_RING();
+
+				sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
+
+				for (i = 0; i < num_rects; i++, rect++) {
+					BEGIN_LP_RING(8);
+
+					OUT_RING(cmd);
+					OUT_RING(pitchropcpp);
+					OUT_RING((rect->y1 << 16) | rect->x1);
+					OUT_RING((rect->y2 << 16) | rect->x2);
+					OUT_RING(sarea_priv->front_offset);
+					OUT_RING((rect->y1 << 16) | rect->x1);
+					OUT_RING(pitchropcpp & 0xffff);
+					OUT_RING(sarea_priv->back_offset);
+
+					ADVANCE_LP_RING();
+				}
+			}
+
+			spin_unlock(&dev->drw_lock);
+
+			spin_lock(&dev_priv->swaps_lock);
+
+			list_del(list);
+
+			drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
+
+			dev_priv->swaps_pending--;
+		}
+	}
+
+	spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+}
+
+irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u16 temp;
+
+	temp = I915_READ16(I915REG_INT_IDENTITY_R);
+
+	temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG);
+
+#if 0
+	DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
+#endif
+	if (temp == 0)
+		return IRQ_NONE;
+
+	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+
+	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+
+	if (temp & USER_INT_FLAG) {
+		DRM_WAKEUP(&dev_priv->irq_queue);
+#ifdef I915_HAVE_FENCE
+		i915_fence_handler(dev);
+#endif
+	}
+
+	if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
+		int vblank_pipe = dev_priv->vblank_pipe;
+
+		if ((vblank_pipe &
+		     (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
+		    == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
+			if (temp & VSYNC_PIPEA_FLAG)
+				atomic_inc(&dev->vbl_received);
+			if (temp & VSYNC_PIPEB_FLAG)
+				atomic_inc(&dev->vbl_received2);
+		} else if (((temp & VSYNC_PIPEA_FLAG) &&
+			    (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
+			   ((temp & VSYNC_PIPEB_FLAG) &&
+			    (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
+			atomic_inc(&dev->vbl_received);
+
+		DRM_WAKEUP(&dev->vbl_queue);
+		drm_vbl_send_signals(dev);
+
+		if (dev_priv->swaps_pending > 0)
+			drm_locked_tasklet(dev, i915_vblank_tasklet);
+	}
+
+	return IRQ_HANDLED;
+}
+
+int i915_emit_irq(drm_device_t * dev)
+{
+	
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	i915_kernel_lost_context(dev);
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+
+	if (dev_priv->counter > 0x7FFFFFFFUL)
+		 dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+
+	BEGIN_LP_RING(6);
+	OUT_RING(CMD_STORE_DWORD_IDX);
+	OUT_RING(20);
+	OUT_RING(dev_priv->counter);
+
+	OUT_RING(0);
+	OUT_RING(0);
+	OUT_RING(GFX_OP_USER_INTERRUPT);
+	ADVANCE_LP_RING();
+
+	return dev_priv->counter;
+
+
+}
+
+void i915_user_irq_on(drm_i915_private_t *dev_priv)
+{
+	spin_lock(&dev_priv->user_irq_lock);
+	if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){
+		dev_priv->irq_enable_reg |= USER_INT_FLAG;
+		I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+	}
+	spin_unlock(&dev_priv->user_irq_lock);
+
+}
+		
+void i915_user_irq_off(drm_i915_private_t *dev_priv)
+{
+	spin_lock(&dev_priv->user_irq_lock);
+	if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
+		//		dev_priv->irq_enable_reg &= ~USER_INT_FLAG;
+		//		I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+	}
+	spin_unlock(&dev_priv->user_irq_lock);
+}
+		
+
+static int i915_wait_irq(drm_device_t * dev, int irq_nr)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int ret = 0;
+
+	DRM_DEBUG("%s irq_nr=%d breadcrumb=%d\n", __FUNCTION__, irq_nr,
+		  READ_BREADCRUMB(dev_priv));
+
+	if (READ_BREADCRUMB(dev_priv) >= irq_nr)
+		return 0;
+
+	dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+	
+	i915_user_irq_on(dev_priv);
+	DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
+		    READ_BREADCRUMB(dev_priv) >= irq_nr);
+	i915_user_irq_off(dev_priv);
+
+	if (ret == DRM_ERR(EBUSY)) {
+		DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n",
+			  __FUNCTION__,
+			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
+	}
+
+	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+	return ret;
+}
+
+static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
+				      atomic_t *counter)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+		    (((cur_vblank = atomic_read(counter))
+			- *sequence) <= (1<<23)));
+	
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
+}
+
+int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+{
+	return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
+}
+
+/* Needs the lock as it touches the ring.
+ */
+int i915_irq_emit(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_irq_emit_t emit;
+	int result;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data,
+				 sizeof(emit));
+
+	result = i915_emit_irq(dev);
+
+	if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+/* Doesn't need the hardware lock.
+ */
+int i915_irq_wait(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_irq_wait_t irqwait;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data,
+				 sizeof(irqwait));
+
+	return i915_wait_irq(dev, irqwait.irq_seq);
+}
+
+static void i915_enable_interrupt (drm_device_t *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	
+	dev_priv->irq_enable_reg = USER_INT_FLAG; 
+	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
+		dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
+	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
+		dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG;
+
+	I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+	dev_priv->irq_enabled = 1;
+}
+
+/* Set the vblank monitor pipe
+ */
+int i915_vblank_pipe_set(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_vblank_pipe_t pipe;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data,
+				 sizeof(pipe));
+
+	if (pipe.pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
+		DRM_ERROR("%s called with invalid pipe 0x%x\n", 
+			  __FUNCTION__, pipe.pipe);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->vblank_pipe = pipe.pipe;
+
+	i915_enable_interrupt (dev);
+
+	return 0;
+}
+
+int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_vblank_pipe_t pipe;
+	u16 flag;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	flag = I915_READ(I915REG_INT_ENABLE_R);
+	pipe.pipe = 0;
+	if (flag & VSYNC_PIPEA_FLAG)
+		pipe.pipe |= DRM_I915_VBLANK_PIPE_A;
+	if (flag & VSYNC_PIPEB_FLAG)
+		pipe.pipe |= DRM_I915_VBLANK_PIPE_B;
+	DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe,
+				 sizeof(pipe));
+	return 0;
+}
+
+/**
+ * Schedule buffer swap at given vertical blank.
+ */
+int i915_vblank_swap(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_vblank_swap_t swap;
+	drm_i915_vbl_swap_t *vbl_swap;
+	unsigned int pipe, seqtype, curseq;
+	unsigned long irqflags;
+	struct list_head *list;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __func__);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (dev_priv->sarea_priv->rotation) {
+		DRM_DEBUG("Rotation not supported\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data,
+				 sizeof(swap));
+
+	if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
+			     _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
+		DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
+		return DRM_ERR(EINVAL);
+	}
+
+	pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+
+	seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
+
+	if (!(dev_priv->vblank_pipe & (1 << pipe))) {
+		DRM_ERROR("Invalid pipe %d\n", pipe);
+		return DRM_ERR(EINVAL);
+	}
+
+	spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+	if (!drm_get_drawable_info(dev, swap.drawable)) {
+		spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+		DRM_ERROR("Invalid drawable ID %d\n", swap.drawable);
+		return DRM_ERR(EINVAL);
+	}
+
+	spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+	curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+
+	if (seqtype == _DRM_VBLANK_RELATIVE)
+		swap.sequence += curseq;
+
+	if ((curseq - swap.sequence) <= (1<<23)) {
+		if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) {
+			swap.sequence = curseq + 1;
+		} else {
+			DRM_DEBUG("Missed target sequence\n");
+			return DRM_ERR(EINVAL);
+		}
+	}
+
+	spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+	list_for_each(list, &dev_priv->vbl_swaps.head) {
+		vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
+
+		if (vbl_swap->drw_id == swap.drawable &&
+		    vbl_swap->pipe == pipe &&
+		    vbl_swap->sequence == swap.sequence) {
+			spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+			DRM_DEBUG("Already scheduled\n");
+			return 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+
+	if (dev_priv->swaps_pending >= 100) {
+		DRM_DEBUG("Too many swaps queued\n");
+		return DRM_ERR(EBUSY);
+	}
+
+	vbl_swap = drm_calloc(1, sizeof(vbl_swap), DRM_MEM_DRIVER);
+
+	if (!vbl_swap) {
+		DRM_ERROR("Failed to allocate memory to queue swap\n");
+		return DRM_ERR(ENOMEM);
+	}
+
+	DRM_DEBUG("\n");
+
+	vbl_swap->drw_id = swap.drawable;
+	vbl_swap->pipe = pipe;
+	vbl_swap->sequence = swap.sequence;
+
+	spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+	list_add_tail((struct list_head *)vbl_swap, &dev_priv->vbl_swaps.head);
+	dev_priv->swaps_pending++;
+
+	spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+
+	DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap,
+			       sizeof(swap));
+
+	return 0;
+}
+
+/* drm_dma.h hooks
+*/
+void i915_driver_irq_preinstall(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	I915_WRITE16(I915REG_HWSTAM, 0xeffe);
+	I915_WRITE16(I915REG_INT_MASK_R, 0x0);
+	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+}
+
+void i915_driver_irq_postinstall(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED;
+	INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+	dev_priv->swaps_pending = 0;
+
+	if (!dev_priv->vblank_pipe)
+		dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
+
+	dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED;
+	INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+	dev_priv->swaps_pending = 0;
+
+	dev_priv->user_irq_lock = SPIN_LOCK_UNLOCKED;
+	dev_priv->user_irq_refcount = 0;
+
+	if (!dev_priv->vblank_pipe)
+		dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
+	i915_enable_interrupt(dev);
+	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+
+	/*
+	 * Initialize the hardware status page IRQ location.
+	 */
+
+	I915_WRITE(I915REG_INSTPM, ( 1 << 5) | ( 1 << 21));
+}
+
+void i915_driver_irq_uninstall(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u16 temp;
+	if (!dev_priv)
+		return;
+
+	dev_priv->irq_enabled = 0;
+	I915_WRITE16(I915REG_HWSTAM, 0xffff);
+	I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
+	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+
+	temp = I915_READ16(I915REG_INT_IDENTITY_R);
+	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+}
--- libdrm-2.3.0.orig/shared-core/sis_ds.c
+++ libdrm-2.3.0/shared-core/sis_ds.c
@@ -0,0 +1,299 @@
+/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Sung-Ching Lin <sclin@sis.com.tw>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "sis_ds.h"
+
+/* Set Data Structure, not check repeated value
+ * temporarily used
+ */
+
+set_t *setInit(void)
+{
+	int i;
+	set_t *set;
+
+	set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
+	if (set != NULL) {
+		for (i = 0; i < SET_SIZE; i++) {
+			set->list[i].free_next = i + 1;
+			set->list[i].alloc_next = -1;
+		}
+		set->list[SET_SIZE - 1].free_next = -1;
+		set->free = 0;
+		set->alloc = -1;
+		set->trace = -1;
+	}
+	return set;
+}
+
+int setAdd(set_t * set, ITEM_TYPE item)
+{
+	int free = set->free;
+
+	if (free != -1) {
+		set->list[free].val = item;
+		set->free = set->list[free].free_next;
+	} else {
+		return 0;
+	}
+
+	set->list[free].alloc_next = set->alloc;
+	set->alloc = free;
+	set->list[free].free_next = -1;
+
+	return 1;
+}
+
+int setDel(set_t * set, ITEM_TYPE item)
+{
+	int alloc = set->alloc;
+	int prev = -1;
+
+	while (alloc != -1) {
+		if (set->list[alloc].val == item) {
+			if (prev != -1)
+				set->list[prev].alloc_next =
+				    set->list[alloc].alloc_next;
+			else
+				set->alloc = set->list[alloc].alloc_next;
+			break;
+		}
+		prev = alloc;
+		alloc = set->list[alloc].alloc_next;
+	}
+
+	if (alloc == -1)
+		return 0;
+
+	set->list[alloc].free_next = set->free;
+	set->free = alloc;
+	set->list[alloc].alloc_next = -1;
+
+	return 1;
+}
+
+/* setFirst -> setAdd -> setNext is wrong */
+
+int setFirst(set_t * set, ITEM_TYPE * item)
+{
+	if (set->alloc == -1)
+		return 0;
+
+	*item = set->list[set->alloc].val;
+	set->trace = set->list[set->alloc].alloc_next;
+
+	return 1;
+}
+
+int setNext(set_t * set, ITEM_TYPE * item)
+{
+	if (set->trace == -1)
+		return 0;
+
+	*item = set->list[set->trace].val;
+	set->trace = set->list[set->trace].alloc_next;
+
+	return 1;
+}
+
+int setDestroy(set_t * set)
+{
+	drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
+
+	return 1;
+}
+
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Wittawat Yamwong
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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
+ * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define ISFREE(bptr) ((bptr)->free)
+
+memHeap_t *mmInit(int ofs, int size)
+{
+	PMemBlock blocks;
+
+	if (size <= 0)
+		return NULL;
+
+	blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
+	if (blocks != NULL) {
+		blocks->ofs = ofs;
+		blocks->size = size;
+		blocks->free = 1;
+		return (memHeap_t *) blocks;
+	} else
+		return NULL;
+}
+
+/* Checks if a pointer 'b' is part of the heap 'heap' */
+int mmBlockInHeap(memHeap_t * heap, PMemBlock b)
+{
+	TMemBlock *p;
+
+	if (heap == NULL || b == NULL)
+		return 0;
+
+	p = heap;
+	while (p != NULL && p != b) {
+		p = p->next;
+	}
+	if (p == b)
+		return 1;
+	else
+		return 0;
+}
+
+static TMemBlock *SliceBlock(TMemBlock * p,
+			     int startofs, int size,
+			     int reserved, int alignment)
+{
+	TMemBlock *newblock;
+
+	/* break left */
+	if (startofs > p->ofs) {
+		newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+						    DRM_MEM_DRIVER);
+		newblock->ofs = startofs;
+		newblock->size = p->size - (startofs - p->ofs);
+		newblock->free = 1;
+		newblock->next = p->next;
+		p->size -= newblock->size;
+		p->next = newblock;
+		p = newblock;
+	}
+
+	/* break right */
+	if (size < p->size) {
+		newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+						    DRM_MEM_DRIVER);
+		newblock->ofs = startofs + size;
+		newblock->size = p->size - size;
+		newblock->free = 1;
+		newblock->next = p->next;
+		p->size = size;
+		p->next = newblock;
+	}
+
+	/* p = middle block */
+	p->align = alignment;
+	p->free = 0;
+	p->reserved = reserved;
+	return p;
+}
+
+PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch)
+{
+	int mask, startofs, endofs;
+	TMemBlock *p;
+
+	if (heap == NULL || align2 < 0 || size <= 0)
+		return NULL;
+
+	mask = (1 << align2) - 1;
+	startofs = 0;
+	p = (TMemBlock *) heap;
+	while (p != NULL) {
+		if (ISFREE(p)) {
+			startofs = (p->ofs + mask) & ~mask;
+			if (startofs < startSearch) {
+				startofs = startSearch;
+			}
+			endofs = startofs + size;
+			if (endofs <= (p->ofs + p->size))
+				break;
+		}
+		p = p->next;
+	}
+	if (p == NULL)
+		return NULL;
+	p = SliceBlock(p, startofs, size, 0, mask + 1);
+	p->heap = heap;
+	return p;
+}
+
+static __inline__ int Join2Blocks(TMemBlock * p)
+{
+	if (p->free && p->next && p->next->free) {
+		TMemBlock *q = p->next;
+		p->size += q->size;
+		p->next = q->next;
+		drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
+		return 1;
+	}
+	return 0;
+}
+
+int mmFreeMem(PMemBlock b)
+{
+	TMemBlock *p, *prev;
+
+	if (b == NULL)
+		return 0;
+	if (b->heap == NULL)
+		return -1;
+
+	p = b->heap;
+	prev = NULL;
+	while (p != NULL && p != b) {
+		prev = p;
+		p = p->next;
+	}
+	if (p == NULL || p->free || p->reserved)
+		return -1;
+
+	p->free = 1;
+	Join2Blocks(p);
+	if (prev)
+		Join2Blocks(prev);
+	return 0;
+}
--- libdrm-2.3.0.orig/shared-core/drm_pciids.txt
+++ libdrm-2.3.0/shared-core/drm_pciids.txt
@@ -0,0 +1,464 @@
+[radeon]
+0x1002 0x3150 CHIP_RV380|RADEON_IS_MOBILITY "ATI Radeon Mobility X600 M24"
+0x1002 0x3152 CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X300 M24"
+0x1002 0x3154 CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI FireGL M24 GL"
+0x1002 0x3E50 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV380 X600"
+0x1002 0x3E54 CHIP_RV380|RADEON_NEW_MEMMAP "ATI FireGL V3200 RV380"
+0x1002 0x4136 CHIP_RS100|RADEON_IS_IGP "ATI Radeon RS100 IGP 320"
+0x1002 0x4137 CHIP_RS200|RADEON_IS_IGP "ATI Radeon RS200 IGP 340"
+0x1002 0x4144 CHIP_R300 "ATI Radeon AD 9500"
+0x1002 0x4145 CHIP_R300 "ATI Radeon AE 9700 Pro"
+0x1002 0x4146 CHIP_R300 "ATI Radeon AF R300 9600TX"
+0x1002 0x4147 CHIP_R300 "ATI FireGL AG Z1"
+0x1002 0x4148 CHIP_R350 "ATI Radeon AH 9800 SE"
+0x1002 0x4149 CHIP_R350 "ATI Radeon AI 9800"
+0x1002 0x414A CHIP_R350 "ATI Radeon AJ 9800"
+0x1002 0x414B CHIP_R350 "ATI FireGL AK X2"
+0x1002 0x4150 CHIP_RV350 "ATI Radeon AP 9600"
+0x1002 0x4151 CHIP_RV350 "ATI Radeon AQ 9600 SE"
+0x1002 0x4152 CHIP_RV350 "ATI Radeon AR 9600 XT"
+0x1002 0x4153 CHIP_RV350 "ATI Radeon AS 9550"
+0x1002 0x4154 CHIP_RV350 "ATI FireGL AT T2"
+0x1002 0x4155 CHIP_RV350 "ATI Radeon 9650"
+0x1002 0x4156 CHIP_RV350 "ATI FireGL AV RV360 T2"
+0x1002 0x4237 CHIP_RS200|RADEON_IS_IGP "ATI Radeon RS250 IGP"
+0x1002 0x4242 CHIP_R200 "ATI Radeon BB R200 AIW 8500DV"
+0x1002 0x4243 CHIP_R200 "ATI Radeon BC R200"
+0x1002 0x4336 CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS100 Mobility U1"
+0x1002 0x4337 CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS200 Mobility IGP 340M"
+0x1002 0x4437 CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS250 Mobility IGP"
+0x1002 0x4966 CHIP_RV250 "ATI Radeon If RV250 9000"
+0x1002 0x4967 CHIP_RV250 "ATI Radeon Ig RV250 9000"
+0x1002 0x4A48 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JH R420 X800"
+0x1002 0x4A49 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JI R420 X800 Pro"
+0x1002 0x4A4A CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JJ R420 X800 SE"
+0x1002 0x4A4B CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JK R420 X800 XT"
+0x1002 0x4A4C CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JL R420 X800"
+0x1002 0x4A4D CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL JM X3-256"
+0x1002 0x4A4E CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon JN R420 Mobility M18"
+0x1002 0x4A4F CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JO R420 X800 SE"
+0x1002 0x4A50 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JP R420 X800 XT PE"
+0x1002 0x4A54 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JT R420 AIW X800 VE"
+0x1002 0x4B49 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R481 X850 XT"
+0x1002 0x4B4A CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R481 X850 SE"
+0x1002 0x4B4B CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R481 X850 Pro"
+0x1002 0x4B4C CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R481 X850 XT PE"
+0x1002 0x4C57 CHIP_RV200|RADEON_IS_MOBILITY "ATI Radeon LW RV200 Mobility 7500 M7"
+0x1002 0x4C58 CHIP_RV200|RADEON_IS_MOBILITY "ATI Radeon LX RV200 Mobility FireGL 7800 M7"
+0x1002 0x4C59 CHIP_RV100|RADEON_IS_MOBILITY "ATI Radeon LY RV100 Mobility M6"
+0x1002 0x4C5A CHIP_RV100|RADEON_IS_MOBILITY "ATI Radeon LZ RV100 Mobility M6"
+0x1002 0x4C64 CHIP_RV250|RADEON_IS_MOBILITY "ATI Radeon Ld RV250 Mobility 9000 M9"
+0x1002 0x4C66 CHIP_RV250 "ATI Radeon Lf RV250 Mobility 9000 M9 / FireMV 2400 PCI"
+0x1002 0x4C67 CHIP_RV250|RADEON_IS_MOBILITY "ATI Radeon Lg RV250 Mobility 9000 M9"
+0x1002 0x4E44 CHIP_R300 "ATI Radeon ND R300 9700 Pro"
+0x1002 0x4E45 CHIP_R300 "ATI Radeon NE R300 9500 Pro / 9700"
+0x1002 0x4E46 CHIP_R300 "ATI Radeon NF R300 9600TX"
+0x1002 0x4E47 CHIP_R300 "ATI Radeon NG R300 FireGL X1"
+0x1002 0x4E48 CHIP_R350 "ATI Radeon NH R350 9800 Pro"
+0x1002 0x4E49 CHIP_R350 "ATI Radeon NI R350 9800"
+0x1002 0x4E4A CHIP_R350 "ATI Radeon NJ R360 9800 XT"
+0x1002 0x4E4B CHIP_R350 "ATI FireGL NK X2"
+0x1002 0x4E50 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M10 NP"
+0x1002 0x4E51 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M10 NQ"
+0x1002 0x4E52 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M11 NR"
+0x1002 0x4E53 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M10 NS"
+0x1002 0x4E54 CHIP_RV350|RADEON_IS_MOBILITY "ATI FireGL T2/T2e"
+0x1002 0x4E56 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon Mobility 9550"
+0x1002 0x5144 CHIP_R100|RADEON_SINGLE_CRTC "ATI Radeon QD R100"
+0x1002 0x5145 CHIP_R100|RADEON_SINGLE_CRTC "ATI Radeon QE R100"
+0x1002 0x5146 CHIP_R100|RADEON_SINGLE_CRTC "ATI Radeon QF R100"
+0x1002 0x5147 CHIP_R100|RADEON_SINGLE_CRTC "ATI Radeon QG R100"
+0x1002 0x5148 CHIP_R200 "ATI Radeon QH R200 8500"
+0x1002 0x514C CHIP_R200 "ATI Radeon QL R200 8500 LE"
+0x1002 0x514D CHIP_R200 "ATI Radeon QM R200 9100"
+0x1002 0x5157 CHIP_RV200 "ATI Radeon QW RV200 7500"
+0x1002 0x5158 CHIP_RV200 "ATI Radeon QX RV200 7500"
+0x1002 0x5159 CHIP_RV100 "ATI Radeon QY RV100 7000/VE"
+0x1002 0x515A CHIP_RV100 "ATI Radeon QZ RV100 7000/VE"
+0x1002 0x515E CHIP_RV100 "ATI ES1000 RN50"
+0x1002 0x5460 CHIP_RV380|RADEON_IS_MOBILITY "ATI Radeon Mobility X300 M22"
+0x1002 0x5462 CHIP_RV380|RADEON_IS_MOBILITY "ATI Radeon Mobility X600 SE M24C"
+0x1002 0x5464 CHIP_RV380|RADEON_IS_MOBILITY "ATI FireGL M22 GL 5464"
+0x1002 0x5548 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800"
+0x1002 0x5549 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 Pro"
+0x1002 0x554A CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 XT PE"
+0x1002 0x554B CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 SE"
+0x1002 0x554C CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R430 X800 XTP"
+0x1002 0x554D CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R430 X800 XL"
+0x1002 0x554E CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R430 X800 SE"
+0x1002 0x554F CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R430 X800"
+0x1002 0x5550 CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL V7100 R423"
+0x1002 0x5551 CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL V5100 R423 UQ"
+0x1002 0x5552 CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL unknown R423 UR"
+0x1002 0x5554 CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL unknown R423 UT"
+0x1002 0x564A CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5000 M26"
+0x1002 0x564B CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5000 M26"
+0x1002 0x564F CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 XL M26"
+0x1002 0x5652 CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 M26"
+0x1002 0x5653 CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 M26"
+0x1002 0x5834 CHIP_RS300|RADEON_IS_IGP "ATI Radeon RS300 9100 IGP"
+0x1002 0x5835 CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS300 Mobility IGP"
+0x1002 0x5960 CHIP_RV280 "ATI Radeon RV280 9250"
+0x1002 0x5961 CHIP_RV280 "ATI Radeon RV280 9200"
+0x1002 0x5962 CHIP_RV280 "ATI Radeon RV280 9200"
+0x1002 0x5964 CHIP_RV280 "ATI Radeon RV280 9200 SE"
+0x1002 0x5965 CHIP_RV280 "ATI FireMV 2200 PCI"
+0x1002 0x5969 CHIP_RV100 "ATI ES1000 RN50"
+0x1002 0x5b60 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X300 SE"
+0x1002 0x5b62 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X600 Pro"
+0x1002 0x5b63 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X550"
+0x1002 0x5b64 CHIP_RV380|RADEON_NEW_MEMMAP "ATI FireGL V3100 (RV370) 5B64"
+0x1002 0x5b65 CHIP_RV380|RADEON_NEW_MEMMAP "ATI FireMV 2200 PCIE (RV370) 5B65"
+0x1002 0x5c61 CHIP_RV280|RADEON_IS_MOBILITY "ATI Radeon RV280 Mobility"
+0x1002 0x5c63 CHIP_RV280|RADEON_IS_MOBILITY "ATI Radeon RV280 Mobility"
+0x1002 0x5d48 CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X800 XT M28"
+0x1002 0x5d49 CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5100 M28"
+0x1002 0x5d4a CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X800 M28"
+0x1002 0x5d4c CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850"
+0x1002 0x5d4d CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850 XT PE"
+0x1002 0x5d4e CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850 SE"
+0x1002 0x5d4f CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850 Pro"
+0x1002 0x5d50 CHIP_R420|RADEON_NEW_MEMMAP "ATI unknown Radeon / FireGL R480"
+0x1002 0x5d52 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850 XT"
+0x1002 0x5d57 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 XT"
+0x1002 0x5e48 CHIP_RV410|RADEON_NEW_MEMMAP "ATI FireGL V5000 RV410"
+0x1002 0x5e4a CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 XT"
+0x1002 0x5e4b CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 Pro"
+0x1002 0x5e4c CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 SE"
+0x1002 0x5e4d CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700"
+0x1002 0x5e4f CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 SE"
+0x1002 0x7834 CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP "ATI Radeon RS350 9000/9100 IGP"
+0x1002 0x7835 CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon RS350 Mobility IGP"
+
+[r128]
+0x1002 0x4c45 0 "ATI Rage 128 Mobility LE (PCI)"
+0x1002 0x4c46 0 "ATI Rage 128 Mobility LF (AGP)"
+0x1002 0x4d46 0 "ATI Rage 128 Mobility MF (AGP)"
+0x1002 0x4d4c 0 "ATI Rage 128 Mobility ML (AGP)"
+0x1002 0x5041 0 "ATI Rage 128 Pro PA (PCI)"
+0x1002 0x5042 0 "ATI Rage 128 Pro PB (AGP)"
+0x1002 0x5043 0 "ATI Rage 128 Pro PC (AGP)"
+0x1002 0x5044 0 "ATI Rage 128 Pro PD (PCI)"
+0x1002 0x5045 0 "ATI Rage 128 Pro PE (AGP)"
+0x1002 0x5046 0 "ATI Rage 128 Pro PF (AGP)"
+0x1002 0x5047 0 "ATI Rage 128 Pro PG (PCI)"
+0x1002 0x5048 0 "ATI Rage 128 Pro PH (AGP)"
+0x1002 0x5049 0 "ATI Rage 128 Pro PI (AGP)"
+0x1002 0x504A 0 "ATI Rage 128 Pro PJ (PCI)"
+0x1002 0x504B 0 "ATI Rage 128 Pro PK (AGP)"
+0x1002 0x504C 0 "ATI Rage 128 Pro PL (AGP)"
+0x1002 0x504D 0 "ATI Rage 128 Pro PM (PCI)"
+0x1002 0x504E 0 "ATI Rage 128 Pro PN (AGP)"
+0x1002 0x504F 0 "ATI Rage 128 Pro PO (AGP)"
+0x1002 0x5050 0 "ATI Rage 128 Pro PP (PCI)"
+0x1002 0x5051 0 "ATI Rage 128 Pro PQ (AGP)"
+0x1002 0x5052 0 "ATI Rage 128 Pro PR (PCI)"
+0x1002 0x5053 0 "ATI Rage 128 Pro PS (PCI)"
+0x1002 0x5054 0 "ATI Rage 128 Pro PT (AGP)"
+0x1002 0x5055 0 "ATI Rage 128 Pro PU (AGP)"
+0x1002 0x5056 0 "ATI Rage 128 Pro PV (PCI)"
+0x1002 0x5057 0 "ATI Rage 128 Pro PW (AGP)"
+0x1002 0x5058 0 "ATI Rage 128 Pro PX (AGP)"
+0x1002 0x5245 0 "ATI Rage 128 RE (PCI)"
+0x1002 0x5246 0 "ATI Rage 128 RF (AGP)"
+0x1002 0x5247 0 "ATI Rage 128 RG (AGP)"
+0x1002 0x524b 0 "ATI Rage 128 RK (PCI)"
+0x1002 0x524c 0 "ATI Rage 128 RL (AGP)"
+0x1002 0x534d 0 "ATI Rage 128 SM (AGP)"
+0x1002 0x5446 0 "ATI Rage 128 Pro Ultra TF (AGP)"
+0x1002 0x544C 0 "ATI Rage 128 Pro Ultra TL (AGP)"
+0x1002 0x5452 0 "ATI Rage 128 Pro Ultra TR (AGP)"
+
+[mga]
+0x102b 0x0520 MGA_CARD_TYPE_G200 "Matrox G200 (PCI)"
+0x102b 0x0521 MGA_CARD_TYPE_G200 "Matrox G200 (AGP)"
+0x102b 0x0525 MGA_CARD_TYPE_G400 "Matrox G400/G450 (AGP)"
+0x102b 0x2527 MGA_CARD_TYPE_G550 "Matrox G550 (AGP)"
+
+[mach64]
+0x1002 0x4749 0 "3D Rage Pro"
+0x1002 0x4750 0 "3D Rage Pro 215GP"
+0x1002 0x4751 0 "3D Rage Pro 215GQ"
+0x1002 0x4742 0 "3D Rage Pro AGP 1X/2X"
+0x1002 0x4744 0 "3D Rage Pro AGP 1X"
+0x1002 0x4c49 0 "3D Rage LT Pro"
+0x1002 0x4c50 0 "3D Rage LT Pro"
+0x1002 0x4c51 0 "3D Rage LT Pro"
+0x1002 0x4c42 0 "3D Rage LT Pro AGP-133"
+0x1002 0x4c44 0 "3D Rage LT Pro AGP-66"
+0x1002 0x4759 0 "Rage 3D IICATI 3D RAGE IIC AGP(A12/A13)
+0x1002 0x474c 0 "Rage XC"
+0x1002 0x474f 0 "Rage XL"
+0x1002 0x4752 0 "Rage XL"
+0x1002 0x4753 0 "Rage XC"
+0x1002 0x474d 0 "Rage XL AGP 2X"
+0x1002 0x474e 0 "Rage XC AGP"
+0x1002 0x4c52 0 "Rage Mobility P/M"
+0x1002 0x4c53 0 "Rage Mobility L"
+0x1002 0x4c4d 0 "Rage Mobility P/M AGP 2X"
+0x1002 0x4c4e 0 "Rage Mobility L AGP 2X"
+
+[sis]
+0x1039 0x0300 0 "SiS 300/305"
+0x1039 0x5300 0 "SiS 540"
+0x1039 0x6300 0 "SiS 630"
+0x1039 0x6330 SIS_CHIP_315 "SiS 661"
+0x1039 0x7300 0 "SiS 730"
+
+[tdfx]
+0x121a 0x0003 0 "3dfx Voodoo Banshee"
+0x121a 0x0004 0 "3dfx Voodoo3 2000"
+0x121a 0x0005 0 "3dfx Voodoo3 3000"
+0x121a 0x0007 0 "3dfx Voodoo4 4500"
+0x121a 0x0009 0 "3dfx Voodoo5 5500"
+0x121a 0x000b 0 "3dfx Voodoo4 4200"
+
+[viadrv]
+0x1106 0x3022 0 "VIA CLE266 3022"
+0x1106 0x3118 VIA_PRO_GROUP_A "VIA CN400 / PM8X0"
+0x1106 0x3122 0 "VIA CLE266"
+0x1106 0x7205 0 "VIA KM400"
+0x1106 0x3108 0 "VIA K8M800"
+0x1106 0x3344 0 "VIA P4VM800PRO"
+
+[i810]
+0x8086 0x7121 0 "Intel i810 GMCH"
+0x8086 0x7123 0 "Intel i810-DC100 GMCH"
+0x8086 0x7125 0 "Intel i810E GMCH"
+0x8086 0x1132 0 "Intel i815 GMCH"
+
+[i830]
+0x8086 0x3577 0 "Intel i830M GMCH"
+0x8086 0x2562 0 "Intel i845G GMCH"
+0x8086 0x3582 0 "Intel i852GM/i855GM GMCH"
+0x8086 0x2572 0 "Intel i865G GMCH"
+
+[gamma]
+0x3d3d 0x0008 0 "3DLabs GLINT Gamma G1"
+
+[savage]
+0x5333 0x8a20 S3_SAVAGE3D "Savage 3D"
+0x5333 0x8a21 S3_SAVAGE3D "Savage 3D/MV"
+0x5333 0x8a22 S3_SAVAGE4 "Savage4"
+0x5333 0x8a23 S3_SAVAGE4 "Savage4"
+0x5333 0x8c10 S3_SAVAGE_MX "Savage/MX-MV"
+0x5333 0x8c11 S3_SAVAGE_MX "Savage/MX"
+0x5333 0x8c12 S3_SAVAGE_MX "Savage/IX-MV"
+0x5333 0x8c13 S3_SAVAGE_MX "Savage/IX"
+0x5333 0x8c22 S3_SUPERSAVAGE "SuperSavage MX/128"
+0x5333 0x8c24 S3_SUPERSAVAGE "SuperSavage MX/64"
+0x5333 0x8c26 S3_SUPERSAVAGE "SuperSavage MX/64C"
+0x5333 0x8c2a S3_SUPERSAVAGE "SuperSavage IX/128 SDR"
+0x5333 0x8c2b S3_SUPERSAVAGE "SuperSavage IX/128 DDR"
+0x5333 0x8c2c S3_SUPERSAVAGE "SuperSavage IX/64 SDR"
+0x5333 0x8c2d S3_SUPERSAVAGE "SuperSavage IX/64 DDR"
+0x5333 0x8c2e S3_SUPERSAVAGE "SuperSavage IX/C SDR"
+0x5333 0x8c2f S3_SUPERSAVAGE "SuperSavage IX/C DDR"
+0x5333 0x8a25 S3_PROSAVAGE "ProSavage PM133"
+0x5333 0x8a26 S3_PROSAVAGE "ProSavage KM133"
+0x5333 0x8d01 S3_TWISTER "ProSavage Twister PN133"
+0x5333 0x8d02 S3_TWISTER "ProSavage Twister KN133"
+0x5333 0x8d03 S3_PROSAVAGEDDR "ProSavage DDR"
+0x5333 0x8d04 S3_PROSAVAGEDDR "ProSavage DDR-K"
+
+[ffb]
+
+[i915]
+0x8086 0x3577 0 "Intel i830M GMCH"
+0x8086 0x2562 0 "Intel i845G GMCH"
+0x8086 0x3582 0 "Intel i852GM/i855GM GMCH"
+0x8086 0x2572 0 "Intel i865G GMCH"
+0x8086 0x2582 0 "Intel i915G"
+0x8086 0x2592 0 "Intel i915GM"
+0x8086 0x2772 0 "Intel i945G"
+0x8086 0x27A2 0 "Intel i945GM"
+0x8086 0x2972 0 "Intel i946GZ"
+0x8086 0x2982 0 "Intel i965G"
+0x8086 0x2992 0 "Intel i965Q"
+0x8086 0x29A2 0 "Intel i965G"
+
+[imagine]
+0x105d 0x2309 IMAGINE_128 "Imagine 128"
+0x105d 0x2339 IMAGINE_128_2 "Imagine 128-II"
+0x105d 0x493d IMAGINE_T2R "Ticket to Ride"
+0x105d 0x5348 IMAGINE_REV4 "Revolution IV"
+
+[nv]
+0x10DE 0x0020 NV04 "NVidia RIVA TNT"
+0x10DE 0x0028 NV04 "NVidia RIVA TNT2"
+0x10DE 0x002A NV04 "NVidia Unknown TNT2"
+0x10DE 0x002C NV04 "NVidia Vanta"
+0x10DE 0x0029 NV04 "NVidia RIVA TNT2 Ultra"
+0x10DE 0x002D NV04 "NVidia RIVA TNT2 Model 64"
+0x10DE 0x00A0 NV04 "NVidia Aladdin TNT2"
+0x10DE 0x0100 NV10 "NVidia GeForce 256"
+0x10DE 0x0101 NV10 "NVidia GeForce DDR"
+0x10DE 0x0103 NV10 "NVidia Quadro"
+0x10DE 0x0110 NV10 "NVidia GeForce2 MX/MX 400"
+0x10DE 0x0111 NV10 "NVidia GeForce2 MX 100/200"
+0x10DE 0x0112 NV10 "NVidia GeForce2 Go"
+0x10DE 0x0113 NV10 "NVidia Quadro2 MXR/EX/Go"
+0x10DE 0x0150 NV10 "NVidia GeForce2 GTS"
+0x10DE 0x0151 NV10 "NVidia GeForce2 Ti"
+0x10DE 0x0152 NV10 "NVidia GeForce2 Ultra"
+0x10DE 0x0153 NV10 "NVidia Quadro2 Pro"
+0x10DE 0x0170 NV10 "NVidia GeForce4 MX 460"
+0x10DE 0x0171 NV10 "NVidia GeForce4 MX 440"
+0x10DE 0x0172 NV10 "NVidia GeForce4 MX 420"
+0x10DE 0x0173 NV10 "NVidia GeForce4 MX 440-SE"
+0x10DE 0x0174 NV10 "NVidia GeForce4 440 Go"
+0x10DE 0x0175 NV10 "NVidia GeForce4 420 Go"
+0x10DE 0x0176 NV10 "NVidia GeForce4 420 Go 32M"
+0x10DE 0x0177 NV10 "NVidia GeForce4 460 Go"
+0x10DE 0x0178 NV10 "NVidia Quadro4 550 XGL"
+0x10DE 0x0179 NV10 "NVidia GeForce4"
+0x10DE 0x017A NV10 "NVidia Quadro4 NVS"
+0x10DE 0x017C NV10 "NVidia Quadro4 500 GoGL"
+0x10DE 0x017D NV10 "NVidia GeForce4 410 Go 16M"
+0x10DE 0x0181 NV10 "NVidia GeForce4 MX 440 with AGP8X"
+0x10DE 0x0182 NV10 "NVidia GeForce4 MX 440SE with AGP8X"
+0x10DE 0x0183 NV10 "NVidia GeForce4 MX 420 with AGP8X"
+0x10DE 0x0185 NV10 "NVidia GeForce4 MX 4000"
+0x10DE 0x0186 NV10 "NVidia GeForce4 448 Go"
+0x10DE 0x0187 NV10 "NVidia GeForce4 488 Go"
+0x10DE 0x0188 NV10 "NVidia Quadro4 580 XGL"
+0x10DE 0x0189 NV10 "NVidia GeForce4 MX with AGP8X (Mac)"
+0x10DE 0x018A NV10 "NVidia Quadro4 280 NVS"
+0x10DE 0x018B NV10 "NVidia Quadro4 380 XGL"
+0x10DE 0x018C NV10 "NVidia Quadro NVS 50 PCI"
+0x10DE 0x018D NV10 "NVidia GeForce4 448 Go"
+0x10DE 0x01A0 NV10 "NVidia GeForce2 Integrated GPU"
+0x10DE 0x01F0 NV10 "NVidia GeForce4 MX Integrated GPU"
+0x10DE 0x0200 NV20 "NVidia GeForce3"
+0x10DE 0x0201 NV20 "NVidia GeForce3 Ti 200"
+0x10DE 0x0202 NV20 "NVidia GeForce3 Ti 500"
+0x10DE 0x0203 NV20 "NVidia Quadro DCC"
+0x10DE 0x0250 NV20 "NVidia GeForce4 Ti 4600"
+0x10DE 0x0251 NV20 "NVidia GeForce4 Ti 4400"
+0x10DE 0x0252 NV20 "NVidia 0x0252"
+0x10DE 0x0253 NV20 "NVidia GeForce4 Ti 4200"
+0x10DE 0x0258 NV20 "NVidia Quadro4 900 XGL"
+0x10DE 0x0259 NV20 "NVidia Quadro4 750 XGL"
+0x10DE 0x025B NV20 "NVidia Quadro4 700 XGL"
+0x10DE 0x0280 NV20 "NVidia GeForce4 Ti 4800"
+0x10DE 0x0281 NV20 "NVidia GeForce4 Ti 4200 with AGP8X"
+0x10DE 0x0282 NV20 "NVidia GeForce4 Ti 4800 SE"
+0x10DE 0x0286 NV20 "NVidia GeForce4 4200 Go"
+0x10DE 0x028C NV20 "NVidia Quadro4 700 GoGL"
+0x10DE 0x0288 NV20 "NVidia Quadro4 980 XGL"
+0x10DE 0x0289 NV20 "NVidia Quadro4 780 XGL"
+0x10DE 0x0301 NV30 "NVidia GeForce FX 5800 Ultra"
+0x10DE 0x0302 NV30 "NVidia GeForce FX 5800"
+0x10DE 0x0308 NV30 "NVidia Quadro FX 2000"
+0x10DE 0x0309 NV30 "NVidia Quadro FX 1000"
+0x10DE 0x0311 NV30 "NVidia GeForce FX 5600 Ultra"
+0x10DE 0x0312 NV30 "NVidia GeForce FX 5600"
+0x10DE 0x0313 NV30 "NVidia 0x0313"},
+0x10DE 0x0314 NV30 "NVidia GeForce FX 5600SE"
+0x10DE 0x0316 NV30 "NVidia 0x0316"
+0x10DE 0x0317 NV30 "NVidia 0x0317"
+0x10DE 0x031A NV30 "NVidia GeForce FX Go5600"
+0x10DE 0x031B NV30 "NVidia GeForce FX Go5650"
+0x10DE 0x031C NV30 "NVidia Quadro FX Go700"
+0x10DE 0x031D NV30 "NVidia 0x031D"
+0x10DE 0x031E NV30 "NVidia 0x031E"
+0x10DE 0x031F NV30 "NVidia 0x031F"
+0x10DE 0x0320 NV30 "NVidia GeForce FX 5200"
+0x10DE 0x0321 NV30 "NVidia GeForce FX 5200 Ultra"
+0x10DE 0x0322 NV30 "NVidia GeForce FX 5200"
+0x10DE 0x0323 NV30 "NVidia GeForce FX 5200SE"
+0x10DE 0x0324 NV30 "NVidia GeForce FX Go5200"
+0x10DE 0x0325 NV30 "NVidia GeForce FX Go5250"
+0x10DE 0x0326 NV30 "NVidia GeForce FX 5500"
+0x10DE 0x0327 NV30 "NVidia GeForce FX 5100"
+0x10DE 0x0328 NV30 "NVidia GeForce FX Go5200 32M/64M"
+0x10DE 0x0329 NV30 "NVidia GeForce FX 5200 (Mac)"
+0x10DE 0x032A NV30 "NVidia Quadro NVS 280 PCI"
+0x10DE 0x032B NV30 "NVidia Quadro FX 500/600 PCI"
+0x10DE 0x032C NV30 "NVidia GeForce FX Go53xx Series"
+0x10DE 0x032D NV30 "NVidia GeForce FX Go5100"
+0x10DE 0x032F NV30 "NVidia 0x032F"
+0x10DE 0x0330 NV30 "NVidia GeForce FX 5900 Ultra"
+0x10DE 0x0331 NV30 "NVidia GeForce FX 5900"
+0x10DE 0x0332 NV30 "NVidia GeForce FX 5900XT"
+0x10DE 0x0333 NV30 "NVidia GeForce FX 5950 Ultra"
+0x10DE 0x033F NV30 "NVidia Quadro FX 700"
+0x10DE 0x0334 NV30 "NVidia GeForce FX 5900ZT"
+0x10DE 0x0338 NV30 "NVidia Quadro FX 3000"
+0x10DE 0x0341 NV30 "NVidia GeForce FX 5700 Ultra"
+0x10DE 0x0342 NV30 "NVidia GeForce FX 5700"
+0x10DE 0x0343 NV30 "NVidia GeForce FX 5700LE"
+0x10DE 0x0344 NV30 "NVidia GeForce FX 5700VE"
+0x10DE 0x0345 NV30 "NVidia 0x0345"
+0x10DE 0x0347 NV30 "NVidia GeForce FX Go5700"
+0x10DE 0x0348 NV30 "NVidia GeForce FX Go5700"
+0x10DE 0x0349 NV30 "NVidia 0x0349"
+0x10DE 0x034B NV30 "NVidia 0x034B"
+0x10DE 0x034C NV30 "NVidia Quadro FX Go1000"
+0x10DE 0x034E NV30 "NVidia Quadro FX 1100"
+0x10DE 0x034F NV30 "NVidia 0x034F"
+0x10DE 0x0040 NV40 "NVidia GeForce 6800 Ultra"
+0x10DE 0x0041 NV40 "NVidia GeForce 6800"
+0x10DE 0x0042 NV40 "NVidia GeForce 6800 LE"
+0x10DE 0x0043 NV40 "NVidia 0x0043"
+0x10DE 0x0045 NV40 "NVidia GeForce 6800 GT"
+0x10DE 0x0046 NV40 "NVidia GeForce 6800 GT"
+0x10DE 0x0049 NV40 "NVidia 0x0049"
+0x10DE 0x004E NV40 "NVidia Quadro FX 4000"
+0x10DE 0x00C0 NV40 "NVidia 0x00C0"
+0x10DE 0x00C1 NV40 "NVidia GeForce 6800"
+0x10DE 0x00C2 NV40 "NVidia GeForce 6800 LE"
+0x10DE 0x00C8 NV40 "NVidia GeForce Go 6800"
+0x10DE 0x00C9 NV40 "NVidia GeForce Go 6800 Ultra"
+0x10DE 0x00CC NV40 "NVidia Quadro FX Go1400"
+0x10DE 0x00CD NV40 "NVidia Quadro FX 3450/4000 SDI"
+0x10DE 0x00CE NV40 "NVidia Quadro FX 1400"
+0x10de 0x00f0 NV40 "Nvidia GeForce 6600 GT"
+0x10de 0x00f1 NV40 "Nvidia GeForce 6600 GT"
+0x10DE 0x0140 NV40 "NVidia GeForce 6600 GT"
+0x10DE 0x0141 NV40 "NVidia GeForce 6600"
+0x10DE 0x0142 NV40 "NVidia GeForce 6600 LE"
+0x10DE 0x0143 NV40 "NVidia 0x0143"
+0x10DE 0x0144 NV40 "NVidia GeForce Go 6600"
+0x10DE 0x0145 NV40 "NVidia GeForce 6610 XL"
+0x10DE 0x0146 NV40 "NVidia GeForce Go 6600 TE/6200 TE"
+0x10DE 0x0147 NV40 "NVidia GeForce 6700 XL"
+0x10DE 0x0148 NV40 "NVidia GeForce Go 6600"
+0x10DE 0x0149 NV40 "NVidia GeForce Go 6600 GT"
+0x10DE 0x014B NV40 "NVidia 0x014B"
+0x10DE 0x014C NV40 "NVidia 0x014C"
+0x10DE 0x014D NV40 "NVidia 0x014D"
+0x10DE 0x014E NV40 "NVidia Quadro FX 540"
+0x10DE 0x014F NV40 "NVidia GeForce 6200"
+0x10DE 0x0160 NV40 "NVidia 0x0160"
+0x10DE 0x0161 NV40 "NVidia GeForce 6200 TurboCache(TM)"
+0x10DE 0x0162 NV40 "NVidia GeForce 6200SE TurboCache(TM)"
+0x10DE 0x0163 NV40 "NVidia 0x0163"
+0x10DE 0x0164 NV40 "NVidia GeForce Go 6200"
+0x10DE 0x0165 NV40 "NVidia Quadro NVS 285"
+0x10DE 0x0166 NV40 "NVidia GeForce Go 6400"
+0x10DE 0x0167 NV40 "NVidia GeForce Go 6200"
+0x10DE 0x0168 NV40 "NVidia GeForce Go 6400"
+0x10DE 0x0169 NV40 "NVidia 0x0169"
+0x10DE 0x016B NV40 "NVidia 0x016B"
+0x10DE 0x016C NV40 "NVidia 0x016C"
+0x10DE 0x016D NV40 "NVidia 0x016D"
+0x10DE 0x016E NV40 "NVidia 0x016E"
+0x10DE 0x0210 NV40 "NVidia 0x0210"
+0x10DE 0x0211 NV40 "NVidia GeForce 6800"
+0x10DE 0x0212 NV40 "NVidia GeForce 6800 LE"
+0x10DE 0x0215 NV40 "NVidia GeForce 6800 GT"
+0x10DE 0x0220 NV40 "NVidia 0x0220"
+0x10DE 0x0221 NV40 "NVidia GeForce 6200"
+0x10DE 0x0222 NV40 "NVidia 0x0222"
+0x10DE 0x0228 NV40 "NVidia 0x0228"
+0x10DE 0x0090 NV40 "NVidia 0x0090"
+0x10DE 0x0091 NV40 "NVidia GeForce 7800 GTX"
+0x10DE 0x0092 NV40 "NVidia 0x0092"
+0x10DE 0x0093 NV40 "NVidia 0x0093"
+0x10DE 0x0094 NV40 "NVidia 0x0094"
+0x10DE 0x0098 NV40 "NVidia 0x0098"
+0x10DE 0x0099 NV40 "NVidia GeForce Go 7800 GTX"
+0x10DE 0x009C NV40 "NVidia 0x009C"
+0x10DE 0x009D NV40 "NVidia Quadro FX 4500"
+0x10DE 0x009E NV40 "NVidia 0x009E"
--- libdrm-2.3.0.orig/shared-core/imagine_drv.h
+++ libdrm-2.3.0/shared-core/imagine_drv.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+/* derived from tdfx_drv.h */
+
+#ifndef __IMAGINE_DRV_H__
+#define __IMAGINE_DRV_H__
+
+#define DRIVER_AUTHOR       "Adam Jackson"
+#define DRIVER_NAME         "imagine"
+#define DRIVER_DESC         "#9 Imagine128 and Ticket 2 Ride"
+#define DRIVER_DATE         "20050328"
+#define DRIVER_MAJOR        0
+#define DRIVER_MINOR        0
+#define DRIVER_PATCHLEVEL   1
+
+enum imagine_family {
+    IMAGINE_128,
+    IMAGINE_128_2,
+    IMAGINE_T2R,
+    IMAGINE_REV4
+};
+
+#endif /* __IMAGINE_DRV_H__ */
--- libdrm-2.3.0.orig/shared-core/savage_bci.c
+++ libdrm-2.3.0/shared-core/savage_bci.c
@@ -0,0 +1,1109 @@
+/* savage_bci.c -- BCI support for Savage
+ *
+ * Copyright 2004  Felix Kuehling
+ * 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 FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 "drmP.h"
+#include "savage_drm.h"
+#include "savage_drv.h"
+
+/* Need a long timeout for shadow status updates can take a while
+ * and so can waiting for events when the queue is full. */
+#define SAVAGE_DEFAULT_USEC_TIMEOUT	1000000 /* 1s */
+#define SAVAGE_EVENT_USEC_TIMEOUT	5000000 /* 5s */
+#define SAVAGE_FREELIST_DEBUG		0
+
+static int
+savage_bci_wait_fifo_shadow(drm_savage_private_t *dev_priv, unsigned int n)
+{
+	uint32_t mask = dev_priv->status_used_mask;
+	uint32_t threshold = dev_priv->bci_threshold_hi;
+	uint32_t status;
+	int i;
+
+#if SAVAGE_BCI_DEBUG
+	if (n > dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - threshold)
+		DRM_ERROR("Trying to emit %d words "
+			  "(more than guaranteed space in COB)\n", n);
+#endif
+
+	for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+		DRM_MEMORYBARRIER();
+		status = dev_priv->status_ptr[0];
+		if ((status & mask) < threshold)
+			return 0;
+		DRM_UDELAY(1);
+	}
+
+#if SAVAGE_BCI_DEBUG
+	DRM_ERROR("failed!\n");
+	DRM_INFO("   status=0x%08x, threshold=0x%08x\n", status, threshold);
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+static int
+savage_bci_wait_fifo_s3d(drm_savage_private_t *dev_priv, unsigned int n)
+{
+	uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+	uint32_t status;
+	int i;
+
+	for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+		status = SAVAGE_READ(SAVAGE_STATUS_WORD0);
+		if ((status & SAVAGE_FIFO_USED_MASK_S3D) <= maxUsed)
+			return 0;
+		DRM_UDELAY(1);
+	}
+
+#if SAVAGE_BCI_DEBUG
+	DRM_ERROR("failed!\n");
+	DRM_INFO("   status=0x%08x\n", status);
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+static int
+savage_bci_wait_fifo_s4(drm_savage_private_t *dev_priv, unsigned int n)
+{
+	uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+	uint32_t status;
+	int i;
+
+	for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+		status = SAVAGE_READ(SAVAGE_ALT_STATUS_WORD0);
+		if ((status & SAVAGE_FIFO_USED_MASK_S4) <= maxUsed)
+			return 0;
+		DRM_UDELAY(1);
+	}
+
+#if SAVAGE_BCI_DEBUG
+	DRM_ERROR("failed!\n");
+	DRM_INFO("   status=0x%08x\n", status);
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+/*
+ * Waiting for events.
+ *
+ * The BIOSresets the event tag to 0 on mode changes. Therefore we
+ * never emit 0 to the event tag. If we find a 0 event tag we know the
+ * BIOS stomped on it and return success assuming that the BIOS waited
+ * for engine idle.
+ *
+ * Note: if the Xserver uses the event tag it has to follow the same
+ * rule. Otherwise there may be glitches every 2^16 events.
+ */
+static int
+savage_bci_wait_event_shadow(drm_savage_private_t *dev_priv, uint16_t e)
+{
+	uint32_t status;
+	int i;
+
+	for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
+		DRM_MEMORYBARRIER();
+		status = dev_priv->status_ptr[1];
+		if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
+		    (status & 0xffff) == 0)
+			return 0;
+		DRM_UDELAY(1);
+	}
+
+#if SAVAGE_BCI_DEBUG
+	DRM_ERROR("failed!\n");
+	DRM_INFO("   status=0x%08x, e=0x%04x\n", status, e);
+#endif
+
+	return DRM_ERR(EBUSY);
+}
+
+static int
+savage_bci_wait_event_reg(drm_savage_private_t *dev_priv, uint16_t e)
+{
+	uint32_t status;
+	int i;
+
+	for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
+		status = SAVAGE_READ(SAVAGE_STATUS_WORD1);
+		if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
+		    (status & 0xffff) == 0)
+			return 0;
+		DRM_UDELAY(1);
+	}
+
+#if SAVAGE_BCI_DEBUG
+	DRM_ERROR("failed!\n");
+	DRM_INFO("   status=0x%08x, e=0x%04x\n", status, e);
+#endif
+
+	return DRM_ERR(EBUSY);
+}
+
+uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
+			       unsigned int flags)
+{
+	uint16_t count;
+	BCI_LOCALS;
+
+	if (dev_priv->status_ptr) {
+		/* coordinate with Xserver */
+		count = dev_priv->status_ptr[1023];
+		if (count < dev_priv->event_counter)
+			dev_priv->event_wrap++;
+	} else {
+		count = dev_priv->event_counter;
+	}
+	count = (count + 1) & 0xffff;
+	if (count == 0) {
+		count++; /* See the comment above savage_wait_event_*. */
+		dev_priv->event_wrap++;
+	}
+	dev_priv->event_counter = count;
+	if (dev_priv->status_ptr)
+		dev_priv->status_ptr[1023] = (uint32_t)count;
+
+	if ((flags & (SAVAGE_WAIT_2D | SAVAGE_WAIT_3D))) {
+		unsigned int wait_cmd = BCI_CMD_WAIT;
+		if ((flags & SAVAGE_WAIT_2D))
+			wait_cmd |= BCI_CMD_WAIT_2D;
+		if ((flags & SAVAGE_WAIT_3D))
+			wait_cmd |= BCI_CMD_WAIT_3D;
+		BEGIN_BCI(2);
+		BCI_WRITE(wait_cmd);
+	} else {
+		BEGIN_BCI(1);
+	}
+	BCI_WRITE(BCI_CMD_UPDATE_EVENT_TAG | (uint32_t)count);
+
+	return count;
+}
+
+/*
+ * Freelist management
+ */
+static int savage_freelist_init(drm_device_t *dev)
+{
+	drm_savage_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_savage_buf_priv_t *entry;
+	int i;
+	DRM_DEBUG("count=%d\n", dma->buf_count);
+
+	dev_priv->head.next = &dev_priv->tail;
+	dev_priv->head.prev = NULL;
+	dev_priv->head.buf = NULL;
+
+	dev_priv->tail.next = NULL;
+	dev_priv->tail.prev = &dev_priv->head;
+	dev_priv->tail.buf = NULL;
+
+	for (i = 0; i < dma->buf_count; i++) {
+		buf = dma->buflist[i];
+		entry = buf->dev_private;
+
+		SET_AGE(&entry->age, 0, 0);
+		entry->buf = buf;
+
+		entry->next = dev_priv->head.next;
+		entry->prev = &dev_priv->head;
+		dev_priv->head.next->prev = entry;
+		dev_priv->head.next = entry;
+	}
+
+	return 0;
+}
+
+static drm_buf_t *savage_freelist_get(drm_device_t *dev)
+{
+	drm_savage_private_t *dev_priv = dev->dev_private;
+	drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
+	uint16_t event;
+	unsigned int wrap;
+	DRM_DEBUG("\n");
+
+	UPDATE_EVENT_COUNTER();
+	if (dev_priv->status_ptr)
+		event = dev_priv->status_ptr[1] & 0xffff;
+	else
+		event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+	wrap = dev_priv->event_wrap;
+	if (event > dev_priv->event_counter)
+		wrap--; /* hardware hasn't passed the last wrap yet */
+
+	DRM_DEBUG("   tail=0x%04x %d\n", tail->age.event, tail->age.wrap);
+	DRM_DEBUG("   head=0x%04x %d\n", event, wrap);
+
+	if (tail->buf && (TEST_AGE(&tail->age, event, wrap) || event == 0)) {
+		drm_savage_buf_priv_t *next = tail->next;
+		drm_savage_buf_priv_t *prev = tail->prev;
+		prev->next = next;
+		next->prev = prev;
+		tail->next = tail->prev = NULL;
+		return tail->buf;
+	}
+
+	DRM_DEBUG("returning NULL, tail->buf=%p!\n", tail->buf);
+	return NULL;
+}
+
+void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf)
+{
+	drm_savage_private_t *dev_priv = dev->dev_private;
+	drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
+
+	DRM_DEBUG("age=0x%04x wrap=%d\n", entry->age.event, entry->age.wrap);
+
+	if (entry->next != NULL || entry->prev != NULL) {
+		DRM_ERROR("entry already on freelist.\n");
+		return;
+	}
+
+	prev = &dev_priv->head;
+	next = prev->next;
+	prev->next = entry;
+	next->prev = entry;
+	entry->prev = prev;
+	entry->next = next;
+}
+
+/*
+ * Command DMA
+ */
+static int savage_dma_init(drm_savage_private_t *dev_priv)
+{
+	unsigned int i;
+
+	dev_priv->nr_dma_pages = dev_priv->cmd_dma->size /
+		(SAVAGE_DMA_PAGE_SIZE*4);
+	dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) *
+					dev_priv->nr_dma_pages, DRM_MEM_DRIVER);
+	if (dev_priv->dma_pages == NULL)
+		return DRM_ERR(ENOMEM);
+
+	for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
+		SET_AGE(&dev_priv->dma_pages[i].age, 0, 0);
+		dev_priv->dma_pages[i].used = 0;
+		dev_priv->dma_pages[i].flushed = 0;
+	}
+	SET_AGE(&dev_priv->last_dma_age, 0, 0);
+
+	dev_priv->first_dma_page = 0;
+	dev_priv->current_dma_page = 0;
+
+	return 0;
+}
+
+void savage_dma_reset(drm_savage_private_t *dev_priv)
+{
+	uint16_t event;
+	unsigned int wrap, i;
+	event = savage_bci_emit_event(dev_priv, 0);
+	wrap = dev_priv->event_wrap;
+	for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
+		SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
+		dev_priv->dma_pages[i].used = 0;
+		dev_priv->dma_pages[i].flushed = 0;
+	}
+	SET_AGE(&dev_priv->last_dma_age, event, wrap);
+	dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
+}
+
+void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page)
+{
+	uint16_t event;
+	unsigned int wrap;
+
+	/* Faked DMA buffer pages don't age. */
+	if (dev_priv->cmd_dma == &dev_priv->fake_dma)
+		return;
+
+	UPDATE_EVENT_COUNTER();
+	if (dev_priv->status_ptr)
+		event = dev_priv->status_ptr[1] & 0xffff;
+	else
+		event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+	wrap = dev_priv->event_wrap;
+	if (event > dev_priv->event_counter)
+		wrap--; /* hardware hasn't passed the last wrap yet */
+
+	if (dev_priv->dma_pages[page].age.wrap > wrap ||
+	    (dev_priv->dma_pages[page].age.wrap == wrap &&
+	     dev_priv->dma_pages[page].age.event > event)) {
+		if (dev_priv->wait_evnt(dev_priv,
+					dev_priv->dma_pages[page].age.event)
+		    < 0)
+			DRM_ERROR("wait_evnt failed!\n");
+	}
+}
+
+uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv, unsigned int n)
+{
+	unsigned int cur = dev_priv->current_dma_page;
+	unsigned int rest = SAVAGE_DMA_PAGE_SIZE -
+		dev_priv->dma_pages[cur].used;
+	unsigned int nr_pages = (n - rest + SAVAGE_DMA_PAGE_SIZE-1) /
+		SAVAGE_DMA_PAGE_SIZE;
+	uint32_t *dma_ptr;
+	unsigned int i;
+
+	DRM_DEBUG("cur=%u, cur->used=%u, n=%u, rest=%u, nr_pages=%u\n",
+		  cur, dev_priv->dma_pages[cur].used, n, rest, nr_pages);
+
+	if (cur + nr_pages < dev_priv->nr_dma_pages) {
+		dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +
+		    cur*SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
+		if (n < rest)
+			rest = n;
+		dev_priv->dma_pages[cur].used += rest;
+		n -= rest;
+		cur++;
+	} else {
+		dev_priv->dma_flush(dev_priv);
+		nr_pages =
+		    (n + SAVAGE_DMA_PAGE_SIZE-1) / SAVAGE_DMA_PAGE_SIZE;
+		for (i = cur; i < dev_priv->nr_dma_pages; ++i) {
+			dev_priv->dma_pages[i].age = dev_priv->last_dma_age;
+			dev_priv->dma_pages[i].used = 0;
+			dev_priv->dma_pages[i].flushed = 0;
+		}
+		dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle;
+		dev_priv->first_dma_page = cur = 0;
+	}
+	for (i = cur; nr_pages > 0; ++i, --nr_pages) {
+#if SAVAGE_DMA_DEBUG
+		if (dev_priv->dma_pages[i].used) {
+			DRM_ERROR("unflushed page %u: used=%u\n",
+				  i, dev_priv->dma_pages[i].used);
+		}
+#endif
+		if (n > SAVAGE_DMA_PAGE_SIZE)
+			dev_priv->dma_pages[i].used = SAVAGE_DMA_PAGE_SIZE;
+		else
+			dev_priv->dma_pages[i].used = n;
+		n -= SAVAGE_DMA_PAGE_SIZE;
+	}
+	dev_priv->current_dma_page = --i;
+
+	DRM_DEBUG("cur=%u, cur->used=%u, n=%u\n",
+		  i, dev_priv->dma_pages[i].used, n);
+
+	savage_dma_wait(dev_priv, dev_priv->current_dma_page);
+
+	return dma_ptr;
+}
+
+static void savage_dma_flush(drm_savage_private_t *dev_priv)
+{
+	unsigned int first = dev_priv->first_dma_page;
+	unsigned int cur = dev_priv->current_dma_page;
+	uint16_t event;
+	unsigned int wrap, pad, align, len, i;
+	unsigned long phys_addr;
+	BCI_LOCALS;
+
+	if (first == cur &&
+	    dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed)
+		return;
+
+	/* pad length to multiples of 2 entries
+	 * align start of next DMA block to multiles of 8 entries */
+	pad = -dev_priv->dma_pages[cur].used & 1;
+	align = -(dev_priv->dma_pages[cur].used + pad) & 7;
+
+	DRM_DEBUG("first=%u, cur=%u, first->flushed=%u, cur->used=%u, "
+		  "pad=%u, align=%u\n",
+		  first, cur, dev_priv->dma_pages[first].flushed,
+		  dev_priv->dma_pages[cur].used, pad, align);
+
+	/* pad with noops */
+	if (pad) {
+		uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +
+		    cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
+		dev_priv->dma_pages[cur].used += pad;
+		while(pad != 0) {
+			*dma_ptr++ = BCI_CMD_WAIT;
+			pad--;
+		}
+	}
+
+	DRM_MEMORYBARRIER();
+
+	/* do flush ... */
+	phys_addr = dev_priv->cmd_dma->offset +
+		(first * SAVAGE_DMA_PAGE_SIZE +
+		 dev_priv->dma_pages[first].flushed) * 4;
+	len = (cur - first) * SAVAGE_DMA_PAGE_SIZE +
+	    dev_priv->dma_pages[cur].used - dev_priv->dma_pages[first].flushed;
+
+	DRM_DEBUG("phys_addr=%lx, len=%u\n",
+		  phys_addr | dev_priv->dma_type, len);
+
+	BEGIN_BCI(3);
+	BCI_SET_REGISTERS(SAVAGE_DMABUFADDR, 1);
+	BCI_WRITE(phys_addr | dev_priv->dma_type);
+	BCI_DMA(len);
+
+	/* fix alignment of the start of the next block */
+	dev_priv->dma_pages[cur].used += align;
+
+	/* age DMA pages */
+	event = savage_bci_emit_event(dev_priv, 0);
+	wrap = dev_priv->event_wrap;
+	for (i = first; i < cur; ++i) {
+		SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
+		dev_priv->dma_pages[i].used = 0;
+		dev_priv->dma_pages[i].flushed = 0;
+	}
+	/* age the current page only when it's full */
+	if (dev_priv->dma_pages[cur].used == SAVAGE_DMA_PAGE_SIZE) {
+		SET_AGE(&dev_priv->dma_pages[cur].age, event, wrap);
+		dev_priv->dma_pages[cur].used = 0;
+		dev_priv->dma_pages[cur].flushed = 0;
+		/* advance to next page */
+		cur++;
+		if (cur == dev_priv->nr_dma_pages)
+			cur = 0;
+		dev_priv->first_dma_page = dev_priv->current_dma_page = cur;
+	} else {
+		dev_priv->first_dma_page = cur;
+		dev_priv->dma_pages[cur].flushed = dev_priv->dma_pages[i].used;
+	}
+	SET_AGE(&dev_priv->last_dma_age, event, wrap);
+
+	DRM_DEBUG("first=cur=%u, cur->used=%u, cur->flushed=%u\n", cur,
+		  dev_priv->dma_pages[cur].used,
+		  dev_priv->dma_pages[cur].flushed);
+}
+
+static void savage_fake_dma_flush(drm_savage_private_t *dev_priv)
+{
+	unsigned int i, j;
+	BCI_LOCALS;
+
+	if (dev_priv->first_dma_page == dev_priv->current_dma_page &&
+	    dev_priv->dma_pages[dev_priv->current_dma_page].used == 0)
+		return;
+
+	DRM_DEBUG("first=%u, cur=%u, cur->used=%u\n",
+		  dev_priv->first_dma_page, dev_priv->current_dma_page,
+		  dev_priv->dma_pages[dev_priv->current_dma_page].used);
+
+	for (i = dev_priv->first_dma_page;
+	     i <= dev_priv->current_dma_page && dev_priv->dma_pages[i].used;
+	     ++i) {
+		uint32_t *dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +
+			i * SAVAGE_DMA_PAGE_SIZE;
+#if SAVAGE_DMA_DEBUG
+		/* Sanity check: all pages except the last one must be full. */
+		if (i < dev_priv->current_dma_page &&
+		    dev_priv->dma_pages[i].used != SAVAGE_DMA_PAGE_SIZE) {
+			DRM_ERROR("partial DMA page %u: used=%u",
+				  i, dev_priv->dma_pages[i].used);
+		}
+#endif
+		BEGIN_BCI(dev_priv->dma_pages[i].used);
+		for (j = 0; j < dev_priv->dma_pages[i].used; ++j) {
+			BCI_WRITE(dma_ptr[j]);
+		}
+		dev_priv->dma_pages[i].used = 0;
+	}
+
+	/* reset to first page */
+	dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
+}
+
+int savage_driver_load(drm_device_t *dev, unsigned long chipset)
+{
+	drm_savage_private_t *dev_priv;
+
+	dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+	if (dev_priv == NULL)
+		return DRM_ERR(ENOMEM);
+
+	memset(dev_priv, 0, sizeof(drm_savage_private_t));
+	dev->dev_private = (void *)dev_priv;
+
+	dev_priv->chipset = (enum savage_family)chipset;
+
+	return 0;
+}
+
+/*
+ * Initalize mappings. On Savage4 and SavageIX the alignment
+ * and size of the aperture is not suitable for automatic MTRR setup
+ * in drm_addmap. Therefore we add them manually before the maps are
+ * initialized, and tear them down on last close.
+ */
+int savage_driver_firstopen(drm_device_t *dev)
+{
+	drm_savage_private_t *dev_priv = dev->dev_private;
+	unsigned long mmio_base, fb_base, fb_size, aperture_base;
+	/* fb_rsrc and aper_rsrc aren't really used currently, but still exist
+	 * in case we decide we need information on the BAR for BSD in the
+	 * future.
+	 */
+	unsigned int fb_rsrc, aper_rsrc;
+	int ret = 0;
+
+	dev_priv->mtrr[0].handle = -1;
+	dev_priv->mtrr[1].handle = -1;
+	dev_priv->mtrr[2].handle = -1;
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+		fb_rsrc = 0;
+		fb_base = drm_get_resource_start(dev, 0);
+		fb_size = SAVAGE_FB_SIZE_S3;
+		mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
+		aper_rsrc = 0;
+		aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+		/* this should always be true */
+		if (drm_get_resource_len(dev, 0) == 0x08000000) {
+			/* Don't make MMIO write-cobining! We need 3
+			 * MTRRs. */
+			dev_priv->mtrr[0].base = fb_base;
+			dev_priv->mtrr[0].size = 0x01000000;
+			dev_priv->mtrr[0].handle = 
+			    drm_mtrr_add(dev_priv->mtrr[0].base,
+					 dev_priv->mtrr[0].size, DRM_MTRR_WC);
+			dev_priv->mtrr[1].base = fb_base+0x02000000;
+			dev_priv->mtrr[1].size = 0x02000000;
+			dev_priv->mtrr[1].handle =
+			    drm_mtrr_add(dev_priv->mtrr[1].base,
+					 dev_priv->mtrr[1].size, DRM_MTRR_WC);
+			dev_priv->mtrr[2].base = fb_base+0x04000000;
+			dev_priv->mtrr[2].size = 0x04000000;
+			dev_priv->mtrr[2].handle =
+			    drm_mtrr_add(dev_priv->mtrr[2].base, 
+				         dev_priv->mtrr[2].size, DRM_MTRR_WC);
+		} else {
+			DRM_ERROR("strange pci_resource_len %08lx\n",
+				  drm_get_resource_len(dev, 0));
+		}
+	} else if (dev_priv->chipset != S3_SUPERSAVAGE &&
+		   dev_priv->chipset != S3_SAVAGE2000) {
+		mmio_base = drm_get_resource_start(dev, 0);
+		fb_rsrc = 1;
+		fb_base = drm_get_resource_start(dev, 1);
+		fb_size = SAVAGE_FB_SIZE_S4;
+		aper_rsrc = 1;
+		aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+		/* this should always be true */
+		if (drm_get_resource_len(dev, 1) == 0x08000000) {
+			/* Can use one MTRR to cover both fb and
+			 * aperture. */
+			dev_priv->mtrr[0].base = fb_base;
+			dev_priv->mtrr[0].size = 0x08000000;
+			dev_priv->mtrr[0].handle = 
+			    drm_mtrr_add(dev_priv->mtrr[0].base,
+					 dev_priv->mtrr[0].size, DRM_MTRR_WC);
+		} else {
+			DRM_ERROR("strange pci_resource_len %08lx\n",
+				  drm_get_resource_len(dev, 1));
+		}
+	} else {
+		mmio_base = drm_get_resource_start(dev, 0);
+		fb_rsrc = 1;
+		fb_base = drm_get_resource_start(dev, 1);
+		fb_size = drm_get_resource_len(dev, 1);
+		aper_rsrc = 2;
+		aperture_base = drm_get_resource_start(dev, 2);
+		/* Automatic MTRR setup will do the right thing. */
+	}
+
+	ret = drm_addmap(dev, mmio_base, SAVAGE_MMIO_SIZE, _DRM_REGISTERS,
+			 _DRM_READ_ONLY, &dev_priv->mmio);
+	if (ret)
+		return ret;
+
+	ret = drm_addmap(dev, fb_base, fb_size, _DRM_FRAME_BUFFER,
+			 _DRM_WRITE_COMBINING, &dev_priv->fb);
+	if (ret)
+		return ret;
+
+	ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,
+			 _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,
+			 &dev_priv->aperture);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+/*
+ * Delete MTRRs and free device-private data.
+ */
+void savage_driver_lastclose(drm_device_t *dev)
+{
+	drm_savage_private_t *dev_priv = dev->dev_private;
+	int i;
+
+	for (i = 0; i < 3; ++i)
+		if (dev_priv->mtrr[i].handle >= 0)
+			drm_mtrr_del(dev_priv->mtrr[i].handle,
+				     dev_priv->mtrr[i].base,
+				     dev_priv->mtrr[i].size, DRM_MTRR_WC);
+}
+
+int savage_driver_unload(drm_device_t *dev)
+{
+	drm_savage_private_t *dev_priv = dev->dev_private;
+
+	drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+
+	return 0;
+}
+
+static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
+{
+	drm_savage_private_t *dev_priv = dev->dev_private;
+
+	if (init->fb_bpp != 16 && init->fb_bpp != 32) {
+		DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp);
+		return DRM_ERR(EINVAL);
+	}
+	if (init->depth_bpp != 16 && init->depth_bpp != 32) {
+		DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp);
+		return DRM_ERR(EINVAL);
+	}
+	if (init->dma_type != SAVAGE_DMA_AGP &&
+	    init->dma_type != SAVAGE_DMA_PCI) {
+		DRM_ERROR("invalid dma memory type %d!\n", init->dma_type);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->cob_size = init->cob_size;
+	dev_priv->bci_threshold_lo = init->bci_threshold_lo;
+	dev_priv->bci_threshold_hi = init->bci_threshold_hi;
+	dev_priv->dma_type = init->dma_type;
+
+	dev_priv->fb_bpp = init->fb_bpp;
+	dev_priv->front_offset = init->front_offset;
+	dev_priv->front_pitch = init->front_pitch;
+	dev_priv->back_offset = init->back_offset;
+	dev_priv->back_pitch = init->back_pitch;
+	dev_priv->depth_bpp = init->depth_bpp;
+	dev_priv->depth_offset = init->depth_offset;
+	dev_priv->depth_pitch = init->depth_pitch;
+
+	dev_priv->texture_offset = init->texture_offset;
+	dev_priv->texture_size = init->texture_size;
+
+	DRM_GETSAREA();
+	if (!dev_priv->sarea) {
+		DRM_ERROR("could not find sarea!\n");
+		savage_do_cleanup_bci(dev);
+		return DRM_ERR(EINVAL);
+	}
+	if (init->status_offset != 0) {
+		dev_priv->status = drm_core_findmap(dev, init->status_offset);
+		if (!dev_priv->status) {
+			DRM_ERROR("could not find shadow status region!\n");
+			savage_do_cleanup_bci(dev);
+			return DRM_ERR(EINVAL);
+		}
+	} else {
+		dev_priv->status = NULL;
+	}
+	if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) {
+		dev->agp_buffer_token = init->buffers_offset;
+		dev->agp_buffer_map = drm_core_findmap(dev,
+						       init->buffers_offset);
+		if (!dev->agp_buffer_map) {
+			DRM_ERROR("could not find DMA buffer region!\n");
+			savage_do_cleanup_bci(dev);
+			return DRM_ERR(EINVAL);
+		}
+		drm_core_ioremap(dev->agp_buffer_map, dev);
+		if (!dev->agp_buffer_map) {
+			DRM_ERROR("failed to ioremap DMA buffer region!\n");
+			savage_do_cleanup_bci(dev);
+			return DRM_ERR(ENOMEM);
+		}
+	}
+	if (init->agp_textures_offset) {
+		dev_priv->agp_textures =
+			drm_core_findmap(dev, init->agp_textures_offset);
+		if (!dev_priv->agp_textures) {
+			DRM_ERROR("could not find agp texture region!\n");
+			savage_do_cleanup_bci(dev);
+			return DRM_ERR(EINVAL);
+		}
+	} else {
+		dev_priv->agp_textures = NULL;
+	}
+
+	if (init->cmd_dma_offset) {
+		if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+			DRM_ERROR("command DMA not supported on "
+				  "Savage3D/MX/IX.\n");
+			savage_do_cleanup_bci(dev);
+			return DRM_ERR(EINVAL);
+		}
+		if (dev->dma && dev->dma->buflist) {
+			DRM_ERROR("command and vertex DMA not supported "
+				  "at the same time.\n");
+			savage_do_cleanup_bci(dev);
+			return DRM_ERR(EINVAL);
+		}
+		dev_priv->cmd_dma = drm_core_findmap(dev, init->cmd_dma_offset);
+		if (!dev_priv->cmd_dma) {
+			DRM_ERROR("could not find command DMA region!\n");
+			savage_do_cleanup_bci(dev);
+			return DRM_ERR(EINVAL);
+		}
+		if (dev_priv->dma_type == SAVAGE_DMA_AGP) {
+			if (dev_priv->cmd_dma->type != _DRM_AGP) {
+				DRM_ERROR("AGP command DMA region is not a "
+					  "_DRM_AGP map!\n");
+				savage_do_cleanup_bci(dev);
+				return DRM_ERR(EINVAL);
+			}
+			drm_core_ioremap(dev_priv->cmd_dma, dev);
+			if (!dev_priv->cmd_dma->handle) {
+				DRM_ERROR("failed to ioremap command "
+					  "DMA region!\n");
+				savage_do_cleanup_bci(dev);
+				return DRM_ERR(ENOMEM);
+			}
+		} else if (dev_priv->cmd_dma->type != _DRM_CONSISTENT) {
+			DRM_ERROR("PCI command DMA region is not a "
+				  "_DRM_CONSISTENT map!\n");
+			savage_do_cleanup_bci(dev);
+			return DRM_ERR(EINVAL);
+		}
+	} else {
+		dev_priv->cmd_dma = NULL;
+	}
+
+	dev_priv->dma_flush = savage_dma_flush;
+	if (!dev_priv->cmd_dma) {
+		DRM_DEBUG("falling back to faked command DMA.\n");
+		dev_priv->fake_dma.offset = 0;
+		dev_priv->fake_dma.size = SAVAGE_FAKE_DMA_SIZE;
+		dev_priv->fake_dma.type = _DRM_SHM;
+		dev_priv->fake_dma.handle = drm_alloc(SAVAGE_FAKE_DMA_SIZE,
+						      DRM_MEM_DRIVER);
+		if (!dev_priv->fake_dma.handle) {
+			DRM_ERROR("could not allocate faked DMA buffer!\n");
+			savage_do_cleanup_bci(dev);
+			return DRM_ERR(ENOMEM);
+		}
+		dev_priv->cmd_dma = &dev_priv->fake_dma;
+		dev_priv->dma_flush = savage_fake_dma_flush;
+	}
+
+	dev_priv->sarea_priv =
+		(drm_savage_sarea_t *)((uint8_t *)dev_priv->sarea->handle +
+				       init->sarea_priv_offset);
+
+	/* setup bitmap descriptors */
+	{
+		unsigned int color_tile_format;
+		unsigned int depth_tile_format;
+		unsigned int front_stride, back_stride, depth_stride;
+		if (dev_priv->chipset <= S3_SAVAGE4) {
+			color_tile_format = dev_priv->fb_bpp == 16 ?
+				SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+			depth_tile_format = dev_priv->depth_bpp == 16 ?
+				SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+		} else {
+			color_tile_format = SAVAGE_BD_TILE_DEST;
+			depth_tile_format = SAVAGE_BD_TILE_DEST;
+		}
+		front_stride = dev_priv->front_pitch / (dev_priv->fb_bpp / 8);
+		back_stride  = dev_priv->back_pitch / (dev_priv->fb_bpp / 8);
+		depth_stride = 
+		    dev_priv->depth_pitch / (dev_priv->depth_bpp / 8);
+
+		dev_priv->front_bd = front_stride | SAVAGE_BD_BW_DISABLE |
+			(dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+			(color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+		dev_priv-> back_bd =  back_stride | SAVAGE_BD_BW_DISABLE |
+			(dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+			(color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+		dev_priv->depth_bd = depth_stride | SAVAGE_BD_BW_DISABLE |
+			(dev_priv->depth_bpp << SAVAGE_BD_BPP_SHIFT) |
+			(depth_tile_format << SAVAGE_BD_TILE_SHIFT);
+	}
+
+	/* setup status and bci ptr */
+	dev_priv->event_counter = 0;
+	dev_priv->event_wrap = 0;
+	dev_priv->bci_ptr = (volatile uint32_t *)
+	    ((uint8_t *)dev_priv->mmio->handle + SAVAGE_BCI_OFFSET);
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+		dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S3D;
+	} else {
+		dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S4;
+	}
+	if (dev_priv->status != NULL) {
+		dev_priv->status_ptr =
+			(volatile uint32_t *)dev_priv->status->handle;
+		dev_priv->wait_fifo = savage_bci_wait_fifo_shadow;
+		dev_priv->wait_evnt = savage_bci_wait_event_shadow;
+		dev_priv->status_ptr[1023] = dev_priv->event_counter;
+	} else {
+		dev_priv->status_ptr = NULL;
+		if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+			dev_priv->wait_fifo = savage_bci_wait_fifo_s3d;
+		} else {
+			dev_priv->wait_fifo = savage_bci_wait_fifo_s4;
+		}
+		dev_priv->wait_evnt = savage_bci_wait_event_reg;
+	}
+
+	/* cliprect functions */
+	if (S3_SAVAGE3D_SERIES(dev_priv->chipset))
+		dev_priv->emit_clip_rect = savage_emit_clip_rect_s3d;
+	else
+		dev_priv->emit_clip_rect = savage_emit_clip_rect_s4;
+
+	if (savage_freelist_init(dev) < 0) {
+		DRM_ERROR("could not initialize freelist\n");
+		savage_do_cleanup_bci(dev);
+		return DRM_ERR(ENOMEM);
+	}
+
+	if (savage_dma_init(dev_priv) <  0) {
+		DRM_ERROR("could not initialize command DMA\n");
+		savage_do_cleanup_bci(dev);
+		return DRM_ERR(ENOMEM);
+	}
+
+	return 0;
+}
+
+int savage_do_cleanup_bci(drm_device_t *dev)
+{
+	drm_savage_private_t *dev_priv = dev->dev_private;
+
+	if (dev_priv->cmd_dma == &dev_priv->fake_dma) {
+		if (dev_priv->fake_dma.handle)
+			drm_free(dev_priv->fake_dma.handle,
+				 SAVAGE_FAKE_DMA_SIZE, DRM_MEM_DRIVER);
+	} else if (dev_priv->cmd_dma && dev_priv->cmd_dma->handle &&
+		   dev_priv->cmd_dma->type == _DRM_AGP &&
+		   dev_priv->dma_type == SAVAGE_DMA_AGP)
+		drm_core_ioremapfree(dev_priv->cmd_dma, dev);
+
+	if (dev_priv->dma_type == SAVAGE_DMA_AGP &&
+	    dev->agp_buffer_map && dev->agp_buffer_map->handle) {
+		drm_core_ioremapfree(dev->agp_buffer_map, dev);
+		/* make sure the next instance (which may be running
+		 * in PCI mode) doesn't try to use an old
+		 * agp_buffer_map. */
+		dev->agp_buffer_map = NULL;
+	}
+
+	if (dev_priv->dma_pages)
+		drm_free(dev_priv->dma_pages,
+			 sizeof(drm_savage_dma_page_t)*dev_priv->nr_dma_pages,
+			 DRM_MEM_DRIVER);
+
+	return 0;
+}
+
+static int savage_bci_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_savage_init_t init;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(init, (drm_savage_init_t __user *)data,
+				 sizeof(init));
+
+	switch (init.func) {
+	case SAVAGE_INIT_BCI:
+		return savage_do_init_bci(dev, &init);
+	case SAVAGE_CLEANUP_BCI:
+		return savage_do_cleanup_bci(dev);
+	}
+
+	return DRM_ERR(EINVAL);
+}
+
+static int savage_bci_event_emit(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_savage_private_t *dev_priv = dev->dev_private;
+	drm_savage_event_emit_t event;
+
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_emit_t __user *)data,
+				 sizeof(event));
+
+	event.count = savage_bci_emit_event(dev_priv, event.flags);
+	event.count |= dev_priv->event_wrap << 16;
+	DRM_COPY_TO_USER_IOCTL((drm_savage_event_emit_t __user *)data,
+			       event, sizeof(event));
+	return 0;
+}
+
+static int savage_bci_event_wait(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_savage_private_t *dev_priv = dev->dev_private;
+	drm_savage_event_wait_t event;
+	unsigned int event_e, hw_e;
+	unsigned int event_w, hw_w;
+
+	DRM_DEBUG("\n");
+
+	DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_wait_t __user *)data,
+				 sizeof(event));
+
+	UPDATE_EVENT_COUNTER();
+	if (dev_priv->status_ptr)
+		hw_e = dev_priv->status_ptr[1] & 0xffff;
+	else
+		hw_e = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+	hw_w = dev_priv->event_wrap;
+	if (hw_e > dev_priv->event_counter)
+		hw_w--; /* hardware hasn't passed the last wrap yet */
+
+	event_e = event.count & 0xffff;
+	event_w = event.count >> 16;
+
+	/* Don't need to wait if
+	 * - event counter wrapped since the event was emitted or
+	 * - the hardware has advanced up to or over the event to wait for.
+	 */
+	if (event_w < hw_w || (event_w == hw_w && event_e <= hw_e) )
+		return 0;
+	else
+		return dev_priv->wait_evnt(dev_priv, event_e);
+}
+
+/*
+ * DMA buffer management
+ */
+
+static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d)
+{
+	drm_buf_t *buf;
+	int i;
+
+	for (i = d->granted_count; i < d->request_count; i++) {
+		buf = savage_freelist_get(dev);
+		if (!buf)
+			return DRM_ERR(EAGAIN);
+
+		buf->filp = filp;
+
+		if (DRM_COPY_TO_USER(&d->request_indices[i],
+				     &buf->idx, sizeof(buf->idx)))
+			return DRM_ERR(EFAULT);
+		if (DRM_COPY_TO_USER(&d->request_sizes[i],
+				     &buf->total, sizeof(buf->total)))
+			return DRM_ERR(EFAULT);
+
+		d->granted_count++;
+	}
+	return 0;
+}
+
+int savage_bci_buffers(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_device_dma_t *dma = dev->dma;
+	drm_dma_t d;
+	int ret = 0;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t __user *)data, sizeof(d));
+
+	/* Please don't send us buffers.
+	 */
+	if (d.send_count != 0) {
+		DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+			  DRM_CURRENTPID, d.send_count);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* We'll send you buffers.
+	 */
+	if (d.request_count < 0 || d.request_count > dma->buf_count) {
+		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+			  DRM_CURRENTPID, d.request_count, dma->buf_count);
+		return DRM_ERR(EINVAL);
+	}
+
+	d.granted_count = 0;
+
+	if (d.request_count) {
+		ret = savage_bci_get_buffers(filp, dev, &d);
+	}
+
+	DRM_COPY_TO_USER_IOCTL((drm_dma_t __user *)data, d, sizeof(d));
+
+	return ret;
+}
+
+void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp)
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_savage_private_t *dev_priv = dev->dev_private;
+	int i;
+
+	if (!dma)
+		return;
+	if (!dev_priv)
+		return;
+	if (!dma->buflist)
+		return;
+
+	/*i830_flush_queue(dev);*/
+
+	for (i = 0; i < dma->buf_count; i++) {
+		drm_buf_t *buf = dma->buflist[i];
+		drm_savage_buf_priv_t *buf_priv = buf->dev_private;
+
+		if (buf->filp == filp && buf_priv &&
+		    buf_priv->next == NULL && buf_priv->prev == NULL) {
+			uint16_t event;
+			DRM_DEBUG("reclaimed from client\n");
+			event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
+			SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
+			savage_freelist_put(dev, buf);
+		}
+	}
+
+	drm_core_reclaim_buffers(dev, filp);
+}
+
+drm_ioctl_desc_t savage_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, DRM_AUTH},
+};
+
+int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls);
+
--- libdrm-2.3.0.orig/shared-core/via_drv.h
+++ libdrm-2.3.0/shared-core/via_drv.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 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 _VIA_DRV_H_
+#define _VIA_DRV_H_
+
+#include "drm_sman.h"
+#define DRIVER_AUTHOR	"Various"
+
+#define DRIVER_NAME		"via"
+#define DRIVER_DESC		"VIA Unichrome / Pro"
+
+#include "via_verifier.h"
+
+#if defined(__linux__)
+#include "via_dmablit.h"
+
+/*
+ * This define and all its references can be removed when
+ * the DMA blit code has been implemented for FreeBSD.
+ */
+#define VIA_HAVE_DMABLIT 1
+#define VIA_HAVE_CORE_MM 1
+#endif
+
+#define VIA_PCI_BUF_SIZE 60000
+#define VIA_FIRE_BUF_SIZE  1024
+#define VIA_NUM_IRQS 4
+
+typedef struct drm_via_ring_buffer {
+	drm_local_map_t map;
+	char *virtual_start;
+} drm_via_ring_buffer_t;
+
+typedef uint32_t maskarray_t[5];
+
+typedef struct drm_via_irq {
+	atomic_t irq_received;
+	uint32_t pending_mask;
+	uint32_t enable_mask;
+	wait_queue_head_t irq_queue;
+} drm_via_irq_t;
+	
+typedef struct drm_via_private {
+	drm_via_sarea_t *sarea_priv;
+	drm_local_map_t *sarea;
+	drm_local_map_t *fb;
+	drm_local_map_t *mmio;
+	unsigned long agpAddr;
+	wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
+	char *dma_ptr;
+	unsigned int dma_low;
+	unsigned int dma_high;
+	unsigned int dma_offset;
+	uint32_t dma_wrap;
+	volatile uint32_t *last_pause_ptr;
+	volatile uint32_t *hw_addr_ptr;
+	drm_via_ring_buffer_t ring;
+	struct timeval last_vblank;
+	int last_vblank_valid;
+	unsigned usec_per_vblank;
+	drm_via_state_t hc_state;
+	char pci_buf[VIA_PCI_BUF_SIZE];
+	const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
+	uint32_t num_fire_offsets;
+	int pro_group_a;
+	drm_via_irq_t via_irqs[VIA_NUM_IRQS];
+	unsigned num_irqs;
+	maskarray_t *irq_masks;
+	uint32_t irq_enable_mask; 
+	uint32_t irq_pending_mask;	
+	int *irq_map;
+	/* Memory manager stuff */
+#ifdef VIA_HAVE_CORE_MM
+	unsigned int idle_fault;
+	drm_sman_t sman;
+	int vram_initialized;
+	int agp_initialized;
+	unsigned long vram_offset;
+	unsigned long agp_offset;
+#endif
+#ifdef VIA_HAVE_DMABLIT
+	drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
+#endif
+} drm_via_private_t;
+
+enum via_family {
+	VIA_OTHER = 0,
+	VIA_PRO_GROUP_A,
+};
+
+/* VIA MMIO register access */
+#define VIA_BASE ((dev_priv->mmio))
+
+#define VIA_READ(reg)		DRM_READ32(VIA_BASE, reg)
+#define VIA_WRITE(reg,val)	DRM_WRITE32(VIA_BASE, reg, val)
+#define VIA_READ8(reg)		DRM_READ8(VIA_BASE, reg)
+#define VIA_WRITE8(reg,val)	DRM_WRITE8(VIA_BASE, reg, val)
+
+extern drm_ioctl_desc_t via_ioctls[];
+extern int via_max_ioctl;
+
+extern int via_fb_init(DRM_IOCTL_ARGS);
+extern int via_mem_alloc(DRM_IOCTL_ARGS);
+extern int via_mem_free(DRM_IOCTL_ARGS);
+extern int via_agp_init(DRM_IOCTL_ARGS);
+extern int via_map_init(DRM_IOCTL_ARGS);
+extern int via_decoder_futex(DRM_IOCTL_ARGS);
+extern int via_wait_irq(DRM_IOCTL_ARGS);
+extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
+extern int via_dma_blit( DRM_IOCTL_ARGS );
+
+extern int via_driver_load(drm_device_t *dev, unsigned long chipset);
+extern int via_driver_unload(drm_device_t *dev);
+extern int via_final_context(drm_device_t * dev, int context);
+
+extern int via_do_cleanup_map(drm_device_t * dev);
+extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+
+extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
+extern void via_driver_irq_preinstall(drm_device_t * dev);
+extern void via_driver_irq_postinstall(drm_device_t * dev);
+extern void via_driver_irq_uninstall(drm_device_t * dev);
+
+extern int via_dma_cleanup(drm_device_t * dev);
+extern void via_init_command_verifier(void);
+extern int via_driver_dma_quiescent(drm_device_t * dev);
+extern void via_init_futex(drm_via_private_t *dev_priv);
+extern void via_cleanup_futex(drm_via_private_t *dev_priv);
+extern void via_release_futex(drm_via_private_t *dev_priv, int context);
+
+#ifdef VIA_HAVE_CORE_MM
+extern void via_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
+extern void via_lastclose(drm_device_t *dev);
+#else
+extern int via_init_context(drm_device_t * dev, int context);
+#endif
+
+#ifdef VIA_HAVE_DMABLIT
+extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
+extern void via_init_dmablit(drm_device_t *dev);
+#endif
+
+#endif
--- libdrm-2.3.0.orig/shared-core/savage_drv.h
+++ libdrm-2.3.0/shared-core/savage_drv.h
@@ -0,0 +1,575 @@
+/* savage_drv.h -- Private header for the savage driver */
+/*
+ * Copyright 2004  Felix Kuehling
+ * 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 FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 __SAVAGE_DRV_H__
+#define __SAVAGE_DRV_H__
+
+#define DRIVER_AUTHOR	"Felix Kuehling"
+
+#define DRIVER_NAME	"savage"
+#define DRIVER_DESC	"Savage3D/MX/IX, Savage4, SuperSavage, Twister, ProSavage[DDR]"
+#define DRIVER_DATE	"20050313"
+
+#define DRIVER_MAJOR		2
+#define DRIVER_MINOR		4
+#define DRIVER_PATCHLEVEL	1
+/* Interface history:
+ *
+ * 1.x   The DRM driver from the VIA/S3 code drop, basically a dummy
+ * 2.0   The first real DRM
+ * 2.1   Scissors registers managed by the DRM, 3D operations clipped by
+ *       cliprects of the cmdbuf ioctl
+ * 2.2   Implemented SAVAGE_CMD_DMA_IDX and SAVAGE_CMD_VB_IDX
+ * 2.3   Event counters used by BCI_EVENT_EMIT/WAIT ioctls are now 32 bits
+ *       wide and thus very long lived (unlikely to ever wrap). The size
+ *       in the struct was 32 bits before, but only 16 bits were used
+ * 2.4   Implemented command DMA. Now drm_savage_init_t.cmd_dma_offset is
+ *       actually used
+ */
+
+typedef struct drm_savage_age {
+	uint16_t event;
+	unsigned int wrap;
+} drm_savage_age_t;
+
+typedef struct drm_savage_buf_priv {
+	struct drm_savage_buf_priv *next;
+	struct drm_savage_buf_priv *prev;
+	drm_savage_age_t age;
+	drm_buf_t *buf;
+} drm_savage_buf_priv_t;
+
+typedef struct drm_savage_dma_page {
+	drm_savage_age_t age;
+	unsigned int used, flushed;
+} drm_savage_dma_page_t;
+#define SAVAGE_DMA_PAGE_SIZE 1024 /* in dwords */
+/* Fake DMA buffer size in bytes. 4 pages. Allows a maximum command
+ * size of 16kbytes or 4k entries. Minimum requirement would be
+ * 10kbytes for 255 40-byte vertices in one drawing command. */
+#define SAVAGE_FAKE_DMA_SIZE (SAVAGE_DMA_PAGE_SIZE*4*4)
+
+/* interesting bits of hardware state that are saved in dev_priv */
+typedef union {
+	struct drm_savage_common_state {
+		uint32_t vbaddr;
+	} common;
+	struct {
+		unsigned char pad[sizeof(struct drm_savage_common_state)];
+		uint32_t texctrl, texaddr;
+		uint32_t scstart, new_scstart;
+		uint32_t scend, new_scend;
+	} s3d;
+	struct {
+		unsigned char pad[sizeof(struct drm_savage_common_state)];
+		uint32_t texdescr, texaddr0, texaddr1;
+		uint32_t drawctrl0, new_drawctrl0;
+		uint32_t drawctrl1, new_drawctrl1;
+	} s4;
+} drm_savage_state_t;
+
+/* these chip tags should match the ones in the 2D driver in savage_regs.h. */
+enum savage_family {
+	S3_UNKNOWN = 0,
+	S3_SAVAGE3D,
+	S3_SAVAGE_MX,
+	S3_SAVAGE4,
+	S3_PROSAVAGE,
+	S3_TWISTER,
+	S3_PROSAVAGEDDR,
+	S3_SUPERSAVAGE,
+	S3_SAVAGE2000,
+	S3_LAST
+};
+
+extern drm_ioctl_desc_t savage_ioctls[];
+extern int savage_max_ioctl;
+
+#define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
+
+#define S3_SAVAGE4_SERIES(chip)  ((chip==S3_SAVAGE4)            \
+                                  || (chip==S3_PROSAVAGE)       \
+                                  || (chip==S3_TWISTER)         \
+                                  || (chip==S3_PROSAVAGEDDR))
+
+#define	S3_SAVAGE_MOBILE_SERIES(chip)	((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
+
+#define S3_SAVAGE_SERIES(chip)    ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
+
+#define S3_MOBILE_TWISTER_SERIES(chip)   ((chip==S3_TWISTER)    \
+                                          ||(chip==S3_PROSAVAGEDDR))
+
+/* flags */
+#define SAVAGE_IS_AGP 1
+
+typedef struct drm_savage_private {
+	drm_savage_sarea_t *sarea_priv;
+
+	drm_savage_buf_priv_t head, tail;
+
+	/* who am I? */
+	enum savage_family chipset;
+
+	unsigned int cob_size;
+	unsigned int bci_threshold_lo, bci_threshold_hi;
+	unsigned int dma_type;
+
+	/* frame buffer layout */
+	unsigned int fb_bpp;
+	unsigned int front_offset, front_pitch;
+	unsigned int back_offset, back_pitch;
+	unsigned int depth_bpp;
+	unsigned int depth_offset, depth_pitch;
+
+	/* bitmap descriptors for swap and clear */
+	unsigned int front_bd, back_bd, depth_bd;
+
+	/* local textures */
+	unsigned int texture_offset;
+	unsigned int texture_size;
+
+	/* memory regions in physical memory */
+	drm_local_map_t *sarea;
+	drm_local_map_t *mmio;
+	drm_local_map_t *fb;
+	drm_local_map_t *aperture;
+	drm_local_map_t *status;
+	drm_local_map_t *agp_textures;
+	drm_local_map_t *cmd_dma;
+	drm_local_map_t fake_dma;
+
+	struct {
+		int handle;
+		unsigned long base, size;
+	} mtrr[3];
+
+	/* BCI and status-related stuff */
+	volatile uint32_t *status_ptr, *bci_ptr;
+	uint32_t status_used_mask;
+	uint16_t event_counter;
+	unsigned int event_wrap;
+
+	/* Savage4 command DMA */
+	drm_savage_dma_page_t *dma_pages;
+	unsigned int nr_dma_pages, first_dma_page, current_dma_page;
+	drm_savage_age_t last_dma_age;
+
+	/* saved hw state for global/local check on S3D */
+	uint32_t hw_draw_ctrl, hw_zbuf_ctrl;
+	/* and for scissors (global, so don't emit if not changed) */
+	uint32_t hw_scissors_start, hw_scissors_end;
+
+	drm_savage_state_t state;
+
+	/* after emitting a wait cmd Savage3D needs 63 nops before next DMA */
+	unsigned int waiting;
+
+	/* config/hardware-dependent function pointers */
+	int (*wait_fifo)(struct drm_savage_private *dev_priv, unsigned int n);
+	int (*wait_evnt)(struct drm_savage_private *dev_priv, uint16_t e);
+	/* Err, there is a macro wait_event in include/linux/wait.h.
+	 * Avoid unwanted macro expansion. */
+	void (*emit_clip_rect)(struct drm_savage_private *dev_priv,
+			       const drm_clip_rect_t *pbox);
+	void (*dma_flush)(struct drm_savage_private *dev_priv);
+} drm_savage_private_t;
+
+/* ioctls */
+extern int savage_bci_cmdbuf(DRM_IOCTL_ARGS);
+extern int savage_bci_buffers(DRM_IOCTL_ARGS);
+
+/* BCI functions */
+extern uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
+				      unsigned int flags);
+extern void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf);
+extern void savage_dma_reset(drm_savage_private_t *dev_priv);
+extern void savage_dma_wait(drm_savage_private_t *dev_priv, unsigned int page);
+extern uint32_t *savage_dma_alloc(drm_savage_private_t *dev_priv,
+				  unsigned int n);
+extern int savage_driver_load(drm_device_t *dev, unsigned long chipset);
+extern int savage_driver_firstopen(drm_device_t *dev);
+extern void savage_driver_lastclose(drm_device_t *dev);
+extern int savage_driver_unload(drm_device_t *dev);
+extern int savage_do_cleanup_bci(drm_device_t *dev);
+extern void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp);
+
+/* state functions */
+extern void savage_emit_clip_rect_s3d(drm_savage_private_t *dev_priv,
+				      const drm_clip_rect_t *pbox);
+extern void savage_emit_clip_rect_s4(drm_savage_private_t *dev_priv,
+				     const drm_clip_rect_t *pbox);
+
+#define SAVAGE_FB_SIZE_S3	0x01000000	/*  16MB */
+#define SAVAGE_FB_SIZE_S4	0x02000000	/*  32MB */
+#define SAVAGE_MMIO_SIZE        0x00080000	/* 512kB */
+#define SAVAGE_APERTURE_OFFSET  0x02000000	/*  32MB */
+#define SAVAGE_APERTURE_SIZE    0x05000000	/* 5 tiled surfaces, 16MB each */
+
+#define SAVAGE_BCI_OFFSET       0x00010000      /* offset of the BCI region
+						 * inside the MMIO region */
+#define SAVAGE_BCI_FIFO_SIZE	32		/* number of entries in on-chip
+						 * BCI FIFO */
+
+/*
+ * MMIO registers
+ */
+#define SAVAGE_STATUS_WORD0		0x48C00
+#define SAVAGE_STATUS_WORD1		0x48C04
+#define SAVAGE_ALT_STATUS_WORD0 	0x48C60
+
+#define SAVAGE_FIFO_USED_MASK_S3D	0x0001ffff
+#define SAVAGE_FIFO_USED_MASK_S4	0x001fffff
+
+/* Copied from savage_bci.h in the 2D driver with some renaming. */
+
+/* Bitmap descriptors */
+#define SAVAGE_BD_STRIDE_SHIFT 0
+#define SAVAGE_BD_BPP_SHIFT   16
+#define SAVAGE_BD_TILE_SHIFT  24
+#define SAVAGE_BD_BW_DISABLE  (1<<28)
+/* common: */
+#define	SAVAGE_BD_TILE_LINEAR		0
+/* savage4, MX, IX, 3D */
+#define	SAVAGE_BD_TILE_16BPP		2
+#define	SAVAGE_BD_TILE_32BPP		3
+/* twister, prosavage, DDR, supersavage, 2000 */
+#define	SAVAGE_BD_TILE_DEST		1
+#define	SAVAGE_BD_TILE_TEXTURE		2
+/* GBD - BCI enable */
+/* savage4, MX, IX, 3D */
+#define SAVAGE_GBD_BCI_ENABLE                    8
+/* twister, prosavage, DDR, supersavage, 2000 */
+#define SAVAGE_GBD_BCI_ENABLE_TWISTER            0
+
+#define SAVAGE_GBD_BIG_ENDIAN                    4
+#define SAVAGE_GBD_LITTLE_ENDIAN                 0
+#define SAVAGE_GBD_64                            1
+
+/*  Global Bitmap Descriptor */
+#define SAVAGE_BCI_GLB_BD_LOW             0x8168
+#define SAVAGE_BCI_GLB_BD_HIGH            0x816C
+
+/*
+ * BCI registers
+ */
+/* Savage4/Twister/ProSavage 3D registers */
+#define SAVAGE_DRAWLOCALCTRL_S4		0x1e
+#define SAVAGE_TEXPALADDR_S4		0x1f
+#define SAVAGE_TEXCTRL0_S4		0x20
+#define SAVAGE_TEXCTRL1_S4		0x21
+#define SAVAGE_TEXADDR0_S4		0x22
+#define SAVAGE_TEXADDR1_S4		0x23
+#define SAVAGE_TEXBLEND0_S4		0x24
+#define SAVAGE_TEXBLEND1_S4		0x25
+#define SAVAGE_TEXXPRCLR_S4		0x26 /* never used */
+#define SAVAGE_TEXDESCR_S4		0x27
+#define SAVAGE_FOGTABLE_S4		0x28
+#define SAVAGE_FOGCTRL_S4		0x30
+#define SAVAGE_STENCILCTRL_S4		0x31
+#define SAVAGE_ZBUFCTRL_S4		0x32
+#define SAVAGE_ZBUFOFF_S4		0x33
+#define SAVAGE_DESTCTRL_S4		0x34
+#define SAVAGE_DRAWCTRL0_S4		0x35
+#define SAVAGE_DRAWCTRL1_S4		0x36
+#define SAVAGE_ZWATERMARK_S4		0x37
+#define SAVAGE_DESTTEXRWWATERMARK_S4	0x38
+#define SAVAGE_TEXBLENDCOLOR_S4		0x39
+/* Savage3D/MX/IX 3D registers */
+#define SAVAGE_TEXPALADDR_S3D		0x18
+#define SAVAGE_TEXXPRCLR_S3D		0x19 /* never used */
+#define SAVAGE_TEXADDR_S3D		0x1A
+#define SAVAGE_TEXDESCR_S3D		0x1B
+#define SAVAGE_TEXCTRL_S3D		0x1C
+#define SAVAGE_FOGTABLE_S3D		0x20
+#define SAVAGE_FOGCTRL_S3D		0x30
+#define SAVAGE_DRAWCTRL_S3D		0x31
+#define SAVAGE_ZBUFCTRL_S3D		0x32
+#define SAVAGE_ZBUFOFF_S3D		0x33
+#define SAVAGE_DESTCTRL_S3D		0x34
+#define SAVAGE_SCSTART_S3D		0x35
+#define SAVAGE_SCEND_S3D		0x36
+#define SAVAGE_ZWATERMARK_S3D		0x37 
+#define SAVAGE_DESTTEXRWWATERMARK_S3D	0x38
+/* common stuff */
+#define SAVAGE_VERTBUFADDR		0x3e
+#define SAVAGE_BITPLANEWTMASK		0xd7
+#define SAVAGE_DMABUFADDR		0x51
+
+/* texture enable bits (needed for tex addr checking) */
+#define SAVAGE_TEXCTRL_TEXEN_MASK	0x00010000 /* S3D */
+#define SAVAGE_TEXDESCR_TEX0EN_MASK	0x02000000 /* S4 */
+#define SAVAGE_TEXDESCR_TEX1EN_MASK	0x04000000 /* S4 */
+
+/* Global fields in Savage4/Twister/ProSavage 3D registers:
+ *
+ * All texture registers and DrawLocalCtrl are local. All other
+ * registers are global. */
+
+/* Global fields in Savage3D/MX/IX 3D registers:
+ *
+ * All texture registers are local. DrawCtrl and ZBufCtrl are
+ * partially local. All other registers are global.
+ *
+ * DrawCtrl global fields: cullMode, alphaTestCmpFunc, alphaTestEn, alphaRefVal
+ * ZBufCtrl global fields: zCmpFunc, zBufEn
+ */
+#define SAVAGE_DRAWCTRL_S3D_GLOBAL	0x03f3c00c
+#define SAVAGE_ZBUFCTRL_S3D_GLOBAL	0x00000027
+
+/* Masks for scissor bits (drawCtrl[01] on s4, scissorStart/End on s3d)
+ */
+#define SAVAGE_SCISSOR_MASK_S4		0x00fff7ff
+#define SAVAGE_SCISSOR_MASK_S3D		0x07ff07ff
+
+/*
+ * BCI commands
+ */
+#define BCI_CMD_NOP                  0x40000000
+#define BCI_CMD_RECT                 0x48000000
+#define BCI_CMD_RECT_XP              0x01000000
+#define BCI_CMD_RECT_YP              0x02000000
+#define BCI_CMD_SCANLINE             0x50000000
+#define BCI_CMD_LINE                 0x5C000000
+#define BCI_CMD_LINE_LAST_PIXEL      0x58000000
+#define BCI_CMD_BYTE_TEXT            0x63000000
+#define BCI_CMD_NT_BYTE_TEXT         0x67000000
+#define BCI_CMD_BIT_TEXT             0x6C000000
+#define BCI_CMD_GET_ROP(cmd)         (((cmd) >> 16) & 0xFF)
+#define BCI_CMD_SET_ROP(cmd, rop)    ((cmd) |= ((rop & 0xFF) << 16))
+#define BCI_CMD_SEND_COLOR           0x00008000
+
+#define BCI_CMD_CLIP_NONE            0x00000000
+#define BCI_CMD_CLIP_CURRENT         0x00002000
+#define BCI_CMD_CLIP_LR              0x00004000
+#define BCI_CMD_CLIP_NEW             0x00006000
+
+#define BCI_CMD_DEST_GBD             0x00000000
+#define BCI_CMD_DEST_PBD             0x00000800
+#define BCI_CMD_DEST_PBD_NEW         0x00000C00
+#define BCI_CMD_DEST_SBD             0x00001000
+#define BCI_CMD_DEST_SBD_NEW         0x00001400
+
+#define BCI_CMD_SRC_TRANSPARENT      0x00000200
+#define BCI_CMD_SRC_SOLID            0x00000000
+#define BCI_CMD_SRC_GBD              0x00000020
+#define BCI_CMD_SRC_COLOR            0x00000040
+#define BCI_CMD_SRC_MONO             0x00000060
+#define BCI_CMD_SRC_PBD_COLOR        0x00000080
+#define BCI_CMD_SRC_PBD_MONO         0x000000A0
+#define BCI_CMD_SRC_PBD_COLOR_NEW    0x000000C0
+#define BCI_CMD_SRC_PBD_MONO_NEW     0x000000E0
+#define BCI_CMD_SRC_SBD_COLOR        0x00000100
+#define BCI_CMD_SRC_SBD_MONO         0x00000120
+#define BCI_CMD_SRC_SBD_COLOR_NEW    0x00000140
+#define BCI_CMD_SRC_SBD_MONO_NEW     0x00000160
+
+#define BCI_CMD_PAT_TRANSPARENT      0x00000010
+#define BCI_CMD_PAT_NONE             0x00000000
+#define BCI_CMD_PAT_COLOR            0x00000002
+#define BCI_CMD_PAT_MONO             0x00000003
+#define BCI_CMD_PAT_PBD_COLOR        0x00000004
+#define BCI_CMD_PAT_PBD_MONO         0x00000005
+#define BCI_CMD_PAT_PBD_COLOR_NEW    0x00000006
+#define BCI_CMD_PAT_PBD_MONO_NEW     0x00000007
+#define BCI_CMD_PAT_SBD_COLOR        0x00000008
+#define BCI_CMD_PAT_SBD_MONO         0x00000009
+#define BCI_CMD_PAT_SBD_COLOR_NEW    0x0000000A
+#define BCI_CMD_PAT_SBD_MONO_NEW     0x0000000B
+
+#define BCI_BD_BW_DISABLE            0x10000000
+#define BCI_BD_TILE_MASK             0x03000000
+#define BCI_BD_TILE_NONE             0x00000000
+#define BCI_BD_TILE_16               0x02000000
+#define BCI_BD_TILE_32               0x03000000
+#define BCI_BD_GET_BPP(bd)           (((bd) >> 16) & 0xFF)
+#define BCI_BD_SET_BPP(bd, bpp)      ((bd) |= (((bpp) & 0xFF) << 16))
+#define BCI_BD_GET_STRIDE(bd)        ((bd) & 0xFFFF)
+#define BCI_BD_SET_STRIDE(bd, st)    ((bd) |= ((st) & 0xFFFF))
+
+#define BCI_CMD_SET_REGISTER            0x96000000
+
+#define BCI_CMD_WAIT                    0xC0000000
+#define BCI_CMD_WAIT_3D                 0x00010000
+#define BCI_CMD_WAIT_2D                 0x00020000
+
+#define BCI_CMD_UPDATE_EVENT_TAG        0x98000000
+
+#define BCI_CMD_DRAW_PRIM               0x80000000
+#define BCI_CMD_DRAW_INDEXED_PRIM       0x88000000
+#define BCI_CMD_DRAW_CONT               0x01000000
+#define BCI_CMD_DRAW_TRILIST            0x00000000
+#define BCI_CMD_DRAW_TRISTRIP           0x02000000
+#define BCI_CMD_DRAW_TRIFAN             0x04000000
+#define BCI_CMD_DRAW_SKIPFLAGS          0x000000ff
+#define BCI_CMD_DRAW_NO_Z		0x00000001
+#define BCI_CMD_DRAW_NO_W		0x00000002
+#define BCI_CMD_DRAW_NO_CD		0x00000004
+#define BCI_CMD_DRAW_NO_CS		0x00000008
+#define BCI_CMD_DRAW_NO_U0		0x00000010
+#define BCI_CMD_DRAW_NO_V0		0x00000020
+#define BCI_CMD_DRAW_NO_UV0		0x00000030
+#define BCI_CMD_DRAW_NO_U1		0x00000040
+#define BCI_CMD_DRAW_NO_V1		0x00000080
+#define BCI_CMD_DRAW_NO_UV1		0x000000c0
+
+#define BCI_CMD_DMA			0xa8000000
+
+#define BCI_W_H(w, h)                ((((h) << 16) | (w)) & 0x0FFF0FFF)
+#define BCI_X_Y(x, y)                ((((y) << 16) | (x)) & 0x0FFF0FFF)
+#define BCI_X_W(x, y)                ((((w) << 16) | (x)) & 0x0FFF0FFF)
+#define BCI_CLIP_LR(l, r)            ((((r) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_TL(t, l)            ((((t) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_BR(b, r)            ((((b) << 16) | (r)) & 0x0FFF0FFF)
+
+#define BCI_LINE_X_Y(x, y)           (((y) << 16) | ((x) & 0xFFFF))
+#define BCI_LINE_STEPS(diag, axi)    (((axi) << 16) | ((diag) & 0xFFFF))
+#define BCI_LINE_MISC(maj, ym, xp, yp, err) \
+	(((maj) & 0x1FFF) | \
+	((ym) ? 1<<13 : 0) | \
+	((xp) ? 1<<14 : 0) | \
+	((yp) ? 1<<15 : 0) | \
+	((err) << 16))
+
+/*
+ * common commands
+ */
+#define BCI_SET_REGISTERS( first, n )			\
+	BCI_WRITE(BCI_CMD_SET_REGISTER |		\
+		  ((uint32_t)(n) & 0xff) << 16 |	\
+		  ((uint32_t)(first) & 0xffff))
+#define DMA_SET_REGISTERS( first, n )			\
+	DMA_WRITE(BCI_CMD_SET_REGISTER |		\
+		  ((uint32_t)(n) & 0xff) << 16 |	\
+		  ((uint32_t)(first) & 0xffff))
+
+#define BCI_DRAW_PRIMITIVE(n, type, skip)         \
+        BCI_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
+		  ((n) << 16))
+#define DMA_DRAW_PRIMITIVE(n, type, skip)         \
+        DMA_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
+		  ((n) << 16))
+
+#define BCI_DRAW_INDICES_S3D(n, type, i0)         \
+        BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) |  \
+		  ((n) << 16) | (i0))
+
+#define BCI_DRAW_INDICES_S4(n, type, skip)        \
+        BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) |  \
+                  (skip) | ((n) << 16))
+
+#define BCI_DMA(n)	\
+	BCI_WRITE(BCI_CMD_DMA | (((n) >> 1) - 1))
+
+/*
+ * access to MMIO
+ */
+#define SAVAGE_READ(reg)	DRM_READ32(  dev_priv->mmio, (reg) )
+#define SAVAGE_WRITE(reg)	DRM_WRITE32( dev_priv->mmio, (reg) )
+
+/*
+ * access to the burst command interface (BCI)
+ */
+#define SAVAGE_BCI_DEBUG 1
+
+#define BCI_LOCALS    volatile uint32_t *bci_ptr;
+
+#define BEGIN_BCI( n ) do {			\
+	dev_priv->wait_fifo(dev_priv, (n));	\
+	bci_ptr = dev_priv->bci_ptr;		\
+} while(0)
+
+#define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val)
+
+/*
+ * command DMA support
+ */
+#define SAVAGE_DMA_DEBUG 1
+
+#define DMA_LOCALS   uint32_t *dma_ptr;
+
+#define BEGIN_DMA( n ) do {						\
+	unsigned int cur = dev_priv->current_dma_page;			\
+	unsigned int rest = SAVAGE_DMA_PAGE_SIZE -			\
+		dev_priv->dma_pages[cur].used;				\
+	if ((n) > rest) {						\
+		dma_ptr = savage_dma_alloc(dev_priv, (n));		\
+	} else { /* fast path for small allocations */			\
+		dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +	\
+			cur * SAVAGE_DMA_PAGE_SIZE +			\
+			dev_priv->dma_pages[cur].used;			\
+		if (dev_priv->dma_pages[cur].used == 0)			\
+			savage_dma_wait(dev_priv, cur);			\
+		dev_priv->dma_pages[cur].used += (n);			\
+	}								\
+} while(0)
+
+#define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val)
+
+#define DMA_COPY(src, n) do {					\
+	memcpy(dma_ptr, (src), (n)*4);				\
+	dma_ptr += n;						\
+} while(0)
+
+#if SAVAGE_DMA_DEBUG
+#define DMA_COMMIT() do {						\
+	unsigned int cur = dev_priv->current_dma_page;			\
+	uint32_t *expected = (uint32_t *)dev_priv->cmd_dma->handle +	\
+			cur * SAVAGE_DMA_PAGE_SIZE +			\
+			dev_priv->dma_pages[cur].used;			\
+	if (dma_ptr != expected) {					\
+		DRM_ERROR("DMA allocation and use don't match: "	\
+			  "%p != %p\n", expected, dma_ptr);		\
+		savage_dma_reset(dev_priv);				\
+	}								\
+} while(0)
+#else
+#define DMA_COMMIT() do {/* nothing */} while(0)
+#endif
+
+#define DMA_FLUSH() dev_priv->dma_flush(dev_priv)
+
+/* Buffer aging via event tag
+ */
+
+#define UPDATE_EVENT_COUNTER( ) do {			\
+	if (dev_priv->status_ptr) {			\
+		uint16_t count;				\
+		/* coordinate with Xserver */		\
+		count = dev_priv->status_ptr[1023];	\
+		if (count < dev_priv->event_counter)	\
+			dev_priv->event_wrap++;		\
+		dev_priv->event_counter = count;	\
+	}						\
+} while(0)
+
+#define SET_AGE( age, e, w ) do {	\
+	(age)->event = e;		\
+	(age)->wrap = w;		\
+} while(0)
+
+#define TEST_AGE( age, e, w )				\
+	( (age)->wrap < (w) || ( (age)->wrap == (w) && (age)->event <= (e) ) )
+
+#endif /* __SAVAGE_DRV_H__ */
--- libdrm-2.3.0.orig/shared-core/r128_irq.c
+++ libdrm-2.3.0/shared-core/r128_irq.c
@@ -0,0 +1,102 @@
+/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ */
+/*
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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
+ * 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+#include "r128_drv.h"
+
+irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+	int status;
+
+	status = R128_READ(R128_GEN_INT_STATUS);
+
+	/* VBLANK interrupt */
+	if (status & R128_CRTC_VBLANK_INT) {
+		R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+		atomic_inc(&dev->vbl_received);
+		DRM_WAKEUP(&dev->vbl_queue);
+		drm_vbl_send_signals(dev);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+{
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks...
+	 */
+	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+		    (((cur_vblank = atomic_read(&dev->vbl_received))
+		      - *sequence) <= (1 << 23)));
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+void r128_driver_irq_preinstall(drm_device_t * dev)
+{
+	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+
+	/* Disable *all* interrupts */
+	R128_WRITE(R128_GEN_INT_CNTL, 0);
+	/* Clear vblank bit if it's already high */
+	R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+}
+
+void r128_driver_irq_postinstall(drm_device_t * dev)
+{
+	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+
+	/* Turn on VBL interrupt */
+	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+}
+
+void r128_driver_irq_uninstall(drm_device_t * dev)
+{
+	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+	if (!dev_priv)
+		return;
+
+	/* Disable *all* interrupts */
+	R128_WRITE(R128_GEN_INT_CNTL, 0);
+}
--- libdrm-2.3.0.orig/shared-core/via_verifier.c
+++ libdrm-2.3.0/shared-core/via_verifier.c
@@ -0,0 +1,1101 @@
+/*
+ * Copyright 2004 The Unichrome Project. All Rights Reserved.
+ * Copyright 2005 Thomas Hellstrom. 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
+ * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Thomas Hellstrom 2004, 2005.
+ * This code was written using docs obtained under NDA from VIA Inc.
+ *
+ * Don't run this code directly on an AGP buffer. Due to cache problems it will
+ * be very slow.
+ */
+
+#include "via_3d_reg.h"
+#include "drmP.h"
+#include "drm.h"
+#include "via_drm.h"
+#include "via_verifier.h"
+#include "via_drv.h"
+
+typedef enum {
+	state_command,
+	state_header2,
+	state_header1,
+	state_vheader5,
+	state_vheader6,
+	state_error
+} verifier_state_t;
+
+typedef enum {
+	no_check = 0,
+	check_for_header2,
+	check_for_header1,
+	check_for_header2_err,
+	check_for_header1_err,
+	check_for_fire,
+	check_z_buffer_addr0,
+	check_z_buffer_addr1,
+	check_z_buffer_addr_mode,
+	check_destination_addr0,
+	check_destination_addr1,
+	check_destination_addr_mode,
+	check_for_dummy,
+	check_for_dd,
+	check_texture_addr0,
+	check_texture_addr1,
+	check_texture_addr2,
+	check_texture_addr3,
+	check_texture_addr4,
+	check_texture_addr5,
+	check_texture_addr6,
+	check_texture_addr7,
+	check_texture_addr8,
+	check_texture_addr_mode,
+	check_for_vertex_count,
+	check_number_texunits,
+	forbidden_command
+} hazard_t;
+
+/*
+ * Associates each hazard above with a possible multi-command
+ * sequence. For example an address that is split over multiple
+ * commands and that needs to be checked at the first command 
+ * that does not include any part of the address.
+ */
+
+static drm_via_sequence_t seqs[] = {
+	no_sequence,
+	no_sequence,
+	no_sequence,
+	no_sequence,
+	no_sequence,
+	no_sequence,
+	z_address,
+	z_address,
+	z_address,
+	dest_address,
+	dest_address,
+	dest_address,
+	no_sequence,
+	no_sequence,
+	tex_address,
+	tex_address,
+	tex_address,
+	tex_address,
+	tex_address,
+	tex_address,
+	tex_address,
+	tex_address,
+	tex_address,
+	tex_address,
+	no_sequence
+};
+
+typedef struct {
+	unsigned int code;
+	hazard_t hz;
+} hz_init_t;
+
+static hz_init_t init_table1[] = {
+	{0xf2, check_for_header2_err},
+	{0xf0, check_for_header1_err},
+	{0xee, check_for_fire},
+	{0xcc, check_for_dummy},
+	{0xdd, check_for_dd},
+	{0x00, no_check},
+	{0x10, check_z_buffer_addr0},
+	{0x11, check_z_buffer_addr1},
+	{0x12, check_z_buffer_addr_mode},
+	{0x13, no_check},
+	{0x14, no_check},
+	{0x15, no_check},
+	{0x23, no_check},
+	{0x24, no_check},
+	{0x33, no_check},
+	{0x34, no_check},
+	{0x35, no_check},
+	{0x36, no_check},
+	{0x37, no_check},
+	{0x38, no_check},
+	{0x39, no_check},
+	{0x3A, no_check},
+	{0x3B, no_check},
+	{0x3C, no_check},
+	{0x3D, no_check},
+	{0x3E, no_check},
+	{0x40, check_destination_addr0},
+	{0x41, check_destination_addr1},
+	{0x42, check_destination_addr_mode},
+	{0x43, no_check},
+	{0x44, no_check},
+	{0x50, no_check},
+	{0x51, no_check},
+	{0x52, no_check},
+	{0x53, no_check},
+	{0x54, no_check},
+	{0x55, no_check},
+	{0x56, no_check},
+	{0x57, no_check},
+	{0x58, no_check},
+	{0x70, no_check},
+	{0x71, no_check},
+	{0x78, no_check},
+	{0x79, no_check},
+	{0x7A, no_check},
+	{0x7B, no_check},
+	{0x7C, no_check},
+	{0x7D, check_for_vertex_count}
+};
+
+static hz_init_t init_table2[] = {
+	{0xf2, check_for_header2_err},
+	{0xf0, check_for_header1_err},
+	{0xee, check_for_fire},
+	{0xcc, check_for_dummy},
+	{0x00, check_texture_addr0},
+	{0x01, check_texture_addr0},
+	{0x02, check_texture_addr0},
+	{0x03, check_texture_addr0},
+	{0x04, check_texture_addr0},
+	{0x05, check_texture_addr0},
+	{0x06, check_texture_addr0},
+	{0x07, check_texture_addr0},
+	{0x08, check_texture_addr0},
+	{0x09, check_texture_addr0},
+	{0x20, check_texture_addr1},
+	{0x21, check_texture_addr1},
+	{0x22, check_texture_addr1},
+	{0x23, check_texture_addr4},
+	{0x2B, check_texture_addr3},
+	{0x2C, check_texture_addr3},
+	{0x2D, check_texture_addr3},
+	{0x2E, check_texture_addr3},
+	{0x2F, check_texture_addr3},
+	{0x30, check_texture_addr3},
+	{0x31, check_texture_addr3},
+	{0x32, check_texture_addr3},
+	{0x33, check_texture_addr3},
+	{0x34, check_texture_addr3},
+	{0x4B, check_texture_addr5},
+	{0x4C, check_texture_addr6},
+	{0x51, check_texture_addr7},
+	{0x52, check_texture_addr8},
+	{0x77, check_texture_addr2},
+	{0x78, no_check},
+	{0x79, no_check},
+	{0x7A, no_check},
+	{0x7B, check_texture_addr_mode},
+	{0x7C, no_check},
+	{0x7D, no_check},
+	{0x7E, no_check},
+	{0x7F, no_check},
+	{0x80, no_check},
+	{0x81, no_check},
+	{0x82, no_check},
+	{0x83, no_check},
+	{0x85, no_check},
+	{0x86, no_check},
+	{0x87, no_check},
+	{0x88, no_check},
+	{0x89, no_check},
+	{0x8A, no_check},
+	{0x90, no_check},
+	{0x91, no_check},
+	{0x92, no_check},
+	{0x93, no_check}
+};
+
+static hz_init_t init_table3[] = {
+	{0xf2, check_for_header2_err},
+	{0xf0, check_for_header1_err},
+	{0xcc, check_for_dummy},
+	{0x00, check_number_texunits}
+};
+
+static hazard_t table1[256];
+static hazard_t table2[256];
+static hazard_t table3[256];
+
+static __inline__ int
+eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
+{
+	if ((buf_end - *buf) >= num_words) {
+		*buf += num_words;
+		return 0;
+	}
+	DRM_ERROR("Illegal termination of DMA command buffer\n");
+	return 1;
+}
+
+/*
+ * Partially stolen from drm_memory.h
+ */
+
+static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t * seq,
+							  unsigned long offset,
+							  unsigned long size,
+							  drm_device_t * dev)
+{
+#ifdef __linux__
+	struct list_head *list;
+	drm_map_list_t *r_list;
+#endif
+	drm_local_map_t *map = seq->map_cache;
+
+	if (map && map->offset <= offset
+	    && (offset + size) <= (map->offset + map->size)) {
+		return map;
+	}
+#ifdef __linux__
+	list_for_each(list, &dev->maplist->head) {
+		r_list = (drm_map_list_t *) list;
+		map = r_list->map;
+		if (!map)
+			continue;
+#else
+	TAILQ_FOREACH(map, &dev->maplist, link) {
+#endif
+		if (map->offset <= offset
+		    && (offset + size) <= (map->offset + map->size)
+		    && !(map->flags & _DRM_RESTRICTED)
+		    && (map->type == _DRM_AGP)) {
+			seq->map_cache = map;
+			return map;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Require that all AGP texture levels reside in the same AGP map which should 
+ * be mappable by the client. This is not a big restriction.
+ * FIXME: To actually enforce this security policy strictly, drm_rmmap 
+ * would have to wait for dma quiescent before removing an AGP map. 
+ * The via_drm_lookup_agp_map call in reality seems to take
+ * very little CPU time.
+ */
+
+static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
+{
+	switch (cur_seq->unfinished) {
+	case z_address:
+		DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
+		break;
+	case dest_address:
+		DRM_DEBUG("Destination start address is 0x%x\n",
+			  cur_seq->d_addr);
+		break;
+	case tex_address:
+		if (cur_seq->agp_texture) {
+			unsigned start =
+			    cur_seq->tex_level_lo[cur_seq->texture];
+			unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
+			unsigned long lo = ~0, hi = 0, tmp;
+			uint32_t *addr, *pitch, *height, tex;
+			unsigned i;
+
+			if (end > 9)
+				end = 9;
+			if (start > 9)
+				start = 9;
+
+			addr =
+			    &(cur_seq->t_addr[tex = cur_seq->texture][start]);
+			pitch = &(cur_seq->pitch[tex][start]);
+			height = &(cur_seq->height[tex][start]);
+
+			for (i = start; i <= end; ++i) {
+				tmp = *addr++;
+				if (tmp < lo)
+					lo = tmp;
+				tmp += (*height++ << *pitch++);
+				if (tmp > hi)
+					hi = tmp;
+			}
+
+			if (!via_drm_lookup_agp_map
+			    (cur_seq, lo, hi - lo, cur_seq->dev)) {
+				DRM_ERROR
+				    ("AGP texture is not in allowed map\n");
+				return 2;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	cur_seq->unfinished = no_sequence;
+	return 0;
+}
+
+static __inline__ int
+investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq)
+{
+	register uint32_t tmp, *tmp_addr;
+
+	if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
+		int ret;
+		if ((ret = finish_current_sequence(cur_seq)))
+			return ret;
+	}
+
+	switch (hz) {
+	case check_for_header2:
+		if (cmd == HALCYON_HEADER2)
+			return 1;
+		return 0;
+	case check_for_header1:
+		if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+			return 1;
+		return 0;
+	case check_for_header2_err:
+		if (cmd == HALCYON_HEADER2)
+			return 1;
+		DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
+		break;
+	case check_for_header1_err:
+		if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+			return 1;
+		DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
+		break;
+	case check_for_fire:
+		if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
+			return 1;
+		DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
+		break;
+	case check_for_dummy:
+		if (HC_DUMMY == cmd)
+			return 0;
+		DRM_ERROR("Illegal DMA HC_DUMMY command\n");
+		break;
+	case check_for_dd:
+		if (0xdddddddd == cmd)
+			return 0;
+		DRM_ERROR("Illegal DMA 0xdddddddd command\n");
+		break;
+	case check_z_buffer_addr0:
+		cur_seq->unfinished = z_address;
+		cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
+		    (cmd & 0x00FFFFFF);
+		return 0;
+	case check_z_buffer_addr1:
+		cur_seq->unfinished = z_address;
+		cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
+		    ((cmd & 0xFF) << 24);
+		return 0;
+	case check_z_buffer_addr_mode:
+		cur_seq->unfinished = z_address;
+		if ((cmd & 0x0000C000) == 0)
+			return 0;
+		DRM_ERROR("Attempt to place Z buffer in system memory\n");
+		return 2;
+	case check_destination_addr0:
+		cur_seq->unfinished = dest_address;
+		cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
+		    (cmd & 0x00FFFFFF);
+		return 0;
+	case check_destination_addr1:
+		cur_seq->unfinished = dest_address;
+		cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
+		    ((cmd & 0xFF) << 24);
+		return 0;
+	case check_destination_addr_mode:
+		cur_seq->unfinished = dest_address;
+		if ((cmd & 0x0000C000) == 0)
+			return 0;
+		DRM_ERROR
+		    ("Attempt to place 3D drawing buffer in system memory\n");
+		return 2;
+	case check_texture_addr0:
+		cur_seq->unfinished = tex_address;
+		tmp = (cmd >> 24);
+		tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
+		*tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
+		return 0;
+	case check_texture_addr1:
+		cur_seq->unfinished = tex_address;
+		tmp = ((cmd >> 24) - 0x20);
+		tmp += tmp << 1;
+		tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
+		*tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
+		tmp_addr++;
+		*tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
+		tmp_addr++;
+		*tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
+		return 0;
+	case check_texture_addr2:
+		cur_seq->unfinished = tex_address;
+		cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
+		cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
+		return 0;
+	case check_texture_addr3:
+		cur_seq->unfinished = tex_address;
+		tmp = ((cmd >> 24) - 0x2B);
+		cur_seq->pitch[cur_seq->texture][tmp] =
+		    (cmd & 0x00F00000) >> 20;
+		if (!tmp && (cmd & 0x000FFFFF)) {
+			DRM_ERROR
+			    ("Unimplemented texture level 0 pitch mode.\n");
+			return 2;
+		}
+		return 0;
+	case check_texture_addr4:
+		cur_seq->unfinished = tex_address;
+		tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
+		*tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
+		return 0;
+	case check_texture_addr5:
+	case check_texture_addr6:
+		cur_seq->unfinished = tex_address;
+		/*
+		 * Texture width. We don't care since we have the pitch.
+		 */
+		return 0;
+	case check_texture_addr7:
+		cur_seq->unfinished = tex_address;
+		tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
+		tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
+		tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
+		tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
+		tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
+		tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
+		tmp_addr[0] = 1 << (cmd & 0x0000000F);
+		return 0;
+	case check_texture_addr8:
+		cur_seq->unfinished = tex_address;
+		tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
+		tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
+		tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
+		tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
+		tmp_addr[6] = 1 << (cmd & 0x0000000F);
+		return 0;
+	case check_texture_addr_mode:
+		cur_seq->unfinished = tex_address;
+		if (2 == (tmp = cmd & 0x00000003)) {
+			DRM_ERROR
+			    ("Attempt to fetch texture from system memory.\n");
+			return 2;
+		}
+		cur_seq->agp_texture = (tmp == 3);
+		cur_seq->tex_palette_size[cur_seq->texture] =
+		    (cmd >> 16) & 0x000000007;
+		return 0;
+	case check_for_vertex_count:
+		cur_seq->vertex_count = cmd & 0x0000FFFF;
+		return 0;
+	case check_number_texunits:
+		cur_seq->multitex = (cmd >> 3) & 1;
+		return 0;
+	default:
+		DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
+		return 2;
+	}
+	return 2;
+}
+
+static __inline__ int
+via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
+		    drm_via_state_t * cur_seq)
+{
+	drm_via_private_t *dev_priv =
+	    (drm_via_private_t *) cur_seq->dev->dev_private;
+	uint32_t a_fire, bcmd, dw_count;
+	int ret = 0;
+	int have_fire;
+	const uint32_t *buf = *buffer;
+
+	while (buf < buf_end) {
+		have_fire = 0;
+		if ((buf_end - buf) < 2) {
+			DRM_ERROR
+			    ("Unexpected termination of primitive list.\n");
+			ret = 1;
+			break;
+		}
+		if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
+			break;
+		bcmd = *buf++;
+		if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
+			DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
+				  *buf);
+			ret = 1;
+			break;
+		}
+		a_fire =
+		    *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
+		    HC_HE3Fire_MASK;
+
+		/*
+		 * How many dwords per vertex ?
+		 */
+
+		if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
+			DRM_ERROR("Illegal B command vertex data for AGP.\n");
+			ret = 1;
+			break;
+		}
+
+		dw_count = 0;
+		if (bcmd & (1 << 7))
+			dw_count += (cur_seq->multitex) ? 2 : 1;
+		if (bcmd & (1 << 8))
+			dw_count += (cur_seq->multitex) ? 2 : 1;
+		if (bcmd & (1 << 9))
+			dw_count++;
+		if (bcmd & (1 << 10))
+			dw_count++;
+		if (bcmd & (1 << 11))
+			dw_count++;
+		if (bcmd & (1 << 12))
+			dw_count++;
+		if (bcmd & (1 << 13))
+			dw_count++;
+		if (bcmd & (1 << 14))
+			dw_count++;
+
+		while (buf < buf_end) {
+			if (*buf == a_fire) {
+				if (dev_priv->num_fire_offsets >=
+				    VIA_FIRE_BUF_SIZE) {
+					DRM_ERROR("Fire offset buffer full.\n");
+					ret = 1;
+					break;
+				}
+				dev_priv->fire_offsets[dev_priv->
+						       num_fire_offsets++] =
+				    buf;
+				have_fire = 1;
+				buf++;
+				if (buf < buf_end && *buf == a_fire)
+					buf++;
+				break;
+			}
+			if ((*buf == HALCYON_HEADER2) ||
+			    ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
+				DRM_ERROR("Missing Vertex Fire command, "
+					  "Stray Vertex Fire command  or verifier "
+					  "lost sync.\n");
+				ret = 1;
+				break;
+			}
+			if ((ret = eat_words(&buf, buf_end, dw_count)))
+				break;
+		}
+		if (buf >= buf_end && !have_fire) {
+			DRM_ERROR("Missing Vertex Fire command or verifier "
+				  "lost sync.\n");
+			ret = 1;
+			break;
+		}
+		if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
+			DRM_ERROR("AGP Primitive list end misaligned.\n");
+			ret = 1;
+			break;
+		}
+	}
+	*buffer = buf;
+	return ret;
+}
+
+static __inline__ verifier_state_t
+via_check_header2(uint32_t const **buffer, const uint32_t * buf_end,
+		  drm_via_state_t * hc_state)
+{
+	uint32_t cmd;
+	int hz_mode;
+	hazard_t hz;
+	const uint32_t *buf = *buffer;
+	const hazard_t *hz_table;
+
+	if ((buf_end - buf) < 2) {
+		DRM_ERROR
+		    ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
+		return state_error;
+	}
+	buf++;
+	cmd = (*buf++ & 0xFFFF0000) >> 16;
+
+	switch (cmd) {
+	case HC_ParaType_CmdVdata:
+		if (via_check_prim_list(&buf, buf_end, hc_state))
+			return state_error;
+		*buffer = buf;
+		return state_command;
+	case HC_ParaType_NotTex:
+		hz_table = table1;
+		break;
+	case HC_ParaType_Tex:
+		hc_state->texture = 0;
+		hz_table = table2;
+		break;
+	case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
+		hc_state->texture = 1;
+		hz_table = table2;
+		break;
+	case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
+		hz_table = table3;
+		break;
+	case HC_ParaType_Auto:
+		if (eat_words(&buf, buf_end, 2))
+			return state_error;
+		*buffer = buf;
+		return state_command;
+	case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
+		if (eat_words(&buf, buf_end, 32))
+			return state_error;
+		*buffer = buf;
+		return state_command;
+	case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
+	case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
+		DRM_ERROR("Texture palettes are rejected because of "
+			  "lack of info how to determine their size.\n");
+		return state_error;
+	case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
+		DRM_ERROR("Fog factor palettes are rejected because of "
+			  "lack of info how to determine their size.\n");
+		return state_error;
+	default:
+
+		/*
+		 * There are some unimplemented HC_ParaTypes here, that
+		 * need to be implemented if the Mesa driver is extended.
+		 */
+
+		DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
+			  "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
+			  cmd, *(buf - 2));
+		*buffer = buf;
+		return state_error;
+	}
+
+	while (buf < buf_end) {
+		cmd = *buf++;
+		if ((hz = hz_table[cmd >> 24])) {
+			if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
+				if (hz_mode == 1) {
+					buf--;
+					break;
+				}
+				return state_error;
+			}
+		} else if (hc_state->unfinished &&
+			   finish_current_sequence(hc_state)) {
+			return state_error;
+		}
+	}
+	if (hc_state->unfinished && finish_current_sequence(hc_state)) {
+		return state_error;
+	}
+	*buffer = buf;
+	return state_command;
+}
+
+static __inline__ verifier_state_t
+via_parse_header2(drm_via_private_t * dev_priv, uint32_t const **buffer,
+		  const uint32_t * buf_end, int *fire_count)
+{
+	uint32_t cmd;
+	const uint32_t *buf = *buffer;
+	const uint32_t *next_fire;
+	int burst = 0;
+
+	next_fire = dev_priv->fire_offsets[*fire_count];
+	buf++;
+	cmd = (*buf & 0xFFFF0000) >> 16;
+	VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
+	switch (cmd) {
+	case HC_ParaType_CmdVdata:
+		while ((buf < buf_end) &&
+		       (*fire_count < dev_priv->num_fire_offsets) &&
+		       (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
+			while (buf <= next_fire) {
+				VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+					  (burst & 63), *buf++);
+				burst += 4;
+			}
+			if ((buf < buf_end)
+			    && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
+				buf++;
+
+			if (++(*fire_count) < dev_priv->num_fire_offsets)
+				next_fire = dev_priv->fire_offsets[*fire_count];
+		}
+		break;
+	default:
+		while (buf < buf_end) {
+
+			if (*buf == HC_HEADER2 ||
+			    (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
+			    (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
+			    (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+				break;
+
+			VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+				  (burst & 63), *buf++);
+			burst += 4;
+		}
+	}
+	*buffer = buf;
+	return state_command;
+}
+
+static __inline__ int verify_mmio_address(uint32_t address)
+{
+	if ((address > 0x3FF) && (address < 0xC00)) {
+		DRM_ERROR("Invalid VIDEO DMA command. "
+			  "Attempt to access 3D- or command burst area.\n");
+		return 1;
+	} else if ((address > 0xCFF) && (address < 0x1300)) {
+		DRM_ERROR("Invalid VIDEO DMA command. "
+			  "Attempt to access PCI DMA area.\n");
+		return 1;
+	} else if (address > 0x13FF) {
+		DRM_ERROR("Invalid VIDEO DMA command. "
+			  "Attempt to access VGA registers.\n");
+		return 1;
+	}
+	return 0;
+}
+
+static __inline__ int
+verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
+		  uint32_t dwords)
+{
+	const uint32_t *buf = *buffer;
+
+	if (buf_end - buf < dwords) {
+		DRM_ERROR("Illegal termination of video command.\n");
+		return 1;
+	}
+	while (dwords--) {
+		if (*buf++) {
+			DRM_ERROR("Illegal video command tail.\n");
+			return 1;
+		}
+	}
+	*buffer = buf;
+	return 0;
+}
+
+static __inline__ verifier_state_t
+via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
+{
+	uint32_t cmd;
+	const uint32_t *buf = *buffer;
+	verifier_state_t ret = state_command;
+
+	while (buf < buf_end) {
+		cmd = *buf;
+		if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
+		    (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
+			if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+				break;
+			DRM_ERROR("Invalid HALCYON_HEADER1 command. "
+				  "Attempt to access 3D- or command burst area.\n");
+			ret = state_error;
+			break;
+		} else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
+			if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+				break;
+			DRM_ERROR("Invalid HALCYON_HEADER1 command. "
+				  "Attempt to access VGA registers.\n");
+			ret = state_error;
+			break;
+		} else {
+			buf += 2;
+		}
+	}
+	*buffer = buf;
+	return ret;
+}
+
+static __inline__ verifier_state_t
+via_parse_header1(drm_via_private_t * dev_priv, uint32_t const **buffer,
+		  const uint32_t * buf_end)
+{
+	register uint32_t cmd;
+	const uint32_t *buf = *buffer;
+
+	while (buf < buf_end) {
+		cmd = *buf;
+		if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+			break;
+		VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
+		buf++;
+	}
+	*buffer = buf;
+	return state_command;
+}
+
+static __inline__ verifier_state_t
+via_check_vheader5(uint32_t const **buffer, const uint32_t * buf_end)
+{
+	uint32_t data;
+	const uint32_t *buf = *buffer;
+
+	if (buf_end - buf < 4) {
+		DRM_ERROR("Illegal termination of video header5 command\n");
+		return state_error;
+	}
+
+	data = *buf++ & ~VIA_VIDEOMASK;
+	if (verify_mmio_address(data))
+		return state_error;
+
+	data = *buf++;
+	if (*buf++ != 0x00F50000) {
+		DRM_ERROR("Illegal header5 header data\n");
+		return state_error;
+	}
+	if (*buf++ != 0x00000000) {
+		DRM_ERROR("Illegal header5 header data\n");
+		return state_error;
+	}
+	if (eat_words(&buf, buf_end, data))
+		return state_error;
+	if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
+		return state_error;
+	*buffer = buf;
+	return state_command;
+
+}
+
+static __inline__ verifier_state_t
+via_parse_vheader5(drm_via_private_t * dev_priv, uint32_t const **buffer,
+		   const uint32_t * buf_end)
+{
+	uint32_t addr, count, i;
+	const uint32_t *buf = *buffer;
+
+	addr = *buf++ & ~VIA_VIDEOMASK;
+	i = count = *buf;
+	buf += 3;
+	while (i--) {
+		VIA_WRITE(addr, *buf++);
+	}
+	if (count & 3)
+		buf += 4 - (count & 3);
+	*buffer = buf;
+	return state_command;
+}
+
+static __inline__ verifier_state_t
+via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
+{
+	uint32_t data;
+	const uint32_t *buf = *buffer;
+	uint32_t i;
+
+	if (buf_end - buf < 4) {
+		DRM_ERROR("Illegal termination of video header6 command\n");
+		return state_error;
+	}
+	buf++;
+	data = *buf++;
+	if (*buf++ != 0x00F60000) {
+		DRM_ERROR("Illegal header6 header data\n");
+		return state_error;
+	}
+	if (*buf++ != 0x00000000) {
+		DRM_ERROR("Illegal header6 header data\n");
+		return state_error;
+	}
+	if ((buf_end - buf) < (data << 1)) {
+		DRM_ERROR("Illegal termination of video header6 command\n");
+		return state_error;
+	}
+	for (i = 0; i < data; ++i) {
+		if (verify_mmio_address(*buf++))
+			return state_error;
+		buf++;
+	}
+	data <<= 1;
+	if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
+		return state_error;
+	*buffer = buf;
+	return state_command;
+}
+
+static __inline__ verifier_state_t
+via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
+		   const uint32_t * buf_end)
+{
+
+	uint32_t addr, count, i;
+	const uint32_t *buf = *buffer;
+
+	i = count = *++buf;
+	buf += 3;
+	while (i--) {
+		addr = *buf++;
+		VIA_WRITE(addr, *buf++);
+	}
+	count <<= 1;
+	if (count & 3)
+		buf += 4 - (count & 3);
+	*buffer = buf;
+	return state_command;
+}
+
+int
+via_verify_command_stream(const uint32_t * buf, unsigned int size,
+			  drm_device_t * dev, int agp)
+{
+
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	drm_via_state_t *hc_state = &dev_priv->hc_state;
+	drm_via_state_t saved_state = *hc_state;
+	uint32_t cmd;
+	const uint32_t *buf_end = buf + (size >> 2);
+	verifier_state_t state = state_command;
+	int pro_group_a = dev_priv->pro_group_a;
+
+	hc_state->dev = dev;
+	hc_state->unfinished = no_sequence;
+	hc_state->map_cache = NULL;
+	hc_state->agp = agp;
+	hc_state->buf_start = buf;
+	dev_priv->num_fire_offsets = 0;
+
+	while (buf < buf_end) {
+
+		switch (state) {
+		case state_header2:
+			state = via_check_header2(&buf, buf_end, hc_state);
+			break;
+		case state_header1:
+			state = via_check_header1(&buf, buf_end);
+			break;
+		case state_vheader5:
+			state = via_check_vheader5(&buf, buf_end);
+			break;
+		case state_vheader6:
+			state = via_check_vheader6(&buf, buf_end);
+			break;
+		case state_command:
+			if (HALCYON_HEADER2 == (cmd = *buf))
+				state = state_header2;
+			else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+				state = state_header1;
+			else if (pro_group_a
+				 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+				state = state_vheader5;
+			else if (pro_group_a
+				 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+				state = state_vheader6;
+			else {
+				DRM_ERROR
+				    ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+				     cmd);
+				state = state_error;
+			}
+			break;
+		case state_error:
+		default:
+			*hc_state = saved_state;
+			return DRM_ERR(EINVAL);
+		}
+	}
+	if (state == state_error) {
+		*hc_state = saved_state;
+		return DRM_ERR(EINVAL);
+	}
+	return 0;
+}
+
+int
+via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
+			 unsigned int size)
+{
+
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	uint32_t cmd;
+	const uint32_t *buf_end = buf + (size >> 2);
+	verifier_state_t state = state_command;
+	int fire_count = 0;
+
+	while (buf < buf_end) {
+
+		switch (state) {
+		case state_header2:
+			state =
+			    via_parse_header2(dev_priv, &buf, buf_end,
+					      &fire_count);
+			break;
+		case state_header1:
+			state = via_parse_header1(dev_priv, &buf, buf_end);
+			break;
+		case state_vheader5:
+			state = via_parse_vheader5(dev_priv, &buf, buf_end);
+			break;
+		case state_vheader6:
+			state = via_parse_vheader6(dev_priv, &buf, buf_end);
+			break;
+		case state_command:
+			if (HALCYON_HEADER2 == (cmd = *buf))
+				state = state_header2;
+			else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+				state = state_header1;
+			else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+				state = state_vheader5;
+			else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+				state = state_vheader6;
+			else {
+				DRM_ERROR
+				    ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+				     cmd);
+				state = state_error;
+			}
+			break;
+		case state_error:
+		default:
+			return DRM_ERR(EINVAL);
+		}
+	}
+	if (state == state_error) {
+		return DRM_ERR(EINVAL);
+	}
+	return 0;
+}
+
+static void
+setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
+{
+	int i;
+
+	for (i = 0; i < 256; ++i) {
+		table[i] = forbidden_command;
+	}
+
+	for (i = 0; i < size; ++i) {
+		table[init_table[i].code] = init_table[i].hz;
+	}
+}
+
+void via_init_command_verifier(void)
+{
+	setup_hazard_table(init_table1, table1,
+			   sizeof(init_table1) / sizeof(hz_init_t));
+	setup_hazard_table(init_table2, table2,
+			   sizeof(init_table2) / sizeof(hz_init_t));
+	setup_hazard_table(init_table3, table3,
+			   sizeof(init_table3) / sizeof(hz_init_t));
+}
--- libdrm-2.3.0.orig/shared-core/mach64_dma.c
+++ libdrm-2.3.0/shared-core/mach64_dma.c
@@ -0,0 +1,1539 @@
+/* mach64_dma.c -- DMA support for mach64 (Rage Pro) driver -*- linux-c -*- */
+/**
+ * \file mach64_dma.c
+ * DMA support for mach64 (Rage Pro) driver
+ *
+ * \author Gareth Hughes <gareth@valinux.com>
+ * \author Frank C. Earl <fearl@airmail.net>
+ * \author Leif Delgass <ldelgass@retinalburn.net>
+ * \author Jose Fonseca <j_r_fonseca@yahoo.co.uk>
+ */
+
+/*
+ * Copyright 2000 Gareth Hughes
+ * Copyright 2002 Frank C. Earl
+ * Copyright 2002-2003 Leif Delgass
+ * 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 COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION 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 "drmP.h"
+#include "drm.h"
+#include "mach64_drm.h"
+#include "mach64_drv.h"
+
+/*******************************************************************/
+/** \name Engine, FIFO control */
+/*@{*/
+
+/**
+ * Waits for free entries in the FIFO.
+ *
+ * \note Most writes to Mach64 registers are automatically routed through
+ * command FIFO which is 16 entry deep. Prior to writing to any draw engine
+ * register one has to ensure that enough FIFO entries are available by calling
+ * this function.  Failure to do so may cause the engine to lock.
+ *
+ * \param dev_priv pointer to device private data structure.
+ * \param entries number of free entries in the FIFO to wait for.
+ * 
+ * \returns zero on success, or -EBUSY if the timeout (specificed by
+ * drm_mach64_private::usec_timeout) occurs.
+ */
+int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries)
+{
+	int slots = 0, i;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		slots = (MACH64_READ(MACH64_FIFO_STAT) & MACH64_FIFO_SLOT_MASK);
+		if (slots <= (0x8000 >> entries))
+			return 0;
+		DRM_UDELAY(1);
+	}
+
+	DRM_INFO("%s failed! slots=%d entries=%d\n", __FUNCTION__, slots,
+		 entries);
+	return DRM_ERR(EBUSY);
+}
+
+/**
+ * Wait for the draw engine to be idle.
+ */
+int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv)
+{
+	int i, ret;
+
+	ret = mach64_do_wait_for_fifo(dev_priv, 16);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		if (!(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+
+	DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__,
+		 MACH64_READ(MACH64_GUI_STAT));
+	mach64_dump_ring_info(dev_priv);
+	return DRM_ERR(EBUSY);
+}
+
+/**
+ * Wait for free entries in the ring buffer.
+ *
+ * The Mach64 bus master can be configured to act as a virtual FIFO, using a
+ * circular buffer (commonly referred as "ring buffer" in other drivers) with
+ * pointers to engine commands. This allows the CPU to do other things while
+ * the graphics engine is busy, i.e., DMA mode.
+ *
+ * This function should be called before writing new entries to the ring
+ * buffer.
+ * 
+ * \param dev_priv pointer to device private data structure.
+ * \param n number of free entries in the ring buffer to wait for.
+ * 
+ * \returns zero on success, or -EBUSY if the timeout (specificed by
+ * drm_mach64_private_t::usec_timeout) occurs.
+ *
+ * \sa mach64_dump_ring_info()
+ */
+int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+	int i;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		mach64_update_ring_snapshot(dev_priv);
+		if (ring->space >= n) {
+			if (i > 0) {
+				DRM_DEBUG("%s: %d usecs\n", __FUNCTION__, i);
+			}
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+
+	/* FIXME: This is being ignored... */
+	DRM_ERROR("failed!\n");
+	mach64_dump_ring_info(dev_priv);
+	return DRM_ERR(EBUSY);
+}
+
+/**
+ * Wait until all DMA requests have been processed... 
+ *
+ * \sa mach64_wait_ring()
+ */
+static int mach64_ring_idle(drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+	u32 head;
+	int i;
+
+	head = ring->head;
+	i = 0;
+	while (i < dev_priv->usec_timeout) {
+		mach64_update_ring_snapshot(dev_priv);
+		if (ring->head == ring->tail &&
+		    !(MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE)) {
+			if (i > 0) {
+				DRM_DEBUG("%s: %d usecs\n", __FUNCTION__, i);
+			}
+			return 0;
+		}
+		if (ring->head == head) {
+			++i;
+		} else {
+			head = ring->head;
+			i = 0;
+		}
+		DRM_UDELAY(1);
+	}
+
+	DRM_INFO("%s failed! GUI_STAT=0x%08x\n", __FUNCTION__,
+		 MACH64_READ(MACH64_GUI_STAT));
+	mach64_dump_ring_info(dev_priv);
+	return DRM_ERR(EBUSY);
+}
+
+/**
+ * Reset the the ring buffer descriptors.
+ *
+ * \sa mach64_do_engine_reset()
+ */
+static void mach64_ring_reset(drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+
+	mach64_do_release_used_buffers(dev_priv);
+	ring->head_addr = ring->start_addr;
+	ring->head = ring->tail = 0;
+	ring->space = ring->size;
+
+	MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
+		     ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
+
+	dev_priv->ring_running = 0;
+}
+
+/**
+ * Ensure the all the queued commands will be processed.
+ */
+int mach64_do_dma_flush(drm_mach64_private_t * dev_priv)
+{
+	/* FIXME: It's not necessary to wait for idle when flushing
+	 * we just need to ensure the ring will be completely processed
+	 * in finite time without another ioctl
+	 */
+	return mach64_ring_idle(dev_priv);
+}
+
+/**
+ * Stop all DMA activity.
+ */
+int mach64_do_dma_idle(drm_mach64_private_t * dev_priv)
+{
+	int ret;
+
+	/* wait for completion */
+	if ((ret = mach64_ring_idle(dev_priv)) < 0) {
+		DRM_ERROR("%s failed BM_GUI_TABLE=0x%08x tail: %u\n",
+			  __FUNCTION__, MACH64_READ(MACH64_BM_GUI_TABLE),
+			  dev_priv->ring.tail);
+		return ret;
+	}
+
+	mach64_ring_stop(dev_priv);
+
+	/* clean up after pass */
+	mach64_do_release_used_buffers(dev_priv);
+	return 0;
+}
+
+/**
+ * Reset the engine.  This will stop the DMA if it is running.
+ */
+int mach64_do_engine_reset(drm_mach64_private_t * dev_priv)
+{
+	u32 tmp;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	/* Kill off any outstanding DMA transfers.
+	 */
+	tmp = MACH64_READ(MACH64_BUS_CNTL);
+	MACH64_WRITE(MACH64_BUS_CNTL, tmp | MACH64_BUS_MASTER_DIS);
+
+	/* Reset the GUI engine (high to low transition).
+	 */
+	tmp = MACH64_READ(MACH64_GEN_TEST_CNTL);
+	MACH64_WRITE(MACH64_GEN_TEST_CNTL, tmp & ~MACH64_GUI_ENGINE_ENABLE);
+	/* Enable the GUI engine
+	 */
+	tmp = MACH64_READ(MACH64_GEN_TEST_CNTL);
+	MACH64_WRITE(MACH64_GEN_TEST_CNTL, tmp | MACH64_GUI_ENGINE_ENABLE);
+
+	/* ensure engine is not locked up by clearing any FIFO or HOST errors
+	 */
+	tmp = MACH64_READ(MACH64_BUS_CNTL);
+	MACH64_WRITE(MACH64_BUS_CNTL, tmp | 0x00a00000);
+
+	/* Once GUI engine is restored, disable bus mastering */
+	MACH64_WRITE(MACH64_SRC_CNTL, 0);
+
+	/* Reset descriptor ring */
+	mach64_ring_reset(dev_priv);
+
+	return 0;
+}
+
+/*@}*/
+
+
+/*******************************************************************/
+/** \name Debugging output */
+/*@{*/
+
+/**
+ * Dump engine registers values.
+ */
+void mach64_dump_engine_info(drm_mach64_private_t * dev_priv)
+{
+	DRM_INFO("\n");
+	if (!dev_priv->is_pci) {
+		DRM_INFO("           AGP_BASE = 0x%08x\n",
+			 MACH64_READ(MACH64_AGP_BASE));
+		DRM_INFO("           AGP_CNTL = 0x%08x\n",
+			 MACH64_READ(MACH64_AGP_CNTL));
+	}
+	DRM_INFO("     ALPHA_TST_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_ALPHA_TST_CNTL));
+	DRM_INFO("\n");
+	DRM_INFO("         BM_COMMAND = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_COMMAND));
+	DRM_INFO("BM_FRAME_BUF_OFFSET = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_FRAME_BUF_OFFSET));
+	DRM_INFO("       BM_GUI_TABLE = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_GUI_TABLE));
+	DRM_INFO("          BM_STATUS = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_STATUS));
+	DRM_INFO(" BM_SYSTEM_MEM_ADDR = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_SYSTEM_MEM_ADDR));
+	DRM_INFO("    BM_SYSTEM_TABLE = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_SYSTEM_TABLE));
+	DRM_INFO("           BUS_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_BUS_CNTL));
+	DRM_INFO("\n");
+	/* DRM_INFO( "         CLOCK_CNTL = 0x%08x\n", MACH64_READ( MACH64_CLOCK_CNTL ) ); */
+	DRM_INFO("        CLR_CMP_CLR = 0x%08x\n",
+		 MACH64_READ(MACH64_CLR_CMP_CLR));
+	DRM_INFO("       CLR_CMP_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_CLR_CMP_CNTL));
+	/* DRM_INFO( "        CLR_CMP_MSK = 0x%08x\n", MACH64_READ( MACH64_CLR_CMP_MSK ) ); */
+	DRM_INFO("     CONFIG_CHIP_ID = 0x%08x\n",
+		 MACH64_READ(MACH64_CONFIG_CHIP_ID));
+	DRM_INFO("        CONFIG_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_CONFIG_CNTL));
+	DRM_INFO("       CONFIG_STAT0 = 0x%08x\n",
+		 MACH64_READ(MACH64_CONFIG_STAT0));
+	DRM_INFO("       CONFIG_STAT1 = 0x%08x\n",
+		 MACH64_READ(MACH64_CONFIG_STAT1));
+	DRM_INFO("       CONFIG_STAT2 = 0x%08x\n",
+		 MACH64_READ(MACH64_CONFIG_STAT2));
+	DRM_INFO("            CRC_SIG = 0x%08x\n", MACH64_READ(MACH64_CRC_SIG));
+	DRM_INFO("  CUSTOM_MACRO_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_CUSTOM_MACRO_CNTL));
+	DRM_INFO("\n");
+	/* DRM_INFO( "           DAC_CNTL = 0x%08x\n", MACH64_READ( MACH64_DAC_CNTL ) ); */
+	/* DRM_INFO( "           DAC_REGS = 0x%08x\n", MACH64_READ( MACH64_DAC_REGS ) ); */
+	DRM_INFO("        DP_BKGD_CLR = 0x%08x\n",
+		 MACH64_READ(MACH64_DP_BKGD_CLR));
+	DRM_INFO("        DP_FRGD_CLR = 0x%08x\n",
+		 MACH64_READ(MACH64_DP_FRGD_CLR));
+	DRM_INFO("             DP_MIX = 0x%08x\n", MACH64_READ(MACH64_DP_MIX));
+	DRM_INFO("       DP_PIX_WIDTH = 0x%08x\n",
+		 MACH64_READ(MACH64_DP_PIX_WIDTH));
+	DRM_INFO("             DP_SRC = 0x%08x\n", MACH64_READ(MACH64_DP_SRC));
+	DRM_INFO("      DP_WRITE_MASK = 0x%08x\n",
+		 MACH64_READ(MACH64_DP_WRITE_MASK));
+	DRM_INFO("         DSP_CONFIG = 0x%08x\n",
+		 MACH64_READ(MACH64_DSP_CONFIG));
+	DRM_INFO("         DSP_ON_OFF = 0x%08x\n",
+		 MACH64_READ(MACH64_DSP_ON_OFF));
+	DRM_INFO("           DST_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_DST_CNTL));
+	DRM_INFO("      DST_OFF_PITCH = 0x%08x\n",
+		 MACH64_READ(MACH64_DST_OFF_PITCH));
+	DRM_INFO("\n");
+	/* DRM_INFO( "       EXT_DAC_REGS = 0x%08x\n", MACH64_READ( MACH64_EXT_DAC_REGS ) ); */
+	DRM_INFO("       EXT_MEM_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_EXT_MEM_CNTL));
+	DRM_INFO("\n");
+	DRM_INFO("          FIFO_STAT = 0x%08x\n",
+		 MACH64_READ(MACH64_FIFO_STAT));
+	DRM_INFO("\n");
+	DRM_INFO("      GEN_TEST_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_GEN_TEST_CNTL));
+	/* DRM_INFO( "              GP_IO = 0x%08x\n", MACH64_READ( MACH64_GP_IO ) ); */
+	DRM_INFO("   GUI_CMDFIFO_DATA = 0x%08x\n",
+		 MACH64_READ(MACH64_GUI_CMDFIFO_DATA));
+	DRM_INFO("  GUI_CMDFIFO_DEBUG = 0x%08x\n",
+		 MACH64_READ(MACH64_GUI_CMDFIFO_DEBUG));
+	DRM_INFO("           GUI_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_GUI_CNTL));
+	DRM_INFO("           GUI_STAT = 0x%08x\n",
+		 MACH64_READ(MACH64_GUI_STAT));
+	DRM_INFO("      GUI_TRAJ_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_GUI_TRAJ_CNTL));
+	DRM_INFO("\n");
+	DRM_INFO("          HOST_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_HOST_CNTL));
+	DRM_INFO("           HW_DEBUG = 0x%08x\n",
+		 MACH64_READ(MACH64_HW_DEBUG));
+	DRM_INFO("\n");
+	DRM_INFO("    MEM_ADDR_CONFIG = 0x%08x\n",
+		 MACH64_READ(MACH64_MEM_ADDR_CONFIG));
+	DRM_INFO("       MEM_BUF_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_MEM_BUF_CNTL));
+	DRM_INFO("\n");
+	DRM_INFO("           PAT_REG0 = 0x%08x\n",
+		 MACH64_READ(MACH64_PAT_REG0));
+	DRM_INFO("           PAT_REG1 = 0x%08x\n",
+		 MACH64_READ(MACH64_PAT_REG1));
+	DRM_INFO("\n");
+	DRM_INFO("            SC_LEFT = 0x%08x\n", MACH64_READ(MACH64_SC_LEFT));
+	DRM_INFO("           SC_RIGHT = 0x%08x\n",
+		 MACH64_READ(MACH64_SC_RIGHT));
+	DRM_INFO("             SC_TOP = 0x%08x\n", MACH64_READ(MACH64_SC_TOP));
+	DRM_INFO("          SC_BOTTOM = 0x%08x\n",
+		 MACH64_READ(MACH64_SC_BOTTOM));
+	DRM_INFO("\n");
+	DRM_INFO("      SCALE_3D_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_SCALE_3D_CNTL));
+	DRM_INFO("       SCRATCH_REG0 = 0x%08x\n",
+		 MACH64_READ(MACH64_SCRATCH_REG0));
+	DRM_INFO("       SCRATCH_REG1 = 0x%08x\n",
+		 MACH64_READ(MACH64_SCRATCH_REG1));
+	DRM_INFO("         SETUP_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_SETUP_CNTL));
+	DRM_INFO("           SRC_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_SRC_CNTL));
+	DRM_INFO("\n");
+	DRM_INFO("           TEX_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_TEX_CNTL));
+	DRM_INFO("     TEX_SIZE_PITCH = 0x%08x\n",
+		 MACH64_READ(MACH64_TEX_SIZE_PITCH));
+	DRM_INFO("       TIMER_CONFIG = 0x%08x\n",
+		 MACH64_READ(MACH64_TIMER_CONFIG));
+	DRM_INFO("\n");
+	DRM_INFO("             Z_CNTL = 0x%08x\n", MACH64_READ(MACH64_Z_CNTL));
+	DRM_INFO("        Z_OFF_PITCH = 0x%08x\n",
+		 MACH64_READ(MACH64_Z_OFF_PITCH));
+	DRM_INFO("\n");
+}
+
+#define MACH64_DUMP_CONTEXT	3
+
+/**
+ * Used by mach64_dump_ring_info() to dump the contents of the current buffer
+ * pointed by the ring head.
+ */
+static void mach64_dump_buf_info(drm_mach64_private_t * dev_priv,
+				 drm_buf_t * buf)
+{
+	u32 addr = GETBUFADDR(buf);
+	u32 used = buf->used >> 2;
+	u32 sys_addr = MACH64_READ(MACH64_BM_SYSTEM_MEM_ADDR);
+	u32 *p = GETBUFPTR(buf);
+	int skipped = 0;
+
+	DRM_INFO("buffer contents:\n");
+
+	while (used) {
+		u32 reg, count;
+
+		reg = le32_to_cpu(*p++);
+		if (addr <= GETBUFADDR(buf) + MACH64_DUMP_CONTEXT * 4 ||
+		    (addr >= sys_addr - MACH64_DUMP_CONTEXT * 4 &&
+		     addr <= sys_addr + MACH64_DUMP_CONTEXT * 4) ||
+		    addr >=
+		    GETBUFADDR(buf) + buf->used - MACH64_DUMP_CONTEXT * 4) {
+			DRM_INFO("%08x:  0x%08x\n", addr, reg);
+		}
+		addr += 4;
+		used--;
+
+		count = (reg >> 16) + 1;
+		reg = reg & 0xffff;
+		reg = MMSELECT(reg);
+		while (count && used) {
+			if (addr <= GETBUFADDR(buf) + MACH64_DUMP_CONTEXT * 4 ||
+			    (addr >= sys_addr - MACH64_DUMP_CONTEXT * 4 &&
+			     addr <= sys_addr + MACH64_DUMP_CONTEXT * 4) ||
+			    addr >=
+			    GETBUFADDR(buf) + buf->used -
+			    MACH64_DUMP_CONTEXT * 4) {
+				DRM_INFO("%08x:    0x%04x = 0x%08x\n", addr,
+					 reg, le32_to_cpu(*p));
+				skipped = 0;
+			} else {
+				if (!skipped) {
+					DRM_INFO("  ...\n");
+					skipped = 1;
+				}
+			}
+			p++;
+			addr += 4;
+			used--;
+
+			reg += 4;
+			count--;
+		}
+	}
+
+	DRM_INFO("\n");
+}
+
+/**
+ * Dump the ring state and contents, including the contents of the buffer being
+ * processed by the graphics engine.
+ */
+void mach64_dump_ring_info(drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+	int i, skipped;
+
+	DRM_INFO("\n");
+
+	DRM_INFO("ring contents:\n");
+	DRM_INFO("  head_addr: 0x%08x head: %u tail: %u\n\n",
+		 ring->head_addr, ring->head, ring->tail);
+
+	skipped = 0;
+	for (i = 0; i < ring->size / sizeof(u32); i += 4) {
+		if (i <= MACH64_DUMP_CONTEXT * 4 ||
+		    i >= ring->size / sizeof(u32) - MACH64_DUMP_CONTEXT * 4 ||
+		    (i >= ring->tail - MACH64_DUMP_CONTEXT * 4 &&
+		     i <= ring->tail + MACH64_DUMP_CONTEXT * 4) ||
+		    (i >= ring->head - MACH64_DUMP_CONTEXT * 4 &&
+		     i <= ring->head + MACH64_DUMP_CONTEXT * 4)) {
+			DRM_INFO("  0x%08x:  0x%08x 0x%08x 0x%08x 0x%08x%s%s\n",
+				 (u32)(ring->start_addr + i * sizeof(u32)),
+				 le32_to_cpu(((u32 *) ring->start)[i + 0]),
+				 le32_to_cpu(((u32 *) ring->start)[i + 1]),
+				 le32_to_cpu(((u32 *) ring->start)[i + 2]),
+				 le32_to_cpu(((u32 *) ring->start)[i + 3]),
+				 i == ring->head ? " (head)" : "",
+				 i == ring->tail ? " (tail)" : "");
+			skipped = 0;
+		} else {
+			if (!skipped) {
+				DRM_INFO("  ...\n");
+				skipped = 1;
+			}
+		}
+	}
+
+	DRM_INFO("\n");
+
+	if (ring->head >= 0 && ring->head < ring->size / sizeof(u32)) {
+		struct list_head *ptr;
+		u32 addr = le32_to_cpu(((u32 *) ring->start)[ring->head + 1]);
+
+		list_for_each(ptr, &dev_priv->pending) {
+			drm_mach64_freelist_t *entry =
+			    list_entry(ptr, drm_mach64_freelist_t, list);
+			drm_buf_t *buf = entry->buf;
+
+			u32 buf_addr = GETBUFADDR(buf);
+
+			if (buf_addr <= addr && addr < buf_addr + buf->used) {
+				mach64_dump_buf_info(dev_priv, buf);
+			}
+		}
+	}
+
+	DRM_INFO("\n");
+	DRM_INFO("       BM_GUI_TABLE = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_GUI_TABLE));
+	DRM_INFO("\n");
+	DRM_INFO("BM_FRAME_BUF_OFFSET = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_FRAME_BUF_OFFSET));
+	DRM_INFO(" BM_SYSTEM_MEM_ADDR = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_SYSTEM_MEM_ADDR));
+	DRM_INFO("         BM_COMMAND = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_COMMAND));
+	DRM_INFO("\n");
+	DRM_INFO("          BM_STATUS = 0x%08x\n",
+		 MACH64_READ(MACH64_BM_STATUS));
+	DRM_INFO("           BUS_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_BUS_CNTL));
+	DRM_INFO("          FIFO_STAT = 0x%08x\n",
+		 MACH64_READ(MACH64_FIFO_STAT));
+	DRM_INFO("           GUI_STAT = 0x%08x\n",
+		 MACH64_READ(MACH64_GUI_STAT));
+	DRM_INFO("           SRC_CNTL = 0x%08x\n",
+		 MACH64_READ(MACH64_SRC_CNTL));
+}
+
+/*@}*/
+
+
+/*******************************************************************/
+/** \name DMA test and initialization */
+/*@{*/
+
+/**
+ * Perform a simple DMA operation using the pattern registers to test whether
+ * DMA works.
+ *
+ * \return zero if successful.
+ *
+ * \note This function was the testbed for many experiences regarding Mach64
+ * DMA operation. It is left here since it so tricky to get DMA operating
+ * properly in some architectures and hardware.
+ */
+static int mach64_bm_dma_test(drm_device_t * dev)
+{
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_dma_handle_t *cpu_addr_dmah;
+	u32 data_addr;
+	u32 *table, *data;
+	u32 expected[2];
+	u32 src_cntl, pat_reg0, pat_reg1;
+	int i, count, failed;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	table = (u32 *) dev_priv->ring.start;
+
+	/* FIXME: get a dma buffer from the freelist here */
+	DRM_DEBUG("Allocating data memory ...\n");
+	cpu_addr_dmah =
+	    drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful);
+	if (!cpu_addr_dmah) {
+		DRM_INFO("data-memory allocation failed!\n");
+		return DRM_ERR(ENOMEM);
+	} else {
+		data = (u32 *) cpu_addr_dmah->vaddr;
+		data_addr = (u32) cpu_addr_dmah->busaddr;
+	}
+
+	/* Save the X server's value for SRC_CNTL and restore it
+	 * in case our test fails.  This prevents the X server
+	 * from disabling it's cache for this register
+	 */
+	src_cntl = MACH64_READ(MACH64_SRC_CNTL);
+	pat_reg0 = MACH64_READ(MACH64_PAT_REG0);
+	pat_reg1 = MACH64_READ(MACH64_PAT_REG1);
+
+	mach64_do_wait_for_fifo(dev_priv, 3);
+
+	MACH64_WRITE(MACH64_SRC_CNTL, 0);
+	MACH64_WRITE(MACH64_PAT_REG0, 0x11111111);
+	MACH64_WRITE(MACH64_PAT_REG1, 0x11111111);
+
+	mach64_do_wait_for_idle(dev_priv);
+
+	for (i = 0; i < 2; i++) {
+		u32 reg;
+		reg = MACH64_READ((MACH64_PAT_REG0 + i * 4));
+		DRM_DEBUG("(Before DMA Transfer) reg %d = 0x%08x\n", i, reg);
+		if (reg != 0x11111111) {
+			DRM_INFO("Error initializing test registers\n");
+			DRM_INFO("resetting engine ...\n");
+			mach64_do_engine_reset(dev_priv);
+			DRM_INFO("freeing data buffer memory.\n");
+			drm_pci_free(dev, cpu_addr_dmah);
+			return DRM_ERR(EIO);
+		}
+	}
+
+	/* fill up a buffer with sets of 2 consecutive writes starting with PAT_REG0 */
+	count = 0;
+
+	data[count++] = cpu_to_le32(DMAREG(MACH64_PAT_REG0) | (1 << 16));
+	data[count++] = expected[0] = 0x22222222;
+	data[count++] = expected[1] = 0xaaaaaaaa;
+
+	while (count < 1020) {
+		data[count++] =
+		    cpu_to_le32(DMAREG(MACH64_PAT_REG0) | (1 << 16));
+		data[count++] = 0x22222222;
+		data[count++] = 0xaaaaaaaa;
+	}
+	data[count++] = cpu_to_le32(DMAREG(MACH64_SRC_CNTL) | (0 << 16));
+	data[count++] = 0;
+
+	DRM_DEBUG("Preparing table ...\n");
+	table[MACH64_DMA_FRAME_BUF_OFFSET] = cpu_to_le32(MACH64_BM_ADDR +
+							 MACH64_APERTURE_OFFSET);
+	table[MACH64_DMA_SYS_MEM_ADDR] = cpu_to_le32(data_addr);
+	table[MACH64_DMA_COMMAND] = cpu_to_le32(count * sizeof(u32)
+						| MACH64_DMA_HOLD_OFFSET
+						| MACH64_DMA_EOL);
+	table[MACH64_DMA_RESERVED] = 0;
+
+	DRM_DEBUG("table[0] = 0x%08x\n", table[0]);
+	DRM_DEBUG("table[1] = 0x%08x\n", table[1]);
+	DRM_DEBUG("table[2] = 0x%08x\n", table[2]);
+	DRM_DEBUG("table[3] = 0x%08x\n", table[3]);
+
+	for (i = 0; i < 6; i++) {
+		DRM_DEBUG(" data[%d] = 0x%08x\n", i, data[i]);
+	}
+	DRM_DEBUG(" ...\n");
+	for (i = count - 5; i < count; i++) {
+		DRM_DEBUG(" data[%d] = 0x%08x\n", i, data[i]);
+	}
+
+	DRM_MEMORYBARRIER();
+
+	DRM_DEBUG("waiting for idle...\n");
+	if ((i = mach64_do_wait_for_idle(dev_priv))) {
+		DRM_INFO("mach64_do_wait_for_idle failed (result=%d)\n", i);
+		DRM_INFO("resetting engine ...\n");
+		mach64_do_engine_reset(dev_priv);
+		mach64_do_wait_for_fifo(dev_priv, 3);
+		MACH64_WRITE(MACH64_SRC_CNTL, src_cntl);
+		MACH64_WRITE(MACH64_PAT_REG0, pat_reg0);
+		MACH64_WRITE(MACH64_PAT_REG1, pat_reg1);
+		DRM_INFO("freeing data buffer memory.\n");
+		drm_pci_free(dev, cpu_addr_dmah);
+		return i;
+	}
+	DRM_DEBUG("waiting for idle...done\n");
+
+	DRM_DEBUG("BUS_CNTL = 0x%08x\n", MACH64_READ(MACH64_BUS_CNTL));
+	DRM_DEBUG("SRC_CNTL = 0x%08x\n", MACH64_READ(MACH64_SRC_CNTL));
+	DRM_DEBUG("\n");
+	DRM_DEBUG("data bus addr = 0x%08x\n", data_addr);
+	DRM_DEBUG("table bus addr = 0x%08x\n", dev_priv->ring.start_addr);
+
+	DRM_DEBUG("starting DMA transfer...\n");
+	MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
+		     dev_priv->ring.start_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
+
+	MACH64_WRITE(MACH64_SRC_CNTL,
+		     MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC |
+		     MACH64_SRC_BM_OP_SYSTEM_TO_REG);
+
+	/* Kick off the transfer */
+	DRM_DEBUG("starting DMA transfer... done.\n");
+	MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0);
+
+	DRM_DEBUG("waiting for idle...\n");
+
+	if ((i = mach64_do_wait_for_idle(dev_priv))) {
+		/* engine locked up, dump register state and reset */
+		DRM_INFO("mach64_do_wait_for_idle failed (result=%d)\n", i);
+		mach64_dump_engine_info(dev_priv);
+		DRM_INFO("resetting engine ...\n");
+		mach64_do_engine_reset(dev_priv);
+		mach64_do_wait_for_fifo(dev_priv, 3);
+		MACH64_WRITE(MACH64_SRC_CNTL, src_cntl);
+		MACH64_WRITE(MACH64_PAT_REG0, pat_reg0);
+		MACH64_WRITE(MACH64_PAT_REG1, pat_reg1);
+		DRM_INFO("freeing data buffer memory.\n");
+		drm_pci_free(dev, cpu_addr_dmah);
+		return i;
+	}
+
+	DRM_DEBUG("waiting for idle...done\n");
+
+	/* restore SRC_CNTL */
+	mach64_do_wait_for_fifo(dev_priv, 1);
+	MACH64_WRITE(MACH64_SRC_CNTL, src_cntl);
+
+	failed = 0;
+
+	/* Check register values to see if the GUI master operation succeeded */
+	for (i = 0; i < 2; i++) {
+		u32 reg;
+		reg = MACH64_READ((MACH64_PAT_REG0 + i * 4));
+		DRM_DEBUG("(After DMA Transfer) reg %d = 0x%08x\n", i, reg);
+		if (reg != expected[i]) {
+			failed = -1;
+		}
+	}
+
+	/* restore pattern registers */
+	mach64_do_wait_for_fifo(dev_priv, 2);
+	MACH64_WRITE(MACH64_PAT_REG0, pat_reg0);
+	MACH64_WRITE(MACH64_PAT_REG1, pat_reg1);
+
+	DRM_DEBUG("freeing data buffer memory.\n");
+	drm_pci_free(dev, cpu_addr_dmah);
+	DRM_DEBUG("returning ...\n");
+
+	return failed;
+}
+
+/**
+ * Called during the DMA initialization ioctl to initialize all the necessary
+ * software and hardware state for DMA operation.
+ */
+static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init)
+{
+	drm_mach64_private_t *dev_priv;
+	u32 tmp;
+	int i, ret;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	dev_priv = drm_alloc(sizeof(drm_mach64_private_t), DRM_MEM_DRIVER);
+	if (dev_priv == NULL)
+		return DRM_ERR(ENOMEM);
+
+	memset(dev_priv, 0, sizeof(drm_mach64_private_t));
+
+	dev_priv->is_pci = init->is_pci;
+
+	dev_priv->fb_bpp = init->fb_bpp;
+	dev_priv->front_offset = init->front_offset;
+	dev_priv->front_pitch = init->front_pitch;
+	dev_priv->back_offset = init->back_offset;
+	dev_priv->back_pitch = init->back_pitch;
+
+	dev_priv->depth_bpp = init->depth_bpp;
+	dev_priv->depth_offset = init->depth_offset;
+	dev_priv->depth_pitch = init->depth_pitch;
+
+	dev_priv->front_offset_pitch = (((dev_priv->front_pitch / 8) << 22) |
+					(dev_priv->front_offset >> 3));
+	dev_priv->back_offset_pitch = (((dev_priv->back_pitch / 8) << 22) |
+				       (dev_priv->back_offset >> 3));
+	dev_priv->depth_offset_pitch = (((dev_priv->depth_pitch / 8) << 22) |
+					(dev_priv->depth_offset >> 3));
+
+	dev_priv->usec_timeout = 1000000;
+
+	/* Set up the freelist, placeholder list and pending list */
+	INIT_LIST_HEAD(&dev_priv->free_list);
+	INIT_LIST_HEAD(&dev_priv->placeholders);
+	INIT_LIST_HEAD(&dev_priv->pending);
+
+	DRM_GETSAREA();
+
+	if (!dev_priv->sarea) {
+		DRM_ERROR("can not find sarea!\n");
+		dev->dev_private = (void *)dev_priv;
+		mach64_do_cleanup_dma(dev);
+		return DRM_ERR(EINVAL);
+	}
+	dev_priv->fb = drm_core_findmap(dev, init->fb_offset);
+	if (!dev_priv->fb) {
+		DRM_ERROR("can not find frame buffer map!\n");
+		dev->dev_private = (void *)dev_priv;
+		mach64_do_cleanup_dma(dev);
+		return DRM_ERR(EINVAL);
+	}
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+	if (!dev_priv->mmio) {
+		DRM_ERROR("can not find mmio map!\n");
+		dev->dev_private = (void *)dev_priv;
+		mach64_do_cleanup_dma(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset);
+	if (!dev_priv->ring_map) {
+		DRM_ERROR("can not find ring map!\n");
+		dev->dev_private = (void *)dev_priv;
+		mach64_do_cleanup_dma(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->sarea_priv = (drm_mach64_sarea_t *)
+	    ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
+
+	if (!dev_priv->is_pci) {
+		drm_core_ioremap(dev_priv->ring_map, dev);
+		if (!dev_priv->ring_map->handle) {
+			DRM_ERROR("can not ioremap virtual address for"
+				  " descriptor ring\n");
+			dev->dev_private = (void *)dev_priv;
+			mach64_do_cleanup_dma(dev);
+			return DRM_ERR(ENOMEM);
+		}
+		dev->agp_buffer_token = init->buffers_offset;
+		dev->agp_buffer_map =
+		    drm_core_findmap(dev, init->buffers_offset);
+		if (!dev->agp_buffer_map) {
+			DRM_ERROR("can not find dma buffer map!\n");
+			dev->dev_private = (void *)dev_priv;
+			mach64_do_cleanup_dma(dev);
+			return DRM_ERR(EINVAL);
+		}
+		/* there might be a nicer way to do this -
+		   dev isn't passed all the way though the mach64 - DA */
+		dev_priv->dev_buffers = dev->agp_buffer_map;
+
+		drm_core_ioremap(dev->agp_buffer_map, dev);
+		if (!dev->agp_buffer_map->handle) {
+			DRM_ERROR("can not ioremap virtual address for"
+				  " dma buffer\n");
+			dev->dev_private = (void *)dev_priv;
+			mach64_do_cleanup_dma(dev);
+			return DRM_ERR(ENOMEM);
+		}
+		dev_priv->agp_textures =
+		    drm_core_findmap(dev, init->agp_textures_offset);
+		if (!dev_priv->agp_textures) {
+			DRM_ERROR("can not find agp texture region!\n");
+			dev->dev_private = (void *)dev_priv;
+			mach64_do_cleanup_dma(dev);
+			return DRM_ERR(EINVAL);
+		}
+	}
+
+	dev->dev_private = (void *)dev_priv;
+
+	dev_priv->driver_mode = init->dma_mode;
+
+	/* changing the FIFO size from the default causes problems with DMA */
+	tmp = MACH64_READ(MACH64_GUI_CNTL);
+	if ((tmp & MACH64_CMDFIFO_SIZE_MASK) != MACH64_CMDFIFO_SIZE_128) {
+		DRM_INFO("Setting FIFO size to 128 entries\n");
+		/* FIFO must be empty to change the FIFO depth */
+		if ((ret = mach64_do_wait_for_idle(dev_priv))) {
+			DRM_ERROR
+			    ("wait for idle failed before changing FIFO depth!\n");
+			mach64_do_cleanup_dma(dev);
+			return ret;
+		}
+		MACH64_WRITE(MACH64_GUI_CNTL, ((tmp & ~MACH64_CMDFIFO_SIZE_MASK)
+					       | MACH64_CMDFIFO_SIZE_128));
+		/* need to read GUI_STAT for proper sync according to docs */
+		if ((ret = mach64_do_wait_for_idle(dev_priv))) {
+			DRM_ERROR
+			    ("wait for idle failed when changing FIFO depth!\n");
+			mach64_do_cleanup_dma(dev);
+			return ret;
+		}
+	}
+
+	dev_priv->ring.size = 0x4000;	/* 16KB */
+	dev_priv->ring.start = dev_priv->ring_map->handle;
+	dev_priv->ring.start_addr = (u32) dev_priv->ring_map->offset;
+
+	memset(dev_priv->ring.start, 0, dev_priv->ring.size);
+	DRM_INFO("descriptor ring: cpu addr %p, bus addr: 0x%08x\n",
+		 dev_priv->ring.start, dev_priv->ring.start_addr);
+
+	ret = 0;
+	if (dev_priv->driver_mode != MACH64_MODE_MMIO) {
+
+		/* enable block 1 registers and bus mastering */
+		MACH64_WRITE(MACH64_BUS_CNTL, ((MACH64_READ(MACH64_BUS_CNTL)
+						| MACH64_BUS_EXT_REG_EN)
+					       & ~MACH64_BUS_MASTER_DIS));
+
+		/* try a DMA GUI-mastering pass and fall back to MMIO if it fails */
+		DRM_DEBUG("Starting DMA test...\n");
+		if ((ret = mach64_bm_dma_test(dev))) {
+			dev_priv->driver_mode = MACH64_MODE_MMIO;
+		}
+	}
+
+	switch (dev_priv->driver_mode) {
+	case MACH64_MODE_MMIO:
+		MACH64_WRITE(MACH64_BUS_CNTL, (MACH64_READ(MACH64_BUS_CNTL)
+					       | MACH64_BUS_EXT_REG_EN
+					       | MACH64_BUS_MASTER_DIS));
+		if (init->dma_mode == MACH64_MODE_MMIO)
+			DRM_INFO("Forcing pseudo-DMA mode\n");
+		else
+			DRM_INFO
+			    ("DMA test failed (ret=%d), using pseudo-DMA mode\n",
+			     ret);
+		break;
+	case MACH64_MODE_DMA_SYNC:
+		DRM_INFO("DMA test succeeded, using synchronous DMA mode\n");
+		break;
+	case MACH64_MODE_DMA_ASYNC:
+	default:
+		DRM_INFO("DMA test succeeded, using asynchronous DMA mode\n");
+	}
+
+	dev_priv->ring_running = 0;
+
+	/* setup offsets for physical address of table start and end */
+	dev_priv->ring.head_addr = dev_priv->ring.start_addr;
+	dev_priv->ring.head = dev_priv->ring.tail = 0;
+	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
+	dev_priv->ring.space = dev_priv->ring.size;
+
+	/* setup physical address and size of descriptor table */
+	mach64_do_wait_for_fifo(dev_priv, 1);
+	MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
+		     (dev_priv->ring.
+		      head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB));
+
+	/* init frame counter */
+	dev_priv->sarea_priv->frames_queued = 0;
+	for (i = 0; i < MACH64_MAX_QUEUED_FRAMES; i++) {
+		dev_priv->frame_ofs[i] = ~0;	/* All ones indicates placeholder */
+	}
+
+	/* Allocate the DMA buffer freelist */
+	if ((ret = mach64_init_freelist(dev))) {
+		DRM_ERROR("Freelist allocation failed\n");
+		mach64_do_cleanup_dma(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*******************************************************************/
+/** MMIO Pseudo-DMA (intended primarily for debugging, not performance)
+ */
+
+int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+	volatile u32 *ring_read;
+	struct list_head *ptr;
+	drm_mach64_freelist_t *entry;
+	drm_buf_t *buf = NULL;
+	u32 *buf_ptr;
+	u32 used, reg, target;
+	int fifo, count, found, ret, no_idle_wait;
+
+	fifo = count = reg = no_idle_wait = 0;
+	target = MACH64_BM_ADDR;
+
+	if ((ret = mach64_do_wait_for_idle(dev_priv)) < 0) {
+		DRM_INFO
+		    ("%s: idle failed before pseudo-dma dispatch, resetting engine\n",
+		     __FUNCTION__);
+		mach64_dump_engine_info(dev_priv);
+		mach64_do_engine_reset(dev_priv);
+		return ret;
+	}
+
+	ring_read = (u32 *) ring->start;
+
+	while (ring->tail != ring->head) {
+		u32 buf_addr, new_target, offset;
+		u32 bytes, remaining, head, eol;
+
+		head = ring->head;
+
+		new_target =
+		    le32_to_cpu(ring_read[head++]) - MACH64_APERTURE_OFFSET;
+		buf_addr = le32_to_cpu(ring_read[head++]);
+		eol = le32_to_cpu(ring_read[head]) & MACH64_DMA_EOL;
+		bytes = le32_to_cpu(ring_read[head++])
+		    & ~(MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL);
+		head++;
+		head &= ring->tail_mask;
+
+		/* can't wait for idle between a blit setup descriptor
+		 * and a HOSTDATA descriptor or the engine will lock
+		 */
+		if (new_target == MACH64_BM_HOSTDATA
+		    && target == MACH64_BM_ADDR)
+			no_idle_wait = 1;
+
+		target = new_target;
+
+		found = 0;
+		offset = 0;
+		list_for_each(ptr, &dev_priv->pending) {
+			entry = list_entry(ptr, drm_mach64_freelist_t, list);
+			buf = entry->buf;
+			offset = buf_addr - GETBUFADDR(buf);
+			if (offset >= 0 && offset < MACH64_BUFFER_SIZE) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (!found || buf == NULL) {
+			DRM_ERROR
+			    ("Couldn't find pending buffer: head: %u tail: %u buf_addr: 0x%08x %s\n",
+			     head, ring->tail, buf_addr, (eol ? "eol" : ""));
+			mach64_dump_ring_info(dev_priv);
+			mach64_do_engine_reset(dev_priv);
+			return DRM_ERR(EINVAL);
+		}
+
+		/* Hand feed the buffer to the card via MMIO, waiting for the fifo
+		 * every 16 writes
+		 */
+		DRM_DEBUG("target: (0x%08x) %s\n", target,
+			  (target ==
+			   MACH64_BM_HOSTDATA ? "BM_HOSTDATA" : "BM_ADDR"));
+		DRM_DEBUG("offset: %u bytes: %u used: %u\n", offset, bytes,
+			  buf->used);
+
+		remaining = (buf->used - offset) >> 2;	/* dwords remaining in buffer */
+		used = bytes >> 2;	/* dwords in buffer for this descriptor */
+		buf_ptr = (u32 *) ((char *)GETBUFPTR(buf) + offset);
+
+		while (used) {
+
+			if (count == 0) {
+				if (target == MACH64_BM_HOSTDATA) {
+					reg = DMAREG(MACH64_HOST_DATA0);
+					count =
+					    (remaining > 16) ? 16 : remaining;
+					fifo = 0;
+				} else {
+					reg = le32_to_cpu(*buf_ptr++);
+					used--;
+					count = (reg >> 16) + 1;
+				}
+
+				reg = reg & 0xffff;
+				reg = MMSELECT(reg);
+			}
+			while (count && used) {
+				if (!fifo) {
+					if (no_idle_wait) {
+						if ((ret =
+						     mach64_do_wait_for_fifo
+						     (dev_priv, 16)) < 0) {
+							no_idle_wait = 0;
+							return ret;
+						}
+					} else {
+						if ((ret =
+						     mach64_do_wait_for_idle
+						     (dev_priv)) < 0) {
+							return ret;
+						}
+					}
+					fifo = 16;
+				}
+				--fifo;
+				MACH64_WRITE(reg, le32_to_cpu(*buf_ptr++));
+				used--;
+				remaining--;
+
+				reg += 4;
+				count--;
+			}
+		}
+		ring->head = head;
+		ring->head_addr = ring->start_addr + (ring->head * sizeof(u32));
+		ring->space += (4 * sizeof(u32));
+	}
+
+	if ((ret = mach64_do_wait_for_idle(dev_priv)) < 0) {
+		return ret;
+	}
+	MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
+		     ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
+
+	DRM_DEBUG("%s completed\n", __FUNCTION__);
+	return 0;
+}
+
+/*@}*/
+
+
+/*******************************************************************/
+/** \name DMA cleanup */
+/*@{*/
+
+int mach64_do_cleanup_dma(drm_device_t * dev)
+{
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if (dev->irq)
+		drm_irq_uninstall(dev);
+
+	if (dev->dev_private) {
+		drm_mach64_private_t *dev_priv = dev->dev_private;
+
+		if (!dev_priv->is_pci) {
+			if (dev_priv->ring_map)
+				drm_core_ioremapfree(dev_priv->ring_map, dev);
+
+			if (dev->agp_buffer_map) {
+				drm_core_ioremapfree(dev->agp_buffer_map, dev);
+				dev->agp_buffer_map = NULL;
+			}
+		}
+
+		mach64_destroy_freelist(dev);
+
+		drm_free(dev_priv, sizeof(drm_mach64_private_t),
+			 DRM_MEM_DRIVER);
+		dev->dev_private = NULL;
+	}
+
+	return 0;
+}
+
+/*@}*/
+
+
+/*******************************************************************/
+/** \name IOCTL handlers */
+/*@{*/
+
+int mach64_dma_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mach64_init_t init;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(init, (drm_mach64_init_t *) data,
+				 sizeof(init));
+
+	switch (init.func) {
+	case DRM_MACH64_INIT_DMA:
+		return mach64_do_dma_init(dev, &init);
+	case DRM_MACH64_CLEANUP_DMA:
+		return mach64_do_cleanup_dma(dev);
+	}
+
+	return DRM_ERR(EINVAL);
+}
+
+int mach64_dma_idle(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	return mach64_do_dma_idle(dev_priv);
+}
+
+int mach64_dma_flush(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	return mach64_do_dma_flush(dev_priv);
+}
+
+int mach64_engine_reset(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	return mach64_do_engine_reset(dev_priv);
+}
+
+/*@}*/
+
+
+/*******************************************************************/
+/** \name Freelist management */
+/*@{*/
+
+int mach64_init_freelist(drm_device_t * dev)
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_freelist_t *entry;
+	struct list_head *ptr;
+	int i;
+
+	DRM_DEBUG("%s: adding %d buffers to freelist\n", __FUNCTION__,
+		  dma->buf_count);
+
+	for (i = 0; i < dma->buf_count; i++) {
+		if ((entry =
+		     (drm_mach64_freelist_t *)
+		     drm_alloc(sizeof(drm_mach64_freelist_t),
+			       DRM_MEM_BUFLISTS)) == NULL)
+			return DRM_ERR(ENOMEM);
+		memset(entry, 0, sizeof(drm_mach64_freelist_t));
+		entry->buf = dma->buflist[i];
+		ptr = &entry->list;
+		list_add_tail(ptr, &dev_priv->free_list);
+	}
+
+	return 0;
+}
+
+void mach64_destroy_freelist(drm_device_t * dev)
+{
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_freelist_t *entry;
+	struct list_head *ptr;
+	struct list_head *tmp;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	list_for_each_safe(ptr, tmp, &dev_priv->pending) {
+		list_del(ptr);
+		entry = list_entry(ptr, drm_mach64_freelist_t, list);
+		drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS);
+	}
+	list_for_each_safe(ptr, tmp, &dev_priv->placeholders) {
+		list_del(ptr);
+		entry = list_entry(ptr, drm_mach64_freelist_t, list);
+		drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS);
+	}
+
+	list_for_each_safe(ptr, tmp, &dev_priv->free_list) {
+		list_del(ptr);
+		entry = list_entry(ptr, drm_mach64_freelist_t, list);
+		drm_free(entry, sizeof(*entry), DRM_MEM_BUFLISTS);
+	}
+}
+
+/* IMPORTANT: This function should only be called when the engine is idle or locked up,
+ * as it assumes all buffers in the pending list have been completed by the hardware.
+ */
+int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv)
+{
+	struct list_head *ptr;
+	struct list_head *tmp;
+	drm_mach64_freelist_t *entry;
+	int i;
+
+	if (list_empty(&dev_priv->pending))
+		return 0;
+
+	/* Iterate the pending list and move all buffers into the freelist... */
+	i = 0;
+	list_for_each_safe(ptr, tmp, &dev_priv->pending) {
+		entry = list_entry(ptr, drm_mach64_freelist_t, list);
+		if (entry->discard) {
+			entry->buf->pending = 0;
+			list_del(ptr);
+			list_add_tail(ptr, &dev_priv->free_list);
+			i++;
+		}
+	}
+
+	DRM_DEBUG("%s: released %d buffers from pending list\n", __FUNCTION__,
+		  i);
+
+	return 0;
+}
+
+static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+	struct list_head *ptr;
+	struct list_head *tmp;
+	drm_mach64_freelist_t *entry;
+	u32 head, tail, ofs;
+
+	mach64_ring_tick(dev_priv, ring);
+	head = ring->head;
+	tail = ring->tail;
+
+	if (head == tail) {
+#if MACH64_EXTRA_CHECKING
+		if (MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE) {
+			DRM_ERROR("Empty ring with non-idle engine!\n");
+			mach64_dump_ring_info(dev_priv);
+			return -1;
+		}
+#endif
+		/* last pass is complete, so release everything */
+		mach64_do_release_used_buffers(dev_priv);
+		DRM_DEBUG("%s: idle engine, freed all buffers.\n",
+		     __FUNCTION__);
+		if (list_empty(&dev_priv->free_list)) {
+			DRM_ERROR("Freelist empty with idle engine\n");
+			return -1;
+		}
+		return 0;
+	}
+	/* Look for a completed buffer and bail out of the loop
+	 * as soon as we find one -- don't waste time trying
+	 * to free extra bufs here, leave that to do_release_used_buffers
+	 */
+	list_for_each_safe(ptr, tmp, &dev_priv->pending) {
+		entry = list_entry(ptr, drm_mach64_freelist_t, list);
+		ofs = entry->ring_ofs;
+		if (entry->discard &&
+		    ((head < tail && (ofs < head || ofs >= tail)) ||
+		     (head > tail && (ofs < head && ofs >= tail)))) {
+#if MACH64_EXTRA_CHECKING
+			int i;
+
+			for (i = head; i != tail; i = (i + 4) & ring->tail_mask)
+			{
+				u32 o1 = le32_to_cpu(((u32 *) ring->
+						 start)[i + 1]);
+				u32 o2 = GETBUFADDR(entry->buf);
+
+				if (o1 == o2) {
+					DRM_ERROR
+					    ("Attempting to free used buffer: "
+					     "i=%d  buf=0x%08x\n",
+					     i, o1);
+					mach64_dump_ring_info(dev_priv);
+					return -1;
+				}
+			}
+#endif
+			/* found a processed buffer */
+			entry->buf->pending = 0;
+			list_del(ptr);
+			list_add_tail(ptr, &dev_priv->free_list);
+			DRM_DEBUG
+			    ("%s: freed processed buffer (head=%d tail=%d "
+			     "buf ring ofs=%d).\n",
+			     __FUNCTION__, head, tail, ofs);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+	drm_mach64_freelist_t *entry;
+	struct list_head *ptr;
+	int t;
+
+	if (list_empty(&dev_priv->free_list)) {
+		if (list_empty(&dev_priv->pending)) {
+			DRM_ERROR
+			    ("Couldn't get buffer - pending and free lists empty\n");
+			t = 0;
+			list_for_each(ptr, &dev_priv->placeholders) {
+				t++;
+			}
+			DRM_INFO("Placeholders: %d\n", t);
+			return NULL;
+		}
+
+		for (t = 0; t < dev_priv->usec_timeout; t++) {
+			int ret;
+
+			ret = mach64_do_reclaim_completed(dev_priv);
+			if (ret == 0)
+				goto _freelist_entry_found;
+			if (ret < 0)
+				return NULL;
+
+			DRM_UDELAY(1);
+		}
+		mach64_dump_ring_info(dev_priv);
+		DRM_ERROR
+		    ("timeout waiting for buffers: ring head_addr: 0x%08x head: %d tail: %d\n",
+		     ring->head_addr, ring->head, ring->tail);
+		return NULL;
+	}
+
+      _freelist_entry_found:
+	ptr = dev_priv->free_list.next;
+	list_del(ptr);
+	entry = list_entry(ptr, drm_mach64_freelist_t, list);
+	entry->buf->used = 0;
+	list_add_tail(ptr, &dev_priv->placeholders);
+	return entry->buf;
+}
+
+int mach64_freelist_put(drm_mach64_private_t * dev_priv, drm_buf_t * copy_buf)
+{
+	struct list_head *ptr;
+	drm_mach64_freelist_t *entry;
+
+#if MACH64_EXTRA_CHECKING
+	list_for_each(ptr, &dev_priv->pending) {
+		entry = list_entry(ptr, drm_mach64_freelist_t, list);
+		if (copy_buf == entry->buf) {
+			DRM_ERROR("%s: Trying to release a pending buf\n",
+			     __FUNCTION__);
+			return DRM_ERR(EFAULT);
+		}
+	}
+#endif
+	ptr = dev_priv->placeholders.next;
+	entry = list_entry(ptr, drm_mach64_freelist_t, list);
+	copy_buf->pending = 0;
+	copy_buf->used = 0;
+	entry->buf = copy_buf;
+	entry->discard = 1;
+	list_del(ptr);
+	list_add_tail(ptr, &dev_priv->free_list);
+
+	return 0;
+}
+
+/*@}*/
+
+
+/*******************************************************************/
+/** \name DMA buffer request and submission IOCTL handler */
+/*@{*/
+
+static int mach64_dma_get_buffers(DRMFILE filp, drm_device_t * dev,
+				  drm_dma_t * d)
+{
+	int i;
+	drm_buf_t *buf;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+
+	for (i = d->granted_count; i < d->request_count; i++) {
+		buf = mach64_freelist_get(dev_priv);
+#if MACH64_EXTRA_CHECKING
+		if (!buf)
+			return DRM_ERR(EFAULT);
+#else
+		if (!buf)
+			return DRM_ERR(EAGAIN);
+#endif
+
+		buf->filp = filp;
+
+		if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+				     sizeof(buf->idx)))
+			return DRM_ERR(EFAULT);
+		if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+				     sizeof(buf->total)))
+			return DRM_ERR(EFAULT);
+
+		d->granted_count++;
+	}
+	return 0;
+}
+
+int mach64_dma_buffers(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_device_dma_t *dma = dev->dma;
+	drm_dma_t d;
+	int ret = 0;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(d, (drm_dma_t *) data, sizeof(d));
+
+	/* Please don't send us buffers.
+	 */
+	if (d.send_count != 0) {
+		DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+			  DRM_CURRENTPID, d.send_count);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* We'll send you buffers.
+	 */
+	if (d.request_count < 0 || d.request_count > dma->buf_count) {
+		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+			  DRM_CURRENTPID, d.request_count, dma->buf_count);
+		ret = DRM_ERR(EINVAL);
+	}
+
+	d.granted_count = 0;
+
+	if (d.request_count) {
+		ret = mach64_dma_get_buffers(filp, dev, &d);
+	}
+
+	DRM_COPY_TO_USER_IOCTL((drm_dma_t *) data, d, sizeof(d));
+
+	return ret;
+}
+
+void mach64_driver_lastclose(drm_device_t * dev)
+{
+	mach64_do_cleanup_dma(dev);
+}
+
+/*@}*/
--- libdrm-2.3.0.orig/shared-core/mga_state.c
+++ libdrm-2.3.0/shared-core/mga_state.c
@@ -0,0 +1,1178 @@
+/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*-
+ * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com
+ */
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * VA LINUX SYSTEMS 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.
+ *
+ * Authors:
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * Rewritten by:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+
+/* ================================================================
+ * DMA hardware state programming functions
+ */
+
+static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
+			       drm_clip_rect_t * box)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	unsigned int pitch = dev_priv->front_pitch;
+	DMA_LOCALS;
+
+	BEGIN_DMA(2);
+
+	/* Force reset of DWGCTL on G400 (eliminates clip disable bit).
+	 */
+	if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
+		DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl,
+			  MGA_LEN + MGA_EXEC, 0x80000000,
+			  MGA_DWGCTL, ctx->dwgctl,
+			  MGA_LEN + MGA_EXEC, 0x80000000);
+	}
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+		  MGA_YTOP, box->y1 * pitch,
+		  MGA_YBOT, (box->y2 - 1) * pitch);
+
+	ADVANCE_DMA();
+}
+
+static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	DMA_LOCALS;
+
+	BEGIN_DMA(3);
+
+	DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
+		  MGA_MACCESS, ctx->maccess,
+		  MGA_PLNWT, ctx->plnwt,
+		  MGA_DWGCTL, ctx->dwgctl);
+
+	DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
+		  MGA_FOGCOL, ctx->fogcolor,
+		  MGA_WFLAG, ctx->wflag,
+		  MGA_ZORG, dev_priv->depth_offset);
+
+	DMA_BLOCK(MGA_FCOL, ctx->fcol,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000);
+
+	ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	DMA_LOCALS;
+
+	BEGIN_DMA(4);
+
+	DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
+		  MGA_MACCESS, ctx->maccess,
+		  MGA_PLNWT, ctx->plnwt,
+		  MGA_DWGCTL, ctx->dwgctl);
+
+	DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
+		  MGA_FOGCOL, ctx->fogcolor,
+		  MGA_WFLAG, ctx->wflag,
+		  MGA_ZORG, dev_priv->depth_offset);
+
+	DMA_BLOCK(MGA_WFLAG1, ctx->wflag,
+		  MGA_TDUALSTAGE0, ctx->tdualstage0,
+		  MGA_TDUALSTAGE1, ctx->tdualstage1,
+		  MGA_FCOL, ctx->fcol);
+
+	DMA_BLOCK(MGA_STENCIL, ctx->stencil,
+		  MGA_STENCILCTL, ctx->stencilctl,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000);
+
+	ADVANCE_DMA();
+}
+
+static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+	DMA_LOCALS;
+
+	BEGIN_DMA(4);
+
+	DMA_BLOCK(MGA_TEXCTL2, tex->texctl2,
+		  MGA_TEXCTL, tex->texctl,
+		  MGA_TEXFILTER, tex->texfilter,
+		  MGA_TEXBORDERCOL, tex->texbordercol);
+
+	DMA_BLOCK(MGA_TEXORG, tex->texorg,
+		  MGA_TEXORG1, tex->texorg1,
+		  MGA_TEXORG2, tex->texorg2,
+		  MGA_TEXORG3, tex->texorg3);
+
+	DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
+		  MGA_TEXWIDTH, tex->texwidth,
+		  MGA_TEXHEIGHT, tex->texheight,
+		  MGA_WR24, tex->texwidth);
+
+	DMA_BLOCK(MGA_WR34, tex->texheight,
+		  MGA_TEXTRANS, 0x0000ffff,
+		  MGA_TEXTRANSHIGH, 0x0000ffff,
+		  MGA_DMAPAD, 0x00000000);
+
+	ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+	DMA_LOCALS;
+
+/*  	printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */
+/*  	       tex->texctl, tex->texctl2); */
+
+	BEGIN_DMA(6);
+
+	DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
+		  MGA_TEXCTL, tex->texctl,
+		  MGA_TEXFILTER, tex->texfilter,
+		  MGA_TEXBORDERCOL, tex->texbordercol);
+
+	DMA_BLOCK(MGA_TEXORG, tex->texorg,
+		  MGA_TEXORG1, tex->texorg1,
+		  MGA_TEXORG2, tex->texorg2,
+		  MGA_TEXORG3, tex->texorg3);
+
+	DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
+		  MGA_TEXWIDTH, tex->texwidth,
+		  MGA_TEXHEIGHT, tex->texheight,
+		  MGA_WR49, 0x00000000);
+
+	DMA_BLOCK(MGA_WR57, 0x00000000,
+		  MGA_WR53, 0x00000000,
+		  MGA_WR61, 0x00000000,
+		  MGA_WR52, MGA_G400_WR_MAGIC);
+
+	DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC,
+		  MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
+		  MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
+		  MGA_DMAPAD, 0x00000000);
+
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_TEXTRANS, 0x0000ffff,
+		  MGA_TEXTRANSHIGH, 0x0000ffff);
+
+	ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
+	DMA_LOCALS;
+
+/*  	printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg,  */
+/*  	       tex->texctl, tex->texctl2); */
+
+	BEGIN_DMA(5);
+
+	DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 |
+				MGA_MAP1_ENABLE |
+				MGA_G400_TC2_MAGIC),
+		  MGA_TEXCTL, tex->texctl,
+		  MGA_TEXFILTER, tex->texfilter,
+		  MGA_TEXBORDERCOL, tex->texbordercol);
+
+	DMA_BLOCK(MGA_TEXORG, tex->texorg,
+		  MGA_TEXORG1, tex->texorg1,
+		  MGA_TEXORG2, tex->texorg2,
+		  MGA_TEXORG3, tex->texorg3);
+
+	DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
+		  MGA_TEXWIDTH, tex->texwidth,
+		  MGA_TEXHEIGHT, tex->texheight,
+		  MGA_WR49, 0x00000000);
+
+	DMA_BLOCK(MGA_WR57, 0x00000000,
+		  MGA_WR53, 0x00000000,
+		  MGA_WR61, 0x00000000,
+		  MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC);
+
+	DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
+		  MGA_TEXTRANS, 0x0000ffff,
+		  MGA_TEXTRANSHIGH, 0x0000ffff,
+		  MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC);
+
+	ADVANCE_DMA();
+}
+
+static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	unsigned int pipe = sarea_priv->warp_pipe;
+	DMA_LOCALS;
+
+	BEGIN_DMA(3);
+
+	DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND,
+		  MGA_WVRTXSZ, 0x00000007,
+		  MGA_WFLAG, 0x00000000,
+		  MGA_WR24, 0x00000000);
+
+	DMA_BLOCK(MGA_WR25, 0x00000100,
+		  MGA_WR34, 0x00000000,
+		  MGA_WR42, 0x0000ffff,
+		  MGA_WR60, 0x0000ffff);
+
+	/* Padding required to to hardware bug.
+	 */
+	DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+		  MGA_DMAPAD, 0xffffffff,
+		  MGA_DMAPAD, 0xffffffff,
+		  MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
+			       MGA_WMODE_START | dev_priv->wagp_enable));
+
+	ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	unsigned int pipe = sarea_priv->warp_pipe;
+	DMA_LOCALS;
+
+/*  	printk("mga_g400_emit_pipe %x\n", pipe); */
+
+	BEGIN_DMA(10);
+
+	DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000);
+
+	if (pipe & MGA_T2) {
+		DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09,
+			  MGA_DMAPAD, 0x00000000,
+			  MGA_DMAPAD, 0x00000000,
+			  MGA_DMAPAD, 0x00000000);
+
+		DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
+			  MGA_WACCEPTSEQ, 0x00000000,
+			  MGA_WACCEPTSEQ, 0x00000000,
+			  MGA_WACCEPTSEQ, 0x1e000000);
+	} else {
+		if (dev_priv->warp_pipe & MGA_T2) {
+			/* Flush the WARP pipe */
+			DMA_BLOCK(MGA_YDST, 0x00000000,
+				  MGA_FXLEFT, 0x00000000,
+				  MGA_FXRIGHT, 0x00000001,
+				  MGA_DWGCTL, MGA_DWGCTL_FLUSH);
+
+			DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001,
+				  MGA_DWGSYNC, 0x00007000,
+				  MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+				  MGA_LEN + MGA_EXEC, 0x00000000);
+
+			DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX |
+						MGA_G400_TC2_MAGIC),
+				  MGA_LEN + MGA_EXEC, 0x00000000,
+				  MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+				  MGA_DMAPAD, 0x00000000);
+		}
+
+		DMA_BLOCK(MGA_WVRTXSZ, 0x00001807,
+			  MGA_DMAPAD, 0x00000000,
+			  MGA_DMAPAD, 0x00000000,
+			  MGA_DMAPAD, 0x00000000);
+
+		DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
+			  MGA_WACCEPTSEQ, 0x00000000,
+			  MGA_WACCEPTSEQ, 0x00000000,
+			  MGA_WACCEPTSEQ, 0x18000000);
+	}
+
+	DMA_BLOCK(MGA_WFLAG, 0x00000000,
+		  MGA_WFLAG1, 0x00000000,
+		  MGA_WR56, MGA_G400_WR56_MAGIC,
+		  MGA_DMAPAD, 0x00000000);
+
+	DMA_BLOCK(MGA_WR49, 0x00000000,	/* tex0              */
+		  MGA_WR57, 0x00000000,	/* tex0              */
+		  MGA_WR53, 0x00000000,	/* tex1              */
+		  MGA_WR61, 0x00000000);	/* tex1              */
+
+	DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC,	/* tex0 width        */
+		  MGA_WR62, MGA_G400_WR_MAGIC,	/* tex0 height       */
+		  MGA_WR52, MGA_G400_WR_MAGIC,	/* tex1 width        */
+		  MGA_WR60, MGA_G400_WR_MAGIC);	/* tex1 height       */
+
+	/* Padding required to to hardware bug */
+	DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+		  MGA_DMAPAD, 0xffffffff,
+		  MGA_DMAPAD, 0xffffffff,
+		  MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
+				MGA_WMODE_START | dev_priv->wagp_enable));
+
+	ADVANCE_DMA();
+}
+
+static void mga_g200_emit_state(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	unsigned int dirty = sarea_priv->dirty;
+
+	if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
+		mga_g200_emit_pipe(dev_priv);
+		dev_priv->warp_pipe = sarea_priv->warp_pipe;
+	}
+
+	if (dirty & MGA_UPLOAD_CONTEXT) {
+		mga_g200_emit_context(dev_priv);
+		sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+	}
+
+	if (dirty & MGA_UPLOAD_TEX0) {
+		mga_g200_emit_tex0(dev_priv);
+		sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+	}
+}
+
+static void mga_g400_emit_state(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	unsigned int dirty = sarea_priv->dirty;
+	int multitex = sarea_priv->warp_pipe & MGA_T2;
+
+	if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
+		mga_g400_emit_pipe(dev_priv);
+		dev_priv->warp_pipe = sarea_priv->warp_pipe;
+	}
+
+	if (dirty & MGA_UPLOAD_CONTEXT) {
+		mga_g400_emit_context(dev_priv);
+		sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+	}
+
+	if (dirty & MGA_UPLOAD_TEX0) {
+		mga_g400_emit_tex0(dev_priv);
+		sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+	}
+
+	if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
+		mga_g400_emit_tex1(dev_priv);
+		sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
+	}
+}
+
+/* ================================================================
+ * SAREA state verification
+ */
+
+/* Disallow all write destinations except the front and backbuffer.
+ */
+static int mga_verify_context(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+
+	if (ctx->dstorg != dev_priv->front_offset &&
+	    ctx->dstorg != dev_priv->back_offset) {
+		DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n",
+			  ctx->dstorg, dev_priv->front_offset,
+			  dev_priv->back_offset);
+		ctx->dstorg = 0;
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
+
+/* Disallow texture reads from PCI space.
+ */
+static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
+	unsigned int org;
+
+	org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
+
+	if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) {
+		DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit);
+		tex->texorg = 0;
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
+
+static int mga_verify_state(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	unsigned int dirty = sarea_priv->dirty;
+	int ret = 0;
+
+	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+	if (dirty & MGA_UPLOAD_CONTEXT)
+		ret |= mga_verify_context(dev_priv);
+
+	if (dirty & MGA_UPLOAD_TEX0)
+		ret |= mga_verify_tex(dev_priv, 0);
+
+	if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
+		if (dirty & MGA_UPLOAD_TEX1)
+			ret |= mga_verify_tex(dev_priv, 1);
+
+		if (dirty & MGA_UPLOAD_PIPE)
+			ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES);
+	} else {
+		if (dirty & MGA_UPLOAD_PIPE)
+			ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES);
+	}
+
+	return (ret == 0);
+}
+
+static int mga_verify_iload(drm_mga_private_t * dev_priv,
+			    unsigned int dstorg, unsigned int length)
+{
+	if (dstorg < dev_priv->texture_offset ||
+	    dstorg + length > (dev_priv->texture_offset +
+			       dev_priv->texture_size)) {
+		DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (length & MGA_ILOAD_MASK) {
+		DRM_ERROR("*** bad iload length: 0x%x\n",
+			  length & MGA_ILOAD_MASK);
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
+
+static int mga_verify_blit(drm_mga_private_t * dev_priv,
+			   unsigned int srcorg, unsigned int dstorg)
+{
+	if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
+	    (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) {
+		DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg);
+		return DRM_ERR(EINVAL);
+	}
+	return 0;
+}
+
+/* ================================================================
+ *
+ */
+
+static void mga_dma_dispatch_clear(drm_device_t * dev, drm_mga_clear_t * clear)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	int nbox = sarea_priv->nbox;
+	int i;
+	DMA_LOCALS;
+	DRM_DEBUG("\n");
+
+	BEGIN_DMA(1);
+
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DWGSYNC, 0x00007100,
+		  MGA_DWGSYNC, 0x00007000);
+
+	ADVANCE_DMA();
+
+	for (i = 0; i < nbox; i++) {
+		drm_clip_rect_t *box = &pbox[i];
+		u32 height = box->y2 - box->y1;
+
+		DRM_DEBUG("   from=%d,%d to=%d,%d\n",
+			  box->x1, box->y1, box->x2, box->y2);
+
+		if (clear->flags & MGA_FRONT) {
+			BEGIN_DMA(2);
+
+			DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+				  MGA_PLNWT, clear->color_mask,
+				  MGA_YDSTLEN, (box->y1 << 16) | height,
+				  MGA_FXBNDRY, (box->x2 << 16) | box->x1);
+
+			DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+				  MGA_FCOL, clear->clear_color,
+				  MGA_DSTORG, dev_priv->front_offset,
+				  MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
+
+			ADVANCE_DMA();
+		}
+
+		if (clear->flags & MGA_BACK) {
+			BEGIN_DMA(2);
+
+			DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+				  MGA_PLNWT, clear->color_mask,
+				  MGA_YDSTLEN, (box->y1 << 16) | height,
+				  MGA_FXBNDRY, (box->x2 << 16) | box->x1);
+
+			DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+				  MGA_FCOL, clear->clear_color,
+				  MGA_DSTORG, dev_priv->back_offset,
+				  MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
+
+			ADVANCE_DMA();
+		}
+
+		if (clear->flags & MGA_DEPTH) {
+			BEGIN_DMA(2);
+
+			DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+				  MGA_PLNWT, clear->depth_mask,
+				  MGA_YDSTLEN, (box->y1 << 16) | height,
+				  MGA_FXBNDRY, (box->x2 << 16) | box->x1);
+
+			DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+				  MGA_FCOL, clear->clear_depth,
+				  MGA_DSTORG, dev_priv->depth_offset,
+				  MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
+
+			ADVANCE_DMA();
+		}
+
+	}
+
+	BEGIN_DMA(1);
+
+	/* Force reset of DWGCTL */
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_PLNWT, ctx->plnwt,
+		  MGA_DWGCTL, ctx->dwgctl);
+
+	ADVANCE_DMA();
+
+	FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_swap(drm_device_t * dev)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	int nbox = sarea_priv->nbox;
+	int i;
+	DMA_LOCALS;
+	DRM_DEBUG("\n");
+
+	sarea_priv->last_frame.head = dev_priv->prim.tail;
+	sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
+
+	BEGIN_DMA(4 + nbox);
+
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DWGSYNC, 0x00007100,
+		  MGA_DWGSYNC, 0x00007000);
+
+	DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset,
+		  MGA_MACCESS, dev_priv->maccess,
+		  MGA_SRCORG, dev_priv->back_offset,
+		  MGA_AR5, dev_priv->front_pitch);
+
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_PLNWT, 0xffffffff,
+		  MGA_DWGCTL, MGA_DWGCTL_COPY);
+
+	for (i = 0; i < nbox; i++) {
+		drm_clip_rect_t *box = &pbox[i];
+		u32 height = box->y2 - box->y1;
+		u32 start = box->y1 * dev_priv->front_pitch;
+
+		DRM_DEBUG("   from=%d,%d to=%d,%d\n",
+			  box->x1, box->y1, box->x2, box->y2);
+
+		DMA_BLOCK(MGA_AR0, start + box->x2 - 1,
+			  MGA_AR3, start + box->x1,
+			  MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+			  MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height);
+	}
+
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_PLNWT, ctx->plnwt,
+		  MGA_SRCORG, dev_priv->front_offset,
+		  MGA_DWGCTL, ctx->dwgctl);
+
+	ADVANCE_DMA();
+
+	FLUSH_DMA();
+
+	DRM_DEBUG("%s... done.\n", __FUNCTION__);
+}
+
+static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	u32 address = (u32) buf->bus_address;
+	u32 length = (u32) buf->used;
+	int i = 0;
+	DMA_LOCALS;
+	DRM_DEBUG("vertex: buf=%d used=%d\n", buf->idx, buf->used);
+
+	if (buf->used) {
+		buf_priv->dispatched = 1;
+
+		MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
+
+		do {
+			if (i < sarea_priv->nbox) {
+				mga_emit_clip_rect(dev_priv,
+						   &sarea_priv->boxes[i]);
+			}
+
+			BEGIN_DMA(1);
+
+			DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+				  MGA_DMAPAD, 0x00000000,
+				  MGA_SECADDRESS, (address |
+						   MGA_DMA_VERTEX),
+				  MGA_SECEND, ((address + length) |
+					       dev_priv->dma_access));
+
+			ADVANCE_DMA();
+		} while (++i < sarea_priv->nbox);
+	}
+
+	if (buf_priv->discard) {
+		AGE_BUFFER(buf_priv);
+		buf->pending = 0;
+		buf->used = 0;
+		buf_priv->dispatched = 0;
+
+		mga_freelist_put(dev, buf);
+	}
+
+	FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_indices(drm_device_t * dev, drm_buf_t * buf,
+				     unsigned int start, unsigned int end)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	u32 address = (u32) buf->bus_address;
+	int i = 0;
+	DMA_LOCALS;
+	DRM_DEBUG("indices: buf=%d start=%d end=%d\n", buf->idx, start, end);
+
+	if (start != end) {
+		buf_priv->dispatched = 1;
+
+		MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
+
+		do {
+			if (i < sarea_priv->nbox) {
+				mga_emit_clip_rect(dev_priv,
+						   &sarea_priv->boxes[i]);
+			}
+
+			BEGIN_DMA(1);
+
+			DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+				  MGA_DMAPAD, 0x00000000,
+				  MGA_SETUPADDRESS, address + start,
+				  MGA_SETUPEND, ((address + end) |
+						 dev_priv->dma_access));
+
+			ADVANCE_DMA();
+		} while (++i < sarea_priv->nbox);
+	}
+
+	if (buf_priv->discard) {
+		AGE_BUFFER(buf_priv);
+		buf->pending = 0;
+		buf->used = 0;
+		buf_priv->dispatched = 0;
+
+		mga_freelist_put(dev, buf);
+	}
+
+	FLUSH_DMA();
+}
+
+/* This copies a 64 byte aligned agp region to the frambuffer with a
+ * standard blit, the ioctl needs to do checking.
+ */
+static void mga_dma_dispatch_iload(drm_device_t * dev, drm_buf_t * buf,
+				   unsigned int dstorg, unsigned int length)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+	drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
+	u32 srcorg = buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
+	u32 y2;
+	DMA_LOCALS;
+	DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
+
+	y2 = length / 64;
+
+	BEGIN_DMA(5);
+
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DWGSYNC, 0x00007100,
+		  MGA_DWGSYNC, 0x00007000);
+
+	DMA_BLOCK(MGA_DSTORG, dstorg,
+		  MGA_MACCESS, 0x00000000,
+		  MGA_SRCORG, srcorg,
+		  MGA_AR5, 64);
+
+	DMA_BLOCK(MGA_PITCH, 64,
+		  MGA_PLNWT, 0xffffffff,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DWGCTL, MGA_DWGCTL_COPY);
+
+	DMA_BLOCK(MGA_AR0, 63,
+		  MGA_AR3, 0,
+		  MGA_FXBNDRY, (63 << 16) | 0,
+		  MGA_YDSTLEN + MGA_EXEC, y2);
+
+	DMA_BLOCK(MGA_PLNWT, ctx->plnwt,
+		  MGA_SRCORG, dev_priv->front_offset,
+		  MGA_PITCH, dev_priv->front_pitch,
+		  MGA_DWGSYNC, 0x00007000);
+
+	ADVANCE_DMA();
+
+	AGE_BUFFER(buf_priv);
+
+	buf->pending = 0;
+	buf->used = 0;
+	buf_priv->dispatched = 0;
+
+	mga_freelist_put(dev, buf);
+
+	FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_blit(drm_device_t * dev, drm_mga_blit_t * blit)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	int nbox = sarea_priv->nbox;
+	u32 scandir = 0, i;
+	DMA_LOCALS;
+	DRM_DEBUG("\n");
+
+	BEGIN_DMA(4 + nbox);
+
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DWGSYNC, 0x00007100,
+		  MGA_DWGSYNC, 0x00007000);
+
+	DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY,
+		  MGA_PLNWT, blit->planemask,
+		  MGA_SRCORG, blit->srcorg,
+		  MGA_DSTORG, blit->dstorg);
+
+	DMA_BLOCK(MGA_SGN, scandir,
+		  MGA_MACCESS, dev_priv->maccess,
+		  MGA_AR5, blit->ydir * blit->src_pitch,
+		  MGA_PITCH, blit->dst_pitch);
+
+	for (i = 0; i < nbox; i++) {
+		int srcx = pbox[i].x1 + blit->delta_sx;
+		int srcy = pbox[i].y1 + blit->delta_sy;
+		int dstx = pbox[i].x1 + blit->delta_dx;
+		int dsty = pbox[i].y1 + blit->delta_dy;
+		int h = pbox[i].y2 - pbox[i].y1;
+		int w = pbox[i].x2 - pbox[i].x1 - 1;
+		int start;
+
+		if (blit->ydir == -1) {
+			srcy = blit->height - srcy - 1;
+		}
+
+		start = srcy * blit->src_pitch + srcx;
+
+		DMA_BLOCK(MGA_AR0, start + w,
+			  MGA_AR3, start,
+			  MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
+			  MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h);
+	}
+
+	/* Do something to flush AGP?
+	 */
+
+	/* Force reset of DWGCTL */
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_PLNWT, ctx->plnwt,
+		  MGA_PITCH, dev_priv->front_pitch,
+		  MGA_DWGCTL, ctx->dwgctl);
+
+	ADVANCE_DMA();
+}
+
+/* ================================================================
+ *
+ */
+
+static int mga_dma_clear(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_clear_t clear;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(clear, (drm_mga_clear_t __user *) data,
+				 sizeof(clear));
+
+	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+	WRAP_TEST_WITH_RETURN(dev_priv);
+
+	mga_dma_dispatch_clear(dev, &clear);
+
+	/* Make sure we restore the 3D state next time.
+	 */
+	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+	return 0;
+}
+
+static int mga_dma_swap(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+	WRAP_TEST_WITH_RETURN(dev_priv);
+
+	mga_dma_dispatch_swap(dev);
+
+	/* Make sure we restore the 3D state next time.
+	 */
+	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+	return 0;
+}
+
+static int mga_dma_vertex(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_mga_buf_priv_t *buf_priv;
+	drm_mga_vertex_t vertex;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(vertex,
+				 (drm_mga_vertex_t __user *) data,
+				 sizeof(vertex));
+
+	if (vertex.idx < 0 || vertex.idx > dma->buf_count)
+		return DRM_ERR(EINVAL);
+	buf = dma->buflist[vertex.idx];
+	buf_priv = buf->dev_private;
+
+	buf->used = vertex.used;
+	buf_priv->discard = vertex.discard;
+
+	if (!mga_verify_state(dev_priv)) {
+		if (vertex.discard) {
+			if (buf_priv->dispatched == 1)
+				AGE_BUFFER(buf_priv);
+			buf_priv->dispatched = 0;
+			mga_freelist_put(dev, buf);
+		}
+		return DRM_ERR(EINVAL);
+	}
+
+	WRAP_TEST_WITH_RETURN(dev_priv);
+
+	mga_dma_dispatch_vertex(dev, buf);
+
+	return 0;
+}
+
+static int mga_dma_indices(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_mga_buf_priv_t *buf_priv;
+	drm_mga_indices_t indices;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(indices,
+				 (drm_mga_indices_t __user *) data,
+				 sizeof(indices));
+
+	if (indices.idx < 0 || indices.idx > dma->buf_count)
+		return DRM_ERR(EINVAL);
+
+	buf = dma->buflist[indices.idx];
+	buf_priv = buf->dev_private;
+
+	buf_priv->discard = indices.discard;
+
+	if (!mga_verify_state(dev_priv)) {
+		if (indices.discard) {
+			if (buf_priv->dispatched == 1)
+				AGE_BUFFER(buf_priv);
+			buf_priv->dispatched = 0;
+			mga_freelist_put(dev, buf);
+		}
+		return DRM_ERR(EINVAL);
+	}
+
+	WRAP_TEST_WITH_RETURN(dev_priv);
+
+	mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
+
+	return 0;
+}
+
+static int mga_dma_iload(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_device_dma_t *dma = dev->dma;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_buf_t *buf;
+	drm_mga_buf_priv_t *buf_priv;
+	drm_mga_iload_t iload;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(iload, (drm_mga_iload_t __user *) data,
+				 sizeof(iload));
+
+#if 0
+	if (mga_do_wait_for_idle(dev_priv) < 0) {
+		if (MGA_DMA_DEBUG)
+			DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
+		return DRM_ERR(EBUSY);
+	}
+#endif
+	if (iload.idx < 0 || iload.idx > dma->buf_count)
+		return DRM_ERR(EINVAL);
+
+	buf = dma->buflist[iload.idx];
+	buf_priv = buf->dev_private;
+
+	if (mga_verify_iload(dev_priv, iload.dstorg, iload.length)) {
+		mga_freelist_put(dev, buf);
+		return DRM_ERR(EINVAL);
+	}
+
+	WRAP_TEST_WITH_RETURN(dev_priv);
+
+	mga_dma_dispatch_iload(dev, buf, iload.dstorg, iload.length);
+
+	/* Make sure we restore the 3D state next time.
+	 */
+	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+	return 0;
+}
+
+static int mga_dma_blit(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_blit_t blit;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(blit, (drm_mga_blit_t __user *) data,
+				 sizeof(blit));
+
+	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+	if (mga_verify_blit(dev_priv, blit.srcorg, blit.dstorg))
+		return DRM_ERR(EINVAL);
+
+	WRAP_TEST_WITH_RETURN(dev_priv);
+
+	mga_dma_dispatch_blit(dev, &blit);
+
+	/* Make sure we restore the 3D state next time.
+	 */
+	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+	return 0;
+}
+
+static int mga_getparam(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_getparam_t param;
+	int value;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(param, (drm_mga_getparam_t __user *) data,
+				 sizeof(param));
+
+	DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+	switch (param.param) {
+	case MGA_PARAM_IRQ_NR:
+		value = dev->irq;
+		break;
+	case MGA_PARAM_CARD_TYPE:
+		value = dev_priv->chipset;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+static int mga_set_fence(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	u32 temp;
+	DMA_LOCALS;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+	/* I would normal do this assignment in the declaration of temp,
+	 * but dev_priv may be NULL.
+	 */
+
+	temp = dev_priv->next_fence_to_post;
+	dev_priv->next_fence_to_post++;
+
+	BEGIN_DMA(1);
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_SOFTRAP, 0x00000000);
+	ADVANCE_DMA();
+
+	DRM_COPY_TO_USER_IOCTL((u32 __user *)data, temp, sizeof(u32));
+
+	return 0;
+}
+
+static int mga_wait_fence(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	u32 fence;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32));
+
+	DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+	mga_driver_fence_wait(dev, & fence);
+
+	DRM_COPY_TO_USER_IOCTL((u32 __user *)data, fence, sizeof(u32));
+
+	return 0;
+}
+
+drm_ioctl_desc_t mga_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+
+};
+
+int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
--- libdrm-2.3.0.orig/shared-core/i915_dma.c
+++ libdrm-2.3.0/shared-core/i915_dma.c
@@ -0,0 +1,846 @@
+/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
+ */
+/*
+ * 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.
+ * 
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#define IS_I965G(dev)  (dev->pci_device == 0x2972 || \
+			dev->pci_device == 0x2982 || \
+			dev->pci_device == 0x2992 || \
+			dev->pci_device == 0x29A2)
+
+
+/* Really want an OS-independent resettable timer.  Would like to have
+ * this loop run for (eg) 3 sec, but have the timer reset every time
+ * the head pointer changes, so that EBUSY only happens if the ring
+ * actually stalls for (eg) 3 seconds.
+ */
+int i915_wait_ring(drm_device_t * dev, int n, const char *caller)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+	u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+	int i;
+
+	for (i = 0; i < 10000; i++) {
+		ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+		ring->space = ring->head - (ring->tail + 8);
+		if (ring->space < 0)
+			ring->space += ring->Size;
+		if (ring->space >= n)
+			return 0;
+
+		dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+
+		if (ring->head != last_head)
+			i = 0;
+
+		last_head = ring->head;
+	}
+
+	return DRM_ERR(EBUSY);
+}
+
+void i915_kernel_lost_context(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+
+	ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+	ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+	ring->space = ring->head - (ring->tail + 8);
+	if (ring->space < 0)
+		ring->space += ring->Size;
+
+	if (ring->head == ring->tail)
+		dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
+}
+
+static int i915_dma_cleanup(drm_device_t * dev)
+{
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if (dev->irq)
+		drm_irq_uninstall(dev);
+
+	if (dev->dev_private) {
+		drm_i915_private_t *dev_priv =
+		    (drm_i915_private_t *) dev->dev_private;
+
+		if (dev_priv->ring.virtual_start) {
+			drm_core_ioremapfree(&dev_priv->ring.map, dev);
+		}
+
+		if (dev_priv->status_page_dmah) {
+			drm_pci_free(dev, dev_priv->status_page_dmah);
+			/* Need to rewrite hardware status page */
+			I915_WRITE(0x02080, 0x1ffff000);
+		}
+
+		drm_free(dev->dev_private, sizeof(drm_i915_private_t),
+			 DRM_MEM_DRIVER);
+
+		dev->dev_private = NULL;
+	}
+
+	return 0;
+}
+
+static int i915_initialize(drm_device_t * dev,
+			   drm_i915_private_t * dev_priv,
+			   drm_i915_init_t * init)
+{
+	memset(dev_priv, 0, sizeof(drm_i915_private_t));
+
+	DRM_GETSAREA();
+	if (!dev_priv->sarea) {
+		DRM_ERROR("can not find sarea!\n");
+		dev->dev_private = (void *)dev_priv;
+		i915_dma_cleanup(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
+	if (!dev_priv->mmio_map) {
+		dev->dev_private = (void *)dev_priv;
+		i915_dma_cleanup(dev);
+		DRM_ERROR("can not find mmio map!\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->sarea_priv = (drm_i915_sarea_t *)
+	    ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
+
+	dev_priv->ring.Start = init->ring_start;
+	dev_priv->ring.End = init->ring_end;
+	dev_priv->ring.Size = init->ring_size;
+	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+	dev_priv->ring.map.offset = init->ring_start;
+	dev_priv->ring.map.size = init->ring_size;
+	dev_priv->ring.map.type = 0;
+	dev_priv->ring.map.flags = 0;
+	dev_priv->ring.map.mtrr = 0;
+
+	drm_core_ioremap(&dev_priv->ring.map, dev);
+
+	if (dev_priv->ring.map.handle == NULL) {
+		dev->dev_private = (void *)dev_priv;
+		i915_dma_cleanup(dev);
+		DRM_ERROR("can not ioremap virtual address for"
+			  " ring buffer\n");
+		return DRM_ERR(ENOMEM);
+	}
+
+	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+	dev_priv->cpp = init->cpp;
+	dev_priv->back_offset = init->back_offset;
+	dev_priv->front_offset = init->front_offset;
+	dev_priv->current_page = 0;
+	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+
+	/* We are using separate values as placeholders for mechanisms for
+	 * private backbuffer/depthbuffer usage.
+	 */
+	dev_priv->use_mi_batchbuffer_start = 0;
+
+	/* Allow hardware batchbuffers unless told otherwise.
+	 */
+	dev_priv->allow_batchbuffer = 1;
+
+	/* Program Hardware Status Page */
+	dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 
+	    0xffffffff);
+
+	if (!dev_priv->status_page_dmah) {
+		dev->dev_private = (void *)dev_priv;
+		i915_dma_cleanup(dev);
+		DRM_ERROR("Can not allocate hardware status page\n");
+		return DRM_ERR(ENOMEM);
+	}
+	dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+	
+	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+	I915_WRITE(0x02080, dev_priv->dma_status_page);
+	DRM_DEBUG("Enabled hardware status page\n");
+	dev->dev_private = (void *)dev_priv;
+#ifdef I915_HAVE_BUFFER
+	drm_bo_driver_init(dev);
+#endif
+	return 0;
+}
+
+static int i915_dma_resume(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	if (!dev_priv->sarea) {
+		DRM_ERROR("can not find sarea!\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (!dev_priv->mmio_map) {
+		DRM_ERROR("can not find mmio map!\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (dev_priv->ring.map.handle == NULL) {
+		DRM_ERROR("can not ioremap virtual address for"
+			  " ring buffer\n");
+		return DRM_ERR(ENOMEM);
+	}
+
+	/* Program Hardware Status Page */
+	if (!dev_priv->hw_status_page) {
+		DRM_ERROR("Can not find hardware status page\n");
+		return DRM_ERR(EINVAL);
+	}
+	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+	I915_WRITE(0x02080, dev_priv->dma_status_page);
+	DRM_DEBUG("Enabled hardware status page\n");
+
+	return 0;
+}
+
+static int i915_dma_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv;
+	drm_i915_init_t init;
+	int retcode = 0;
+
+	DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data,
+				 sizeof(init));
+
+	switch (init.func) {
+	case I915_INIT_DMA:
+		dev_priv = drm_alloc(sizeof(drm_i915_private_t),
+				     DRM_MEM_DRIVER);
+		if (dev_priv == NULL)
+			return DRM_ERR(ENOMEM);
+		retcode = i915_initialize(dev, dev_priv, &init);
+		break;
+	case I915_CLEANUP_DMA:
+		retcode = i915_dma_cleanup(dev);
+		break;
+	case I915_RESUME_DMA:
+		retcode = i915_dma_resume(dev);
+		break;
+	default:
+		retcode = -EINVAL;
+		break;
+	}
+
+	return retcode;
+}
+
+/* Implement basically the same security restrictions as hardware does
+ * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
+ *
+ * Most of the calculations below involve calculating the size of a
+ * particular instruction.  It's important to get the size right as
+ * that tells us where the next instruction to check is.  Any illegal
+ * instruction detected will be given a size of zero, which is a
+ * signal to abort the rest of the buffer.
+ */
+static int do_validate_cmd(int cmd)
+{
+	switch (((cmd >> 29) & 0x7)) {
+	case 0x0:
+		switch ((cmd >> 23) & 0x3f) {
+		case 0x0:
+			return 1;	/* MI_NOOP */
+		case 0x4:
+			return 1;	/* MI_FLUSH */
+		default:
+			return 0;	/* disallow everything else */
+		}
+		break;
+	case 0x1:
+		return 0;	/* reserved */
+	case 0x2:
+		return (cmd & 0xff) + 2;	/* 2d commands */
+	case 0x3:
+		if (((cmd >> 24) & 0x1f) <= 0x18)
+			return 1;
+
+		switch ((cmd >> 24) & 0x1f) {
+		case 0x1c:
+			return 1;
+		case 0x1d:
+			switch ((cmd >> 16) & 0xff) {
+			case 0x3:
+				return (cmd & 0x1f) + 2;
+			case 0x4:
+				return (cmd & 0xf) + 2;
+			default:
+				return (cmd & 0xffff) + 2;
+			}
+		case 0x1e:
+			if (cmd & (1 << 23))
+				return (cmd & 0xffff) + 1;
+			else
+				return 1;
+		case 0x1f:
+			if ((cmd & (1 << 23)) == 0)	/* inline vertices */
+				return (cmd & 0x1ffff) + 2;
+			else if (cmd & (1 << 17))	/* indirect random */
+				if ((cmd & 0xffff) == 0)
+					return 0;	/* unknown length, too hard */
+				else
+					return (((cmd & 0xffff) + 1) / 2) + 1;
+			else
+				return 2;	/* indirect sequential */
+		default:
+			return 0;
+		}
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int validate_cmd(int cmd)
+{
+	int ret = do_validate_cmd(cmd);
+
+/* 	printk("validate_cmd( %x ): %d\n", cmd, ret); */
+
+	return ret;
+}
+
+static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int i;
+	RING_LOCALS;
+
+	if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
+		return DRM_ERR(EINVAL);
+
+	BEGIN_LP_RING((dwords+1)&~1);
+
+	for (i = 0; i < dwords;) {
+		int cmd, sz;
+
+	     if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) {
+
+			return DRM_ERR(EINVAL);
+	      }
+		if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
+			return DRM_ERR(EINVAL);
+
+		OUT_RING(cmd);
+
+		while (++i, --sz) {
+			if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
+							 sizeof(cmd))) {
+				return DRM_ERR(EINVAL);
+			}
+			OUT_RING(cmd);
+		}
+	}
+		
+	if (dwords & 1)
+		OUT_RING(0);
+
+	ADVANCE_LP_RING();
+		
+	return 0;
+}
+
+static int i915_emit_box(drm_device_t * dev,
+			 drm_clip_rect_t __user * boxes,
+			 int i, int DR1, int DR4)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_clip_rect_t box;
+	RING_LOCALS;
+
+	if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
+		return EFAULT;
+	}
+
+	if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
+		DRM_ERROR("Bad box %d,%d..%d,%d\n",
+			  box.x1, box.y1, box.x2, box.y2);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (IS_I965G(dev)) {
+		BEGIN_LP_RING(4);
+		OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
+		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+		OUT_RING(DR4);
+		ADVANCE_LP_RING();
+	} else {
+		BEGIN_LP_RING(6);
+		OUT_RING(GFX_OP_DRAWRECT_INFO);
+		OUT_RING(DR1);
+		OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+		OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+		OUT_RING(DR4);
+		OUT_RING(0);
+		ADVANCE_LP_RING();
+	}
+
+	return 0;
+}
+
+/* XXX: Emitting the counter should really be moved to part of the IRQ
+ * emit.  For now, do it in both places:
+ */
+
+static void i915_emit_breadcrumb(drm_device_t *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+
+	BEGIN_LP_RING(4);
+	OUT_RING(CMD_STORE_DWORD_IDX);
+	OUT_RING(20);
+	OUT_RING(dev_priv->counter);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+#ifdef I915_HAVE_FENCE
+	drm_fence_flush_old(dev, dev_priv->counter);
+#endif
+}
+
+
+int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	uint32_t flush_cmd = CMD_MI_FLUSH;
+	RING_LOCALS;
+
+	flush_cmd |= flush;
+
+	i915_kernel_lost_context(dev);
+
+	BEGIN_LP_RING(4);
+	OUT_RING(flush_cmd);
+	OUT_RING(0);
+	OUT_RING(0);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	return 0;
+}
+
+
+static int i915_dispatch_cmdbuffer(drm_device_t * dev,
+				   drm_i915_cmdbuffer_t * cmd)
+{
+	int nbox = cmd->num_cliprects;
+	int i = 0, count, ret;
+
+	if (cmd->sz & 0x3) {
+		DRM_ERROR("alignment");
+		return DRM_ERR(EINVAL);
+	}
+
+	i915_kernel_lost_context(dev);
+
+	count = nbox ? nbox : 1;
+
+	for (i = 0; i < count; i++) {
+		if (i < nbox) {
+			ret = i915_emit_box(dev, cmd->cliprects, i,
+					    cmd->DR1, cmd->DR4);
+			if (ret)
+				return ret;
+		}
+
+		ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
+		if (ret)
+			return ret;
+	}
+
+	i915_emit_breadcrumb( dev );
+	return 0;
+}
+
+static int i915_dispatch_batchbuffer(drm_device_t * dev,
+				     drm_i915_batchbuffer_t * batch)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_clip_rect_t __user *boxes = batch->cliprects;
+	int nbox = batch->num_cliprects;
+	int i = 0, count;
+	RING_LOCALS;
+
+	if ((batch->start | batch->used) & 0x7) {
+		DRM_ERROR("alignment");
+		return DRM_ERR(EINVAL);
+	}
+
+	i915_kernel_lost_context(dev);
+
+	count = nbox ? nbox : 1;
+
+	for (i = 0; i < count; i++) {
+		if (i < nbox) {
+			int ret = i915_emit_box(dev, boxes, i,
+						batch->DR1, batch->DR4);
+			if (ret)
+				return ret;
+		}
+
+		if (dev_priv->use_mi_batchbuffer_start) {
+			BEGIN_LP_RING(2);
+			OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+			ADVANCE_LP_RING();
+		} else {
+			BEGIN_LP_RING(4);
+			OUT_RING(MI_BATCH_BUFFER);
+			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+			OUT_RING(batch->start + batch->used - 4);
+			OUT_RING(0);
+			ADVANCE_LP_RING();
+		}
+	}
+
+	i915_emit_breadcrumb( dev );
+	return 0;
+}
+
+static int i915_dispatch_flip(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+		  __FUNCTION__,
+		  dev_priv->current_page,
+		  dev_priv->sarea_priv->pf_current_page);
+
+	i915_kernel_lost_context(dev);
+
+	BEGIN_LP_RING(2);
+	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	BEGIN_LP_RING(6);
+	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
+	OUT_RING(0);
+	if (dev_priv->current_page == 0) {
+		OUT_RING(dev_priv->back_offset);
+		dev_priv->current_page = 1;
+	} else {
+		OUT_RING(dev_priv->front_offset);
+		dev_priv->current_page = 0;
+	}
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	BEGIN_LP_RING(2);
+	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+
+	BEGIN_LP_RING(4);
+	OUT_RING(CMD_STORE_DWORD_IDX);
+	OUT_RING(20);
+	OUT_RING(dev_priv->counter);
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+#ifdef I915_HAVE_FENCE
+	drm_fence_flush_old(dev, dev_priv->counter);
+#endif
+	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+	return 0;
+}
+
+static int i915_quiescent(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	i915_kernel_lost_context(dev);
+	return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+}
+
+static int i915_flush_ioctl(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	return i915_quiescent(dev);
+}
+
+static int i915_batchbuffer(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 *hw_status = dev_priv->hw_status_page;
+	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+	    dev_priv->sarea_priv;
+	drm_i915_batchbuffer_t batch;
+	int ret;
+
+	if (!dev_priv->allow_batchbuffer) {
+		DRM_ERROR("Batchbuffer ioctl disabled\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(batch, (drm_i915_batchbuffer_t __user *) data,
+				 sizeof(batch));
+
+	DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
+		  batch.start, batch.used, batch.num_cliprects);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects,
+						       batch.num_cliprects *
+						       sizeof(drm_clip_rect_t)))
+		return DRM_ERR(EFAULT);
+
+	ret = i915_dispatch_batchbuffer(dev, &batch);
+
+	sarea_priv->last_dispatch = (int)hw_status[5];
+	return ret;
+}
+
+static int i915_cmdbuffer(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u32 *hw_status = dev_priv->hw_status_page;
+	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+	    dev_priv->sarea_priv;
+	drm_i915_cmdbuffer_t cmdbuf;
+	int ret;
+
+	DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data,
+				 sizeof(cmdbuf));
+
+	DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
+		  cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (cmdbuf.num_cliprects &&
+	    DRM_VERIFYAREA_READ(cmdbuf.cliprects,
+				cmdbuf.num_cliprects *
+				sizeof(drm_clip_rect_t))) {
+		DRM_ERROR("Fault accessing cliprects\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	ret = i915_dispatch_cmdbuffer(dev, &cmdbuf);
+	if (ret) {
+		DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
+		return ret;
+	}
+
+	sarea_priv->last_dispatch = (int)hw_status[5];
+	return 0;
+}
+
+static int i915_do_cleanup_pageflip(drm_device_t * dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+	if (dev_priv->current_page != 0)
+		i915_dispatch_flip(dev);
+
+	return 0;
+}
+
+static int i915_flip_bufs(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	return i915_dispatch_flip(dev);
+}
+
+
+static int i915_getparam(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_getparam_t param;
+	int value;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data,
+				 sizeof(param));
+
+	switch (param.param) {
+	case I915_PARAM_IRQ_ACTIVE:
+		value = dev->irq ? 1 : 0;
+		break;
+	case I915_PARAM_ALLOW_BATCHBUFFER:
+		value = dev_priv->allow_batchbuffer ? 1 : 0;
+		break;
+	case I915_PARAM_LAST_DISPATCH:
+		value = READ_BREADCRUMB(dev_priv);
+		break;
+	default:
+		DRM_ERROR("Unknown parameter %d\n", param.param);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+		DRM_ERROR("DRM_COPY_TO_USER failed\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+static int i915_setparam(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_setparam_t param;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data,
+				 sizeof(param));
+
+	switch (param.param) {
+	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
+		dev_priv->use_mi_batchbuffer_start = param.value;
+		break;
+	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
+		dev_priv->tex_lru_log_granularity = param.value;
+		break;
+	case I915_SETPARAM_ALLOW_BATCHBUFFER:
+		dev_priv->allow_batchbuffer = param.value;
+		break;
+	default:
+		DRM_ERROR("unknown parameter %d\n", param.param);
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
+
+int i915_driver_load(drm_device_t *dev, unsigned long flags)
+{
+	/* i915 has 4 more counters */
+	dev->counters += 4;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
+	dev->types[9] = _DRM_STAT_DMA;
+
+	return 0;
+}
+
+void i915_driver_lastclose(drm_device_t * dev)
+{
+	if (dev->dev_private) {
+		drm_i915_private_t *dev_priv = dev->dev_private;
+		i915_mem_takedown(&(dev_priv->agp_heap));
+	}
+	i915_dma_cleanup(dev);
+}
+
+void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
+{
+	if (dev->dev_private) {
+		drm_i915_private_t *dev_priv = dev->dev_private;
+		if (dev_priv->page_flipping) {
+			i915_do_cleanup_pageflip(dev);
+		}
+		i915_mem_release(dev, filp, dev_priv->agp_heap);
+	}
+}
+
+drm_ioctl_desc_t i915_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
+	[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
+	[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
+	[DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH},
+};
+
+int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev   The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i9x5 is AGP.
+ */
+int i915_driver_device_is_agp(drm_device_t * dev)
+{
+	return 1;
+}
--- libdrm-2.3.0.orig/shared-core/radeon_drv.h
+++ libdrm-2.3.0/shared-core/radeon_drv.h
@@ -0,0 +1,1170 @@
+/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_DRV_H__
+#define __RADEON_DRV_H__
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR		"Gareth Hughes, Keith Whitwell, others."
+
+#define DRIVER_NAME		"radeon"
+#define DRIVER_DESC		"ATI Radeon"
+#define DRIVER_DATE		"20060524"
+
+/* Interface history:
+ *
+ * 1.1 - ??
+ * 1.2 - Add vertex2 ioctl (keith)
+ *     - Add stencil capability to clear ioctl (gareth, keith)
+ *     - Increase MAX_TEXTURE_LEVELS (brian)
+ * 1.3 - Add cmdbuf ioctl (keith)
+ *     - Add support for new radeon packets (keith)
+ *     - Add getparam ioctl (keith)
+ *     - Add flip-buffers ioctl, deprecate fullscreen foo (keith).
+ * 1.4 - Add scratch registers to get_param ioctl.
+ * 1.5 - Add r200 packets to cmdbuf ioctl
+ *     - Add r200 function to init ioctl
+ *     - Add 'scalar2' instruction to cmdbuf
+ * 1.6 - Add static GART memory manager
+ *       Add irq handler (won't be turned on unless X server knows to)
+ *       Add irq ioctls and irq_active getparam.
+ *       Add wait command for cmdbuf ioctl
+ *       Add GART offset query for getparam
+ * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5]
+ *       and R200_PP_CUBIC_OFFSET_F1_[0..5].
+ *       Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and
+ *       R200_EMIT_PP_CUBIC_OFFSETS_[0..5].  (brian)
+ * 1.8 - Remove need to call cleanup ioctls on last client exit (keith)
+ *       Add 'GET' queries for starting additional clients on different VT's.
+ * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
+ *       Add texture rectangle support for r100.
+ * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
+ *       clients use to tell the DRM where they think the framebuffer is
+ *       located in the card's address space
+ * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color
+ *       and GL_EXT_blend_[func|equation]_separate on r200
+ * 1.12- Add R300 CP microcode support - this just loads the CP on r300
+ *       (No 3D support yet - just microcode loading).
+ * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters
+ *     - Add hyperz support, add hyperz flags to clear ioctl.
+ * 1.14- Add support for color tiling
+ *     - Add R100/R200 surface allocation/free support
+ * 1.15- Add support for texture micro tiling
+ *     - Add support for r100 cube maps
+ * 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear
+ *       texture filtering on r200
+ * 1.17- Add initial support for R300 (3D).
+ * 1.18- Add support for GL_ATI_fragment_shader, new packets
+ *       R200_EMIT_PP_AFS_0/1, R200_EMIT_PP_TXCTLALL_0-5 (replaces
+ *       R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR
+ *       (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6)
+ * 1.19- Add support for gart table in FB memory and PCIE r300
+ * 1.20- Add support for r300 texrect
+ * 1.21- Add support for card type getparam
+ * 1.22- Add support for texture cache flushes (R300_TX_CNTL)
+ * 1.23- Add new radeon memory map work from benh
+ * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
+ * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
+ *       new packet type)
+ */
+
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		25
+#define DRIVER_PATCHLEVEL	0
+
+/*
+ * Radeon chip families
+ */
+enum radeon_family {
+	CHIP_R100,
+	CHIP_RV100,
+	CHIP_RS100,
+	CHIP_RV200,
+	CHIP_RS200,
+	CHIP_R200,
+	CHIP_RV250,
+	CHIP_RS300,
+	CHIP_RV280,
+	CHIP_R300,
+	CHIP_R350,
+	CHIP_RV350,
+	CHIP_RV380,
+	CHIP_R420,
+	CHIP_RV410,
+	CHIP_RS400,
+	CHIP_LAST,
+};
+
+enum radeon_cp_microcode_version {
+	UCODE_R100,
+	UCODE_R200,
+	UCODE_R300,
+};
+
+/*
+ * Chip flags
+ */
+enum radeon_chip_flags {
+	RADEON_FAMILY_MASK = 0x0000ffffUL,
+	RADEON_FLAGS_MASK = 0xffff0000UL,
+	RADEON_IS_MOBILITY = 0x00010000UL,
+	RADEON_IS_IGP = 0x00020000UL,
+	RADEON_SINGLE_CRTC = 0x00040000UL,
+	RADEON_IS_AGP = 0x00080000UL,
+	RADEON_HAS_HIERZ = 0x00100000UL,
+	RADEON_IS_PCIE = 0x00200000UL,
+	RADEON_NEW_MEMMAP = 0x00400000UL,
+	RADEON_IS_PCI = 0x00800000UL,
+};
+
+#define GET_RING_HEAD(dev_priv)	(dev_priv->writeback_works ? \
+        DRM_READ32(  (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR))
+#define SET_RING_HEAD(dev_priv,val)	DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
+
+typedef struct drm_radeon_freelist {
+	unsigned int age;
+	drm_buf_t *buf;
+	struct drm_radeon_freelist *next;
+	struct drm_radeon_freelist *prev;
+} drm_radeon_freelist_t;
+
+typedef struct drm_radeon_ring_buffer {
+	u32 *start;
+	u32 *end;
+	int size;
+	int size_l2qw;
+
+	u32 tail;
+	u32 tail_mask;
+	int space;
+
+	int high_mark;
+} drm_radeon_ring_buffer_t;
+
+typedef struct drm_radeon_depth_clear_t {
+	u32 rb3d_cntl;
+	u32 rb3d_zstencilcntl;
+	u32 se_cntl;
+} drm_radeon_depth_clear_t;
+
+struct drm_radeon_driver_file_fields {
+	int64_t radeon_fb_delta;
+};
+
+struct mem_block {
+	struct mem_block *next;
+	struct mem_block *prev;
+	int start;
+	int size;
+	DRMFILE filp;		/* 0: free, -1: heap, other: real files */
+};
+
+struct radeon_surface {
+	int refcount;
+	u32 lower;
+	u32 upper;
+	u32 flags;
+};
+
+struct radeon_virt_surface {
+	int surface_index;
+	u32 lower;
+	u32 upper;
+	u32 flags;
+	DRMFILE filp;
+};
+
+typedef struct drm_radeon_private {
+
+	drm_radeon_ring_buffer_t ring;
+	drm_radeon_sarea_t *sarea_priv;
+
+	u32 fb_location;
+	u32 fb_size;
+	int new_memmap;
+
+	int gart_size;
+	u32 gart_vm_start;
+	unsigned long gart_buffers_offset;
+
+	int cp_mode;
+	int cp_running;
+
+	drm_radeon_freelist_t *head;
+	drm_radeon_freelist_t *tail;
+	int last_buf;
+	volatile u32 *scratch;
+	int writeback_works;
+
+	int usec_timeout;
+
+	int microcode_version;
+
+	struct {
+		u32 boxes;
+		int freelist_timeouts;
+		int freelist_loops;
+		int requested_bufs;
+		int last_frame_reads;
+		int last_clear_reads;
+		int clears;
+		int texture_uploads;
+	} stats;
+
+	int do_boxes;
+	int page_flipping;
+	int current_page;
+
+	u32 color_fmt;
+	unsigned int front_offset;
+	unsigned int front_pitch;
+	unsigned int back_offset;
+	unsigned int back_pitch;
+
+	u32 depth_fmt;
+	unsigned int depth_offset;
+	unsigned int depth_pitch;
+
+	u32 front_pitch_offset;
+	u32 back_pitch_offset;
+	u32 depth_pitch_offset;
+
+	drm_radeon_depth_clear_t depth_clear;
+
+	unsigned long ring_offset;
+	unsigned long ring_rptr_offset;
+	unsigned long buffers_offset;
+	unsigned long gart_textures_offset;
+
+	drm_local_map_t *sarea;
+	drm_local_map_t *mmio;
+	drm_local_map_t *cp_ring;
+	drm_local_map_t *ring_rptr;
+	drm_local_map_t *gart_textures;
+
+	struct mem_block *gart_heap;
+	struct mem_block *fb_heap;
+
+	/* SW interrupt */
+	wait_queue_head_t swi_queue;
+	atomic_t swi_emitted;
+
+	struct radeon_surface surfaces[RADEON_MAX_SURFACES];
+	struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES];
+
+	unsigned long pcigart_offset;
+	drm_ati_pcigart_info gart_info;
+
+	u32 scratch_ages[5];
+
+	/* starting from here on, data is preserved accross an open */
+	uint32_t flags;		/* see radeon_chip_flags */
+
+} drm_radeon_private_t;
+
+typedef struct drm_radeon_buf_priv {
+	u32 age;
+} drm_radeon_buf_priv_t;
+
+typedef struct drm_radeon_kcmd_buffer {
+	int bufsz;
+	char *buf;
+	int nbox;
+	drm_clip_rect_t __user *boxes;
+} drm_radeon_kcmd_buffer_t;
+
+extern int radeon_no_wb;
+extern drm_ioctl_desc_t radeon_ioctls[];
+extern int radeon_max_ioctl;
+
+				/* radeon_cp.c */
+extern int radeon_cp_init(DRM_IOCTL_ARGS);
+extern int radeon_cp_start(DRM_IOCTL_ARGS);
+extern int radeon_cp_stop(DRM_IOCTL_ARGS);
+extern int radeon_cp_reset(DRM_IOCTL_ARGS);
+extern int radeon_cp_idle(DRM_IOCTL_ARGS);
+extern int radeon_cp_resume(DRM_IOCTL_ARGS);
+extern int radeon_engine_reset(DRM_IOCTL_ARGS);
+extern int radeon_fullscreen(DRM_IOCTL_ARGS);
+extern int radeon_cp_buffers(DRM_IOCTL_ARGS);
+
+extern void radeon_freelist_reset(drm_device_t * dev);
+extern drm_buf_t *radeon_freelist_get(drm_device_t * dev);
+
+extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
+
+extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv);
+
+extern int radeon_mem_alloc(DRM_IOCTL_ARGS);
+extern int radeon_mem_free(DRM_IOCTL_ARGS);
+extern int radeon_mem_init_heap(DRM_IOCTL_ARGS);
+extern void radeon_mem_takedown(struct mem_block **heap);
+extern void radeon_mem_release(DRMFILE filp, struct mem_block *heap);
+
+				/* radeon_irq.c */
+extern int radeon_irq_emit(DRM_IOCTL_ARGS);
+extern int radeon_irq_wait(DRM_IOCTL_ARGS);
+
+extern void radeon_do_release(drm_device_t * dev);
+extern int radeon_driver_vblank_wait(drm_device_t * dev,
+				     unsigned int *sequence);
+extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
+extern void radeon_driver_irq_preinstall(drm_device_t * dev);
+extern void radeon_driver_irq_postinstall(drm_device_t * dev);
+extern void radeon_driver_irq_uninstall(drm_device_t * dev);
+
+extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
+extern int radeon_driver_unload(struct drm_device *dev);
+extern int radeon_driver_firstopen(struct drm_device *dev);
+extern void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp);
+extern void radeon_driver_lastclose(drm_device_t * dev);
+extern int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv);
+extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
+					 unsigned long arg);
+
+/* r300_cmdbuf.c */
+extern void r300_init_reg_flags(void);
+
+extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp,
+			     drm_file_t* filp_priv,
+			     drm_radeon_kcmd_buffer_t* cmdbuf);
+
+/* Flags for stats.boxes
+ */
+#define RADEON_BOX_DMA_IDLE      0x1
+#define RADEON_BOX_RING_FULL     0x2
+#define RADEON_BOX_FLIP          0x4
+#define RADEON_BOX_WAIT_IDLE     0x8
+#define RADEON_BOX_TEXTURE_LOAD  0x10
+
+/* Register definitions, register access macros and drmAddMap constants
+ * for Radeon kernel driver.
+ */
+#define RADEON_AGP_COMMAND		0x0f60
+#define RADEON_AGP_COMMAND_PCI_CONFIG	0x0060	/* offset in PCI config */
+#       define RADEON_AGP_ENABLE            (1<<8)
+#define RADEON_AUX_SCISSOR_CNTL		0x26f0
+#	define RADEON_EXCLUSIVE_SCISSOR_0	(1 << 24)
+#	define RADEON_EXCLUSIVE_SCISSOR_1	(1 << 25)
+#	define RADEON_EXCLUSIVE_SCISSOR_2	(1 << 26)
+#	define RADEON_SCISSOR_0_ENABLE		(1 << 28)
+#	define RADEON_SCISSOR_1_ENABLE		(1 << 29)
+#	define RADEON_SCISSOR_2_ENABLE		(1 << 30)
+
+#define RADEON_BUS_CNTL			0x0030
+#	define RADEON_BUS_MASTER_DIS		(1 << 6)
+
+#define RADEON_CLOCK_CNTL_DATA		0x000c
+#	define RADEON_PLL_WR_EN			(1 << 7)
+#define RADEON_CLOCK_CNTL_INDEX		0x0008
+#define RADEON_CONFIG_APER_SIZE		0x0108
+#define RADEON_CONFIG_MEMSIZE           0x00f8
+#define RADEON_CRTC_OFFSET		0x0224
+#define RADEON_CRTC_OFFSET_CNTL		0x0228
+#	define RADEON_CRTC_TILE_EN		(1 << 15)
+#	define RADEON_CRTC_OFFSET_FLIP_CNTL	(1 << 16)
+#define RADEON_CRTC2_OFFSET		0x0324
+#define RADEON_CRTC2_OFFSET_CNTL	0x0328
+
+#define RADEON_PCIE_INDEX               0x0030
+#define RADEON_PCIE_DATA                0x0034
+#define RADEON_PCIE_TX_GART_CNTL	0x10
+#	define RADEON_PCIE_TX_GART_EN   	(1 << 0)
+#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0<<1)
+#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO  (1<<1)
+#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD   (3<<1)
+#	define RADEON_PCIE_TX_GART_MODE_32_128_CACHE	(0<<3)
+#	define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE	(1<<3)
+#	define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN      (1<<5)
+#	define RADEON_PCIE_TX_GART_INVALIDATE_TLB	(1<<8)
+#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11
+#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12
+#define RADEON_PCIE_TX_GART_BASE  	0x13
+#define RADEON_PCIE_TX_GART_START_LO	0x14
+#define RADEON_PCIE_TX_GART_START_HI	0x15
+#define RADEON_PCIE_TX_GART_END_LO	0x16
+#define RADEON_PCIE_TX_GART_END_HI	0x17
+
+#define RADEON_MPP_TB_CONFIG		0x01c0
+#define RADEON_MEM_CNTL			0x0140
+#define RADEON_MEM_SDRAM_MODE_REG	0x0158
+#define RADEON_AGP_BASE			0x0170
+
+#define RADEON_RB3D_COLOROFFSET		0x1c40
+#define RADEON_RB3D_COLORPITCH		0x1c48
+
+#define	RADEON_SRC_X_Y			0x1590
+
+#define RADEON_DP_GUI_MASTER_CNTL	0x146c
+#	define RADEON_GMC_SRC_PITCH_OFFSET_CNTL	(1 << 0)
+#	define RADEON_GMC_DST_PITCH_OFFSET_CNTL	(1 << 1)
+#	define RADEON_GMC_BRUSH_SOLID_COLOR	(13 << 4)
+#	define RADEON_GMC_BRUSH_NONE		(15 << 4)
+#	define RADEON_GMC_DST_16BPP		(4 << 8)
+#	define RADEON_GMC_DST_24BPP		(5 << 8)
+#	define RADEON_GMC_DST_32BPP		(6 << 8)
+#	define RADEON_GMC_DST_DATATYPE_SHIFT	8
+#	define RADEON_GMC_SRC_DATATYPE_COLOR	(3 << 12)
+#	define RADEON_DP_SRC_SOURCE_MEMORY	(2 << 24)
+#	define RADEON_DP_SRC_SOURCE_HOST_DATA	(3 << 24)
+#	define RADEON_GMC_CLR_CMP_CNTL_DIS	(1 << 28)
+#	define RADEON_GMC_WR_MSK_DIS		(1 << 30)
+#	define RADEON_ROP3_S			0x00cc0000
+#	define RADEON_ROP3_P			0x00f00000
+#define RADEON_DP_WRITE_MASK		0x16cc
+#define RADEON_SRC_PITCH_OFFSET		0x1428
+#define RADEON_DST_PITCH_OFFSET		0x142c
+#define RADEON_DST_PITCH_OFFSET_C	0x1c80
+#	define RADEON_DST_TILE_LINEAR		(0 << 30)
+#	define RADEON_DST_TILE_MACRO		(1 << 30)
+#	define RADEON_DST_TILE_MICRO		(2 << 30)
+#	define RADEON_DST_TILE_BOTH		(3 << 30)
+
+#define RADEON_SCRATCH_REG0		0x15e0
+#define RADEON_SCRATCH_REG1		0x15e4
+#define RADEON_SCRATCH_REG2		0x15e8
+#define RADEON_SCRATCH_REG3		0x15ec
+#define RADEON_SCRATCH_REG4		0x15f0
+#define RADEON_SCRATCH_REG5		0x15f4
+#define RADEON_SCRATCH_UMSK		0x0770
+#define RADEON_SCRATCH_ADDR		0x0774
+
+#define RADEON_SCRATCHOFF( x )		(RADEON_SCRATCH_REG_OFFSET + 4*(x))
+
+#define GET_SCRATCH( x )	(dev_priv->writeback_works			\
+				? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
+				: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+
+#define RADEON_GEN_INT_CNTL		0x0040
+#	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
+#	define RADEON_GUI_IDLE_INT_ENABLE	(1 << 19)
+#	define RADEON_SW_INT_ENABLE		(1 << 25)
+
+#define RADEON_GEN_INT_STATUS		0x0044
+#	define RADEON_CRTC_VBLANK_STAT		(1 << 0)
+#	define RADEON_CRTC_VBLANK_STAT_ACK   	(1 << 0)
+#	define RADEON_GUI_IDLE_INT_TEST_ACK     (1 << 19)
+#	define RADEON_SW_INT_TEST		(1 << 25)
+#	define RADEON_SW_INT_TEST_ACK   	(1 << 25)
+#	define RADEON_SW_INT_FIRE		(1 << 26)
+
+#define RADEON_HOST_PATH_CNTL		0x0130
+#	define RADEON_HDP_SOFT_RESET		(1 << 26)
+#	define RADEON_HDP_WC_TIMEOUT_MASK	(7 << 28)
+#	define RADEON_HDP_WC_TIMEOUT_28BCLK	(7 << 28)
+
+#define RADEON_ISYNC_CNTL		0x1724
+#	define RADEON_ISYNC_ANY2D_IDLE3D	(1 << 0)
+#	define RADEON_ISYNC_ANY3D_IDLE2D	(1 << 1)
+#	define RADEON_ISYNC_TRIG2D_IDLE3D	(1 << 2)
+#	define RADEON_ISYNC_TRIG3D_IDLE2D	(1 << 3)
+#	define RADEON_ISYNC_WAIT_IDLEGUI	(1 << 4)
+#	define RADEON_ISYNC_CPSCRATCH_IDLEGUI	(1 << 5)
+
+#define RADEON_RBBM_GUICNTL		0x172c
+#	define RADEON_HOST_DATA_SWAP_NONE	(0 << 0)
+#	define RADEON_HOST_DATA_SWAP_16BIT	(1 << 0)
+#	define RADEON_HOST_DATA_SWAP_32BIT	(2 << 0)
+#	define RADEON_HOST_DATA_SWAP_HDW	(3 << 0)
+
+#define RADEON_MC_AGP_LOCATION		0x014c
+#define RADEON_MC_FB_LOCATION		0x0148
+#define RADEON_MCLK_CNTL		0x0012
+#	define RADEON_FORCEON_MCLKA		(1 << 16)
+#	define RADEON_FORCEON_MCLKB		(1 << 17)
+#	define RADEON_FORCEON_YCLKA		(1 << 18)
+#	define RADEON_FORCEON_YCLKB		(1 << 19)
+#	define RADEON_FORCEON_MC		(1 << 20)
+#	define RADEON_FORCEON_AIC		(1 << 21)
+
+#define RADEON_PP_BORDER_COLOR_0	0x1d40
+#define RADEON_PP_BORDER_COLOR_1	0x1d44
+#define RADEON_PP_BORDER_COLOR_2	0x1d48
+#define RADEON_PP_CNTL			0x1c38
+#	define RADEON_SCISSOR_ENABLE		(1 <<  1)
+#define RADEON_PP_LUM_MATRIX		0x1d00
+#define RADEON_PP_MISC			0x1c14
+#define RADEON_PP_ROT_MATRIX_0		0x1d58
+#define RADEON_PP_TXFILTER_0		0x1c54
+#define RADEON_PP_TXOFFSET_0		0x1c5c
+#define RADEON_PP_TXFILTER_1		0x1c6c
+#define RADEON_PP_TXFILTER_2		0x1c84
+
+#define RADEON_RB2D_DSTCACHE_CTLSTAT	0x342c
+#	define RADEON_RB2D_DC_FLUSH		(3 << 0)
+#	define RADEON_RB2D_DC_FREE		(3 << 2)
+#	define RADEON_RB2D_DC_FLUSH_ALL		0xf
+#	define RADEON_RB2D_DC_BUSY		(1 << 31)
+#define RADEON_RB3D_CNTL		0x1c3c
+#	define RADEON_ALPHA_BLEND_ENABLE	(1 << 0)
+#	define RADEON_PLANE_MASK_ENABLE		(1 << 1)
+#	define RADEON_DITHER_ENABLE		(1 << 2)
+#	define RADEON_ROUND_ENABLE		(1 << 3)
+#	define RADEON_SCALE_DITHER_ENABLE	(1 << 4)
+#	define RADEON_DITHER_INIT		(1 << 5)
+#	define RADEON_ROP_ENABLE		(1 << 6)
+#	define RADEON_STENCIL_ENABLE		(1 << 7)
+#	define RADEON_Z_ENABLE			(1 << 8)
+#	define RADEON_ZBLOCK16			(1 << 15)
+#define RADEON_RB3D_DEPTHOFFSET		0x1c24
+#define RADEON_RB3D_DEPTHCLEARVALUE	0x3230
+#define RADEON_RB3D_DEPTHPITCH		0x1c28
+#define RADEON_RB3D_PLANEMASK		0x1d84
+#define RADEON_RB3D_STENCILREFMASK	0x1d7c
+#define RADEON_RB3D_ZCACHE_MODE		0x3250
+#define RADEON_RB3D_ZCACHE_CTLSTAT	0x3254
+#	define RADEON_RB3D_ZC_FLUSH		(1 << 0)
+#	define RADEON_RB3D_ZC_FREE		(1 << 2)
+#	define RADEON_RB3D_ZC_FLUSH_ALL		0x5
+#	define RADEON_RB3D_ZC_BUSY		(1 << 31)
+#define RADEON_RB3D_DSTCACHE_CTLSTAT            0x325c
+#	define RADEON_RB3D_DC_FLUSH		(3 << 0)
+#	define RADEON_RB3D_DC_FREE		(3 << 2)
+#	define RADEON_RB3D_DC_FLUSH_ALL		0xf
+#	define RADEON_RB3D_DC_BUSY		(1 << 31)
+#define RADEON_RB3D_ZSTENCILCNTL	0x1c2c
+#	define RADEON_Z_TEST_MASK		(7 << 4)
+#	define RADEON_Z_TEST_ALWAYS		(7 << 4)
+#	define RADEON_Z_HIERARCHY_ENABLE        (1 << 8)
+#	define RADEON_STENCIL_TEST_ALWAYS	(7 << 12)
+#	define RADEON_STENCIL_S_FAIL_REPLACE	(2 << 16)
+#	define RADEON_STENCIL_ZPASS_REPLACE	(2 << 20)
+#	define RADEON_STENCIL_ZFAIL_REPLACE	(2 << 24)
+#	define RADEON_Z_COMPRESSION_ENABLE      (1 << 28)
+#	define RADEON_FORCE_Z_DIRTY             (1 << 29)
+#	define RADEON_Z_WRITE_ENABLE		(1 << 30)
+#	define RADEON_Z_DECOMPRESSION_ENABLE    (1 << 31)
+#define RADEON_RBBM_SOFT_RESET		0x00f0
+#	define RADEON_SOFT_RESET_CP		(1 <<  0)
+#	define RADEON_SOFT_RESET_HI		(1 <<  1)
+#	define RADEON_SOFT_RESET_SE		(1 <<  2)
+#	define RADEON_SOFT_RESET_RE		(1 <<  3)
+#	define RADEON_SOFT_RESET_PP		(1 <<  4)
+#	define RADEON_SOFT_RESET_E2		(1 <<  5)
+#	define RADEON_SOFT_RESET_RB		(1 <<  6)
+#	define RADEON_SOFT_RESET_HDP		(1 <<  7)
+#define RADEON_RBBM_STATUS		0x0e40
+#	define RADEON_RBBM_FIFOCNT_MASK		0x007f
+#	define RADEON_RBBM_ACTIVE		(1 << 31)
+#define RADEON_RE_LINE_PATTERN		0x1cd0
+#define RADEON_RE_MISC			0x26c4
+#define RADEON_RE_TOP_LEFT		0x26c0
+#define RADEON_RE_WIDTH_HEIGHT		0x1c44
+#define RADEON_RE_STIPPLE_ADDR		0x1cc8
+#define RADEON_RE_STIPPLE_DATA		0x1ccc
+
+#define RADEON_SCISSOR_TL_0		0x1cd8
+#define RADEON_SCISSOR_BR_0		0x1cdc
+#define RADEON_SCISSOR_TL_1		0x1ce0
+#define RADEON_SCISSOR_BR_1		0x1ce4
+#define RADEON_SCISSOR_TL_2		0x1ce8
+#define RADEON_SCISSOR_BR_2		0x1cec
+#define RADEON_SE_COORD_FMT		0x1c50
+#define RADEON_SE_CNTL			0x1c4c
+#	define RADEON_FFACE_CULL_CW		(0 << 0)
+#	define RADEON_BFACE_SOLID		(3 << 1)
+#	define RADEON_FFACE_SOLID		(3 << 3)
+#	define RADEON_FLAT_SHADE_VTX_LAST	(3 << 6)
+#	define RADEON_DIFFUSE_SHADE_FLAT	(1 << 8)
+#	define RADEON_DIFFUSE_SHADE_GOURAUD	(2 << 8)
+#	define RADEON_ALPHA_SHADE_FLAT		(1 << 10)
+#	define RADEON_ALPHA_SHADE_GOURAUD	(2 << 10)
+#	define RADEON_SPECULAR_SHADE_FLAT	(1 << 12)
+#	define RADEON_SPECULAR_SHADE_GOURAUD	(2 << 12)
+#	define RADEON_FOG_SHADE_FLAT		(1 << 14)
+#	define RADEON_FOG_SHADE_GOURAUD		(2 << 14)
+#	define RADEON_VPORT_XY_XFORM_ENABLE	(1 << 24)
+#	define RADEON_VPORT_Z_XFORM_ENABLE	(1 << 25)
+#	define RADEON_VTX_PIX_CENTER_OGL	(1 << 27)
+#	define RADEON_ROUND_MODE_TRUNC		(0 << 28)
+#	define RADEON_ROUND_PREC_8TH_PIX	(1 << 30)
+#define RADEON_SE_CNTL_STATUS		0x2140
+#define RADEON_SE_LINE_WIDTH		0x1db8
+#define RADEON_SE_VPORT_XSCALE		0x1d98
+#define RADEON_SE_ZBIAS_FACTOR		0x1db0
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210
+#define RADEON_SE_TCL_OUTPUT_VTX_FMT         0x2254
+#define RADEON_SE_TCL_VECTOR_INDX_REG        0x2200
+#       define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT  16
+#       define RADEON_VEC_INDX_DWORD_COUNT_SHIFT     28
+#define RADEON_SE_TCL_VECTOR_DATA_REG       0x2204
+#define RADEON_SE_TCL_SCALAR_INDX_REG       0x2208
+#       define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT  16
+#define RADEON_SE_TCL_SCALAR_DATA_REG       0x220C
+#define RADEON_SURFACE_ACCESS_FLAGS	0x0bf8
+#define RADEON_SURFACE_ACCESS_CLR	0x0bfc
+#define RADEON_SURFACE_CNTL		0x0b00
+#	define RADEON_SURF_TRANSLATION_DIS	(1 << 8)
+#	define RADEON_NONSURF_AP0_SWP_MASK	(3 << 20)
+#	define RADEON_NONSURF_AP0_SWP_LITTLE	(0 << 20)
+#	define RADEON_NONSURF_AP0_SWP_BIG16	(1 << 20)
+#	define RADEON_NONSURF_AP0_SWP_BIG32	(2 << 20)
+#	define RADEON_NONSURF_AP1_SWP_MASK	(3 << 22)
+#	define RADEON_NONSURF_AP1_SWP_LITTLE	(0 << 22)
+#	define RADEON_NONSURF_AP1_SWP_BIG16	(1 << 22)
+#	define RADEON_NONSURF_AP1_SWP_BIG32	(2 << 22)
+#define RADEON_SURFACE0_INFO		0x0b0c
+#	define RADEON_SURF_PITCHSEL_MASK	(0x1ff << 0)
+#	define RADEON_SURF_TILE_MODE_MASK	(3 << 16)
+#	define RADEON_SURF_TILE_MODE_MACRO	(0 << 16)
+#	define RADEON_SURF_TILE_MODE_MICRO	(1 << 16)
+#	define RADEON_SURF_TILE_MODE_32BIT_Z	(2 << 16)
+#	define RADEON_SURF_TILE_MODE_16BIT_Z	(3 << 16)
+#define RADEON_SURFACE0_LOWER_BOUND	0x0b04
+#define RADEON_SURFACE0_UPPER_BOUND	0x0b08
+#	define RADEON_SURF_ADDRESS_FIXED_MASK	(0x3ff << 0)
+#define RADEON_SURFACE1_INFO		0x0b1c
+#define RADEON_SURFACE1_LOWER_BOUND	0x0b14
+#define RADEON_SURFACE1_UPPER_BOUND	0x0b18
+#define RADEON_SURFACE2_INFO		0x0b2c
+#define RADEON_SURFACE2_LOWER_BOUND	0x0b24
+#define RADEON_SURFACE2_UPPER_BOUND	0x0b28
+#define RADEON_SURFACE3_INFO		0x0b3c
+#define RADEON_SURFACE3_LOWER_BOUND	0x0b34
+#define RADEON_SURFACE3_UPPER_BOUND	0x0b38
+#define RADEON_SURFACE4_INFO		0x0b4c
+#define RADEON_SURFACE4_LOWER_BOUND	0x0b44
+#define RADEON_SURFACE4_UPPER_BOUND	0x0b48
+#define RADEON_SURFACE5_INFO		0x0b5c
+#define RADEON_SURFACE5_LOWER_BOUND	0x0b54
+#define RADEON_SURFACE5_UPPER_BOUND	0x0b58
+#define RADEON_SURFACE6_INFO		0x0b6c
+#define RADEON_SURFACE6_LOWER_BOUND	0x0b64
+#define RADEON_SURFACE6_UPPER_BOUND	0x0b68
+#define RADEON_SURFACE7_INFO		0x0b7c
+#define RADEON_SURFACE7_LOWER_BOUND	0x0b74
+#define RADEON_SURFACE7_UPPER_BOUND	0x0b78
+#define RADEON_SW_SEMAPHORE		0x013c
+
+#define RADEON_WAIT_UNTIL		0x1720
+#	define RADEON_WAIT_CRTC_PFLIP		(1 << 0)
+#	define RADEON_WAIT_2D_IDLE		(1 << 14)
+#	define RADEON_WAIT_3D_IDLE		(1 << 15)
+#	define RADEON_WAIT_2D_IDLECLEAN		(1 << 16)
+#	define RADEON_WAIT_3D_IDLECLEAN		(1 << 17)
+#	define RADEON_WAIT_HOST_IDLECLEAN	(1 << 18)
+
+#define RADEON_RB3D_ZMASKOFFSET		0x3234
+#define RADEON_RB3D_ZSTENCILCNTL	0x1c2c
+#	define RADEON_DEPTH_FORMAT_16BIT_INT_Z	(0 << 0)
+#	define RADEON_DEPTH_FORMAT_24BIT_INT_Z	(2 << 0)
+
+/* CP registers */
+#define RADEON_CP_ME_RAM_ADDR		0x07d4
+#define RADEON_CP_ME_RAM_RADDR		0x07d8
+#define RADEON_CP_ME_RAM_DATAH		0x07dc
+#define RADEON_CP_ME_RAM_DATAL		0x07e0
+
+#define RADEON_CP_RB_BASE		0x0700
+#define RADEON_CP_RB_CNTL		0x0704
+#	define RADEON_BUF_SWAP_32BIT		(2 << 16)
+#	define RADEON_RB_NO_UPDATE		(1 << 27)
+#define RADEON_CP_RB_RPTR_ADDR		0x070c
+#define RADEON_CP_RB_RPTR		0x0710
+#define RADEON_CP_RB_WPTR		0x0714
+
+#define RADEON_CP_RB_WPTR_DELAY		0x0718
+#	define RADEON_PRE_WRITE_TIMER_SHIFT	0
+#	define RADEON_PRE_WRITE_LIMIT_SHIFT	23
+
+#define RADEON_CP_IB_BASE		0x0738
+
+#define RADEON_CP_CSQ_CNTL		0x0740
+#	define RADEON_CSQ_CNT_PRIMARY_MASK	(0xff << 0)
+#	define RADEON_CSQ_PRIDIS_INDDIS		(0 << 28)
+#	define RADEON_CSQ_PRIPIO_INDDIS		(1 << 28)
+#	define RADEON_CSQ_PRIBM_INDDIS		(2 << 28)
+#	define RADEON_CSQ_PRIPIO_INDBM		(3 << 28)
+#	define RADEON_CSQ_PRIBM_INDBM		(4 << 28)
+#	define RADEON_CSQ_PRIPIO_INDPIO		(15 << 28)
+
+#define RADEON_AIC_CNTL			0x01d0
+#	define RADEON_PCIGART_TRANSLATE_EN	(1 << 0)
+#define RADEON_AIC_STAT			0x01d4
+#define RADEON_AIC_PT_BASE		0x01d8
+#define RADEON_AIC_LO_ADDR		0x01dc
+#define RADEON_AIC_HI_ADDR		0x01e0
+#define RADEON_AIC_TLB_ADDR		0x01e4
+#define RADEON_AIC_TLB_DATA		0x01e8
+
+/* CP command packets */
+#define RADEON_CP_PACKET0		0x00000000
+#	define RADEON_ONE_REG_WR		(1 << 15)
+#define RADEON_CP_PACKET1		0x40000000
+#define RADEON_CP_PACKET2		0x80000000
+#define RADEON_CP_PACKET3		0xC0000000
+#       define RADEON_CP_NOP                    0x00001000
+#       define RADEON_CP_NEXT_CHAR              0x00001900
+#       define RADEON_CP_PLY_NEXTSCAN           0x00001D00
+#       define RADEON_CP_SET_SCISSORS           0x00001E00
+             /* GEN_INDX_PRIM is unsupported starting with R300 */
+#	define RADEON_3D_RNDR_GEN_INDX_PRIM	0x00002300
+#	define RADEON_WAIT_FOR_IDLE		0x00002600
+#	define RADEON_3D_DRAW_VBUF		0x00002800
+#	define RADEON_3D_DRAW_IMMD		0x00002900
+#	define RADEON_3D_DRAW_INDX		0x00002A00
+#       define RADEON_CP_LOAD_PALETTE           0x00002C00
+#	define RADEON_3D_LOAD_VBPNTR		0x00002F00
+#	define RADEON_MPEG_IDCT_MACROBLOCK	0x00003000
+#	define RADEON_MPEG_IDCT_MACROBLOCK_REV	0x00003100
+#	define RADEON_3D_CLEAR_ZMASK		0x00003200
+#	define RADEON_CP_INDX_BUFFER		0x00003300
+#       define RADEON_CP_3D_DRAW_VBUF_2         0x00003400
+#       define RADEON_CP_3D_DRAW_IMMD_2         0x00003500
+#       define RADEON_CP_3D_DRAW_INDX_2         0x00003600
+#	define RADEON_3D_CLEAR_HIZ		0x00003700
+#       define RADEON_CP_3D_CLEAR_CMASK         0x00003802
+#	define RADEON_CNTL_HOSTDATA_BLT		0x00009400
+#	define RADEON_CNTL_PAINT_MULTI		0x00009A00
+#	define RADEON_CNTL_BITBLT_MULTI		0x00009B00
+#	define RADEON_CNTL_SET_SCISSORS		0xC0001E00
+
+#define RADEON_CP_PACKET_MASK		0xC0000000
+#define RADEON_CP_PACKET_COUNT_MASK	0x3fff0000
+#define RADEON_CP_PACKET0_REG_MASK	0x000007ff
+#define RADEON_CP_PACKET1_REG0_MASK	0x000007ff
+#define RADEON_CP_PACKET1_REG1_MASK	0x003ff800
+
+#define RADEON_VTX_Z_PRESENT			(1 << 31)
+#define RADEON_VTX_PKCOLOR_PRESENT		(1 << 3)
+
+#define RADEON_PRIM_TYPE_NONE			(0 << 0)
+#define RADEON_PRIM_TYPE_POINT			(1 << 0)
+#define RADEON_PRIM_TYPE_LINE			(2 << 0)
+#define RADEON_PRIM_TYPE_LINE_STRIP		(3 << 0)
+#define RADEON_PRIM_TYPE_TRI_LIST		(4 << 0)
+#define RADEON_PRIM_TYPE_TRI_FAN		(5 << 0)
+#define RADEON_PRIM_TYPE_TRI_STRIP		(6 << 0)
+#define RADEON_PRIM_TYPE_TRI_TYPE2		(7 << 0)
+#define RADEON_PRIM_TYPE_RECT_LIST		(8 << 0)
+#define RADEON_PRIM_TYPE_3VRT_POINT_LIST	(9 << 0)
+#define RADEON_PRIM_TYPE_3VRT_LINE_LIST		(10 << 0)
+#define RADEON_PRIM_TYPE_MASK                   0xf
+#define RADEON_PRIM_WALK_IND			(1 << 4)
+#define RADEON_PRIM_WALK_LIST			(2 << 4)
+#define RADEON_PRIM_WALK_RING			(3 << 4)
+#define RADEON_COLOR_ORDER_BGRA			(0 << 6)
+#define RADEON_COLOR_ORDER_RGBA			(1 << 6)
+#define RADEON_MAOS_ENABLE			(1 << 7)
+#define RADEON_VTX_FMT_R128_MODE		(0 << 8)
+#define RADEON_VTX_FMT_RADEON_MODE		(1 << 8)
+#define RADEON_NUM_VERTICES_SHIFT		16
+
+#define RADEON_COLOR_FORMAT_CI8		2
+#define RADEON_COLOR_FORMAT_ARGB1555	3
+#define RADEON_COLOR_FORMAT_RGB565	4
+#define RADEON_COLOR_FORMAT_ARGB8888	6
+#define RADEON_COLOR_FORMAT_RGB332	7
+#define RADEON_COLOR_FORMAT_RGB8	9
+#define RADEON_COLOR_FORMAT_ARGB4444	15
+
+#define RADEON_TXFORMAT_I8		0
+#define RADEON_TXFORMAT_AI88		1
+#define RADEON_TXFORMAT_RGB332		2
+#define RADEON_TXFORMAT_ARGB1555	3
+#define RADEON_TXFORMAT_RGB565		4
+#define RADEON_TXFORMAT_ARGB4444	5
+#define RADEON_TXFORMAT_ARGB8888	6
+#define RADEON_TXFORMAT_RGBA8888	7
+#define RADEON_TXFORMAT_Y8		8
+#define RADEON_TXFORMAT_VYUY422         10
+#define RADEON_TXFORMAT_YVYU422         11
+#define RADEON_TXFORMAT_DXT1            12
+#define RADEON_TXFORMAT_DXT23           14
+#define RADEON_TXFORMAT_DXT45           15
+
+#define R200_PP_TXCBLEND_0                0x2f00
+#define R200_PP_TXCBLEND_1                0x2f10
+#define R200_PP_TXCBLEND_2                0x2f20
+#define R200_PP_TXCBLEND_3                0x2f30
+#define R200_PP_TXCBLEND_4                0x2f40
+#define R200_PP_TXCBLEND_5                0x2f50
+#define R200_PP_TXCBLEND_6                0x2f60
+#define R200_PP_TXCBLEND_7                0x2f70
+#define R200_SE_TCL_LIGHT_MODEL_CTL_0     0x2268
+#define R200_PP_TFACTOR_0                 0x2ee0
+#define R200_SE_VTX_FMT_0                 0x2088
+#define R200_SE_VAP_CNTL                  0x2080
+#define R200_SE_TCL_MATRIX_SEL_0          0x2230
+#define R200_SE_TCL_TEX_PROC_CTL_2        0x22a8
+#define R200_SE_TCL_UCP_VERT_BLEND_CTL    0x22c0
+#define R200_PP_TXFILTER_5                0x2ca0
+#define R200_PP_TXFILTER_4                0x2c80
+#define R200_PP_TXFILTER_3                0x2c60
+#define R200_PP_TXFILTER_2                0x2c40
+#define R200_PP_TXFILTER_1                0x2c20
+#define R200_PP_TXFILTER_0                0x2c00
+#define R200_PP_TXOFFSET_5                0x2d78
+#define R200_PP_TXOFFSET_4                0x2d60
+#define R200_PP_TXOFFSET_3                0x2d48
+#define R200_PP_TXOFFSET_2                0x2d30
+#define R200_PP_TXOFFSET_1                0x2d18
+#define R200_PP_TXOFFSET_0                0x2d00
+
+#define R200_PP_CUBIC_FACES_0             0x2c18
+#define R200_PP_CUBIC_FACES_1             0x2c38
+#define R200_PP_CUBIC_FACES_2             0x2c58
+#define R200_PP_CUBIC_FACES_3             0x2c78
+#define R200_PP_CUBIC_FACES_4             0x2c98
+#define R200_PP_CUBIC_FACES_5             0x2cb8
+#define R200_PP_CUBIC_OFFSET_F1_0         0x2d04
+#define R200_PP_CUBIC_OFFSET_F2_0         0x2d08
+#define R200_PP_CUBIC_OFFSET_F3_0         0x2d0c
+#define R200_PP_CUBIC_OFFSET_F4_0         0x2d10
+#define R200_PP_CUBIC_OFFSET_F5_0         0x2d14
+#define R200_PP_CUBIC_OFFSET_F1_1         0x2d1c
+#define R200_PP_CUBIC_OFFSET_F2_1         0x2d20
+#define R200_PP_CUBIC_OFFSET_F3_1         0x2d24
+#define R200_PP_CUBIC_OFFSET_F4_1         0x2d28
+#define R200_PP_CUBIC_OFFSET_F5_1         0x2d2c
+#define R200_PP_CUBIC_OFFSET_F1_2         0x2d34
+#define R200_PP_CUBIC_OFFSET_F2_2         0x2d38
+#define R200_PP_CUBIC_OFFSET_F3_2         0x2d3c
+#define R200_PP_CUBIC_OFFSET_F4_2         0x2d40
+#define R200_PP_CUBIC_OFFSET_F5_2         0x2d44
+#define R200_PP_CUBIC_OFFSET_F1_3         0x2d4c
+#define R200_PP_CUBIC_OFFSET_F2_3         0x2d50
+#define R200_PP_CUBIC_OFFSET_F3_3         0x2d54
+#define R200_PP_CUBIC_OFFSET_F4_3         0x2d58
+#define R200_PP_CUBIC_OFFSET_F5_3         0x2d5c
+#define R200_PP_CUBIC_OFFSET_F1_4         0x2d64
+#define R200_PP_CUBIC_OFFSET_F2_4         0x2d68
+#define R200_PP_CUBIC_OFFSET_F3_4         0x2d6c
+#define R200_PP_CUBIC_OFFSET_F4_4         0x2d70
+#define R200_PP_CUBIC_OFFSET_F5_4         0x2d74
+#define R200_PP_CUBIC_OFFSET_F1_5         0x2d7c
+#define R200_PP_CUBIC_OFFSET_F2_5         0x2d80
+#define R200_PP_CUBIC_OFFSET_F3_5         0x2d84
+#define R200_PP_CUBIC_OFFSET_F4_5         0x2d88
+#define R200_PP_CUBIC_OFFSET_F5_5         0x2d8c
+
+#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
+#define R200_SE_VTE_CNTL                  0x20b0
+#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL   0x2250
+#define R200_PP_TAM_DEBUG3                0x2d9c
+#define R200_PP_CNTL_X                    0x2cc4
+#define R200_SE_VAP_CNTL_STATUS           0x2140
+#define R200_RE_SCISSOR_TL_0              0x1cd8
+#define R200_RE_SCISSOR_TL_1              0x1ce0
+#define R200_RE_SCISSOR_TL_2              0x1ce8
+#define R200_RB3D_DEPTHXY_OFFSET          0x1d60
+#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
+#define R200_SE_VTX_STATE_CNTL            0x2180
+#define R200_RE_POINTSIZE                 0x2648
+#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
+
+#define RADEON_PP_TEX_SIZE_0                0x1d04	/* NPOT */
+#define RADEON_PP_TEX_SIZE_1                0x1d0c
+#define RADEON_PP_TEX_SIZE_2                0x1d14
+
+#define RADEON_PP_CUBIC_FACES_0             0x1d24
+#define RADEON_PP_CUBIC_FACES_1             0x1d28
+#define RADEON_PP_CUBIC_FACES_2             0x1d2c
+#define RADEON_PP_CUBIC_OFFSET_T0_0         0x1dd0	/* bits [31:5] */
+#define RADEON_PP_CUBIC_OFFSET_T1_0         0x1e00
+#define RADEON_PP_CUBIC_OFFSET_T2_0         0x1e14
+
+#define RADEON_SE_TCL_STATE_FLUSH           0x2284
+
+#define SE_VAP_CNTL__TCL_ENA_MASK                          0x00000001
+#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK                   0x00010000
+#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT                 0x00000012
+#define SE_VTE_CNTL__VTX_XY_FMT_MASK                       0x00000100
+#define SE_VTE_CNTL__VTX_Z_FMT_MASK                        0x00000200
+#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK                  0x00000001
+#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK                  0x00000002
+#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT               0x0000000b
+#define R200_3D_DRAW_IMMD_2      0xC0003500
+#define R200_SE_VTX_FMT_1                 0x208c
+#define R200_RE_CNTL                      0x1c50
+
+#define R200_RB3D_BLENDCOLOR              0x3218
+
+#define R200_SE_TCL_POINT_SPRITE_CNTL     0x22c4
+
+#define R200_PP_TRI_PERF                  0x2cf8
+
+#define R200_PP_AFS_0                     0x2f80
+#define R200_PP_AFS_1                     0x2f00 /* same as txcblend_0 */
+
+#define R200_VAP_PVS_CNTL_1               0x22D0
+
+/* MPEG settings from VHA code */
+#define RADEON_VHA_SETTO16_1                       0x2694
+#define RADEON_VHA_SETTO16_2                       0x2680
+#define RADEON_VHA_SETTO0_1                        0x1840
+#define RADEON_VHA_FB_OFFSET                       0x19e4
+#define RADEON_VHA_SETTO1AND70S                    0x19d8
+#define RADEON_VHA_DST_PITCH                       0x1408
+
+// set as reference header
+#define RADEON_VHA_BACKFRAME0_OFF_Y              0x1840
+#define RADEON_VHA_BACKFRAME1_OFF_PITCH_Y        0x1844
+#define RADEON_VHA_BACKFRAME0_OFF_U              0x1848
+#define RADEON_VHA_BACKFRAME1_OFF_PITCH_U        0x184c
+#define RADOEN_VHA_BACKFRAME0_OFF_V              0x1850
+#define RADEON_VHA_BACKFRAME1_OFF_PITCH_V        0x1854
+#define RADEON_VHA_FORWFRAME0_OFF_Y              0x1858
+#define RADEON_VHA_FORWFRAME1_OFF_PITCH_Y        0x185c
+#define RADEON_VHA_FORWFRAME0_OFF_U              0x1860
+#define RADEON_VHA_FORWFRAME1_OFF_PITCH_U        0x1864
+#define RADEON_VHA_FORWFRAME0_OFF_V              0x1868
+#define RADEON_VHA_FORWFRAME0_OFF_PITCH_V        0x1880
+#define RADEON_VHA_BACKFRAME0_OFF_Y_2            0x1884
+#define RADEON_VHA_BACKFRAME1_OFF_PITCH_Y_2      0x1888
+#define RADEON_VHA_BACKFRAME0_OFF_U_2            0x188c
+#define RADEON_VHA_BACKFRAME1_OFF_PITCH_U_2      0x1890
+#define RADEON_VHA_BACKFRAME0_OFF_V_2            0x1894
+#define RADEON_VHA_BACKFRAME1_OFF_PITCH_V_2      0x1898
+
+
+
+/* Constants */
+#define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
+
+#define RADEON_LAST_FRAME_REG		RADEON_SCRATCH_REG0
+#define RADEON_LAST_DISPATCH_REG	RADEON_SCRATCH_REG1
+#define RADEON_LAST_CLEAR_REG		RADEON_SCRATCH_REG2
+#define RADEON_LAST_SWI_REG		RADEON_SCRATCH_REG3
+#define RADEON_LAST_DISPATCH		1
+
+#define RADEON_MAX_VB_AGE		0x7fffffff
+#define RADEON_MAX_VB_VERTS		(0xffff)
+
+#define RADEON_RING_HIGH_MARK		128
+
+#define RADEON_PCIGART_TABLE_SIZE      (32*1024)
+
+#define RADEON_READ(reg)	DRM_READ32(  dev_priv->mmio, (reg) )
+#define RADEON_WRITE(reg,val)	DRM_WRITE32( dev_priv->mmio, (reg), (val) )
+#define RADEON_READ8(reg)	DRM_READ8(  dev_priv->mmio, (reg) )
+#define RADEON_WRITE8(reg,val)	DRM_WRITE8( dev_priv->mmio, (reg), (val) )
+
+#define RADEON_WRITE_PLL( addr, val )					\
+do {									\
+	RADEON_WRITE8( RADEON_CLOCK_CNTL_INDEX,				\
+		       ((addr) & 0x1f) | RADEON_PLL_WR_EN );		\
+	RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) );			\
+} while (0)
+
+#define RADEON_WRITE_PCIE( addr, val )					\
+do {									\
+	RADEON_WRITE8( RADEON_PCIE_INDEX,				\
+			((addr) & 0xff));				\
+	RADEON_WRITE( RADEON_PCIE_DATA, (val) );			\
+} while (0)
+
+#define CP_PACKET0( reg, n )						\
+	(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET0_TABLE( reg, n )					\
+	(RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET1( reg0, reg1 )					\
+	(RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2))
+#define CP_PACKET2()							\
+	(RADEON_CP_PACKET2)
+#define CP_PACKET3( pkt, n )						\
+	(RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
+
+/* ================================================================
+ * Engine control helper macros
+ */
+
+#define RADEON_WAIT_UNTIL_2D_IDLE() do {				\
+	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
+		   RADEON_WAIT_HOST_IDLECLEAN) );			\
+} while (0)
+
+#define RADEON_WAIT_UNTIL_3D_IDLE() do {				\
+	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( (RADEON_WAIT_3D_IDLECLEAN |				\
+		   RADEON_WAIT_HOST_IDLECLEAN) );			\
+} while (0)
+
+#define RADEON_WAIT_UNTIL_IDLE() do {					\
+	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
+		   RADEON_WAIT_3D_IDLECLEAN |				\
+		   RADEON_WAIT_HOST_IDLECLEAN) );			\
+} while (0)
+
+#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do {				\
+	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( RADEON_WAIT_CRTC_PFLIP );				\
+} while (0)
+
+#define RADEON_FLUSH_CACHE() do {					\
+	OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) );	\
+	OUT_RING( RADEON_RB3D_DC_FLUSH );				\
+} while (0)
+
+#define RADEON_PURGE_CACHE() do {					\
+	OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) );	\
+	OUT_RING( RADEON_RB3D_DC_FLUSH_ALL );				\
+} while (0)
+
+#define RADEON_FLUSH_ZCACHE() do {					\
+	OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );	\
+	OUT_RING( RADEON_RB3D_ZC_FLUSH );				\
+} while (0)
+
+#define RADEON_PURGE_ZCACHE() do {					\
+	OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );	\
+	OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL );				\
+} while (0)
+
+/* ================================================================
+ * Misc helper macros
+ */
+
+/* Perfbox functionality only.
+ */
+#define RING_SPACE_TEST_WITH_RETURN( dev_priv )				\
+do {									\
+	if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) {		\
+		u32 head = GET_RING_HEAD( dev_priv );			\
+		if (head == dev_priv->ring.tail)			\
+			dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE;	\
+	}								\
+} while (0)
+
+#define VB_AGE_TEST_WITH_RETURN( dev_priv )				\
+do {									\
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;		\
+	if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {		\
+		int __ret = radeon_do_cp_idle( dev_priv );		\
+		if ( __ret ) return __ret;				\
+		sarea_priv->last_dispatch = 0;				\
+		radeon_freelist_reset( dev );				\
+	}								\
+} while (0)
+
+#define RADEON_DISPATCH_AGE( age ) do {					\
+	OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) );		\
+	OUT_RING( age );						\
+} while (0)
+
+#define RADEON_FRAME_AGE( age ) do {					\
+	OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) );		\
+	OUT_RING( age );						\
+} while (0)
+
+#define RADEON_CLEAR_AGE( age ) do {					\
+	OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) );		\
+	OUT_RING( age );						\
+} while (0)
+
+/* ================================================================
+ * Ring control
+ */
+
+#define RADEON_VERBOSE	0
+
+#define RING_LOCALS	int write, _nr; unsigned int mask; u32 *ring;
+
+#define BEGIN_RING( n ) do {						\
+	if ( RADEON_VERBOSE ) {						\
+		DRM_INFO( "BEGIN_RING( %d ) in %s\n",			\
+			   n, __FUNCTION__ );				\
+	}								\
+	if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {		\
+		COMMIT_RING();						\
+		radeon_wait_ring( dev_priv, (n) * sizeof(u32) );	\
+	}								\
+	_nr = n; dev_priv->ring.space -= (n) * sizeof(u32);		\
+	ring = dev_priv->ring.start;					\
+	write = dev_priv->ring.tail;					\
+	mask = dev_priv->ring.tail_mask;				\
+} while (0)
+
+#define ADVANCE_RING() do {						\
+	if ( RADEON_VERBOSE ) {						\
+		DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",	\
+			  write, dev_priv->ring.tail );			\
+	}								\
+	if (((dev_priv->ring.tail + _nr) & mask) != write) {		\
+		DRM_ERROR( 						\
+			"ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",	\
+			((dev_priv->ring.tail + _nr) & mask),		\
+			write, __LINE__);						\
+	} else								\
+		dev_priv->ring.tail = write;				\
+} while (0)
+
+#define COMMIT_RING() do {						\
+	/* Flush writes to ring */					\
+	DRM_MEMORYBARRIER();						\
+	GET_RING_HEAD( dev_priv );					\
+	RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail );		\
+	/* read from PCI bus to ensure correct posting */		\
+	RADEON_READ( RADEON_CP_RB_RPTR );				\
+} while (0)
+
+#define OUT_RING( x ) do {						\
+	if ( RADEON_VERBOSE ) {						\
+		DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",		\
+			   (unsigned int)(x), write );			\
+	}								\
+	ring[write++] = (x);						\
+	write &= mask;							\
+} while (0)
+
+#define OUT_RING_REG( reg, val ) do {					\
+	OUT_RING( CP_PACKET0( reg, 0 ) );				\
+	OUT_RING( val );						\
+} while (0)
+
+#define OUT_RING_TABLE( tab, sz ) do {				\
+	int _size = (sz);					\
+	int *_tab = (int *)(tab);				\
+								\
+	if (write + _size > mask) {				\
+		int _i = (mask+1) - write;			\
+		_size -= _i;					\
+		while (_i > 0) {				\
+			*(int *)(ring + write) = *_tab++;	\
+			write++;				\
+			_i--;					\
+		}						\
+		write = 0;					\
+		_tab += _i;					\
+	}							\
+	while (_size > 0) {					\
+		*(ring + write) = *_tab++;			\
+		write++;					\
+		_size--;					\
+	}							\
+	write &= mask;						\
+} while (0)
+
+#endif				/* __RADEON_DRV_H__ */
--- libdrm-2.3.0.orig/shared-core/mach64_drv.h
+++ libdrm-2.3.0/shared-core/mach64_drv.h
@@ -0,0 +1,1048 @@
+/* mach64_drv.h -- Private header for mach64 driver -*- linux-c -*-
+ * Created: Fri Nov 24 22:07:58 2000 by gareth@valinux.com
+ */
+/*
+ * Copyright 2000 Gareth Hughes
+ * Copyright 2002 Frank C. Earl
+ * Copyright 2002-2003 Leif Delgass
+ * 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 COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION 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:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Frank C. Earl <fearl@airmail.net>
+ *    Leif Delgass <ldelgass@retinalburn.net>
+ *    Jos�Fonseca <j_r_fonseca@yahoo.co.uk>
+ */
+
+#ifndef __MACH64_DRV_H__
+#define __MACH64_DRV_H__
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR		"Gareth Hughes, Leif Delgass, José Fonseca"
+
+#define DRIVER_NAME		"mach64"
+#define DRIVER_DESC		"DRM module for the ATI Rage Pro"
+#define DRIVER_DATE		"20060718"
+
+#define DRIVER_MAJOR		2
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	0
+
+/* FIXME: remove these when not needed */
+/* Development driver options */
+#define MACH64_EXTRA_CHECKING     0	/* Extra sanity checks for DMA/freelist management */
+#define MACH64_VERBOSE		  0	/* Verbose debugging output */
+
+typedef struct drm_mach64_freelist {
+	struct list_head list;	/* List pointers for free_list, placeholders, or pending list */
+	drm_buf_t *buf;		/* Pointer to the buffer */
+	int discard;		/* This flag is set when we're done (re)using a buffer */
+	u32 ring_ofs;		/* dword offset in ring of last descriptor for this buffer */
+} drm_mach64_freelist_t;
+
+typedef struct drm_mach64_descriptor_ring {
+	void *start;		/* write pointer (cpu address) to start of descriptor ring */
+	u32 start_addr;		/* bus address of beginning of descriptor ring */
+	int size;		/* size of ring in bytes */
+
+	u32 head_addr;		/* bus address of descriptor ring head */
+	u32 head;		/* dword offset of descriptor ring head */
+	u32 tail;		/* dword offset of descriptor ring tail */
+	u32 tail_mask;		/* mask used to wrap ring */
+	int space;		/* number of free bytes in ring */
+} drm_mach64_descriptor_ring_t;
+
+typedef struct drm_mach64_private {
+	drm_mach64_sarea_t *sarea_priv;
+
+	int is_pci;
+	drm_mach64_dma_mode_t driver_mode;	/* Async DMA, sync DMA, or MMIO */
+
+	int usec_timeout;	/* Timeout for the wait functions */
+
+	drm_mach64_descriptor_ring_t ring;	/* DMA descriptor table (ring buffer) */
+	int ring_running;	/* Is bus mastering is enabled */
+
+	struct list_head free_list;	/* Free-list head */
+	struct list_head placeholders;	/* Placeholder list for buffers held by clients */
+	struct list_head pending;	/* Buffers pending completion */
+
+	u32 frame_ofs[MACH64_MAX_QUEUED_FRAMES];	/* dword ring offsets of most recent frame swaps */
+
+	unsigned int fb_bpp;
+	unsigned int front_offset, front_pitch;
+	unsigned int back_offset, back_pitch;
+
+	unsigned int depth_bpp;
+	unsigned int depth_offset, depth_pitch;
+
+	u32 front_offset_pitch;
+	u32 back_offset_pitch;
+	u32 depth_offset_pitch;
+
+	drm_local_map_t *sarea;
+	drm_local_map_t *fb;
+	drm_local_map_t *mmio;
+	drm_local_map_t *ring_map;
+	drm_local_map_t *dev_buffers;	/* this is a pointer to a structure in dev */
+	drm_local_map_t *agp_textures;
+} drm_mach64_private_t;
+
+extern drm_ioctl_desc_t mach64_ioctls[];
+extern int mach64_max_ioctl;
+
+				/* mach64_dma.c */
+extern int mach64_dma_init(DRM_IOCTL_ARGS);
+extern int mach64_dma_idle(DRM_IOCTL_ARGS);
+extern int mach64_dma_flush(DRM_IOCTL_ARGS);
+extern int mach64_engine_reset(DRM_IOCTL_ARGS);
+extern int mach64_dma_buffers(DRM_IOCTL_ARGS);
+extern void mach64_driver_lastclose(drm_device_t * dev);
+
+extern int mach64_init_freelist(drm_device_t * dev);
+extern void mach64_destroy_freelist(drm_device_t * dev);
+extern drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv);
+extern int mach64_freelist_put(drm_mach64_private_t * dev_priv,
+			       drm_buf_t * copy_buf);
+
+extern int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv,
+				   int entries);
+extern int mach64_do_wait_for_idle(drm_mach64_private_t * dev_priv);
+extern int mach64_wait_ring(drm_mach64_private_t * dev_priv, int n);
+extern int mach64_do_dispatch_pseudo_dma(drm_mach64_private_t * dev_priv);
+extern int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv);
+extern void mach64_dump_engine_info(drm_mach64_private_t * dev_priv);
+extern void mach64_dump_ring_info(drm_mach64_private_t * dev_priv);
+extern int mach64_do_engine_reset(drm_mach64_private_t * dev_priv);
+
+extern int mach64_do_dma_idle(drm_mach64_private_t * dev_priv);
+extern int mach64_do_dma_flush(drm_mach64_private_t * dev_priv);
+extern int mach64_do_cleanup_dma(drm_device_t * dev);
+
+				/* mach64_state.c */
+extern int mach64_dma_clear(DRM_IOCTL_ARGS);
+extern int mach64_dma_swap(DRM_IOCTL_ARGS);
+extern int mach64_dma_vertex(DRM_IOCTL_ARGS);
+extern int mach64_dma_blit(DRM_IOCTL_ARGS);
+extern int mach64_get_param(DRM_IOCTL_ARGS);
+extern int mach64_driver_vblank_wait(drm_device_t * dev,
+				     unsigned int *sequence);
+
+extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS);
+extern void mach64_driver_irq_preinstall(drm_device_t * dev);
+extern void mach64_driver_irq_postinstall(drm_device_t * dev);
+extern void mach64_driver_irq_uninstall(drm_device_t * dev);
+
+/* ================================================================
+ * Registers
+ */
+
+#define MACH64_AGP_BASE				0x0148
+#define MACH64_AGP_CNTL				0x014c
+#define MACH64_ALPHA_TST_CNTL			0x0550
+
+#define MACH64_DSP_CONFIG 			0x0420
+#define MACH64_DSP_ON_OFF 			0x0424
+#define MACH64_EXT_MEM_CNTL 			0x04ac
+#define MACH64_GEN_TEST_CNTL 			0x04d0
+#define MACH64_HW_DEBUG 			0x047c
+#define MACH64_MEM_ADDR_CONFIG 			0x0434
+#define MACH64_MEM_BUF_CNTL 			0x042c
+#define MACH64_MEM_CNTL 			0x04b0
+
+#define MACH64_BM_ADDR				0x0648
+#define MACH64_BM_COMMAND			0x0188
+#define MACH64_BM_DATA				0x0648
+#define MACH64_BM_FRAME_BUF_OFFSET		0x0180
+#define MACH64_BM_GUI_TABLE			0x01b8
+#define MACH64_BM_GUI_TABLE_CMD			0x064c
+#	define MACH64_CIRCULAR_BUF_SIZE_16KB		(0 << 0)
+#	define MACH64_CIRCULAR_BUF_SIZE_32KB		(1 << 0)
+#	define MACH64_CIRCULAR_BUF_SIZE_64KB		(2 << 0)
+#	define MACH64_CIRCULAR_BUF_SIZE_128KB		(3 << 0)
+#	define MACH64_LAST_DESCRIPTOR			(1 << 31)
+#define MACH64_BM_HOSTDATA			0x0644
+#define MACH64_BM_STATUS			0x018c
+#define MACH64_BM_SYSTEM_MEM_ADDR		0x0184
+#define MACH64_BM_SYSTEM_TABLE			0x01bc
+#define MACH64_BUS_CNTL				0x04a0
+#	define MACH64_BUS_MSTR_RESET			(1 << 1)
+#	define MACH64_BUS_APER_REG_DIS			(1 << 4)
+#	define MACH64_BUS_FLUSH_BUF			(1 << 2)
+#	define MACH64_BUS_MASTER_DIS			(1 << 6)
+#	define MACH64_BUS_EXT_REG_EN			(1 << 27)
+
+#define MACH64_CLR_CMP_CLR			0x0700
+#define MACH64_CLR_CMP_CNTL			0x0708
+#define MACH64_CLR_CMP_MASK			0x0704
+#define MACH64_CONFIG_CHIP_ID 			0x04e0
+#define MACH64_CONFIG_CNTL 			0x04dc
+#define MACH64_CONFIG_STAT0 			0x04e4
+#define MACH64_CONFIG_STAT1 			0x0494
+#define MACH64_CONFIG_STAT2 			0x0498
+#define MACH64_CONTEXT_LOAD_CNTL		0x072c
+#define MACH64_CONTEXT_MASK			0x0720
+#define MACH64_COMPOSITE_SHADOW_ID		0x0798
+#define MACH64_CRC_SIG 				0x04e8
+#define MACH64_CUSTOM_MACRO_CNTL 		0x04d4
+
+#define MACH64_DP_BKGD_CLR			0x06c0
+#define MACH64_DP_FOG_CLR			0x06c4
+#define MACH64_DP_FGRD_BKGD_CLR			0x06e0
+#define MACH64_DP_FRGD_CLR			0x06c4
+#define MACH64_DP_FGRD_CLR_MIX			0x06dc
+
+#define MACH64_DP_MIX				0x06d4
+#	define BKGD_MIX_NOT_D				(0 << 0)
+#	define BKGD_MIX_ZERO				(1 << 0)
+#	define BKGD_MIX_ONE				(2 << 0)
+#	define MACH64_BKGD_MIX_D			(3 << 0)
+#	define BKGD_MIX_NOT_S				(4 << 0)
+#	define BKGD_MIX_D_XOR_S				(5 << 0)
+#	define BKGD_MIX_NOT_D_XOR_S			(6 << 0)
+#	define MACH64_BKGD_MIX_S			(7 << 0)
+#	define BKGD_MIX_NOT_D_OR_NOT_S			(8 << 0)
+#	define BKGD_MIX_D_OR_NOT_S			(9 << 0)
+#	define BKGD_MIX_NOT_D_OR_S			(10 << 0)
+#	define BKGD_MIX_D_OR_S				(11 << 0)
+#	define BKGD_MIX_D_AND_S				(12 << 0)
+#	define BKGD_MIX_NOT_D_AND_S			(13 << 0)
+#	define BKGD_MIX_D_AND_NOT_S			(14 << 0)
+#	define BKGD_MIX_NOT_D_AND_NOT_S			(15 << 0)
+#	define BKGD_MIX_D_PLUS_S_DIV2			(23 << 0)
+#	define FRGD_MIX_NOT_D				(0 << 16)
+#	define FRGD_MIX_ZERO				(1 << 16)
+#	define FRGD_MIX_ONE				(2 << 16)
+#	define FRGD_MIX_D				(3 << 16)
+#	define FRGD_MIX_NOT_S				(4 << 16)
+#	define FRGD_MIX_D_XOR_S				(5 << 16)
+#	define FRGD_MIX_NOT_D_XOR_S			(6 << 16)
+#	define MACH64_FRGD_MIX_S			(7 << 16)
+#	define FRGD_MIX_NOT_D_OR_NOT_S			(8 << 16)
+#	define FRGD_MIX_D_OR_NOT_S			(9 << 16)
+#	define FRGD_MIX_NOT_D_OR_S			(10 << 16)
+#	define FRGD_MIX_D_OR_S				(11 << 16)
+#	define FRGD_MIX_D_AND_S				(12 << 16)
+#	define FRGD_MIX_NOT_D_AND_S			(13 << 16)
+#	define FRGD_MIX_D_AND_NOT_S			(14 << 16)
+#	define FRGD_MIX_NOT_D_AND_NOT_S			(15 << 16)
+#	define FRGD_MIX_D_PLUS_S_DIV2			(23 << 16)
+
+#define MACH64_DP_PIX_WIDTH			0x06d0
+#	define MACH64_HOST_TRIPLE_ENABLE		(1 << 13)
+#	define MACH64_BYTE_ORDER_MSB_TO_LSB		(0 << 24)
+#	define MACH64_BYTE_ORDER_LSB_TO_MSB		(1 << 24)
+
+#define MACH64_DP_SRC				0x06d8
+#	define MACH64_BKGD_SRC_BKGD_CLR			(0 << 0)
+#	define MACH64_BKGD_SRC_FRGD_CLR			(1 << 0)
+#	define MACH64_BKGD_SRC_HOST			(2 << 0)
+#	define MACH64_BKGD_SRC_BLIT			(3 << 0)
+#	define MACH64_BKGD_SRC_PATTERN			(4 << 0)
+#	define MACH64_BKGD_SRC_3D			(5 << 0)
+#	define MACH64_FRGD_SRC_BKGD_CLR			(0 << 8)
+#	define MACH64_FRGD_SRC_FRGD_CLR			(1 << 8)
+#	define MACH64_FRGD_SRC_HOST			(2 << 8)
+#	define MACH64_FRGD_SRC_BLIT			(3 << 8)
+#	define MACH64_FRGD_SRC_PATTERN			(4 << 8)
+#	define MACH64_FRGD_SRC_3D			(5 << 8)
+#	define MACH64_MONO_SRC_ONE			(0 << 16)
+#	define MACH64_MONO_SRC_PATTERN			(1 << 16)
+#	define MACH64_MONO_SRC_HOST			(2 << 16)
+#	define MACH64_MONO_SRC_BLIT			(3 << 16)
+
+#define MACH64_DP_WRITE_MASK			0x06c8
+
+#define MACH64_DST_CNTL				0x0530
+#	define MACH64_DST_X_RIGHT_TO_LEFT		(0 << 0)
+#	define MACH64_DST_X_LEFT_TO_RIGHT		(1 << 0)
+#	define MACH64_DST_Y_BOTTOM_TO_TOP		(0 << 1)
+#	define MACH64_DST_Y_TOP_TO_BOTTOM		(1 << 1)
+#	define MACH64_DST_X_MAJOR			(0 << 2)
+#	define MACH64_DST_Y_MAJOR			(1 << 2)
+#	define MACH64_DST_X_TILE			(1 << 3)
+#	define MACH64_DST_Y_TILE			(1 << 4)
+#	define MACH64_DST_LAST_PEL			(1 << 5)
+#	define MACH64_DST_POLYGON_ENABLE		(1 << 6)
+#	define MACH64_DST_24_ROTATION_ENABLE		(1 << 7)
+
+#define MACH64_DST_HEIGHT_WIDTH			0x0518
+#define MACH64_DST_OFF_PITCH			0x0500
+#define MACH64_DST_WIDTH_HEIGHT			0x06ec
+#define MACH64_DST_X_Y				0x06e8
+#define MACH64_DST_Y_X				0x050c
+
+#define MACH64_FIFO_STAT			0x0710
+#	define MACH64_FIFO_SLOT_MASK			0x0000ffff
+#	define MACH64_FIFO_ERR				(1 << 31)
+
+#define MACH64_GEN_TEST_CNTL			0x04d0
+#	define MACH64_GUI_ENGINE_ENABLE			(1 << 8)
+#define MACH64_GUI_CMDFIFO_DEBUG		0x0170
+#define MACH64_GUI_CMDFIFO_DATA			0x0174
+#define MACH64_GUI_CNTL				0x0178
+#       define MACH64_CMDFIFO_SIZE_MASK                 0x00000003ul
+#       define MACH64_CMDFIFO_SIZE_192                  0x00000000ul
+#       define MACH64_CMDFIFO_SIZE_128                  0x00000001ul
+#       define MACH64_CMDFIFO_SIZE_64                   0x00000002ul
+#define MACH64_GUI_STAT				0x0738
+#	define MACH64_GUI_ACTIVE			(1 << 0)
+#define MACH64_GUI_TRAJ_CNTL			0x0730
+
+#define MACH64_HOST_CNTL			0x0640
+#define MACH64_HOST_DATA0			0x0600
+
+#define MACH64_ONE_OVER_AREA			0x029c
+#define MACH64_ONE_OVER_AREA_UC			0x0300
+
+#define MACH64_PAT_REG0				0x0680
+#define MACH64_PAT_REG1				0x0684
+
+#define MACH64_SC_LEFT                          0x06a0
+#define MACH64_SC_RIGHT                         0x06a4
+#define MACH64_SC_LEFT_RIGHT                    0x06a8
+#define MACH64_SC_TOP                           0x06ac
+#define MACH64_SC_BOTTOM                        0x06b0
+#define MACH64_SC_TOP_BOTTOM                    0x06b4
+
+#define MACH64_SCALE_3D_CNTL			0x05fc
+#define MACH64_SCRATCH_REG0			0x0480
+#define MACH64_SCRATCH_REG1			0x0484
+#define MACH64_SECONDARY_TEX_OFF		0x0778
+#define MACH64_SETUP_CNTL			0x0304
+#define MACH64_SRC_CNTL				0x05b4
+#	define MACH64_SRC_BM_ENABLE			(1 << 8)
+#	define MACH64_SRC_BM_SYNC			(1 << 9)
+#	define MACH64_SRC_BM_OP_FRAME_TO_SYSTEM		(0 << 10)
+#	define MACH64_SRC_BM_OP_SYSTEM_TO_FRAME		(1 << 10)
+#	define MACH64_SRC_BM_OP_REG_TO_SYSTEM		(2 << 10)
+#	define MACH64_SRC_BM_OP_SYSTEM_TO_REG		(3 << 10)
+#define MACH64_SRC_HEIGHT1			0x0594
+#define MACH64_SRC_HEIGHT2			0x05ac
+#define MACH64_SRC_HEIGHT1_WIDTH1		0x0598
+#define MACH64_SRC_HEIGHT2_WIDTH2		0x05b0
+#define MACH64_SRC_OFF_PITCH			0x0580
+#define MACH64_SRC_WIDTH1			0x0590
+#define MACH64_SRC_Y_X				0x058c
+
+#define MACH64_TEX_0_OFF			0x05c0
+#define MACH64_TEX_CNTL				0x0774
+#define MACH64_TEX_SIZE_PITCH			0x0770
+#define MACH64_TIMER_CONFIG 			0x0428
+
+#define MACH64_VERTEX_1_ARGB			0x0254
+#define MACH64_VERTEX_1_S			0x0240
+#define MACH64_VERTEX_1_SECONDARY_S		0x0328
+#define MACH64_VERTEX_1_SECONDARY_T		0x032c
+#define MACH64_VERTEX_1_SECONDARY_W		0x0330
+#define MACH64_VERTEX_1_SPEC_ARGB		0x024c
+#define MACH64_VERTEX_1_T			0x0244
+#define MACH64_VERTEX_1_W			0x0248
+#define MACH64_VERTEX_1_X_Y			0x0258
+#define MACH64_VERTEX_1_Z			0x0250
+#define MACH64_VERTEX_2_ARGB			0x0274
+#define MACH64_VERTEX_2_S			0x0260
+#define MACH64_VERTEX_2_SECONDARY_S		0x0334
+#define MACH64_VERTEX_2_SECONDARY_T		0x0338
+#define MACH64_VERTEX_2_SECONDARY_W		0x033c
+#define MACH64_VERTEX_2_SPEC_ARGB		0x026c
+#define MACH64_VERTEX_2_T			0x0264
+#define MACH64_VERTEX_2_W			0x0268
+#define MACH64_VERTEX_2_X_Y			0x0278
+#define MACH64_VERTEX_2_Z			0x0270
+#define MACH64_VERTEX_3_ARGB			0x0294
+#define MACH64_VERTEX_3_S			0x0280
+#define MACH64_VERTEX_3_SECONDARY_S		0x02a0
+#define MACH64_VERTEX_3_SECONDARY_T		0x02a4
+#define MACH64_VERTEX_3_SECONDARY_W		0x02a8
+#define MACH64_VERTEX_3_SPEC_ARGB		0x028c
+#define MACH64_VERTEX_3_T			0x0284
+#define MACH64_VERTEX_3_W			0x0288
+#define MACH64_VERTEX_3_X_Y			0x0298
+#define MACH64_VERTEX_3_Z			0x0290
+
+#define MACH64_Z_CNTL				0x054c
+#define MACH64_Z_OFF_PITCH			0x0548
+
+#define MACH64_CRTC_VLINE_CRNT_VLINE		0x0410
+#	define MACH64_CRTC_VLINE_MASK		        0x000007ff
+#	define MACH64_CRTC_CRNT_VLINE_MASK		0x07ff0000
+#define MACH64_CRTC_OFF_PITCH			0x0414
+#define MACH64_CRTC_INT_CNTL			0x0418
+#	define MACH64_CRTC_VBLANK			(1 << 0)
+#	define MACH64_CRTC_VBLANK_INT_EN		(1 << 1)
+#	define MACH64_CRTC_VBLANK_INT			(1 << 2)
+#	define MACH64_CRTC_VLINE_INT_EN			(1 << 3)
+#	define MACH64_CRTC_VLINE_INT			(1 << 4)
+#	define MACH64_CRTC_VLINE_SYNC			(1 << 5)	/* 0=even, 1=odd */
+#	define MACH64_CRTC_FRAME			(1 << 6)	/* 0=even, 1=odd */
+#	define MACH64_CRTC_SNAPSHOT_INT_EN		(1 << 7)
+#	define MACH64_CRTC_SNAPSHOT_INT			(1 << 8)
+#	define MACH64_CRTC_I2C_INT_EN			(1 << 9)
+#	define MACH64_CRTC_I2C_INT			(1 << 10)
+#	define MACH64_CRTC2_VBLANK			(1 << 11)	/* LT Pro */
+#	define MACH64_CRTC2_VBLANK_INT_EN		(1 << 12)	/* LT Pro */
+#	define MACH64_CRTC2_VBLANK_INT			(1 << 13)	/* LT Pro */
+#	define MACH64_CRTC2_VLINE_INT_EN		(1 << 14)	/* LT Pro */
+#	define MACH64_CRTC2_VLINE_INT			(1 << 15)	/* LT Pro */
+#	define MACH64_CRTC_CAPBUF0_INT_EN		(1 << 16)
+#	define MACH64_CRTC_CAPBUF0_INT			(1 << 17)
+#	define MACH64_CRTC_CAPBUF1_INT_EN		(1 << 18)
+#	define MACH64_CRTC_CAPBUF1_INT			(1 << 19)
+#	define MACH64_CRTC_OVERLAY_EOF_INT_EN		(1 << 20)
+#	define MACH64_CRTC_OVERLAY_EOF_INT		(1 << 21)
+#	define MACH64_CRTC_ONESHOT_CAP_INT_EN		(1 << 22)
+#	define MACH64_CRTC_ONESHOT_CAP_INT		(1 << 23)
+#	define MACH64_CRTC_BUSMASTER_EOL_INT_EN		(1 << 24)
+#	define MACH64_CRTC_BUSMASTER_EOL_INT		(1 << 25)
+#	define MACH64_CRTC_GP_INT_EN			(1 << 26)
+#	define MACH64_CRTC_GP_INT			(1 << 27)
+#	define MACH64_CRTC2_VLINE_SYNC			(1 << 28) /* LT Pro */	/* 0=even, 1=odd */
+#	define MACH64_CRTC_SNAPSHOT2_INT_EN		(1 << 29)	/* LT Pro */
+#	define MACH64_CRTC_SNAPSHOT2_INT		(1 << 30)	/* LT Pro */
+#	define MACH64_CRTC_VBLANK2_INT			(1 << 31)
+#	define MACH64_CRTC_INT_ENS				\
+		(						\
+			MACH64_CRTC_VBLANK_INT_EN |		\
+			MACH64_CRTC_VLINE_INT_EN |		\
+			MACH64_CRTC_SNAPSHOT_INT_EN |		\
+			MACH64_CRTC_I2C_INT_EN |		\
+			MACH64_CRTC2_VBLANK_INT_EN |		\
+			MACH64_CRTC2_VLINE_INT_EN |		\
+			MACH64_CRTC_CAPBUF0_INT_EN |		\
+			MACH64_CRTC_CAPBUF1_INT_EN |		\
+			MACH64_CRTC_OVERLAY_EOF_INT_EN |	\
+			MACH64_CRTC_ONESHOT_CAP_INT_EN |	\
+			MACH64_CRTC_BUSMASTER_EOL_INT_EN |	\
+			MACH64_CRTC_GP_INT_EN |			\
+			MACH64_CRTC_SNAPSHOT2_INT_EN |		\
+			0					\
+		)
+#	define MACH64_CRTC_INT_ACKS			\
+		(					\
+			MACH64_CRTC_VBLANK_INT |	\
+			MACH64_CRTC_VLINE_INT |		\
+			MACH64_CRTC_SNAPSHOT_INT |	\
+			MACH64_CRTC_I2C_INT |		\
+			MACH64_CRTC2_VBLANK_INT |	\
+			MACH64_CRTC2_VLINE_INT |	\
+			MACH64_CRTC_CAPBUF0_INT |	\
+			MACH64_CRTC_CAPBUF1_INT |	\
+			MACH64_CRTC_OVERLAY_EOF_INT |	\
+			MACH64_CRTC_ONESHOT_CAP_INT |	\
+			MACH64_CRTC_BUSMASTER_EOL_INT |	\
+			MACH64_CRTC_GP_INT |		\
+			MACH64_CRTC_SNAPSHOT2_INT |	\
+			MACH64_CRTC_VBLANK2_INT |	\
+			0				\
+		)
+
+#define MACH64_DATATYPE_CI8				2
+#define MACH64_DATATYPE_ARGB1555			3
+#define MACH64_DATATYPE_RGB565				4
+#define MACH64_DATATYPE_ARGB8888			6
+#define MACH64_DATATYPE_RGB332				7
+#define MACH64_DATATYPE_Y8				8
+#define MACH64_DATATYPE_RGB8				9
+#define MACH64_DATATYPE_VYUY422				11
+#define MACH64_DATATYPE_YVYU422				12
+#define MACH64_DATATYPE_AYUV444				14
+#define MACH64_DATATYPE_ARGB4444			15
+
+#define MACH64_READ(reg)	DRM_READ32(dev_priv->mmio, (reg) )
+#define MACH64_WRITE(reg,val)	DRM_WRITE32(dev_priv->mmio, (reg), (val) )
+
+#define DWMREG0		0x0400
+#define DWMREG0_END	0x07ff
+#define DWMREG1		0x0000
+#define DWMREG1_END	0x03ff
+
+#define ISREG0(r)	(((r) >= DWMREG0) && ((r) <= DWMREG0_END))
+#define DMAREG0(r)	(((r) - DWMREG0) >> 2)
+#define DMAREG1(r)	((((r) - DWMREG1) >> 2 ) | 0x0100)
+#define DMAREG(r)	(ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
+
+#define MMREG0		0x0000
+#define MMREG0_END	0x00ff
+
+#define ISMMREG0(r)	(((r) >= MMREG0) && ((r) <= MMREG0_END))
+#define MMSELECT0(r)	(((r) << 2) + DWMREG0)
+#define MMSELECT1(r)	(((((r) & 0xff) << 2) + DWMREG1))
+#define MMSELECT(r)	(ISMMREG0(r) ? MMSELECT0(r) : MMSELECT1(r))
+
+/* ================================================================
+ * DMA constants
+ */
+
+/* DMA descriptor field indices:
+ * The descriptor fields are loaded into the read-only
+ * BM_* system bus master registers during a bus-master operation
+ */
+#define MACH64_DMA_FRAME_BUF_OFFSET	0	/* BM_FRAME_BUF_OFFSET */
+#define MACH64_DMA_SYS_MEM_ADDR		1	/* BM_SYSTEM_MEM_ADDR */
+#define MACH64_DMA_COMMAND		2	/* BM_COMMAND */
+#define MACH64_DMA_RESERVED		3	/* BM_STATUS */
+
+/* BM_COMMAND descriptor field flags */
+#define MACH64_DMA_HOLD_OFFSET		(1<<30)	/* Don't increment DMA_FRAME_BUF_OFFSET */
+#define MACH64_DMA_EOL			(1<<31)	/* End of descriptor list flag */
+
+#define MACH64_DMA_CHUNKSIZE	        0x1000	/* 4kB per DMA descriptor */
+#define MACH64_APERTURE_OFFSET	        0x7ff800	/* frame-buffer offset for gui-masters */
+
+/* ================================================================
+ * Misc helper macros
+ */
+
+static __inline__ void mach64_set_dma_eol(volatile u32 * addr)
+{
+#if defined(__i386__)
+	int nr = 31;
+
+	/* Taken from include/asm-i386/bitops.h linux header */
+	__asm__ __volatile__("lock;" "btsl %1,%0":"=m"(*addr)
+			     :"Ir"(nr));
+#elif defined(__powerpc__)
+	u32 old;
+	u32 mask = cpu_to_le32(MACH64_DMA_EOL);
+
+	/* Taken from the include/asm-ppc/bitops.h linux header */
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	or	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
+	bne-	1b":"=&r"(old), "=m"(*addr)
+			     :"r"(mask), "r"(addr), "m"(*addr)
+			     :"cc");
+#elif defined(__alpha__)
+	u32 temp;
+	u32 mask = MACH64_DMA_EOL;
+
+	/* Taken from the include/asm-alpha/bitops.h linux header */
+	__asm__ __volatile__("1:	ldl_l %0,%3\n"
+			     "	bis %0,%2,%0\n"
+			     "	stl_c %0,%1\n"
+			     "	beq %0,2f\n"
+			     ".subsection 2\n"
+			     "2:	br 1b\n"
+			     ".previous":"=&r"(temp), "=m"(*addr)
+			     :"Ir"(mask), "m"(*addr));
+#else
+	u32 mask = cpu_to_le32(MACH64_DMA_EOL);
+
+	*addr |= mask;
+#endif
+}
+
+static __inline__ void mach64_clear_dma_eol(volatile u32 * addr)
+{
+#if defined(__i386__)
+	int nr = 31;
+
+	/* Taken from include/asm-i386/bitops.h linux header */
+	__asm__ __volatile__("lock;" "btrl %1,%0":"=m"(*addr)
+			     :"Ir"(nr));
+#elif defined(__powerpc__)
+	u32 old;
+	u32 mask = cpu_to_le32(MACH64_DMA_EOL);
+
+	/* Taken from the include/asm-ppc/bitops.h linux header */
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	andc	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
+	bne-	1b":"=&r"(old), "=m"(*addr)
+			     :"r"(mask), "r"(addr), "m"(*addr)
+			     :"cc");
+#elif defined(__alpha__)
+	u32 temp;
+	u32 mask = ~MACH64_DMA_EOL;
+
+	/* Taken from the include/asm-alpha/bitops.h linux header */
+	__asm__ __volatile__("1:	ldl_l %0,%3\n"
+			     "	and %0,%2,%0\n"
+			     "	stl_c %0,%1\n"
+			     "	beq %0,2f\n"
+			     ".subsection 2\n"
+			     "2:	br 1b\n"
+			     ".previous":"=&r"(temp), "=m"(*addr)
+			     :"Ir"(mask), "m"(*addr));
+#else
+	u32 mask = cpu_to_le32(~MACH64_DMA_EOL);
+
+	*addr &= mask;
+#endif
+}
+
+static __inline__ void mach64_ring_start(drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+
+	DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
+		  __FUNCTION__,
+		  ring->head_addr, ring->head, ring->tail, ring->space);
+
+	if (mach64_do_wait_for_idle(dev_priv) < 0) {
+		mach64_do_engine_reset(dev_priv);
+	}
+
+	if (dev_priv->driver_mode != MACH64_MODE_MMIO) {
+		/* enable bus mastering and block 1 registers */
+		MACH64_WRITE(MACH64_BUS_CNTL,
+			     (MACH64_READ(MACH64_BUS_CNTL) &
+			      ~MACH64_BUS_MASTER_DIS)
+			     | MACH64_BUS_EXT_REG_EN);
+		mach64_do_wait_for_idle(dev_priv);
+	}
+
+	/* reset descriptor table ring head */
+	MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
+		     ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
+
+	dev_priv->ring_running = 1;
+}
+
+static __inline__ void mach64_ring_resume(drm_mach64_private_t * dev_priv,
+					  drm_mach64_descriptor_ring_t * ring)
+{
+	DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
+		  __FUNCTION__,
+		  ring->head_addr, ring->head, ring->tail, ring->space);
+
+	/* reset descriptor table ring head */
+	MACH64_WRITE(MACH64_BM_GUI_TABLE_CMD,
+		     ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB);
+
+	if (dev_priv->driver_mode == MACH64_MODE_MMIO) {
+		mach64_do_dispatch_pseudo_dma(dev_priv);
+	} else {
+		/* enable GUI bus mastering, and sync the bus master to the GUI */
+		MACH64_WRITE(MACH64_SRC_CNTL,
+			     MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC |
+			     MACH64_SRC_BM_OP_SYSTEM_TO_REG);
+
+		/* kick off the transfer */
+		MACH64_WRITE(MACH64_DST_HEIGHT_WIDTH, 0);
+		if (dev_priv->driver_mode == MACH64_MODE_DMA_SYNC) {
+			if ((mach64_do_wait_for_idle(dev_priv)) < 0) {
+				DRM_ERROR("%s: idle failed, resetting engine\n",
+					  __FUNCTION__);
+				mach64_dump_engine_info(dev_priv);
+				mach64_do_engine_reset(dev_priv);
+				return;
+			}
+			mach64_do_release_used_buffers(dev_priv);
+		}
+	}
+}
+
+static __inline__ void mach64_ring_tick(drm_mach64_private_t * dev_priv,
+					drm_mach64_descriptor_ring_t * ring)
+{
+	DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
+		  __FUNCTION__,
+		  ring->head_addr, ring->head, ring->tail, ring->space);
+
+	if (!dev_priv->ring_running) {
+		mach64_ring_start(dev_priv);
+
+		if (ring->head != ring->tail) {
+			mach64_ring_resume(dev_priv, ring);
+		}
+	} else {
+		/* GUI_ACTIVE must be read before BM_GUI_TABLE to
+		 * correctly determine the ring head
+		 */
+		int gui_active =
+		    MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE;
+
+		ring->head_addr = MACH64_READ(MACH64_BM_GUI_TABLE) & 0xfffffff0;
+
+		if (gui_active) {
+			/* If not idle, BM_GUI_TABLE points one descriptor
+			 * past the current head
+			 */
+			if (ring->head_addr == ring->start_addr) {
+				ring->head_addr += ring->size;
+			}
+			ring->head_addr -= 4 * sizeof(u32);
+		}
+
+		if (ring->head_addr < ring->start_addr ||
+		    ring->head_addr >= ring->start_addr + ring->size) {
+			DRM_ERROR("bad ring head address: 0x%08x\n",
+				  ring->head_addr);
+			mach64_dump_ring_info(dev_priv);
+			mach64_do_engine_reset(dev_priv);
+			return;
+		}
+
+		ring->head = (ring->head_addr - ring->start_addr) / sizeof(u32);
+
+		if (!gui_active && ring->head != ring->tail) {
+			mach64_ring_resume(dev_priv, ring);
+		}
+	}
+}
+
+static __inline__ void mach64_ring_stop(drm_mach64_private_t * dev_priv)
+{
+	DRM_DEBUG("%s: head_addr: 0x%08x head: %d tail: %d space: %d\n",
+		  __FUNCTION__,
+		  dev_priv->ring.head_addr, dev_priv->ring.head,
+		  dev_priv->ring.tail, dev_priv->ring.space);
+
+	/* restore previous SRC_CNTL to disable busmastering */
+	mach64_do_wait_for_fifo(dev_priv, 1);
+	MACH64_WRITE(MACH64_SRC_CNTL, 0);
+
+	/* disable busmastering but keep the block 1 registers enabled */
+	mach64_do_wait_for_idle(dev_priv);
+	MACH64_WRITE(MACH64_BUS_CNTL, MACH64_READ(MACH64_BUS_CNTL)
+		     | MACH64_BUS_MASTER_DIS | MACH64_BUS_EXT_REG_EN);
+
+	dev_priv->ring_running = 0;
+}
+
+static __inline__ void
+mach64_update_ring_snapshot(drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	mach64_ring_tick(dev_priv, ring);
+
+	ring->space = (ring->head - ring->tail) * sizeof(u32);
+	if (ring->space <= 0) {
+		ring->space += ring->size;
+	}
+}
+
+/* ================================================================
+ * DMA descriptor ring macros
+ */
+
+#define RING_LOCALS									\
+	int _ring_tail, _ring_write; unsigned int _ring_mask; volatile u32 *_ring
+
+#define RING_WRITE_OFS  _ring_write
+
+#define BEGIN_RING( n ) 								\
+do {											\
+	if ( MACH64_VERBOSE ) {								\
+		DRM_INFO( "BEGIN_RING( %d ) in %s\n",					\
+			   (n), __FUNCTION__ );						\
+	}										\
+	if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {				\
+		int ret;								\
+		if ((ret=mach64_wait_ring( dev_priv, (n) * sizeof(u32))) < 0 ) {	\
+			DRM_ERROR( "wait_ring failed, resetting engine\n");		\
+			mach64_dump_engine_info( dev_priv );				\
+			mach64_do_engine_reset( dev_priv );				\
+			return ret;							\
+		}									\
+	}										\
+	dev_priv->ring.space -= (n) * sizeof(u32);					\
+	_ring = (u32 *) dev_priv->ring.start;						\
+	_ring_tail = _ring_write = dev_priv->ring.tail;					\
+	_ring_mask = dev_priv->ring.tail_mask;						\
+} while (0)
+
+#define OUT_RING( x )						\
+do {								\
+	if ( MACH64_VERBOSE ) {					\
+		DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",	\
+			   (unsigned int)(x), _ring_write );	\
+	}							\
+	_ring[_ring_write++] = cpu_to_le32( x );		\
+	_ring_write &= _ring_mask;				\
+} while (0)
+
+#define ADVANCE_RING() 							\
+do {									\
+	if ( MACH64_VERBOSE ) {						\
+		DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",	\
+			  _ring_write, _ring_tail );			\
+	}								\
+	DRM_MEMORYBARRIER();						\
+	mach64_clear_dma_eol( &_ring[(_ring_tail - 2) & _ring_mask] );	\
+	DRM_MEMORYBARRIER();						\
+	dev_priv->ring.tail = _ring_write;				\
+	mach64_ring_tick( dev_priv, &(dev_priv)->ring );		\
+} while (0)
+
+/* ================================================================
+ * DMA macros
+ */
+
+#define DMALOCALS				\
+	drm_mach64_freelist_t *_entry = NULL;	\
+	drm_buf_t *_buf = NULL; 		\
+	u32 *_buf_wptr; int _outcount
+
+#define GETBUFPTR( __buf )						\
+((dev_priv->is_pci) ? 							\
+	((u32 *)(__buf)->address) : 					\
+	((u32 *)((char *)dev_priv->dev_buffers->handle + (__buf)->offset)))
+
+#define GETBUFADDR( __buf ) ((u32)(__buf)->bus_address)
+
+#define GETRINGOFFSET() (_entry->ring_ofs)
+
+static __inline__ int mach64_find_pending_buf_entry(drm_mach64_private_t *
+						    dev_priv,
+						    drm_mach64_freelist_t **
+						    entry, drm_buf_t * buf)
+{
+	struct list_head *ptr;
+#if MACH64_EXTRA_CHECKING
+	if (list_empty(&dev_priv->pending)) {
+		DRM_ERROR("Empty pending list in %s\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+#endif
+	ptr = dev_priv->pending.prev;
+	*entry = list_entry(ptr, drm_mach64_freelist_t, list);
+	while ((*entry)->buf != buf) {
+		if (ptr == &dev_priv->pending) {
+			return DRM_ERR(EFAULT);
+		}
+		ptr = ptr->prev;
+		*entry = list_entry(ptr, drm_mach64_freelist_t, list);
+	}
+	return 0;
+}
+
+#define DMASETPTR( _p ) 			\
+do {						\
+	_buf = (_p);				\
+	_outcount = 0;				\
+	_buf_wptr = GETBUFPTR( _buf );		\
+} while(0)
+
+/* FIXME: use a private set of smaller buffers for state emits, clears, and swaps? */
+#define DMAGETPTR( filp, dev_priv, n )					\
+do {									\
+	if ( MACH64_VERBOSE ) {						\
+		DRM_INFO( "DMAGETPTR( %d ) in %s\n",			\
+			  n, __FUNCTION__ );				\
+	}								\
+	_buf = mach64_freelist_get( dev_priv );				\
+	if (_buf == NULL) {						\
+		DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n",	\
+			   __FUNCTION__ );				\
+		return DRM_ERR(EAGAIN);					\
+	}								\
+	if (_buf->pending) {						\
+	        DRM_ERROR("%s: pending buf in DMAGETPTR\n",		\
+			   __FUNCTION__ );				\
+		return DRM_ERR(EFAULT);					\
+	}								\
+	_buf->filp = filp;						\
+	_outcount = 0;							\
+									\
+        _buf_wptr = GETBUFPTR( _buf );					\
+} while (0)
+
+#define DMAOUTREG( reg, val )					\
+do {								\
+	if ( MACH64_VERBOSE ) {					\
+		DRM_INFO( "   DMAOUTREG( 0x%x = 0x%08x )\n",	\
+			  reg, val );				\
+	}							\
+	_buf_wptr[_outcount++] = cpu_to_le32(DMAREG(reg));	\
+	_buf_wptr[_outcount++] = cpu_to_le32((val));		\
+	_buf->used += 8;					\
+} while (0)
+
+#define DMAADVANCE( dev_priv, _discard )						     \
+do {											     \
+	struct list_head *ptr;								     \
+	RING_LOCALS;									     \
+											     \
+	if ( MACH64_VERBOSE ) {								     \
+		DRM_INFO( "DMAADVANCE() in %s\n", __FUNCTION__ );			     \
+	}										     \
+											     \
+	if (_buf->used <= 0) {								     \
+		DRM_ERROR( "DMAADVANCE() in %s: sending empty buf %d\n",		     \
+				   __FUNCTION__, _buf->idx );				     \
+		return DRM_ERR(EFAULT);							     \
+	}										     \
+	if (_buf->pending) {								     \
+                /* This is a resued buffer, so we need to find it in the pending list */     \
+		int ret;								     \
+		if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) {	     \
+			DRM_ERROR( "DMAADVANCE() in %s: couldn't find pending buf %d\n",     \
+				   __FUNCTION__, _buf->idx );				     \
+			return ret;							     \
+		}									     \
+		if (_entry->discard) {							     \
+			DRM_ERROR( "DMAADVANCE() in %s: sending discarded pending buf %d\n", \
+				   __FUNCTION__, _buf->idx );				     \
+			return DRM_ERR(EFAULT);						     \
+		}									     \
+     	} else {									     \
+		if (list_empty(&dev_priv->placeholders)) {				     \
+			DRM_ERROR( "DMAADVANCE() in %s: empty placeholder list\n",	     \
+			   	__FUNCTION__ );						     \
+			return DRM_ERR(EFAULT);						     \
+		}									     \
+		ptr = dev_priv->placeholders.next;					     \
+		list_del(ptr);								     \
+		_entry = list_entry(ptr, drm_mach64_freelist_t, list);			     \
+		_buf->pending = 1;							     \
+		_entry->buf = _buf;							     \
+		list_add_tail(ptr, &dev_priv->pending);					     \
+	}										     \
+	_entry->discard = (_discard);							     \
+	ADD_BUF_TO_RING( dev_priv );							     \
+} while (0)
+
+#define DMADISCARDBUF()									\
+do {											\
+	if (_entry == NULL) {								\
+		int ret;								\
+		if ( (ret=mach64_find_pending_buf_entry(dev_priv, &_entry, _buf)) ) {	\
+			DRM_ERROR( "%s: couldn't find pending buf %d\n",		\
+				   __FUNCTION__, _buf->idx );				\
+			return ret;							\
+		}									\
+	}										\
+	_entry->discard = 1;								\
+} while(0)
+
+#define ADD_BUF_TO_RING( dev_priv )							\
+do {											\
+	int bytes, pages, remainder;							\
+	u32 address, page;								\
+	int i;										\
+											\
+	bytes = _buf->used;								\
+	address = GETBUFADDR( _buf );							\
+											\
+	pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE;		\
+											\
+	BEGIN_RING( pages * 4 );							\
+											\
+	for ( i = 0 ; i < pages-1 ; i++ ) {						\
+		page = address + i * MACH64_DMA_CHUNKSIZE;				\
+		OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR );			\
+		OUT_RING( page );							\
+		OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET );		\
+		OUT_RING( 0 );								\
+	}										\
+											\
+	/* generate the final descriptor for any remaining commands in this buffer */	\
+	page = address + i * MACH64_DMA_CHUNKSIZE;					\
+	remainder = bytes - i * MACH64_DMA_CHUNKSIZE;					\
+											\
+	/* Save dword offset of last descriptor for this buffer.			\
+	 * This is needed to check for completion of the buffer in freelist_get		\
+	 */										\
+	_entry->ring_ofs = RING_WRITE_OFS;						\
+											\
+	OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR );				\
+	OUT_RING( page );								\
+	OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL );		\
+	OUT_RING( 0 );									\
+											\
+	ADVANCE_RING();									\
+} while(0)
+
+#define DMAADVANCEHOSTDATA( dev_priv )							\
+do {											\
+	struct list_head *ptr;								\
+	RING_LOCALS;									\
+											\
+	if ( MACH64_VERBOSE ) {								\
+		DRM_INFO( "DMAADVANCEHOSTDATA() in %s\n", __FUNCTION__ );		\
+	}										\
+											\
+	if (_buf->used <= 0) {								\
+		DRM_ERROR( "DMAADVANCEHOSTDATA() in %s: sending empty buf %d\n",	\
+				   __FUNCTION__, _buf->idx );				\
+		return DRM_ERR(EFAULT);							\
+	}										\
+	if (list_empty(&dev_priv->placeholders)) {					\
+		DRM_ERROR( "%s: empty placeholder list in DMAADVANCEHOSTDATA()\n",	\
+			   __FUNCTION__ );						\
+		return DRM_ERR(EFAULT);							\
+	}										\
+											\
+        ptr = dev_priv->placeholders.next;						\
+	list_del(ptr);									\
+	_entry = list_entry(ptr, drm_mach64_freelist_t, list);				\
+	_entry->buf = _buf;								\
+	_entry->buf->pending = 1;							\
+	list_add_tail(ptr, &dev_priv->pending);						\
+	_entry->discard = 1;								\
+	ADD_HOSTDATA_BUF_TO_RING( dev_priv );						\
+} while (0)
+
+#define ADD_HOSTDATA_BUF_TO_RING( dev_priv )						 \
+do {											 \
+	int bytes, pages, remainder;							 \
+	u32 address, page;								 \
+	int i;										 \
+											 \
+	bytes = _buf->used - MACH64_HOSTDATA_BLIT_OFFSET;				 \
+	pages = (bytes + MACH64_DMA_CHUNKSIZE - 1) / MACH64_DMA_CHUNKSIZE;		 \
+	address = GETBUFADDR( _buf );							 \
+											 \
+	BEGIN_RING( 4 + pages * 4 );							 \
+											 \
+	OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_ADDR );				 \
+	OUT_RING( address );								 \
+	OUT_RING( MACH64_HOSTDATA_BLIT_OFFSET | MACH64_DMA_HOLD_OFFSET );		 \
+	OUT_RING( 0 );									 \
+											 \
+	address += MACH64_HOSTDATA_BLIT_OFFSET;						 \
+											 \
+	for ( i = 0 ; i < pages-1 ; i++ ) {						 \
+		page = address + i * MACH64_DMA_CHUNKSIZE;				 \
+		OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA );		 \
+		OUT_RING( page );							 \
+		OUT_RING( MACH64_DMA_CHUNKSIZE | MACH64_DMA_HOLD_OFFSET );		 \
+		OUT_RING( 0 );								 \
+	}										 \
+											 \
+	/* generate the final descriptor for any remaining commands in this buffer */	 \
+	page = address + i * MACH64_DMA_CHUNKSIZE;					 \
+	remainder = bytes - i * MACH64_DMA_CHUNKSIZE;					 \
+											 \
+	/* Save dword offset of last descriptor for this buffer.			 \
+	 * This is needed to check for completion of the buffer in freelist_get		 \
+	 */										 \
+	_entry->ring_ofs = RING_WRITE_OFS;						 \
+											 \
+	OUT_RING( MACH64_APERTURE_OFFSET + MACH64_BM_HOSTDATA );			 \
+	OUT_RING( page );								 \
+	OUT_RING( remainder | MACH64_DMA_HOLD_OFFSET | MACH64_DMA_EOL );		 \
+	OUT_RING( 0 );									 \
+											 \
+	ADVANCE_RING();									 \
+} while(0)
+
+#endif				/* __MACH64_DRV_H__ */
--- libdrm-2.3.0.orig/shared-core/via_drv.c
+++ libdrm-2.3.0/shared-core/via_drv.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 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 "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+#include "drm_pciids.h"
+
+
+static int dri_library_name(struct drm_device * dev, char * buf)
+{
+	return snprintf(buf, PAGE_SIZE, "unichrome\n");
+}
+
+static struct pci_device_id pciidlist[] = {
+	viadrv_PCI_IDS
+};
+
+static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static struct drm_driver driver = {
+	.driver_features =
+	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
+	    DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+	.load = via_driver_load,
+	.unload = via_driver_unload,
+#ifndef VIA_HAVE_CORE_MM
+	.context_ctor = via_init_context,
+#endif
+	.context_dtor = via_final_context,
+	.vblank_wait = via_driver_vblank_wait,
+	.irq_preinstall = via_driver_irq_preinstall,
+	.irq_postinstall = via_driver_irq_postinstall,
+	.irq_uninstall = via_driver_irq_uninstall,
+	.irq_handler = via_driver_irq_handler,
+	.dma_quiescent = via_driver_dma_quiescent,
+	.dri_library_name = dri_library_name,
+	.reclaim_buffers = drm_core_reclaim_buffers,
+#ifdef VIA_HAVE_CORE_MM
+	.reclaim_buffers_locked = via_reclaim_buffers_locked,
+	.lastclose = via_lastclose,
+#endif
+	.get_map_ofs = drm_core_get_map_ofs,
+	.get_reg_ofs = drm_core_get_reg_ofs,
+	.ioctls = via_ioctls,
+	.fops = {
+		.owner = THIS_MODULE,
+		.open = drm_open,
+		.release = drm_release,
+		.ioctl = drm_ioctl,
+		.mmap = drm_mmap,
+		.poll = drm_poll,
+		.fasync = drm_fasync,
+		},
+	.pci_driver = {
+		.name = DRIVER_NAME,
+		.id_table = pciidlist,
+		.probe = probe,
+		.remove = __devexit_p(drm_cleanup_pci),
+	},
+
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+	.date = VIA_DRM_DRIVER_DATE,
+	.major = VIA_DRM_DRIVER_MAJOR,
+	.minor = VIA_DRM_DRIVER_MINOR,
+	.patchlevel = VIA_DRM_DRIVER_PATCHLEVEL
+};
+
+static int probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	return drm_get_dev(pdev, ent, &driver);
+}
+
+static int __init via_init(void)
+{
+	driver.num_ioctls = via_max_ioctl;
+
+	via_init_command_verifier();
+	return drm_init(&driver, pciidlist);
+}
+
+static void __exit via_exit(void)
+{
+	drm_exit(&driver);
+}
+
+module_init(via_init);
+module_exit(via_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
--- libdrm-2.3.0.orig/shared-core/radeon_state.c
+++ libdrm-2.3.0/shared-core/radeon_state.c
@@ -0,0 +1,3301 @@
+/* radeon_state.c -- State support for Radeon -*- linux-c -*- */
+/*
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Kevin E. Martin <martin@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sarea.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+/* ================================================================
+ * Helper functions for client state checking and fixup
+ */
+
+static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
+						    dev_priv,
+						    drm_file_t * filp_priv,
+						    u32 * offset)
+{
+	u64 off = *offset;
+	u32 fb_start = dev_priv->fb_location;
+	u32 fb_end = fb_start + dev_priv->fb_size - 1;
+	u32 gart_start = dev_priv->gart_vm_start;
+	u32 gart_end = gart_start + dev_priv->gart_size - 1;
+	struct drm_radeon_driver_file_fields *radeon_priv;
+
+	/* Hrm ... the story of the offset ... So this function converts
+	 * the various ideas of what userland clients might have for an
+	 * offset in the card address space into an offset into the card
+	 * address space :) So with a sane client, it should just keep
+	 * the value intact and just do some boundary checking. However,
+	 * not all clients are sane. Some older clients pass us 0 based
+	 * offsets relative to the start of the framebuffer and some may
+	 * assume the AGP aperture it appended to the framebuffer, so we
+	 * try to detect those cases and fix them up.
+	 *
+	 * Note: It might be a good idea here to make sure the offset lands
+	 * in some "allowed" area to protect things like the PCIE GART...
+	 */
+
+	/* First, the best case, the offset already lands in either the
+	 * framebuffer or the GART mapped space
+	 */
+	if ((off >= fb_start && off <= fb_end) ||
+	    (off >= gart_start && off <= gart_end))
+		return 0;
+
+	/* Ok, that didn't happen... now check if we have a zero based
+	 * offset that fits in the framebuffer + gart space, apply the
+	 * magic offset we get from SETPARAM or calculated from fb_location
+	 */
+	if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
+		radeon_priv = filp_priv->driver_priv;
+		off += radeon_priv->radeon_fb_delta;
+	}
+
+	/* Finally, assume we aimed at a GART offset if beyond the fb */
+	if (off > fb_end)
+		off = off - fb_end - 1 + gart_start;
+
+	/* Now recheck and fail if out of bounds */
+	if ((off >= fb_start && off <= fb_end) ||
+	    (off >= gart_start && off <= gart_end)) {
+		DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
+		*offset = off;
+		return 0;
+	}
+	return DRM_ERR(EINVAL);
+}
+
+static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
+						     dev_priv,
+						     drm_file_t * filp_priv,
+						     int id, u32 *data)
+{
+	switch (id) {
+
+	case RADEON_EMIT_PP_MISC:
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+		    &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
+			DRM_ERROR("Invalid depth buffer offset\n");
+			return DRM_ERR(EINVAL);
+		}
+		break;
+
+	case RADEON_EMIT_PP_CNTL:
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+		    &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
+			DRM_ERROR("Invalid colour buffer offset\n");
+			return DRM_ERR(EINVAL);
+		}
+		break;
+
+	case R200_EMIT_PP_TXOFFSET_0:
+	case R200_EMIT_PP_TXOFFSET_1:
+	case R200_EMIT_PP_TXOFFSET_2:
+	case R200_EMIT_PP_TXOFFSET_3:
+	case R200_EMIT_PP_TXOFFSET_4:
+	case R200_EMIT_PP_TXOFFSET_5:
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+						  &data[0])) {
+			DRM_ERROR("Invalid R200 texture offset\n");
+			return DRM_ERR(EINVAL);
+		}
+		break;
+
+	case RADEON_EMIT_PP_TXFILTER_0:
+	case RADEON_EMIT_PP_TXFILTER_1:
+	case RADEON_EMIT_PP_TXFILTER_2:
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+		    &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
+			DRM_ERROR("Invalid R100 texture offset\n");
+			return DRM_ERR(EINVAL);
+		}
+		break;
+
+	case R200_EMIT_PP_CUBIC_OFFSETS_0:
+	case R200_EMIT_PP_CUBIC_OFFSETS_1:
+	case R200_EMIT_PP_CUBIC_OFFSETS_2:
+	case R200_EMIT_PP_CUBIC_OFFSETS_3:
+	case R200_EMIT_PP_CUBIC_OFFSETS_4:
+	case R200_EMIT_PP_CUBIC_OFFSETS_5:{
+			int i;
+			for (i = 0; i < 5; i++) {
+				if (radeon_check_and_fixup_offset(dev_priv,
+								  filp_priv,
+								  &data[i])) {
+					DRM_ERROR
+					    ("Invalid R200 cubic texture offset\n");
+					return DRM_ERR(EINVAL);
+				}
+			}
+			break;
+		}
+
+	case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
+	case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
+	case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
+			int i;
+			for (i = 0; i < 5; i++) {
+				if (radeon_check_and_fixup_offset(dev_priv,
+								  filp_priv,
+								  &data[i])) {
+					DRM_ERROR
+					    ("Invalid R100 cubic texture offset\n");
+					return DRM_ERR(EINVAL);
+				}
+			}
+		}
+		break;
+
+	case R200_EMIT_VAP_CTL: {
+			RING_LOCALS;
+			BEGIN_RING(2);
+			OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+			ADVANCE_RING();
+		}
+		break;
+
+	case RADEON_EMIT_RB3D_COLORPITCH:
+	case RADEON_EMIT_RE_LINE_PATTERN:
+	case RADEON_EMIT_SE_LINE_WIDTH:
+	case RADEON_EMIT_PP_LUM_MATRIX:
+	case RADEON_EMIT_PP_ROT_MATRIX_0:
+	case RADEON_EMIT_RB3D_STENCILREFMASK:
+	case RADEON_EMIT_SE_VPORT_XSCALE:
+	case RADEON_EMIT_SE_CNTL:
+	case RADEON_EMIT_SE_CNTL_STATUS:
+	case RADEON_EMIT_RE_MISC:
+	case RADEON_EMIT_PP_BORDER_COLOR_0:
+	case RADEON_EMIT_PP_BORDER_COLOR_1:
+	case RADEON_EMIT_PP_BORDER_COLOR_2:
+	case RADEON_EMIT_SE_ZBIAS_FACTOR:
+	case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
+	case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
+	case R200_EMIT_PP_TXCBLEND_0:
+	case R200_EMIT_PP_TXCBLEND_1:
+	case R200_EMIT_PP_TXCBLEND_2:
+	case R200_EMIT_PP_TXCBLEND_3:
+	case R200_EMIT_PP_TXCBLEND_4:
+	case R200_EMIT_PP_TXCBLEND_5:
+	case R200_EMIT_PP_TXCBLEND_6:
+	case R200_EMIT_PP_TXCBLEND_7:
+	case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
+	case R200_EMIT_TFACTOR_0:
+	case R200_EMIT_VTX_FMT_0:
+	case R200_EMIT_MATRIX_SELECT_0:
+	case R200_EMIT_TEX_PROC_CTL_2:
+	case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
+	case R200_EMIT_PP_TXFILTER_0:
+	case R200_EMIT_PP_TXFILTER_1:
+	case R200_EMIT_PP_TXFILTER_2:
+	case R200_EMIT_PP_TXFILTER_3:
+	case R200_EMIT_PP_TXFILTER_4:
+	case R200_EMIT_PP_TXFILTER_5:
+	case R200_EMIT_VTE_CNTL:
+	case R200_EMIT_OUTPUT_VTX_COMP_SEL:
+	case R200_EMIT_PP_TAM_DEBUG3:
+	case R200_EMIT_PP_CNTL_X:
+	case R200_EMIT_RB3D_DEPTHXY_OFFSET:
+	case R200_EMIT_RE_AUX_SCISSOR_CNTL:
+	case R200_EMIT_RE_SCISSOR_TL_0:
+	case R200_EMIT_RE_SCISSOR_TL_1:
+	case R200_EMIT_RE_SCISSOR_TL_2:
+	case R200_EMIT_SE_VAP_CNTL_STATUS:
+	case R200_EMIT_SE_VTX_STATE_CNTL:
+	case R200_EMIT_RE_POINTSIZE:
+	case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0:
+	case R200_EMIT_PP_CUBIC_FACES_0:
+	case R200_EMIT_PP_CUBIC_FACES_1:
+	case R200_EMIT_PP_CUBIC_FACES_2:
+	case R200_EMIT_PP_CUBIC_FACES_3:
+	case R200_EMIT_PP_CUBIC_FACES_4:
+	case R200_EMIT_PP_CUBIC_FACES_5:
+	case RADEON_EMIT_PP_TEX_SIZE_0:
+	case RADEON_EMIT_PP_TEX_SIZE_1:
+	case RADEON_EMIT_PP_TEX_SIZE_2:
+	case R200_EMIT_RB3D_BLENDCOLOR:
+	case R200_EMIT_TCL_POINT_SPRITE_CNTL:
+	case RADEON_EMIT_PP_CUBIC_FACES_0:
+	case RADEON_EMIT_PP_CUBIC_FACES_1:
+	case RADEON_EMIT_PP_CUBIC_FACES_2:
+	case R200_EMIT_PP_TRI_PERF_CNTL:
+	case R200_EMIT_PP_AFS_0:
+	case R200_EMIT_PP_AFS_1:
+	case R200_EMIT_ATF_TFACTOR:
+	case R200_EMIT_PP_TXCTLALL_0:
+	case R200_EMIT_PP_TXCTLALL_1:
+	case R200_EMIT_PP_TXCTLALL_2:
+	case R200_EMIT_PP_TXCTLALL_3:
+	case R200_EMIT_PP_TXCTLALL_4:
+	case R200_EMIT_PP_TXCTLALL_5:
+	case R200_EMIT_VAP_PVS_CNTL:
+		/* These packets don't contain memory offsets */
+		break;
+
+	default:
+		DRM_ERROR("Unknown state packet ID %d\n", id);
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
+						     dev_priv,
+						     drm_file_t *filp_priv,
+						     drm_radeon_kcmd_buffer_t *
+						     cmdbuf,
+						     unsigned int *cmdsz)
+{
+	u32 *cmd = (u32 *) cmdbuf->buf;
+	u32 offset, narrays;
+	int count, i, k;
+
+	*cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+
+	if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
+		DRM_ERROR("Not a type 3 packet\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (4 * *cmdsz > cmdbuf->bufsz) {
+		DRM_ERROR("Packet size larger than size of data provided\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	switch(cmd[0] & 0xff00) {
+	/* XXX Are there old drivers needing other packets? */
+
+	case RADEON_3D_DRAW_IMMD:
+	case RADEON_3D_DRAW_VBUF:
+	case RADEON_3D_DRAW_INDX:
+	case RADEON_WAIT_FOR_IDLE:
+	case RADEON_CP_NOP:
+	case RADEON_3D_CLEAR_ZMASK:
+/*	case RADEON_CP_NEXT_CHAR:
+	case RADEON_CP_PLY_NEXTSCAN:
+	case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */
+		/* these packets are safe */
+		break;
+
+	case RADEON_CP_3D_DRAW_IMMD_2:
+	case RADEON_CP_3D_DRAW_VBUF_2:
+	case RADEON_CP_3D_DRAW_INDX_2:
+	case RADEON_3D_CLEAR_HIZ:
+		/* safe but r200 only */
+		if (dev_priv->microcode_version != UCODE_R200) {
+			DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+			return DRM_ERR(EINVAL);
+		}
+		break;
+
+	case RADEON_3D_LOAD_VBPNTR:
+		count = (cmd[0] >> 16) & 0x3fff;
+
+		if (count > 18) { /* 12 arrays max */
+			DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
+				  count);
+			return DRM_ERR(EINVAL);
+		}
+
+		/* carefully check packet contents */
+		narrays = cmd[1] & ~0xc000;
+		k = 0;
+		i = 2;
+		while ((k < narrays) && (i < (count + 2))) {
+			i++;		/* skip attribute field */
+			if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
+				DRM_ERROR
+				    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
+				     k, i);
+				return DRM_ERR(EINVAL);
+			}
+			k++;
+			i++;
+			if (k == narrays)
+				break;
+			/* have one more to process, they come in pairs */
+			if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
+				DRM_ERROR
+				    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
+				     k, i);
+				return DRM_ERR(EINVAL);
+			}
+			k++;
+			i++;
+		}
+		/* do the counts match what we expect ? */
+		if ((k != narrays) || (i != (count + 2))) {
+			DRM_ERROR
+			    ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
+			      k, i, narrays, count + 1);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+
+	case RADEON_3D_RNDR_GEN_INDX_PRIM:
+		if (dev_priv->microcode_version != UCODE_R100) {
+			DRM_ERROR("Invalid 3d packet for r200-class chip\n");
+			return DRM_ERR(EINVAL);
+		}
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) {
+				DRM_ERROR("Invalid rndr_gen_indx offset\n");
+				return DRM_ERR(EINVAL);
+		}
+		break;
+
+	case RADEON_CP_INDX_BUFFER:
+		if (dev_priv->microcode_version != UCODE_R200) {
+			DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+			return DRM_ERR(EINVAL);
+		}
+		if ((cmd[1] & 0x8000ffff) != 0x80000810) {
+			DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+			return DRM_ERR(EINVAL);
+		}
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) {
+			DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+			return DRM_ERR(EINVAL);
+		}
+		break;
+
+	case RADEON_CNTL_HOSTDATA_BLT:
+	case RADEON_CNTL_PAINT_MULTI:
+	case RADEON_CNTL_BITBLT_MULTI:
+		/* MSB of opcode: next DWORD GUI_CNTL */
+		if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+			      | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+			offset = cmd[2] << 10;
+			if (radeon_check_and_fixup_offset
+			    (dev_priv, filp_priv, &offset)) {
+				DRM_ERROR("Invalid first packet offset\n");
+				return DRM_ERR(EINVAL);
+			}
+			cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
+		}
+
+		if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
+		    (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+			offset = cmd[3] << 10;
+			if (radeon_check_and_fixup_offset
+			    (dev_priv, filp_priv, &offset)) {
+				DRM_ERROR("Invalid second packet offset\n");
+				return DRM_ERR(EINVAL);
+			}
+			cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
+		}
+		break;
+
+	default:
+		DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
+
+/* ================================================================
+ * CP hardware state programming functions
+ */
+
+static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
+					     drm_clip_rect_t * box)
+{
+	RING_LOCALS;
+
+	DRM_DEBUG("   box:  x1=%d y1=%d  x2=%d y2=%d\n",
+		  box->x1, box->y1, box->x2, box->y2);
+
+	BEGIN_RING(4);
+	OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
+	OUT_RING((box->y1 << 16) | box->x1);
+	OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
+	OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
+	ADVANCE_RING();
+}
+
+/* Emit 1.1 state
+ */
+static int radeon_emit_state(drm_radeon_private_t * dev_priv,
+			     drm_file_t * filp_priv,
+			     drm_radeon_context_regs_t * ctx,
+			     drm_radeon_texture_regs_t * tex,
+			     unsigned int dirty)
+{
+	RING_LOCALS;
+	DRM_DEBUG("dirty=0x%08x\n", dirty);
+
+	if (dirty & RADEON_UPLOAD_CONTEXT) {
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+						  &ctx->rb3d_depthoffset)) {
+			DRM_ERROR("Invalid depth buffer offset\n");
+			return DRM_ERR(EINVAL);
+		}
+
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+						  &ctx->rb3d_coloroffset)) {
+			DRM_ERROR("Invalid depth buffer offset\n");
+			return DRM_ERR(EINVAL);
+		}
+
+		BEGIN_RING(14);
+		OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
+		OUT_RING(ctx->pp_misc);
+		OUT_RING(ctx->pp_fog_color);
+		OUT_RING(ctx->re_solid_color);
+		OUT_RING(ctx->rb3d_blendcntl);
+		OUT_RING(ctx->rb3d_depthoffset);
+		OUT_RING(ctx->rb3d_depthpitch);
+		OUT_RING(ctx->rb3d_zstencilcntl);
+		OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
+		OUT_RING(ctx->pp_cntl);
+		OUT_RING(ctx->rb3d_cntl);
+		OUT_RING(ctx->rb3d_coloroffset);
+		OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
+		OUT_RING(ctx->rb3d_colorpitch);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_VERTFMT) {
+		BEGIN_RING(2);
+		OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
+		OUT_RING(ctx->se_coord_fmt);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_LINE) {
+		BEGIN_RING(5);
+		OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
+		OUT_RING(ctx->re_line_pattern);
+		OUT_RING(ctx->re_line_state);
+		OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
+		OUT_RING(ctx->se_line_width);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_BUMPMAP) {
+		BEGIN_RING(5);
+		OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
+		OUT_RING(ctx->pp_lum_matrix);
+		OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
+		OUT_RING(ctx->pp_rot_matrix_0);
+		OUT_RING(ctx->pp_rot_matrix_1);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_MASKS) {
+		BEGIN_RING(4);
+		OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
+		OUT_RING(ctx->rb3d_stencilrefmask);
+		OUT_RING(ctx->rb3d_ropcntl);
+		OUT_RING(ctx->rb3d_planemask);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_VIEWPORT) {
+		BEGIN_RING(7);
+		OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
+		OUT_RING(ctx->se_vport_xscale);
+		OUT_RING(ctx->se_vport_xoffset);
+		OUT_RING(ctx->se_vport_yscale);
+		OUT_RING(ctx->se_vport_yoffset);
+		OUT_RING(ctx->se_vport_zscale);
+		OUT_RING(ctx->se_vport_zoffset);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_SETUP) {
+		BEGIN_RING(4);
+		OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
+		OUT_RING(ctx->se_cntl);
+		OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
+		OUT_RING(ctx->se_cntl_status);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_MISC) {
+		BEGIN_RING(2);
+		OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
+		OUT_RING(ctx->re_misc);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_TEX0) {
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+						  &tex[0].pp_txoffset)) {
+			DRM_ERROR("Invalid texture offset for unit 0\n");
+			return DRM_ERR(EINVAL);
+		}
+
+		BEGIN_RING(9);
+		OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
+		OUT_RING(tex[0].pp_txfilter);
+		OUT_RING(tex[0].pp_txformat);
+		OUT_RING(tex[0].pp_txoffset);
+		OUT_RING(tex[0].pp_txcblend);
+		OUT_RING(tex[0].pp_txablend);
+		OUT_RING(tex[0].pp_tfactor);
+		OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
+		OUT_RING(tex[0].pp_border_color);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_TEX1) {
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+						  &tex[1].pp_txoffset)) {
+			DRM_ERROR("Invalid texture offset for unit 1\n");
+			return DRM_ERR(EINVAL);
+		}
+
+		BEGIN_RING(9);
+		OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
+		OUT_RING(tex[1].pp_txfilter);
+		OUT_RING(tex[1].pp_txformat);
+		OUT_RING(tex[1].pp_txoffset);
+		OUT_RING(tex[1].pp_txcblend);
+		OUT_RING(tex[1].pp_txablend);
+		OUT_RING(tex[1].pp_tfactor);
+		OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
+		OUT_RING(tex[1].pp_border_color);
+		ADVANCE_RING();
+	}
+
+	if (dirty & RADEON_UPLOAD_TEX2) {
+		if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
+						  &tex[2].pp_txoffset)) {
+			DRM_ERROR("Invalid texture offset for unit 2\n");
+			return DRM_ERR(EINVAL);
+		}
+
+		BEGIN_RING(9);
+		OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
+		OUT_RING(tex[2].pp_txfilter);
+		OUT_RING(tex[2].pp_txformat);
+		OUT_RING(tex[2].pp_txoffset);
+		OUT_RING(tex[2].pp_txcblend);
+		OUT_RING(tex[2].pp_txablend);
+		OUT_RING(tex[2].pp_tfactor);
+		OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
+		OUT_RING(tex[2].pp_border_color);
+		ADVANCE_RING();
+	}
+
+	return 0;
+}
+
+/* Emit 1.2 state
+ */
+static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
+			      drm_file_t * filp_priv,
+			      drm_radeon_state_t * state)
+{
+	RING_LOCALS;
+
+	if (state->dirty & RADEON_UPLOAD_ZBIAS) {
+		BEGIN_RING(3);
+		OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
+		OUT_RING(state->context2.se_zbias_factor);
+		OUT_RING(state->context2.se_zbias_constant);
+		ADVANCE_RING();
+	}
+
+	return radeon_emit_state(dev_priv, filp_priv, &state->context,
+				 state->tex, state->dirty);
+}
+
+/* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
+ * 1.3 cmdbuffers allow all previous state to be updated as well as
+ * the tcl scalar and vector areas.
+ */
+static struct {
+	int start;
+	int len;
+	const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+	{RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
+	{RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
+	{RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
+	{RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
+	{RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
+	{RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
+	{RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
+	{RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
+	{RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
+	{RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
+	{RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
+	{RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
+	{RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
+	{RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
+	{RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
+	{RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
+	{RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
+	{RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
+	{RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
+	{RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
+	{RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
+		    "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
+	{R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
+	{R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
+	{R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
+	{R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
+	{R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
+	{R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
+	{R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
+	{R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
+	{R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
+	{R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
+	{R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
+	{R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
+	{R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
+	{R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
+	{R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
+	{R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
+	{R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
+	{R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
+	{R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
+	{R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
+	{R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
+	{R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
+	{R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
+	{R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
+	{R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
+	{R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
+	{R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
+	{R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
+	{R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1,
+	 "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
+	{R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
+	{R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
+	{R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
+	{R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
+	{R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
+	{R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
+	{R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
+	{R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
+	{R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
+	{R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
+	{R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
+		    "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
+	{R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"},	/* 61 */
+	{R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
+	{R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
+	{R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
+	{R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
+	{R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
+	{R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
+	{R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
+	{R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
+	{R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
+	{R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
+	{R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
+	{RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
+	{RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
+	{RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
+	{R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
+	{R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
+	{RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
+	{RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
+	{RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
+	{RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
+	{RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
+	{RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
+	{R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
+	{R200_PP_AFS_0, 32, "R200_PP_AFS_0"},     /* 85 */
+	{R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
+	{R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
+	{R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
+	{R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
+	{R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
+	{R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
+	{R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
+	{R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
+	{R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
+};
+
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void radeon_clear_box(drm_radeon_private_t * dev_priv,
+			     int x, int y, int w, int h, int r, int g, int b)
+{
+	u32 color;
+	RING_LOCALS;
+
+	x += dev_priv->sarea_priv->boxes[0].x1;
+	y += dev_priv->sarea_priv->boxes[0].y1;
+
+	switch (dev_priv->color_fmt) {
+	case RADEON_COLOR_FORMAT_RGB565:
+		color = (((r & 0xf8) << 8) |
+			 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
+		break;
+	case RADEON_COLOR_FORMAT_ARGB8888:
+	default:
+		color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+		break;
+	}
+
+	BEGIN_RING(4);
+	RADEON_WAIT_UNTIL_3D_IDLE();
+	OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
+	OUT_RING(0xffffffff);
+	ADVANCE_RING();
+
+	BEGIN_RING(6);
+
+	OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4));
+	OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+		 RADEON_GMC_BRUSH_SOLID_COLOR |
+		 (dev_priv->color_fmt << 8) |
+		 RADEON_GMC_SRC_DATATYPE_COLOR |
+		 RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+	if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+		OUT_RING(dev_priv->front_pitch_offset);
+	} else {
+		OUT_RING(dev_priv->back_pitch_offset);
+	}
+
+	OUT_RING(color);
+
+	OUT_RING((x << 16) | y);
+	OUT_RING((w << 16) | h);
+
+	ADVANCE_RING();
+}
+
+static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
+{
+	/* Collapse various things into a wait flag -- trying to
+	 * guess if userspase slept -- better just to have them tell us.
+	 */
+	if (dev_priv->stats.last_frame_reads > 1 ||
+	    dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
+		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+	}
+
+	if (dev_priv->stats.freelist_loops) {
+		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+	}
+
+	/* Purple box for page flipping
+	 */
+	if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
+		radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
+
+	/* Red box if we have to wait for idle at any point
+	 */
+	if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
+		radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
+
+	/* Blue box: lost context?
+	 */
+
+	/* Yellow box for texture swaps
+	 */
+	if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
+		radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
+
+	/* Green box if hardware never idles (as far as we can tell)
+	 */
+	if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
+		radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
+
+	/* Draw bars indicating number of buffers allocated
+	 * (not a great measure, easily confused)
+	 */
+	if (dev_priv->stats.requested_bufs) {
+		if (dev_priv->stats.requested_bufs > 100)
+			dev_priv->stats.requested_bufs = 100;
+
+		radeon_clear_box(dev_priv, 4, 16,
+				 dev_priv->stats.requested_bufs, 4,
+				 196, 128, 128);
+	}
+
+	memset(&dev_priv->stats, 0, sizeof(dev_priv->stats));
+
+}
+
+/* ================================================================
+ * CP command dispatch functions
+ */
+
+static void radeon_cp_dispatch_clear(drm_device_t * dev,
+				     drm_radeon_clear_t * clear,
+				     drm_radeon_clear_rect_t * depth_boxes)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
+	int nbox = sarea_priv->nbox;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	unsigned int flags = clear->flags;
+	u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG("flags = 0x%x\n", flags);
+
+	dev_priv->stats.clears++;
+
+	if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+		unsigned int tmp = flags;
+
+		flags &= ~(RADEON_FRONT | RADEON_BACK);
+		if (tmp & RADEON_FRONT)
+			flags |= RADEON_BACK;
+		if (tmp & RADEON_BACK)
+			flags |= RADEON_FRONT;
+	}
+
+	if (flags & (RADEON_FRONT | RADEON_BACK)) {
+
+		BEGIN_RING(4);
+
+		/* Ensure the 3D stream is idle before doing a
+		 * 2D fill to clear the front or back buffer.
+		 */
+		RADEON_WAIT_UNTIL_3D_IDLE();
+
+		OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
+		OUT_RING(clear->color_mask);
+
+		ADVANCE_RING();
+
+		/* Make sure we restore the 3D state next time.
+		 */
+		dev_priv->sarea_priv->ctx_owner = 0;
+
+		for (i = 0; i < nbox; i++) {
+			int x = pbox[i].x1;
+			int y = pbox[i].y1;
+			int w = pbox[i].x2 - x;
+			int h = pbox[i].y2 - y;
+
+			DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
+				  x, y, w, h, flags);
+
+			if (flags & RADEON_FRONT) {
+				BEGIN_RING(6);
+
+				OUT_RING(CP_PACKET3
+					 (RADEON_CNTL_PAINT_MULTI, 4));
+				OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+					 RADEON_GMC_BRUSH_SOLID_COLOR |
+					 (dev_priv->
+					  color_fmt << 8) |
+					 RADEON_GMC_SRC_DATATYPE_COLOR |
+					 RADEON_ROP3_P |
+					 RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+				OUT_RING(dev_priv->front_pitch_offset);
+				OUT_RING(clear->clear_color);
+
+				OUT_RING((x << 16) | y);
+				OUT_RING((w << 16) | h);
+
+				ADVANCE_RING();
+			}
+
+			if (flags & RADEON_BACK) {
+				BEGIN_RING(6);
+
+				OUT_RING(CP_PACKET3
+					 (RADEON_CNTL_PAINT_MULTI, 4));
+				OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+					 RADEON_GMC_BRUSH_SOLID_COLOR |
+					 (dev_priv->
+					  color_fmt << 8) |
+					 RADEON_GMC_SRC_DATATYPE_COLOR |
+					 RADEON_ROP3_P |
+					 RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+				OUT_RING(dev_priv->back_pitch_offset);
+				OUT_RING(clear->clear_color);
+
+				OUT_RING((x << 16) | y);
+				OUT_RING((w << 16) | h);
+
+				ADVANCE_RING();
+			}
+		}
+	}
+
+	/* hyper z clear */
+	/* no docs available, based on reverse engeneering by Stephane Marchesin */
+	if ((flags & (RADEON_DEPTH | RADEON_STENCIL))
+	    && (flags & RADEON_CLEAR_FASTZ)) {
+
+		int i;
+		int depthpixperline =
+		    dev_priv->depth_fmt ==
+		    RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch /
+						       2) : (dev_priv->
+							     depth_pitch / 4);
+
+		u32 clearmask;
+
+		u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
+		    ((clear->depth_mask & 0xff) << 24);
+
+		/* Make sure we restore the 3D state next time.
+		 * we haven't touched any "normal" state - still need this?
+		 */
+		dev_priv->sarea_priv->ctx_owner = 0;
+
+		if ((dev_priv->flags & RADEON_HAS_HIERZ)
+		    && (flags & RADEON_USE_HIERZ)) {
+			/* FIXME : reverse engineer that for Rx00 cards */
+			/* FIXME : the mask supposedly contains low-res z values. So can't set
+			   just to the max (0xff? or actually 0x3fff?), need to take z clear
+			   value into account? */
+			/* pattern seems to work for r100, though get slight
+			   rendering errors with glxgears. If hierz is not enabled for r100,
+			   only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
+			   other ones are ignored, and the same clear mask can be used. That's
+			   very different behaviour than R200 which needs different clear mask
+			   and different number of tiles to clear if hierz is enabled or not !?!
+			 */
+			clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f;
+		} else {
+			/* clear mask : chooses the clearing pattern.
+			   rv250: could be used to clear only parts of macrotiles
+			   (but that would get really complicated...)?
+			   bit 0 and 1 (either or both of them ?!?!) are used to
+			   not clear tile (or maybe one of the bits indicates if the tile is
+			   compressed or not), bit 2 and 3 to not clear tile 1,...,.
+			   Pattern is as follows:
+			   | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
+			   bits -------------------------------------------------
+			   | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
+			   rv100: clearmask covers 2x8 4x1 tiles, but one clear still
+			   covers 256 pixels ?!?
+			 */
+			clearmask = 0x0;
+		}
+
+		BEGIN_RING(8);
+		RADEON_WAIT_UNTIL_2D_IDLE();
+		OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,
+			     tempRB3D_DEPTHCLEARVALUE);
+		/* what offset is this exactly ? */
+		OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);
+		/* need ctlstat, otherwise get some strange black flickering */
+		OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,
+			     RADEON_RB3D_ZC_FLUSH_ALL);
+		ADVANCE_RING();
+
+		for (i = 0; i < nbox; i++) {
+			int tileoffset, nrtilesx, nrtilesy, j;
+			/* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
+			if ((dev_priv->flags & RADEON_HAS_HIERZ)
+			    && !(dev_priv->microcode_version == UCODE_R200)) {
+				/* FIXME : figure this out for r200 (when hierz is enabled). Or
+				   maybe r200 actually doesn't need to put the low-res z value into
+				   the tile cache like r100, but just needs to clear the hi-level z-buffer?
+				   Works for R100, both with hierz and without.
+				   R100 seems to operate on 2x1 8x8 tiles, but...
+				   odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially
+				   problematic with resolutions which are not 64 pix aligned? */
+				tileoffset =
+				    ((pbox[i].y1 >> 3) * depthpixperline +
+				     pbox[i].x1) >> 6;
+				nrtilesx =
+				    ((pbox[i].x2 & ~63) -
+				     (pbox[i].x1 & ~63)) >> 4;
+				nrtilesy =
+				    (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
+				for (j = 0; j <= nrtilesy; j++) {
+					BEGIN_RING(4);
+					OUT_RING(CP_PACKET3
+						 (RADEON_3D_CLEAR_ZMASK, 2));
+					/* first tile */
+					OUT_RING(tileoffset * 8);
+					/* the number of tiles to clear */
+					OUT_RING(nrtilesx + 4);
+					/* clear mask : chooses the clearing pattern. */
+					OUT_RING(clearmask);
+					ADVANCE_RING();
+					tileoffset += depthpixperline >> 6;
+				}
+			} else if (dev_priv->microcode_version == UCODE_R200) {
+				/* works for rv250. */
+				/* find first macro tile (8x2 4x4 z-pixels on rv250) */
+				tileoffset =
+				    ((pbox[i].y1 >> 3) * depthpixperline +
+				     pbox[i].x1) >> 5;
+				nrtilesx =
+				    (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
+				nrtilesy =
+				    (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
+				for (j = 0; j <= nrtilesy; j++) {
+					BEGIN_RING(4);
+					OUT_RING(CP_PACKET3
+						 (RADEON_3D_CLEAR_ZMASK, 2));
+					/* first tile */
+					/* judging by the first tile offset needed, could possibly
+					   directly address/clear 4x4 tiles instead of 8x2 * 4x4
+					   macro tiles, though would still need clear mask for
+					   right/bottom if truely 4x4 granularity is desired ? */
+					OUT_RING(tileoffset * 16);
+					/* the number of tiles to clear */
+					OUT_RING(nrtilesx + 1);
+					/* clear mask : chooses the clearing pattern. */
+					OUT_RING(clearmask);
+					ADVANCE_RING();
+					tileoffset += depthpixperline >> 5;
+				}
+			} else {	/* rv 100 */
+				/* rv100 might not need 64 pix alignment, who knows */
+				/* offsets are, hmm, weird */
+				tileoffset =
+				    ((pbox[i].y1 >> 4) * depthpixperline +
+				     pbox[i].x1) >> 6;
+				nrtilesx =
+				    ((pbox[i].x2 & ~63) -
+				     (pbox[i].x1 & ~63)) >> 4;
+				nrtilesy =
+				    (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
+				for (j = 0; j <= nrtilesy; j++) {
+					BEGIN_RING(4);
+					OUT_RING(CP_PACKET3
+						 (RADEON_3D_CLEAR_ZMASK, 2));
+					OUT_RING(tileoffset * 128);
+					/* the number of tiles to clear */
+					OUT_RING(nrtilesx + 4);
+					/* clear mask : chooses the clearing pattern. */
+					OUT_RING(clearmask);
+					ADVANCE_RING();
+					tileoffset += depthpixperline >> 6;
+				}
+			}
+		}
+
+		/* TODO don't always clear all hi-level z tiles */
+		if ((dev_priv->flags & RADEON_HAS_HIERZ)
+		    && (dev_priv->microcode_version == UCODE_R200)
+		    && (flags & RADEON_USE_HIERZ))
+			/* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
+			/* FIXME : the mask supposedly contains low-res z values. So can't set
+			   just to the max (0xff? or actually 0x3fff?), need to take z clear
+			   value into account? */
+		{
+			BEGIN_RING(4);
+			OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));
+			OUT_RING(0x0);	/* First tile */
+			OUT_RING(0x3cc0);
+			OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);
+			ADVANCE_RING();
+		}
+	}
+
+	/* We have to clear the depth and/or stencil buffers by
+	 * rendering a quad into just those buffers.  Thus, we have to
+	 * make sure the 3D engine is configured correctly.
+	 */
+	else if ((dev_priv->microcode_version == UCODE_R200) &&
+		(flags & (RADEON_DEPTH | RADEON_STENCIL))) {
+
+		int tempPP_CNTL;
+		int tempRE_CNTL;
+		int tempRB3D_CNTL;
+		int tempRB3D_ZSTENCILCNTL;
+		int tempRB3D_STENCILREFMASK;
+		int tempRB3D_PLANEMASK;
+		int tempSE_CNTL;
+		int tempSE_VTE_CNTL;
+		int tempSE_VTX_FMT_0;
+		int tempSE_VTX_FMT_1;
+		int tempSE_VAP_CNTL;
+		int tempRE_AUX_SCISSOR_CNTL;
+
+		tempPP_CNTL = 0;
+		tempRE_CNTL = 0;
+
+		tempRB3D_CNTL = depth_clear->rb3d_cntl;
+
+		tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
+		tempRB3D_STENCILREFMASK = 0x0;
+
+		tempSE_CNTL = depth_clear->se_cntl;
+
+		/* Disable TCL */
+
+		tempSE_VAP_CNTL = (	/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK |  */
+					  (0x9 <<
+					   SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
+
+		tempRB3D_PLANEMASK = 0x0;
+
+		tempRE_AUX_SCISSOR_CNTL = 0x0;
+
+		tempSE_VTE_CNTL =
+		    SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;
+
+		/* Vertex format (X, Y, Z, W) */
+		tempSE_VTX_FMT_0 =
+		    SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
+		    SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
+		tempSE_VTX_FMT_1 = 0x0;
+
+		/*
+		 * Depth buffer specific enables
+		 */
+		if (flags & RADEON_DEPTH) {
+			/* Enable depth buffer */
+			tempRB3D_CNTL |= RADEON_Z_ENABLE;
+		} else {
+			/* Disable depth buffer */
+			tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
+		}
+
+		/*
+		 * Stencil buffer specific enables
+		 */
+		if (flags & RADEON_STENCIL) {
+			tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
+			tempRB3D_STENCILREFMASK = clear->depth_mask;
+		} else {
+			tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
+			tempRB3D_STENCILREFMASK = 0x00000000;
+		}
+
+		if (flags & RADEON_USE_COMP_ZBUF) {
+			tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
+			    RADEON_Z_DECOMPRESSION_ENABLE;
+		}
+		if (flags & RADEON_USE_HIERZ) {
+			tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
+		}
+
+		BEGIN_RING(26);
+		RADEON_WAIT_UNTIL_2D_IDLE();
+
+		OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);
+		OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);
+		OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);
+		OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
+		OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,
+			     tempRB3D_STENCILREFMASK);
+		OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);
+		OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);
+		OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);
+		OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);
+		OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);
+		OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);
+		OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);
+		ADVANCE_RING();
+
+		/* Make sure we restore the 3D state next time.
+		 */
+		dev_priv->sarea_priv->ctx_owner = 0;
+
+		for (i = 0; i < nbox; i++) {
+
+			/* Funny that this should be required --
+			 *  sets top-left?
+			 */
+			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+			BEGIN_RING(14);
+			OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));
+			OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
+				  RADEON_PRIM_WALK_RING |
+				  (3 << RADEON_NUM_VERTICES_SHIFT)));
+			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+			OUT_RING(0x3f800000);
+			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+			OUT_RING(0x3f800000);
+			OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+			OUT_RING(0x3f800000);
+			ADVANCE_RING();
+		}
+	} else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {
+
+		int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
+
+		rb3d_cntl = depth_clear->rb3d_cntl;
+
+		if (flags & RADEON_DEPTH) {
+			rb3d_cntl |= RADEON_Z_ENABLE;
+		} else {
+			rb3d_cntl &= ~RADEON_Z_ENABLE;
+		}
+
+		if (flags & RADEON_STENCIL) {
+			rb3d_cntl |= RADEON_STENCIL_ENABLE;
+			rb3d_stencilrefmask = clear->depth_mask;	/* misnamed field */
+		} else {
+			rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
+			rb3d_stencilrefmask = 0x00000000;
+		}
+
+		if (flags & RADEON_USE_COMP_ZBUF) {
+			tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
+			    RADEON_Z_DECOMPRESSION_ENABLE;
+		}
+		if (flags & RADEON_USE_HIERZ) {
+			tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
+		}
+
+		BEGIN_RING(13);
+		RADEON_WAIT_UNTIL_2D_IDLE();
+
+		OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));
+		OUT_RING(0x00000000);
+		OUT_RING(rb3d_cntl);
+
+		OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
+		OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);
+		OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);
+		OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);
+		ADVANCE_RING();
+
+		/* Make sure we restore the 3D state next time.
+		 */
+		dev_priv->sarea_priv->ctx_owner = 0;
+
+		for (i = 0; i < nbox; i++) {
+
+			/* Funny that this should be required --
+			 *  sets top-left?
+			 */
+			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+			BEGIN_RING(15);
+
+			OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));
+			OUT_RING(RADEON_VTX_Z_PRESENT |
+				 RADEON_VTX_PKCOLOR_PRESENT);
+			OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
+				  RADEON_PRIM_WALK_RING |
+				  RADEON_MAOS_ENABLE |
+				  RADEON_VTX_FMT_RADEON_MODE |
+				  (3 << RADEON_NUM_VERTICES_SHIFT)));
+
+			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+			OUT_RING(0x0);
+
+			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+			OUT_RING(0x0);
+
+			OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+			OUT_RING(0x0);
+
+			ADVANCE_RING();
+		}
+	}
+
+	/* Increment the clear counter.  The client-side 3D driver must
+	 * wait on this value before performing the clear ioctl.  We
+	 * need this because the card's so damned fast...
+	 */
+	dev_priv->sarea_priv->last_clear++;
+
+	BEGIN_RING(4);
+
+	RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
+	RADEON_WAIT_UNTIL_IDLE();
+
+	ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_swap(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int nbox = sarea_priv->nbox;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG("\n");
+
+	/* Do some trivial performance monitoring...
+	 */
+	if (dev_priv->do_boxes)
+		radeon_cp_performance_boxes(dev_priv);
+
+	/* Wait for the 3D stream to idle before dispatching the bitblt.
+	 * This will prevent data corruption between the two streams.
+	 */
+	BEGIN_RING(2);
+
+	RADEON_WAIT_UNTIL_3D_IDLE();
+
+	ADVANCE_RING();
+
+	for (i = 0; i < nbox; i++) {
+		int x = pbox[i].x1;
+		int y = pbox[i].y1;
+		int w = pbox[i].x2 - x;
+		int h = pbox[i].y2 - y;
+
+		DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);
+
+		BEGIN_RING(9);
+
+		OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));
+		OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+			 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+			 RADEON_GMC_BRUSH_NONE |
+			 (dev_priv->color_fmt << 8) |
+			 RADEON_GMC_SRC_DATATYPE_COLOR |
+			 RADEON_ROP3_S |
+			 RADEON_DP_SRC_SOURCE_MEMORY |
+			 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
+
+		/* Make this work even if front & back are flipped:
+		 */
+		OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
+		if (dev_priv->current_page == 0) {
+			OUT_RING(dev_priv->back_pitch_offset);
+			OUT_RING(dev_priv->front_pitch_offset);
+		} else {
+			OUT_RING(dev_priv->front_pitch_offset);
+			OUT_RING(dev_priv->back_pitch_offset);
+		}
+
+		OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2));
+		OUT_RING((x << 16) | y);
+		OUT_RING((x << 16) | y);
+		OUT_RING((w << 16) | h);
+
+		ADVANCE_RING();
+	}
+
+	/* Increment the frame counter.  The client-side 3D driver must
+	 * throttle the framerate by waiting for this value before
+	 * performing the swapbuffer ioctl.
+	 */
+	dev_priv->sarea_priv->last_frame++;
+
+	BEGIN_RING(4);
+
+	RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
+	RADEON_WAIT_UNTIL_2D_IDLE();
+
+	ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_flip(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;
+	int offset = (dev_priv->current_page == 1)
+	    ? dev_priv->front_offset : dev_priv->back_offset;
+	RING_LOCALS;
+	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+		  __FUNCTION__,
+		  dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
+
+	/* Do some trivial performance monitoring...
+	 */
+	if (dev_priv->do_boxes) {
+		dev_priv->stats.boxes |= RADEON_BOX_FLIP;
+		radeon_cp_performance_boxes(dev_priv);
+	}
+
+	/* Update the frame offsets for both CRTCs
+	 */
+	BEGIN_RING(6);
+
+	RADEON_WAIT_UNTIL_3D_IDLE();
+	OUT_RING_REG(RADEON_CRTC_OFFSET,
+		     ((sarea->frame.y * dev_priv->front_pitch +
+		       sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
+		     + offset);
+	OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
+		     + offset);
+
+	ADVANCE_RING();
+
+	/* Increment the frame counter.  The client-side 3D driver must
+	 * throttle the framerate by waiting for this value before
+	 * performing the swapbuffer ioctl.
+	 */
+	dev_priv->sarea_priv->last_frame++;
+	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
+	    1 - dev_priv->current_page;
+
+	BEGIN_RING(2);
+
+	RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
+
+	ADVANCE_RING();
+}
+
+static int bad_prim_vertex_nr(int primitive, int nr)
+{
+	switch (primitive & RADEON_PRIM_TYPE_MASK) {
+	case RADEON_PRIM_TYPE_NONE:
+	case RADEON_PRIM_TYPE_POINT:
+		return nr < 1;
+	case RADEON_PRIM_TYPE_LINE:
+		return (nr & 1) || nr == 0;
+	case RADEON_PRIM_TYPE_LINE_STRIP:
+		return nr < 2;
+	case RADEON_PRIM_TYPE_TRI_LIST:
+	case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
+	case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
+	case RADEON_PRIM_TYPE_RECT_LIST:
+		return nr % 3 || nr == 0;
+	case RADEON_PRIM_TYPE_TRI_FAN:
+	case RADEON_PRIM_TYPE_TRI_STRIP:
+		return nr < 3;
+	default:
+		return 1;
+	}
+}
+
+typedef struct {
+	unsigned int start;
+	unsigned int finish;
+	unsigned int prim;
+	unsigned int numverts;
+	unsigned int offset;
+	unsigned int vc_format;
+} drm_radeon_tcl_prim_t;
+
+static void radeon_cp_dispatch_vertex(drm_device_t * dev,
+				      drm_buf_t * buf,
+				      drm_radeon_tcl_prim_t * prim)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
+	int numverts = (int)prim->numverts;
+	int nbox = sarea_priv->nbox;
+	int i = 0;
+	RING_LOCALS;
+
+	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
+		  prim->prim,
+		  prim->vc_format, prim->start, prim->finish, prim->numverts);
+
+	if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {
+		DRM_ERROR("bad prim %x numverts %d\n",
+			  prim->prim, prim->numverts);
+		return;
+	}
+
+	do {
+		/* Emit the next cliprect */
+		if (i < nbox) {
+			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+		}
+
+		/* Emit the vertex buffer rendering commands */
+		BEGIN_RING(5);
+
+		OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));
+		OUT_RING(offset);
+		OUT_RING(numverts);
+		OUT_RING(prim->vc_format);
+		OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |
+			 RADEON_COLOR_ORDER_RGBA |
+			 RADEON_VTX_FMT_RADEON_MODE |
+			 (numverts << RADEON_NUM_VERTICES_SHIFT));
+
+		ADVANCE_RING();
+
+		i++;
+	} while (i < nbox);
+}
+
+static void radeon_cp_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+	RING_LOCALS;
+
+	buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
+
+	/* Emit the vertex buffer age */
+	BEGIN_RING(2);
+	RADEON_DISPATCH_AGE(buf_priv->age);
+	ADVANCE_RING();
+
+	buf->pending = 1;
+	buf->used = 0;
+}
+
+static void radeon_cp_dispatch_indirect(drm_device_t * dev,
+					drm_buf_t * buf, int start, int end)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+	DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
+
+	if (start != end) {
+		int offset = (dev_priv->gart_buffers_offset
+			      + buf->offset + start);
+		int dwords = (end - start + 3) / sizeof(u32);
+
+		/* Indirect buffer data must be an even number of
+		 * dwords, so if we've been given an odd number we must
+		 * pad the data with a Type-2 CP packet.
+		 */
+		if (dwords & 1) {
+			u32 *data = (u32 *)
+			    ((char *)dev->agp_buffer_map->handle
+			     + buf->offset + start);
+			data[dwords++] = RADEON_CP_PACKET2;
+		}
+
+		/* Fire off the indirect buffer */
+		BEGIN_RING(3);
+
+		OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
+		OUT_RING(offset);
+		OUT_RING(dwords);
+
+		ADVANCE_RING();
+	}
+}
+
+static void radeon_cp_dispatch_indices(drm_device_t * dev,
+				       drm_buf_t * elt_buf,
+				       drm_radeon_tcl_prim_t * prim)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int offset = dev_priv->gart_buffers_offset + prim->offset;
+	u32 *data;
+	int dwords;
+	int i = 0;
+	int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
+	int count = (prim->finish - start) / sizeof(u16);
+	int nbox = sarea_priv->nbox;
+
+	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
+		  prim->prim,
+		  prim->vc_format,
+		  prim->start, prim->finish, prim->offset, prim->numverts);
+
+	if (bad_prim_vertex_nr(prim->prim, count)) {
+		DRM_ERROR("bad prim %x count %d\n", prim->prim, count);
+		return;
+	}
+
+	if (start >= prim->finish || (prim->start & 0x7)) {
+		DRM_ERROR("buffer prim %d\n", prim->prim);
+		return;
+	}
+
+	dwords = (prim->finish - prim->start + 3) / sizeof(u32);
+
+	data = (u32 *) ((char *)dev->agp_buffer_map->handle +
+			elt_buf->offset + prim->start);
+
+	data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
+	data[1] = offset;
+	data[2] = prim->numverts;
+	data[3] = prim->vc_format;
+	data[4] = (prim->prim |
+		   RADEON_PRIM_WALK_IND |
+		   RADEON_COLOR_ORDER_RGBA |
+		   RADEON_VTX_FMT_RADEON_MODE |
+		   (count << RADEON_NUM_VERTICES_SHIFT));
+
+	do {
+		if (i < nbox)
+			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+		radeon_cp_dispatch_indirect(dev, elt_buf,
+					    prim->start, prim->finish);
+
+		i++;
+	} while (i < nbox);
+
+}
+
+#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
+
+static int radeon_cp_dispatch_texture(DRMFILE filp,
+				      drm_device_t * dev,
+				      drm_radeon_texture_t * tex,
+				      drm_radeon_tex_image_t * image)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
+	drm_buf_t *buf;
+	u32 format;
+	u32 *buffer;
+	const u8 __user *data;
+	int size, dwords, tex_width, blit_width, spitch;
+	u32 height;
+	int i;
+	u32 texpitch, microtile;
+	u32 offset;
+	RING_LOCALS;
+
+	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+	if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex->offset)) {
+		DRM_ERROR("Invalid destination offset\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
+
+	/* Flush the pixel cache.  This ensures no pixel data gets mixed
+	 * up with the texture data from the host data blit, otherwise
+	 * part of the texture image may be corrupted.
+	 */
+	BEGIN_RING(4);
+	RADEON_FLUSH_CACHE();
+	RADEON_WAIT_UNTIL_IDLE();
+	ADVANCE_RING();
+
+	/* The compiler won't optimize away a division by a variable,
+	 * even if the only legal values are powers of two.  Thus, we'll
+	 * use a shift instead.
+	 */
+	switch (tex->format) {
+	case RADEON_TXFORMAT_ARGB8888:
+	case RADEON_TXFORMAT_RGBA8888:
+		format = RADEON_COLOR_FORMAT_ARGB8888;
+		tex_width = tex->width * 4;
+		blit_width = image->width * 4;
+		break;
+	case RADEON_TXFORMAT_AI88:
+	case RADEON_TXFORMAT_ARGB1555:
+	case RADEON_TXFORMAT_RGB565:
+	case RADEON_TXFORMAT_ARGB4444:
+	case RADEON_TXFORMAT_VYUY422:
+	case RADEON_TXFORMAT_YVYU422:
+		format = RADEON_COLOR_FORMAT_RGB565;
+		tex_width = tex->width * 2;
+		blit_width = image->width * 2;
+		break;
+	case RADEON_TXFORMAT_I8:
+	case RADEON_TXFORMAT_RGB332:
+		format = RADEON_COLOR_FORMAT_CI8;
+		tex_width = tex->width * 1;
+		blit_width = image->width * 1;
+		break;
+	default:
+		DRM_ERROR("invalid texture format %d\n", tex->format);
+		return DRM_ERR(EINVAL);
+	}
+	spitch = blit_width >> 6;
+	if (spitch == 0 && image->height > 1)
+		return DRM_ERR(EINVAL);
+
+	texpitch = tex->pitch;
+	if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
+		microtile = 1;
+		if (tex_width < 64) {
+			texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
+			/* we got tiled coordinates, untile them */
+			image->x *= 2;
+		}
+	} else
+		microtile = 0;
+
+	DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
+
+	do {
+		DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
+			  tex->offset >> 10, tex->pitch, tex->format,
+			  image->x, image->y, image->width, image->height);
+
+		/* Make a copy of some parameters in case we have to
+		 * update them for a multi-pass texture blit.
+		 */
+		height = image->height;
+		data = (const u8 __user *)image->data;
+
+		size = height * blit_width;
+
+		if (size > RADEON_MAX_TEXTURE_SIZE) {
+			height = RADEON_MAX_TEXTURE_SIZE / blit_width;
+			size = height * blit_width;
+		} else if (size < 4 && size > 0) {
+			size = 4;
+		} else if (size == 0) {
+			return 0;
+		}
+
+		buf = radeon_freelist_get(dev);
+		if (0 && !buf) {
+			radeon_do_cp_idle(dev_priv);
+			buf = radeon_freelist_get(dev);
+		}
+		if (!buf) {
+			DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
+			if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
+				return DRM_ERR(EFAULT);
+			return DRM_ERR(EAGAIN);
+		}
+
+		/* Dispatch the indirect buffer.
+		 */
+		buffer =
+		    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+		dwords = size / 4;
+
+#define RADEON_COPY_MT(_buf, _data, _width) \
+	do { \
+		if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
+			DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
+			return DRM_ERR(EFAULT); \
+		} \
+	} while(0)
+
+		if (microtile) {
+			/* texture micro tiling in use, minimum texture width is thus 16 bytes.
+			   however, we cannot use blitter directly for texture width < 64 bytes,
+			   since minimum tex pitch is 64 bytes and we need this to match
+			   the texture width, otherwise the blitter will tile it wrong.
+			   Thus, tiling manually in this case. Additionally, need to special
+			   case tex height = 1, since our actual image will have height 2
+			   and we need to ensure we don't read beyond the texture size
+			   from user space. */
+			if (tex->height == 1) {
+				if (tex_width >= 64 || tex_width <= 16) {
+					RADEON_COPY_MT(buffer, data,
+						(int)(tex_width * sizeof(u32)));
+				} else if (tex_width == 32) {
+					RADEON_COPY_MT(buffer, data, 16);
+					RADEON_COPY_MT(buffer + 8,
+						       data + 16, 16);
+				}
+			} else if (tex_width >= 64 || tex_width == 16) {
+				RADEON_COPY_MT(buffer, data,
+					       (int)(dwords * sizeof(u32)));
+			} else if (tex_width < 16) {
+				for (i = 0; i < tex->height; i++) {
+					RADEON_COPY_MT(buffer, data, tex_width);
+					buffer += 4;
+					data += tex_width;
+				}
+			} else if (tex_width == 32) {
+				/* TODO: make sure this works when not fitting in one buffer
+				   (i.e. 32bytes x 2048...) */
+				for (i = 0; i < tex->height; i += 2) {
+					RADEON_COPY_MT(buffer, data, 16);
+					data += 16;
+					RADEON_COPY_MT(buffer + 8, data, 16);
+					data += 16;
+					RADEON_COPY_MT(buffer + 4, data, 16);
+					data += 16;
+					RADEON_COPY_MT(buffer + 12, data, 16);
+					data += 16;
+					buffer += 16;
+				}
+			}
+		} else {
+			if (tex_width >= 32) {
+				/* Texture image width is larger than the minimum, so we
+				 * can upload it directly.
+				 */
+				RADEON_COPY_MT(buffer, data,
+					       (int)(dwords * sizeof(u32)));
+			} else {
+				/* Texture image width is less than the minimum, so we
+				 * need to pad out each image scanline to the minimum
+				 * width.
+				 */
+				for (i = 0; i < tex->height; i++) {
+					RADEON_COPY_MT(buffer, data, tex_width);
+					buffer += 8;
+					data += tex_width;
+				}
+			}
+		}
+
+#undef RADEON_COPY_MT
+		buf->filp = filp;
+		buf->used = size;
+		offset = dev_priv->gart_buffers_offset + buf->offset;
+		BEGIN_RING(9);
+		OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
+		OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+			 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+			 RADEON_GMC_BRUSH_NONE |
+			 (format << 8) |
+			 RADEON_GMC_SRC_DATATYPE_COLOR |
+			 RADEON_ROP3_S |
+			 RADEON_DP_SRC_SOURCE_MEMORY |
+			 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
+		OUT_RING((spitch << 22) | (offset >> 10));
+		OUT_RING((texpitch << 22) | (tex->offset >> 10));
+		OUT_RING(0);
+		OUT_RING((image->x << 16) | image->y);
+		OUT_RING((image->width << 16) | height);
+		RADEON_WAIT_UNTIL_2D_IDLE();
+		ADVANCE_RING();
+
+		radeon_cp_discard_buffer(dev, buf);
+
+		/* Update the input parameters for next time */
+		image->y += height;
+		image->height -= height;
+		image->data = (const u8 __user *)image->data + size;
+	} while (image->height > 0);
+
+	/* Flush the pixel cache after the blit completes.  This ensures
+	 * the texture data is written out to memory before rendering
+	 * continues.
+	 */
+	BEGIN_RING(4);
+	RADEON_FLUSH_CACHE();
+	RADEON_WAIT_UNTIL_2D_IDLE();
+	ADVANCE_RING();
+	return 0;
+}
+
+static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG("\n");
+
+	BEGIN_RING(35);
+
+	OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0));
+	OUT_RING(0x00000000);
+
+	OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31));
+	for (i = 0; i < 32; i++) {
+		OUT_RING(stipple[i]);
+	}
+
+	ADVANCE_RING();
+}
+
+static void radeon_apply_surface_regs(int surf_index,
+				      drm_radeon_private_t *dev_priv)
+{
+	if (!dev_priv->mmio)
+		return;
+
+	radeon_do_cp_idle(dev_priv);
+
+	RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index,
+		     dev_priv->surfaces[surf_index].flags);
+	RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index,
+		     dev_priv->surfaces[surf_index].lower);
+	RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index,
+		     dev_priv->surfaces[surf_index].upper);
+}
+
+/* Allocates a virtual surface
+ * doesn't always allocate a real surface, will stretch an existing
+ * surface when possible.
+ *
+ * Note that refcount can be at most 2, since during a free refcount=3
+ * might mean we have to allocate a new surface which might not always
+ * be available.
+ * For example : we allocate three contigous surfaces ABC. If B is
+ * freed, we suddenly need two surfaces to store A and C, which might
+ * not always be available.
+ */
+static int alloc_surface(drm_radeon_surface_alloc_t *new,
+			 drm_radeon_private_t *dev_priv, DRMFILE filp)
+{
+	struct radeon_virt_surface *s;
+	int i;
+	int virt_surface_index;
+	uint32_t new_upper, new_lower;
+
+	new_lower = new->address;
+	new_upper = new_lower + new->size - 1;
+
+	/* sanity check */
+	if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
+	    ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) !=
+	     RADEON_SURF_ADDRESS_FIXED_MASK)
+	    || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
+		return -1;
+
+	/* make sure there is no overlap with existing surfaces */
+	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+		if ((dev_priv->surfaces[i].refcount != 0) &&
+		    (((new_lower >= dev_priv->surfaces[i].lower) &&
+		      (new_lower < dev_priv->surfaces[i].upper)) ||
+		     ((new_lower < dev_priv->surfaces[i].lower) &&
+		      (new_upper > dev_priv->surfaces[i].lower)))) {
+			return -1;
+		}
+	}
+
+	/* find a virtual surface */
+	for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
+		if (dev_priv->virt_surfaces[i].filp == 0)
+			break;
+	if (i == 2 * RADEON_MAX_SURFACES) {
+		return -1;
+	}
+	virt_surface_index = i;
+
+	/* try to reuse an existing surface */
+	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+		/* extend before */
+		if ((dev_priv->surfaces[i].refcount == 1) &&
+		    (new->flags == dev_priv->surfaces[i].flags) &&
+		    (new_upper + 1 == dev_priv->surfaces[i].lower)) {
+			s = &(dev_priv->virt_surfaces[virt_surface_index]);
+			s->surface_index = i;
+			s->lower = new_lower;
+			s->upper = new_upper;
+			s->flags = new->flags;
+			s->filp = filp;
+			dev_priv->surfaces[i].refcount++;
+			dev_priv->surfaces[i].lower = s->lower;
+			radeon_apply_surface_regs(s->surface_index, dev_priv);
+			return virt_surface_index;
+		}
+
+		/* extend after */
+		if ((dev_priv->surfaces[i].refcount == 1) &&
+		    (new->flags == dev_priv->surfaces[i].flags) &&
+		    (new_lower == dev_priv->surfaces[i].upper + 1)) {
+			s = &(dev_priv->virt_surfaces[virt_surface_index]);
+			s->surface_index = i;
+			s->lower = new_lower;
+			s->upper = new_upper;
+			s->flags = new->flags;
+			s->filp = filp;
+			dev_priv->surfaces[i].refcount++;
+			dev_priv->surfaces[i].upper = s->upper;
+			radeon_apply_surface_regs(s->surface_index, dev_priv);
+			return virt_surface_index;
+		}
+	}
+
+	/* okay, we need a new one */
+	for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+		if (dev_priv->surfaces[i].refcount == 0) {
+			s = &(dev_priv->virt_surfaces[virt_surface_index]);
+			s->surface_index = i;
+			s->lower = new_lower;
+			s->upper = new_upper;
+			s->flags = new->flags;
+			s->filp = filp;
+			dev_priv->surfaces[i].refcount = 1;
+			dev_priv->surfaces[i].lower = s->lower;
+			dev_priv->surfaces[i].upper = s->upper;
+			dev_priv->surfaces[i].flags = s->flags;
+			radeon_apply_surface_regs(s->surface_index, dev_priv);
+			return virt_surface_index;
+		}
+	}
+
+	/* we didn't find anything */
+	return -1;
+}
+
+static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv,
+			int lower)
+{
+	struct radeon_virt_surface *s;
+	int i;
+	/* find the virtual surface */
+	for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
+		s = &(dev_priv->virt_surfaces[i]);
+		if (s->filp) {
+			if ((lower == s->lower) && (filp == s->filp)) {
+				if (dev_priv->surfaces[s->surface_index].
+				    lower == s->lower)
+					dev_priv->surfaces[s->surface_index].
+					    lower = s->upper;
+
+				if (dev_priv->surfaces[s->surface_index].
+				    upper == s->upper)
+					dev_priv->surfaces[s->surface_index].
+					    upper = s->lower;
+
+				dev_priv->surfaces[s->surface_index].refcount--;
+				if (dev_priv->surfaces[s->surface_index].
+				    refcount == 0)
+					dev_priv->surfaces[s->surface_index].
+					    flags = 0;
+				s->filp = NULL;
+				radeon_apply_surface_regs(s->surface_index,
+							  dev_priv);
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
+
+static void radeon_surfaces_release(DRMFILE filp,
+				    drm_radeon_private_t * dev_priv)
+{
+	int i;
+	for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
+		if (dev_priv->virt_surfaces[i].filp == filp)
+			free_surface(filp, dev_priv,
+				     dev_priv->virt_surfaces[i].lower);
+	}
+}
+
+/* ================================================================
+ * IOCTL functions
+ */
+static int radeon_surface_alloc(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_surface_alloc_t alloc;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(alloc,
+				 (drm_radeon_surface_alloc_t __user *) data,
+				 sizeof(alloc));
+
+	if (alloc_surface(&alloc, dev_priv, filp) == -1)
+		return DRM_ERR(EINVAL);
+	else
+		return 0;
+}
+
+static int radeon_surface_free(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_surface_free_t memfree;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data,
+				 sizeof(memfree));
+
+	if (free_surface(filp, dev_priv, memfree.address))
+		return DRM_ERR(EINVAL);
+	else
+		return 0;
+}
+
+static int radeon_cp_clear(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_clear_t clear;
+	drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(clear, (drm_radeon_clear_t __user *) data,
+				 sizeof(clear));
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+	if (DRM_COPY_FROM_USER(&depth_boxes, clear.depth_boxes,
+			       sarea_priv->nbox * sizeof(depth_boxes[0])))
+		return DRM_ERR(EFAULT);
+
+	radeon_cp_dispatch_clear(dev, &clear, depth_boxes);
+
+	COMMIT_RING();
+	return 0;
+}
+
+/* Not sure why this isn't set all the time:
+ */
+static int radeon_do_init_pageflip(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	DRM_DEBUG("\n");
+
+	BEGIN_RING(6);
+	RADEON_WAIT_UNTIL_3D_IDLE();
+	OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0));
+	OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) |
+		 RADEON_CRTC_OFFSET_FLIP_CNTL);
+	OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0));
+	OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) |
+		 RADEON_CRTC_OFFSET_FLIP_CNTL);
+	ADVANCE_RING();
+
+	dev_priv->page_flipping = 1;
+	dev_priv->current_page = 0;
+	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
+
+	return 0;
+}
+
+/* Called whenever a client dies, from drm_release.
+ * NOTE:  Lock isn't necessarily held when this is called!
+ */
+static int radeon_do_cleanup_pageflip(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	if (dev_priv->current_page != 0)
+		radeon_cp_dispatch_flip(dev);
+
+	dev_priv->page_flipping = 0;
+	return 0;
+}
+
+/* Swapping and flipping are different operations, need different ioctls.
+ * They can & should be intermixed to support multiple 3d windows.
+ */
+static int radeon_cp_flip(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+	if (!dev_priv->page_flipping)
+		radeon_do_init_pageflip(dev);
+
+	radeon_cp_dispatch_flip(dev);
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int radeon_cp_swap(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+	radeon_cp_dispatch_swap(dev);
+	dev_priv->sarea_priv->ctx_owner = 0;
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int radeon_cp_vertex(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
+	drm_radeon_sarea_t *sarea_priv;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_radeon_vertex_t vertex;
+	drm_radeon_tcl_prim_t prim;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	sarea_priv = dev_priv->sarea_priv;
+
+	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
+				 sizeof(vertex));
+
+	DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
+		  DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
+
+	if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
+		DRM_ERROR("buffer index %d (of %d max)\n",
+			  vertex.idx, dma->buf_count - 1);
+		return DRM_ERR(EINVAL);
+	}
+	if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
+		DRM_ERROR("buffer prim %d\n", vertex.prim);
+		return DRM_ERR(EINVAL);
+	}
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	buf = dma->buflist[vertex.idx];
+
+	if (buf->filp != filp) {
+		DRM_ERROR("process %d using buffer owned by %p\n",
+			  DRM_CURRENTPID, buf->filp);
+		return DRM_ERR(EINVAL);
+	}
+	if (buf->pending) {
+		DRM_ERROR("sending pending buffer %d\n", vertex.idx);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* Build up a prim_t record:
+	 */
+	if (vertex.count) {
+		buf->used = vertex.count;	/* not used? */
+
+		if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
+			if (radeon_emit_state(dev_priv, filp_priv,
+					      &sarea_priv->context_state,
+					      sarea_priv->tex_state,
+					      sarea_priv->dirty)) {
+				DRM_ERROR("radeon_emit_state failed\n");
+				return DRM_ERR(EINVAL);
+			}
+
+			sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+					       RADEON_UPLOAD_TEX1IMAGES |
+					       RADEON_UPLOAD_TEX2IMAGES |
+					       RADEON_REQUIRE_QUIESCENCE);
+		}
+
+		prim.start = 0;
+		prim.finish = vertex.count;	/* unused */
+		prim.prim = vertex.prim;
+		prim.numverts = vertex.count;
+		prim.vc_format = dev_priv->sarea_priv->vc_format;
+
+		radeon_cp_dispatch_vertex(dev, buf, &prim);
+	}
+
+	if (vertex.discard) {
+		radeon_cp_discard_buffer(dev, buf);
+	}
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int radeon_cp_indices(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
+	drm_radeon_sarea_t *sarea_priv;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_radeon_indices_t elts;
+	drm_radeon_tcl_prim_t prim;
+	int count;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+	sarea_priv = dev_priv->sarea_priv;
+
+	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data,
+				 sizeof(elts));
+
+	DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
+		  DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard);
+
+	if (elts.idx < 0 || elts.idx >= dma->buf_count) {
+		DRM_ERROR("buffer index %d (of %d max)\n",
+			  elts.idx, dma->buf_count - 1);
+		return DRM_ERR(EINVAL);
+	}
+	if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
+		DRM_ERROR("buffer prim %d\n", elts.prim);
+		return DRM_ERR(EINVAL);
+	}
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	buf = dma->buflist[elts.idx];
+
+	if (buf->filp != filp) {
+		DRM_ERROR("process %d using buffer owned by %p\n",
+			  DRM_CURRENTPID, buf->filp);
+		return DRM_ERR(EINVAL);
+	}
+	if (buf->pending) {
+		DRM_ERROR("sending pending buffer %d\n", elts.idx);
+		return DRM_ERR(EINVAL);
+	}
+
+	count = (elts.end - elts.start) / sizeof(u16);
+	elts.start -= RADEON_INDEX_PRIM_OFFSET;
+
+	if (elts.start & 0x7) {
+		DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
+		return DRM_ERR(EINVAL);
+	}
+	if (elts.start < buf->used) {
+		DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
+		return DRM_ERR(EINVAL);
+	}
+
+	buf->used = elts.end;
+
+	if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
+		if (radeon_emit_state(dev_priv, filp_priv,
+				      &sarea_priv->context_state,
+				      sarea_priv->tex_state,
+				      sarea_priv->dirty)) {
+			DRM_ERROR("radeon_emit_state failed\n");
+			return DRM_ERR(EINVAL);
+		}
+
+		sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+				       RADEON_UPLOAD_TEX1IMAGES |
+				       RADEON_UPLOAD_TEX2IMAGES |
+				       RADEON_REQUIRE_QUIESCENCE);
+	}
+
+	/* Build up a prim_t record:
+	 */
+	prim.start = elts.start;
+	prim.finish = elts.end;
+	prim.prim = elts.prim;
+	prim.offset = 0;	/* offset from start of dma buffers */
+	prim.numverts = RADEON_MAX_VB_VERTS;	/* duh */
+	prim.vc_format = dev_priv->sarea_priv->vc_format;
+
+	radeon_cp_dispatch_indices(dev, buf, &prim);
+	if (elts.discard) {
+		radeon_cp_discard_buffer(dev, buf);
+	}
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int radeon_cp_texture(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_texture_t tex;
+	drm_radeon_tex_image_t image;
+	int ret;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(tex, (drm_radeon_texture_t __user *) data,
+				 sizeof(tex));
+
+	if (tex.image == NULL) {
+		DRM_ERROR("null texture image!\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (DRM_COPY_FROM_USER(&image,
+			       (drm_radeon_tex_image_t __user *) tex.image,
+			       sizeof(image)))
+		return DRM_ERR(EFAULT);
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	ret = radeon_cp_dispatch_texture(filp, dev, &tex, &image);
+
+	COMMIT_RING();
+	return ret;
+}
+
+static int radeon_cp_stipple(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_stipple_t stipple;
+	u32 mask[32];
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(stipple, (drm_radeon_stipple_t __user *) data,
+				 sizeof(stipple));
+
+	if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
+		return DRM_ERR(EFAULT);
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+	radeon_cp_dispatch_stipple(dev, mask);
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int radeon_cp_indirect(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_radeon_indirect_t indirect;
+	RING_LOCALS;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(indirect,
+				 (drm_radeon_indirect_t __user *) data,
+				 sizeof(indirect));
+
+	DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
+		  indirect.idx, indirect.start, indirect.end, indirect.discard);
+
+	if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
+		DRM_ERROR("buffer index %d (of %d max)\n",
+			  indirect.idx, dma->buf_count - 1);
+		return DRM_ERR(EINVAL);
+	}
+
+	buf = dma->buflist[indirect.idx];
+
+	if (buf->filp != filp) {
+		DRM_ERROR("process %d using buffer owned by %p\n",
+			  DRM_CURRENTPID, buf->filp);
+		return DRM_ERR(EINVAL);
+	}
+	if (buf->pending) {
+		DRM_ERROR("sending pending buffer %d\n", indirect.idx);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (indirect.start < buf->used) {
+		DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
+			  indirect.start, buf->used);
+		return DRM_ERR(EINVAL);
+	}
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	buf->used = indirect.end;
+
+	/* Wait for the 3D stream to idle before the indirect buffer
+	 * containing 2D acceleration commands is processed.
+	 */
+	BEGIN_RING(2);
+
+	RADEON_WAIT_UNTIL_3D_IDLE();
+
+	ADVANCE_RING();
+
+	/* Dispatch the indirect buffer full of commands from the
+	 * X server.  This is insecure and is thus only available to
+	 * privileged clients.
+	 */
+	radeon_cp_dispatch_indirect(dev, buf, indirect.start, indirect.end);
+	if (indirect.discard) {
+		radeon_cp_discard_buffer(dev, buf);
+	}
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int radeon_cp_vertex2(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
+	drm_radeon_sarea_t *sarea_priv;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_radeon_vertex2_t vertex;
+	int i;
+	unsigned char laststate;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	sarea_priv = dev_priv->sarea_priv;
+
+	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data,
+				 sizeof(vertex));
+
+	DRM_DEBUG("pid=%d index=%d discard=%d\n",
+		  DRM_CURRENTPID, vertex.idx, vertex.discard);
+
+	if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
+		DRM_ERROR("buffer index %d (of %d max)\n",
+			  vertex.idx, dma->buf_count - 1);
+		return DRM_ERR(EINVAL);
+	}
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	buf = dma->buflist[vertex.idx];
+
+	if (buf->filp != filp) {
+		DRM_ERROR("process %d using buffer owned by %p\n",
+			  DRM_CURRENTPID, buf->filp);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (buf->pending) {
+		DRM_ERROR("sending pending buffer %d\n", vertex.idx);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+		return DRM_ERR(EINVAL);
+
+	for (laststate = 0xff, i = 0; i < vertex.nr_prims; i++) {
+		drm_radeon_prim_t prim;
+		drm_radeon_tcl_prim_t tclprim;
+
+		if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof(prim)))
+			return DRM_ERR(EFAULT);
+
+		if (prim.stateidx != laststate) {
+			drm_radeon_state_t state;
+
+			if (DRM_COPY_FROM_USER(&state,
+					       &vertex.state[prim.stateidx],
+					       sizeof(state)))
+				return DRM_ERR(EFAULT);
+
+			if (radeon_emit_state2(dev_priv, filp_priv, &state)) {
+				DRM_ERROR("radeon_emit_state2 failed\n");
+				return DRM_ERR(EINVAL);
+			}
+
+			laststate = prim.stateidx;
+		}
+
+		tclprim.start = prim.start;
+		tclprim.finish = prim.finish;
+		tclprim.prim = prim.prim;
+		tclprim.vc_format = prim.vc_format;
+
+		if (prim.prim & RADEON_PRIM_WALK_IND) {
+			tclprim.offset = prim.numverts * 64;
+			tclprim.numverts = RADEON_MAX_VB_VERTS;	/* duh */
+
+			radeon_cp_dispatch_indices(dev, buf, &tclprim);
+		} else {
+			tclprim.numverts = prim.numverts;
+			tclprim.offset = 0;	/* not used */
+
+			radeon_cp_dispatch_vertex(dev, buf, &tclprim);
+		}
+
+		if (sarea_priv->nbox == 1)
+			sarea_priv->nbox = 0;
+	}
+
+	if (vertex.discard) {
+		radeon_cp_discard_buffer(dev, buf);
+	}
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
+			       drm_file_t * filp_priv,
+			       drm_radeon_cmd_header_t header,
+			       drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	int id = (int)header.packet.packet_id;
+	int sz, reg;
+	int *data = (int *)cmdbuf->buf;
+	RING_LOCALS;
+
+	if (id >= RADEON_MAX_STATE_PACKETS)
+		return DRM_ERR(EINVAL);
+
+	sz = packet[id].len;
+	reg = packet[id].start;
+
+	if (sz * sizeof(int) > cmdbuf->bufsz) {
+		DRM_ERROR("Packet size provided larger than data provided\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) {
+		DRM_ERROR("Packet verification failed\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	BEGIN_RING(sz + 1);
+	OUT_RING(CP_PACKET0(reg, (sz - 1)));
+	OUT_RING_TABLE(data, sz);
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
+static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
+					  drm_radeon_cmd_header_t header,
+					  drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	int sz = header.scalars.count;
+	int start = header.scalars.offset;
+	int stride = header.scalars.stride;
+	RING_LOCALS;
+
+	BEGIN_RING(3 + sz);
+	OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
+	OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
+	OUT_RING_TABLE(cmdbuf->buf, sz);
+	ADVANCE_RING();
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
+/* God this is ugly
+ */
+static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
+					   drm_radeon_cmd_header_t header,
+					   drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	int sz = header.scalars.count;
+	int start = ((unsigned int)header.scalars.offset) + 0x100;
+	int stride = header.scalars.stride;
+	RING_LOCALS;
+
+	BEGIN_RING(3 + sz);
+	OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
+	OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
+	OUT_RING_TABLE(cmdbuf->buf, sz);
+	ADVANCE_RING();
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
+static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
+					  drm_radeon_cmd_header_t header,
+					  drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	int sz = header.vectors.count;
+	int start = header.vectors.offset;
+	int stride = header.vectors.stride;
+	RING_LOCALS;
+
+	BEGIN_RING(5 + sz);
+	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
+	OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
+	OUT_RING_TABLE(cmdbuf->buf, sz);
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
+static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
+					  drm_radeon_cmd_header_t header,
+					  drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	int sz = header.veclinear.count * 4;
+	int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
+	RING_LOCALS;
+
+	if (!sz)
+		return 0;
+	if (sz * 4 > cmdbuf->bufsz)
+		return DRM_ERR(EINVAL);
+
+	BEGIN_RING(5 + sz);
+	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
+	OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
+	OUT_RING_TABLE(cmdbuf->buf, sz);
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
+static int radeon_emit_packet3(drm_device_t * dev,
+			       drm_file_t * filp_priv,
+			       drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	unsigned int cmdsz;
+	int ret;
+	RING_LOCALS;
+
+	DRM_DEBUG("\n");
+
+	if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
+						  cmdbuf, &cmdsz))) {
+		DRM_ERROR("Packet verification failed\n");
+		return ret;
+	}
+
+	BEGIN_RING(cmdsz);
+	OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+	ADVANCE_RING();
+
+	cmdbuf->buf += cmdsz * 4;
+	cmdbuf->bufsz -= cmdsz * 4;
+	return 0;
+}
+
+static int radeon_emit_packet3_cliprect(drm_device_t *dev,
+					drm_file_t *filp_priv,
+					drm_radeon_kcmd_buffer_t *cmdbuf,
+					int orig_nbox)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_clip_rect_t box;
+	unsigned int cmdsz;
+	int ret;
+	drm_clip_rect_t __user *boxes = cmdbuf->boxes;
+	int i = 0;
+	RING_LOCALS;
+
+	DRM_DEBUG("\n");
+
+	if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv,
+						  cmdbuf, &cmdsz))) {
+		DRM_ERROR("Packet verification failed\n");
+		return ret;
+	}
+
+	if (!orig_nbox)
+		goto out;
+
+	do {
+		if (i < cmdbuf->nbox) {
+			if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
+				return DRM_ERR(EFAULT);
+			/* FIXME The second and subsequent times round
+			 * this loop, send a WAIT_UNTIL_3D_IDLE before
+			 * calling emit_clip_rect(). This fixes a
+			 * lockup on fast machines when sending
+			 * several cliprects with a cmdbuf, as when
+			 * waving a 2D window over a 3D
+			 * window. Something in the commands from user
+			 * space seems to hang the card when they're
+			 * sent several times in a row. That would be
+			 * the correct place to fix it but this works
+			 * around it until I can figure that out - Tim
+			 * Smith */
+			if (i) {
+				BEGIN_RING(2);
+				RADEON_WAIT_UNTIL_3D_IDLE();
+				ADVANCE_RING();
+			}
+			radeon_emit_clip_rect(dev_priv, &box);
+		}
+
+		BEGIN_RING(cmdsz);
+		OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+		ADVANCE_RING();
+
+	} while (++i < cmdbuf->nbox);
+	if (cmdbuf->nbox == 1)
+		cmdbuf->nbox = 0;
+
+      out:
+	cmdbuf->buf += cmdsz * 4;
+	cmdbuf->bufsz -= cmdsz * 4;
+	return 0;
+}
+
+static int radeon_emit_wait(drm_device_t * dev, int flags)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
+	switch (flags) {
+	case RADEON_WAIT_2D:
+		BEGIN_RING(2);
+		RADEON_WAIT_UNTIL_2D_IDLE();
+		ADVANCE_RING();
+		break;
+	case RADEON_WAIT_3D:
+		BEGIN_RING(2);
+		RADEON_WAIT_UNTIL_3D_IDLE();
+		ADVANCE_RING();
+		break;
+	case RADEON_WAIT_2D | RADEON_WAIT_3D:
+		BEGIN_RING(2);
+		RADEON_WAIT_UNTIL_IDLE();
+		ADVANCE_RING();
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
+
+static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf = NULL;
+	int idx;
+	drm_radeon_kcmd_buffer_t cmdbuf;
+	drm_radeon_cmd_header_t header;
+	int orig_nbox, orig_bufsz;
+	char *kbuf = NULL;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(cmdbuf,
+				 (drm_radeon_kcmd_buffer_t __user *) data,
+				 sizeof(cmdbuf));
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) {
+		return DRM_ERR(EINVAL);
+	}
+
+	/* Allocate an in-kernel area and copy in the cmdbuf.  Do this to avoid
+	 * races between checking values and using those values in other code,
+	 * and simply to avoid a lot of function calls to copy in data.
+	 */
+	orig_bufsz = cmdbuf.bufsz;
+	if (orig_bufsz != 0) {
+		kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
+		if (kbuf == NULL)
+			return DRM_ERR(ENOMEM);
+		if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf,
+				       cmdbuf.bufsz)) {
+			drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+			return DRM_ERR(EFAULT);
+		}
+		cmdbuf.buf = kbuf;
+	}
+
+	orig_nbox = cmdbuf.nbox;
+
+	if (dev_priv->microcode_version == UCODE_R300) {
+		int temp;
+		temp = r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf);
+
+		if (orig_bufsz != 0)
+			drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+
+		return temp;
+	}
+
+	/* microcode_version != r300 */
+	while (cmdbuf.bufsz >= sizeof(header)) {
+
+		header.i = *(int *)cmdbuf.buf;
+		cmdbuf.buf += sizeof(header);
+		cmdbuf.bufsz -= sizeof(header);
+
+		switch (header.header.cmd_type) {
+		case RADEON_CMD_PACKET:
+			DRM_DEBUG("RADEON_CMD_PACKET\n");
+			if (radeon_emit_packets
+			    (dev_priv, filp_priv, header, &cmdbuf)) {
+				DRM_ERROR("radeon_emit_packets failed\n");
+				goto err;
+			}
+			break;
+
+		case RADEON_CMD_SCALARS:
+			DRM_DEBUG("RADEON_CMD_SCALARS\n");
+			if (radeon_emit_scalars(dev_priv, header, &cmdbuf)) {
+				DRM_ERROR("radeon_emit_scalars failed\n");
+				goto err;
+			}
+			break;
+
+		case RADEON_CMD_VECTORS:
+			DRM_DEBUG("RADEON_CMD_VECTORS\n");
+			if (radeon_emit_vectors(dev_priv, header, &cmdbuf)) {
+				DRM_ERROR("radeon_emit_vectors failed\n");
+				goto err;
+			}
+			break;
+
+		case RADEON_CMD_DMA_DISCARD:
+			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+			idx = header.dma.buf_idx;
+			if (idx < 0 || idx >= dma->buf_count) {
+				DRM_ERROR("buffer index %d (of %d max)\n",
+					  idx, dma->buf_count - 1);
+				goto err;
+			}
+
+			buf = dma->buflist[idx];
+			if (buf->filp != filp || buf->pending) {
+				DRM_ERROR("bad buffer %p %p %d\n",
+					  buf->filp, filp, buf->pending);
+				goto err;
+			}
+
+			radeon_cp_discard_buffer(dev, buf);
+			break;
+
+		case RADEON_CMD_PACKET3:
+			DRM_DEBUG("RADEON_CMD_PACKET3\n");
+			if (radeon_emit_packet3(dev, filp_priv, &cmdbuf)) {
+				DRM_ERROR("radeon_emit_packet3 failed\n");
+				goto err;
+			}
+			break;
+
+		case RADEON_CMD_PACKET3_CLIP:
+			DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
+			if (radeon_emit_packet3_cliprect
+			    (dev, filp_priv, &cmdbuf, orig_nbox)) {
+				DRM_ERROR("radeon_emit_packet3_clip failed\n");
+				goto err;
+			}
+			break;
+
+		case RADEON_CMD_SCALARS2:
+			DRM_DEBUG("RADEON_CMD_SCALARS2\n");
+			if (radeon_emit_scalars2(dev_priv, header, &cmdbuf)) {
+				DRM_ERROR("radeon_emit_scalars2 failed\n");
+				goto err;
+			}
+			break;
+
+		case RADEON_CMD_WAIT:
+			DRM_DEBUG("RADEON_CMD_WAIT\n");
+			if (radeon_emit_wait(dev, header.wait.flags)) {
+				DRM_ERROR("radeon_emit_wait failed\n");
+				goto err;
+			}
+			break;
+		case RADEON_CMD_VECLINEAR:
+			DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
+			if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) {
+				DRM_ERROR("radeon_emit_veclinear failed\n");
+				goto err;
+			}
+			break;
+
+		default:
+			DRM_ERROR("bad cmd_type %d at %p\n",
+				  header.header.cmd_type,
+				  cmdbuf.buf - sizeof(header));
+			goto err;
+		}
+	}
+
+	if (orig_bufsz != 0)
+		drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+
+	DRM_DEBUG("DONE\n");
+	COMMIT_RING();
+	return 0;
+
+      err:
+	if (orig_bufsz != 0)
+		drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+	return DRM_ERR(EINVAL);
+}
+
+static int radeon_cp_getparam(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_getparam_t param;
+	int value;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data,
+				 sizeof(param));
+
+	DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+	switch (param.param) {
+	case RADEON_PARAM_GART_BUFFER_OFFSET:
+		value = dev_priv->gart_buffers_offset;
+		break;
+	case RADEON_PARAM_LAST_FRAME:
+		dev_priv->stats.last_frame_reads++;
+		value = GET_SCRATCH(0);
+		break;
+	case RADEON_PARAM_LAST_DISPATCH:
+		value = GET_SCRATCH(1);
+		break;
+	case RADEON_PARAM_LAST_CLEAR:
+		dev_priv->stats.last_clear_reads++;
+		value = GET_SCRATCH(2);
+		break;
+	case RADEON_PARAM_IRQ_NR:
+		value = dev->irq;
+		break;
+	case RADEON_PARAM_GART_BASE:
+		value = dev_priv->gart_vm_start;
+		break;
+	case RADEON_PARAM_REGISTER_HANDLE:
+		value = dev_priv->mmio->offset;
+		break;
+	case RADEON_PARAM_STATUS_HANDLE:
+		value = dev_priv->ring_rptr_offset;
+		break;
+#ifndef __LP64__
+		/*
+		 * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
+		 * pointer which can't fit into an int-sized variable.  According to
+		 * Michel Dänzer, the ioctl() is only used on embedded platforms, so
+		 * not supporting it shouldn't be a problem.  If the same functionality
+		 * is needed on 64-bit platforms, a new ioctl() would have to be added,
+		 * so backwards-compatibility for the embedded platforms can be
+		 * maintained.  --davidm 4-Feb-2004.
+		 */
+	case RADEON_PARAM_SAREA_HANDLE:
+		/* The lock is the first dword in the sarea. */
+		value = (long)dev->lock.hw_lock;
+		break;
+#endif
+	case RADEON_PARAM_GART_TEX_HANDLE:
+		value = dev_priv->gart_textures_offset;
+		break;
+	case RADEON_PARAM_SCRATCH_OFFSET:
+		if (!dev_priv->writeback_works)
+			return DRM_ERR(EINVAL);
+		value = RADEON_SCRATCH_REG_OFFSET;
+		break;
+	
+	case RADEON_PARAM_CARD_TYPE:
+		if (dev_priv->flags & RADEON_IS_PCIE)
+			value = RADEON_CARD_PCIE;
+		else if (dev_priv->flags & RADEON_IS_AGP)
+			value = RADEON_CARD_AGP;
+		else
+			value = RADEON_CARD_PCI;
+		break;
+	default:
+		DRM_DEBUG( "Invalid parameter %d\n", param.param );
+		return DRM_ERR(EINVAL);
+	}
+
+	if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+static int radeon_cp_setparam(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_file_t *filp_priv;
+	drm_radeon_setparam_t sp;
+	struct drm_radeon_driver_file_fields *radeon_priv;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data,
+				 sizeof(sp));
+
+	switch (sp.param) {
+	case RADEON_SETPARAM_FB_LOCATION:
+		radeon_priv = filp_priv->driver_priv;
+		radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
+		break;
+	case RADEON_SETPARAM_SWITCH_TILING:
+		if (sp.value == 0) {
+			DRM_DEBUG("color tiling disabled\n");
+			dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
+			dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
+			dev_priv->sarea_priv->tiling_enabled = 0;
+		} else if (sp.value == 1) {
+			DRM_DEBUG("color tiling enabled\n");
+			dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
+			dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
+			dev_priv->sarea_priv->tiling_enabled = 1;
+		}
+		break;
+	case RADEON_SETPARAM_PCIGART_LOCATION:
+		dev_priv->pcigart_offset = sp.value;
+		break;
+	case RADEON_SETPARAM_NEW_MEMMAP:
+		dev_priv->new_memmap = sp.value;
+		break;
+	default:
+		DRM_DEBUG("Invalid parameter %d\n", sp.param);
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
+
+/* When a client dies:
+ *    - Check for and clean up flipped page state
+ *    - Free any alloced GART memory.
+ *    - Free any alloced radeon surfaces.
+ *
+ * DRM infrastructure takes care of reclaiming dma buffers.
+ */
+void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
+{
+	if (dev->dev_private) {
+		drm_radeon_private_t *dev_priv = dev->dev_private;
+		if (dev_priv->page_flipping) {
+			radeon_do_cleanup_pageflip(dev);
+		}
+		radeon_mem_release(filp, dev_priv->gart_heap);
+		radeon_mem_release(filp, dev_priv->fb_heap);
+		radeon_surfaces_release(filp, dev_priv);
+	}
+}
+
+void radeon_driver_lastclose(drm_device_t * dev)
+{
+	radeon_do_release(dev);
+}
+
+int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	struct drm_radeon_driver_file_fields *radeon_priv;
+
+	DRM_DEBUG("\n");
+	radeon_priv =
+	    (struct drm_radeon_driver_file_fields *)
+	    drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
+
+	if (!radeon_priv)
+		return -ENOMEM;
+
+	filp_priv->driver_priv = radeon_priv;
+
+	if (dev_priv)
+		radeon_priv->radeon_fb_delta = dev_priv->fb_location;
+	else
+		radeon_priv->radeon_fb_delta = 0;
+	return 0;
+}
+
+void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv)
+{
+	struct drm_radeon_driver_file_fields *radeon_priv =
+	    filp_priv->driver_priv;
+
+	drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
+}
+
+drm_ioctl_desc_t radeon_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, DRM_AUTH}
+};
+
+int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
--- libdrm-2.3.0.orig/shared-core/r128_state.c
+++ libdrm-2.3.0/shared-core/r128_state.c
@@ -0,0 +1,1713 @@
+/* r128_state.c -- State support for r128 -*- linux-c -*-
+ * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
+ */
+/*
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+#include "r128_drv.h"
+
+/* ================================================================
+ * CCE hardware state programming functions
+ */
+
+static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
+				 drm_clip_rect_t * boxes, int count)
+{
+	u32 aux_sc_cntl = 0x00000000;
+	RING_LOCALS;
+	DRM_DEBUG("    %s\n", __FUNCTION__);
+
+	BEGIN_RING((count < 3 ? count : 3) * 5 + 2);
+
+	if (count >= 1) {
+		OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3));
+		OUT_RING(boxes[0].x1);
+		OUT_RING(boxes[0].x2 - 1);
+		OUT_RING(boxes[0].y1);
+		OUT_RING(boxes[0].y2 - 1);
+
+		aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
+	}
+	if (count >= 2) {
+		OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3));
+		OUT_RING(boxes[1].x1);
+		OUT_RING(boxes[1].x2 - 1);
+		OUT_RING(boxes[1].y1);
+		OUT_RING(boxes[1].y2 - 1);
+
+		aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
+	}
+	if (count >= 3) {
+		OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3));
+		OUT_RING(boxes[2].x1);
+		OUT_RING(boxes[2].x2 - 1);
+		OUT_RING(boxes[2].y1);
+		OUT_RING(boxes[2].y2 - 1);
+
+		aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
+	}
+
+	OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0));
+	OUT_RING(aux_sc_cntl);
+
+	ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_core(drm_r128_private_t * dev_priv)
+{
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG("    %s\n", __FUNCTION__);
+
+	BEGIN_RING(2);
+
+	OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0));
+	OUT_RING(ctx->scale_3d_cntl);
+
+	ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_context(drm_r128_private_t * dev_priv)
+{
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG("    %s\n", __FUNCTION__);
+
+	BEGIN_RING(13);
+
+	OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11));
+	OUT_RING(ctx->dst_pitch_offset_c);
+	OUT_RING(ctx->dp_gui_master_cntl_c);
+	OUT_RING(ctx->sc_top_left_c);
+	OUT_RING(ctx->sc_bottom_right_c);
+	OUT_RING(ctx->z_offset_c);
+	OUT_RING(ctx->z_pitch_c);
+	OUT_RING(ctx->z_sten_cntl_c);
+	OUT_RING(ctx->tex_cntl_c);
+	OUT_RING(ctx->misc_3d_state_cntl_reg);
+	OUT_RING(ctx->texture_clr_cmp_clr_c);
+	OUT_RING(ctx->texture_clr_cmp_msk_c);
+	OUT_RING(ctx->fog_color_c);
+
+	ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv)
+{
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG("    %s\n", __FUNCTION__);
+
+	BEGIN_RING(3);
+
+	OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP));
+	OUT_RING(ctx->setup_cntl);
+	OUT_RING(ctx->pm4_vc_fpu_setup);
+
+	ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv)
+{
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG("    %s\n", __FUNCTION__);
+
+	BEGIN_RING(5);
+
+	OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
+	OUT_RING(ctx->dp_write_mask);
+
+	OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1));
+	OUT_RING(ctx->sten_ref_mask_c);
+	OUT_RING(ctx->plane_3d_mask_c);
+
+	ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_window(drm_r128_private_t * dev_priv)
+{
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+	RING_LOCALS;
+	DRM_DEBUG("    %s\n", __FUNCTION__);
+
+	BEGIN_RING(2);
+
+	OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0));
+	OUT_RING(ctx->window_xy_offset);
+
+	ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv)
+{
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG("    %s\n", __FUNCTION__);
+
+	BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);
+
+	OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C,
+			     2 + R128_MAX_TEXTURE_LEVELS));
+	OUT_RING(tex->tex_cntl);
+	OUT_RING(tex->tex_combine_cntl);
+	OUT_RING(ctx->tex_size_pitch_c);
+	for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
+		OUT_RING(tex->tex_offset[i]);
+	}
+
+	OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1));
+	OUT_RING(ctx->constant_color_c);
+	OUT_RING(tex->tex_border_color);
+
+	ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
+{
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG("    %s\n", __FUNCTION__);
+
+	BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
+
+	OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));
+	OUT_RING(tex->tex_cntl);
+	OUT_RING(tex->tex_combine_cntl);
+	for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
+		OUT_RING(tex->tex_offset[i]);
+	}
+
+	OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));
+	OUT_RING(tex->tex_border_color);
+
+	ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv)
+{
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	unsigned int dirty = sarea_priv->dirty;
+
+	DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty);
+
+	if (dirty & R128_UPLOAD_CORE) {
+		r128_emit_core(dev_priv);
+		sarea_priv->dirty &= ~R128_UPLOAD_CORE;
+	}
+
+	if (dirty & R128_UPLOAD_CONTEXT) {
+		r128_emit_context(dev_priv);
+		sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
+	}
+
+	if (dirty & R128_UPLOAD_SETUP) {
+		r128_emit_setup(dev_priv);
+		sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
+	}
+
+	if (dirty & R128_UPLOAD_MASKS) {
+		r128_emit_masks(dev_priv);
+		sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
+	}
+
+	if (dirty & R128_UPLOAD_WINDOW) {
+		r128_emit_window(dev_priv);
+		sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
+	}
+
+	if (dirty & R128_UPLOAD_TEX0) {
+		r128_emit_tex0(dev_priv);
+		sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
+	}
+
+	if (dirty & R128_UPLOAD_TEX1) {
+		r128_emit_tex1(dev_priv);
+		sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
+	}
+
+	/* Turn off the texture cache flushing */
+	sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
+
+	sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
+}
+
+#if R128_PERFORMANCE_BOXES
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void r128_clear_box(drm_r128_private_t * dev_priv,
+			   int x, int y, int w, int h, int r, int g, int b)
+{
+	u32 pitch, offset;
+	u32 fb_bpp, color;
+	RING_LOCALS;
+
+	switch (dev_priv->fb_bpp) {
+	case 16:
+		fb_bpp = R128_GMC_DST_16BPP;
+		color = (((r & 0xf8) << 8) |
+			 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
+		break;
+	case 24:
+		fb_bpp = R128_GMC_DST_24BPP;
+		color = ((r << 16) | (g << 8) | b);
+		break;
+	case 32:
+		fb_bpp = R128_GMC_DST_32BPP;
+		color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+		break;
+	default:
+		return;
+	}
+
+	offset = dev_priv->back_offset;
+	pitch = dev_priv->back_pitch >> 3;
+
+	BEGIN_RING(6);
+
+	OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+	OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+		 R128_GMC_BRUSH_SOLID_COLOR |
+		 fb_bpp |
+		 R128_GMC_SRC_DATATYPE_COLOR |
+		 R128_ROP3_P |
+		 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);
+
+	OUT_RING((pitch << 21) | (offset >> 5));
+	OUT_RING(color);
+
+	OUT_RING((x << 16) | y);
+	OUT_RING((w << 16) | h);
+
+	ADVANCE_RING();
+}
+
+static void r128_cce_performance_boxes(drm_r128_private_t * dev_priv)
+{
+	if (atomic_read(&dev_priv->idle_count) == 0) {
+		r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
+	} else {
+		atomic_set(&dev_priv->idle_count, 0);
+	}
+}
+
+#endif
+
+/* ================================================================
+ * CCE command dispatch functions
+ */
+
+static void r128_print_dirty(const char *msg, unsigned int flags)
+{
+	DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
+		 msg,
+		 flags,
+		 (flags & R128_UPLOAD_CORE) ? "core, " : "",
+		 (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
+		 (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
+		 (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
+		 (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
+		 (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
+		 (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
+		 (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
+		 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
+}
+
+static void r128_cce_dispatch_clear(drm_device_t * dev,
+				    drm_r128_clear_t * clear)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int nbox = sarea_priv->nbox;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	unsigned int flags = clear->flags;
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+		unsigned int tmp = flags;
+
+		flags &= ~(R128_FRONT | R128_BACK);
+		if (tmp & R128_FRONT)
+			flags |= R128_BACK;
+		if (tmp & R128_BACK)
+			flags |= R128_FRONT;
+	}
+
+	for (i = 0; i < nbox; i++) {
+		int x = pbox[i].x1;
+		int y = pbox[i].y1;
+		int w = pbox[i].x2 - x;
+		int h = pbox[i].y2 - y;
+
+		DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
+			  pbox[i].x1, pbox[i].y1, pbox[i].x2,
+			  pbox[i].y2, flags);
+
+		if (flags & (R128_FRONT | R128_BACK)) {
+			BEGIN_RING(2);
+
+			OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
+			OUT_RING(clear->color_mask);
+
+			ADVANCE_RING();
+		}
+
+		if (flags & R128_FRONT) {
+			BEGIN_RING(6);
+
+			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+				 R128_GMC_BRUSH_SOLID_COLOR |
+				 (dev_priv->color_fmt << 8) |
+				 R128_GMC_SRC_DATATYPE_COLOR |
+				 R128_ROP3_P |
+				 R128_GMC_CLR_CMP_CNTL_DIS |
+				 R128_GMC_AUX_CLIP_DIS);
+
+			OUT_RING(dev_priv->front_pitch_offset_c);
+			OUT_RING(clear->clear_color);
+
+			OUT_RING((x << 16) | y);
+			OUT_RING((w << 16) | h);
+
+			ADVANCE_RING();
+		}
+
+		if (flags & R128_BACK) {
+			BEGIN_RING(6);
+
+			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+				 R128_GMC_BRUSH_SOLID_COLOR |
+				 (dev_priv->color_fmt << 8) |
+				 R128_GMC_SRC_DATATYPE_COLOR |
+				 R128_ROP3_P |
+				 R128_GMC_CLR_CMP_CNTL_DIS |
+				 R128_GMC_AUX_CLIP_DIS);
+
+			OUT_RING(dev_priv->back_pitch_offset_c);
+			OUT_RING(clear->clear_color);
+
+			OUT_RING((x << 16) | y);
+			OUT_RING((w << 16) | h);
+
+			ADVANCE_RING();
+		}
+
+		if (flags & R128_DEPTH) {
+			BEGIN_RING(6);
+
+			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+				 R128_GMC_BRUSH_SOLID_COLOR |
+				 (dev_priv->depth_fmt << 8) |
+				 R128_GMC_SRC_DATATYPE_COLOR |
+				 R128_ROP3_P |
+				 R128_GMC_CLR_CMP_CNTL_DIS |
+				 R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
+
+			OUT_RING(dev_priv->depth_pitch_offset_c);
+			OUT_RING(clear->clear_depth);
+
+			OUT_RING((x << 16) | y);
+			OUT_RING((w << 16) | h);
+
+			ADVANCE_RING();
+		}
+	}
+}
+
+static void r128_cce_dispatch_swap(drm_device_t * dev)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int nbox = sarea_priv->nbox;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+#if R128_PERFORMANCE_BOXES
+	/* Do some trivial performance monitoring...
+	 */
+	r128_cce_performance_boxes(dev_priv);
+#endif
+
+	for (i = 0; i < nbox; i++) {
+		int x = pbox[i].x1;
+		int y = pbox[i].y1;
+		int w = pbox[i].x2 - x;
+		int h = pbox[i].y2 - y;
+
+		BEGIN_RING(7);
+
+		OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
+		OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
+			 R128_GMC_DST_PITCH_OFFSET_CNTL |
+			 R128_GMC_BRUSH_NONE |
+			 (dev_priv->color_fmt << 8) |
+			 R128_GMC_SRC_DATATYPE_COLOR |
+			 R128_ROP3_S |
+			 R128_DP_SRC_SOURCE_MEMORY |
+			 R128_GMC_CLR_CMP_CNTL_DIS |
+			 R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
+
+		/* Make this work even if front & back are flipped:
+		 */
+		if (dev_priv->current_page == 0) {
+			OUT_RING(dev_priv->back_pitch_offset_c);
+			OUT_RING(dev_priv->front_pitch_offset_c);
+		} else {
+			OUT_RING(dev_priv->front_pitch_offset_c);
+			OUT_RING(dev_priv->back_pitch_offset_c);
+		}
+
+		OUT_RING((x << 16) | y);
+		OUT_RING((x << 16) | y);
+		OUT_RING((w << 16) | h);
+
+		ADVANCE_RING();
+	}
+
+	/* Increment the frame counter.  The client-side 3D driver must
+	 * throttle the framerate by waiting for this value before
+	 * performing the swapbuffer ioctl.
+	 */
+	dev_priv->sarea_priv->last_frame++;
+
+	BEGIN_RING(2);
+
+	OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
+	OUT_RING(dev_priv->sarea_priv->last_frame);
+
+	ADVANCE_RING();
+}
+
+static void r128_cce_dispatch_flip(drm_device_t * dev)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+		  __FUNCTION__,
+		  dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
+
+#if R128_PERFORMANCE_BOXES
+	/* Do some trivial performance monitoring...
+	 */
+	r128_cce_performance_boxes(dev_priv);
+#endif
+
+	BEGIN_RING(4);
+
+	R128_WAIT_UNTIL_PAGE_FLIPPED();
+	OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));
+
+	if (dev_priv->current_page == 0) {
+		OUT_RING(dev_priv->back_offset);
+	} else {
+		OUT_RING(dev_priv->front_offset);
+	}
+
+	ADVANCE_RING();
+
+	/* Increment the frame counter.  The client-side 3D driver must
+	 * throttle the framerate by waiting for this value before
+	 * performing the swapbuffer ioctl.
+	 */
+	dev_priv->sarea_priv->last_frame++;
+	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
+	    1 - dev_priv->current_page;
+
+	BEGIN_RING(2);
+
+	OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
+	OUT_RING(dev_priv->sarea_priv->last_frame);
+
+	ADVANCE_RING();
+}
+
+static void r128_cce_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int format = sarea_priv->vc_format;
+	int offset = buf->bus_address;
+	int size = buf->used;
+	int prim = buf_priv->prim;
+	int i = 0;
+	RING_LOCALS;
+	DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);
+
+	if (0)
+		r128_print_dirty("dispatch_vertex", sarea_priv->dirty);
+
+	if (buf->used) {
+		buf_priv->dispatched = 1;
+
+		if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
+			r128_emit_state(dev_priv);
+		}
+
+		do {
+			/* Emit the next set of up to three cliprects */
+			if (i < sarea_priv->nbox) {
+				r128_emit_clip_rects(dev_priv,
+						     &sarea_priv->boxes[i],
+						     sarea_priv->nbox - i);
+			}
+
+			/* Emit the vertex buffer rendering commands */
+			BEGIN_RING(5);
+
+			OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));
+			OUT_RING(offset);
+			OUT_RING(size);
+			OUT_RING(format);
+			OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
+				 (size << R128_CCE_VC_CNTL_NUM_SHIFT));
+
+			ADVANCE_RING();
+
+			i += 3;
+		} while (i < sarea_priv->nbox);
+	}
+
+	if (buf_priv->discard) {
+		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+		/* Emit the vertex buffer age */
+		BEGIN_RING(2);
+
+		OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
+		OUT_RING(buf_priv->age);
+
+		ADVANCE_RING();
+
+		buf->pending = 1;
+		buf->used = 0;
+		/* FIXME: Check dispatched field */
+		buf_priv->dispatched = 0;
+	}
+
+	dev_priv->sarea_priv->last_dispatch++;
+
+	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
+	sarea_priv->nbox = 0;
+}
+
+static void r128_cce_dispatch_indirect(drm_device_t * dev,
+				       drm_buf_t * buf, int start, int end)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+	RING_LOCALS;
+	DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
+
+	if (start != end) {
+		int offset = buf->bus_address + start;
+		int dwords = (end - start + 3) / sizeof(u32);
+
+		/* Indirect buffer data must be an even number of
+		 * dwords, so if we've been given an odd number we must
+		 * pad the data with a Type-2 CCE packet.
+		 */
+		if (dwords & 1) {
+			u32 *data = (u32 *)
+			    ((char *)dev->agp_buffer_map->handle
+			     + buf->offset + start);
+			data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);
+		}
+
+		buf_priv->dispatched = 1;
+
+		/* Fire off the indirect buffer */
+		BEGIN_RING(3);
+
+		OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));
+		OUT_RING(offset);
+		OUT_RING(dwords);
+
+		ADVANCE_RING();
+	}
+
+	if (buf_priv->discard) {
+		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+		/* Emit the indirect buffer age */
+		BEGIN_RING(2);
+
+		OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
+		OUT_RING(buf_priv->age);
+
+		ADVANCE_RING();
+
+		buf->pending = 1;
+		buf->used = 0;
+		/* FIXME: Check dispatched field */
+		buf_priv->dispatched = 0;
+	}
+
+	dev_priv->sarea_priv->last_dispatch++;
+}
+
+static void r128_cce_dispatch_indices(drm_device_t * dev,
+				      drm_buf_t * buf,
+				      int start, int end, int count)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int format = sarea_priv->vc_format;
+	int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
+	int prim = buf_priv->prim;
+	u32 *data;
+	int dwords;
+	int i = 0;
+	RING_LOCALS;
+	DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);
+
+	if (0)
+		r128_print_dirty("dispatch_indices", sarea_priv->dirty);
+
+	if (start != end) {
+		buf_priv->dispatched = 1;
+
+		if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
+			r128_emit_state(dev_priv);
+		}
+
+		dwords = (end - start + 3) / sizeof(u32);
+
+		data = (u32 *) ((char *)dev->agp_buffer_map->handle
+				+ buf->offset + start);
+
+		data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,
+						  dwords - 2));
+
+		data[1] = cpu_to_le32(offset);
+		data[2] = cpu_to_le32(R128_MAX_VB_VERTS);
+		data[3] = cpu_to_le32(format);
+		data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
+				       (count << 16)));
+
+		if (count & 0x1) {
+#ifdef __LITTLE_ENDIAN
+			data[dwords - 1] &= 0x0000ffff;
+#else
+			data[dwords - 1] &= 0xffff0000;
+#endif
+		}
+
+		do {
+			/* Emit the next set of up to three cliprects */
+			if (i < sarea_priv->nbox) {
+				r128_emit_clip_rects(dev_priv,
+						     &sarea_priv->boxes[i],
+						     sarea_priv->nbox - i);
+			}
+
+			r128_cce_dispatch_indirect(dev, buf, start, end);
+
+			i += 3;
+		} while (i < sarea_priv->nbox);
+	}
+
+	if (buf_priv->discard) {
+		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+		/* Emit the vertex buffer age */
+		BEGIN_RING(2);
+
+		OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
+		OUT_RING(buf_priv->age);
+
+		ADVANCE_RING();
+
+		buf->pending = 1;
+		/* FIXME: Check dispatched field */
+		buf_priv->dispatched = 0;
+	}
+
+	dev_priv->sarea_priv->last_dispatch++;
+
+	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
+	sarea_priv->nbox = 0;
+}
+
+static int r128_cce_dispatch_blit(DRMFILE filp,
+				  drm_device_t * dev, drm_r128_blit_t * blit)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_r128_buf_priv_t *buf_priv;
+	u32 *data;
+	int dword_shift, dwords;
+	RING_LOCALS;
+	DRM_DEBUG("\n");
+
+	/* The compiler won't optimize away a division by a variable,
+	 * even if the only legal values are powers of two.  Thus, we'll
+	 * use a shift instead.
+	 */
+	switch (blit->format) {
+	case R128_DATATYPE_ARGB8888:
+		dword_shift = 0;
+		break;
+	case R128_DATATYPE_ARGB1555:
+	case R128_DATATYPE_RGB565:
+	case R128_DATATYPE_ARGB4444:
+	case R128_DATATYPE_YVYU422:
+	case R128_DATATYPE_VYUY422:
+		dword_shift = 1;
+		break;
+	case R128_DATATYPE_CI8:
+	case R128_DATATYPE_RGB8:
+		dword_shift = 2;
+		break;
+	default:
+		DRM_ERROR("invalid blit format %d\n", blit->format);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* Flush the pixel cache, and mark the contents as Read Invalid.
+	 * This ensures no pixel data gets mixed up with the texture
+	 * data from the host data blit, otherwise part of the texture
+	 * image may be corrupted.
+	 */
+	BEGIN_RING(2);
+
+	OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
+	OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);
+
+	ADVANCE_RING();
+
+	/* Dispatch the indirect buffer.
+	 */
+	buf = dma->buflist[blit->idx];
+	buf_priv = buf->dev_private;
+
+	if (buf->filp != filp) {
+		DRM_ERROR("process %d using buffer owned by %p\n",
+			  DRM_CURRENTPID, buf->filp);
+		return DRM_ERR(EINVAL);
+	}
+	if (buf->pending) {
+		DRM_ERROR("sending pending buffer %d\n", blit->idx);
+		return DRM_ERR(EINVAL);
+	}
+
+	buf_priv->discard = 1;
+
+	dwords = (blit->width * blit->height) >> dword_shift;
+
+	data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+
+	data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));
+	data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |
+			       R128_GMC_BRUSH_NONE |
+			       (blit->format << 8) |
+			       R128_GMC_SRC_DATATYPE_COLOR |
+			       R128_ROP3_S |
+			       R128_DP_SRC_SOURCE_HOST_DATA |
+			       R128_GMC_CLR_CMP_CNTL_DIS |
+			       R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));
+
+	data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));
+	data[3] = cpu_to_le32(0xffffffff);
+	data[4] = cpu_to_le32(0xffffffff);
+	data[5] = cpu_to_le32((blit->y << 16) | blit->x);
+	data[6] = cpu_to_le32((blit->height << 16) | blit->width);
+	data[7] = cpu_to_le32(dwords);
+
+	buf->used = (dwords + 8) * sizeof(u32);
+
+	r128_cce_dispatch_indirect(dev, buf, 0, buf->used);
+
+	/* Flush the pixel cache after the blit completes.  This ensures
+	 * the texture data is written out to memory before rendering
+	 * continues.
+	 */
+	BEGIN_RING(2);
+
+	OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
+	OUT_RING(R128_PC_FLUSH_GUI);
+
+	ADVANCE_RING();
+
+	return 0;
+}
+
+/* ================================================================
+ * Tiled depth buffer management
+ *
+ * FIXME: These should all set the destination write mask for when we
+ * have hardware stencil support.
+ */
+
+static int r128_cce_dispatch_write_span(drm_device_t * dev,
+					drm_r128_depth_t * depth)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	int count, x, y;
+	u32 *buffer;
+	u8 *mask;
+	int i, buffer_size, mask_size;
+	RING_LOCALS;
+	DRM_DEBUG("\n");
+
+	count = depth->n;
+	if (count > 4096 || count <= 0)
+		return DRM_ERR(EMSGSIZE);
+
+	if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
+		return DRM_ERR(EFAULT);
+	}
+	if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
+		return DRM_ERR(EFAULT);
+	}
+
+	buffer_size = depth->n * sizeof(u32);
+	buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+	if (buffer == NULL)
+		return DRM_ERR(ENOMEM);
+	if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
+		drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+		return DRM_ERR(EFAULT);
+	}
+
+	mask_size = depth->n * sizeof(u8);
+	if (depth->mask) {
+		mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+		if (mask == NULL) {
+			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+			return DRM_ERR(ENOMEM);
+		}
+		if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
+			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+			drm_free(mask, mask_size, DRM_MEM_BUFS);
+			return DRM_ERR(EFAULT);
+		}
+
+		for (i = 0; i < count; i++, x++) {
+			if (mask[i]) {
+				BEGIN_RING(6);
+
+				OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+				OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+					 R128_GMC_BRUSH_SOLID_COLOR |
+					 (dev_priv->depth_fmt << 8) |
+					 R128_GMC_SRC_DATATYPE_COLOR |
+					 R128_ROP3_P |
+					 R128_GMC_CLR_CMP_CNTL_DIS |
+					 R128_GMC_WR_MSK_DIS);
+
+				OUT_RING(dev_priv->depth_pitch_offset_c);
+				OUT_RING(buffer[i]);
+
+				OUT_RING((x << 16) | y);
+				OUT_RING((1 << 16) | 1);
+
+				ADVANCE_RING();
+			}
+		}
+
+		drm_free(mask, mask_size, DRM_MEM_BUFS);
+	} else {
+		for (i = 0; i < count; i++, x++) {
+			BEGIN_RING(6);
+
+			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+				 R128_GMC_BRUSH_SOLID_COLOR |
+				 (dev_priv->depth_fmt << 8) |
+				 R128_GMC_SRC_DATATYPE_COLOR |
+				 R128_ROP3_P |
+				 R128_GMC_CLR_CMP_CNTL_DIS |
+				 R128_GMC_WR_MSK_DIS);
+
+			OUT_RING(dev_priv->depth_pitch_offset_c);
+			OUT_RING(buffer[i]);
+
+			OUT_RING((x << 16) | y);
+			OUT_RING((1 << 16) | 1);
+
+			ADVANCE_RING();
+		}
+	}
+
+	drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+
+	return 0;
+}
+
+static int r128_cce_dispatch_write_pixels(drm_device_t * dev,
+					  drm_r128_depth_t * depth)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	int count, *x, *y;
+	u32 *buffer;
+	u8 *mask;
+	int i, xbuf_size, ybuf_size, buffer_size, mask_size;
+	RING_LOCALS;
+	DRM_DEBUG("\n");
+
+	count = depth->n;
+	if (count > 4096 || count <= 0)
+		return DRM_ERR(EMSGSIZE);
+
+	xbuf_size = count * sizeof(*x);
+	ybuf_size = count * sizeof(*y);
+	x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+	if (x == NULL) {
+		return DRM_ERR(ENOMEM);
+	}
+	y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+	if (y == NULL) {
+		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		return DRM_ERR(ENOMEM);
+	}
+	if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		return DRM_ERR(EFAULT);
+	}
+	if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
+		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		return DRM_ERR(EFAULT);
+	}
+
+	buffer_size = depth->n * sizeof(u32);
+	buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+	if (buffer == NULL) {
+		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		return DRM_ERR(ENOMEM);
+	}
+	if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
+		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+		return DRM_ERR(EFAULT);
+	}
+
+	if (depth->mask) {
+		mask_size = depth->n * sizeof(u8);
+		mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+		if (mask == NULL) {
+			drm_free(x, xbuf_size, DRM_MEM_BUFS);
+			drm_free(y, ybuf_size, DRM_MEM_BUFS);
+			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+			return DRM_ERR(ENOMEM);
+		}
+		if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
+			drm_free(x, xbuf_size, DRM_MEM_BUFS);
+			drm_free(y, ybuf_size, DRM_MEM_BUFS);
+			drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+			drm_free(mask, mask_size, DRM_MEM_BUFS);
+			return DRM_ERR(EFAULT);
+		}
+
+		for (i = 0; i < count; i++) {
+			if (mask[i]) {
+				BEGIN_RING(6);
+
+				OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+				OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+					 R128_GMC_BRUSH_SOLID_COLOR |
+					 (dev_priv->depth_fmt << 8) |
+					 R128_GMC_SRC_DATATYPE_COLOR |
+					 R128_ROP3_P |
+					 R128_GMC_CLR_CMP_CNTL_DIS |
+					 R128_GMC_WR_MSK_DIS);
+
+				OUT_RING(dev_priv->depth_pitch_offset_c);
+				OUT_RING(buffer[i]);
+
+				OUT_RING((x[i] << 16) | y[i]);
+				OUT_RING((1 << 16) | 1);
+
+				ADVANCE_RING();
+			}
+		}
+
+		drm_free(mask, mask_size, DRM_MEM_BUFS);
+	} else {
+		for (i = 0; i < count; i++) {
+			BEGIN_RING(6);
+
+			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+				 R128_GMC_BRUSH_SOLID_COLOR |
+				 (dev_priv->depth_fmt << 8) |
+				 R128_GMC_SRC_DATATYPE_COLOR |
+				 R128_ROP3_P |
+				 R128_GMC_CLR_CMP_CNTL_DIS |
+				 R128_GMC_WR_MSK_DIS);
+
+			OUT_RING(dev_priv->depth_pitch_offset_c);
+			OUT_RING(buffer[i]);
+
+			OUT_RING((x[i] << 16) | y[i]);
+			OUT_RING((1 << 16) | 1);
+
+			ADVANCE_RING();
+		}
+	}
+
+	drm_free(x, xbuf_size, DRM_MEM_BUFS);
+	drm_free(y, ybuf_size, DRM_MEM_BUFS);
+	drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+
+	return 0;
+}
+
+static int r128_cce_dispatch_read_span(drm_device_t * dev,
+				       drm_r128_depth_t * depth)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	int count, x, y;
+	RING_LOCALS;
+	DRM_DEBUG("\n");
+
+	count = depth->n;
+	if (count > 4096 || count <= 0)
+		return DRM_ERR(EMSGSIZE);
+
+	if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
+		return DRM_ERR(EFAULT);
+	}
+	if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
+		return DRM_ERR(EFAULT);
+	}
+
+	BEGIN_RING(7);
+
+	OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
+	OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
+		 R128_GMC_DST_PITCH_OFFSET_CNTL |
+		 R128_GMC_BRUSH_NONE |
+		 (dev_priv->depth_fmt << 8) |
+		 R128_GMC_SRC_DATATYPE_COLOR |
+		 R128_ROP3_S |
+		 R128_DP_SRC_SOURCE_MEMORY |
+		 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
+
+	OUT_RING(dev_priv->depth_pitch_offset_c);
+	OUT_RING(dev_priv->span_pitch_offset_c);
+
+	OUT_RING((x << 16) | y);
+	OUT_RING((0 << 16) | 0);
+	OUT_RING((count << 16) | 1);
+
+	ADVANCE_RING();
+
+	return 0;
+}
+
+static int r128_cce_dispatch_read_pixels(drm_device_t * dev,
+					 drm_r128_depth_t * depth)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	int count, *x, *y;
+	int i, xbuf_size, ybuf_size;
+	RING_LOCALS;
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	count = depth->n;
+	if (count > 4096 || count <= 0)
+		return DRM_ERR(EMSGSIZE);
+
+	if (count > dev_priv->depth_pitch) {
+		count = dev_priv->depth_pitch;
+	}
+
+	xbuf_size = count * sizeof(*x);
+	ybuf_size = count * sizeof(*y);
+	x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+	if (x == NULL) {
+		return DRM_ERR(ENOMEM);
+	}
+	y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+	if (y == NULL) {
+		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		return DRM_ERR(ENOMEM);
+	}
+	if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		return DRM_ERR(EFAULT);
+	}
+	if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
+		drm_free(x, xbuf_size, DRM_MEM_BUFS);
+		drm_free(y, ybuf_size, DRM_MEM_BUFS);
+		return DRM_ERR(EFAULT);
+	}
+
+	for (i = 0; i < count; i++) {
+		BEGIN_RING(7);
+
+		OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
+		OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
+			 R128_GMC_DST_PITCH_OFFSET_CNTL |
+			 R128_GMC_BRUSH_NONE |
+			 (dev_priv->depth_fmt << 8) |
+			 R128_GMC_SRC_DATATYPE_COLOR |
+			 R128_ROP3_S |
+			 R128_DP_SRC_SOURCE_MEMORY |
+			 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
+
+		OUT_RING(dev_priv->depth_pitch_offset_c);
+		OUT_RING(dev_priv->span_pitch_offset_c);
+
+		OUT_RING((x[i] << 16) | y[i]);
+		OUT_RING((i << 16) | 0);
+		OUT_RING((1 << 16) | 1);
+
+		ADVANCE_RING();
+	}
+
+	drm_free(x, xbuf_size, DRM_MEM_BUFS);
+	drm_free(y, ybuf_size, DRM_MEM_BUFS);
+
+	return 0;
+}
+
+/* ================================================================
+ * Polygon stipple
+ */
+
+static void r128_cce_dispatch_stipple(drm_device_t * dev, u32 * stipple)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	int i;
+	RING_LOCALS;
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	BEGIN_RING(33);
+
+	OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));
+	for (i = 0; i < 32; i++) {
+		OUT_RING(stipple[i]);
+	}
+
+	ADVANCE_RING();
+}
+
+/* ================================================================
+ * IOCTL functions
+ */
+
+static int r128_cce_clear(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_r128_clear_t clear;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(clear, (drm_r128_clear_t __user *) data,
+				 sizeof(clear));
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+	if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
+
+	r128_cce_dispatch_clear(dev, &clear);
+	COMMIT_RING();
+
+	/* Make sure we restore the 3D state next time.
+	 */
+	dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+
+	return 0;
+}
+
+static int r128_do_init_pageflip(drm_device_t * dev)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);
+	dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);
+
+	R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);
+	R128_WRITE(R128_CRTC_OFFSET_CNTL,
+		   dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);
+
+	dev_priv->page_flipping = 1;
+	dev_priv->current_page = 0;
+	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
+
+	return 0;
+}
+
+static int r128_do_cleanup_pageflip(drm_device_t * dev)
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);
+	R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);
+
+	if (dev_priv->current_page != 0) {
+		r128_cce_dispatch_flip(dev);
+		COMMIT_RING();
+	}
+
+	dev_priv->page_flipping = 0;
+	return 0;
+}
+
+/* Swapping and flipping are different operations, need different ioctls.
+ * They can & should be intermixed to support multiple 3d windows.
+ */
+
+static int r128_cce_flip(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+	if (!dev_priv->page_flipping)
+		r128_do_init_pageflip(dev);
+
+	r128_cce_dispatch_flip(dev);
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int r128_cce_swap(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+	if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
+
+	r128_cce_dispatch_swap(dev);
+	dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
+					R128_UPLOAD_MASKS);
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int r128_cce_vertex(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_r128_buf_priv_t *buf_priv;
+	drm_r128_vertex_t vertex;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(vertex, (drm_r128_vertex_t __user *) data,
+				 sizeof(vertex));
+
+	DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
+		  DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard);
+
+	if (vertex.idx < 0 || vertex.idx >= dma->buf_count) {
+		DRM_ERROR("buffer index %d (of %d max)\n",
+			  vertex.idx, dma->buf_count - 1);
+		return DRM_ERR(EINVAL);
+	}
+	if (vertex.prim < 0 ||
+	    vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
+		DRM_ERROR("buffer prim %d\n", vertex.prim);
+		return DRM_ERR(EINVAL);
+	}
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	buf = dma->buflist[vertex.idx];
+	buf_priv = buf->dev_private;
+
+	if (buf->filp != filp) {
+		DRM_ERROR("process %d using buffer owned by %p\n",
+			  DRM_CURRENTPID, buf->filp);
+		return DRM_ERR(EINVAL);
+	}
+	if (buf->pending) {
+		DRM_ERROR("sending pending buffer %d\n", vertex.idx);
+		return DRM_ERR(EINVAL);
+	}
+
+	buf->used = vertex.count;
+	buf_priv->prim = vertex.prim;
+	buf_priv->discard = vertex.discard;
+
+	r128_cce_dispatch_vertex(dev, buf);
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int r128_cce_indices(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_r128_buf_priv_t *buf_priv;
+	drm_r128_indices_t elts;
+	int count;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(elts, (drm_r128_indices_t __user *) data,
+				 sizeof(elts));
+
+	DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
+		  elts.idx, elts.start, elts.end, elts.discard);
+
+	if (elts.idx < 0 || elts.idx >= dma->buf_count) {
+		DRM_ERROR("buffer index %d (of %d max)\n",
+			  elts.idx, dma->buf_count - 1);
+		return DRM_ERR(EINVAL);
+	}
+	if (elts.prim < 0 || elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
+		DRM_ERROR("buffer prim %d\n", elts.prim);
+		return DRM_ERR(EINVAL);
+	}
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	buf = dma->buflist[elts.idx];
+	buf_priv = buf->dev_private;
+
+	if (buf->filp != filp) {
+		DRM_ERROR("process %d using buffer owned by %p\n",
+			  DRM_CURRENTPID, buf->filp);
+		return DRM_ERR(EINVAL);
+	}
+	if (buf->pending) {
+		DRM_ERROR("sending pending buffer %d\n", elts.idx);
+		return DRM_ERR(EINVAL);
+	}
+
+	count = (elts.end - elts.start) / sizeof(u16);
+	elts.start -= R128_INDEX_PRIM_OFFSET;
+
+	if (elts.start & 0x7) {
+		DRM_ERROR("misaligned buffer 0x%x\n", elts.start);
+		return DRM_ERR(EINVAL);
+	}
+	if (elts.start < buf->used) {
+		DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used);
+		return DRM_ERR(EINVAL);
+	}
+
+	buf->used = elts.end;
+	buf_priv->prim = elts.prim;
+	buf_priv->discard = elts.discard;
+
+	r128_cce_dispatch_indices(dev, buf, elts.start, elts.end, count);
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int r128_cce_blit(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_device_dma_t *dma = dev->dma;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_blit_t blit;
+	int ret;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(blit, (drm_r128_blit_t __user *) data,
+				 sizeof(blit));
+
+	DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit.idx);
+
+	if (blit.idx < 0 || blit.idx >= dma->buf_count) {
+		DRM_ERROR("buffer index %d (of %d max)\n",
+			  blit.idx, dma->buf_count - 1);
+		return DRM_ERR(EINVAL);
+	}
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	ret = r128_cce_dispatch_blit(filp, dev, &blit);
+
+	COMMIT_RING();
+	return ret;
+}
+
+static int r128_cce_depth(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_depth_t depth;
+	int ret;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(depth, (drm_r128_depth_t __user *) data,
+				 sizeof(depth));
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+	ret = DRM_ERR(EINVAL);
+	switch (depth.func) {
+	case R128_WRITE_SPAN:
+		ret = r128_cce_dispatch_write_span(dev, &depth);
+		break;
+	case R128_WRITE_PIXELS:
+		ret = r128_cce_dispatch_write_pixels(dev, &depth);
+		break;
+	case R128_READ_SPAN:
+		ret = r128_cce_dispatch_read_span(dev, &depth);
+		break;
+	case R128_READ_PIXELS:
+		ret = r128_cce_dispatch_read_pixels(dev, &depth);
+		break;
+	}
+
+	COMMIT_RING();
+	return ret;
+}
+
+static int r128_cce_stipple(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_stipple_t stipple;
+	u32 mask[32];
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(stipple, (drm_r128_stipple_t __user *) data,
+				 sizeof(stipple));
+
+	if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32)))
+		return DRM_ERR(EFAULT);
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+	r128_cce_dispatch_stipple(dev, mask);
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int r128_cce_indirect(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_r128_buf_priv_t *buf_priv;
+	drm_r128_indirect_t indirect;
+#if 0
+	RING_LOCALS;
+#endif
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(indirect, (drm_r128_indirect_t __user *) data,
+				 sizeof(indirect));
+
+	DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n",
+		  indirect.idx, indirect.start, indirect.end, indirect.discard);
+
+	if (indirect.idx < 0 || indirect.idx >= dma->buf_count) {
+		DRM_ERROR("buffer index %d (of %d max)\n",
+			  indirect.idx, dma->buf_count - 1);
+		return DRM_ERR(EINVAL);
+	}
+
+	buf = dma->buflist[indirect.idx];
+	buf_priv = buf->dev_private;
+
+	if (buf->filp != filp) {
+		DRM_ERROR("process %d using buffer owned by %p\n",
+			  DRM_CURRENTPID, buf->filp);
+		return DRM_ERR(EINVAL);
+	}
+	if (buf->pending) {
+		DRM_ERROR("sending pending buffer %d\n", indirect.idx);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (indirect.start < buf->used) {
+		DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
+			  indirect.start, buf->used);
+		return DRM_ERR(EINVAL);
+	}
+
+	RING_SPACE_TEST_WITH_RETURN(dev_priv);
+	VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+	buf->used = indirect.end;
+	buf_priv->discard = indirect.discard;
+
+#if 0
+	/* Wait for the 3D stream to idle before the indirect buffer
+	 * containing 2D acceleration commands is processed.
+	 */
+	BEGIN_RING(2);
+	RADEON_WAIT_UNTIL_3D_IDLE();
+	ADVANCE_RING();
+#endif
+
+	/* Dispatch the indirect buffer full of commands from the
+	 * X server.  This is insecure and is thus only available to
+	 * privileged clients.
+	 */
+	r128_cce_dispatch_indirect(dev, buf, indirect.start, indirect.end);
+
+	COMMIT_RING();
+	return 0;
+}
+
+static int r128_getparam(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_getparam_t param;
+	int value;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(param, (drm_r128_getparam_t __user *) data,
+				 sizeof(param));
+
+	DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+	switch (param.param) {
+	case R128_PARAM_IRQ_NR:
+		value = dev->irq;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)
+{
+	if (dev->dev_private) {
+		drm_r128_private_t *dev_priv = dev->dev_private;
+		if (dev_priv->page_flipping) {
+			r128_do_cleanup_pageflip(dev);
+		}
+	}
+}
+
+void r128_driver_lastclose(drm_device_t * dev)
+{
+	r128_do_cleanup_cce(dev);
+}
+
+drm_ioctl_desc_t r128_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, DRM_AUTH},
+};
+
+int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
--- libdrm-2.3.0.orig/shared-core/via_dma.c
+++ libdrm-2.3.0/shared-core/via_dma.c
@@ -0,0 +1,777 @@
+/* via_dma.c -- DMA support for the VIA Unichrome/Pro
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
+ * All Rights Reserved.
+ * 
+ * Copyright 2004 The Unichrome project.
+ * 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
+ * THE COPYRIGHT HOLDERS, AUTHORS 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.
+ *
+ * Authors: 
+ *    Tungsten Graphics, 
+ *    Erdi Chen, 
+ *    Thomas Hellstrom.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "via_drm.h"
+#include "via_drv.h"
+#include "via_3d_reg.h"
+
+#define CMDBUF_ALIGNMENT_SIZE   (0x100)
+#define CMDBUF_ALIGNMENT_MASK   (0x0ff)
+
+/* defines for VIA 3D registers */
+#define VIA_REG_STATUS	  0x400
+#define VIA_REG_TRANSET	 0x43C
+#define VIA_REG_TRANSPACE       0x440
+
+/* VIA_REG_STATUS(0x400): Engine Status */
+#define VIA_CMD_RGTR_BUSY       0x00000080	/* Command Regulator is busy */
+#define VIA_2D_ENG_BUSY	 0x00000001	/* 2D Engine is busy */
+#define VIA_3D_ENG_BUSY	 0x00000002	/* 3D Engine is busy */
+#define VIA_VR_QUEUE_BUSY       0x00020000	/* Virtual Queue is busy */
+
+#define SetReg2DAGP(nReg, nData) {				\
+	*((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1;	\
+	*((uint32_t *)(vb) + 1) = (nData);			\
+	vb = ((uint32_t *)vb) + 2;				\
+	dev_priv->dma_low +=8;					\
+}
+
+#define via_flush_write_combine() DRM_MEMORYBARRIER() 
+
+#define VIA_OUT_RING_QW(w1,w2)			\
+	*vb++ = (w1);				\
+	*vb++ = (w2);				\
+	dev_priv->dma_low += 8; 
+
+static void via_cmdbuf_start(drm_via_private_t * dev_priv);
+static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
+static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
+static void via_cmdbuf_rewind(drm_via_private_t * dev_priv);
+static int via_wait_idle(drm_via_private_t * dev_priv);
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords);
+
+
+/*
+ * Free space in command buffer.
+ */
+
+static uint32_t via_cmdbuf_space(drm_via_private_t *dev_priv)
+{
+	uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+	uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+	
+	return ((hw_addr <= dev_priv->dma_low) ? 
+		(dev_priv->dma_high + hw_addr - dev_priv->dma_low) : 
+		(hw_addr - dev_priv->dma_low));
+}
+
+/*
+ * How much does the command regulator lag behind?
+ */
+
+static uint32_t via_cmdbuf_lag(drm_via_private_t *dev_priv)
+{
+	uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+	uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+	
+	return ((hw_addr <= dev_priv->dma_low) ? 
+		(dev_priv->dma_low - hw_addr) : 
+		(dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
+}
+
+/*
+ * Check that the given size fits in the buffer, otherwise wait.
+ */
+
+static inline int
+via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
+{
+	uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+	uint32_t cur_addr, hw_addr, next_addr;
+	volatile uint32_t *hw_addr_ptr;
+	uint32_t count;
+	hw_addr_ptr = dev_priv->hw_addr_ptr;
+	cur_addr = dev_priv->dma_low;
+	next_addr = cur_addr + size + 512*1024;
+	count = 1000000;
+	do {
+		hw_addr = *hw_addr_ptr - agp_base;
+		if (count-- == 0) {
+			DRM_ERROR
+			    ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
+			    hw_addr, cur_addr, next_addr);
+			return -1;
+		}
+	} while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
+	return 0;
+}
+
+
+/*
+ * Checks whether buffer head has reach the end. Rewind the ring buffer
+ * when necessary.
+ *
+ * Returns virtual pointer to ring buffer.
+ */
+
+static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
+				      unsigned int size)
+{
+	if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) >
+	    dev_priv->dma_high) {
+		via_cmdbuf_rewind(dev_priv);
+	}
+	if (via_cmdbuf_wait(dev_priv, size) != 0) {
+		return NULL;
+	}
+
+	return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
+}
+
+int via_dma_cleanup(drm_device_t * dev)
+{
+	if (dev->dev_private) {
+		drm_via_private_t *dev_priv =
+			(drm_via_private_t *) dev->dev_private;
+
+		if (dev_priv->ring.virtual_start) {
+			via_cmdbuf_reset(dev_priv);
+
+			drm_core_ioremapfree(&dev_priv->ring.map, dev);
+			dev_priv->ring.virtual_start = NULL;
+		}
+
+	}
+
+	return 0;
+}
+
+static int via_initialize(drm_device_t * dev,
+			  drm_via_private_t * dev_priv,
+			  drm_via_dma_init_t * init)
+{
+	if (!dev_priv || !dev_priv->mmio) {
+		DRM_ERROR("via_dma_init called before via_map_init\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	if (dev_priv->ring.virtual_start != NULL) {
+		DRM_ERROR("%s called again without calling cleanup\n",
+			  __FUNCTION__);
+		return DRM_ERR(EFAULT);
+	}
+
+	if (!dev->agp || !dev->agp->base) {
+		DRM_ERROR("%s called with no agp memory available\n", 
+			  __FUNCTION__);
+		return DRM_ERR(EFAULT);
+	}
+
+	dev_priv->ring.map.offset = dev->agp->base + init->offset;
+	dev_priv->ring.map.size = init->size;
+	dev_priv->ring.map.type = 0;
+	dev_priv->ring.map.flags = 0;
+	dev_priv->ring.map.mtrr = 0;
+
+	drm_core_ioremap(&dev_priv->ring.map, dev);
+
+	if (dev_priv->ring.map.handle == NULL) {
+		via_dma_cleanup(dev);
+		DRM_ERROR("can not ioremap virtual address for"
+			  " ring buffer\n");
+		return DRM_ERR(ENOMEM);
+	}
+
+	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+	dev_priv->dma_ptr = dev_priv->ring.virtual_start;
+	dev_priv->dma_low = 0;
+	dev_priv->dma_high = init->size;
+	dev_priv->dma_wrap = init->size;
+	dev_priv->dma_offset = init->offset;
+	dev_priv->last_pause_ptr = NULL;
+	dev_priv->hw_addr_ptr =
+	    (volatile uint32_t *)((char *)dev_priv->mmio->handle +
+	    init->reg_pause_addr);
+
+	via_cmdbuf_start(dev_priv);
+
+	return 0;
+}
+
+static int via_dma_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	drm_via_dma_init_t init;
+	int retcode = 0;
+
+	DRM_COPY_FROM_USER_IOCTL(init, (drm_via_dma_init_t __user *) data,
+				 sizeof(init));
+
+	switch (init.func) {
+	case VIA_INIT_DMA:
+		if (!DRM_SUSER(DRM_CURPROC))
+			retcode = DRM_ERR(EPERM);
+		else
+			retcode = via_initialize(dev, dev_priv, &init);
+		break;
+	case VIA_CLEANUP_DMA:
+		if (!DRM_SUSER(DRM_CURPROC))
+			retcode = DRM_ERR(EPERM);
+		else
+			retcode = via_dma_cleanup(dev);
+		break;
+	case VIA_DMA_INITIALIZED:
+		retcode = (dev_priv->ring.virtual_start != NULL) ? 
+			0: DRM_ERR( EFAULT );
+		break;
+	default:
+		retcode = DRM_ERR(EINVAL);
+		break;
+	}
+
+	return retcode;
+}
+
+
+
+static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
+{
+	drm_via_private_t *dev_priv;
+	uint32_t *vb;
+	int ret;
+
+	dev_priv = (drm_via_private_t *) dev->dev_private;
+
+	if (dev_priv->ring.virtual_start == NULL) {
+		DRM_ERROR("%s called without initializing AGP ring buffer.\n",
+			  __FUNCTION__);
+		return DRM_ERR(EFAULT);
+	}
+
+	if (cmd->size > VIA_PCI_BUF_SIZE) {
+		return DRM_ERR(ENOMEM);
+	} 
+
+
+	if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+		return DRM_ERR(EFAULT);
+
+	/*
+	 * Running this function on AGP memory is dead slow. Therefore
+	 * we run it on a temporary cacheable system memory buffer and
+	 * copy it to AGP memory when ready.
+	 */
+
+	if ((ret =
+	     via_verify_command_stream((uint32_t *)dev_priv->pci_buf,
+				       cmd->size, dev, 1))) {
+		return ret;
+	}
+       	
+	vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
+	if (vb == NULL) {
+		return DRM_ERR(EAGAIN);
+	}
+
+	memcpy(vb, dev_priv->pci_buf, cmd->size);
+	
+	dev_priv->dma_low += cmd->size;
+
+	/*
+	 * Small submissions somehow stalls the CPU. (AGP cache effects?)
+	 * pad to greater size.
+	 */
+
+	if (cmd->size < 0x100)
+	  via_pad_cache(dev_priv,(0x100 - cmd->size) >> 3);
+	via_cmdbuf_pause(dev_priv);
+
+	return 0;
+}
+
+int via_driver_dma_quiescent(drm_device_t * dev)
+{
+	drm_via_private_t *dev_priv = dev->dev_private;
+
+	if (!via_wait_idle(dev_priv)) {
+		return DRM_ERR(EBUSY);
+	}
+	return 0;
+}
+
+static int via_flush_ioctl(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+
+	LOCK_TEST_WITH_RETURN( dev, filp );
+
+	return via_driver_dma_quiescent(dev);
+}
+
+static int via_cmdbuffer(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_via_cmdbuffer_t cmdbuf;
+	int ret;
+
+	LOCK_TEST_WITH_RETURN( dev, filp );
+
+	DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
+				 sizeof(cmdbuf));
+
+	DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf.buf, cmdbuf.size);
+
+	ret = via_dispatch_cmdbuffer(dev, &cmdbuf);
+	if (ret) {
+		return ret;
+	}
+
+	return 0;
+}
+
+static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
+				      drm_via_cmdbuffer_t * cmd)
+{
+	drm_via_private_t *dev_priv = dev->dev_private;
+	int ret;
+
+	if (cmd->size > VIA_PCI_BUF_SIZE) {
+		return DRM_ERR(ENOMEM);
+	} 
+	if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+		return DRM_ERR(EFAULT);
+	
+	if ((ret = 
+	     via_verify_command_stream((uint32_t *)dev_priv->pci_buf,
+				       cmd->size, dev, 0))) {
+		return ret;
+	}
+	
+	ret =
+	    via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf,
+				     cmd->size);
+	return ret;
+}
+
+static int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_via_cmdbuffer_t cmdbuf;
+	int ret;
+
+	LOCK_TEST_WITH_RETURN( dev, filp );
+
+	DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
+				 sizeof(cmdbuf));
+
+	DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf.buf,
+		  cmdbuf.size);
+
+	ret = via_dispatch_pci_cmdbuffer(dev, &cmdbuf);
+	if (ret) {
+		return ret;
+	}
+
+	return 0;
+}
+
+
+static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
+					 uint32_t * vb, int qw_count)
+{
+	for (; qw_count > 0; --qw_count) {
+		VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
+	}
+	return vb;
+}
+
+
+/*
+ * This function is used internally by ring buffer mangement code.
+ *
+ * Returns virtual pointer to ring buffer.
+ */
+static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv)
+{
+	return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
+}
+
+/*
+ * Hooks a segment of data into the tail of the ring-buffer by
+ * modifying the pause address stored in the buffer itself. If
+ * the regulator has already paused, restart it.
+ */
+static int via_hook_segment(drm_via_private_t *dev_priv,
+			    uint32_t pause_addr_hi, uint32_t pause_addr_lo,
+			    int no_pci_fire)
+{
+	int paused, count;
+	volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
+
+	via_flush_write_combine();
+	while(! *(via_get_dma(dev_priv)-1));
+	*dev_priv->last_pause_ptr = pause_addr_lo;
+	via_flush_write_combine();
+
+	/*
+	 * The below statement is inserted to really force the flush.
+	 * Not sure it is needed.
+	 */
+
+	while(! *dev_priv->last_pause_ptr);
+	dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
+	while(! *dev_priv->last_pause_ptr);
+
+
+	paused = 0;
+	count = 20; 
+
+	while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
+	if ((count <= 8) && (count >= 0)) {
+		uint32_t rgtr, ptr;
+		rgtr = *(dev_priv->hw_addr_ptr);
+		ptr = ((volatile char *)dev_priv->last_pause_ptr -
+		      dev_priv->dma_ptr) + dev_priv->dma_offset +
+		      (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE;
+		if (rgtr <= ptr) {
+			DRM_ERROR
+			   ("Command regulator\npaused at count %d, address %x, "
+			    "while current pause address is %x.\n"
+			    "Please mail this message to "
+			    "<unichrome-devel@lists.sourceforge.net>\n", count,
+			    rgtr, ptr);
+		}
+	}
+		
+	if (paused && !no_pci_fire) {
+		uint32_t rgtr,ptr;
+		uint32_t ptr_low;
+
+		count = 1000000;
+		while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY)
+		       && count--);
+		
+		rgtr = *(dev_priv->hw_addr_ptr);
+		ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + 
+			dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+		
+
+		ptr_low = (ptr > 3*CMDBUF_ALIGNMENT_SIZE) ? 
+			ptr - 3*CMDBUF_ALIGNMENT_SIZE : 0;
+		if (rgtr <= ptr && rgtr >= ptr_low) {
+			VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+			VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
+			VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
+		} 
+	}
+	return paused;
+}
+
+
+
+static int via_wait_idle(drm_via_private_t * dev_priv)
+{
+	int count = 10000000;
+	while (count-- && (VIA_READ(VIA_REG_STATUS) &
+			   (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
+			    VIA_3D_ENG_BUSY))) ;
+	return count;
+}
+
+static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
+			       uint32_t addr, uint32_t *cmd_addr_hi, 
+			       uint32_t *cmd_addr_lo, int skip_wait)
+{
+	uint32_t agp_base;
+	uint32_t cmd_addr, addr_lo, addr_hi;
+	uint32_t *vb;
+	uint32_t qw_pad_count;
+
+	if (!skip_wait)
+		via_cmdbuf_wait(dev_priv, 2*CMDBUF_ALIGNMENT_SIZE);
+
+	vb = via_get_dma(dev_priv);
+	VIA_OUT_RING_QW( HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
+			 (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16); 
+	agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+	qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
+		((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
+
+	cmd_addr = (addr) ? addr : 
+		agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
+	addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) |
+		   (cmd_addr & HC_HAGPBpL_MASK));
+	addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24));
+
+	vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
+	VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo);
+	return vb;
+}
+
+
+
+
+static void via_cmdbuf_start(drm_via_private_t * dev_priv)
+{
+	uint32_t pause_addr_lo, pause_addr_hi;
+	uint32_t start_addr, start_addr_lo;
+	uint32_t end_addr, end_addr_lo;
+	uint32_t command;
+	uint32_t agp_base;
+
+
+	dev_priv->dma_low = 0;
+
+	agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+	start_addr = agp_base;
+	end_addr = agp_base + dev_priv->dma_high;
+
+	start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF));
+	end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
+	command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
+		   ((end_addr & 0xff000000) >> 16));
+
+	dev_priv->last_pause_ptr = 
+		via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, 
+			      &pause_addr_hi, & pause_addr_lo, 1) - 1;
+
+	via_flush_write_combine();
+	while(! *dev_priv->last_pause_ptr);
+
+	VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+	VIA_WRITE(VIA_REG_TRANSPACE, command);
+	VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo);
+	VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo);
+
+	VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
+	VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
+
+	VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
+}
+
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
+{
+	uint32_t *vb;
+
+	via_cmdbuf_wait(dev_priv, qwords + 2);
+	vb = via_get_dma(dev_priv);
+	VIA_OUT_RING_QW( HC_HEADER2, HC_ParaType_NotTex << 16);
+	via_align_buffer(dev_priv,vb,qwords);
+}
+
+static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
+{
+	uint32_t *vb = via_get_dma(dev_priv);
+	SetReg2DAGP(0x0C, (0 | (0 << 16)));
+	SetReg2DAGP(0x10, 0 | (0 << 16));
+	SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000); 
+}
+
+
+static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
+{
+	uint32_t agp_base;
+	uint32_t pause_addr_lo, pause_addr_hi;
+	uint32_t jump_addr_lo, jump_addr_hi;
+	volatile uint32_t *last_pause_ptr;
+	uint32_t dma_low_save1, dma_low_save2;
+
+	agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+	via_align_cmd(dev_priv,  HC_HAGPBpID_JUMP, 0, &jump_addr_hi, 
+		      &jump_addr_lo, 0);
+	
+	dev_priv->dma_wrap = dev_priv->dma_low;
+
+
+	/*
+	 * Wrap command buffer to the beginning.
+	 */
+
+	dev_priv->dma_low = 0;
+	if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) {
+		DRM_ERROR("via_cmdbuf_jump failed\n");
+	}
+
+	via_dummy_bitblt(dev_priv);
+	via_dummy_bitblt(dev_priv); 
+
+	last_pause_ptr =
+	    via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 
+				       &pause_addr_lo, 0) -1;
+	via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 
+		      &pause_addr_lo, 0);
+
+	*last_pause_ptr = pause_addr_lo;
+	dma_low_save1 = dev_priv->dma_low;
+
+	/*
+	 * Now, set a trap that will pause the regulator if it tries to rerun the old
+	 * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
+	 * and reissues the jump command over PCI, while the regulator has already taken the jump
+	 * and actually paused at the current buffer end).
+	 * There appears to be no other way to detect this condition, since the hw_addr_pointer
+	 * does not seem to get updated immediately when a jump occurs.
+	 */
+
+	last_pause_ptr =
+	    via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 
+				       &pause_addr_lo, 0) -1;
+	via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 
+		      &pause_addr_lo, 0);
+	*last_pause_ptr = pause_addr_lo;
+
+	dma_low_save2 = dev_priv->dma_low;
+	dev_priv->dma_low = dma_low_save1;	
+	via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
+	dev_priv->dma_low = dma_low_save2;
+	via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
+}
+
+
+static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
+{
+	via_cmdbuf_jump(dev_priv); 
+}
+
+static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
+{
+	uint32_t pause_addr_lo, pause_addr_hi;
+
+	via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
+	via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
+}
+
+
+static void via_cmdbuf_pause(drm_via_private_t * dev_priv)
+{
+	via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE);
+}
+
+static void via_cmdbuf_reset(drm_via_private_t * dev_priv)
+{
+	via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP);
+	via_wait_idle(dev_priv);
+}
+
+/*
+ * User interface to the space and lag functions.
+ */
+
+static int via_cmdbuf_size(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_via_cmdbuf_size_t d_siz;
+	int ret = 0;
+	uint32_t tmp_size, count;
+	drm_via_private_t *dev_priv;
+
+	DRM_DEBUG("via cmdbuf_size\n");
+	LOCK_TEST_WITH_RETURN( dev, filp );
+
+	dev_priv = (drm_via_private_t *) dev->dev_private;
+
+	if (dev_priv->ring.virtual_start == NULL) {
+		DRM_ERROR("%s called without initializing AGP ring buffer.\n",
+			  __FUNCTION__);
+		return DRM_ERR(EFAULT);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t __user *) data,
+				 sizeof(d_siz));
+
+
+	count = 1000000;
+	tmp_size = d_siz.size;
+	switch(d_siz.func) {
+	case VIA_CMDBUF_SPACE:
+		while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz.size)
+		       && count--) {
+			if (!d_siz.wait) {
+				break;
+			}
+		}
+		if (!count) {
+			DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n");
+			ret = DRM_ERR(EAGAIN);
+		}
+		break;
+	case VIA_CMDBUF_LAG:
+		while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz.size)
+		       && count--) {
+			if (!d_siz.wait) {
+				break;
+			}
+		}
+		if (!count) {
+			DRM_ERROR("VIA_CMDBUF_LAG timed out.\n");
+			ret = DRM_ERR(EAGAIN);
+		}
+		break;
+	default:
+		ret = DRM_ERR(EFAULT);
+	}
+	d_siz.size = tmp_size;
+
+	DRM_COPY_TO_USER_IOCTL((drm_via_cmdbuf_size_t __user *) data, d_siz,
+			       sizeof(d_siz));
+	return ret;
+}
+
+#ifndef VIA_HAVE_DMABLIT
+int 
+via_dma_blit_sync( DRM_IOCTL_ARGS ) {
+	DRM_ERROR("PCI DMA BitBlt is not implemented for this system.\n");
+	return DRM_ERR(EINVAL);
+}
+int 
+via_dma_blit( DRM_IOCTL_ARGS ) {
+	DRM_ERROR("PCI DMA BitBlt is not implemented for this system.\n");
+	return DRM_ERR(EINVAL);
+}
+#endif
+
+drm_ioctl_desc_t via_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, DRM_AUTH|DRM_MASTER},
+	[DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, DRM_AUTH|DRM_MASTER},
+	[DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, DRM_AUTH|DRM_MASTER},
+	[DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_DMA_BLIT)] = {via_dma_blit, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_VIA_BLIT_SYNC)] = {via_dma_blit_sync, DRM_AUTH}
+};
+
+int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);
--- libdrm-2.3.0.orig/shared-core/via_mm.h
+++ libdrm-2.3.0/shared-core/via_mm.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. 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
+ * VIA, S3 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 _via_drm_mm_h_
+#define _via_drm_mm_h_
+
+typedef struct {
+	unsigned int context;
+	unsigned int size;
+	unsigned long offset;
+	unsigned long free;
+} drm_via_mm_t;
+
+typedef struct {
+	unsigned int size;
+	unsigned long handle;
+	void *virtual;
+} drm_via_dma_t;
+
+#endif
--- libdrm-2.3.0.orig/shared-core/sis_mm.c
+++ libdrm-2.3.0/shared-core/sis_mm.c
@@ -0,0 +1,418 @@
+/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Sung-Ching Lin <sclin@sis.com.tw>
+ *
+ */
+
+#if defined(__linux__) && defined(CONFIG_FB_SIS)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#include <video/sisfb.h>
+#else
+#include <linux/sisfb.h>
+#endif
+#endif
+#include "drmP.h"
+#include "sis_drm.h"
+#include "sis_drv.h"
+#include "sis_ds.h"
+
+#define MAX_CONTEXT 100
+#define VIDEO_TYPE 0
+#define AGP_TYPE 1
+
+typedef struct {
+	int used;
+	int context;
+	set_t *sets[2];		/* 0 for video, 1 for AGP */
+} sis_context_t;
+
+static sis_context_t global_ppriv[MAX_CONTEXT];
+
+static int add_alloc_set(int context, int type, unsigned int val)
+{
+	int i, retval = 0;
+
+	for (i = 0; i < MAX_CONTEXT; i++) {
+		if (global_ppriv[i].used && global_ppriv[i].context == context) {
+			retval = setAdd(global_ppriv[i].sets[type], val);
+			break;
+		}
+	}
+	return retval;
+}
+
+static int del_alloc_set(int context, int type, unsigned int val)
+{
+	int i, retval = 0;
+
+	for (i = 0; i < MAX_CONTEXT; i++) {
+		if (global_ppriv[i].used && global_ppriv[i].context == context) {
+			retval = setDel(global_ppriv[i].sets[type], val);
+			break;
+		}
+	}
+	return retval;
+}
+
+/* fb management via fb device */
+#if defined(__linux__) && defined(CONFIG_FB_SIS)
+
+static int sis_fb_init(DRM_IOCTL_ARGS)
+{
+	return 0;
+}
+
+static int sis_fb_alloc(DRM_IOCTL_ARGS)
+{
+	drm_sis_mem_t fb;
+	struct sis_memreq req;
+	drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
+	int retval = 0;
+
+	DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
+
+	req.size = fb.size;
+	sis_malloc(&req);
+	if (req.offset) {
+		/* TODO */
+		fb.offset = req.offset;
+		fb.free = req.offset;
+		if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
+			DRM_DEBUG("adding to allocation set fails\n");
+			sis_free(req.offset);
+			retval = DRM_ERR(EINVAL);
+		}
+	} else {
+		fb.offset = 0;
+		fb.size = 0;
+		fb.free = 0;
+	}
+
+	DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
+
+	DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
+
+	return retval;
+}
+
+static int sis_fb_free(DRM_IOCTL_ARGS)
+{
+	drm_sis_mem_t fb;
+	int retval = 0;
+
+	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
+
+	if (!fb.free)
+		return DRM_ERR(EINVAL);
+
+	if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
+		retval = DRM_ERR(EINVAL);
+	sis_free(fb.free);
+
+	DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
+
+	return retval;
+}
+
+#else
+
+/* Called by the X Server to initialize the FB heap.  Allocations will fail
+ * unless this is called.  Offset is the beginning of the heap from the
+ * framebuffer offset (MaxXFBMem in XFree86).
+ *
+ * Memory layout according to Thomas Winischofer:
+ * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
+ *
+ *    X driver/sisfb                                  HW-   Command-
+ *  framebuffer memory           DRI heap           Cursor   queue
+ */
+static int sis_fb_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_sis_private_t *dev_priv = dev->dev_private;
+	drm_sis_fb_t fb;
+
+	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
+
+	if (dev_priv == NULL) {
+		dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
+					      DRM_MEM_DRIVER);
+		dev_priv = dev->dev_private;
+		if (dev_priv == NULL)
+			return ENOMEM;
+	}
+
+	if (dev_priv->FBHeap != NULL)
+		return DRM_ERR(EINVAL);
+
+	dev_priv->FBHeap = mmInit(fb.offset, fb.size);
+
+	DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
+
+	return 0;
+}
+
+static int sis_fb_alloc(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_sis_private_t *dev_priv = dev->dev_private;
+	drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
+	drm_sis_mem_t fb;
+	PMemBlock block;
+	int retval = 0;
+
+	if (dev_priv == NULL || dev_priv->FBHeap == NULL)
+		return DRM_ERR(EINVAL);
+
+	DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
+
+	block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
+	if (block) {
+		/* TODO */
+		fb.offset = block->ofs;
+		fb.free = (unsigned long)block;
+		if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
+			DRM_DEBUG("adding to allocation set fails\n");
+			mmFreeMem((PMemBlock) fb.free);
+			retval = DRM_ERR(EINVAL);
+		}
+	} else {
+		fb.offset = 0;
+		fb.size = 0;
+		fb.free = 0;
+	}
+
+	DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
+
+	DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
+
+	return retval;
+}
+
+static int sis_fb_free(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_sis_private_t *dev_priv = dev->dev_private;
+	drm_sis_mem_t fb;
+
+	if (dev_priv == NULL || dev_priv->FBHeap == NULL)
+		return DRM_ERR(EINVAL);
+
+	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
+
+	if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free))
+		return DRM_ERR(EINVAL);
+
+	if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
+		return DRM_ERR(EINVAL);
+	mmFreeMem((PMemBlock) fb.free);
+
+	DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
+
+	return 0;
+}
+
+#endif
+
+/* agp memory management */
+
+static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_sis_private_t *dev_priv = dev->dev_private;
+	drm_sis_agp_t agp;
+
+	if (dev_priv == NULL) {
+		dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
+					      DRM_MEM_DRIVER);
+		dev_priv = dev->dev_private;
+		if (dev_priv == NULL)
+			return ENOMEM;
+	}
+
+	if (dev_priv->AGPHeap != NULL)
+		return DRM_ERR(EINVAL);
+
+	DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
+				 sizeof(agp));
+
+	dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
+
+	DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
+
+	return 0;
+}
+
+static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_sis_private_t *dev_priv = dev->dev_private;
+	drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
+	drm_sis_mem_t agp;
+	PMemBlock block;
+	int retval = 0;
+
+	if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
+		return DRM_ERR(EINVAL);
+
+	DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp));
+
+	block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
+	if (block) {
+		/* TODO */
+		agp.offset = block->ofs;
+		agp.free = (unsigned long)block;
+		if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
+			DRM_DEBUG("adding to allocation set fails\n");
+			mmFreeMem((PMemBlock) agp.free);
+			retval = -1;
+		}
+	} else {
+		agp.offset = 0;
+		agp.size = 0;
+		agp.free = 0;
+	}
+
+	DRM_COPY_TO_USER_IOCTL(argp, agp, sizeof(agp));
+
+	DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
+
+	return retval;
+}
+
+static int sis_ioctl_agp_free(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_sis_private_t *dev_priv = dev->dev_private;
+	drm_sis_mem_t agp;
+
+	if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
+		return DRM_ERR(EINVAL);
+
+	DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data,
+				 sizeof(agp));
+
+	if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free))
+		return DRM_ERR(EINVAL);
+
+	mmFreeMem((PMemBlock) agp.free);
+	if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
+		return DRM_ERR(EINVAL);
+
+	DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
+
+	return 0;
+}
+
+int sis_init_context(struct drm_device *dev, int context)
+{
+	int i;
+
+	for (i = 0; i < MAX_CONTEXT; i++) {
+		if (global_ppriv[i].used &&
+		    (global_ppriv[i].context == context))
+			break;
+	}
+
+	if (i >= MAX_CONTEXT) {
+		for (i = 0; i < MAX_CONTEXT; i++) {
+			if (!global_ppriv[i].used) {
+				global_ppriv[i].context = context;
+				global_ppriv[i].used = 1;
+				global_ppriv[i].sets[0] = setInit();
+				global_ppriv[i].sets[1] = setInit();
+				DRM_DEBUG("init allocation set, socket=%d, "
+					  "context = %d\n", i, context);
+				break;
+			}
+		}
+		if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
+		    (global_ppriv[i].sets[1] == NULL)) {
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+int sis_final_context(struct drm_device *dev, int context)
+{
+	int i;
+
+	for (i = 0; i < MAX_CONTEXT; i++) {
+		if (global_ppriv[i].used &&
+		    (global_ppriv[i].context == context))
+			break;
+	}
+
+	if (i < MAX_CONTEXT) {
+		set_t *set;
+		ITEM_TYPE item;
+		int retval;
+
+		DRM_DEBUG("find socket %d, context = %d\n", i, context);
+
+		/* Video Memory */
+		set = global_ppriv[i].sets[0];
+		retval = setFirst(set, &item);
+		while (retval) {
+			DRM_DEBUG("free video memory 0x%lx\n", item);
+#if defined(__linux__) && defined(CONFIG_FB_SIS)
+			sis_free(item);
+#else
+			mmFreeMem((PMemBlock) item);
+#endif
+			retval = setNext(set, &item);
+		}
+		setDestroy(set);
+
+		/* AGP Memory */
+		set = global_ppriv[i].sets[1];
+		retval = setFirst(set, &item);
+		while (retval) {
+			DRM_DEBUG("free agp memory 0x%lx\n", item);
+			mmFreeMem((PMemBlock) item);
+			retval = setNext(set, &item);
+		}
+		setDestroy(set);
+
+		global_ppriv[i].used = 0;
+	}
+
+	return 1;
+}
+
+drm_ioctl_desc_t sis_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}
+};
+
+int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
--- libdrm-2.3.0.orig/shared-core/radeon_cp.c
+++ libdrm-2.3.0/shared-core/radeon_cp.c
@@ -0,0 +1,2257 @@
+/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
+/*
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+#include "r300_reg.h"
+
+#define RADEON_FIFO_DEBUG	0
+
+static int radeon_do_cleanup_cp(drm_device_t * dev);
+
+/* CP microcode (from ATI) */
+static const u32 R200_cp_microcode[][2] = {
+	{0x21007000, 0000000000},
+	{0x20007000, 0000000000},
+	{0x000000ab, 0x00000004},
+	{0x000000af, 0x00000004},
+	{0x66544a49, 0000000000},
+	{0x49494174, 0000000000},
+	{0x54517d83, 0000000000},
+	{0x498d8b64, 0000000000},
+	{0x49494949, 0000000000},
+	{0x49da493c, 0000000000},
+	{0x49989898, 0000000000},
+	{0xd34949d5, 0000000000},
+	{0x9dc90e11, 0000000000},
+	{0xce9b9b9b, 0000000000},
+	{0x000f0000, 0x00000016},
+	{0x352e232c, 0000000000},
+	{0x00000013, 0x00000004},
+	{0x000f0000, 0x00000016},
+	{0x352e272c, 0000000000},
+	{0x000f0001, 0x00000016},
+	{0x3239362f, 0000000000},
+	{0x000077ef, 0x00000002},
+	{0x00061000, 0x00000002},
+	{0x00000020, 0x0000001a},
+	{0x00004000, 0x0000001e},
+	{0x00061000, 0x00000002},
+	{0x00000020, 0x0000001a},
+	{0x00004000, 0x0000001e},
+	{0x00061000, 0x00000002},
+	{0x00000020, 0x0000001a},
+	{0x00004000, 0x0000001e},
+	{0x00000016, 0x00000004},
+	{0x0003802a, 0x00000002},
+	{0x040067e0, 0x00000002},
+	{0x00000016, 0x00000004},
+	{0x000077e0, 0x00000002},
+	{0x00065000, 0x00000002},
+	{0x000037e1, 0x00000002},
+	{0x040067e1, 0x00000006},
+	{0x000077e0, 0x00000002},
+	{0x000077e1, 0x00000002},
+	{0x000077e1, 0x00000006},
+	{0xffffffff, 0000000000},
+	{0x10000000, 0000000000},
+	{0x0003802a, 0x00000002},
+	{0x040067e0, 0x00000006},
+	{0x00007675, 0x00000002},
+	{0x00007676, 0x00000002},
+	{0x00007677, 0x00000002},
+	{0x00007678, 0x00000006},
+	{0x0003802b, 0x00000002},
+	{0x04002676, 0x00000002},
+	{0x00007677, 0x00000002},
+	{0x00007678, 0x00000006},
+	{0x0000002e, 0x00000018},
+	{0x0000002e, 0x00000018},
+	{0000000000, 0x00000006},
+	{0x0000002f, 0x00000018},
+	{0x0000002f, 0x00000018},
+	{0000000000, 0x00000006},
+	{0x01605000, 0x00000002},
+	{0x00065000, 0x00000002},
+	{0x00098000, 0x00000002},
+	{0x00061000, 0x00000002},
+	{0x64c0603d, 0x00000004},
+	{0x00080000, 0x00000016},
+	{0000000000, 0000000000},
+	{0x0400251d, 0x00000002},
+	{0x00007580, 0x00000002},
+	{0x00067581, 0x00000002},
+	{0x04002580, 0x00000002},
+	{0x00067581, 0x00000002},
+	{0x00000046, 0x00000004},
+	{0x00005000, 0000000000},
+	{0x00061000, 0x00000002},
+	{0x0000750e, 0x00000002},
+	{0x00019000, 0x00000002},
+	{0x00011055, 0x00000014},
+	{0x00000055, 0x00000012},
+	{0x0400250f, 0x00000002},
+	{0x0000504a, 0x00000004},
+	{0x00007565, 0x00000002},
+	{0x00007566, 0x00000002},
+	{0x00000051, 0x00000004},
+	{0x01e655b4, 0x00000002},
+	{0x4401b0dc, 0x00000002},
+	{0x01c110dc, 0x00000002},
+	{0x2666705d, 0x00000018},
+	{0x040c2565, 0x00000002},
+	{0x0000005d, 0x00000018},
+	{0x04002564, 0x00000002},
+	{0x00007566, 0x00000002},
+	{0x00000054, 0x00000004},
+	{0x00401060, 0x00000008},
+	{0x00101000, 0x00000002},
+	{0x000d80ff, 0x00000002},
+	{0x00800063, 0x00000008},
+	{0x000f9000, 0x00000002},
+	{0x000e00ff, 0x00000002},
+	{0000000000, 0x00000006},
+	{0x00000080, 0x00000018},
+	{0x00000054, 0x00000004},
+	{0x00007576, 0x00000002},
+	{0x00065000, 0x00000002},
+	{0x00009000, 0x00000002},
+	{0x00041000, 0x00000002},
+	{0x0c00350e, 0x00000002},
+	{0x00049000, 0x00000002},
+	{0x00051000, 0x00000002},
+	{0x01e785f8, 0x00000002},
+	{0x00200000, 0x00000002},
+	{0x00600073, 0x0000000c},
+	{0x00007563, 0x00000002},
+	{0x006075f0, 0x00000021},
+	{0x20007068, 0x00000004},
+	{0x00005068, 0x00000004},
+	{0x00007576, 0x00000002},
+	{0x00007577, 0x00000002},
+	{0x0000750e, 0x00000002},
+	{0x0000750f, 0x00000002},
+	{0x00a05000, 0x00000002},
+	{0x00600076, 0x0000000c},
+	{0x006075f0, 0x00000021},
+	{0x000075f8, 0x00000002},
+	{0x00000076, 0x00000004},
+	{0x000a750e, 0x00000002},
+	{0x0020750f, 0x00000002},
+	{0x00600079, 0x00000004},
+	{0x00007570, 0x00000002},
+	{0x00007571, 0x00000002},
+	{0x00007572, 0x00000006},
+	{0x00005000, 0x00000002},
+	{0x00a05000, 0x00000002},
+	{0x00007568, 0x00000002},
+	{0x00061000, 0x00000002},
+	{0x00000084, 0x0000000c},
+	{0x00058000, 0x00000002},
+	{0x0c607562, 0x00000002},
+	{0x00000086, 0x00000004},
+	{0x00600085, 0x00000004},
+	{0x400070dd, 0000000000},
+	{0x000380dd, 0x00000002},
+	{0x00000093, 0x0000001c},
+	{0x00065095, 0x00000018},
+	{0x040025bb, 0x00000002},
+	{0x00061096, 0x00000018},
+	{0x040075bc, 0000000000},
+	{0x000075bb, 0x00000002},
+	{0x000075bc, 0000000000},
+	{0x00090000, 0x00000006},
+	{0x00090000, 0x00000002},
+	{0x000d8002, 0x00000006},
+	{0x00005000, 0x00000002},
+	{0x00007821, 0x00000002},
+	{0x00007800, 0000000000},
+	{0x00007821, 0x00000002},
+	{0x00007800, 0000000000},
+	{0x01665000, 0x00000002},
+	{0x000a0000, 0x00000002},
+	{0x000671cc, 0x00000002},
+	{0x0286f1cd, 0x00000002},
+	{0x000000a3, 0x00000010},
+	{0x21007000, 0000000000},
+	{0x000000aa, 0x0000001c},
+	{0x00065000, 0x00000002},
+	{0x000a0000, 0x00000002},
+	{0x00061000, 0x00000002},
+	{0x000b0000, 0x00000002},
+	{0x38067000, 0x00000002},
+	{0x000a00a6, 0x00000004},
+	{0x20007000, 0000000000},
+	{0x01200000, 0x00000002},
+	{0x20077000, 0x00000002},
+	{0x01200000, 0x00000002},
+	{0x20007000, 0000000000},
+	{0x00061000, 0x00000002},
+	{0x0120751b, 0x00000002},
+	{0x8040750a, 0x00000002},
+	{0x8040750b, 0x00000002},
+	{0x00110000, 0x00000002},
+	{0x000380dd, 0x00000002},
+	{0x000000bd, 0x0000001c},
+	{0x00061096, 0x00000018},
+	{0x844075bd, 0x00000002},
+	{0x00061095, 0x00000018},
+	{0x840075bb, 0x00000002},
+	{0x00061096, 0x00000018},
+	{0x844075bc, 0x00000002},
+	{0x000000c0, 0x00000004},
+	{0x804075bd, 0x00000002},
+	{0x800075bb, 0x00000002},
+	{0x804075bc, 0x00000002},
+	{0x00108000, 0x00000002},
+	{0x01400000, 0x00000002},
+	{0x006000c4, 0x0000000c},
+	{0x20c07000, 0x00000020},
+	{0x000000c6, 0x00000012},
+	{0x00800000, 0x00000006},
+	{0x0080751d, 0x00000006},
+	{0x000025bb, 0x00000002},
+	{0x000040c0, 0x00000004},
+	{0x0000775c, 0x00000002},
+	{0x00a05000, 0x00000002},
+	{0x00661000, 0x00000002},
+	{0x0460275d, 0x00000020},
+	{0x00004000, 0000000000},
+	{0x00007999, 0x00000002},
+	{0x00a05000, 0x00000002},
+	{0x00661000, 0x00000002},
+	{0x0460299b, 0x00000020},
+	{0x00004000, 0000000000},
+	{0x01e00830, 0x00000002},
+	{0x21007000, 0000000000},
+	{0x00005000, 0x00000002},
+	{0x00038042, 0x00000002},
+	{0x040025e0, 0x00000002},
+	{0x000075e1, 0000000000},
+	{0x00000001, 0000000000},
+	{0x000380d9, 0x00000002},
+	{0x04007394, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+};
+
+static const u32 radeon_cp_microcode[][2] = {
+	{0x21007000, 0000000000},
+	{0x20007000, 0000000000},
+	{0x000000b4, 0x00000004},
+	{0x000000b8, 0x00000004},
+	{0x6f5b4d4c, 0000000000},
+	{0x4c4c427f, 0000000000},
+	{0x5b568a92, 0000000000},
+	{0x4ca09c6d, 0000000000},
+	{0xad4c4c4c, 0000000000},
+	{0x4ce1af3d, 0000000000},
+	{0xd8afafaf, 0000000000},
+	{0xd64c4cdc, 0000000000},
+	{0x4cd10d10, 0000000000},
+	{0x000f0000, 0x00000016},
+	{0x362f242d, 0000000000},
+	{0x00000012, 0x00000004},
+	{0x000f0000, 0x00000016},
+	{0x362f282d, 0000000000},
+	{0x000380e7, 0x00000002},
+	{0x04002c97, 0x00000002},
+	{0x000f0001, 0x00000016},
+	{0x333a3730, 0000000000},
+	{0x000077ef, 0x00000002},
+	{0x00061000, 0x00000002},
+	{0x00000021, 0x0000001a},
+	{0x00004000, 0x0000001e},
+	{0x00061000, 0x00000002},
+	{0x00000021, 0x0000001a},
+	{0x00004000, 0x0000001e},
+	{0x00061000, 0x00000002},
+	{0x00000021, 0x0000001a},
+	{0x00004000, 0x0000001e},
+	{0x00000017, 0x00000004},
+	{0x0003802b, 0x00000002},
+	{0x040067e0, 0x00000002},
+	{0x00000017, 0x00000004},
+	{0x000077e0, 0x00000002},
+	{0x00065000, 0x00000002},
+	{0x000037e1, 0x00000002},
+	{0x040067e1, 0x00000006},
+	{0x000077e0, 0x00000002},
+	{0x000077e1, 0x00000002},
+	{0x000077e1, 0x00000006},
+	{0xffffffff, 0000000000},
+	{0x10000000, 0000000000},
+	{0x0003802b, 0x00000002},
+	{0x040067e0, 0x00000006},
+	{0x00007675, 0x00000002},
+	{0x00007676, 0x00000002},
+	{0x00007677, 0x00000002},
+	{0x00007678, 0x00000006},
+	{0x0003802c, 0x00000002},
+	{0x04002676, 0x00000002},
+	{0x00007677, 0x00000002},
+	{0x00007678, 0x00000006},
+	{0x0000002f, 0x00000018},
+	{0x0000002f, 0x00000018},
+	{0000000000, 0x00000006},
+	{0x00000030, 0x00000018},
+	{0x00000030, 0x00000018},
+	{0000000000, 0x00000006},
+	{0x01605000, 0x00000002},
+	{0x00065000, 0x00000002},
+	{0x00098000, 0x00000002},
+	{0x00061000, 0x00000002},
+	{0x64c0603e, 0x00000004},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x00080000, 0x00000016},
+	{0000000000, 0000000000},
+	{0x0400251d, 0x00000002},
+	{0x00007580, 0x00000002},
+	{0x00067581, 0x00000002},
+	{0x04002580, 0x00000002},
+	{0x00067581, 0x00000002},
+	{0x00000049, 0x00000004},
+	{0x00005000, 0000000000},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x00061000, 0x00000002},
+	{0x0000750e, 0x00000002},
+	{0x00019000, 0x00000002},
+	{0x00011055, 0x00000014},
+	{0x00000055, 0x00000012},
+	{0x0400250f, 0x00000002},
+	{0x0000504f, 0x00000004},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x00007565, 0x00000002},
+	{0x00007566, 0x00000002},
+	{0x00000058, 0x00000004},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x01e655b4, 0x00000002},
+	{0x4401b0e4, 0x00000002},
+	{0x01c110e4, 0x00000002},
+	{0x26667066, 0x00000018},
+	{0x040c2565, 0x00000002},
+	{0x00000066, 0x00000018},
+	{0x04002564, 0x00000002},
+	{0x00007566, 0x00000002},
+	{0x0000005d, 0x00000004},
+	{0x00401069, 0x00000008},
+	{0x00101000, 0x00000002},
+	{0x000d80ff, 0x00000002},
+	{0x0080006c, 0x00000008},
+	{0x000f9000, 0x00000002},
+	{0x000e00ff, 0x00000002},
+	{0000000000, 0x00000006},
+	{0x0000008f, 0x00000018},
+	{0x0000005b, 0x00000004},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x00007576, 0x00000002},
+	{0x00065000, 0x00000002},
+	{0x00009000, 0x00000002},
+	{0x00041000, 0x00000002},
+	{0x0c00350e, 0x00000002},
+	{0x00049000, 0x00000002},
+	{0x00051000, 0x00000002},
+	{0x01e785f8, 0x00000002},
+	{0x00200000, 0x00000002},
+	{0x0060007e, 0x0000000c},
+	{0x00007563, 0x00000002},
+	{0x006075f0, 0x00000021},
+	{0x20007073, 0x00000004},
+	{0x00005073, 0x00000004},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x00007576, 0x00000002},
+	{0x00007577, 0x00000002},
+	{0x0000750e, 0x00000002},
+	{0x0000750f, 0x00000002},
+	{0x00a05000, 0x00000002},
+	{0x00600083, 0x0000000c},
+	{0x006075f0, 0x00000021},
+	{0x000075f8, 0x00000002},
+	{0x00000083, 0x00000004},
+	{0x000a750e, 0x00000002},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x0020750f, 0x00000002},
+	{0x00600086, 0x00000004},
+	{0x00007570, 0x00000002},
+	{0x00007571, 0x00000002},
+	{0x00007572, 0x00000006},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x00005000, 0x00000002},
+	{0x00a05000, 0x00000002},
+	{0x00007568, 0x00000002},
+	{0x00061000, 0x00000002},
+	{0x00000095, 0x0000000c},
+	{0x00058000, 0x00000002},
+	{0x0c607562, 0x00000002},
+	{0x00000097, 0x00000004},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x00600096, 0x00000004},
+	{0x400070e5, 0000000000},
+	{0x000380e6, 0x00000002},
+	{0x040025c5, 0x00000002},
+	{0x000380e5, 0x00000002},
+	{0x000000a8, 0x0000001c},
+	{0x000650aa, 0x00000018},
+	{0x040025bb, 0x00000002},
+	{0x000610ab, 0x00000018},
+	{0x040075bc, 0000000000},
+	{0x000075bb, 0x00000002},
+	{0x000075bc, 0000000000},
+	{0x00090000, 0x00000006},
+	{0x00090000, 0x00000002},
+	{0x000d8002, 0x00000006},
+	{0x00007832, 0x00000002},
+	{0x00005000, 0x00000002},
+	{0x000380e7, 0x00000002},
+	{0x04002c97, 0x00000002},
+	{0x00007820, 0x00000002},
+	{0x00007821, 0x00000002},
+	{0x00007800, 0000000000},
+	{0x01200000, 0x00000002},
+	{0x20077000, 0x00000002},
+	{0x01200000, 0x00000002},
+	{0x20007000, 0x00000002},
+	{0x00061000, 0x00000002},
+	{0x0120751b, 0x00000002},
+	{0x8040750a, 0x00000002},
+	{0x8040750b, 0x00000002},
+	{0x00110000, 0x00000002},
+	{0x000380e5, 0x00000002},
+	{0x000000c6, 0x0000001c},
+	{0x000610ab, 0x00000018},
+	{0x844075bd, 0x00000002},
+	{0x000610aa, 0x00000018},
+	{0x840075bb, 0x00000002},
+	{0x000610ab, 0x00000018},
+	{0x844075bc, 0x00000002},
+	{0x000000c9, 0x00000004},
+	{0x804075bd, 0x00000002},
+	{0x800075bb, 0x00000002},
+	{0x804075bc, 0x00000002},
+	{0x00108000, 0x00000002},
+	{0x01400000, 0x00000002},
+	{0x006000cd, 0x0000000c},
+	{0x20c07000, 0x00000020},
+	{0x000000cf, 0x00000012},
+	{0x00800000, 0x00000006},
+	{0x0080751d, 0x00000006},
+	{0000000000, 0000000000},
+	{0x0000775c, 0x00000002},
+	{0x00a05000, 0x00000002},
+	{0x00661000, 0x00000002},
+	{0x0460275d, 0x00000020},
+	{0x00004000, 0000000000},
+	{0x01e00830, 0x00000002},
+	{0x21007000, 0000000000},
+	{0x6464614d, 0000000000},
+	{0x69687420, 0000000000},
+	{0x00000073, 0000000000},
+	{0000000000, 0000000000},
+	{0x00005000, 0x00000002},
+	{0x000380d0, 0x00000002},
+	{0x040025e0, 0x00000002},
+	{0x000075e1, 0000000000},
+	{0x00000001, 0000000000},
+	{0x000380e0, 0x00000002},
+	{0x04002394, 0x00000002},
+	{0x00005000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0x00000008, 0000000000},
+	{0x00000004, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+	{0000000000, 0000000000},
+};
+
+static const u32 R300_cp_microcode[][2] = {
+	{ 0x4200e000, 0000000000 },
+	{ 0x4000e000, 0000000000 },
+	{ 0x000000af, 0x00000008 },
+	{ 0x000000b3, 0x00000008 },
+	{ 0x6c5a504f, 0000000000 },
+	{ 0x4f4f497a, 0000000000 },
+	{ 0x5a578288, 0000000000 },
+	{ 0x4f91906a, 0000000000 },
+	{ 0x4f4f4f4f, 0000000000 },
+	{ 0x4fe24f44, 0000000000 },
+	{ 0x4f9c9c9c, 0000000000 },
+	{ 0xdc4f4fde, 0000000000 },
+	{ 0xa1cd4f4f, 0000000000 },
+	{ 0xd29d9d9d, 0000000000 },
+	{ 0x4f0f9fd7, 0000000000 },
+	{ 0x000ca000, 0x00000004 },
+	{ 0x000d0012, 0x00000038 },
+	{ 0x0000e8b4, 0x00000004 },
+	{ 0x000d0014, 0x00000038 },
+	{ 0x0000e8b6, 0x00000004 },
+	{ 0x000d0016, 0x00000038 },
+	{ 0x0000e854, 0x00000004 },
+	{ 0x000d0018, 0x00000038 },
+	{ 0x0000e855, 0x00000004 },
+	{ 0x000d001a, 0x00000038 },
+	{ 0x0000e856, 0x00000004 },
+	{ 0x000d001c, 0x00000038 },
+	{ 0x0000e857, 0x00000004 },
+	{ 0x000d001e, 0x00000038 },
+	{ 0x0000e824, 0x00000004 },
+	{ 0x000d0020, 0x00000038 },
+	{ 0x0000e825, 0x00000004 },
+	{ 0x000d0022, 0x00000038 },
+	{ 0x0000e830, 0x00000004 },
+	{ 0x000d0024, 0x00000038 },
+	{ 0x0000f0c0, 0x00000004 },
+	{ 0x000d0026, 0x00000038 },
+	{ 0x0000f0c1, 0x00000004 },
+	{ 0x000d0028, 0x00000038 },
+	{ 0x0000f041, 0x00000004 },
+	{ 0x000d002a, 0x00000038 },
+	{ 0x0000f184, 0x00000004 },
+	{ 0x000d002c, 0x00000038 },
+	{ 0x0000f185, 0x00000004 },
+	{ 0x000d002e, 0x00000038 },
+	{ 0x0000f186, 0x00000004 },
+	{ 0x000d0030, 0x00000038 },
+	{ 0x0000f187, 0x00000004 },
+	{ 0x000d0032, 0x00000038 },
+	{ 0x0000f180, 0x00000004 },
+	{ 0x000d0034, 0x00000038 },
+	{ 0x0000f393, 0x00000004 },
+	{ 0x000d0036, 0x00000038 },
+	{ 0x0000f38a, 0x00000004 },
+	{ 0x000d0038, 0x00000038 },
+	{ 0x0000f38e, 0x00000004 },
+	{ 0x0000e821, 0x00000004 },
+	{ 0x0140a000, 0x00000004 },
+	{ 0x00000043, 0x00000018 },
+	{ 0x00cce800, 0x00000004 },
+	{ 0x001b0001, 0x00000004 },
+	{ 0x08004800, 0x00000004 },
+	{ 0x001b0001, 0x00000004 },
+	{ 0x08004800, 0x00000004 },
+	{ 0x001b0001, 0x00000004 },
+	{ 0x08004800, 0x00000004 },
+	{ 0x0000003a, 0x00000008 },
+	{ 0x0000a000, 0000000000 },
+	{ 0x02c0a000, 0x00000004 },
+	{ 0x000ca000, 0x00000004 },
+	{ 0x00130000, 0x00000004 },
+	{ 0x000c2000, 0x00000004 },
+	{ 0xc980c045, 0x00000008 },
+	{ 0x2000451d, 0x00000004 },
+	{ 0x0000e580, 0x00000004 },
+	{ 0x000ce581, 0x00000004 },
+	{ 0x08004580, 0x00000004 },
+	{ 0x000ce581, 0x00000004 },
+	{ 0x0000004c, 0x00000008 },
+	{ 0x0000a000, 0000000000 },
+	{ 0x000c2000, 0x00000004 },
+	{ 0x0000e50e, 0x00000004 },
+	{ 0x00032000, 0x00000004 },
+	{ 0x00022056, 0x00000028 },
+	{ 0x00000056, 0x00000024 },
+	{ 0x0800450f, 0x00000004 },
+	{ 0x0000a050, 0x00000008 },
+	{ 0x0000e565, 0x00000004 },
+	{ 0x0000e566, 0x00000004 },
+	{ 0x00000057, 0x00000008 },
+	{ 0x03cca5b4, 0x00000004 },
+	{ 0x05432000, 0x00000004 },
+	{ 0x00022000, 0x00000004 },
+	{ 0x4ccce063, 0x00000030 },
+	{ 0x08274565, 0x00000004 },
+	{ 0x00000063, 0x00000030 },
+	{ 0x08004564, 0x00000004 },
+	{ 0x0000e566, 0x00000004 },
+	{ 0x0000005a, 0x00000008 },
+	{ 0x00802066, 0x00000010 },
+	{ 0x00202000, 0x00000004 },
+	{ 0x001b00ff, 0x00000004 },
+	{ 0x01000069, 0x00000010 },
+	{ 0x001f2000, 0x00000004 },
+	{ 0x001c00ff, 0x00000004 },
+	{ 0000000000, 0x0000000c },
+	{ 0x00000085, 0x00000030 },
+	{ 0x0000005a, 0x00000008 },
+	{ 0x0000e576, 0x00000004 },
+	{ 0x000ca000, 0x00000004 },
+	{ 0x00012000, 0x00000004 },
+	{ 0x00082000, 0x00000004 },
+	{ 0x1800650e, 0x00000004 },
+	{ 0x00092000, 0x00000004 },
+	{ 0x000a2000, 0x00000004 },
+	{ 0x000f0000, 0x00000004 },
+	{ 0x00400000, 0x00000004 },
+	{ 0x00000079, 0x00000018 },
+	{ 0x0000e563, 0x00000004 },
+	{ 0x00c0e5f9, 0x000000c2 },
+	{ 0x0000006e, 0x00000008 },
+	{ 0x0000a06e, 0x00000008 },
+	{ 0x0000e576, 0x00000004 },
+	{ 0x0000e577, 0x00000004 },
+	{ 0x0000e50e, 0x00000004 },
+	{ 0x0000e50f, 0x00000004 },
+	{ 0x0140a000, 0x00000004 },
+	{ 0x0000007c, 0x00000018 },
+	{ 0x00c0e5f9, 0x000000c2 },
+	{ 0x0000007c, 0x00000008 },
+	{ 0x0014e50e, 0x00000004 },
+	{ 0x0040e50f, 0x00000004 },
+	{ 0x00c0007f, 0x00000008 },
+	{ 0x0000e570, 0x00000004 },
+	{ 0x0000e571, 0x00000004 },
+	{ 0x0000e572, 0x0000000c },
+	{ 0x0000a000, 0x00000004 },
+	{ 0x0140a000, 0x00000004 }, 
+	{ 0x0000e568, 0x00000004 },
+	{ 0x000c2000, 0x00000004 },
+	{ 0x00000089, 0x00000018 },
+	{ 0x000b0000, 0x00000004 },
+	{ 0x18c0e562, 0x00000004 },
+	{ 0x0000008b, 0x00000008 },
+	{ 0x00c0008a, 0x00000008 },
+	{ 0x000700e4, 0x00000004 },
+	{ 0x00000097, 0x00000038 },
+	{ 0x000ca099, 0x00000030 },
+	{ 0x080045bb, 0x00000004 },
+	{ 0x000c209a, 0x00000030 },
+	{ 0x0800e5bc, 0000000000 },
+	{ 0x0000e5bb, 0x00000004 },
+	{ 0x0000e5bc, 0000000000 },
+	{ 0x00120000, 0x0000000c },
+	{ 0x00120000, 0x00000004 },
+	{ 0x001b0002, 0x0000000c },
+	{ 0x0000a000, 0x00000004 },
+	{ 0x0000e821, 0x00000004 },
+	{ 0x0000e800, 0000000000 },
+	{ 0x0000e821, 0x00000004 },
+	{ 0x0000e82e, 0000000000 },
+	{ 0x02cca000, 0x00000004 },
+	{ 0x00140000, 0x00000004 },
+	{ 0x000ce1cc, 0x00000004 },
+	{ 0x050de1cd, 0x00000004 },
+	{ 0x000000a7, 0x00000020 },
+	{ 0x4200e000, 0000000000 },
+	{ 0x000000ae, 0x00000038 },
+	{ 0x000ca000, 0x00000004 },
+	{ 0x00140000, 0x00000004 },
+	{ 0x000c2000, 0x00000004 },
+	{ 0x00160000, 0x00000004 },
+	{ 0x700ce000, 0x00000004 },
+	{ 0x001400aa, 0x00000008 },
+	{ 0x4000e000, 0000000000 },
+	{ 0x02400000, 0x00000004 },
+	{ 0x400ee000, 0x00000004 },
+	{ 0x02400000, 0x00000004 },
+	{ 0x4000e000, 0000000000 },
+	{ 0x000c2000, 0x00000004 },
+	{ 0x0240e51b, 0x00000004 },
+	{ 0x0080e50a, 0x00000005 },
+	{ 0x0080e50b, 0x00000005 },
+	{ 0x00220000, 0x00000004 },
+	{ 0x000700e4, 0x00000004 },
+	{ 0x000000c1, 0x00000038 },
+	{ 0x000c209a, 0x00000030 },
+	{ 0x0880e5bd, 0x00000005 },
+	{ 0x000c2099, 0x00000030 },
+	{ 0x0800e5bb, 0x00000005 },
+	{ 0x000c209a, 0x00000030 },
+	{ 0x0880e5bc, 0x00000005 },
+	{ 0x000000c4, 0x00000008 },
+	{ 0x0080e5bd, 0x00000005 },
+	{ 0x0000e5bb, 0x00000005 },
+	{ 0x0080e5bc, 0x00000005 },
+	{ 0x00210000, 0x00000004 },
+	{ 0x02800000, 0x00000004 },
+	{ 0x00c000c8, 0x00000018 },
+	{ 0x4180e000, 0x00000040 },
+	{ 0x000000ca, 0x00000024 },
+	{ 0x01000000, 0x0000000c },
+	{ 0x0100e51d, 0x0000000c },
+	{ 0x000045bb, 0x00000004 },
+	{ 0x000080c4, 0x00000008 },
+	{ 0x0000f3ce, 0x00000004 },
+	{ 0x0140a000, 0x00000004 },
+	{ 0x00cc2000, 0x00000004 },
+	{ 0x08c053cf, 0x00000040 },
+	{ 0x00008000, 0000000000 },
+	{ 0x0000f3d2, 0x00000004 },
+	{ 0x0140a000, 0x00000004 },
+	{ 0x00cc2000, 0x00000004 },
+	{ 0x08c053d3, 0x00000040 },
+	{ 0x00008000, 0000000000 },
+	{ 0x0000f39d, 0x00000004 },
+	{ 0x0140a000, 0x00000004 },
+	{ 0x00cc2000, 0x00000004 },
+	{ 0x08c0539e, 0x00000040 },
+	{ 0x00008000, 0000000000 },
+	{ 0x03c00830, 0x00000004 },
+	{ 0x4200e000, 0000000000 },
+	{ 0x0000a000, 0x00000004 },
+	{ 0x200045e0, 0x00000004 },
+	{ 0x0000e5e1, 0000000000 },
+	{ 0x00000001, 0000000000 },
+	{ 0x000700e1, 0x00000004 },
+	{ 0x0800e394, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+};
+
+static int RADEON_READ_PLL(drm_device_t * dev, int addr)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
+	return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+}
+
+static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
+{
+	RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
+	return RADEON_READ(RADEON_PCIE_DATA);
+}
+
+#if RADEON_FIFO_DEBUG
+static void radeon_status(drm_radeon_private_t * dev_priv)
+{
+	printk("%s:\n", __FUNCTION__);
+	printk("RBBM_STATUS = 0x%08x\n",
+	       (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
+	printk("CP_RB_RTPR = 0x%08x\n",
+	       (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR));
+	printk("CP_RB_WTPR = 0x%08x\n",
+	       (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR));
+	printk("AIC_CNTL = 0x%08x\n",
+	       (unsigned int)RADEON_READ(RADEON_AIC_CNTL));
+	printk("AIC_STAT = 0x%08x\n",
+	       (unsigned int)RADEON_READ(RADEON_AIC_STAT));
+	printk("AIC_PT_BASE = 0x%08x\n",
+	       (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE));
+	printk("TLB_ADDR = 0x%08x\n",
+	       (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR));
+	printk("TLB_DATA = 0x%08x\n",
+	       (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA));
+}
+#endif
+
+/* ================================================================
+ * Engine, FIFO control
+ */
+
+static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
+{
+	u32 tmp;
+	int i;
+
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+	tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
+	tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+	RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
+		      & RADEON_RB3D_DC_BUSY)) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+
+#if RADEON_FIFO_DEBUG
+	DRM_ERROR("failed!\n");
+	radeon_status(dev_priv);
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
+{
+	int i;
+
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		int slots = (RADEON_READ(RADEON_RBBM_STATUS)
+			     & RADEON_RBBM_FIFOCNT_MASK);
+		if (slots >= entries)
+			return 0;
+		DRM_UDELAY(1);
+	}
+
+#if RADEON_FIFO_DEBUG
+	DRM_ERROR("failed!\n");
+	radeon_status(dev_priv);
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
+{
+	int i, ret;
+
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+	ret = radeon_do_wait_for_fifo(dev_priv, 64);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		if (!(RADEON_READ(RADEON_RBBM_STATUS)
+		      & RADEON_RBBM_ACTIVE)) {
+			radeon_do_pixcache_flush(dev_priv);
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+
+#if RADEON_FIFO_DEBUG
+	DRM_ERROR("failed!\n");
+	radeon_status(dev_priv);
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+/* ================================================================
+ * CP control, initialization
+ */
+
+/* Load the microcode for the CP */
+static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
+{
+	int i;
+	DRM_DEBUG("\n");
+
+	radeon_do_wait_for_idle(dev_priv);
+
+	RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
+
+	if (dev_priv->microcode_version == UCODE_R200) {
+		DRM_INFO("Loading R200 Microcode\n");
+		for (i = 0; i < 256; i++) {
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+				     R200_cp_microcode[i][1]);
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+				     R200_cp_microcode[i][0]);
+		}
+	} else if (dev_priv->microcode_version == UCODE_R300) {
+		DRM_INFO("Loading R300 Microcode\n");
+		for (i = 0; i < 256; i++) {
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+				     R300_cp_microcode[i][1]);
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+				     R300_cp_microcode[i][0]);
+		}
+	} else {
+		for (i = 0; i < 256; i++) {
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+				     radeon_cp_microcode[i][1]);
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+				     radeon_cp_microcode[i][0]);
+		}
+	}
+}
+
+/* Flush any pending commands to the CP.  This should only be used just
+ * prior to a wait for idle, as it informs the engine that the command
+ * stream is ending.
+ */
+static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv)
+{
+	DRM_DEBUG("\n");
+#if 0
+	u32 tmp;
+
+	tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
+	RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
+#endif
+}
+
+/* Wait for the CP to go idle.
+ */
+int radeon_do_cp_idle(drm_radeon_private_t * dev_priv)
+{
+	RING_LOCALS;
+	DRM_DEBUG("\n");
+
+	BEGIN_RING(6);
+
+	RADEON_PURGE_CACHE();
+	RADEON_PURGE_ZCACHE();
+	RADEON_WAIT_UNTIL_IDLE();
+
+	ADVANCE_RING();
+	COMMIT_RING();
+
+	return radeon_do_wait_for_idle(dev_priv);
+}
+
+/* Start the Command Processor.
+ */
+static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
+{
+	RING_LOCALS;
+	DRM_DEBUG("\n");
+
+	radeon_do_wait_for_idle(dev_priv);
+
+	RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode);
+
+	dev_priv->cp_running = 1;
+
+	BEGIN_RING(6);
+
+	RADEON_PURGE_CACHE();
+	RADEON_PURGE_ZCACHE();
+	RADEON_WAIT_UNTIL_IDLE();
+
+	ADVANCE_RING();
+	COMMIT_RING();
+}
+
+/* Reset the Command Processor.  This will not flush any pending
+ * commands, so you must wait for the CP command stream to complete
+ * before calling this routine.
+ */
+static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
+{
+	u32 cur_read_ptr;
+	DRM_DEBUG("\n");
+
+	cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
+	RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
+	SET_RING_HEAD(dev_priv, cur_read_ptr);
+	dev_priv->ring.tail = cur_read_ptr;
+}
+
+/* Stop the Command Processor.  This will not flush any pending
+ * commands, so you must flush the command stream and wait for the CP
+ * to go idle before calling this routine.
+ */
+static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
+{
+	DRM_DEBUG("\n");
+
+	RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
+
+	dev_priv->cp_running = 0;
+}
+
+/* Reset the engine.  This will stop the CP if it is running.
+ */
+static int radeon_do_engine_reset(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+	DRM_DEBUG("\n");
+
+	radeon_do_pixcache_flush(dev_priv);
+
+	clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
+	mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
+
+	RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
+					    RADEON_FORCEON_MCLKA |
+					    RADEON_FORCEON_MCLKB |
+					    RADEON_FORCEON_YCLKA |
+					    RADEON_FORCEON_YCLKB |
+					    RADEON_FORCEON_MC |
+					    RADEON_FORCEON_AIC));
+
+	rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
+					      RADEON_SOFT_RESET_CP |
+					      RADEON_SOFT_RESET_HI |
+					      RADEON_SOFT_RESET_SE |
+					      RADEON_SOFT_RESET_RE |
+					      RADEON_SOFT_RESET_PP |
+					      RADEON_SOFT_RESET_E2 |
+					      RADEON_SOFT_RESET_RB));
+	RADEON_READ(RADEON_RBBM_SOFT_RESET);
+	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
+					      ~(RADEON_SOFT_RESET_CP |
+						RADEON_SOFT_RESET_HI |
+						RADEON_SOFT_RESET_SE |
+						RADEON_SOFT_RESET_RE |
+						RADEON_SOFT_RESET_PP |
+						RADEON_SOFT_RESET_E2 |
+						RADEON_SOFT_RESET_RB)));
+	RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+	RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
+	RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
+	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
+
+	/* Reset the CP ring */
+	radeon_do_cp_reset(dev_priv);
+
+	/* The CP is no longer running after an engine reset */
+	dev_priv->cp_running = 0;
+
+	/* Reset any pending vertex, indirect buffers */
+	radeon_freelist_reset(dev);
+
+	return 0;
+}
+
+static void radeon_cp_init_ring_buffer(drm_device_t * dev,
+				       drm_radeon_private_t * dev_priv)
+{
+	u32 ring_start, cur_read_ptr;
+	u32 tmp;
+	
+	/* Initialize the memory controller. With new memory map, the fb location
+	 * is not changed, it should have been properly initialized already. Part
+	 * of the problem is that the code below is bogus, assuming the GART is
+	 * always appended to the fb which is not necessarily the case
+	 */
+	if (!dev_priv->new_memmap)
+		RADEON_WRITE(RADEON_MC_FB_LOCATION,
+			     ((dev_priv->gart_vm_start - 1) & 0xffff0000)
+			     | (dev_priv->fb_location >> 16));
+
+#if __OS_HAS_AGP
+	if (dev_priv->flags & RADEON_IS_AGP) {
+		RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
+		RADEON_WRITE(RADEON_MC_AGP_LOCATION,
+			     (((dev_priv->gart_vm_start - 1 +
+				dev_priv->gart_size) & 0xffff0000) |
+			      (dev_priv->gart_vm_start >> 16)));
+
+		ring_start = (dev_priv->cp_ring->offset
+			      - dev->agp->base
+			      + dev_priv->gart_vm_start);
+	} else
+#endif
+		ring_start = (dev_priv->cp_ring->offset
+			      - (unsigned long)dev->sg->virtual
+			      + dev_priv->gart_vm_start);
+
+	RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);
+
+	/* Set the write pointer delay */
+	RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);
+
+	/* Initialize the ring buffer's read and write pointers */
+	cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
+	RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
+	SET_RING_HEAD(dev_priv, cur_read_ptr);
+	dev_priv->ring.tail = cur_read_ptr;
+
+#if __OS_HAS_AGP
+	if (dev_priv->flags & RADEON_IS_AGP) {
+		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
+			     dev_priv->ring_rptr->offset
+			     - dev->agp->base + dev_priv->gart_vm_start);
+	} else
+#endif
+	{
+		drm_sg_mem_t *entry = dev->sg;
+		unsigned long tmp_ofs, page_ofs;
+
+		tmp_ofs = dev_priv->ring_rptr->offset -
+				(unsigned long)dev->sg->virtual;
+		page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]);
+		DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n",
+			  (unsigned long)entry->busaddr[page_ofs],
+			  entry->handle + tmp_ofs);
+	}
+
+	/* Set ring buffer size */
+#ifdef __BIG_ENDIAN
+	RADEON_WRITE(RADEON_CP_RB_CNTL,
+		     dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
+#else
+	RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
+#endif
+
+	/* Start with assuming that writeback doesn't work */
+	dev_priv->writeback_works = 0;
+
+	/* Initialize the scratch register pointer.  This will cause
+	 * the scratch register values to be written out to memory
+	 * whenever they are updated.
+	 *
+	 * We simply put this behind the ring read pointer, this works
+	 * with PCI GART as well as (whatever kind of) AGP GART
+	 */
+	RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
+		     + RADEON_SCRATCH_REG_OFFSET);
+
+	dev_priv->scratch = ((__volatile__ u32 *)
+			     dev_priv->ring_rptr->handle +
+			     (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+
+	RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
+
+	/* Turn on bus mastering */
+	tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+	RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+
+	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
+	RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
+
+	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
+	RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
+		     dev_priv->sarea_priv->last_dispatch);
+
+	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
+	RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
+
+	radeon_do_wait_for_idle(dev_priv);
+
+	/* Sync everything up */
+	RADEON_WRITE(RADEON_ISYNC_CNTL,
+		     (RADEON_ISYNC_ANY2D_IDLE3D |
+		      RADEON_ISYNC_ANY3D_IDLE2D |
+		      RADEON_ISYNC_WAIT_IDLEGUI |
+		      RADEON_ISYNC_CPSCRATCH_IDLEGUI));
+
+}
+
+static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
+{
+	u32 tmp;
+
+	/* Writeback doesn't seem to work everywhere, test it here and possibly
+	 * enable it if it appears to work
+	 */
+	DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
+	RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
+
+	for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
+		if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
+		    0xdeadbeef)
+			break;
+		DRM_UDELAY(1);
+	}
+
+	if (tmp < dev_priv->usec_timeout) {
+		dev_priv->writeback_works = 1;
+		DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
+	} else {
+		dev_priv->writeback_works = 0;
+		DRM_INFO("writeback test failed\n");
+	}
+	if (radeon_no_wb == 1) {
+		dev_priv->writeback_works = 0;
+		DRM_INFO("writeback forced off\n");
+	}
+
+	if (!dev_priv->writeback_works) {
+		/* Disable writeback to avoid unnecessary bus master transfers */
+		RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) | RADEON_RB_NO_UPDATE);
+		RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
+	}
+}
+
+/* Enable or disable PCI-E GART on the chip */
+static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
+{
+	u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
+	if (on) {
+
+		DRM_DEBUG("programming pcie %08X %08lX %08X\n",
+			  dev_priv->gart_vm_start,
+			  (long)dev_priv->gart_info.bus_addr,
+			  dev_priv->gart_size);
+		RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,
+				  dev_priv->gart_vm_start);
+		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,
+				  dev_priv->gart_info.bus_addr);
+		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,
+				  dev_priv->gart_vm_start);
+		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,
+				  dev_priv->gart_vm_start +
+				  dev_priv->gart_size - 1);
+
+		RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);	/* ?? */
+
+		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
+				  RADEON_PCIE_TX_GART_EN);
+	} else {
+		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
+				  tmp & ~RADEON_PCIE_TX_GART_EN);
+	}
+}
+
+/* Enable or disable PCI GART on the chip */
+static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
+{
+	u32 tmp;
+
+	if (dev_priv->flags & RADEON_IS_PCIE) {
+		radeon_set_pciegart(dev_priv, on);
+		return;
+	}
+
+ 	tmp = RADEON_READ(RADEON_AIC_CNTL);
+
+	if (on) {
+		RADEON_WRITE(RADEON_AIC_CNTL,
+			     tmp | RADEON_PCIGART_TRANSLATE_EN);
+
+		/* set PCI GART page-table base address
+		 */
+		RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
+
+		/* set address range for PCI address translate
+		 */
+		RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);
+		RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
+			     + dev_priv->gart_size - 1);
+
+		/* Turn off AGP aperture -- is this required for PCI GART?
+		 */
+		RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);	/* ?? */
+		RADEON_WRITE(RADEON_AGP_COMMAND, 0);	/* clear AGP_COMMAND */
+	} else {
+		RADEON_WRITE(RADEON_AIC_CNTL,
+			     tmp & ~RADEON_PCIGART_TRANSLATE_EN);
+	}
+}
+
+static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("\n");
+
+	/* if we require new memory map but we don't have it fail */
+	if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap)
+	{
+		DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
+		radeon_do_cleanup_cp(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP))
+	{
+		DRM_DEBUG("Forcing AGP card to PCI mode\n");
+		dev_priv->flags &= ~RADEON_IS_AGP;
+	}
+	else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
+		 && !init->is_pci)
+	{
+		DRM_DEBUG("Restoring AGP flag\n");
+		dev_priv->flags |= RADEON_IS_AGP;
+	}
+
+	if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
+		DRM_ERROR("PCI GART memory not allocated!\n");
+		radeon_do_cleanup_cp(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->usec_timeout = init->usec_timeout;
+	if (dev_priv->usec_timeout < 1 ||
+	    dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
+		DRM_DEBUG("TIMEOUT problem!\n");
+		radeon_do_cleanup_cp(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	switch(init->func) {
+	case RADEON_INIT_R200_CP:
+		dev_priv->microcode_version = UCODE_R200;
+		break;
+	case RADEON_INIT_R300_CP:
+		dev_priv->microcode_version = UCODE_R300;
+		break;
+	default:
+		dev_priv->microcode_version = UCODE_R100;
+	}
+
+	dev_priv->do_boxes = 0;
+	dev_priv->cp_mode = init->cp_mode;
+
+	/* We don't support anything other than bus-mastering ring mode,
+	 * but the ring can be in either AGP or PCI space for the ring
+	 * read pointer.
+	 */
+	if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
+	    (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
+		DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
+		radeon_do_cleanup_cp(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	switch (init->fb_bpp) {
+	case 16:
+		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
+		break;
+	case 32:
+	default:
+		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
+		break;
+	}
+	dev_priv->front_offset = init->front_offset;
+	dev_priv->front_pitch = init->front_pitch;
+	dev_priv->back_offset = init->back_offset;
+	dev_priv->back_pitch = init->back_pitch;
+
+	switch (init->depth_bpp) {
+	case 16:
+		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+		break;
+	case 32:
+	default:
+		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+		break;
+	}
+	dev_priv->depth_offset = init->depth_offset;
+	dev_priv->depth_pitch = init->depth_pitch;
+
+	/* Hardware state for depth clears.  Remove this if/when we no
+	 * longer clear the depth buffer with a 3D rectangle.  Hard-code
+	 * all values to prevent unwanted 3D state from slipping through
+	 * and screwing with the clear operation.
+	 */
+	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
+					   (dev_priv->color_fmt << 10) |
+					   (dev_priv->microcode_version ==
+					    UCODE_R100 ? RADEON_ZBLOCK16 : 0));
+
+	dev_priv->depth_clear.rb3d_zstencilcntl =
+	    (dev_priv->depth_fmt |
+	     RADEON_Z_TEST_ALWAYS |
+	     RADEON_STENCIL_TEST_ALWAYS |
+	     RADEON_STENCIL_S_FAIL_REPLACE |
+	     RADEON_STENCIL_ZPASS_REPLACE |
+	     RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);
+
+	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
+					 RADEON_BFACE_SOLID |
+					 RADEON_FFACE_SOLID |
+					 RADEON_FLAT_SHADE_VTX_LAST |
+					 RADEON_DIFFUSE_SHADE_FLAT |
+					 RADEON_ALPHA_SHADE_FLAT |
+					 RADEON_SPECULAR_SHADE_FLAT |
+					 RADEON_FOG_SHADE_FLAT |
+					 RADEON_VTX_PIX_CENTER_OGL |
+					 RADEON_ROUND_MODE_TRUNC |
+					 RADEON_ROUND_PREC_8TH_PIX);
+
+	DRM_GETSAREA();
+
+	dev_priv->ring_offset = init->ring_offset;
+	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
+	dev_priv->buffers_offset = init->buffers_offset;
+	dev_priv->gart_textures_offset = init->gart_textures_offset;
+
+	if (!dev_priv->sarea) {
+		DRM_ERROR("could not find sarea!\n");
+		radeon_do_cleanup_cp(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
+	if (!dev_priv->cp_ring) {
+		DRM_ERROR("could not find cp ring region!\n");
+		radeon_do_cleanup_cp(dev);
+		return DRM_ERR(EINVAL);
+	}
+	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
+	if (!dev_priv->ring_rptr) {
+		DRM_ERROR("could not find ring read pointer!\n");
+		radeon_do_cleanup_cp(dev);
+		return DRM_ERR(EINVAL);
+	}
+	dev->agp_buffer_token = init->buffers_offset;
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if (!dev->agp_buffer_map) {
+		DRM_ERROR("could not find dma buffer region!\n");
+		radeon_do_cleanup_cp(dev);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (init->gart_textures_offset) {
+		dev_priv->gart_textures =
+		    drm_core_findmap(dev, init->gart_textures_offset);
+		if (!dev_priv->gart_textures) {
+			DRM_ERROR("could not find GART texture region!\n");
+			radeon_do_cleanup_cp(dev);
+			return DRM_ERR(EINVAL);
+		}
+	}
+
+	dev_priv->sarea_priv =
+	    (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+				    init->sarea_priv_offset);
+
+#if __OS_HAS_AGP
+	if (dev_priv->flags & RADEON_IS_AGP) {
+		drm_core_ioremap(dev_priv->cp_ring, dev);
+		drm_core_ioremap(dev_priv->ring_rptr, dev);
+		drm_core_ioremap(dev->agp_buffer_map, dev);
+		if (!dev_priv->cp_ring->handle ||
+		    !dev_priv->ring_rptr->handle ||
+		    !dev->agp_buffer_map->handle) {
+			DRM_ERROR("could not find ioremap agp regions!\n");
+			radeon_do_cleanup_cp(dev);
+			return DRM_ERR(EINVAL);
+		}
+	} else
+#endif
+	{
+		dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset;
+		dev_priv->ring_rptr->handle =
+		    (void *)dev_priv->ring_rptr->offset;
+		dev->agp_buffer_map->handle =
+		    (void *)dev->agp_buffer_map->offset;
+
+		DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
+			  dev_priv->cp_ring->handle);
+		DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
+			  dev_priv->ring_rptr->handle);
+		DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
+			  dev->agp_buffer_map->handle);
+	}
+
+	dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION)
+				 & 0xffff) << 16;
+	dev_priv->fb_size = 
+		((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000)
+		- dev_priv->fb_location;
+
+	dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
+					((dev_priv->front_offset
+					  + dev_priv->fb_location) >> 10));
+
+	dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
+				       ((dev_priv->back_offset
+					 + dev_priv->fb_location) >> 10));
+
+	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
+					((dev_priv->depth_offset
+					  + dev_priv->fb_location) >> 10));
+
+	dev_priv->gart_size = init->gart_size;
+
+	/* New let's set the memory map ... */
+	if (dev_priv->new_memmap) {
+		u32 base = 0;
+
+		DRM_INFO("Setting GART location based on new memory map\n");
+
+		/* If using AGP, try to locate the AGP aperture at the same
+		 * location in the card and on the bus, though we have to
+		 * align it down.
+		 */
+#if __OS_HAS_AGP
+		if (dev_priv->flags & RADEON_IS_AGP) {
+			base = dev->agp->base;
+			/* Check if valid */
+			if ((base + dev_priv->gart_size) > dev_priv->fb_location &&
+			    base < (dev_priv->fb_location + dev_priv->fb_size)) {
+				DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
+					 dev->agp->base);
+				base = 0;
+			}
+		}
+#endif
+		/* If not or if AGP is at 0 (Macs), try to put it elsewhere */
+		if (base == 0) {
+			base = dev_priv->fb_location + dev_priv->fb_size;
+			if (((base + dev_priv->gart_size) & 0xfffffffful)
+			    < base)
+				base = dev_priv->fb_location
+					- dev_priv->gart_size;
+		}		
+		dev_priv->gart_vm_start = base & 0xffc00000u;
+		if (dev_priv->gart_vm_start != base)
+			DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
+				 base, dev_priv->gart_vm_start);
+	} else {
+		DRM_INFO("Setting GART location based on old memory map\n");
+		dev_priv->gart_vm_start = dev_priv->fb_location +
+			RADEON_READ(RADEON_CONFIG_APER_SIZE);
+	}
+
+#if __OS_HAS_AGP
+	if (dev_priv->flags & RADEON_IS_AGP)
+		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
+						 - dev->agp->base
+						 + dev_priv->gart_vm_start);
+	else
+#endif
+		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
+					- (unsigned long)dev->sg->virtual
+					+ dev_priv->gart_vm_start);
+
+	DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
+	DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);
+	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
+		  dev_priv->gart_buffers_offset);
+
+	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
+	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
+			      + init->ring_size / sizeof(u32));
+	dev_priv->ring.size = init->ring_size;
+	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+
+	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
+
+	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
+
+#if __OS_HAS_AGP
+	if (dev_priv->flags & RADEON_IS_AGP) {
+		/* Turn off PCI GART */
+		radeon_set_pcigart(dev_priv, 0);
+	} else
+#endif
+	{
+		/* if we have an offset set from userspace */
+		if (dev_priv->pcigart_offset) {
+			dev_priv->gart_info.bus_addr =
+			    dev_priv->pcigart_offset + dev_priv->fb_location;
+			dev_priv->gart_info.mapping.offset =
+			    dev_priv->gart_info.bus_addr;
+			dev_priv->gart_info.mapping.size =
+			    RADEON_PCIGART_TABLE_SIZE;
+
+			drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
+			dev_priv->gart_info.addr =
+			    dev_priv->gart_info.mapping.handle;
+
+			dev_priv->gart_info.is_pcie =
+			    !!(dev_priv->flags & RADEON_IS_PCIE);
+			dev_priv->gart_info.gart_table_location =
+			    DRM_ATI_GART_FB;
+
+			DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
+				  dev_priv->gart_info.addr,
+				  dev_priv->pcigart_offset);
+		} else {
+			dev_priv->gart_info.gart_table_location =
+			    DRM_ATI_GART_MAIN;
+			dev_priv->gart_info.addr = NULL;
+			dev_priv->gart_info.bus_addr = 0;
+			if (dev_priv->flags & RADEON_IS_PCIE) {
+				DRM_ERROR
+				    ("Cannot use PCI Express without GART in FB memory\n");
+				radeon_do_cleanup_cp(dev);
+				return DRM_ERR(EINVAL);
+			}
+		}
+
+		if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
+			DRM_ERROR("failed to init PCI GART!\n");
+			radeon_do_cleanup_cp(dev);
+			return DRM_ERR(ENOMEM);
+		}
+
+		/* Turn on PCI GART */
+		radeon_set_pcigart(dev_priv, 1);
+	}
+
+	radeon_cp_load_microcode(dev_priv);
+	radeon_cp_init_ring_buffer(dev, dev_priv);
+
+	dev_priv->last_buf = 0;
+
+	radeon_do_engine_reset(dev);
+	radeon_test_writeback(dev_priv);
+
+	return 0;
+}
+
+static int radeon_do_cleanup_cp(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if (dev->irq_enabled)
+		drm_irq_uninstall(dev);
+
+#if __OS_HAS_AGP
+	if (dev_priv->flags & RADEON_IS_AGP) {
+		if (dev_priv->cp_ring != NULL) {
+			drm_core_ioremapfree(dev_priv->cp_ring, dev);
+			dev_priv->cp_ring = NULL;
+		}
+		if (dev_priv->ring_rptr != NULL) {
+			drm_core_ioremapfree(dev_priv->ring_rptr, dev);
+			dev_priv->ring_rptr = NULL;
+		}
+		if (dev->agp_buffer_map != NULL) {
+			drm_core_ioremapfree(dev->agp_buffer_map, dev);
+			dev->agp_buffer_map = NULL;
+		}
+	} else
+#endif
+	{
+
+		if (dev_priv->gart_info.bus_addr) {
+			/* Turn off PCI GART */
+			radeon_set_pcigart(dev_priv, 0);
+			if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
+				DRM_ERROR("failed to cleanup PCI GART!\n");
+		}
+
+		if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
+		{
+			drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
+			dev_priv->gart_info.addr = 0;
+		}
+	}
+	/* only clear to the start of flags */
+	memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
+
+	return 0;
+}
+
+/* This code will reinit the Radeon CP hardware after a resume from disc.
+ * AFAIK, it would be very difficult to pickle the state at suspend time, so
+ * here we make sure that all Radeon hardware initialisation is re-done without
+ * affecting running applications.
+ *
+ * Charl P. Botha <http://cpbotha.net>
+ */
+static int radeon_do_resume_cp(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	if (!dev_priv) {
+		DRM_ERROR("Called with no initialization\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_DEBUG("Starting radeon_do_resume_cp()\n");
+
+#if __OS_HAS_AGP
+	if (dev_priv->flags & RADEON_IS_AGP) {
+		/* Turn off PCI GART */
+		radeon_set_pcigart(dev_priv, 0);
+	} else
+#endif
+	{
+		/* Turn on PCI GART */
+		radeon_set_pcigart(dev_priv, 1);
+	}
+
+	radeon_cp_load_microcode(dev_priv);
+	radeon_cp_init_ring_buffer(dev, dev_priv);
+
+	radeon_do_engine_reset(dev);
+
+	DRM_DEBUG("radeon_do_resume_cp() complete\n");
+
+	return 0;
+}
+
+int radeon_cp_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_init_t init;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(init, (drm_radeon_init_t __user *) data,
+				 sizeof(init));
+
+	if (init.func == RADEON_INIT_R300_CP)
+		r300_init_reg_flags();
+
+	switch (init.func) {
+	case RADEON_INIT_CP:
+	case RADEON_INIT_R200_CP:
+	case RADEON_INIT_R300_CP:
+		return radeon_do_init_cp(dev, &init);
+	case RADEON_CLEANUP_CP:
+		return radeon_do_cleanup_cp(dev);
+	}
+
+	return DRM_ERR(EINVAL);
+}
+
+int radeon_cp_start(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (dev_priv->cp_running) {
+		DRM_DEBUG("%s while CP running\n", __FUNCTION__);
+		return 0;
+	}
+	if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
+		DRM_DEBUG("%s called with bogus CP mode (%d)\n",
+			  __FUNCTION__, dev_priv->cp_mode);
+		return 0;
+	}
+
+	radeon_do_cp_start(dev_priv);
+
+	return 0;
+}
+
+/* Stop the CP.  The engine must have been idled before calling this
+ * routine.
+ */
+int radeon_cp_stop(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_cp_stop_t stop;
+	int ret;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(stop, (drm_radeon_cp_stop_t __user *) data,
+				 sizeof(stop));
+
+	if (!dev_priv->cp_running)
+		return 0;
+
+	/* Flush any pending CP commands.  This ensures any outstanding
+	 * commands are exectuted by the engine before we turn it off.
+	 */
+	if (stop.flush) {
+		radeon_do_cp_flush(dev_priv);
+	}
+
+	/* If we fail to make the engine go idle, we return an error
+	 * code so that the DRM ioctl wrapper can try again.
+	 */
+	if (stop.idle) {
+		ret = radeon_do_cp_idle(dev_priv);
+		if (ret)
+			return ret;
+	}
+
+	/* Finally, we can turn off the CP.  If the engine isn't idle,
+	 * we will get some dropped triangles as they won't be fully
+	 * rendered before the CP is shut down.
+	 */
+	radeon_do_cp_stop(dev_priv);
+
+	/* Reset the engine */
+	radeon_do_engine_reset(dev);
+
+	return 0;
+}
+
+void radeon_do_release(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	int i, ret;
+
+	if (dev_priv) {
+		if (dev_priv->cp_running) {
+			/* Stop the cp */
+			while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
+				DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
+#ifdef __linux__
+				schedule();
+#else
+#if defined(__FreeBSD__) && __FreeBSD_version > 500000
+				msleep(&ret, &dev->dev_lock, PZERO, "rdnrel",
+				       1);
+#else
+				tsleep(&ret, PZERO, "rdnrel", 1);
+#endif
+#endif
+			}
+			radeon_do_cp_stop(dev_priv);
+			radeon_do_engine_reset(dev);
+		}
+
+		/* Disable *all* interrupts */
+		if (dev_priv->mmio)	/* remove this after permanent addmaps */
+			RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+
+		if (dev_priv->mmio) {	/* remove all surfaces */
+			for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+				RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0);
+				RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND +
+					     16 * i, 0);
+				RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND +
+					     16 * i, 0);
+			}
+		}
+
+		/* Free memory heap structures */
+		radeon_mem_takedown(&(dev_priv->gart_heap));
+		radeon_mem_takedown(&(dev_priv->fb_heap));
+
+		/* deallocate kernel resources */
+		radeon_do_cleanup_cp(dev);
+	}
+}
+
+/* Just reset the CP ring.  Called as part of an X Server engine reset.
+ */
+int radeon_cp_reset(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_DEBUG("%s called before init done\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	radeon_do_cp_reset(dev_priv);
+
+	/* The CP is no longer running after an engine reset */
+	dev_priv->cp_running = 0;
+
+	return 0;
+}
+
+int radeon_cp_idle(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	return radeon_do_cp_idle(dev_priv);
+}
+
+/* Added by Charl P. Botha to call radeon_do_resume_cp().
+ */
+int radeon_cp_resume(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+
+	return radeon_do_resume_cp(dev);
+}
+
+int radeon_engine_reset(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	DRM_DEBUG("\n");
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	return radeon_do_engine_reset(dev);
+}
+
+/* ================================================================
+ * Fullscreen mode
+ */
+
+/* KW: Deprecated to say the least:
+ */
+int radeon_fullscreen(DRM_IOCTL_ARGS)
+{
+	return 0;
+}
+
+/* ================================================================
+ * Freelist management
+ */
+
+/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
+ *   bufs until freelist code is used.  Note this hides a problem with
+ *   the scratch register * (used to keep track of last buffer
+ *   completed) being written to before * the last buffer has actually
+ *   completed rendering.
+ *
+ * KW:  It's also a good way to find free buffers quickly.
+ *
+ * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
+ * sleep.  However, bugs in older versions of radeon_accel.c mean that
+ * we essentially have to do this, else old clients will break.
+ *
+ * However, it does leave open a potential deadlock where all the
+ * buffers are held by other clients, which can't release them because
+ * they can't get the lock.
+ */
+
+drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_buf_priv_t *buf_priv;
+	drm_buf_t *buf;
+	int i, t;
+	int start;
+
+	if (++dev_priv->last_buf >= dma->buf_count)
+		dev_priv->last_buf = 0;
+
+	start = dev_priv->last_buf;
+
+	for (t = 0; t < dev_priv->usec_timeout; t++) {
+		u32 done_age = GET_SCRATCH(1);
+		DRM_DEBUG("done_age = %d\n", done_age);
+		for (i = start; i < dma->buf_count; i++) {
+			buf = dma->buflist[i];
+			buf_priv = buf->dev_private;
+			if (buf->filp == 0 || (buf->pending &&
+					       buf_priv->age <= done_age)) {
+				dev_priv->stats.requested_bufs++;
+				buf->pending = 0;
+				return buf;
+			}
+			start = 0;
+		}
+
+		if (t) {
+			DRM_UDELAY(1);
+			dev_priv->stats.freelist_loops++;
+		}
+	}
+
+	DRM_DEBUG("returning NULL!\n");
+	return NULL;
+}
+
+#if 0
+drm_buf_t *radeon_freelist_get(drm_device_t * dev)
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_buf_priv_t *buf_priv;
+	drm_buf_t *buf;
+	int i, t;
+	int start;
+	u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
+
+	if (++dev_priv->last_buf >= dma->buf_count)
+		dev_priv->last_buf = 0;
+
+	start = dev_priv->last_buf;
+	dev_priv->stats.freelist_loops++;
+
+	for (t = 0; t < 2; t++) {
+		for (i = start; i < dma->buf_count; i++) {
+			buf = dma->buflist[i];
+			buf_priv = buf->dev_private;
+			if (buf->filp == 0 || (buf->pending &&
+					       buf_priv->age <= done_age)) {
+				dev_priv->stats.requested_bufs++;
+				buf->pending = 0;
+				return buf;
+			}
+		}
+		start = 0;
+	}
+
+	return NULL;
+}
+#endif
+
+void radeon_freelist_reset(drm_device_t * dev)
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	int i;
+
+	dev_priv->last_buf = 0;
+	for (i = 0; i < dma->buf_count; i++) {
+		drm_buf_t *buf = dma->buflist[i];
+		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+		buf_priv->age = 0;
+	}
+}
+
+/* ================================================================
+ * CP command submission
+ */
+
+int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n)
+{
+	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
+	int i;
+	u32 last_head = GET_RING_HEAD(dev_priv);
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		u32 head = GET_RING_HEAD(dev_priv);
+
+		ring->space = (head - ring->tail) * sizeof(u32);
+		if (ring->space <= 0)
+			ring->space += ring->size;
+		if (ring->space > n)
+			return 0;
+
+		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+		if (head != last_head)
+			i = 0;
+		last_head = head;
+
+		DRM_UDELAY(1);
+	}
+
+	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
+#if RADEON_FIFO_DEBUG
+	radeon_status(dev_priv);
+	DRM_ERROR("failed!\n");
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+static int radeon_cp_get_buffers(DRMFILE filp, drm_device_t * dev,
+				 drm_dma_t * d)
+{
+	int i;
+	drm_buf_t *buf;
+
+	for (i = d->granted_count; i < d->request_count; i++) {
+		buf = radeon_freelist_get(dev);
+		if (!buf)
+			return DRM_ERR(EBUSY);	/* NOTE: broken client */
+
+		buf->filp = filp;
+
+		if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+				     sizeof(buf->idx)))
+			return DRM_ERR(EFAULT);
+		if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+				     sizeof(buf->total)))
+			return DRM_ERR(EFAULT);
+
+		d->granted_count++;
+	}
+	return 0;
+}
+
+int radeon_cp_buffers(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_device_dma_t *dma = dev->dma;
+	int ret = 0;
+	drm_dma_t __user *argp = (void __user *)data;
+	drm_dma_t d;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
+
+	/* Please don't send us buffers.
+	 */
+	if (d.send_count != 0) {
+		DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+			  DRM_CURRENTPID, d.send_count);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* We'll send you buffers.
+	 */
+	if (d.request_count < 0 || d.request_count > dma->buf_count) {
+		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+			  DRM_CURRENTPID, d.request_count, dma->buf_count);
+		return DRM_ERR(EINVAL);
+	}
+
+	d.granted_count = 0;
+
+	if (d.request_count) {
+		ret = radeon_cp_get_buffers(filp, dev, &d);
+	}
+
+	DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
+
+	return ret;
+}
+
+int radeon_driver_load(struct drm_device *dev, unsigned long flags)
+{
+	drm_radeon_private_t *dev_priv;
+	int ret = 0;
+
+	dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);
+	if (dev_priv == NULL)
+		return DRM_ERR(ENOMEM);
+
+	memset(dev_priv, 0, sizeof(drm_radeon_private_t));
+	dev->dev_private = (void *)dev_priv;
+	dev_priv->flags = flags;
+
+	switch (flags & RADEON_FAMILY_MASK) {
+	case CHIP_R100:
+	case CHIP_RV200:
+	case CHIP_R200:
+	case CHIP_R300:
+	case CHIP_R350:
+	case CHIP_R420:
+	case CHIP_RV410:
+		dev_priv->flags |= RADEON_HAS_HIERZ;
+		break;
+	default:
+		/* all other chips have no hierarchical z buffer */
+		break;
+	}
+
+	if (drm_device_is_agp(dev))
+		dev_priv->flags |= RADEON_IS_AGP;
+	else if (drm_device_is_pcie(dev))
+		dev_priv->flags |= RADEON_IS_PCIE;
+	else
+		dev_priv->flags |= RADEON_IS_PCI;
+
+	DRM_DEBUG("%s card detected\n",
+		  ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
+	return ret;
+}
+
+/* Create mappings for registers and framebuffer so userland doesn't necessarily
+ * have to find them.
+ */
+int radeon_driver_firstopen(struct drm_device *dev)
+{
+	int ret;
+	drm_local_map_t *map;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
+			 drm_get_resource_len(dev, 2), _DRM_REGISTERS,
+			 _DRM_READ_ONLY, &dev_priv->mmio);
+	if (ret != 0)
+		return ret;
+
+	ret = drm_addmap(dev, drm_get_resource_start(dev, 0),
+			 drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
+			 _DRM_WRITE_COMBINING, &map);
+	if (ret != 0)
+		return ret;
+
+	return 0;
+}
+
+int radeon_driver_unload(struct drm_device *dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("\n");
+	drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+
+	dev->dev_private = NULL;
+	return 0;
+}
--- libdrm-2.3.0.orig/shared-core/mach64_irq.c
+++ libdrm-2.3.0/shared-core/mach64_irq.c
@@ -0,0 +1,136 @@
+/* mach64_irq.c -- IRQ handling for ATI Mach64 -*- linux-c -*-
+ * Created: Tue Feb 25, 2003 by Leif Delgass, based on radeon_irq.c/r128_irq.c
+ */
+/*-
+ * Copyright (C) The Weather Channel, Inc.  2002.
+ * Copyright 2003 Leif Delgass
+ * All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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 COPYRIGHT OWNER(S) 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Eric Anholt <anholt@FreeBSD.org>
+ *    Leif Delgass <ldelgass@retinalburn.net>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "mach64_drm.h"
+#include "mach64_drv.h"
+
+irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS)
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_mach64_private_t *dev_priv =
+	    (drm_mach64_private_t *) dev->dev_private;
+	int status;
+
+	status = MACH64_READ(MACH64_CRTC_INT_CNTL);
+
+	/* VBLANK interrupt */
+	if (status & MACH64_CRTC_VBLANK_INT) {
+		/* Mask off all interrupt ack bits before setting the ack bit, since
+		 * there may be other handlers outside the DRM.
+		 *
+		 * NOTE: On mach64, you need to keep the enable bits set when doing
+		 * the ack, despite what the docs say about not acking and enabling
+		 * in a single write.
+		 */
+		MACH64_WRITE(MACH64_CRTC_INT_CNTL,
+			     (status & ~MACH64_CRTC_INT_ACKS)
+			     | MACH64_CRTC_VBLANK_INT);
+
+		atomic_inc(&dev->vbl_received);
+		DRM_WAKEUP(&dev->vbl_queue);
+		drm_vbl_send_signals(dev);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+int mach64_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+{
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks...
+	 */
+	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+		    (((cur_vblank = atomic_read(&dev->vbl_received))
+		      - *sequence) <= (1 << 23)));
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+/* drm_dma.h hooks
+*/
+void mach64_driver_irq_preinstall(drm_device_t * dev)
+{
+	drm_mach64_private_t *dev_priv =
+	    (drm_mach64_private_t *) dev->dev_private;
+
+	u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL);
+
+	DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status);
+
+	/* Disable and clear VBLANK interrupt */
+	MACH64_WRITE(MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_VBLANK_INT_EN)
+		     | MACH64_CRTC_VBLANK_INT);
+}
+
+void mach64_driver_irq_postinstall(drm_device_t * dev)
+{
+	drm_mach64_private_t *dev_priv =
+	    (drm_mach64_private_t *) dev->dev_private;
+
+	/* Turn on VBLANK interrupt */
+	MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL)
+		     | MACH64_CRTC_VBLANK_INT_EN);
+
+	DRM_DEBUG("after install CRTC_INT_CTNL: 0x%08x\n",
+		  MACH64_READ(MACH64_CRTC_INT_CNTL));
+
+}
+
+void mach64_driver_irq_uninstall(drm_device_t * dev)
+{
+	drm_mach64_private_t *dev_priv =
+	    (drm_mach64_private_t *) dev->dev_private;
+	if (!dev_priv)
+		return;
+
+	/* Disable and clear VBLANK interrupt */
+	MACH64_WRITE(MACH64_CRTC_INT_CNTL,
+		     (MACH64_READ(MACH64_CRTC_INT_CNTL) &
+		      ~MACH64_CRTC_VBLANK_INT_EN)
+		     | MACH64_CRTC_VBLANK_INT);
+
+	DRM_DEBUG("after uninstall CRTC_INT_CTNL: 0x%08x\n",
+		  MACH64_READ(MACH64_CRTC_INT_CNTL));
+}
--- libdrm-2.3.0.orig/shared-core/via_verifier.h
+++ libdrm-2.3.0/shared-core/via_verifier.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2004 The Unichrome Project. 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
+ * THE UNICHROME PROJECT, 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.
+ *
+ * Author: Thomas Hellström 2004.
+ */
+
+#ifndef _VIA_VERIFIER_H_
+#define _VIA_VERIFIER_H_
+
+typedef enum {
+	no_sequence = 0, 
+	z_address,
+	dest_address,
+	tex_address
+} drm_via_sequence_t;
+
+
+
+typedef struct {
+	unsigned texture;
+	uint32_t z_addr; 
+	uint32_t d_addr; 
+	uint32_t t_addr[2][10];
+	uint32_t pitch[2][10];
+	uint32_t height[2][10];
+	uint32_t tex_level_lo[2]; 
+	uint32_t tex_level_hi[2];
+	uint32_t tex_palette_size[2];
+	drm_via_sequence_t unfinished;
+	int agp_texture;
+	int multitex;
+	drm_device_t *dev;
+	drm_local_map_t *map_cache;
+	uint32_t vertex_count;
+	int agp;
+	const uint32_t *buf_start;
+} drm_via_state_t;
+
+extern int via_verify_command_stream(const uint32_t * buf, unsigned int size, 
+				    drm_device_t *dev, int agp);
+extern int via_parse_command_stream(drm_device_t *dev, const uint32_t * buf,
+                                   unsigned int size);
+
+#endif
--- libdrm-2.3.0.orig/shared-core/mach64_state.c
+++ libdrm-2.3.0/shared-core/mach64_state.c
@@ -0,0 +1,903 @@
+/* mach64_state.c -- State support for mach64 (Rage Pro) driver -*- linux-c -*-
+ * Created: Sun Dec 03 19:20:26 2000 by gareth@valinux.com
+ */
+/*
+ * Copyright 2000 Gareth Hughes
+ * Copyright 2002-2003 Leif Delgass
+ * 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 COPYRIGHT OWNER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION 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:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Leif Delgass <ldelgass@retinalburn.net>
+ *    Jos�Fonseca <j_r_fonseca@yahoo.co.uk>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "mach64_drm.h"
+#include "mach64_drv.h"
+
+/* Interface history:
+ *
+ * 1.0 - Initial mach64 DRM
+ *
+ */
+drm_ioctl_desc_t mach64_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_MACH64_INIT)] = {mach64_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_MACH64_CLEAR)] = {mach64_dma_clear, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MACH64_SWAP)] = {mach64_dma_swap, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MACH64_IDLE)] = {mach64_dma_idle, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MACH64_RESET)] = {mach64_engine_reset, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MACH64_VERTEX)] = {mach64_dma_vertex, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MACH64_BLIT)] = {mach64_dma_blit, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MACH64_FLUSH)] = {mach64_dma_flush, DRM_AUTH},
+	[DRM_IOCTL_NR(DRM_MACH64_GETPARAM)] = {mach64_get_param, DRM_AUTH},
+};
+
+int mach64_max_ioctl = DRM_ARRAY_SIZE(mach64_ioctls);
+
+/* ================================================================
+ * DMA hardware state programming functions
+ */
+
+static void mach64_print_dirty(const char *msg, unsigned int flags)
+{
+	DRM_DEBUG("%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s\n",
+		  msg,
+		  flags,
+		  (flags & MACH64_UPLOAD_DST_OFF_PITCH) ? "dst_off_pitch, " :
+		  "",
+		  (flags & MACH64_UPLOAD_Z_ALPHA_CNTL) ? "z_alpha_cntl, " : "",
+		  (flags & MACH64_UPLOAD_SCALE_3D_CNTL) ? "scale_3d_cntl, " :
+		  "", (flags & MACH64_UPLOAD_DP_FOG_CLR) ? "dp_fog_clr, " : "",
+		  (flags & MACH64_UPLOAD_DP_WRITE_MASK) ? "dp_write_mask, " :
+		  "",
+		  (flags & MACH64_UPLOAD_DP_PIX_WIDTH) ? "dp_pix_width, " : "",
+		  (flags & MACH64_UPLOAD_SETUP_CNTL) ? "setup_cntl, " : "",
+		  (flags & MACH64_UPLOAD_MISC) ? "misc, " : "",
+		  (flags & MACH64_UPLOAD_TEXTURE) ? "texture, " : "",
+		  (flags & MACH64_UPLOAD_TEX0IMAGE) ? "tex0 image, " : "",
+		  (flags & MACH64_UPLOAD_TEX1IMAGE) ? "tex1 image, " : "",
+		  (flags & MACH64_UPLOAD_CLIPRECTS) ? "cliprects, " : "");
+}
+
+/* Mach64 doesn't have hardware cliprects, just one hardware scissor,
+ * so the GL scissor is intersected with each cliprect here
+ */
+/* This function returns 0 on success, 1 for no intersection, and
+ * negative for an error
+ */
+static int mach64_emit_cliprect(DRMFILE filp, drm_mach64_private_t * dev_priv,
+				drm_clip_rect_t * box)
+{
+	u32 sc_left_right, sc_top_bottom;
+	drm_clip_rect_t scissor;
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mach64_context_regs_t *regs = &sarea_priv->context_state;
+	DMALOCALS;
+
+	DRM_DEBUG("%s: box=%p\n", __FUNCTION__, box);
+
+	/* Get GL scissor */
+	/* FIXME: store scissor in SAREA as a cliprect instead of in
+	 * hardware format, or do intersection client-side
+	 */
+	scissor.x1 = regs->sc_left_right & 0xffff;
+	scissor.x2 = (regs->sc_left_right & 0xffff0000) >> 16;
+	scissor.y1 = regs->sc_top_bottom & 0xffff;
+	scissor.y2 = (regs->sc_top_bottom & 0xffff0000) >> 16;
+
+	/* Intersect GL scissor with cliprect */
+	if (box->x1 > scissor.x1)
+		scissor.x1 = box->x1;
+	if (box->y1 > scissor.y1)
+		scissor.y1 = box->y1;
+	if (box->x2 < scissor.x2)
+		scissor.x2 = box->x2;
+	if (box->y2 < scissor.y2)
+		scissor.y2 = box->y2;
+	/* positive return means skip */
+	if (scissor.x1 >= scissor.x2)
+		return 1;
+	if (scissor.y1 >= scissor.y2)
+		return 1;
+
+	DMAGETPTR(filp, dev_priv, 2);	/* returns on failure to get buffer */
+
+	sc_left_right = ((scissor.x1 << 0) | (scissor.x2 << 16));
+	sc_top_bottom = ((scissor.y1 << 0) | (scissor.y2 << 16));
+
+	DMAOUTREG(MACH64_SC_LEFT_RIGHT, sc_left_right);
+	DMAOUTREG(MACH64_SC_TOP_BOTTOM, sc_top_bottom);
+
+	DMAADVANCE(dev_priv, 1);
+
+	return 0;
+}
+
+static __inline__ int mach64_emit_state(DRMFILE filp,
+					drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mach64_context_regs_t *regs = &sarea_priv->context_state;
+	unsigned int dirty = sarea_priv->dirty;
+	u32 offset = ((regs->tex_size_pitch & 0xf0) >> 2);
+	DMALOCALS;
+
+	if (MACH64_VERBOSE) {
+		mach64_print_dirty(__FUNCTION__, dirty);
+	} else {
+		DRM_DEBUG("%s: dirty=0x%08x\n", __FUNCTION__, dirty);
+	}
+
+	DMAGETPTR(filp, dev_priv, 17);	/* returns on failure to get buffer */
+
+	if (dirty & MACH64_UPLOAD_MISC) {
+		DMAOUTREG(MACH64_DP_MIX, regs->dp_mix);
+		DMAOUTREG(MACH64_DP_SRC, regs->dp_src);
+		DMAOUTREG(MACH64_CLR_CMP_CNTL, regs->clr_cmp_cntl);
+		DMAOUTREG(MACH64_GUI_TRAJ_CNTL, regs->gui_traj_cntl);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_MISC;
+	}
+
+	if (dirty & MACH64_UPLOAD_DST_OFF_PITCH) {
+		DMAOUTREG(MACH64_DST_OFF_PITCH, regs->dst_off_pitch);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_DST_OFF_PITCH;
+	}
+	if (dirty & MACH64_UPLOAD_Z_OFF_PITCH) {
+		DMAOUTREG(MACH64_Z_OFF_PITCH, regs->z_off_pitch);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_Z_OFF_PITCH;
+	}
+	if (dirty & MACH64_UPLOAD_Z_ALPHA_CNTL) {
+		DMAOUTREG(MACH64_Z_CNTL, regs->z_cntl);
+		DMAOUTREG(MACH64_ALPHA_TST_CNTL, regs->alpha_tst_cntl);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_Z_ALPHA_CNTL;
+	}
+	if (dirty & MACH64_UPLOAD_SCALE_3D_CNTL) {
+		DMAOUTREG(MACH64_SCALE_3D_CNTL, regs->scale_3d_cntl);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_SCALE_3D_CNTL;
+	}
+	if (dirty & MACH64_UPLOAD_DP_FOG_CLR) {
+		DMAOUTREG(MACH64_DP_FOG_CLR, regs->dp_fog_clr);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_DP_FOG_CLR;
+	}
+	if (dirty & MACH64_UPLOAD_DP_WRITE_MASK) {
+		DMAOUTREG(MACH64_DP_WRITE_MASK, regs->dp_write_mask);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_DP_WRITE_MASK;
+	}
+	if (dirty & MACH64_UPLOAD_DP_PIX_WIDTH) {
+		DMAOUTREG(MACH64_DP_PIX_WIDTH, regs->dp_pix_width);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_DP_PIX_WIDTH;
+	}
+	if (dirty & MACH64_UPLOAD_SETUP_CNTL) {
+		DMAOUTREG(MACH64_SETUP_CNTL, regs->setup_cntl);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_SETUP_CNTL;
+	}
+
+	if (dirty & MACH64_UPLOAD_TEXTURE) {
+		DMAOUTREG(MACH64_TEX_SIZE_PITCH, regs->tex_size_pitch);
+		DMAOUTREG(MACH64_TEX_CNTL, regs->tex_cntl);
+		DMAOUTREG(MACH64_SECONDARY_TEX_OFF, regs->secondary_tex_off);
+		DMAOUTREG(MACH64_TEX_0_OFF + offset, regs->tex_offset);
+		sarea_priv->dirty &= ~MACH64_UPLOAD_TEXTURE;
+	}
+
+	DMAADVANCE(dev_priv, 1);
+
+	sarea_priv->dirty &= MACH64_UPLOAD_CLIPRECTS;
+
+	return 0;
+
+}
+
+/* ================================================================
+ * DMA command dispatch functions
+ */
+
+static int mach64_dma_dispatch_clear(DRMFILE filp, drm_device_t * dev,
+				     unsigned int flags,
+				     int cx, int cy, int cw, int ch,
+				     unsigned int clear_color,
+				     unsigned int clear_depth)
+{
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mach64_context_regs_t *ctx = &sarea_priv->context_state;
+	int nbox = sarea_priv->nbox;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	u32 fb_bpp, depth_bpp;
+	int i;
+	DMALOCALS;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	switch (dev_priv->fb_bpp) {
+	case 16:
+		fb_bpp = MACH64_DATATYPE_RGB565;
+		break;
+	case 32:
+		fb_bpp = MACH64_DATATYPE_ARGB8888;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+	switch (dev_priv->depth_bpp) {
+	case 16:
+		depth_bpp = MACH64_DATATYPE_RGB565;
+		break;
+	case 24:
+	case 32:
+		depth_bpp = MACH64_DATATYPE_ARGB8888;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if (!nbox)
+		return 0;
+
+	DMAGETPTR(filp, dev_priv, nbox * 31);	/* returns on failure to get buffer */
+
+	for (i = 0; i < nbox; i++) {
+		int x = pbox[i].x1;
+		int y = pbox[i].y1;
+		int w = pbox[i].x2 - x;
+		int h = pbox[i].y2 - y;
+
+		DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
+			  pbox[i].x1, pbox[i].y1,
+			  pbox[i].x2, pbox[i].y2, flags);
+
+		if (flags & (MACH64_FRONT | MACH64_BACK)) {
+			/* Setup for color buffer clears
+			 */
+
+			DMAOUTREG(MACH64_Z_CNTL, 0);
+			DMAOUTREG(MACH64_SCALE_3D_CNTL, 0);
+
+			DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right);
+			DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom);
+
+			DMAOUTREG(MACH64_CLR_CMP_CNTL, 0);
+			DMAOUTREG(MACH64_GUI_TRAJ_CNTL,
+				  (MACH64_DST_X_LEFT_TO_RIGHT |
+				   MACH64_DST_Y_TOP_TO_BOTTOM));
+
+			DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) |
+							(fb_bpp << 4) |
+							(fb_bpp << 8) |
+							(fb_bpp << 16) |
+							(fb_bpp << 28)));
+
+			DMAOUTREG(MACH64_DP_FRGD_CLR, clear_color);
+			DMAOUTREG(MACH64_DP_WRITE_MASK, ctx->dp_write_mask);
+			DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D |
+						  MACH64_FRGD_MIX_S));
+			DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR |
+						  MACH64_FRGD_SRC_FRGD_CLR |
+						  MACH64_MONO_SRC_ONE));
+
+		}
+
+		if (flags & MACH64_FRONT) {
+
+			DMAOUTREG(MACH64_DST_OFF_PITCH,
+				  dev_priv->front_offset_pitch);
+			DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x);
+			DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w);
+
+		}
+
+		if (flags & MACH64_BACK) {
+
+			DMAOUTREG(MACH64_DST_OFF_PITCH,
+				  dev_priv->back_offset_pitch);
+			DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x);
+			DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w);
+
+		}
+
+		if (flags & MACH64_DEPTH) {
+			/* Setup for depth buffer clear
+			 */
+			DMAOUTREG(MACH64_Z_CNTL, 0);
+			DMAOUTREG(MACH64_SCALE_3D_CNTL, 0);
+
+			DMAOUTREG(MACH64_SC_LEFT_RIGHT, ctx->sc_left_right);
+			DMAOUTREG(MACH64_SC_TOP_BOTTOM, ctx->sc_top_bottom);
+
+			DMAOUTREG(MACH64_CLR_CMP_CNTL, 0);
+			DMAOUTREG(MACH64_GUI_TRAJ_CNTL,
+				  (MACH64_DST_X_LEFT_TO_RIGHT |
+				   MACH64_DST_Y_TOP_TO_BOTTOM));
+
+			DMAOUTREG(MACH64_DP_PIX_WIDTH, ((depth_bpp << 0) |
+							(depth_bpp << 4) |
+							(depth_bpp << 8) |
+							(depth_bpp << 16) |
+							(depth_bpp << 28)));
+
+			DMAOUTREG(MACH64_DP_FRGD_CLR, clear_depth);
+			DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff);
+			DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D |
+						  MACH64_FRGD_MIX_S));
+			DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_FRGD_CLR |
+						  MACH64_FRGD_SRC_FRGD_CLR |
+						  MACH64_MONO_SRC_ONE));
+
+			DMAOUTREG(MACH64_DST_OFF_PITCH,
+				  dev_priv->depth_offset_pitch);
+			DMAOUTREG(MACH64_DST_X_Y, (y << 16) | x);
+			DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w);
+		}
+	}
+
+	DMAADVANCE(dev_priv, 1);
+
+	return 0;
+}
+
+static int mach64_dma_dispatch_swap(DRMFILE filp, drm_device_t * dev)
+{
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int nbox = sarea_priv->nbox;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	u32 fb_bpp;
+	int i;
+	DMALOCALS;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	switch (dev_priv->fb_bpp) {
+	case 16:
+		fb_bpp = MACH64_DATATYPE_RGB565;
+		break;
+	case 32:
+	default:
+		fb_bpp = MACH64_DATATYPE_ARGB8888;
+		break;
+	}
+
+	if (!nbox)
+		return 0;
+
+	DMAGETPTR(filp, dev_priv, 13 + nbox * 4);	/* returns on failure to get buffer */
+
+	DMAOUTREG(MACH64_Z_CNTL, 0);
+	DMAOUTREG(MACH64_SCALE_3D_CNTL, 0);
+
+	DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16));	/* no scissor */
+	DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16));
+
+	DMAOUTREG(MACH64_CLR_CMP_CNTL, 0);
+	DMAOUTREG(MACH64_GUI_TRAJ_CNTL, (MACH64_DST_X_LEFT_TO_RIGHT |
+					 MACH64_DST_Y_TOP_TO_BOTTOM));
+
+	DMAOUTREG(MACH64_DP_PIX_WIDTH, ((fb_bpp << 0) |
+					(fb_bpp << 4) |
+					(fb_bpp << 8) |
+					(fb_bpp << 16) | (fb_bpp << 28)));
+
+	DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff);
+	DMAOUTREG(MACH64_DP_MIX, (MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S));
+	DMAOUTREG(MACH64_DP_SRC, (MACH64_BKGD_SRC_BKGD_CLR |
+				  MACH64_FRGD_SRC_BLIT | MACH64_MONO_SRC_ONE));
+
+	DMAOUTREG(MACH64_SRC_OFF_PITCH, dev_priv->back_offset_pitch);
+	DMAOUTREG(MACH64_DST_OFF_PITCH, dev_priv->front_offset_pitch);
+
+	for (i = 0; i < nbox; i++) {
+		int x = pbox[i].x1;
+		int y = pbox[i].y1;
+		int w = pbox[i].x2 - x;
+		int h = pbox[i].y2 - y;
+
+		DRM_DEBUG("dispatch swap %d,%d-%d,%d\n",
+			  pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2);
+
+		DMAOUTREG(MACH64_SRC_WIDTH1, w);
+		DMAOUTREG(MACH64_SRC_Y_X, (x << 16) | y);
+		DMAOUTREG(MACH64_DST_Y_X, (x << 16) | y);
+		DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (h << 16) | w);
+
+	}
+
+	DMAADVANCE(dev_priv, 1);
+
+	if (dev_priv->driver_mode == MACH64_MODE_DMA_ASYNC) {
+		for (i = 0; i < MACH64_MAX_QUEUED_FRAMES - 1; i++) {
+			dev_priv->frame_ofs[i] = dev_priv->frame_ofs[i + 1];
+		}
+		dev_priv->frame_ofs[i] = GETRINGOFFSET();
+
+		dev_priv->sarea_priv->frames_queued++;
+	}
+
+	return 0;
+}
+
+static int mach64_do_get_frames_queued(drm_mach64_private_t * dev_priv)
+{
+	drm_mach64_descriptor_ring_t *ring = &dev_priv->ring;
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int i, start;
+	u32 head, tail, ofs;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	if (sarea_priv->frames_queued == 0)
+		return 0;
+
+	tail = ring->tail;
+	mach64_ring_tick(dev_priv, ring);
+	head = ring->head;
+
+	start = (MACH64_MAX_QUEUED_FRAMES -
+		 DRM_MIN(MACH64_MAX_QUEUED_FRAMES, sarea_priv->frames_queued));
+
+	if (head == tail) {
+		sarea_priv->frames_queued = 0;
+		for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) {
+			dev_priv->frame_ofs[i] = ~0;
+		}
+		return 0;
+	}
+
+	for (i = start; i < MACH64_MAX_QUEUED_FRAMES; i++) {
+		ofs = dev_priv->frame_ofs[i];
+		DRM_DEBUG("frame_ofs[%d] ofs: %d\n", i, ofs);
+		if (ofs == ~0 ||
+		    (head < tail && (ofs < head || ofs >= tail)) ||
+		    (head > tail && (ofs < head && ofs >= tail))) {
+			sarea_priv->frames_queued =
+			    (MACH64_MAX_QUEUED_FRAMES - 1) - i;
+			dev_priv->frame_ofs[i] = ~0;
+		}
+	}
+
+	return sarea_priv->frames_queued;
+}
+
+/* Copy and verify a client submited buffer.
+ * FIXME: Make an assembly optimized version
+ */
+static __inline__ int copy_from_user_vertex(u32 *to,
+					    const u32 __user *ufrom,
+					    unsigned long bytes)
+{
+	unsigned long n = bytes;	/* dwords remaining in buffer */
+	u32 *from, *orig_from;
+
+	from = drm_alloc(bytes, DRM_MEM_DRIVER);
+	if (from == NULL)
+		return DRM_ERR(ENOMEM);
+
+	if (DRM_COPY_FROM_USER(from, ufrom, bytes)) {
+		drm_free(from, bytes, DRM_MEM_DRIVER);
+		return DRM_ERR(EFAULT);
+	}
+	orig_from = from; /* we'll be modifying the "from" ptr, so save it */
+
+	n >>= 2;
+
+	while (n > 1) {
+		u32 data, reg, count;
+
+		data = *from++;
+
+		n--;
+
+		reg = le32_to_cpu(data);
+		count = (reg >> 16) + 1;
+		if (count <= n) {
+			n -= count;
+			reg &= 0xffff;
+
+			/* This is an exact match of Mach64's Setup Engine registers,
+			 * excluding SETUP_CNTL (1_C1).
+			 */
+			if ((reg >= 0x0190 && reg < 0x01c1) ||
+			    (reg >= 0x01ca && reg <= 0x01cf)) {
+				*to++ = data;
+				memcpy(to, from, count << 2);
+				from += count;
+				to += count;
+			} else {
+				DRM_ERROR("%s: Got bad command: 0x%04x\n",
+					  __FUNCTION__, reg);
+				drm_free(orig_from, bytes, DRM_MEM_DRIVER);
+				return DRM_ERR(EACCES);
+			}
+		} else {
+			DRM_ERROR
+			    ("%s: Got bad command count(=%u) dwords remaining=%lu\n",
+			     __FUNCTION__, count, n);
+			drm_free(orig_from, bytes, DRM_MEM_DRIVER);
+			return DRM_ERR(EINVAL);
+		}
+	}
+
+	drm_free(orig_from, bytes, DRM_MEM_DRIVER);
+	if (n == 0)
+		return 0;
+	else {
+		DRM_ERROR("%s: Bad buf->used(=%lu)\n", __FUNCTION__, bytes);
+		return DRM_ERR(EINVAL);
+	}
+}
+
+static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev,
+				      drm_mach64_vertex_t * vertex)
+{
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_buf_t *copy_buf;
+	void *buf = vertex->buf;
+	unsigned long used = vertex->used;
+	int ret = 0;
+	int i = 0;
+	int done = 0;
+	int verify_ret = 0;
+	DMALOCALS;
+
+	DRM_DEBUG("%s: buf=%p used=%lu nbox=%d\n",
+		  __FUNCTION__, buf, used, sarea_priv->nbox);
+
+	if (!used)
+		goto _vertex_done;
+
+	copy_buf = mach64_freelist_get(dev_priv);
+	if (copy_buf == NULL) {
+		DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__);
+		return DRM_ERR(EAGAIN);
+	}
+
+	verify_ret = copy_from_user_vertex(GETBUFPTR(copy_buf), buf, used);
+
+	if (verify_ret != 0) {
+		mach64_freelist_put(dev_priv, copy_buf);
+		goto _vertex_done;
+	}
+
+	copy_buf->used = used;
+
+	DMASETPTR(copy_buf);
+
+	if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) {
+		ret = mach64_emit_state(filp, dev_priv);
+		if (ret < 0)
+			return ret;
+	}
+
+	do {
+		/* Emit the next cliprect */
+		if (i < sarea_priv->nbox) {
+			ret = mach64_emit_cliprect(filp, dev_priv,
+						   &sarea_priv->boxes[i]);
+			if (ret < 0) {
+				/* failed to get buffer */
+				return ret;
+			} else if (ret != 0) {
+				/* null intersection with scissor */
+				continue;
+			}
+		}
+		if ((i >= sarea_priv->nbox - 1))
+			done = 1;
+
+		/* Add the buffer to the DMA queue */
+		DMAADVANCE(dev_priv, done);
+
+	} while (++i < sarea_priv->nbox);
+
+	if (!done) {
+		if (copy_buf->pending) {
+			DMADISCARDBUF();
+		} else {
+			/* This buffer wasn't used (no cliprects), so place it
+			 * back on the free list
+			 */
+			mach64_freelist_put(dev_priv, copy_buf);
+		}
+	}
+
+_vertex_done:
+	sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS;
+	sarea_priv->nbox = 0;
+
+	return verify_ret;
+}
+
+static __inline__ int copy_from_user_blit(u32 *to,
+					  const u32 __user *ufrom,
+					  unsigned long bytes)
+{
+	to = (u32 *)((char *)to + MACH64_HOSTDATA_BLIT_OFFSET);
+
+	if (DRM_COPY_FROM_USER(to, ufrom, bytes)) {
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev,
+				    drm_mach64_blit_t * blit)
+{
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	int dword_shift, dwords;
+	unsigned long used;
+	drm_buf_t *copy_buf;
+	int verify_ret = 0;
+	DMALOCALS;
+
+	/* The compiler won't optimize away a division by a variable,
+	 * even if the only legal values are powers of two.  Thus, we'll
+	 * use a shift instead.
+	 */
+	switch (blit->format) {
+	case MACH64_DATATYPE_ARGB8888:
+		dword_shift = 0;
+		break;
+	case MACH64_DATATYPE_ARGB1555:
+	case MACH64_DATATYPE_RGB565:
+	case MACH64_DATATYPE_VYUY422:
+	case MACH64_DATATYPE_YVYU422:
+	case MACH64_DATATYPE_ARGB4444:
+		dword_shift = 1;
+		break;
+	case MACH64_DATATYPE_CI8:
+	case MACH64_DATATYPE_RGB8:
+		dword_shift = 2;
+		break;
+	default:
+		DRM_ERROR("invalid blit format %d\n", blit->format);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* Set buf->used to the bytes of blit data based on the blit dimensions
+	 * and verify the size.  When the setup is emitted to the buffer with
+	 * the DMA* macros below, buf->used is incremented to include the bytes
+	 * used for setup as well as the blit data.
+	 */
+	dwords = (blit->width * blit->height) >> dword_shift;
+	used = dwords << 2;
+	if (used <= 0 ||
+	    used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) {
+		DRM_ERROR("Invalid blit size: %lu bytes\n", used);
+		return DRM_ERR(EINVAL);
+	}
+
+	copy_buf = mach64_freelist_get(dev_priv);
+	if (copy_buf == NULL) {
+		DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__);
+		return DRM_ERR(EAGAIN);
+	}
+
+	verify_ret = copy_from_user_blit(GETBUFPTR(copy_buf), blit->buf, used);
+
+	if (verify_ret != 0) {
+		mach64_freelist_put(dev_priv, copy_buf);
+		goto _blit_done;
+	}
+
+	copy_buf->used = used;
+
+	/* FIXME: Use a last buffer flag and reduce the state emitted for subsequent,
+	 * continuation buffers?
+	 */
+
+	/* Blit via BM_HOSTDATA (gui-master) - like HOST_DATA[0-15], but doesn't require
+	 * a register command every 16 dwords.  State setup is added at the start of the
+	 * buffer -- the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET
+	 */
+	DMASETPTR(copy_buf);
+
+	DMAOUTREG(MACH64_Z_CNTL, 0);
+	DMAOUTREG(MACH64_SCALE_3D_CNTL, 0);
+
+	DMAOUTREG(MACH64_SC_LEFT_RIGHT, 0 | (8191 << 16));	/* no scissor */
+	DMAOUTREG(MACH64_SC_TOP_BOTTOM, 0 | (16383 << 16));
+
+	DMAOUTREG(MACH64_CLR_CMP_CNTL, 0);	/* disable */
+	DMAOUTREG(MACH64_GUI_TRAJ_CNTL,
+		  MACH64_DST_X_LEFT_TO_RIGHT | MACH64_DST_Y_TOP_TO_BOTTOM);
+
+	DMAOUTREG(MACH64_DP_PIX_WIDTH, (blit->format << 0)	/* dst pix width */
+		  |(blit->format << 4)	/* composite pix width */
+		  |(blit->format << 8)	/* src pix width */
+		  |(blit->format << 16)	/* host data pix width */
+		  |(blit->format << 28)	/* scaler/3D pix width */
+	    );
+
+	DMAOUTREG(MACH64_DP_WRITE_MASK, 0xffffffff);	/* enable all planes */
+	DMAOUTREG(MACH64_DP_MIX, MACH64_BKGD_MIX_D | MACH64_FRGD_MIX_S);
+	DMAOUTREG(MACH64_DP_SRC,
+		  MACH64_BKGD_SRC_BKGD_CLR
+		  | MACH64_FRGD_SRC_HOST | MACH64_MONO_SRC_ONE);
+
+	DMAOUTREG(MACH64_DST_OFF_PITCH,
+		  (blit->pitch << 22) | (blit->offset >> 3));
+	DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x);
+	DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width);
+
+	DRM_DEBUG("%s: %lu bytes\n", __FUNCTION__, used);
+
+	/* Add the buffer to the queue */
+	DMAADVANCEHOSTDATA(dev_priv);
+
+_blit_done:
+	return verify_ret;
+}
+
+/* ================================================================
+ * IOCTL functions
+ */
+
+int mach64_dma_clear(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mach64_clear_t clear;
+	int ret;
+
+	DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(clear, (drm_mach64_clear_t *) data,
+				 sizeof(clear));
+
+	if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS;
+
+	ret = mach64_dma_dispatch_clear(filp, dev, clear.flags,
+					clear.x, clear.y, clear.w, clear.h,
+					clear.clear_color, clear.clear_depth);
+
+	/* Make sure we restore the 3D state next time.
+	 */
+	sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC);
+	return ret;
+}
+
+int mach64_dma_swap(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	int ret;
+
+	DRM_DEBUG("%s: pid=%d\n", __FUNCTION__, DRM_CURRENTPID);
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS;
+
+	ret = mach64_dma_dispatch_swap(filp, dev);
+
+	/* Make sure we restore the 3D state next time.
+	 */
+	sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT | MACH64_UPLOAD_MISC);
+	return ret;
+}
+
+int mach64_dma_vertex(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mach64_vertex_t vertex;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(vertex, (drm_mach64_vertex_t *) data,
+				 sizeof(vertex));
+
+	DRM_DEBUG("%s: pid=%d buf=%p used=%lu discard=%d\n",
+		  __FUNCTION__, DRM_CURRENTPID,
+		  vertex.buf, vertex.used, vertex.discard);
+
+	if (vertex.prim < 0 || vertex.prim > MACH64_PRIM_POLYGON) {
+		DRM_ERROR("buffer prim %d\n", vertex.prim);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (vertex.used > MACH64_BUFFER_SIZE || (vertex.used & 3) != 0) {
+		DRM_ERROR("Invalid vertex buffer size: %lu bytes\n",
+			  vertex.used);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS)
+		sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS;
+
+	return mach64_dma_dispatch_vertex(filp, dev, &vertex);
+}
+
+int mach64_dma_blit(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mach64_blit_t blit;
+	int ret;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(blit, (drm_mach64_blit_t *) data,
+				 sizeof(blit));
+
+	ret = mach64_dma_dispatch_blit(filp, dev, &blit);
+
+	/* Make sure we restore the 3D state next time.
+	 */
+	sarea_priv->dirty |= (MACH64_UPLOAD_CONTEXT |
+			      MACH64_UPLOAD_MISC | MACH64_UPLOAD_CLIPRECTS);
+
+	return ret;
+}
+
+int mach64_get_param(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	drm_mach64_getparam_t param;
+	int value;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(param, (drm_mach64_getparam_t *) data,
+				 sizeof(param));
+
+	switch (param.param) {
+	case MACH64_PARAM_FRAMES_QUEUED:
+		/* Needs lock since it calls mach64_ring_tick() */
+		LOCK_TEST_WITH_RETURN(dev, filp);
+		value = mach64_do_get_frames_queued(dev_priv);
+		break;
+	case MACH64_PARAM_IRQ_NR:
+		value = dev->irq;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
--- libdrm-2.3.0.orig/shared-core/via_irq.c
+++ libdrm-2.3.0/shared-core/via_irq.c
@@ -0,0 +1,393 @@
+/* via_irq.c
+ *
+ * Copyright 2004 BEAM Ltd.
+ * Copyright 2002 Tungsten Graphics, Inc.
+ * Copyright 2005 Thomas Hellstrom.
+ * 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
+ * BEAM LTD, 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.
+ *
+ * Authors:
+ *    Terry Barnaby <terry1@beam.ltd.uk>
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Thomas Hellstrom <unichrome@shipmail.org>
+ *
+ * This code provides standard DRM access to the Via Unichrome / Pro Vertical blank
+ * interrupt, as well as an infrastructure to handle other interrupts of the chip.
+ * The refresh rate is also calculated for video playback sync purposes.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+#define VIA_REG_INTERRUPT       0x200
+
+/* VIA_REG_INTERRUPT */
+#define VIA_IRQ_GLOBAL	  (1 << 31)
+#define VIA_IRQ_VBLANK_ENABLE   (1 << 19)
+#define VIA_IRQ_VBLANK_PENDING  (1 << 3)
+#define VIA_IRQ_HQV0_ENABLE     (1 << 11)
+#define VIA_IRQ_HQV1_ENABLE     (1 << 25)
+#define VIA_IRQ_HQV0_PENDING    (1 << 9)
+#define VIA_IRQ_HQV1_PENDING    (1 << 10)
+#define VIA_IRQ_DMA0_DD_ENABLE  (1 << 20)
+#define VIA_IRQ_DMA0_TD_ENABLE  (1 << 21)
+#define VIA_IRQ_DMA1_DD_ENABLE  (1 << 22)
+#define VIA_IRQ_DMA1_TD_ENABLE  (1 << 23)
+#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
+#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
+#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
+#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
+
+
+/*
+ * Device-specific IRQs go here. This type might need to be extended with
+ * the register if there are multiple IRQ control registers.
+ * Currently we activate the HQV interrupts of  Unichrome Pro group A. 
+ */
+
+static maskarray_t via_pro_group_a_irqs[] = {
+	{VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
+	 0x00000000 },
+	{VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
+	 0x00000000 },
+	{VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, 
+	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+	{VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+};
+static int via_num_pro_group_a =
+    sizeof(via_pro_group_a_irqs)/sizeof(maskarray_t);
+static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
+
+static maskarray_t via_unichrome_irqs[] = {
+	{VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, 
+	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+	{VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+	 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
+};
+static int via_num_unichrome = sizeof(via_unichrome_irqs)/sizeof(maskarray_t);
+static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
+
+
+static unsigned time_diff(struct timeval *now,struct timeval *then) 
+{
+    return (now->tv_usec >= then->tv_usec) ?
+	now->tv_usec - then->tv_usec :
+	1000000 - (then->tv_usec - now->tv_usec);
+}
+
+irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	u32 status;
+	int handled = 0;
+	struct timeval cur_vblank;
+	drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+	int i;
+
+	status = VIA_READ(VIA_REG_INTERRUPT);
+	if (status & VIA_IRQ_VBLANK_PENDING) {
+		atomic_inc(&dev->vbl_received);
+		if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
+#ifdef __linux__
+			do_gettimeofday(&cur_vblank);
+#else
+			microtime(&cur_vblank);
+#endif
+			if (dev_priv->last_vblank_valid) {
+				dev_priv->usec_per_vblank = 
+					time_diff(&cur_vblank,
+						  &dev_priv->last_vblank) >> 4;
+			}
+			dev_priv->last_vblank = cur_vblank;
+			dev_priv->last_vblank_valid = 1;
+		}
+		if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
+			DRM_DEBUG("US per vblank is: %u\n",
+				dev_priv->usec_per_vblank);
+		}
+		DRM_WAKEUP(&dev->vbl_queue);
+		drm_vbl_send_signals(dev);
+		handled = 1;
+	}
+	
+	for (i=0; i<dev_priv->num_irqs; ++i) {
+		if (status & cur_irq->pending_mask) {
+			atomic_inc( &cur_irq->irq_received );
+			DRM_WAKEUP( &cur_irq->irq_queue );
+			handled = 1;
+#ifdef VIA_HAVE_DMABLIT
+			if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) {
+				via_dmablit_handler(dev, 0, 1);
+			} else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) {
+				via_dmablit_handler(dev, 1, 1);
+			}
+#endif
+		}
+		cur_irq++;
+	}
+	
+	/* Acknowlege interrupts */
+	VIA_WRITE(VIA_REG_INTERRUPT, status);
+
+
+	if (handled)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+
+static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
+{
+	u32 status;
+
+	if (dev_priv) {
+		/* Acknowlege interrupts */
+		status = VIA_READ(VIA_REG_INTERRUPT);
+		VIA_WRITE(VIA_REG_INTERRUPT, status | 
+			  dev_priv->irq_pending_mask);
+	}
+}
+
+int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+{
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	DRM_DEBUG("viadrv_vblank_wait\n");
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	viadrv_acknowledge_irqs(dev_priv);
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks...
+	 */
+
+	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+		    (((cur_vblank = atomic_read(&dev->vbl_received)) -
+		      *sequence) <= (1 << 23)));
+	
+	*sequence = cur_vblank;
+	return ret;
+}
+
+static int
+via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
+		    unsigned int *sequence)
+{
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	unsigned int cur_irq_sequence;
+	drm_via_irq_t *cur_irq;
+	int ret = 0;
+	maskarray_t *masks;
+	int real_irq;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (irq >= drm_via_irq_num ) {
+		DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
+			  irq);
+		return DRM_ERR(EINVAL);
+	}
+		
+	real_irq = dev_priv->irq_map[irq];
+
+	if (real_irq < 0) {
+		DRM_ERROR("%s Video IRQ %d not available on this hardware.\n",
+			  __FUNCTION__, irq);
+		return DRM_ERR(EINVAL);
+	}
+
+	masks = dev_priv->irq_masks;
+	cur_irq = dev_priv->via_irqs + real_irq;
+
+	if (masks[real_irq][2] && !force_sequence) {
+		DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+			    ((VIA_READ(masks[irq][2]) & masks[irq][3]) == 
+			     masks[irq][4]));
+		cur_irq_sequence = atomic_read(&cur_irq->irq_received);
+	} else {
+		DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+			    (((cur_irq_sequence =
+			       atomic_read(&cur_irq->irq_received)) -
+			      *sequence) <= (1 << 23)));		
+	}
+	*sequence = cur_irq_sequence;
+	return ret;
+}
+
+
+/*
+ * drm_dma.h hooks
+ */
+
+void via_driver_irq_preinstall(drm_device_t * dev)
+{
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	u32 status;
+	drm_via_irq_t *cur_irq;
+	int i;
+
+	DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv);
+	if (dev_priv) {
+		cur_irq = dev_priv->via_irqs;
+
+		dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
+		dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
+
+		dev_priv->irq_masks = (dev_priv->pro_group_a) ?
+			via_pro_group_a_irqs : via_unichrome_irqs;
+		dev_priv->num_irqs = (dev_priv->pro_group_a) ?
+			via_num_pro_group_a : via_num_unichrome;
+		dev_priv->irq_map = (dev_priv->pro_group_a) ?
+			via_irqmap_pro_group_a : via_irqmap_unichrome;
+		
+		for(i=0; i < dev_priv->num_irqs; ++i) {
+			atomic_set(&cur_irq->irq_received, 0);
+			cur_irq->enable_mask = dev_priv->irq_masks[i][0]; 
+			cur_irq->pending_mask = dev_priv->irq_masks[i][1];
+			DRM_INIT_WAITQUEUE( &cur_irq->irq_queue );
+			dev_priv->irq_enable_mask |= cur_irq->enable_mask;
+			dev_priv->irq_pending_mask |= cur_irq->pending_mask;
+			cur_irq++;
+			
+			DRM_DEBUG("Initializing IRQ %d\n", i);
+		}
+			
+		dev_priv->last_vblank_valid = 0;
+
+		/* Clear VSync interrupt regs */
+		status = VIA_READ(VIA_REG_INTERRUPT);
+		VIA_WRITE(VIA_REG_INTERRUPT, status & 
+			  ~(dev_priv->irq_enable_mask));
+		
+		/* Clear bits if they're already high */
+		viadrv_acknowledge_irqs(dev_priv);
+	}
+}
+
+void via_driver_irq_postinstall(drm_device_t * dev)
+{
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	u32 status;
+
+	DRM_DEBUG("via_driver_irq_postinstall\n");
+	if (dev_priv) {
+		status = VIA_READ(VIA_REG_INTERRUPT);
+		VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+			  | dev_priv->irq_enable_mask);
+
+		/* Some magic, oh for some data sheets ! */
+
+		VIA_WRITE8(0x83d4, 0x11);
+		VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+		
+	}
+}
+
+void via_driver_irq_uninstall(drm_device_t * dev)
+{
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	u32 status;
+
+	DRM_DEBUG("driver_irq_uninstall)\n");
+	if (dev_priv) {
+
+		/* Some more magic, oh for some data sheets ! */
+
+		VIA_WRITE8(0x83d4, 0x11);
+		VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+
+		status = VIA_READ(VIA_REG_INTERRUPT);
+		VIA_WRITE(VIA_REG_INTERRUPT, status & 
+			  ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
+	}
+}
+
+int via_wait_irq(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_via_irqwait_t __user *argp = (void __user *)data;
+	drm_via_irqwait_t irqwait;
+	struct timeval now;
+	int ret = 0;
+	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+	drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+	int force_sequence;
+
+	if (!dev->irq)
+		return DRM_ERR(EINVAL);
+
+	DRM_COPY_FROM_USER_IOCTL(irqwait, argp, sizeof(irqwait));
+	if (irqwait.request.irq >= dev_priv->num_irqs) {
+		DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, 
+			  irqwait.request.irq);
+		return DRM_ERR(EINVAL);
+	}
+
+	cur_irq += irqwait.request.irq;
+
+	switch (irqwait.request.type & ~VIA_IRQ_FLAGS_MASK) {
+	case VIA_IRQ_RELATIVE:
+		irqwait.request.sequence += atomic_read(&cur_irq->irq_received);
+		irqwait.request.type &= ~_DRM_VBLANK_RELATIVE;
+	case VIA_IRQ_ABSOLUTE:
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if (irqwait.request.type & VIA_IRQ_SIGNAL) {
+		DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n", 
+			  __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	force_sequence = (irqwait.request.type & VIA_IRQ_FORCE_SEQUENCE);
+
+	ret = via_driver_irq_wait(dev, irqwait.request.irq, force_sequence,
+				  &irqwait.request.sequence);
+#ifdef __linux__
+	do_gettimeofday(&now);
+#else
+	microtime(&now);
+#endif
+	irqwait.reply.tval_sec = now.tv_sec;
+	irqwait.reply.tval_usec = now.tv_usec;
+
+	DRM_COPY_TO_USER_IOCTL(argp, irqwait, sizeof(irqwait));
+
+	return ret;
+}
--- libdrm-2.3.0.orig/shared-core/mga_irq.c
+++ libdrm-2.3.0/shared-core/mga_irq.c
@@ -0,0 +1,150 @@
+/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ */
+/*
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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
+ * 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+
+irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+	int status;
+	int handled = 0;
+
+	status = MGA_READ(MGA_STATUS);
+
+	/* VBLANK interrupt */
+	if (status & MGA_VLINEPEN) {
+		MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
+		atomic_inc(&dev->vbl_received);
+		DRM_WAKEUP(&dev->vbl_queue);
+		drm_vbl_send_signals(dev);
+		handled = 1;
+	}
+
+	/* SOFTRAP interrupt */
+	if (status & MGA_SOFTRAPEN) {
+		const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
+		const u32 prim_end   = MGA_READ(MGA_PRIMEND);
+
+
+		MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
+
+		/* In addition to clearing the interrupt-pending bit, we
+		 * have to write to MGA_PRIMEND to re-start the DMA operation.
+		 */
+		if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) {
+			MGA_WRITE(MGA_PRIMEND, prim_end);
+		}
+
+		atomic_inc(&dev_priv->last_fence_retired);
+		DRM_WAKEUP(&dev_priv->fence_queue);
+		handled = 1;
+	}
+
+	if ( handled ) {
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+int mga_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+{
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks...
+	 */
+	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+		    (((cur_vblank = atomic_read(&dev->vbl_received))
+		      - *sequence) <= (1 << 23)));
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+int mga_driver_fence_wait(drm_device_t * dev, unsigned int *sequence)
+{
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+	unsigned int cur_fence;
+	int ret = 0;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using fences.
+	 */
+	DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
+		    (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
+		      - *sequence) <= (1 << 23)));
+
+	*sequence = cur_fence;
+
+	return ret;
+}
+
+void mga_driver_irq_preinstall(drm_device_t * dev)
+{
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+	/* Disable *all* interrupts */
+	MGA_WRITE(MGA_IEN, 0);
+	/* Clear bits if they're already high */
+	MGA_WRITE(MGA_ICLEAR, ~0);
+}
+
+void mga_driver_irq_postinstall(drm_device_t * dev)
+{
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+	DRM_INIT_WAITQUEUE( &dev_priv->fence_queue );
+
+	/* Turn on vertical blank interrupt and soft trap interrupt. */
+	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+}
+
+void mga_driver_irq_uninstall(drm_device_t * dev)
+{
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+	if (!dev_priv)
+		return;
+
+	/* Disable *all* interrupts */
+	MGA_WRITE(MGA_IEN, 0);
+	
+	dev->irq_enabled = 0;
+}
--- libdrm-2.3.0.orig/shared-core/radeon_mem.c
+++ libdrm-2.3.0/shared-core/radeon_mem.c
@@ -0,0 +1,314 @@
+/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */
+/*
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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
+ * 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+/* Very simple allocator for GART memory, working on a static range
+ * already mapped into each client's address space.
+ */
+
+static struct mem_block *split_block(struct mem_block *p, int start, int size,
+				     DRMFILE filp)
+{
+	/* Maybe cut off the start of an existing block */
+	if (start > p->start) {
+		struct mem_block *newblock =
+		    drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+		if (!newblock)
+			goto out;
+		newblock->start = start;
+		newblock->size = p->size - (start - p->start);
+		newblock->filp = NULL;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size -= newblock->size;
+		p = newblock;
+	}
+
+	/* Maybe cut off the end of an existing block */
+	if (size < p->size) {
+		struct mem_block *newblock =
+		    drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+		if (!newblock)
+			goto out;
+		newblock->start = start + size;
+		newblock->size = p->size - size;
+		newblock->filp = NULL;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size = size;
+	}
+
+      out:
+	/* Our block is in the middle */
+	p->filp = filp;
+	return p;
+}
+
+static struct mem_block *alloc_block(struct mem_block *heap, int size,
+				     int align2, DRMFILE filp)
+{
+	struct mem_block *p;
+	int mask = (1 << align2) - 1;
+
+	list_for_each(p, heap) {
+		int start = (p->start + mask) & ~mask;
+		if (p->filp == 0 && start + size <= p->start + p->size)
+			return split_block(p, start, size, filp);
+	}
+
+	return NULL;
+}
+
+static struct mem_block *find_block(struct mem_block *heap, int start)
+{
+	struct mem_block *p;
+
+	list_for_each(p, heap)
+		if (p->start == start)
+			return p;
+
+	return NULL;
+}
+
+static void free_block(struct mem_block *p)
+{
+	p->filp = NULL;
+
+	/* Assumes a single contiguous range.  Needs a special filp in
+	 * 'heap' to stop it being subsumed.
+	 */
+	if (p->next->filp == 0) {
+		struct mem_block *q = p->next;
+		p->size += q->size;
+		p->next = q->next;
+		p->next->prev = p;
+		drm_free(q, sizeof(*q), DRM_MEM_BUFS);
+	}
+
+	if (p->prev->filp == 0) {
+		struct mem_block *q = p->prev;
+		q->size += p->size;
+		q->next = p->next;
+		q->next->prev = q;
+		drm_free(p, sizeof(*q), DRM_MEM_BUFS);
+	}
+}
+
+/* Initialize.  How to check for an uninitialized heap?
+ */
+static int init_heap(struct mem_block **heap, int start, int size)
+{
+	struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
+
+	if (!blocks)
+		return DRM_ERR(ENOMEM);
+
+	*heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
+	if (!*heap) {
+		drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
+		return DRM_ERR(ENOMEM);
+	}
+
+	blocks->start = start;
+	blocks->size = size;
+	blocks->filp = NULL;
+	blocks->next = blocks->prev = *heap;
+
+	memset(*heap, 0, sizeof(**heap));
+	(*heap)->filp = (DRMFILE) - 1;
+	(*heap)->next = (*heap)->prev = blocks;
+	return 0;
+}
+
+/* Free all blocks associated with the releasing file.
+ */
+void radeon_mem_release(DRMFILE filp, struct mem_block *heap)
+{
+	struct mem_block *p;
+
+	if (!heap || !heap->next)
+		return;
+
+	list_for_each(p, heap) {
+		if (p->filp == filp)
+			p->filp = NULL;
+	}
+
+	/* Assumes a single contiguous range.  Needs a special filp in
+	 * 'heap' to stop it being subsumed.
+	 */
+	list_for_each(p, heap) {
+		while (p->filp == 0 && p->next->filp == 0) {
+			struct mem_block *q = p->next;
+			p->size += q->size;
+			p->next = q->next;
+			p->next->prev = p;
+			drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+		}
+	}
+}
+
+/* Shutdown.
+ */
+void radeon_mem_takedown(struct mem_block **heap)
+{
+	struct mem_block *p;
+
+	if (!*heap)
+		return;
+
+	for (p = (*heap)->next; p != *heap;) {
+		struct mem_block *q = p;
+		p = p->next;
+		drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+	}
+
+	drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER);
+	*heap = NULL;
+}
+
+/* IOCTL HANDLERS */
+
+static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region)
+{
+	switch (region) {
+	case RADEON_MEM_REGION_GART:
+		return &dev_priv->gart_heap;
+	case RADEON_MEM_REGION_FB:
+		return &dev_priv->fb_heap;
+	default:
+		return NULL;
+	}
+}
+
+int radeon_mem_alloc(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_mem_alloc_t alloc;
+	struct mem_block *block, **heap;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_mem_alloc_t __user *) data,
+				 sizeof(alloc));
+
+	heap = get_heap(dev_priv, alloc.region);
+	if (!heap || !*heap)
+		return DRM_ERR(EFAULT);
+
+	/* Make things easier on ourselves: all allocations at least
+	 * 4k aligned.
+	 */
+	if (alloc.alignment < 12)
+		alloc.alignment = 12;
+
+	block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
+
+	if (!block)
+		return DRM_ERR(ENOMEM);
+
+	if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+int radeon_mem_free(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_mem_free_t memfree;
+	struct mem_block *block, **heap;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data,
+				 sizeof(memfree));
+
+	heap = get_heap(dev_priv, memfree.region);
+	if (!heap || !*heap)
+		return DRM_ERR(EFAULT);
+
+	block = find_block(*heap, memfree.region_offset);
+	if (!block)
+		return DRM_ERR(EFAULT);
+
+	if (block->filp != filp)
+		return DRM_ERR(EPERM);
+
+	free_block(block);
+	return 0;
+}
+
+int radeon_mem_init_heap(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_mem_init_heap_t initheap;
+	struct mem_block **heap;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(initheap,
+				 (drm_radeon_mem_init_heap_t __user *) data,
+				 sizeof(initheap));
+
+	heap = get_heap(dev_priv, initheap.region);
+	if (!heap)
+		return DRM_ERR(EFAULT);
+
+	if (*heap) {
+		DRM_ERROR("heap already initialized?");
+		return DRM_ERR(EFAULT);
+	}
+
+	return init_heap(heap, initheap.start, initheap.size);
+}
--- libdrm-2.3.0.orig/shared-core/radeon_irq.c
+++ libdrm-2.3.0/shared-core/radeon_irq.c
@@ -0,0 +1,244 @@
+/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
+/*
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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
+ * 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Michel D�zer <michel@daenzer.net>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
+					      u32 mask)
+{
+	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+	if (irqs)
+		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+	return irqs;
+}
+
+/* Interrupts - Used for device synchronization and flushing in the
+ * following circumstances:
+ *
+ * - Exclusive FB access with hw idle:
+ *    - Wait for GUI Idle (?) interrupt, then do normal flush.
+ *
+ * - Frame throttling, NV_fence:
+ *    - Drop marker irq's into command stream ahead of time.
+ *    - Wait on irq's with lock *not held*
+ *    - Check each for termination condition
+ *
+ * - Internally in cp_getbuffer, etc:
+ *    - as above, but wait with lock held???
+ *
+ * NOTE: These functions are misleadingly named -- the irq's aren't
+ * tied to dma at all, this is just a hangover from dri prehistory.
+ */
+
+irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_radeon_private_t *dev_priv =
+	    (drm_radeon_private_t *) dev->dev_private;
+	u32 stat;
+
+	/* Only consider the bits we're interested in - others could be used
+	 * outside the DRM
+	 */
+	stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+						  RADEON_CRTC_VBLANK_STAT));
+	if (!stat)
+		return IRQ_NONE;
+
+	/* SW interrupt */
+	if (stat & RADEON_SW_INT_TEST) {
+		DRM_WAKEUP(&dev_priv->swi_queue);
+	}
+
+	/* VBLANK interrupt */
+	if (stat & RADEON_CRTC_VBLANK_STAT) {
+		atomic_inc(&dev->vbl_received);
+		DRM_WAKEUP(&dev->vbl_queue);
+		drm_vbl_send_signals(dev);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int radeon_emit_irq(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	unsigned int ret;
+	RING_LOCALS;
+
+	atomic_inc(&dev_priv->swi_emitted);
+	ret = atomic_read(&dev_priv->swi_emitted);
+
+	BEGIN_RING(4);
+	OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
+	OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
+	ADVANCE_RING();
+	COMMIT_RING();
+
+	return ret;
+}
+
+static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
+{
+	drm_radeon_private_t *dev_priv =
+	    (drm_radeon_private_t *) dev->dev_private;
+	int ret = 0;
+
+	if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
+		return 0;
+
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+	DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
+		    RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
+
+	return ret;
+}
+
+int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+{
+	drm_radeon_private_t *dev_priv =
+	    (drm_radeon_private_t *) dev->dev_private;
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
+
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks...
+	 */
+	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+		    (((cur_vblank = atomic_read(&dev->vbl_received))
+		      - *sequence) <= (1 << 23)));
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+/* Needs the lock as it touches the ring.
+ */
+int radeon_irq_emit(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_irq_emit_t emit;
+	int result;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(emit, (drm_radeon_irq_emit_t __user *) data,
+				 sizeof(emit));
+
+	result = radeon_emit_irq(dev);
+
+	if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+/* Doesn't need the hardware lock.
+ */
+int radeon_irq_wait(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_irq_wait_t irqwait;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_radeon_irq_wait_t __user *) data,
+				 sizeof(irqwait));
+
+	return radeon_wait_irq(dev, irqwait.irq_seq);
+}
+
+/* drm_dma.h hooks
+*/
+void radeon_driver_irq_preinstall(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv =
+	    (drm_radeon_private_t *) dev->dev_private;
+
+	/* Disable *all* interrupts */
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+
+	/* Clear bits if they're already high */
+	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+					   RADEON_CRTC_VBLANK_STAT));
+}
+
+void radeon_driver_irq_postinstall(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv =
+	    (drm_radeon_private_t *) dev->dev_private;
+
+	atomic_set(&dev_priv->swi_emitted, 0);
+	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
+
+	/* Turn on SW and VBL ints */
+	RADEON_WRITE(RADEON_GEN_INT_CNTL,
+		     RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
+}
+
+void radeon_driver_irq_uninstall(drm_device_t * dev)
+{
+	drm_radeon_private_t *dev_priv =
+	    (drm_radeon_private_t *) dev->dev_private;
+	if (!dev_priv)
+		return;
+
+	/* Disable *all* interrupts */
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+}
--- libdrm-2.3.0.orig/shared-core/tdfx_drv.h
+++ libdrm-2.3.0/shared-core/tdfx_drv.h
@@ -0,0 +1,47 @@
+/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-
+ * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
+ */
+/*
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * VA LINUX SYSTEMS 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.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __TDFX_H__
+#define __TDFX_H__
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR		"VA Linux Systems Inc."
+
+#define DRIVER_NAME		"tdfx"
+#define DRIVER_DESC		"3dfx Banshee/Voodoo3+"
+#define DRIVER_DATE		"20010216"
+
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	0
+
+#endif
--- libdrm-2.3.0.orig/shared-core/via_ds.c
+++ libdrm-2.3.0/shared-core/via_ds.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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
+ * VIA, S3 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 "drmP.h"
+
+#include "via_ds.h"
+extern unsigned int VIA_DEBUG;
+
+set_t *via_setInit(void)
+{
+	int i;
+	set_t *set;
+	set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
+	for (i = 0; i < SET_SIZE; i++) {
+		set->list[i].free_next = i + 1;
+		set->list[i].alloc_next = -1;
+	}
+	set->list[SET_SIZE - 1].free_next = -1;
+	set->free = 0;
+	set->alloc = -1;
+	set->trace = -1;
+	return set;
+}
+
+int via_setAdd(set_t * set, ITEM_TYPE item)
+{
+	int free = set->free;
+	if (free != -1) {
+		set->list[free].val = item;
+		set->free = set->list[free].free_next;
+	} else {
+		return 0;
+	}
+	set->list[free].alloc_next = set->alloc;
+	set->alloc = free;
+	set->list[free].free_next = -1;
+	return 1;
+}
+
+int via_setDel(set_t * set, ITEM_TYPE item)
+{
+	int alloc = set->alloc;
+	int prev = -1;
+
+	while (alloc != -1) {
+		if (set->list[alloc].val == item) {
+			if (prev != -1)
+				set->list[prev].alloc_next =
+				    set->list[alloc].alloc_next;
+			else
+				set->alloc = set->list[alloc].alloc_next;
+			break;
+		}
+		prev = alloc;
+		alloc = set->list[alloc].alloc_next;
+	}
+
+	if (alloc == -1)
+		return 0;
+
+	set->list[alloc].free_next = set->free;
+	set->free = alloc;
+	set->list[alloc].alloc_next = -1;
+
+	return 1;
+}
+
+/* setFirst -> setAdd -> setNext is wrong */
+
+int via_setFirst(set_t * set, ITEM_TYPE * item)
+{
+	if (set->alloc == -1)
+		return 0;
+
+	*item = set->list[set->alloc].val;
+	set->trace = set->list[set->alloc].alloc_next;
+
+	return 1;
+}
+
+int via_setNext(set_t * set, ITEM_TYPE * item)
+{
+	if (set->trace == -1)
+		return 0;
+
+	*item = set->list[set->trace].val;
+	set->trace = set->list[set->trace].alloc_next;
+
+	return 1;
+}
+
+int via_setDestroy(set_t * set)
+{
+	drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
+
+	return 1;
+}
+
+#define ISFREE(bptr) ((bptr)->free)
+
+#define fprintf(fmt, arg...) do{}while(0)
+
+memHeap_t *via_mmInit(int ofs, int size)
+{
+	PMemBlock blocks;
+
+	if (size <= 0)
+		return NULL;
+
+	blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
+
+	if (blocks) {
+		blocks->ofs = ofs;
+		blocks->size = size;
+		blocks->free = 1;
+		return (memHeap_t *) blocks;
+	} else
+		return NULL;
+}
+
+static TMemBlock *SliceBlock(TMemBlock * p,
+			     int startofs, int size,
+			     int reserved, int alignment)
+{
+	TMemBlock *newblock;
+
+	/* break left */
+	if (startofs > p->ofs) {
+		newblock =
+		    (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+					     DRM_MEM_DRIVER);
+		newblock->ofs = startofs;
+		newblock->size = p->size - (startofs - p->ofs);
+		newblock->free = 1;
+		newblock->next = p->next;
+		p->size -= newblock->size;
+		p->next = newblock;
+		p = newblock;
+	}
+
+	/* break right */
+	if (size < p->size) {
+		newblock =
+		    (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+					     DRM_MEM_DRIVER);
+		newblock->ofs = startofs + size;
+		newblock->size = p->size - size;
+		newblock->free = 1;
+		newblock->next = p->next;
+		p->size = size;
+		p->next = newblock;
+	}
+
+	/* p = middle block */
+	p->align = alignment;
+	p->free = 0;
+	p->reserved = reserved;
+	return p;
+}
+
+PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
+			 int startSearch)
+{
+	int mask, startofs, endofs;
+	TMemBlock *p;
+
+	if (!heap || align2 < 0 || size <= 0)
+		return NULL;
+
+	mask = (1 << align2) - 1;
+	startofs = 0;
+	p = (TMemBlock *) heap;
+
+	while (p) {
+		if (ISFREE(p)) {
+			startofs = (p->ofs + mask) & ~mask;
+
+			if (startofs < startSearch)
+				startofs = startSearch;
+
+			endofs = startofs + size;
+
+			if (endofs <= (p->ofs + p->size))
+				break;
+		}
+
+		p = p->next;
+	}
+
+	if (!p)
+		return NULL;
+
+	p = SliceBlock(p, startofs, size, 0, mask + 1);
+	p->heap = heap;
+
+	return p;
+}
+
+static __inline__ int Join2Blocks(TMemBlock * p)
+{
+	if (p->free && p->next && p->next->free) {
+		TMemBlock *q = p->next;
+		p->size += q->size;
+		p->next = q->next;
+		drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+int via_mmFreeMem(PMemBlock b)
+{
+	TMemBlock *p, *prev;
+
+	if (!b)
+		return 0;
+
+	if (!b->heap) {
+		fprintf(stderr, "no heap\n");
+
+		return -1;
+	}
+
+	p = b->heap;
+	prev = NULL;
+
+	while (p && p != b) {
+		prev = p;
+		p = p->next;
+	}
+
+	if (!p || p->free || p->reserved) {
+		if (!p)
+			fprintf(stderr, "block not found in heap\n");
+		else if (p->free)
+			fprintf(stderr, "block already free\n");
+		else
+			fprintf(stderr, "block is reserved\n");
+
+		return -1;
+	}
+
+	p->free = 1;
+	Join2Blocks(p);
+
+	if (prev)
+		Join2Blocks(prev);
+
+	return 0;
+}
--- libdrm-2.3.0.orig/shared-core/i915_mem.c
+++ libdrm-2.3.0/shared-core/i915_mem.c
@@ -0,0 +1,397 @@
+/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
+ */
+/*
+ * 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.
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/* This memory manager is integrated into the global/local lru
+ * mechanisms used by the clients.  Specifically, it operates by
+ * setting the 'in_use' fields of the global LRU to indicate whether
+ * this region is privately allocated to a client.
+ *
+ * This does require the client to actually respect that field.
+ *
+ * Currently no effort is made to allocate 'private' memory in any
+ * clever way - the LRU information isn't used to determine which
+ * block to allocate, and the ring is drained prior to allocations --
+ * in other words allocation is expensive.
+ */
+static void mark_block(drm_device_t * dev, struct mem_block *p, int in_use)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_tex_region_t *list;
+	unsigned shift, nr;
+	unsigned start;
+	unsigned end;
+	unsigned i;
+	int age;
+
+	shift = dev_priv->tex_lru_log_granularity;
+	nr = I915_NR_TEX_REGIONS;
+
+	start = p->start >> shift;
+	end = (p->start + p->size - 1) >> shift;
+
+	age = ++sarea_priv->texAge;
+	list = sarea_priv->texList;
+
+	/* Mark the regions with the new flag and update their age.  Move
+	 * them to head of list to preserve LRU semantics.
+	 */
+	for (i = start; i <= end; i++) {
+		list[i].in_use = in_use;
+		list[i].age = age;
+
+		/* remove_from_list(i)
+		 */
+		list[(unsigned)list[i].next].prev = list[i].prev;
+		list[(unsigned)list[i].prev].next = list[i].next;
+
+		/* insert_at_head(list, i)
+		 */
+		list[i].prev = nr;
+		list[i].next = list[nr].next;
+		list[(unsigned)list[nr].next].prev = i;
+		list[nr].next = i;
+	}
+}
+
+/* Very simple allocator for agp memory, working on a static range
+ * already mapped into each client's address space.
+ */
+
+static struct mem_block *split_block(struct mem_block *p, int start, int size,
+				     DRMFILE filp)
+{
+	/* Maybe cut off the start of an existing block */
+	if (start > p->start) {
+		struct mem_block *newblock =
+		    drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+		if (!newblock)
+			goto out;
+		newblock->start = start;
+		newblock->size = p->size - (start - p->start);
+		newblock->filp = NULL;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size -= newblock->size;
+		p = newblock;
+	}
+
+	/* Maybe cut off the end of an existing block */
+	if (size < p->size) {
+		struct mem_block *newblock =
+		    drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+		if (!newblock)
+			goto out;
+		newblock->start = start + size;
+		newblock->size = p->size - size;
+		newblock->filp = NULL;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size = size;
+	}
+
+      out:
+	/* Our block is in the middle */
+	p->filp = filp;
+	return p;
+}
+
+static struct mem_block *alloc_block(struct mem_block *heap, int size,
+				     int align2, DRMFILE filp)
+{
+	struct mem_block *p;
+	int mask = (1 << align2) - 1;
+
+	for (p = heap->next; p != heap; p = p->next) {
+		int start = (p->start + mask) & ~mask;
+		if (p->filp == NULL && start + size <= p->start + p->size)
+			return split_block(p, start, size, filp);
+	}
+
+	return NULL;
+}
+
+static struct mem_block *find_block(struct mem_block *heap, int start)
+{
+	struct mem_block *p;
+
+	for (p = heap->next; p != heap; p = p->next)
+		if (p->start == start)
+			return p;
+
+	return NULL;
+}
+
+static void free_block(struct mem_block *p)
+{
+	p->filp = NULL;
+
+	/* Assumes a single contiguous range.  Needs a special filp in
+	 * 'heap' to stop it being subsumed.
+	 */
+	if (p->next->filp == NULL) {
+		struct mem_block *q = p->next;
+		p->size += q->size;
+		p->next = q->next;
+		p->next->prev = p;
+		drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+	}
+
+	if (p->prev->filp == NULL) {
+		struct mem_block *q = p->prev;
+		q->size += p->size;
+		q->next = p->next;
+		q->next->prev = q;
+		drm_free(p, sizeof(*q), DRM_MEM_BUFLISTS);
+	}
+}
+
+/* Initialize.  How to check for an uninitialized heap?
+ */
+static int init_heap(struct mem_block **heap, int start, int size)
+{
+	struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFLISTS);
+
+	if (!blocks)
+		return -ENOMEM;
+
+	*heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFLISTS);
+	if (!*heap) {
+		drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFLISTS);
+		return -ENOMEM;
+	}
+
+	blocks->start = start;
+	blocks->size = size;
+	blocks->filp = NULL;
+	blocks->next = blocks->prev = *heap;
+
+	memset(*heap, 0, sizeof(**heap));
+	(*heap)->filp = (DRMFILE) - 1;
+	(*heap)->next = (*heap)->prev = blocks;
+	return 0;
+}
+
+/* Free all blocks associated with the releasing file.
+ */
+void i915_mem_release(drm_device_t * dev, DRMFILE filp, struct mem_block *heap)
+{
+	struct mem_block *p;
+
+	if (!heap || !heap->next)
+		return;
+
+	for (p = heap->next; p != heap; p = p->next) {
+		if (p->filp == filp) {
+			p->filp = NULL;
+			mark_block(dev, p, 0);
+		}
+	}
+
+	/* Assumes a single contiguous range.  Needs a special filp in
+	 * 'heap' to stop it being subsumed.
+	 */
+	for (p = heap->next; p != heap; p = p->next) {
+		while (p->filp == NULL && p->next->filp == NULL) {
+			struct mem_block *q = p->next;
+			p->size += q->size;
+			p->next = q->next;
+			p->next->prev = p;
+			drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+		}
+	}
+}
+
+/* Shutdown.
+ */
+void i915_mem_takedown(struct mem_block **heap)
+{
+	struct mem_block *p;
+
+	if (!*heap)
+		return;
+
+	for (p = (*heap)->next; p != *heap;) {
+		struct mem_block *q = p;
+		p = p->next;
+		drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+	}
+
+	drm_free(*heap, sizeof(**heap), DRM_MEM_BUFLISTS);
+	*heap = NULL;
+}
+
+static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
+{
+	switch (region) {
+	case I915_MEM_REGION_AGP:
+		return &dev_priv->agp_heap;
+	default:
+		return NULL;
+	}
+}
+
+/* IOCTL HANDLERS */
+
+int i915_mem_alloc(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_mem_alloc_t alloc;
+	struct mem_block *block, **heap;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(alloc, (drm_i915_mem_alloc_t __user *) data,
+				 sizeof(alloc));
+
+	heap = get_heap(dev_priv, alloc.region);
+	if (!heap || !*heap)
+		return DRM_ERR(EFAULT);
+
+	/* Make things easier on ourselves: all allocations at least
+	 * 4k aligned.
+	 */
+	if (alloc.alignment < 12)
+		alloc.alignment = 12;
+
+	block = alloc_block(*heap, alloc.size, alloc.alignment, filp);
+
+	if (!block)
+		return DRM_ERR(ENOMEM);
+
+	mark_block(dev, block, 1);
+
+	if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) {
+		DRM_ERROR("copy_to_user\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+int i915_mem_free(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_mem_free_t memfree;
+	struct mem_block *block, **heap;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(memfree, (drm_i915_mem_free_t __user *) data,
+				 sizeof(memfree));
+
+	heap = get_heap(dev_priv, memfree.region);
+	if (!heap || !*heap)
+		return DRM_ERR(EFAULT);
+
+	block = find_block(*heap, memfree.region_offset);
+	if (!block)
+		return DRM_ERR(EFAULT);
+
+	if (block->filp != filp)
+		return DRM_ERR(EPERM);
+
+	mark_block(dev, block, 0);
+	free_block(block);
+	return 0;
+}
+
+int i915_mem_init_heap(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_mem_init_heap_t initheap;
+	struct mem_block **heap;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(initheap,
+				 (drm_i915_mem_init_heap_t __user *) data,
+				 sizeof(initheap));
+
+	heap = get_heap(dev_priv, initheap.region);
+	if (!heap)
+		return DRM_ERR(EFAULT);
+
+	if (*heap) {
+		DRM_ERROR("heap already initialized?");
+		return DRM_ERR(EFAULT);
+	}
+
+	return init_heap(heap, initheap.start, initheap.size);
+}
+
+int i915_mem_destroy_heap( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_mem_destroy_heap_t destroyheap;
+	struct mem_block **heap;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( destroyheap, (drm_i915_mem_destroy_heap_t *)data,
+				  sizeof(destroyheap) );
+
+	heap = get_heap( dev_priv, destroyheap.region );
+	if (!heap) {
+		DRM_ERROR("get_heap failed");
+		return DRM_ERR(EFAULT);
+	}
+	
+	if (!*heap) {
+		DRM_ERROR("heap not initialized?");
+		return DRM_ERR(EFAULT);
+	}
+
+	i915_mem_takedown( heap );
+	return 0;
+}
--- libdrm-2.3.0.orig/shared-core/r128_drv.h
+++ libdrm-2.3.0/shared-core/r128_drv.h
@@ -0,0 +1,520 @@
+/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
+ * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
+ */
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * 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.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Michel D�zer <daenzerm@student.ethz.ch>
+ */
+
+#ifndef __R128_DRV_H__
+#define __R128_DRV_H__
+
+/* General customization:
+ */
+#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
+
+#define DRIVER_NAME		"r128"
+#define DRIVER_DESC		"ATI Rage 128"
+#define DRIVER_DATE		"20030725"
+
+/* Interface history:
+ *
+ * ??  - ??
+ * 2.4 - Add support for ycbcr textures (no new ioctls)
+ * 2.5 - Add FLIP ioctl, disable FULLSCREEN.
+ */
+#define DRIVER_MAJOR		2
+#define DRIVER_MINOR		5
+#define DRIVER_PATCHLEVEL	0
+
+#define GET_RING_HEAD(dev_priv)		R128_READ( R128_PM4_BUFFER_DL_RPTR )
+
+typedef struct drm_r128_freelist {
+	unsigned int age;
+	drm_buf_t *buf;
+	struct drm_r128_freelist *next;
+	struct drm_r128_freelist *prev;
+} drm_r128_freelist_t;
+
+typedef struct drm_r128_ring_buffer {
+	u32 *start;
+	u32 *end;
+	int size;
+	int size_l2qw;
+
+	u32 tail;
+	u32 tail_mask;
+	int space;
+
+	int high_mark;
+} drm_r128_ring_buffer_t;
+
+typedef struct drm_r128_private {
+	drm_r128_ring_buffer_t ring;
+	drm_r128_sarea_t *sarea_priv;
+
+	int cce_mode;
+	int cce_fifo_size;
+	int cce_running;
+
+	drm_r128_freelist_t *head;
+	drm_r128_freelist_t *tail;
+
+	int usec_timeout;
+	int is_pci;
+	unsigned long cce_buffers_offset;
+
+	atomic_t idle_count;
+
+	int page_flipping;
+	int current_page;
+	u32 crtc_offset;
+	u32 crtc_offset_cntl;
+
+	u32 color_fmt;
+	unsigned int front_offset;
+	unsigned int front_pitch;
+	unsigned int back_offset;
+	unsigned int back_pitch;
+
+	u32 depth_fmt;
+	unsigned int depth_offset;
+	unsigned int depth_pitch;
+	unsigned int span_offset;
+
+	u32 front_pitch_offset_c;
+	u32 back_pitch_offset_c;
+	u32 depth_pitch_offset_c;
+	u32 span_pitch_offset_c;
+
+	drm_local_map_t *sarea;
+	drm_local_map_t *mmio;
+	drm_local_map_t *cce_ring;
+	drm_local_map_t *ring_rptr;
+	drm_local_map_t *agp_textures;
+	drm_ati_pcigart_info gart_info;
+} drm_r128_private_t;
+
+typedef struct drm_r128_buf_priv {
+	u32 age;
+	int prim;
+	int discard;
+	int dispatched;
+	drm_r128_freelist_t *list_entry;
+} drm_r128_buf_priv_t;
+
+extern drm_ioctl_desc_t r128_ioctls[];
+extern int r128_max_ioctl;
+
+				/* r128_cce.c */
+extern int r128_cce_init(DRM_IOCTL_ARGS);
+extern int r128_cce_start(DRM_IOCTL_ARGS);
+extern int r128_cce_stop(DRM_IOCTL_ARGS);
+extern int r128_cce_reset(DRM_IOCTL_ARGS);
+extern int r128_cce_idle(DRM_IOCTL_ARGS);
+extern int r128_engine_reset(DRM_IOCTL_ARGS);
+extern int r128_fullscreen(DRM_IOCTL_ARGS);
+extern int r128_cce_buffers(DRM_IOCTL_ARGS);
+
+extern void r128_freelist_reset(drm_device_t * dev);
+
+extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
+
+extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
+extern int r128_do_cleanup_cce(drm_device_t * dev);
+
+extern int r128_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+
+extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
+extern void r128_driver_irq_preinstall(drm_device_t * dev);
+extern void r128_driver_irq_postinstall(drm_device_t * dev);
+extern void r128_driver_irq_uninstall(drm_device_t * dev);
+extern void r128_driver_lastclose(drm_device_t * dev);
+extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);
+
+extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
+			      unsigned long arg);
+
+/* Register definitions, register access macros and drmAddMap constants
+ * for Rage 128 kernel driver.
+ */
+
+#define R128_AUX_SC_CNTL		0x1660
+#	define R128_AUX1_SC_EN			(1 << 0)
+#	define R128_AUX1_SC_MODE_OR		(0 << 1)
+#	define R128_AUX1_SC_MODE_NAND		(1 << 1)
+#	define R128_AUX2_SC_EN			(1 << 2)
+#	define R128_AUX2_SC_MODE_OR		(0 << 3)
+#	define R128_AUX2_SC_MODE_NAND		(1 << 3)
+#	define R128_AUX3_SC_EN			(1 << 4)
+#	define R128_AUX3_SC_MODE_OR		(0 << 5)
+#	define R128_AUX3_SC_MODE_NAND		(1 << 5)
+#define R128_AUX1_SC_LEFT		0x1664
+#define R128_AUX1_SC_RIGHT		0x1668
+#define R128_AUX1_SC_TOP		0x166c
+#define R128_AUX1_SC_BOTTOM		0x1670
+#define R128_AUX2_SC_LEFT		0x1674
+#define R128_AUX2_SC_RIGHT		0x1678
+#define R128_AUX2_SC_TOP		0x167c
+#define R128_AUX2_SC_BOTTOM		0x1680
+#define R128_AUX3_SC_LEFT		0x1684
+#define R128_AUX3_SC_RIGHT		0x1688
+#define R128_AUX3_SC_TOP		0x168c
+#define R128_AUX3_SC_BOTTOM		0x1690
+
+#define R128_BRUSH_DATA0		0x1480
+#define R128_BUS_CNTL			0x0030
+#	define R128_BUS_MASTER_DIS		(1 << 6)
+
+#define R128_CLOCK_CNTL_INDEX		0x0008
+#define R128_CLOCK_CNTL_DATA		0x000c
+#	define R128_PLL_WR_EN			(1 << 7)
+#define R128_CONSTANT_COLOR_C		0x1d34
+#define R128_CRTC_OFFSET		0x0224
+#define R128_CRTC_OFFSET_CNTL		0x0228
+#	define R128_CRTC_OFFSET_FLIP_CNTL	(1 << 16)
+
+#define R128_DP_GUI_MASTER_CNTL		0x146c
+#       define R128_GMC_SRC_PITCH_OFFSET_CNTL	(1    <<  0)
+#       define R128_GMC_DST_PITCH_OFFSET_CNTL	(1    <<  1)
+#	define R128_GMC_BRUSH_SOLID_COLOR	(13   <<  4)
+#	define R128_GMC_BRUSH_NONE		(15   <<  4)
+#	define R128_GMC_DST_16BPP		(4    <<  8)
+#	define R128_GMC_DST_24BPP		(5    <<  8)
+#	define R128_GMC_DST_32BPP		(6    <<  8)
+#       define R128_GMC_DST_DATATYPE_SHIFT	8
+#	define R128_GMC_SRC_DATATYPE_COLOR	(3    << 12)
+#	define R128_DP_SRC_SOURCE_MEMORY	(2    << 24)
+#	define R128_DP_SRC_SOURCE_HOST_DATA	(3    << 24)
+#	define R128_GMC_CLR_CMP_CNTL_DIS	(1    << 28)
+#	define R128_GMC_AUX_CLIP_DIS		(1    << 29)
+#	define R128_GMC_WR_MSK_DIS		(1    << 30)
+#	define R128_ROP3_S			0x00cc0000
+#	define R128_ROP3_P			0x00f00000
+#define R128_DP_WRITE_MASK		0x16cc
+#define R128_DST_PITCH_OFFSET_C		0x1c80
+#	define R128_DST_TILE			(1 << 31)
+
+#define R128_GEN_INT_CNTL		0x0040
+#	define R128_CRTC_VBLANK_INT_EN		(1 <<  0)
+#define R128_GEN_INT_STATUS		0x0044
+#	define R128_CRTC_VBLANK_INT		(1 <<  0)
+#	define R128_CRTC_VBLANK_INT_AK		(1 <<  0)
+#define R128_GEN_RESET_CNTL		0x00f0
+#	define R128_SOFT_RESET_GUI		(1 <<  0)
+
+#define R128_GUI_SCRATCH_REG0		0x15e0
+#define R128_GUI_SCRATCH_REG1		0x15e4
+#define R128_GUI_SCRATCH_REG2		0x15e8
+#define R128_GUI_SCRATCH_REG3		0x15ec
+#define R128_GUI_SCRATCH_REG4		0x15f0
+#define R128_GUI_SCRATCH_REG5		0x15f4
+
+#define R128_GUI_STAT			0x1740
+#	define R128_GUI_FIFOCNT_MASK		0x0fff
+#	define R128_GUI_ACTIVE			(1 << 31)
+
+#define R128_MCLK_CNTL			0x000f
+#	define R128_FORCE_GCP			(1 << 16)
+#	define R128_FORCE_PIPE3D_CP		(1 << 17)
+#	define R128_FORCE_RCP			(1 << 18)
+
+#define R128_PC_GUI_CTLSTAT		0x1748
+#define R128_PC_NGUI_CTLSTAT		0x0184
+#	define R128_PC_FLUSH_GUI		(3 << 0)
+#	define R128_PC_RI_GUI			(1 << 2)
+#	define R128_PC_FLUSH_ALL		0x00ff
+#	define R128_PC_BUSY			(1 << 31)
+
+#define R128_PCI_GART_PAGE		0x017c
+#define R128_PRIM_TEX_CNTL_C		0x1cb0
+
+#define R128_SCALE_3D_CNTL		0x1a00
+#define R128_SEC_TEX_CNTL_C		0x1d00
+#define R128_SEC_TEXTURE_BORDER_COLOR_C	0x1d3c
+#define R128_SETUP_CNTL			0x1bc4
+#define R128_STEN_REF_MASK_C		0x1d40
+
+#define R128_TEX_CNTL_C			0x1c9c
+#	define R128_TEX_CACHE_FLUSH		(1 << 23)
+
+#define R128_WAIT_UNTIL			0x1720
+#	define R128_EVENT_CRTC_OFFSET		(1 << 0)
+#define R128_WINDOW_XY_OFFSET		0x1bcc
+
+/* CCE registers
+ */
+#define R128_PM4_BUFFER_OFFSET		0x0700
+#define R128_PM4_BUFFER_CNTL		0x0704
+#	define R128_PM4_MASK			(15 << 28)
+#	define R128_PM4_NONPM4			(0  << 28)
+#	define R128_PM4_192PIO			(1  << 28)
+#	define R128_PM4_192BM			(2  << 28)
+#	define R128_PM4_128PIO_64INDBM		(3  << 28)
+#	define R128_PM4_128BM_64INDBM		(4  << 28)
+#	define R128_PM4_64PIO_128INDBM		(5  << 28)
+#	define R128_PM4_64BM_128INDBM		(6  << 28)
+#	define R128_PM4_64PIO_64VCBM_64INDBM	(7  << 28)
+#	define R128_PM4_64BM_64VCBM_64INDBM	(8  << 28)
+#	define R128_PM4_64PIO_64VCPIO_64INDPIO	(15 << 28)
+#	define R128_PM4_BUFFER_CNTL_NOUPDATE	(1  << 27)
+
+#define R128_PM4_BUFFER_WM_CNTL		0x0708
+#	define R128_WMA_SHIFT			0
+#	define R128_WMB_SHIFT			8
+#	define R128_WMC_SHIFT			16
+#	define R128_WB_WM_SHIFT			24
+
+#define R128_PM4_BUFFER_DL_RPTR_ADDR	0x070c
+#define R128_PM4_BUFFER_DL_RPTR		0x0710
+#define R128_PM4_BUFFER_DL_WPTR		0x0714
+#	define R128_PM4_BUFFER_DL_DONE		(1 << 31)
+
+#define R128_PM4_VC_FPU_SETUP		0x071c
+
+#define R128_PM4_IW_INDOFF		0x0738
+#define R128_PM4_IW_INDSIZE		0x073c
+
+#define R128_PM4_STAT			0x07b8
+#	define R128_PM4_FIFOCNT_MASK		0x0fff
+#	define R128_PM4_BUSY			(1 << 16)
+#	define R128_PM4_GUI_ACTIVE		(1 << 31)
+
+#define R128_PM4_MICROCODE_ADDR		0x07d4
+#define R128_PM4_MICROCODE_RADDR	0x07d8
+#define R128_PM4_MICROCODE_DATAH	0x07dc
+#define R128_PM4_MICROCODE_DATAL	0x07e0
+
+#define R128_PM4_BUFFER_ADDR		0x07f0
+#define R128_PM4_MICRO_CNTL		0x07fc
+#	define R128_PM4_MICRO_FREERUN		(1 << 30)
+
+#define R128_PM4_FIFO_DATA_EVEN		0x1000
+#define R128_PM4_FIFO_DATA_ODD		0x1004
+
+/* CCE command packets
+ */
+#define R128_CCE_PACKET0		0x00000000
+#define R128_CCE_PACKET1		0x40000000
+#define R128_CCE_PACKET2		0x80000000
+#define R128_CCE_PACKET3		0xC0000000
+#	define R128_CNTL_HOSTDATA_BLT		0x00009400
+#	define R128_CNTL_PAINT_MULTI		0x00009A00
+#	define R128_CNTL_BITBLT_MULTI		0x00009B00
+#	define R128_3D_RNDR_GEN_INDX_PRIM	0x00002300
+
+#define R128_CCE_PACKET_MASK		0xC0000000
+#define R128_CCE_PACKET_COUNT_MASK	0x3fff0000
+#define R128_CCE_PACKET0_REG_MASK	0x000007ff
+#define R128_CCE_PACKET1_REG0_MASK	0x000007ff
+#define R128_CCE_PACKET1_REG1_MASK	0x003ff800
+
+#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE		0x00000000
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT	0x00000001
+#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE		0x00000002
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE	0x00000003
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST	0x00000004
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN	0x00000005
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP	0x00000006
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2	0x00000007
+#define R128_CCE_VC_CNTL_PRIM_WALK_IND		0x00000010
+#define R128_CCE_VC_CNTL_PRIM_WALK_LIST		0x00000020
+#define R128_CCE_VC_CNTL_PRIM_WALK_RING		0x00000030
+#define R128_CCE_VC_CNTL_NUM_SHIFT		16
+
+#define R128_DATATYPE_VQ		0
+#define R128_DATATYPE_CI4		1
+#define R128_DATATYPE_CI8		2
+#define R128_DATATYPE_ARGB1555		3
+#define R128_DATATYPE_RGB565		4
+#define R128_DATATYPE_RGB888		5
+#define R128_DATATYPE_ARGB8888		6
+#define R128_DATATYPE_RGB332		7
+#define R128_DATATYPE_Y8		8
+#define R128_DATATYPE_RGB8		9
+#define R128_DATATYPE_CI16		10
+#define R128_DATATYPE_YVYU422		11
+#define R128_DATATYPE_VYUY422		12
+#define R128_DATATYPE_AYUV444		14
+#define R128_DATATYPE_ARGB4444		15
+
+/* Constants */
+#define R128_AGP_OFFSET			0x02000000
+
+#define R128_WATERMARK_L		16
+#define R128_WATERMARK_M		8
+#define R128_WATERMARK_N		8
+#define R128_WATERMARK_K		128
+
+#define R128_MAX_USEC_TIMEOUT		100000	/* 100 ms */
+
+#define R128_LAST_FRAME_REG		R128_GUI_SCRATCH_REG0
+#define R128_LAST_DISPATCH_REG		R128_GUI_SCRATCH_REG1
+#define R128_MAX_VB_AGE			0x7fffffff
+#define R128_MAX_VB_VERTS		(0xffff)
+
+#define R128_RING_HIGH_MARK		128
+
+#define R128_PERFORMANCE_BOXES		0
+
+#define R128_READ(reg)		DRM_READ32(  dev_priv->mmio, (reg) )
+#define R128_WRITE(reg,val)	DRM_WRITE32( dev_priv->mmio, (reg), (val) )
+#define R128_READ8(reg)		DRM_READ8(   dev_priv->mmio, (reg) )
+#define R128_WRITE8(reg,val)	DRM_WRITE8(  dev_priv->mmio, (reg), (val) )
+
+#define R128_WRITE_PLL(addr,val)					\
+do {									\
+	R128_WRITE8(R128_CLOCK_CNTL_INDEX,				\
+		    ((addr) & 0x1f) | R128_PLL_WR_EN);			\
+	R128_WRITE(R128_CLOCK_CNTL_DATA, (val));			\
+} while (0)
+
+#define CCE_PACKET0( reg, n )		(R128_CCE_PACKET0 |		\
+					 ((n) << 16) | ((reg) >> 2))
+#define CCE_PACKET1( reg0, reg1 )	(R128_CCE_PACKET1 |		\
+					 (((reg1) >> 2) << 11) | ((reg0) >> 2))
+#define CCE_PACKET2()			(R128_CCE_PACKET2)
+#define CCE_PACKET3( pkt, n )		(R128_CCE_PACKET3 |		\
+					 (pkt) | ((n) << 16))
+
+static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
+{
+	drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+	ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32);
+	if (ring->space <= 0)
+		ring->space += ring->size;
+}
+
+/* ================================================================
+ * Misc helper macros
+ */
+
+#define RING_SPACE_TEST_WITH_RETURN( dev_priv )				\
+do {									\
+	drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i;		\
+	if ( ring->space < ring->high_mark ) {				\
+		for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {	\
+			r128_update_ring_snapshot( dev_priv );		\
+			if ( ring->space >= ring->high_mark )		\
+				goto __ring_space_done;			\
+			DRM_UDELAY(1);				\
+		}							\
+		DRM_ERROR( "ring space check failed!\n" );		\
+		return DRM_ERR(EBUSY);				\
+	}								\
+ __ring_space_done:							\
+	;								\
+} while (0)
+
+#define VB_AGE_TEST_WITH_RETURN( dev_priv )				\
+do {									\
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;		\
+	if ( sarea_priv->last_dispatch >= R128_MAX_VB_AGE ) {		\
+		int __ret = r128_do_cce_idle( dev_priv );		\
+		if ( __ret ) return __ret;				\
+		sarea_priv->last_dispatch = 0;				\
+		r128_freelist_reset( dev );				\
+	}								\
+} while (0)
+
+#define R128_WAIT_UNTIL_PAGE_FLIPPED() do {				\
+	OUT_RING( CCE_PACKET0( R128_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( R128_EVENT_CRTC_OFFSET );				\
+} while (0)
+
+/* ================================================================
+ * Ring control
+ */
+
+#define R128_VERBOSE	0
+
+#define RING_LOCALS							\
+	int write, _nr; unsigned int tail_mask; volatile u32 *ring;
+
+#define BEGIN_RING( n ) do {						\
+	if ( R128_VERBOSE ) {						\
+		DRM_INFO( "BEGIN_RING( %d ) in %s\n",			\
+			   (n), __FUNCTION__ );				\
+	}								\
+	if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {		\
+		COMMIT_RING();						\
+		r128_wait_ring( dev_priv, (n) * sizeof(u32) );		\
+	}								\
+	_nr = n; dev_priv->ring.space -= (n) * sizeof(u32);		\
+	ring = dev_priv->ring.start;					\
+	write = dev_priv->ring.tail;					\
+	tail_mask = dev_priv->ring.tail_mask;				\
+} while (0)
+
+/* You can set this to zero if you want.  If the card locks up, you'll
+ * need to keep this set.  It works around a bug in early revs of the
+ * Rage 128 chipset, where the CCE would read 32 dwords past the end of
+ * the ring buffer before wrapping around.
+ */
+#define R128_BROKEN_CCE	1
+
+#define ADVANCE_RING() do {						\
+	if ( R128_VERBOSE ) {						\
+		DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",	\
+			  write, dev_priv->ring.tail );			\
+	}								\
+	if ( R128_BROKEN_CCE && write < 32 ) {				\
+		memcpy( dev_priv->ring.end,				\
+			dev_priv->ring.start,				\
+			write * sizeof(u32) );				\
+	}								\
+	if (((dev_priv->ring.tail + _nr) & tail_mask) != write) {	\
+		DRM_ERROR( 						\
+			"ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",	\
+			((dev_priv->ring.tail + _nr) & tail_mask),	\
+			write, __LINE__);				\
+	} else								\
+		dev_priv->ring.tail = write;				\
+} while (0)
+
+#define COMMIT_RING() do {						\
+	if ( R128_VERBOSE ) {						\
+		DRM_INFO( "COMMIT_RING() tail=0x%06x\n",		\
+			dev_priv->ring.tail );				\
+	}								\
+	DRM_MEMORYBARRIER();						\
+	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail );	\
+	R128_READ( R128_PM4_BUFFER_DL_WPTR );				\
+} while (0)
+
+#define OUT_RING( x ) do {						\
+	if ( R128_VERBOSE ) {						\
+		DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",		\
+			   (unsigned int)(x), write );			\
+	}								\
+	ring[write++] = cpu_to_le32( x );				\
+	write &= tail_mask;						\
+} while (0)
+
+#endif				/* __R128_DRV_H__ */
--- libdrm-2.3.0.orig/shared-core/r300_cmdbuf.c
+++ libdrm-2.3.0/shared-core/r300_cmdbuf.c
@@ -0,0 +1,973 @@
+/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc.  2002.
+ * Copyright (C) 2004 Nicolai Haehnle.
+ * All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and 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
+ * 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.
+ *
+ * Authors:
+ *    Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+#include "r300_reg.h"
+
+#define R300_SIMULTANEOUS_CLIPRECTS		4
+
+/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
+ */
+static const int r300_cliprect_cntl[4] = {
+	0xAAAA,
+	0xEEEE,
+	0xFEFE,
+	0xFFFE
+};
+
+/**
+ * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
+ * buffer, starting with index n.
+ */
+static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
+			       drm_radeon_kcmd_buffer_t *cmdbuf, int n)
+{
+	drm_clip_rect_t box;
+	int nr;
+	int i;
+	RING_LOCALS;
+
+	nr = cmdbuf->nbox - n;
+	if (nr > R300_SIMULTANEOUS_CLIPRECTS)
+		nr = R300_SIMULTANEOUS_CLIPRECTS;
+
+	DRM_DEBUG("%i cliprects\n", nr);
+
+	if (nr) {
+		BEGIN_RING(6 + nr * 2);
+		OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
+
+		for (i = 0; i < nr; ++i) {
+			if (DRM_COPY_FROM_USER_UNCHECKED
+			    (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
+				DRM_ERROR("copy cliprect faulted\n");
+				return DRM_ERR(EFAULT);
+			}
+
+			box.x1 =
+			    (box.x1 +
+			     R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+			box.y1 =
+			    (box.y1 +
+			     R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+			box.x2 =
+			    (box.x2 +
+			     R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+			box.y2 =
+			    (box.y2 +
+			     R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
+
+			OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
+				 (box.y1 << R300_CLIPRECT_Y_SHIFT));
+			OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
+				 (box.y2 << R300_CLIPRECT_Y_SHIFT));
+		}
+
+		OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
+
+		/* TODO/SECURITY: Force scissors to a safe value, otherwise the
+		 * client might be able to trample over memory.
+		 * The impact should be very limited, but I'd rather be safe than
+		 * sorry.
+		 */
+		OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
+		OUT_RING(0);
+		OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
+		ADVANCE_RING();
+	} else {
+		/* Why we allow zero cliprect rendering:
+		 * There are some commands in a command buffer that must be submitted
+		 * even when there are no cliprects, e.g. DMA buffer discard
+		 * or state setting (though state setting could be avoided by
+		 * simulating a loss of context).
+		 *
+		 * Now since the cmdbuf interface is so chaotic right now (and is
+		 * bound to remain that way for a bit until things settle down),
+		 * it is basically impossible to filter out the commands that are
+		 * necessary and those that aren't.
+		 *
+		 * So I choose the safe way and don't do any filtering at all;
+		 * instead, I simply set up the engine so that all rendering
+		 * can't produce any fragments.
+		 */
+		BEGIN_RING(2);
+		OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
+		ADVANCE_RING();
+	}
+
+	return 0;
+}
+
+static u8 r300_reg_flags[0x10000 >> 2];
+
+void r300_init_reg_flags(void)
+{
+	int i;
+	memset(r300_reg_flags, 0, 0x10000 >> 2);
+#define ADD_RANGE_MARK(reg, count,mark) \
+		for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
+			r300_reg_flags[i]|=(mark);
+
+#define MARK_SAFE		1
+#define MARK_CHECK_OFFSET	2
+
+#define ADD_RANGE(reg, count)	ADD_RANGE_MARK(reg, count, MARK_SAFE)
+
+	/* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
+	ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
+	ADD_RANGE(0x2080, 1);
+	ADD_RANGE(R300_SE_VTE_CNTL, 2);
+	ADD_RANGE(0x2134, 2);
+	ADD_RANGE(0x2140, 1);
+	ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
+	ADD_RANGE(0x21DC, 1);
+	ADD_RANGE(0x221C, 1);
+	ADD_RANGE(0x2220, 4);
+	ADD_RANGE(0x2288, 1);
+	ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+	ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
+	ADD_RANGE(R300_GB_ENABLE, 1);
+	ADD_RANGE(R300_GB_MSPOS0, 5);
+	ADD_RANGE(R300_TX_CNTL, 1);
+	ADD_RANGE(R300_TX_ENABLE, 1);
+	ADD_RANGE(0x4200, 4);
+	ADD_RANGE(0x4214, 1);
+	ADD_RANGE(R300_RE_POINTSIZE, 1);
+	ADD_RANGE(0x4230, 3);
+	ADD_RANGE(R300_RE_LINE_CNT, 1);
+	ADD_RANGE(0x4238, 1);
+	ADD_RANGE(0x4260, 3);
+	ADD_RANGE(0x4274, 4);
+	ADD_RANGE(0x4288, 5);
+	ADD_RANGE(0x42A0, 1);
+	ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
+	ADD_RANGE(0x42B4, 1);
+	ADD_RANGE(R300_RE_CULL_CNTL, 1);
+	ADD_RANGE(0x42C0, 2);
+	ADD_RANGE(R300_RS_CNTL_0, 2);
+	ADD_RANGE(R300_RS_INTERP_0, 8);
+	ADD_RANGE(R300_RS_ROUTE_0, 8);
+	ADD_RANGE(0x43A4, 2);
+	ADD_RANGE(0x43E8, 1);
+	ADD_RANGE(R300_PFS_CNTL_0, 3);
+	ADD_RANGE(R300_PFS_NODE_0, 4);
+	ADD_RANGE(R300_PFS_TEXI_0, 64);
+	ADD_RANGE(0x46A4, 5);
+	ADD_RANGE(R300_PFS_INSTR0_0, 64);
+	ADD_RANGE(R300_PFS_INSTR1_0, 64);
+	ADD_RANGE(R300_PFS_INSTR2_0, 64);
+	ADD_RANGE(R300_PFS_INSTR3_0, 64);
+	ADD_RANGE(0x4BC0, 1);
+	ADD_RANGE(0x4BC8, 3);
+	ADD_RANGE(R300_PP_ALPHA_TEST, 2);
+	ADD_RANGE(0x4BD8, 1);
+	ADD_RANGE(R300_PFS_PARAM_0_X, 64);
+	ADD_RANGE(0x4E00, 1);
+	ADD_RANGE(R300_RB3D_CBLEND, 2);
+	ADD_RANGE(R300_RB3D_COLORMASK, 1);
+	ADD_RANGE(0x4E10, 3);
+	ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET);	/* check offset */
+	ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
+	ADD_RANGE(0x4E50, 9);
+	ADD_RANGE(0x4E88, 1);
+	ADD_RANGE(0x4EA0, 2);
+	ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
+	ADD_RANGE(0x4F10, 4);
+	ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);	/* check offset */
+	ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
+	ADD_RANGE(0x4F28, 1);
+	ADD_RANGE(0x4F30, 2);
+	ADD_RANGE(0x4F44, 1);
+	ADD_RANGE(0x4F54, 1);
+
+	ADD_RANGE(R300_TX_FILTER_0, 16);
+	ADD_RANGE(R300_TX_FILTER1_0, 16);
+	ADD_RANGE(R300_TX_SIZE_0, 16);
+	ADD_RANGE(R300_TX_FORMAT_0, 16);
+	ADD_RANGE(R300_TX_PITCH_0, 16);
+	/* Texture offset is dangerous and needs more checking */
+	ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
+	ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
+	ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
+
+	/* Sporadic registers used as primitives are emitted */
+	ADD_RANGE(0x4f18, 1);
+	ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
+	ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
+	ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
+
+}
+
+static __inline__ int r300_check_range(unsigned reg, int count)
+{
+	int i;
+	if (reg & ~0xffff)
+		return -1;
+	for (i = (reg >> 2); i < (reg >> 2) + count; i++)
+		if (r300_reg_flags[i] != MARK_SAFE)
+			return 1;
+	return 0;
+}
+
+/*
+ * we expect offsets passed to the framebuffer to be either within video 
+ * memory or within AGP space 
+ */
+static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
+					u32 offset)
+{
+	/* we realy want to check against end of video aperture
+	   but this value is not being kept.
+	   This code is correct for now (does the same thing as the
+	   code that sets MC_FB_LOCATION) in radeon_cp.c */
+	if (offset >= dev_priv->fb_location &&
+	    offset < (dev_priv->fb_location + dev_priv->fb_size))
+		return 0;
+	if (offset >= dev_priv->gart_vm_start &&
+	    offset < (dev_priv->gart_vm_start + dev_priv->gart_size))
+		return 0;
+	return 1;
+}
+
+static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
+							  dev_priv,
+							  drm_radeon_kcmd_buffer_t
+							  * cmdbuf,
+							  drm_r300_cmd_header_t
+							  header)
+{
+	int reg;
+	int sz;
+	int i;
+	int values[64];
+	RING_LOCALS;
+
+	sz = header.packet0.count;
+	reg = (header.packet0.reghi << 8) | header.packet0.reglo;
+
+	if ((sz > 64) || (sz < 0)) {
+		DRM_ERROR
+		    ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
+		     reg, sz);
+		return DRM_ERR(EINVAL);
+	}
+	for (i = 0; i < sz; i++) {
+		values[i] = ((int *)cmdbuf->buf)[i];
+		switch (r300_reg_flags[(reg >> 2) + i]) {
+		case MARK_SAFE:
+			break;
+		case MARK_CHECK_OFFSET:
+			if (r300_check_offset(dev_priv, (u32) values[i])) {
+				DRM_ERROR
+				    ("Offset failed range check (reg=%04x sz=%d)\n",
+				     reg, sz);
+				return DRM_ERR(EINVAL);
+			}
+			break;
+		default:
+			DRM_ERROR("Register %04x failed check as flag=%02x\n",
+				  reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
+			return DRM_ERR(EINVAL);
+		}
+	}
+
+	BEGIN_RING(1 + sz);
+	OUT_RING(CP_PACKET0(reg, sz - 1));
+	OUT_RING_TABLE(values, sz);
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * 4;
+	cmdbuf->bufsz -= sz * 4;
+
+	return 0;
+}
+
+/**
+ * Emits a packet0 setting arbitrary registers.
+ * Called by r300_do_cp_cmdbuf.
+ *
+ * Note that checks are performed on contents and addresses of the registers
+ */
+static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
+					drm_radeon_kcmd_buffer_t *cmdbuf,
+					drm_r300_cmd_header_t header)
+{
+	int reg;
+	int sz;
+	RING_LOCALS;
+
+	sz = header.packet0.count;
+	reg = (header.packet0.reghi << 8) | header.packet0.reglo;
+
+	if (!sz)
+		return 0;
+
+	if (sz * 4 > cmdbuf->bufsz)
+		return DRM_ERR(EINVAL);
+
+	if (reg + sz * 4 >= 0x10000) {
+		DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
+			  sz);
+		return DRM_ERR(EINVAL);
+	}
+
+	if (r300_check_range(reg, sz)) {
+		/* go and check everything */
+		return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
+							   header);
+	}
+	/* the rest of the data is safe to emit, whatever the values the user passed */
+
+	BEGIN_RING(1 + sz);
+	OUT_RING(CP_PACKET0(reg, sz - 1));
+	OUT_RING_TABLE((int *)cmdbuf->buf, sz);
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * 4;
+	cmdbuf->bufsz -= sz * 4;
+
+	return 0;
+}
+
+/**
+ * Uploads user-supplied vertex program instructions or parameters onto
+ * the graphics card.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
+				    drm_radeon_kcmd_buffer_t *cmdbuf,
+				    drm_r300_cmd_header_t header)
+{
+	int sz;
+	int addr;
+	RING_LOCALS;
+
+	sz = header.vpu.count;
+	addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;
+
+	if (!sz)
+		return 0;
+	if (sz * 16 > cmdbuf->bufsz)
+		return DRM_ERR(EINVAL);
+
+	BEGIN_RING(5 + sz * 4);
+	/* Wait for VAP to come to senses.. */
+	/* there is no need to emit it multiple times, (only once before VAP is programmed,
+	   but this optimization is for later */
+	OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0);
+	OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
+	OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
+	OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
+
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * 16;
+	cmdbuf->bufsz -= sz * 16;
+
+	return 0;
+}
+
+/**
+ * Emit a clear packet from userspace.
+ * Called by r300_emit_packet3.
+ */
+static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
+				      drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	RING_LOCALS;
+
+	if (8 * 4 > cmdbuf->bufsz)
+		return DRM_ERR(EINVAL);
+
+	BEGIN_RING(10);
+	OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
+	OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
+		 (1 << R300_PRIM_NUM_VERTICES_SHIFT));
+	OUT_RING_TABLE((int *)cmdbuf->buf, 8);
+	ADVANCE_RING();
+
+	cmdbuf->buf += 8 * 4;
+	cmdbuf->bufsz -= 8 * 4;
+
+	return 0;
+}
+
+static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
+					       drm_radeon_kcmd_buffer_t *cmdbuf,
+					       u32 header)
+{
+	int count, i, k;
+#define MAX_ARRAY_PACKET  64
+	u32 payload[MAX_ARRAY_PACKET];
+	u32 narrays;
+	RING_LOCALS;
+
+	count = (header >> 16) & 0x3fff;
+
+	if ((count + 1) > MAX_ARRAY_PACKET) {
+		DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
+			  count);
+		return DRM_ERR(EINVAL);
+	}
+	memset(payload, 0, MAX_ARRAY_PACKET * 4);
+	memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
+
+	/* carefully check packet contents */
+
+	narrays = payload[0];
+	k = 0;
+	i = 1;
+	while ((k < narrays) && (i < (count + 1))) {
+		i++;		/* skip attribute field */
+		if (r300_check_offset(dev_priv, payload[i])) {
+			DRM_ERROR
+			    ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
+			     k, i);
+			return DRM_ERR(EINVAL);
+		}
+		k++;
+		i++;
+		if (k == narrays)
+			break;
+		/* have one more to process, they come in pairs */
+		if (r300_check_offset(dev_priv, payload[i])) {
+			DRM_ERROR
+			    ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
+			     k, i);
+			return DRM_ERR(EINVAL);
+		}
+		k++;
+		i++;
+	}
+	/* do the counts match what we expect ? */
+	if ((k != narrays) || (i != (count + 1))) {
+		DRM_ERROR
+		    ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
+		     k, i, narrays, count + 1);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* all clear, output packet */
+
+	BEGIN_RING(count + 2);
+	OUT_RING(header);
+	OUT_RING_TABLE(payload, count + 1);
+	ADVANCE_RING();
+
+	cmdbuf->buf += (count + 2) * 4;
+	cmdbuf->bufsz -= (count + 2) * 4;
+
+	return 0;
+}
+
+static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
+					     drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	u32 *cmd = (u32 *) cmdbuf->buf;
+	int count, ret;
+	RING_LOCALS;
+
+	count=(cmd[0]>>16) & 0x3fff;
+
+	if (cmd[0] & 0x8000) {
+		u32 offset;
+
+		if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL 
+			      | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+			offset = cmd[2] << 10;
+			ret = r300_check_offset(dev_priv, offset);
+			if (ret) {
+				DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
+				return DRM_ERR(EINVAL);
+			}
+		}
+
+		if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
+		    (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+			offset = cmd[3] << 10;
+			ret = r300_check_offset(dev_priv, offset);
+			if (ret) {
+				DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
+				return DRM_ERR(EINVAL);
+			}
+			
+		}
+	}
+
+	BEGIN_RING(count+2);
+	OUT_RING(cmd[0]);
+	OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+	ADVANCE_RING();
+
+	cmdbuf->buf += (count+2)*4;
+	cmdbuf->bufsz -= (count+2)*4;
+
+	return 0;
+}
+
+static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
+					     drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	u32 *cmd = (u32 *) cmdbuf->buf;
+	int count, ret;
+	RING_LOCALS;
+
+	count=(cmd[0]>>16) & 0x3fff;
+
+	if ((cmd[1] & 0x8000ffff) != 0x80000810) {
+		DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+		return DRM_ERR(EINVAL);
+	}
+	ret = r300_check_offset(dev_priv, cmd[2]);
+	if (ret) {
+		DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+		return DRM_ERR(EINVAL);
+	}
+
+	BEGIN_RING(count+2);
+	OUT_RING(cmd[0]);
+	OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+	ADVANCE_RING();
+
+	cmdbuf->buf += (count+2)*4;
+	cmdbuf->bufsz -= (count+2)*4;
+
+	return 0;
+}
+
+static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
+					    drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	u32 header;
+	int count;
+	RING_LOCALS;
+
+	if (4 > cmdbuf->bufsz)
+		return DRM_ERR(EINVAL);
+
+	/* Fixme !! This simply emits a packet without much checking.
+	   We need to be smarter. */
+
+	/* obtain first word - actual packet3 header */
+	header = *(u32 *) cmdbuf->buf;
+
+	/* Is it packet 3 ? */
+	if ((header >> 30) != 0x3) {
+		DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
+		return DRM_ERR(EINVAL);
+	}
+
+	count = (header >> 16) & 0x3fff;
+
+	/* Check again now that we know how much data to expect */
+	if ((count + 2) * 4 > cmdbuf->bufsz) {
+		DRM_ERROR
+		    ("Expected packet3 of length %d but have only %d bytes left\n",
+		     (count + 2) * 4, cmdbuf->bufsz);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* Is it a packet type we know about ? */
+	switch (header & 0xff00) {
+	case RADEON_3D_LOAD_VBPNTR:	/* load vertex array pointers */
+		return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
+
+	case RADEON_CNTL_BITBLT_MULTI:
+		return r300_emit_bitblt_multi(dev_priv, cmdbuf);
+
+	case RADEON_CP_INDX_BUFFER:	/* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
+		return r300_emit_indx_buffer(dev_priv, cmdbuf);
+	case RADEON_CP_3D_DRAW_IMMD_2:	/* triggers drawing using in-packet vertex data */
+	case RADEON_CP_3D_DRAW_VBUF_2:	/* triggers drawing of vertex buffers setup elsewhere */
+	case RADEON_CP_3D_DRAW_INDX_2:	/* triggers drawing using indices to vertex buffer */
+	case RADEON_WAIT_FOR_IDLE:
+	case RADEON_CP_NOP:
+		/* these packets are safe */
+		break;
+	default:
+		DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
+		return DRM_ERR(EINVAL);
+	}
+
+	BEGIN_RING(count + 2);
+	OUT_RING(header);
+	OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+	ADVANCE_RING();
+
+	cmdbuf->buf += (count + 2) * 4;
+	cmdbuf->bufsz -= (count + 2) * 4;
+
+	return 0;
+}
+
+/**
+ * Emit a rendering packet3 from userspace.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
+					drm_radeon_kcmd_buffer_t *cmdbuf,
+					drm_r300_cmd_header_t header)
+{
+	int n;
+	int ret;
+	char *orig_buf = cmdbuf->buf;
+	int orig_bufsz = cmdbuf->bufsz;
+
+	/* This is a do-while-loop so that we run the interior at least once,
+	 * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
+	 */
+	n = 0;
+	do {
+		if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
+			ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
+			if (ret)
+				return ret;
+
+			cmdbuf->buf = orig_buf;
+			cmdbuf->bufsz = orig_bufsz;
+		}
+
+		switch (header.packet3.packet) {
+		case R300_CMD_PACKET3_CLEAR:
+			DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
+			ret = r300_emit_clear(dev_priv, cmdbuf);
+			if (ret) {
+				DRM_ERROR("r300_emit_clear failed\n");
+				return ret;
+			}
+			break;
+
+		case R300_CMD_PACKET3_RAW:
+			DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
+			ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
+			if (ret) {
+				DRM_ERROR("r300_emit_raw_packet3 failed\n");
+				return ret;
+			}
+			break;
+
+		default:
+			DRM_ERROR("bad packet3 type %i at %p\n",
+				  header.packet3.packet,
+				  cmdbuf->buf - sizeof(header));
+			return DRM_ERR(EINVAL);
+		}
+
+		n += R300_SIMULTANEOUS_CLIPRECTS;
+	} while (n < cmdbuf->nbox);
+
+	return 0;
+}
+
+/* Some of the R300 chips seem to be extremely touchy about the two registers
+ * that are configured in r300_pacify.
+ * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace
+ * sends a command buffer that contains only state setting commands and a
+ * vertex program/parameter upload sequence, this will eventually lead to a
+ * lockup, unless the sequence is bracketed by calls to r300_pacify.
+ * So we should take great care to *always* call r300_pacify before
+ * *anything* 3D related, and again afterwards. This is what the
+ * call bracket in r300_do_cp_cmdbuf is for.
+ */
+
+/**
+ * Emit the sequence to pacify R300.
+ */
+static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
+{
+	RING_LOCALS;
+
+	BEGIN_RING(6);
+	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+	OUT_RING(0xa);
+	OUT_RING(CP_PACKET0(0x4f18, 0));
+	OUT_RING(0x3);
+	OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
+	OUT_RING(0x0);
+	ADVANCE_RING();
+}
+
+/**
+ * Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
+ * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
+ * be careful about how this function is called.
+ */
+static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+
+	buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
+	buf->pending = 1;
+	buf->used = 0;
+}
+
+static int r300_scratch(drm_radeon_private_t *dev_priv,
+			drm_radeon_kcmd_buffer_t *cmdbuf,
+			drm_r300_cmd_header_t header)
+{
+	u32 *ref_age_base;
+	u32 i, buf_idx, h_pending;
+	RING_LOCALS;
+	
+	if (cmdbuf->bufsz < sizeof(uint64_t) + header.scratch.n_bufs * sizeof(buf_idx) ) {
+		return DRM_ERR(EINVAL);
+	}
+	
+	if (header.scratch.reg >= 5) {
+		return DRM_ERR(EINVAL);
+	}
+	
+	dev_priv->scratch_ages[header.scratch.reg] ++;
+	
+	ref_age_base = (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf);
+	
+	cmdbuf->buf += sizeof(uint64_t);
+	cmdbuf->bufsz -= sizeof(uint64_t);
+	
+	for (i=0; i < header.scratch.n_bufs; i++) {
+		buf_idx = *(u32 *)cmdbuf->buf;
+		buf_idx *= 2; /* 8 bytes per buf */
+		
+		if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
+			return DRM_ERR(EINVAL);
+		}
+					
+		if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
+			return DRM_ERR(EINVAL);
+		}
+					
+		if (h_pending == 0) {
+			return DRM_ERR(EINVAL);
+		}
+					
+		h_pending--;
+						
+		if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
+			return DRM_ERR(EINVAL);
+		}
+					
+		cmdbuf->buf += sizeof(buf_idx);
+		cmdbuf->bufsz -= sizeof(buf_idx);
+	}
+	
+	BEGIN_RING(2);
+	OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
+	OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
+	ADVANCE_RING();
+	
+	return 0;
+}
+
+/**
+ * Parses and validates a user-supplied command buffer and emits appropriate
+ * commands on the DMA ring buffer.
+ * Called by the ioctl handler function radeon_cp_cmdbuf.
+ */
+int r300_do_cp_cmdbuf(drm_device_t *dev,
+		      DRMFILE filp,
+		      drm_file_t *filp_priv,
+		      drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf = NULL;
+	int emit_dispatch_age = 0;
+	int ret = 0;
+
+	DRM_DEBUG("\n");
+
+	/* See the comment above r300_emit_begin3d for why this call must be here,
+	 * and what the cleanup gotos are for. */
+	r300_pacify(dev_priv);
+
+	if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
+		ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
+		if (ret)
+			goto cleanup;
+	}
+
+	while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
+		int idx;
+		drm_r300_cmd_header_t header;
+
+		header.u = *(unsigned int *)cmdbuf->buf;
+
+		cmdbuf->buf += sizeof(header);
+		cmdbuf->bufsz -= sizeof(header);
+
+		switch (header.header.cmd_type) {
+		case R300_CMD_PACKET0:
+			DRM_DEBUG("R300_CMD_PACKET0\n");
+			ret = r300_emit_packet0(dev_priv, cmdbuf, header);
+			if (ret) {
+				DRM_ERROR("r300_emit_packet0 failed\n");
+				goto cleanup;
+			}
+			break;
+
+		case R300_CMD_VPU:
+			DRM_DEBUG("R300_CMD_VPU\n");
+			ret = r300_emit_vpu(dev_priv, cmdbuf, header);
+			if (ret) {
+				DRM_ERROR("r300_emit_vpu failed\n");
+				goto cleanup;
+			}
+			break;
+
+		case R300_CMD_PACKET3:
+			DRM_DEBUG("R300_CMD_PACKET3\n");
+			ret = r300_emit_packet3(dev_priv, cmdbuf, header);
+			if (ret) {
+				DRM_ERROR("r300_emit_packet3 failed\n");
+				goto cleanup;
+			}
+			break;
+
+		case R300_CMD_END3D:
+			DRM_DEBUG("R300_CMD_END3D\n");
+			/* TODO:
+			   Ideally userspace driver should not need to issue this call,
+			   i.e. the drm driver should issue it automatically and prevent
+			   lockups.
+
+			   In practice, we do not understand why this call is needed and what
+			   it does (except for some vague guesses that it has to do with cache
+			   coherence) and so the user space driver does it.
+
+			   Once we are sure which uses prevent lockups the code could be moved
+			   into the kernel and the userspace driver will not
+			   need to use this command.
+
+			   Note that issuing this command does not hurt anything
+			   except, possibly, performance */
+			r300_pacify(dev_priv);
+			break;
+
+		case R300_CMD_CP_DELAY:
+			/* simple enough, we can do it here */
+			DRM_DEBUG("R300_CMD_CP_DELAY\n");
+			{
+				int i;
+				RING_LOCALS;
+
+				BEGIN_RING(header.delay.count);
+				for (i = 0; i < header.delay.count; i++)
+					OUT_RING(RADEON_CP_PACKET2);
+				ADVANCE_RING();
+			}
+			break;
+
+		case R300_CMD_DMA_DISCARD:
+			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+			idx = header.dma.buf_idx;
+			if (idx < 0 || idx >= dma->buf_count) {
+				DRM_ERROR("buffer index %d (of %d max)\n",
+					  idx, dma->buf_count - 1);
+				ret = DRM_ERR(EINVAL);
+				goto cleanup;
+			}
+
+			buf = dma->buflist[idx];
+			if (buf->filp != filp || buf->pending) {
+				DRM_ERROR("bad buffer %p %p %d\n",
+					  buf->filp, filp, buf->pending);
+				ret = DRM_ERR(EINVAL);
+				goto cleanup;
+			}
+
+			emit_dispatch_age = 1;
+			r300_discard_buffer(dev, buf);
+			break;
+
+		case R300_CMD_WAIT:
+			/* simple enough, we can do it here */
+			DRM_DEBUG("R300_CMD_WAIT\n");
+			if (header.wait.flags == 0)
+				break;	/* nothing to do */
+
+			{
+				RING_LOCALS;
+
+				BEGIN_RING(2);
+				OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+				OUT_RING((header.wait.flags & 0xf) << 14);
+				ADVANCE_RING();
+			}
+			break;
+
+		case R300_CMD_SCRATCH:
+			DRM_DEBUG("R300_CMD_SCRATCH\n");
+			ret = r300_scratch(dev_priv, cmdbuf, header);
+			if (ret) {
+				DRM_ERROR("r300_scratch failed\n");
+				goto cleanup;
+			}
+			break;
+			
+		default:
+			DRM_ERROR("bad cmd_type %i at %p\n",
+				  header.header.cmd_type,
+				  cmdbuf->buf - sizeof(header));
+			ret = DRM_ERR(EINVAL);
+			goto cleanup;
+		}
+	}
+
+	DRM_DEBUG("END\n");
+
+      cleanup:
+	r300_pacify(dev_priv);
+
+	/* We emit the vertex buffer age here, outside the pacifier "brackets"
+	 * for two reasons:
+	 *  (1) This may coalesce multiple age emissions into a single one and
+	 *  (2) more importantly, some chips lock up hard when scratch registers
+	 *      are written inside the pacifier bracket.
+	 */
+	if (emit_dispatch_age) {
+		RING_LOCALS;
+
+		/* Emit the vertex buffer age */
+		BEGIN_RING(2);
+		RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
+		ADVANCE_RING();
+	}
+
+	COMMIT_RING();
+
+	return ret;
+}
--- libdrm-2.3.0.orig/shared-core/sis_drv.h
+++ libdrm-2.3.0/shared-core/sis_drv.h
@@ -0,0 +1,91 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * 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.
+ *
+ */
+
+#ifndef _SIS_DRV_H_
+#define _SIS_DRV_H_
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR		"SIS, Tungsten Graphics"
+#define DRIVER_NAME		"sis"
+#define DRIVER_DESC		"SIS 300/630/540"
+#define DRIVER_DATE		"20060619"
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		2
+#define DRIVER_PATCHLEVEL	1
+
+enum sis_family {
+	SIS_OTHER = 0,
+	SIS_CHIP_315 = 1,
+};
+
+#if defined(__linux__)
+#define SIS_HAVE_CORE_MM
+#endif
+
+#ifdef SIS_HAVE_CORE_MM
+#include "drm_sman.h"
+
+#define SIS_BASE (dev_priv->mmio)
+#define SIS_READ(reg)	 DRM_READ32(SIS_BASE, reg);
+#define SIS_WRITE(reg, val)   DRM_WRITE32(SIS_BASE, reg, val);
+
+typedef struct drm_sis_private {
+	drm_local_map_t *mmio;
+	unsigned idle_fault;
+	drm_sman_t sman;
+	unsigned long chipset;
+	int vram_initialized;
+	int agp_initialized;
+	unsigned long vram_offset;
+	unsigned long agp_offset;
+} drm_sis_private_t;
+
+extern int sis_idle(drm_device_t *dev);
+extern void sis_reclaim_buffers_locked(drm_device_t *dev, struct file *filp);
+extern void sis_lastclose(drm_device_t *dev);
+
+#else
+#include "sis_ds.h"
+
+typedef struct drm_sis_private {
+	memHeap_t *AGPHeap;
+	memHeap_t *FBHeap;
+} drm_sis_private_t;
+
+extern int sis_init_context(drm_device_t * dev, int context);
+extern int sis_final_context(drm_device_t * dev, int context);
+
+#endif
+
+
+
+extern drm_ioctl_desc_t sis_ioctls[];
+extern int sis_max_ioctl;
+
+#endif
--- libdrm-2.3.0.orig/shared-core/mga_warp.c
+++ libdrm-2.3.0/shared-core/mga_warp.c
@@ -0,0 +1,198 @@
+/* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*-
+ * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com
+ */
+/*
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * VA LINUX SYSTEMS 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.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+#include "mga_ucode.h"
+
+#define MGA_WARP_CODE_ALIGN		256	/* in bytes */
+
+#define WARP_UCODE_SIZE( which )					\
+	((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
+
+#define WARP_UCODE_INSTALL( which, where )				\
+do {									\
+	DRM_DEBUG( " pcbase = 0x%08lx  vcbase = %p\n", pcbase, vcbase );\
+	dev_priv->warp_pipe_phys[where] = pcbase;			\
+	memcpy( vcbase, which, sizeof(which) );				\
+	pcbase += WARP_UCODE_SIZE( which );				\
+	vcbase += WARP_UCODE_SIZE( which );				\
+} while (0)
+
+static const unsigned int mga_warp_g400_microcode_size =
+	       (WARP_UCODE_SIZE(warp_g400_tgz) +
+		WARP_UCODE_SIZE(warp_g400_tgza) +
+		WARP_UCODE_SIZE(warp_g400_tgzaf) +
+		WARP_UCODE_SIZE(warp_g400_tgzf) +
+		WARP_UCODE_SIZE(warp_g400_tgzs) +
+		WARP_UCODE_SIZE(warp_g400_tgzsa) +
+		WARP_UCODE_SIZE(warp_g400_tgzsaf) +
+		WARP_UCODE_SIZE(warp_g400_tgzsf) +
+		WARP_UCODE_SIZE(warp_g400_t2gz) +
+		WARP_UCODE_SIZE(warp_g400_t2gza) +
+		WARP_UCODE_SIZE(warp_g400_t2gzaf) +
+		WARP_UCODE_SIZE(warp_g400_t2gzf) +
+		WARP_UCODE_SIZE(warp_g400_t2gzs) +
+		WARP_UCODE_SIZE(warp_g400_t2gzsa) +
+		WARP_UCODE_SIZE(warp_g400_t2gzsaf) +
+		WARP_UCODE_SIZE(warp_g400_t2gzsf));
+
+static const unsigned int mga_warp_g200_microcode_size =
+	       (WARP_UCODE_SIZE(warp_g200_tgz) +
+		WARP_UCODE_SIZE(warp_g200_tgza) +
+		WARP_UCODE_SIZE(warp_g200_tgzaf) +
+		WARP_UCODE_SIZE(warp_g200_tgzf) +
+		WARP_UCODE_SIZE(warp_g200_tgzs) +
+		WARP_UCODE_SIZE(warp_g200_tgzsa) +
+		WARP_UCODE_SIZE(warp_g200_tgzsaf) +
+		WARP_UCODE_SIZE(warp_g200_tgzsf));
+
+
+unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
+{
+	switch (dev_priv->chipset) {
+	case MGA_CARD_TYPE_G400:
+	case MGA_CARD_TYPE_G550:
+		return PAGE_ALIGN(mga_warp_g400_microcode_size);
+	case MGA_CARD_TYPE_G200:
+		return PAGE_ALIGN(mga_warp_g200_microcode_size);
+	default:
+		DRM_ERROR("Unknown chipset value: 0x%x\n", dev_priv->chipset);
+		return 0;
+	}
+}
+
+static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv)
+{
+	unsigned char *vcbase = dev_priv->warp->handle;
+	unsigned long pcbase = dev_priv->warp->offset;
+
+	memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+
+	WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ);
+	WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF);
+	WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA);
+	WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF);
+	WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS);
+	WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF);
+	WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA);
+	WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF);
+
+	WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ);
+	WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF);
+	WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA);
+	WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF);
+	WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS);
+	WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF);
+	WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA);
+	WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF);
+
+	return 0;
+}
+
+static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv)
+{
+	unsigned char *vcbase = dev_priv->warp->handle;
+	unsigned long pcbase = dev_priv->warp->offset;
+
+	memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+
+	WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ);
+	WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF);
+	WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA);
+	WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF);
+	WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS);
+	WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF);
+	WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA);
+	WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF);
+
+	return 0;
+}
+
+int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
+{
+	const unsigned int size = mga_warp_microcode_size(dev_priv);
+
+	DRM_DEBUG("MGA ucode size = %d bytes\n", size);
+	if (size > dev_priv->warp->size) {
+		DRM_ERROR("microcode too large! (%u > %lu)\n",
+			  size, dev_priv->warp->size);
+		return DRM_ERR(ENOMEM);
+	}
+
+	switch (dev_priv->chipset) {
+	case MGA_CARD_TYPE_G400:
+	case MGA_CARD_TYPE_G550:
+		return mga_warp_install_g400_microcode(dev_priv);
+	case MGA_CARD_TYPE_G200:
+		return mga_warp_install_g200_microcode(dev_priv);
+	default:
+		return DRM_ERR(EINVAL);
+	}
+}
+
+#define WMISC_EXPECTED		(MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
+
+int mga_warp_init(drm_mga_private_t * dev_priv)
+{
+	u32 wmisc;
+
+	/* FIXME: Get rid of these damned magic numbers...
+	 */
+	switch (dev_priv->chipset) {
+	case MGA_CARD_TYPE_G400:
+	case MGA_CARD_TYPE_G550:
+		MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND);
+		MGA_WRITE(MGA_WGETMSB, 0x00000E00);
+		MGA_WRITE(MGA_WVRTXSZ, 0x00001807);
+		MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000);
+		break;
+	case MGA_CARD_TYPE_G200:
+		MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND);
+		MGA_WRITE(MGA_WGETMSB, 0x1606);
+		MGA_WRITE(MGA_WVRTXSZ, 7);
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
+			      MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE));
+	wmisc = MGA_READ(MGA_WMISC);
+	if (wmisc != WMISC_EXPECTED) {
+		DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n",
+			  wmisc, WMISC_EXPECTED);
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
--- libdrm-2.3.0.orig/shared-core/mga_dma.c
+++ libdrm-2.3.0/shared-core/mga_dma.c
@@ -0,0 +1,1182 @@
+/* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ */
+/* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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
+ * 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 mga_dma.c
+ * DMA support for MGA G200 / G400.
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Jeff Hartmann <jhartmann@valinux.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sarea.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+
+#define MGA_DEFAULT_USEC_TIMEOUT	10000
+#define MGA_FREELIST_DEBUG		0
+
+#define MINIMAL_CLEANUP    0
+#define FULL_CLEANUP       1
+static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup);
+
+/* ================================================================
+ * Engine control
+ */
+
+int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
+{
+	u32 status = 0;
+	int i;
+	DRM_DEBUG("\n");
+
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
+		if (status == MGA_ENDPRDMASTS) {
+			MGA_WRITE8(MGA_CRTC_INDEX, 0);
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+
+#if MGA_DMA_DEBUG
+	DRM_ERROR("failed!\n");
+	DRM_INFO("   status=0x%08x\n", status);
+#endif
+	return DRM_ERR(EBUSY);
+}
+
+static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+
+	DRM_DEBUG("\n");
+
+	/* The primary DMA stream should look like new right about now.
+	 */
+	primary->tail = 0;
+	primary->space = primary->size;
+	primary->last_flush = 0;
+
+	sarea_priv->last_wrap = 0;
+
+	/* FIXME: Reset counters, buffer ages etc...
+	 */
+
+	/* FIXME: What else do we need to reinitialize?  WARP stuff?
+	 */
+
+	return 0;
+}
+
+/* ================================================================
+ * Primary DMA stream
+ */
+
+void mga_do_dma_flush(drm_mga_private_t * dev_priv)
+{
+	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+	u32 head, tail;
+	u32 status = 0;
+	int i;
+	DMA_LOCALS;
+	DRM_DEBUG("\n");
+
+	/* We need to wait so that we can do an safe flush */
+	for (i = 0; i < dev_priv->usec_timeout; i++) {
+		status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
+		if (status == MGA_ENDPRDMASTS)
+			break;
+		DRM_UDELAY(1);
+	}
+
+	if (primary->tail == primary->last_flush) {
+		DRM_DEBUG("   bailing out...\n");
+		return;
+	}
+
+	tail = primary->tail + dev_priv->primary->offset;
+
+	/* We need to pad the stream between flushes, as the card
+	 * actually (partially?) reads the first of these commands.
+	 * See page 4-16 in the G400 manual, middle of the page or so.
+	 */
+	BEGIN_DMA(1);
+
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+	ADVANCE_DMA();
+
+	primary->last_flush = primary->tail;
+
+	head = MGA_READ(MGA_PRIMADDRESS);
+
+	if (head <= tail) {
+		primary->space = primary->size - primary->tail;
+	} else {
+		primary->space = head - tail;
+	}
+
+	DRM_DEBUG("   head = 0x%06lx\n", head - dev_priv->primary->offset);
+	DRM_DEBUG("   tail = 0x%06lx\n", tail - dev_priv->primary->offset);
+	DRM_DEBUG("  space = 0x%06x\n", primary->space);
+
+	mga_flush_write_combine();
+	MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
+
+	DRM_DEBUG("done.\n");
+}
+
+void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
+{
+	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+	u32 head, tail;
+	DMA_LOCALS;
+	DRM_DEBUG("\n");
+
+	BEGIN_DMA_WRAP();
+
+	DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000,
+		  MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+	ADVANCE_DMA();
+
+	tail = primary->tail + dev_priv->primary->offset;
+
+	primary->tail = 0;
+	primary->last_flush = 0;
+	primary->last_wrap++;
+
+	head = MGA_READ(MGA_PRIMADDRESS);
+
+	if (head == dev_priv->primary->offset) {
+		primary->space = primary->size;
+	} else {
+		primary->space = head - dev_priv->primary->offset;
+	}
+
+	DRM_DEBUG("   head = 0x%06lx\n", head - dev_priv->primary->offset);
+	DRM_DEBUG("   tail = 0x%06x\n", primary->tail);
+	DRM_DEBUG("   wrap = %d\n", primary->last_wrap);
+	DRM_DEBUG("  space = 0x%06x\n", primary->space);
+
+	mga_flush_write_combine();
+	MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
+
+	set_bit(0, &primary->wrapped);
+	DRM_DEBUG("done.\n");
+}
+
+void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
+{
+	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	u32 head = dev_priv->primary->offset;
+	DRM_DEBUG("\n");
+
+	sarea_priv->last_wrap++;
+	DRM_DEBUG("   wrap = %d\n", sarea_priv->last_wrap);
+
+	mga_flush_write_combine();
+	MGA_WRITE(MGA_PRIMADDRESS, head | MGA_DMA_GENERAL);
+
+	clear_bit(0, &primary->wrapped);
+	DRM_DEBUG("done.\n");
+}
+
+/* ================================================================
+ * Freelist management
+ */
+
+#define MGA_BUFFER_USED		~0
+#define MGA_BUFFER_FREE		0
+
+#if MGA_FREELIST_DEBUG
+static void mga_freelist_print(drm_device_t * dev)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_freelist_t *entry;
+
+	DRM_INFO("\n");
+	DRM_INFO("current dispatch: last=0x%x done=0x%x\n",
+		 dev_priv->sarea_priv->last_dispatch,
+		 (unsigned int)(MGA_READ(MGA_PRIMADDRESS) -
+				dev_priv->primary->offset));
+	DRM_INFO("current freelist:\n");
+
+	for (entry = dev_priv->head->next; entry; entry = entry->next) {
+		DRM_INFO("   %p   idx=%2d  age=0x%x 0x%06lx\n",
+			 entry, entry->buf->idx, entry->age.head,
+			 entry->age.head - dev_priv->primary->offset);
+	}
+	DRM_INFO("\n");
+}
+#endif
+
+static int mga_freelist_init(drm_device_t * dev, drm_mga_private_t * dev_priv)
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_mga_buf_priv_t *buf_priv;
+	drm_mga_freelist_t *entry;
+	int i;
+	DRM_DEBUG("count=%d\n", dma->buf_count);
+
+	dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+	if (dev_priv->head == NULL)
+		return DRM_ERR(ENOMEM);
+
+	memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
+	SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0);
+
+	for (i = 0; i < dma->buf_count; i++) {
+		buf = dma->buflist[i];
+		buf_priv = buf->dev_private;
+
+		entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+		if (entry == NULL)
+			return DRM_ERR(ENOMEM);
+
+		memset(entry, 0, sizeof(drm_mga_freelist_t));
+
+		entry->next = dev_priv->head->next;
+		entry->prev = dev_priv->head;
+		SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
+		entry->buf = buf;
+
+		if (dev_priv->head->next != NULL)
+			dev_priv->head->next->prev = entry;
+		if (entry->next == NULL)
+			dev_priv->tail = entry;
+
+		buf_priv->list_entry = entry;
+		buf_priv->discard = 0;
+		buf_priv->dispatched = 0;
+
+		dev_priv->head->next = entry;
+	}
+
+	return 0;
+}
+
+static void mga_freelist_cleanup(drm_device_t * dev)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_freelist_t *entry;
+	drm_mga_freelist_t *next;
+	DRM_DEBUG("\n");
+
+	entry = dev_priv->head;
+	while (entry) {
+		next = entry->next;
+		drm_free(entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+		entry = next;
+	}
+
+	dev_priv->head = dev_priv->tail = NULL;
+}
+
+#if 0
+/* FIXME: Still needed?
+ */
+static void mga_freelist_reset(drm_device_t * dev)
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_mga_buf_priv_t *buf_priv;
+	int i;
+
+	for (i = 0; i < dma->buf_count; i++) {
+		buf = dma->buflist[i];
+		buf_priv = buf->dev_private;
+		SET_AGE(&buf_priv->list_entry->age, MGA_BUFFER_FREE, 0);
+	}
+}
+#endif
+
+static drm_buf_t *mga_freelist_get(drm_device_t * dev)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_freelist_t *next;
+	drm_mga_freelist_t *prev;
+	drm_mga_freelist_t *tail = dev_priv->tail;
+	u32 head, wrap;
+	DRM_DEBUG("\n");
+
+	head = MGA_READ(MGA_PRIMADDRESS);
+	wrap = dev_priv->sarea_priv->last_wrap;
+
+	DRM_DEBUG("   tail=0x%06lx %d\n",
+		  tail->age.head ?
+		  tail->age.head - dev_priv->primary->offset : 0,
+		  tail->age.wrap);
+	DRM_DEBUG("   head=0x%06lx %d\n",
+		  head - dev_priv->primary->offset, wrap);
+
+	if (TEST_AGE(&tail->age, head, wrap)) {
+		prev = dev_priv->tail->prev;
+		next = dev_priv->tail;
+		prev->next = NULL;
+		next->prev = next->next = NULL;
+		dev_priv->tail = prev;
+		SET_AGE(&next->age, MGA_BUFFER_USED, 0);
+		return next->buf;
+	}
+
+	DRM_DEBUG("returning NULL!\n");
+	return NULL;
+}
+
+int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+	drm_mga_freelist_t *head, *entry, *prev;
+
+	DRM_DEBUG("age=0x%06lx wrap=%d\n",
+		  buf_priv->list_entry->age.head -
+		  dev_priv->primary->offset, buf_priv->list_entry->age.wrap);
+
+	entry = buf_priv->list_entry;
+	head = dev_priv->head;
+
+	if (buf_priv->list_entry->age.head == MGA_BUFFER_USED) {
+		SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
+		prev = dev_priv->tail;
+		prev->next = entry;
+		entry->prev = prev;
+		entry->next = NULL;
+	} else {
+		prev = head->next;
+		head->next = entry;
+		prev->prev = entry;
+		entry->prev = head;
+		entry->next = prev;
+	}
+
+	return 0;
+}
+
+/* ================================================================
+ * DMA initialization, cleanup
+ */
+
+int mga_driver_load(drm_device_t *dev, unsigned long flags)
+{
+	drm_mga_private_t * dev_priv;
+
+	dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+	if (!dev_priv)
+		return DRM_ERR(ENOMEM);
+
+	dev->dev_private = (void *)dev_priv;
+	memset(dev_priv, 0, sizeof(drm_mga_private_t));
+
+	dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
+	dev_priv->chipset = flags;
+
+	dev_priv->mmio_base = drm_get_resource_start(dev, 1);
+	dev_priv->mmio_size = drm_get_resource_len(dev, 1);
+
+	dev->counters += 3;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
+
+	return 0;
+}
+
+/**
+ * Bootstrap the driver for AGP DMA.
+ * 
+ * \todo
+ * Investigate whether there is any benifit to storing the WARP microcode in
+ * AGP memory.  If not, the microcode may as well always be put in PCI
+ * memory.
+ *
+ * \todo
+ * This routine needs to set dma_bs->agp_mode to the mode actually configured
+ * in the hardware.  Looking just at the Linux AGP driver code, I don't see
+ * an easy way to determine this.
+ *
+ * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
+ */
+static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
+				    drm_mga_dma_bootstrap_t * dma_bs)
+{
+	drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
+	unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+	int err;
+	unsigned  offset;
+	const unsigned secondary_size = dma_bs->secondary_bin_count
+		* dma_bs->secondary_bin_size;
+	const unsigned agp_size = (dma_bs->agp_size << 20);
+	drm_buf_desc_t req;
+	drm_agp_mode_t mode;
+	drm_agp_info_t info;
+	drm_agp_buffer_t agp_req;
+	drm_agp_binding_t bind_req;
+
+	/* Acquire AGP. */
+	err = drm_agp_acquire(dev);
+	if (err) {
+		DRM_ERROR("Unable to acquire AGP: %d\n", err);
+		return err;
+	}
+
+	err = drm_agp_info(dev, &info);
+	if (err) {
+		DRM_ERROR("Unable to get AGP info: %d\n", err);
+		return err;
+	}
+
+	mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode;
+	err = drm_agp_enable(dev, mode);
+	if (err) {
+		DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
+		return err;
+	}
+
+	/* In addition to the usual AGP mode configuration, the G200 AGP cards
+	 * need to have the AGP mode "manually" set.
+	 */
+
+	if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
+		if (mode.mode & 0x02) {
+			MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
+		} else {
+			MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
+		}
+	}
+
+
+	/* Allocate and bind AGP memory. */
+	agp_req.size = agp_size;
+	agp_req.type = 0;
+	err = drm_agp_alloc( dev, & agp_req );
+	if (err) {
+		dev_priv->agp_size = 0;
+		DRM_ERROR("Unable to allocate %uMB AGP memory\n",
+			  dma_bs->agp_size);
+		return err;
+	}
+
+	dev_priv->agp_size = agp_size;
+	dev_priv->agp_handle = agp_req.handle;
+
+	bind_req.handle = agp_req.handle;
+	bind_req.offset = 0;
+	err = drm_agp_bind( dev, &bind_req );
+	if (err) {
+		DRM_ERROR("Unable to bind AGP memory: %d\n", err);
+		return err;
+	}
+
+	/* Make drm_addbufs happy by not trying to create a mapping for less
+	 * than a page.
+	 */
+	if (warp_size < PAGE_SIZE)
+		warp_size = PAGE_SIZE;
+
+	offset = 0;
+	err = drm_addmap( dev, offset, warp_size,
+			  _DRM_AGP, _DRM_READ_ONLY, & dev_priv->warp );
+	if (err) {
+		DRM_ERROR("Unable to map WARP microcode: %d\n", err);
+		return err;
+	}
+
+	offset += warp_size;
+	err = drm_addmap( dev, offset, dma_bs->primary_size,
+			  _DRM_AGP, _DRM_READ_ONLY, & dev_priv->primary );
+	if (err) {
+		DRM_ERROR("Unable to map primary DMA region: %d\n", err);
+		return err;
+	}
+
+	offset += dma_bs->primary_size;
+	err = drm_addmap( dev, offset, secondary_size,
+			  _DRM_AGP, 0, & dev->agp_buffer_map );
+	if (err) {
+		DRM_ERROR("Unable to map secondary DMA region: %d\n", err);
+		return err;
+	}
+
+	(void) memset( &req, 0, sizeof(req) );
+	req.count = dma_bs->secondary_bin_count;
+	req.size = dma_bs->secondary_bin_size;
+	req.flags = _DRM_AGP_BUFFER;
+	req.agp_start = offset;
+
+	err = drm_addbufs_agp( dev, & req );
+	if (err) {
+		DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
+		return err;
+	}
+
+#ifdef __linux__
+	{
+		drm_map_list_t *_entry;
+		unsigned long agp_token = 0;
+
+		list_for_each_entry(_entry, &dev->maplist->head, head) {
+			if (_entry->map == dev->agp_buffer_map)
+				agp_token = _entry->user_token;
+		}
+		if (!agp_token)
+			return -EFAULT;
+
+		dev->agp_buffer_token = agp_token;
+	}
+#endif
+
+	offset += secondary_size;
+	err = drm_addmap( dev, offset, agp_size - offset,
+			  _DRM_AGP, 0, & dev_priv->agp_textures );
+	if (err) {
+		DRM_ERROR("Unable to map AGP texture region: %d\n", err);
+		return err;
+	}
+
+	drm_core_ioremap(dev_priv->warp, dev);
+	drm_core_ioremap(dev_priv->primary, dev);
+	drm_core_ioremap(dev->agp_buffer_map, dev);
+
+	if (!dev_priv->warp->handle ||
+	    !dev_priv->primary->handle || !dev->agp_buffer_map->handle) {
+		DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n",
+			  dev_priv->warp->handle, dev_priv->primary->handle,
+			  dev->agp_buffer_map->handle);
+		return DRM_ERR(ENOMEM);
+	}
+
+	dev_priv->dma_access = MGA_PAGPXFER;
+	dev_priv->wagp_enable = MGA_WAGP_ENABLE;
+
+	DRM_INFO("Initialized card for AGP DMA.\n");
+	return 0;
+}
+
+/**
+ * Bootstrap the driver for PCI DMA.
+ * 
+ * \todo
+ * The algorithm for decreasing the size of the primary DMA buffer could be
+ * better.  The size should be rounded up to the nearest page size, then
+ * decrease the request size by a single page each pass through the loop.
+ *
+ * \todo
+ * Determine whether the maximum address passed to drm_pci_alloc is correct.
+ * The same goes for drm_addbufs_pci.
+ * 
+ * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
+ */
+static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
+				    drm_mga_dma_bootstrap_t * dma_bs)
+{
+	drm_mga_private_t * const dev_priv = (drm_mga_private_t *) dev->dev_private;
+	unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+	unsigned int primary_size;
+	unsigned int bin_count;
+	int err;
+	drm_buf_desc_t req;
+
+	
+	if (dev->dma == NULL) {
+		DRM_ERROR("dev->dma is NULL\n");
+		return DRM_ERR(EFAULT);
+	}
+
+	/* Make drm_addbufs happy by not trying to create a mapping for less
+	 * than a page.
+	 */
+	if (warp_size < PAGE_SIZE)
+		warp_size = PAGE_SIZE;
+
+	/* The proper alignment is 0x100 for this mapping */
+	err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,
+			 _DRM_READ_ONLY, &dev_priv->warp);
+	if (err != 0) {
+		DRM_ERROR("Unable to create mapping for WARP microcode: %d\n",
+			  err);
+		return err;
+	}
+
+	/* Other than the bottom two bits being used to encode other
+	 * information, there don't appear to be any restrictions on the
+	 * alignment of the primary or secondary DMA buffers.
+	 */
+
+	for ( primary_size = dma_bs->primary_size
+	      ; primary_size != 0
+	      ; primary_size >>= 1 ) {
+		/* The proper alignment for this mapping is 0x04 */
+		err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
+				 _DRM_READ_ONLY, &dev_priv->primary);
+		if (!err)
+			break;
+	}
+
+	if (err != 0) {
+		DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);
+		return DRM_ERR(ENOMEM);
+	}
+
+	if (dev_priv->primary->size != dma_bs->primary_size) {
+		DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
+			 dma_bs->primary_size, 
+			 (unsigned) dev_priv->primary->size);
+		dma_bs->primary_size = dev_priv->primary->size;
+	}
+
+	for ( bin_count = dma_bs->secondary_bin_count
+	      ; bin_count > 0 
+	      ; bin_count-- ) {
+		(void) memset( &req, 0, sizeof(req) );
+		req.count = bin_count;
+		req.size = dma_bs->secondary_bin_size;
+
+		err = drm_addbufs_pci( dev, & req );
+		if (!err) {
+			break;
+		}
+	}
+	
+	if (bin_count == 0) {
+		DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
+		return err;
+	}
+
+	if (bin_count != dma_bs->secondary_bin_count) {
+		DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u "
+			 "to %u.\n", dma_bs->secondary_bin_count, bin_count);
+
+		dma_bs->secondary_bin_count = bin_count;
+	}
+
+	dev_priv->dma_access = 0;
+	dev_priv->wagp_enable = 0;
+
+	dma_bs->agp_mode = 0;
+
+	DRM_INFO("Initialized card for PCI DMA.\n");
+	return 0;
+}
+
+
+static int mga_do_dma_bootstrap(drm_device_t * dev,
+				drm_mga_dma_bootstrap_t * dma_bs)
+{
+	const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
+	int err;
+	drm_mga_private_t * const dev_priv =
+		(drm_mga_private_t *) dev->dev_private;
+
+
+	dev_priv->used_new_dma_init = 1;
+
+	/* The first steps are the same for both PCI and AGP based DMA.  Map
+	 * the cards MMIO registers and map a status page.
+	 */
+	err = drm_addmap( dev, dev_priv->mmio_base, dev_priv->mmio_size,
+			  _DRM_REGISTERS, _DRM_READ_ONLY, & dev_priv->mmio );
+	if (err) {
+		DRM_ERROR("Unable to map MMIO region: %d\n", err);
+		return err;
+	}
+
+
+	err = drm_addmap( dev, 0, SAREA_MAX, _DRM_SHM,
+			  _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
+			  & dev_priv->status );
+	if (err) {
+		DRM_ERROR("Unable to map status region: %d\n", err);
+		return err;
+	}
+
+
+	/* The DMA initialization procedure is slightly different for PCI and
+	 * AGP cards.  AGP cards just allocate a large block of AGP memory and
+	 * carve off portions of it for internal uses.  The remaining memory
+	 * is returned to user-mode to be used for AGP textures.
+	 */
+
+	if (is_agp) {
+		err = mga_do_agp_dma_bootstrap(dev, dma_bs);
+	}
+	
+	/* If we attempted to initialize the card for AGP DMA but failed,
+	 * clean-up any mess that may have been created.
+	 */
+
+	if (err) {
+		mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
+	}
+
+
+	/* Not only do we want to try and initialized PCI cards for PCI DMA,
+	 * but we also try to initialized AGP cards that could not be
+	 * initialized for AGP DMA.  This covers the case where we have an AGP
+	 * card in a system with an unsupported AGP chipset.  In that case the
+	 * card will be detected as AGP, but we won't be able to allocate any
+	 * AGP memory, etc.
+	 */
+
+	if (!is_agp || err) {
+		err = mga_do_pci_dma_bootstrap(dev, dma_bs);
+	}
+
+
+	return err;
+}
+
+int mga_dma_bootstrap(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_dma_bootstrap_t bootstrap;
+	int err;
+	static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
+	const drm_mga_private_t * const dev_priv = 
+		(drm_mga_private_t *) dev->dev_private;
+
+
+	DRM_COPY_FROM_USER_IOCTL(bootstrap,
+				 (drm_mga_dma_bootstrap_t __user *) data,
+				 sizeof(bootstrap));
+
+	err = mga_do_dma_bootstrap(dev, & bootstrap);
+	if (err) {
+		mga_do_cleanup_dma(dev, FULL_CLEANUP);
+		return err;
+	}
+
+	if (dev_priv->agp_textures != NULL) {
+		bootstrap.texture_handle = dev_priv->agp_textures->offset;
+		bootstrap.texture_size = dev_priv->agp_textures->size;
+	} else {
+		bootstrap.texture_handle = 0;
+		bootstrap.texture_size = 0;
+	}
+
+	bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];
+
+	DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data,
+			       bootstrap, sizeof(bootstrap));
+
+	return 0;
+}
+
+
+static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
+{
+	drm_mga_private_t *dev_priv;
+	int ret;
+	DRM_DEBUG("\n");
+
+
+	dev_priv = dev->dev_private;
+
+	if (init->sgram) {
+		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
+	} else {
+		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
+	}
+	dev_priv->maccess = init->maccess;
+
+	dev_priv->fb_cpp = init->fb_cpp;
+	dev_priv->front_offset = init->front_offset;
+	dev_priv->front_pitch = init->front_pitch;
+	dev_priv->back_offset = init->back_offset;
+	dev_priv->back_pitch = init->back_pitch;
+
+	dev_priv->depth_cpp = init->depth_cpp;
+	dev_priv->depth_offset = init->depth_offset;
+	dev_priv->depth_pitch = init->depth_pitch;
+
+	/* FIXME: Need to support AGP textures...
+	 */
+	dev_priv->texture_offset = init->texture_offset[0];
+	dev_priv->texture_size = init->texture_size[0];
+
+	DRM_GETSAREA();
+
+	if (!dev_priv->sarea) {
+		DRM_ERROR("failed to find sarea!\n");
+		return DRM_ERR(EINVAL);
+	}
+
+	if (! dev_priv->used_new_dma_init) {
+
+		dev_priv->dma_access = MGA_PAGPXFER;
+		dev_priv->wagp_enable = MGA_WAGP_ENABLE;
+
+		dev_priv->status = drm_core_findmap(dev, init->status_offset);
+		if (!dev_priv->status) {
+			DRM_ERROR("failed to find status page!\n");
+			return DRM_ERR(EINVAL);
+		}
+		dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+		if (!dev_priv->mmio) {
+			DRM_ERROR("failed to find mmio region!\n");
+			return DRM_ERR(EINVAL);
+		}
+		dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
+		if (!dev_priv->warp) {
+			DRM_ERROR("failed to find warp microcode region!\n");
+			return DRM_ERR(EINVAL);
+		}
+		dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
+		if (!dev_priv->primary) {
+			DRM_ERROR("failed to find primary dma region!\n");
+			return DRM_ERR(EINVAL);
+		}
+		dev->agp_buffer_token = init->buffers_offset;
+		dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+		if (!dev->agp_buffer_map) {
+			DRM_ERROR("failed to find dma buffer region!\n");
+			return DRM_ERR(EINVAL);
+		}
+
+		drm_core_ioremap(dev_priv->warp, dev);
+		drm_core_ioremap(dev_priv->primary, dev);
+		drm_core_ioremap(dev->agp_buffer_map, dev);
+	}
+
+	dev_priv->sarea_priv =
+	    (drm_mga_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+				 init->sarea_priv_offset);
+
+	if (!dev_priv->warp->handle ||
+	    !dev_priv->primary->handle ||
+	    ((dev_priv->dma_access != 0) &&
+	     ((dev->agp_buffer_map == NULL) ||
+	      (dev->agp_buffer_map->handle == NULL)))) {
+		DRM_ERROR("failed to ioremap agp regions!\n");
+		return DRM_ERR(ENOMEM);
+	}
+
+	ret = mga_warp_install_microcode(dev_priv);
+	if (ret != 0) {
+		DRM_ERROR("failed to install WARP ucode: %d!\n", ret);
+		return ret;
+	}
+
+	ret = mga_warp_init(dev_priv);
+	if (ret != 0) {
+		DRM_ERROR("failed to init WARP engine: %d!\n", ret);
+		return ret;
+	}
+
+	dev_priv->prim.status = (u32 *) dev_priv->status->handle;
+
+	mga_do_wait_for_idle(dev_priv);
+
+	/* Init the primary DMA registers.
+	 */
+	MGA_WRITE(MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL);
+#if 0
+	MGA_WRITE(MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 |	/* Soft trap, SECEND, SETUPEND */
+		  MGA_PRIMPTREN1);	/* DWGSYNC */
+#endif
+
+	dev_priv->prim.start = (u8 *) dev_priv->primary->handle;
+	dev_priv->prim.end = ((u8 *) dev_priv->primary->handle
+			      + dev_priv->primary->size);
+	dev_priv->prim.size = dev_priv->primary->size;
+
+	dev_priv->prim.tail = 0;
+	dev_priv->prim.space = dev_priv->prim.size;
+	dev_priv->prim.wrapped = 0;
+
+	dev_priv->prim.last_flush = 0;
+	dev_priv->prim.last_wrap = 0;
+
+	dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
+
+	dev_priv->prim.status[0] = dev_priv->primary->offset;
+	dev_priv->prim.status[1] = 0;
+
+	dev_priv->sarea_priv->last_wrap = 0;
+	dev_priv->sarea_priv->last_frame.head = 0;
+	dev_priv->sarea_priv->last_frame.wrap = 0;
+
+	if (mga_freelist_init(dev, dev_priv) < 0) {
+		DRM_ERROR("could not initialize freelist\n");
+		return DRM_ERR(ENOMEM);
+	}
+
+	return 0;
+}
+
+static int mga_do_cleanup_dma(drm_device_t * dev, int full_cleanup)
+{
+	int err = 0;
+	DRM_DEBUG("\n");
+
+	/* Make sure interrupts are disabled here because the uninstall ioctl
+	 * may not have been called from userspace and after dev_private
+	 * is freed, it's too late.
+	 */
+	if (dev->irq_enabled)
+		drm_irq_uninstall(dev);
+
+	if (dev->dev_private) {
+		drm_mga_private_t *dev_priv = dev->dev_private;
+
+		if ((dev_priv->warp != NULL)
+		    && (dev_priv->warp->type != _DRM_CONSISTENT))
+			drm_core_ioremapfree(dev_priv->warp, dev);
+
+		if ((dev_priv->primary != NULL) 
+		    && (dev_priv->primary->type != _DRM_CONSISTENT))
+			drm_core_ioremapfree(dev_priv->primary, dev);
+
+		if (dev->agp_buffer_map != NULL)
+			drm_core_ioremapfree(dev->agp_buffer_map, dev);
+
+		if (dev_priv->used_new_dma_init) {
+			if (dev_priv->agp_handle != 0) {
+				drm_agp_binding_t unbind_req;
+				drm_agp_buffer_t free_req;
+
+				unbind_req.handle = dev_priv->agp_handle;
+				drm_agp_unbind(dev, &unbind_req);
+
+				free_req.handle = dev_priv->agp_handle;
+				drm_agp_free(dev, &free_req);
+
+				dev_priv->agp_textures = NULL;
+				dev_priv->agp_size = 0;
+				dev_priv->agp_handle = 0;
+			}
+
+			if ((dev->agp != NULL) && dev->agp->acquired) {
+				err = drm_agp_release(dev);
+			}
+		}
+
+		dev_priv->warp = NULL;
+		dev_priv->primary = NULL;
+		dev_priv->sarea = NULL;
+		dev_priv->sarea_priv = NULL;
+		dev->agp_buffer_map = NULL;
+
+		if (full_cleanup) {
+			dev_priv->mmio = NULL;
+			dev_priv->status = NULL;
+			dev_priv->used_new_dma_init = 0;
+		}
+
+		memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
+		dev_priv->warp_pipe = 0;
+		memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+
+		if (dev_priv->head != NULL) {
+			mga_freelist_cleanup(dev);
+		}
+	}
+
+	return 0;
+}
+
+int mga_dma_init(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_init_t init;
+	int err;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data,
+				 sizeof(init));
+
+	switch (init.func) {
+	case MGA_INIT_DMA:
+		err = mga_do_init_dma(dev, &init);
+		if (err) {
+			(void) mga_do_cleanup_dma(dev, FULL_CLEANUP);
+		}
+		return err;
+	case MGA_CLEANUP_DMA:
+		return mga_do_cleanup_dma(dev, FULL_CLEANUP);
+	}
+
+	return DRM_ERR(EINVAL);
+}
+
+/* ================================================================
+ * Primary DMA stream management
+ */
+
+int mga_dma_flush(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+	drm_lock_t lock;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(lock, (drm_lock_t __user *) data,
+				 sizeof(lock));
+
+	DRM_DEBUG("%s%s%s\n",
+		  (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
+		  (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
+		  (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "");
+
+	WRAP_WAIT_WITH_RETURN(dev_priv);
+
+	if (lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
+		mga_do_dma_flush(dev_priv);
+	}
+
+	if (lock.flags & _DRM_LOCK_QUIESCENT) {
+#if MGA_DMA_DEBUG
+		int ret = mga_do_wait_for_idle(dev_priv);
+		if (ret < 0)
+			DRM_INFO("%s: -EBUSY\n", __FUNCTION__);
+		return ret;
+#else
+		return mga_do_wait_for_idle(dev_priv);
+#endif
+	} else {
+		return 0;
+	}
+}
+
+int mga_dma_reset(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	return mga_do_dma_reset(dev_priv);
+}
+
+/* ================================================================
+ * DMA buffer management
+ */
+
+static int mga_dma_get_buffers(DRMFILE filp, drm_device_t * dev, drm_dma_t * d)
+{
+	drm_buf_t *buf;
+	int i;
+
+	for (i = d->granted_count; i < d->request_count; i++) {
+		buf = mga_freelist_get(dev);
+		if (!buf)
+			return DRM_ERR(EAGAIN);
+
+		buf->filp = filp;
+
+		if (DRM_COPY_TO_USER(&d->request_indices[i],
+				     &buf->idx, sizeof(buf->idx)))
+			return DRM_ERR(EFAULT);
+		if (DRM_COPY_TO_USER(&d->request_sizes[i],
+				     &buf->total, sizeof(buf->total)))
+			return DRM_ERR(EFAULT);
+
+		d->granted_count++;
+	}
+	return 0;
+}
+
+int mga_dma_buffers(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_device_dma_t *dma = dev->dma;
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+	drm_dma_t __user *argp = (void __user *)data;
+	drm_dma_t d;
+	int ret = 0;
+
+	LOCK_TEST_WITH_RETURN(dev, filp);
+
+	DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d));
+
+	/* Please don't send us buffers.
+	 */
+	if (d.send_count != 0) {
+		DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+			  DRM_CURRENTPID, d.send_count);
+		return DRM_ERR(EINVAL);
+	}
+
+	/* We'll send you buffers.
+	 */
+	if (d.request_count < 0 || d.request_count > dma->buf_count) {
+		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+			  DRM_CURRENTPID, d.request_count, dma->buf_count);
+		return DRM_ERR(EINVAL);
+	}
+
+	WRAP_TEST_WITH_RETURN(dev_priv);
+
+	d.granted_count = 0;
+
+	if (d.request_count) {
+		ret = mga_dma_get_buffers(filp, dev, &d);
+	}
+
+	DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d));
+
+	return ret;
+}
+
+/**
+ * Called just before the module is unloaded.
+ */
+int mga_driver_unload(drm_device_t * dev)
+{
+	drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+/**
+ * Called when the last opener of the device is closed.
+ */
+void mga_driver_lastclose(drm_device_t * dev)
+{
+	mga_do_cleanup_dma(dev, FULL_CLEANUP);
+}
+
+int mga_driver_dma_quiescent(drm_device_t * dev)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	return mga_do_wait_for_idle(dev_priv);
+}
--- libdrm-2.3.0.orig/debian/copyright
+++ libdrm-2.3.0/debian/copyright
@@ -0,0 +1,58 @@
+This package was debianized by Marcelo E. Magallon <mmagallo@debian.org> on
+Fri, 19 Aug 2005 21:11:18 -0600.
+
+It was downloaded from http://people.freedesktop.org/~ajax/libdrm/
+
+Copyright Holder: Adam Jackson <ajax at nwnk dot net>
+
+License:
+
+ 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.
+
+------------------------------------------------------------------------
+
+ Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ 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 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.
+
--- libdrm-2.3.0.orig/debian/patches/101_poulsbo_headers.patch
+++ libdrm-2.3.0/debian/patches/101_poulsbo_headers.patch
@@ -0,0 +1,1196 @@
+diff -Nurp libdrm-2.3.0/shared-core/Makefile.am libdrm-psb/shared-core/Makefile.am
+--- libdrm-2.3.0/shared-core/Makefile.am	2006-11-07 20:03:26.000000000 -0800
++++ libdrm-psb/shared-core/Makefile.am	2007-08-01 17:43:36.000000000 -0700
+@@ -35,4 +35,7 @@ klibdrminclude_HEADERS = \
+                          sis_drm.h \
+                          via_drm.h \
+                          r300_reg.h \
+-                         via_3d_reg.h
++                         via_3d_reg.h \
++			 psb_drm.h \
++			 psb_reg.h \
++			 psb_drv.h
+diff -Nurp libdrm-2.3.0/shared-core/Makefile.in libdrm-psb/shared-core/Makefile.in
+--- libdrm-2.3.0/shared-core/Makefile.in	2006-11-07 21:38:39.000000000 -0800
++++ libdrm-psb/shared-core/Makefile.in	2007-08-01 17:43:36.000000000 -0700
+@@ -194,7 +194,11 @@ klibdrminclude_HEADERS = \
+                          sis_drm.h \
+                          via_drm.h \
+                          r300_reg.h \
+-                         via_3d_reg.h
++                         via_3d_reg.h \
++                         psb_drm.h \
++                         psb_reg.h \
++                         psb_drv.h
++
+ 
+ all: all-am
+ 
+diff -Nurp libdrm-2.3.0/shared-core/psb_drm.h libdrm-psb/shared-core/psb_drm.h
+--- libdrm-2.3.0/shared-core/psb_drm.h	1969-12-31 16:00:00.000000000 -0800
++++ libdrm-psb/shared-core/psb_drm.h	2007-08-01 17:43:36.000000000 -0700
+@@ -0,0 +1,158 @@
++/**************************************************************************
++ * Copyright (c) Intel Corp. 2007.
++ * All Rights Reserved.
++ *
++ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
++ * develop this driver.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and 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
++ * THE COPYRIGHT HOLDERS, AUTHORS 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 _PSB_DRM_H_
++#define _PSB_DRM_H_
++
++#if defined(__linux__) && !defined(__KERNEL__)
++#include<stdint.h>
++#endif
++
++#define DRM_PSB_SAREA_MAJOR 0
++#define DRM_PSB_SAREA_MINOR 1
++#define PSB_FIXED_SHIFT 16
++#define PSB_PLUG_IOCTL_START 16
++/*
++ * Public memory types.
++ */
++
++#define DRM_PSB_MEM_MMU DRM_BO_MEM_PRIV1
++#define DRM_PSB_FLAG_MEM_MMU DRM_BO_FLAG_MEM_PRIV1
++
++#define DRM_PSB_MEM_APER DRM_BO_MEM_PRIV2
++#define DRM_PSB_FLAG_MEM_APER DRM_BO_FLAG_MEM_PRIV2
++
++
++typedef int32_t psb_fixed;
++typedef uint32_t psb_ufixed;
++
++static inline psb_fixed psb_int_to_fixed(int a)
++{
++	return a * (1 << PSB_FIXED_SHIFT);
++}
++
++static inline psb_ufixed psb_unsigned_to_ufixed(unsigned int a)
++{
++	return a << PSB_FIXED_SHIFT;
++}
++
++typedef struct drm_psb_scanout {
++	uint32_t buffer_id;	/* DRM buffer object ID */
++	uint32_t rotation;	/* Rotation as in RR_rotation definitions */
++	uint32_t stride;	/* Buffer stride in bytes */
++	uint32_t depth;		/* Buffer depth in bits (NOT) bpp */
++	uint32_t width;		/* Buffer width in pixels */
++	uint32_t height;	/* Buffer height in lines */
++	psb_fixed transform[3][3];	/* Buffer composite transform */
++	/* (scaling, rot, reflect) */
++} drm_psb_scanout_t;
++
++#define DRM_PSB_SAREA_OWNERS 16
++#define DRM_PSB_SAREA_OWNER_2D 0
++#define DRM_PSB_SAREA_OWNER_3D 1
++
++#define DRM_PSB_SAREA_SCANOUTS 3
++
++typedef struct drm_psb_sarea {
++	/* Track changes of this data structure */
++
++	uint32_t major;
++	uint32_t minor;
++
++	/* Last context to touch part of hw */
++	uint32_t ctx_owners[DRM_PSB_SAREA_OWNERS];
++
++	/* Definition of front- and rotated buffers */
++	uint32_t num_scanouts;
++	drm_psb_scanout_t scanouts[DRM_PSB_SAREA_SCANOUTS];
++
++        int pipeA_x;
++        int pipeA_y;
++        int pipeA_w;
++        int pipeA_h;
++        int pipeB_x;
++        int pipeB_y;
++        int pipeB_w;
++        int pipeB_h;
++} drm_psb_sarea_t;
++
++/*
++ * Padding needed so that we can
++ * so that PAGESIZE % sizeof(drm_psb_reloc) == 0.
++ */
++
++typedef struct drm_psb_reloc {
++	enum {
++		psb_reloc_offset,
++		psb_reloc_stride
++	} reloc_op;
++	uint32_t delta;
++	uint32_t where;
++	uint32_t buffer;
++	uint32_t mask;
++	uint32_t shift;
++	uint32_t align_shift;
++	uint32_t dest_buffer;
++} drm_psb_reloc_t;
++
++#define PSB_ENGINE_2D 0
++#define PSB_ENGINE_3D 1
++#define PSB_ENGINE_VIDEO 2
++
++typedef struct drm_psb_cmdbuf_arg {
++	drm_u64_t buffer_list;	/* List of buffers to validate */
++	drm_u64_t clip_rects;	/* See i915 counterpart */
++
++	uint32_t cmdbuf_handle;	/* Command buffer object */
++	uint32_t cmdbuf_offset;
++	uint32_t cmdbuf_size;
++	
++	uint32_t reloc_handle;	/* Reloc buffer object */
++	uint32_t reloc_offset;
++	uint32_t num_relocs;
++
++	int32_t damage;		/* Damage front buffer with cliprects */
++	/* Not implemented yet */
++	uint32_t fence_flags;
++	uint32_t engine;
++	uint32_t fence_handle;	/* Return: 
++				   User space fence handle if requested */
++} drm_psb_cmdbuf_arg_t;
++
++#define DRM_PSB_CMDBUF          0x00
++#define DRM_PSB_TEST            0x01
++
++struct drm_psb_dev_info_arg {
++	uint32_t num_use_attribute_registers;
++};
++#define DRM_PSB_DEVINFO         0x01
++
++#endif
+diff -Nurp libdrm-2.3.0/shared-core/psb_drv.h libdrm-psb/shared-core/psb_drv.h
+--- libdrm-2.3.0/shared-core/psb_drv.h	1969-12-31 16:00:00.000000000 -0800
++++ libdrm-psb/shared-core/psb_drv.h	2007-08-01 17:43:36.000000000 -0700
+@@ -0,0 +1,528 @@
++/**************************************************************************
++ * Copyright (c) Intel Corp. 2007.
++ * All Rights Reserved.
++ *
++ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
++ * develop this driver.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and 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
++ * THE COPYRIGHT HOLDERS, AUTHORS 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 _PSB_DRV_H_
++#define _PSB_DRV_H_
++
++#include "psb_drm.h"
++
++enum {
++	CHIP_PSB_8108 = 0
++};
++
++#define DRIVER_NAME "psb"
++#define DRIVER_DESC "drm driver for the Intel Poulsbo chipset"
++#define DRIVER_AUTHOR "Tungsten Graphics Inc."
++
++#define PSB_DRM_DRIVER_DATE "20060307"
++#define PSB_DRM_DRIVER_MAJOR 0
++#define PSB_DRM_DRIVER_MINOR 1
++#define PSB_DRM_DRIVER_PATCHLEVEL 0
++#define PSB_VDC_OFFSET           0x00000000
++#define PSB_VDC_SIZE             0x000080000
++#define PSB_SGX_SAVE_SIZE        0x1000
++#define PSB_SGX_SIZE             0x8000
++#define PSB_SGX_OFFSET           0x00040000
++#define PSB_MMIO_RESOURCE        0
++#define PSB_GATT_RESOURCE        2
++#define PSB_GTT_RESOURCE         3
++#define PSB_GMCH_CTRL            0x52
++#define PSB_BSM                  0x5C
++#define _PSB_GMCH_ENABLED        0x4
++#define PSB_PGETBL_CTL           0x2020
++#define _PSB_PGETBL_ENABLED      0x00000001
++#define PSB_SGX_2D_SLAVE_PORT    0x4000
++#define PSB_TT_PRIV0_LIMIT       (256*1024*1024)
++#define PSB_TT_PRIV0_PLIMIT      (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
++#define PSB_NUM_VALIDATE_BUFFERS 256
++#define PSB_MEM_MMU_START        0x20000000
++#define PSB_MEM_KERNEL_START     0x10000000
++
++#define DRM_PSB_MEM_KERNEL       DRM_BO_MEM_PRIV0
++#define DRM_PSB_FLAG_MEM_KERNEL  DRM_BO_FLAG_MEM_PRIV0
++
++/*
++ * Flags for external memory type field.
++ */
++
++#define PSB_MMU_CACHED_MEMORY     0x0001	/* Bind to MMU only */
++#define PSB_MMU_RO_MEMORY         0x0002	/* MMU RO memory */
++#define PSB_MMU_WO_MEMORY         0x0004	/* MMU WO memory */
++
++/*
++ * PTE's and PDE's
++ */
++
++#define PSB_PDE_MASK              0x003FFFFF
++#define PSB_PDE_SHIFT             22
++#define PSB_PTE_SHIFT             12
++
++#define PSB_PTE_VALID             0x0001	/* PTE / PDE valid */
++#define PSB_PTE_WO                0x0002	/* Write only */
++#define PSB_PTE_RO                0x0004	/* Read only */
++#define PSB_PTE_CACHED            0x0008	/* CPU cache coherent */
++
++/*
++ * VDC registers and bits
++ */
++#define PSB_HWSTAM                0x2098
++#define PSB_INSTPM                0x20C0
++#define PSB_INT_IDENTITY_R        0x20A4
++#define _PSB_VSYNC_PIPEB_FLAG     (1<<5)
++#define _PSB_VSYNC_PIPEA_FLAG     (1<<7)
++#define _PSB_IRQ_SGX_FLAG         (1<<18)
++#define _PSG_IRQ_MSVDX_FLAG       (1<<19)
++#define PSB_INT_MASK_R            0x20A8
++#define PSB_INT_ENABLE_R          0x20A0
++#define PSB_PIPEASTAT             0x70024
++#define _PSB_VBLANK_INTERRUPT_ENABLE (1 << 17)
++#define _PSB_VBLANK_CLEAR         (1 << 1)
++#define PSB_PIPEBSTAT             0x71024
++
++#define _PSB_MMU_ER_MASK      0x0001FF00
++#define _PSB_MMU_ER_HOST      (1 << 16)
++#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)
++
++#define VCLK_DIVISOR_VGA0   0x6000
++#define VCLK_DIVISOR_VGA1   0x6004
++#define VCLK_POST_DIV       0x6010
++
++#define DRM_DRIVER_PRIVATE_T drm_psb_private_t
++#define I915_WRITE(_offs, _val) \
++  iowrite32(_val, dev_priv->vdc_reg + (_offs))
++#define I915_READ(_offs) \
++  ioread32(dev_priv->vdc_reg + (_offs))
++
++/*
++ * User options.
++ */
++
++struct drm_psb_uopt{
++	int disable_clock_gating;
++};
++
++
++struct psb_gtt{
++        struct drm_device *dev;
++        int initialized;
++	u32 gatt_start;
++	u32 gtt_start;
++	u32 gtt_phys_start;
++	unsigned gtt_pages;
++        unsigned gatt_pages;
++	u32 stolen_base;
++	u32 pge_ctl;
++	u16 gmch_ctrl;
++	unsigned long stolen_size;
++	u32 *gtt_map;
++	struct rw_semaphore sem;
++};
++
++/*
++ * Non-GPL plugins.
++ */
++
++#define MAX_PLUGIN_IOCTLS 20
++
++struct psb_plugin_private;
++typedef int (*psb_ioctl_func) (DRM_IOCTL_ARGS);
++
++struct drm_psb_plugin{
++	struct psb_plugin_private *(*init) (struct drm_device *);
++	void (*takedown)(struct psb_plugin_private *);
++	int (*firstopen)(struct psb_plugin_private *);
++	int (*lastclose)(struct psb_plugin_private *);
++        int (*suspend)(struct psb_plugin_private *, pm_message_t);
++	int (*resume) (struct psb_plugin_private *);
++        irqreturn_t (*irq_handler) (struct psb_plugin_private *);
++	psb_ioctl_func *ioctls;
++        int num_ioctls;
++};	
++
++struct dev_list_entry {
++	struct list_head head;
++	struct drm_device *dev;
++	int plugin_initialised;
++};
++
++typedef struct drm_psb_private {
++	unsigned long chipset;
++  
++        struct dev_list_entry dev_list;
++	struct drm_psb_dev_info_arg dev_info;
++	struct drm_psb_uopt uopt;
++
++	struct psb_gtt *pg;
++
++	struct page *scratch_page;
++	struct page *comm_page;
++
++	volatile u32 *comm;
++	u32 comm_mmu_offset;
++	u32 mmu_2d_offset;
++	u32 sequence;
++	u32 *sgx_save;
++	int engine_lockup_2d;
++
++	struct psb_mmu_driver *mmu;
++	struct psb_mmu_pd *pf_pd;
++
++	u8 *sgx_reg;
++	u8 *vdc_reg;
++	u32 gatt_free_offset;
++
++	/*
++	 * Fencing / irq.
++	 */
++
++	u32 sgx_irq_mask;
++	u32 vdc_irq_mask;
++       
++	spinlock_t irqmask_lock;
++	int fence0_irq_on;
++	int irq_enabled;
++
++	/*
++	 * Memory managers
++	 */
++
++	int have_vram;
++	int have_tt;
++	int have_mem_mmu;
++	int have_mem_aper;
++	int have_mem_kernel;
++	struct mutex temp_mem;
++
++	/*
++	 * Command submission.
++	 */
++
++	drm_buffer_object_t *buffers[PSB_NUM_VALIDATE_BUFFERS];
++
++	/*
++	 * SAREA
++	 */
++	drm_psb_sarea_t *sarea_priv;
++
++	/*
++	 * LVDS info 
++	 */
++	int backlight_duty_cycle;  /* restore backlight to this value */
++	bool panel_wants_dither;
++	struct drm_display_mode *panel_fixed_mode;
++
++	/* 
++	 * Register state 
++	 */
++	u32 saveDSPACNTR;
++	u32 saveDSPBCNTR;
++	u32 savePIPEACONF;
++	u32 savePIPEBCONF;
++	u32 savePIPEASRC;
++	u32 savePIPEBSRC;
++	u32 saveFPA0;
++	u32 saveFPA1;
++	u32 saveDPLL_A;
++	u32 saveDPLL_A_MD;
++	u32 saveHTOTAL_A;
++	u32 saveHBLANK_A;
++	u32 saveHSYNC_A;
++	u32 saveVTOTAL_A;
++	u32 saveVBLANK_A;
++	u32 saveVSYNC_A;
++	u32 saveDSPASTRIDE;
++	u32 saveDSPASIZE;
++	u32 saveDSPAPOS;
++	u32 saveDSPABASE;
++	u32 saveDSPASURF;
++	u32 saveFPB0;
++	u32 saveFPB1;
++	u32 saveDPLL_B;
++	u32 saveDPLL_B_MD;
++	u32 saveHTOTAL_B;
++	u32 saveHBLANK_B;
++	u32 saveHSYNC_B;
++	u32 saveVTOTAL_B;
++	u32 saveVBLANK_B;
++	u32 saveVSYNC_B;
++	u32 saveDSPBSTRIDE;
++	u32 saveDSPBSIZE;
++	u32 saveDSPBPOS;
++	u32 saveDSPBBASE;
++	u32 saveDSPBSURF;
++	u32 saveVCLK_DIVISOR_VGA0;
++	u32 saveVCLK_DIVISOR_VGA1;
++	u32 saveVCLK_POST_DIV;
++	u32 saveVGACNTRL;
++	u32 saveADPA;
++	u32 saveLVDS;
++	u32 saveDVOA;
++	u32 saveDVOB;
++	u32 saveDVOC;
++	u32 savePP_ON;
++	u32 savePP_OFF;
++	u32 savePP_CONTROL;
++	u32 savePP_CYCLE;
++	u32 savePFIT_CONTROL;
++	u32 savePaletteA[256];
++	u32 savePaletteB[256];
++	u32 saveBLC_PWM_CTL;
++
++        struct psb_plugin_private *plug_priv;
++} drm_psb_private_t;
++
++struct psb_mmu_driver;
++
++extern struct psb_mmu_driver *psb_mmu_driver_init(u8 __iomem * registers);
++extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
++extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver);
++extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, u32 mmu_offset,
++			       u32 gtt_start, __u32 gtt_pages);
++extern void psb_mmu_test(struct psb_mmu_driver *driver, u32 offset);
++extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver);
++extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
++extern void psb_mmu_flush(struct psb_mmu_driver *driver);
++
++/*
++ * Enable / disable MMU for different requestors.
++ */
++
++extern void psb_mmu_enable_requestor(struct psb_mmu_driver *driver, u32 mask);
++extern void psb_mmu_disable_requestor(struct psb_mmu_driver *driver,
++				      u32 mask);
++extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
++extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
++				unsigned long address, u32 num_pages,
++				u32 desired_tile_stride, u32 hw_tile_stride,
++				int type);
++extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
++				 u32 num_pages, __u32 desired_tile_stride,
++				 u32 hw_tile_stride);
++/*
++ * psb_sgx.c 
++ */
++
++extern int psb_blit_sequence(drm_psb_private_t * dev_priv);
++extern void psb_init_2d(drm_psb_private_t * dev_priv);
++extern int drm_psb_idle(drm_device_t * dev);
++extern int psb_emit_2d_copy_blit(drm_device_t * dev,
++				 u32 src_offset,
++				 u32 dst_offset, __u32 pages, int direction);
++extern int psb_cmdbuf_ioctl(DRM_IOCTL_ARGS);
++
++/*
++ * psb_irq.c
++ */
++
++extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
++extern void psb_irq_preinstall(drm_device_t * dev);
++extern void psb_irq_postinstall(drm_device_t * dev);
++extern void psb_irq_uninstall(drm_device_t * dev);
++
++/*
++ * psb_fence.c
++ */
++
++extern void psb_poke_flush(drm_device_t * dev, uint32_t class);
++extern int psb_fence_emit_sequence(drm_device_t * dev, uint32_t class,
++				   uint32_t flags, uint32_t * sequence,
++				   uint32_t * native_type);
++extern void psb_fence_handler(drm_device_t * dev, uint32_t class);
++extern int psb_fence_has_irq(drm_device_t * dev, uint32_t class,
++			     uint32_t flags);
++extern void psb_2D_irq_off(drm_psb_private_t * dev_priv);
++extern void psb_2D_irq_on(drm_psb_private_t * dev_priv);
++
++/*
++ * psb_buffer.c 
++ */
++extern drm_ttm_backend_t *drm_psb_tbe_init(drm_device_t * dev);
++extern int psb_fence_types(drm_buffer_object_t * bo, uint32_t * class,
++			   uint32_t * type);
++extern uint32_t psb_evict_mask(drm_buffer_object_t * bo);
++extern int psb_invalidate_caches(drm_device_t * dev, uint32_t flags);
++extern int psb_init_mem_type(drm_device_t * dev, uint32_t type,
++			     drm_mem_type_manager_t * man);
++extern int psb_move(drm_buffer_object_t * bo,
++		    int evict, int no_wait, drm_bo_mem_reg_t * new_mem);
++
++/*
++ * psb_gtt.c 
++ */
++extern int psb_gtt_init(struct psb_gtt *pg, int resume);
++extern int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages,
++				unsigned offset_pages, unsigned num_pages,
++				unsigned desired_tile_stride, 
++				unsigned hw_tile_stride, 
++				int type);
++extern int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages, 
++				unsigned num_pages, unsigned desired_tile_stride, 
++				unsigned hw_tile_stride);
++
++extern struct psb_gtt *psb_gtt_alloc(drm_device_t *dev);
++extern void psb_gtt_takedown(struct psb_gtt *pg, int free);
++
++/*
++ * psb_fb.c
++ */
++extern int psbfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
++extern int psbfb_remove(struct drm_device *dev, struct drm_crtc *crtc);
++
++/*
++ * psb_drv.c
++ */
++
++extern struct drm_psb_plugin *psb_lock_plugin(int from_irq);
++extern void psb_unlock_plugin(int from_irq);
++extern void  psb_load_plugin(struct drm_psb_plugin *plug);
++extern void psb_unload_plugin(void);
++
++/*
++ * Utilities
++ */
++
++#define PSB_ALIGN_TO(_val, _align) \
++  (((_val) + ((_align) - 1)) & ~((_align) - 1))
++#define PSB_WVDC32(_val, _offs) \
++  iowrite32(_val, dev_priv->vdc_reg + (_offs))
++#define PSB_RVDC32(_offs) \
++  ioread32(dev_priv->vdc_reg + (_offs))
++#define PSB_WSGX32(_val, _offs) \
++  iowrite32(_val, dev_priv->sgx_reg + (_offs))
++#define PSB_RSGX32(_offs) \
++  ioread32(dev_priv->sgx_reg + (_offs))
++
++#define PSB_ALPL(_val, _base)			\
++  (((_val) >> (_base ## _ALIGNSHIFT)) << (_base ## _SHIFT))
++#define PSB_ALPLM(_val, _base)			\
++  ((((_val) >> (_base ## _ALIGNSHIFT)) << (_base ## _SHIFT)) & (_base ## _MASK))
++
++
++
++static inline psb_fixed psb_mul_fixed(psb_fixed a, psb_fixed b)
++{
++	s64 tmp;
++	s64 a64 = (s64) a;
++	s64 b64 = (s64) b;
++
++	tmp = a64*b64;
++	return tmp / (1ULL << PSB_FIXED_SHIFT) + 
++		((tmp & 0x80000000ULL) ? 1 : 0);
++}
++
++static inline psb_fixed psb_mul_ufixed(psb_ufixed a, psb_fixed b)
++{
++	u64 tmp;
++	u64 a64 = (u64) a;
++	u64 b64 = (u64) b;
++
++	tmp = a64*b64;
++	return (tmp >> PSB_FIXED_SHIFT) + 
++		((tmp & 0x80000000ULL) ? 1 : 0);
++}
++
++static inline u32 psb_ufixed_to_float32(psb_ufixed a)
++{
++	u32 exp = 0x7f + 7;
++	u32 mantissa = (u32) a;
++	
++	if (a == 0)
++		return 0;
++	while((mantissa & 0xff800000) == 0) {
++		exp -= 1;
++		mantissa <<= 1;
++	}
++	while((mantissa & 0xff800000) > 0x00800000) {
++		exp += 1;
++		mantissa >>= 1;
++	}
++	return (mantissa & ~0xff800000) | (exp << 23);
++}
++
++static inline u32 psb_fixed_to_float32(psb_fixed a)
++{
++	if (a < 0) 
++		return psb_ufixed_to_float32(-a) | 0x80000000;
++	else
++		return psb_ufixed_to_float32(a);
++}
++
++#define PSB_D_RENDER  (1 << 16)
++
++#define PSB_D_GENERAL (1 << 0)
++#define PSB_D_INIT    (1 << 1)
++#define PSB_D_IRQ     (1 << 2)
++
++extern int drm_psb_debug;
++extern int drm_psb_no_fb;
++
++#define PSB_DEBUG_GENERAL(_fmt, _arg...) \
++	PSB_DEBUG(PSB_D_GENERAL, _fmt, ##_arg)
++#define PSB_DEBUG_INIT(_fmt, _arg...) \
++	PSB_DEBUG(PSB_D_INIT, _fmt, ##_arg)
++#define PSB_DEBUG_IRQ(_fmt, _arg...) \
++	PSB_DEBUG(PSB_D_IRQ, _fmt, ##_arg)
++#define PSB_DEBUG_RENDER(_fmt, _arg...) \
++	PSB_DEBUG(PSB_D_INIT, _fmt, ##_arg)
++
++#if DRM_DEBUG_CODE
++#define PSB_DEBUG(_flag, _fmt, _arg...)					\
++	do {								\
++		if ((_flag) & drm_psb_debug)				\
++			printk(KERN_DEBUG				\
++			       "[psb:0x%02x:%s] " _fmt , _flag,	\
++			       __FUNCTION__ , ##_arg);			\
++	} while (0)
++#else 
++#define PSB_DEBUG(_fmt, _arg...)     do { } while (0)
++#endif
++
++#endif
+diff -Nurp libdrm-2.3.0/shared-core/psb_reg.h libdrm-psb/shared-core/psb_reg.h
+--- libdrm-2.3.0/shared-core/psb_reg.h	1969-12-31 16:00:00.000000000 -0800
++++ libdrm-psb/shared-core/psb_reg.h	2007-08-01 17:43:36.000000000 -0700
+@@ -0,0 +1,470 @@
++/**************************************************************************
++ * 
++ * Copyright (c) (2005-2007) Imagination Technologies Limited.
++ * Copyright (c) Intel Corp. 2007.
++ * All Rights Reserved.
++ *
++ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
++ * develop this driver.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and 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
++ * THE COPYRIGHT HOLDERS, AUTHORS 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 _PSB_REG_H_
++#define _PSB_REG_H_
++
++#define PSB_CR_CLKGATECTL                0x0000
++#define _PSB_C_CLKGATECTL_AUTO_MAN_REG   (1 << 24)
++#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20)
++#define _PSB_C_CLKGATECTL_USE_CLKG_MASK  (0x3 << 20)
++#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16)
++#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK  (0x3 << 16)
++#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT  (12)
++#define _PSB_C_CLKGATECTL_TA_CLKG_MASK   (0x3 << 12)
++#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8)
++#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK  (0x3 << 8)
++#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4)
++#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK  (0x3 << 4)
++#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT  (0)
++#define _PSB_C_CLKGATECTL_2D_CLKG_MASK   (0x3 << 0)
++#define _PSB_C_CLKGATECTL_CLKG_ENABLED   (0)
++#define _PSB_C_CLKGATECTL_CLKG_DISABLED  (1)
++#define _PSB_C_CLKGATECTL_CLKG_AUTO      (2)
++
++#define PSB_CR_CORE_ID                   0x0010
++#define _PSB_CC_ID_ID_SHIFT              (16)
++#define _PSB_CC_ID_ID_MASK               (0xFFFF << 16)
++#define _PSB_CC_ID_CONFIG_SHIFT          (0)
++#define _PSB_CC_ID_CONFIG_MASK           (0xFFFF << 0)
++
++#define PSB_CR_CORE_REVISION               0x0014
++#define _PSB_CC_REVISION_DESIGNER_SHIFT    (24)
++#define _PSB_CC_REVISION_DESIGNER_MASK     (0xFF << 24)
++#define _PSB_CC_REVISION_MAJOR_SHIFT       (16)
++#define _PSB_CC_REVISION_MAJOR_MASK        (0xFF << 16)
++#define _PSB_CC_REVISION_MINOR_SHIFT       (8)
++#define _PSB_CC_REVISION_MINOR_MASK        (0xFF << 8)
++#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0)
++#define _PSB_CC_REVISION_MAINTENANCE_MASK  (0xFF << 0)
++
++#define PSB_CR_DESIGNER_REV_FIELD1       0x0018
++
++#define PSB_CR_SOFT_RESET                0x0080
++#define _PSB_CS_RESET_TWOD_RESET         (1 << 1)
++#define _PSB_CS_RESET_BIF_RESET          (1 << 0)
++
++#define PSB_CR_DESIGNER_REV_FIELD2       0x001C
++
++#define PSB_CR_EVENT_STATUS              0x012C
++
++#define PSB_CR_EVENT_HOST_ENABLE         0x0130
++
++#define PSB_CR_EVENT_HOST_CLEAR          0x0134
++#define _PSB_CE_MASTER_INTERRUPT         (1 << 31)
++#define _PSB_CE_TWOD_COMPLETE            (1 << 27)
++
++#define PSB_CR_BIF_DIR_LIST_BASE1        0x0C38
++
++#define PSB_CR_BIF_CTRL                  0x0C00
++#define _PSB_CB_CTRL_CLEAR_FAULT         (1 << 4)
++#define _PSB_CB_CTRL_INVALDC             (1 << 3)
++#define _PSB_CB_CTRL_FLUSH               (1 << 2)
++
++#define PSB_CR_BIF_INT_STAT              0x0C04
++
++#define PSB_CR_BIF_FAULT                 0x0C08
++
++#define PSB_CR_BIF_BANK0                 0x0C78
++
++#define PSB_CR_BIF_BANK1                 0x0C7C
++
++#define PSB_CR_BIF_DIR_LIST_BASE0        0x0C84
++
++#define PSB_CR_BIF_TWOD_REQ_BASE         0x0C88
++
++#define PSB_CR_2D_SOCIF                  0x0E18
++#define _PSB_C2_SOCIF_FREESPACE_SHIFT    (0)
++#define _PSB_C2_SOCIF_FREESPACE_MASK     (0xFF << 0)
++#define _PSB_C2_SOCIF_EMPTY              (0x80 << 0)
++
++#define PSB_CR_2D_BLIT_STATUS            0x0E04
++#define _PSB_C2B_STATUS_BUSY             (1 << 24)
++#define _PSB_C2B_STATUS_COMPLETE_SHIFT   (0)
++#define _PSB_C2B_STATUS_COMPLETE_MASK    (0xFFFFFF << 0)
++
++/*
++ * 2D defs.
++ */
++
++/*
++ * 2D Slave Port Data : Block Header's Object Type
++ */
++
++#define	PSB_2D_CLIP_BH                   (0x00000000)	
++#define	PSB_2D_PAT_BH                    (0x10000000)	
++#define	PSB_2D_CTRL_BH                   (0x20000000)	
++#define	PSB_2D_SRC_OFF_BH                (0x30000000)	
++#define	PSB_2D_MASK_OFF_BH               (0x40000000)	
++#define	PSB_2D_RESERVED1_BH              (0x50000000)	
++#define	PSB_2D_RESERVED2_BH              (0x60000000)	
++#define	PSB_2D_FENCE_BH                  (0x70000000)	
++#define	PSB_2D_BLIT_BH                   (0x80000000)	
++#define	PSB_2D_SRC_SURF_BH               (0x90000000)	
++#define	PSB_2D_DST_SURF_BH               (0xA0000000)	
++#define	PSB_2D_PAT_SURF_BH               (0xB0000000)	
++#define	PSB_2D_SRC_PAL_BH                (0xC0000000)	
++#define	PSB_2D_PAT_PAL_BH                (0xD0000000)	
++#define	PSB_2D_MASK_SURF_BH              (0xE0000000)	
++#define	PSB_2D_FLUSH_BH                  (0xF0000000)	
++
++/*
++ * Clip Definition block (PSB_2D_CLIP_BH)
++ */
++#define PSB_2D_CLIPCOUNT_MAX             (1)	
++#define PSB_2D_CLIPCOUNT_MASK            (0x00000000)	
++#define PSB_2D_CLIPCOUNT_CLRMASK         (0xFFFFFFFF)	
++#define PSB_2D_CLIPCOUNT_SHIFT           (0)	
++// clip rectangle min & max
++#define PSB_2D_CLIP_XMAX_MASK            (0x00FFF000)
++#define PSB_2D_CLIP_XMAX_CLRMASK         (0xFF000FFF)
++#define PSB_2D_CLIP_XMAX_SHIFT           (12)
++#define PSB_2D_CLIP_XMIN_MASK            (0x00000FFF)
++#define PSB_2D_CLIP_XMIN_CLRMASK         (0x00FFF000)
++#define PSB_2D_CLIP_XMIN_SHIFT           (0)
++// clip rectangle offset 
++#define PSB_2D_CLIP_YMAX_MASK            (0x00FFF000)
++#define PSB_2D_CLIP_YMAX_CLRMASK         (0xFF000FFF)
++#define PSB_2D_CLIP_YMAX_SHIFT           (12)
++#define PSB_2D_CLIP_YMIN_MASK            (0x00000FFF)
++#define PSB_2D_CLIP_YMIN_CLRMASK         (0x00FFF000)
++#define PSB_2D_CLIP_YMIN_SHIFT           (0)
++
++/*
++ * Pattern Control (PSB_2D_PAT_BH)
++ */
++#define PSB_2D_PAT_HEIGHT_MASK           (0x0000001F)
++#define PSB_2D_PAT_HEIGHT_SHIFT          (0)
++#define PSB_2D_PAT_WIDTH_MASK            (0x000003E0)
++#define PSB_2D_PAT_WIDTH_SHIFT           (5)
++#define PSB_2D_PAT_YSTART_MASK           (0x00007C00)
++#define PSB_2D_PAT_YSTART_SHIFT          (10)
++#define PSB_2D_PAT_XSTART_MASK           (0x000F8000)
++#define PSB_2D_PAT_XSTART_SHIFT          (15)
++
++/*
++ * 2D Control block (PSB_2D_CTRL_BH)
++ */
++// Present Flags  
++#define PSB_2D_SRCCK_CTRL                (0x00000001)
++#define PSB_2D_DSTCK_CTRL                (0x00000002)
++#define PSB_2D_ALPHA_CTRL                (0x00000004)
++// Colour Key Colour (SRC/DST)
++#define PSB_2D_CK_COL_MASK               (0xFFFFFFFF)
++#define PSB_2D_CK_COL_CLRMASK            (0x00000000)
++#define PSB_2D_CK_COL_SHIFT              (0)
++// Colour Key Mask (SRC/DST)
++#define PSB_2D_CK_MASK_MASK              (0xFFFFFFFF)
++#define PSB_2D_CK_MASK_CLRMASK           (0x00000000)
++#define PSB_2D_CK_MASK_SHIFT             (0)
++// Alpha Control (Alpha/RGB)
++#define PSB_2D_GBLALPHA_MASK             (0x000FF000)
++#define PSB_2D_GBLALPHA_CLRMASK          (0xFFF00FFF)
++#define PSB_2D_GBLALPHA_SHIFT            (12)
++#define PSB_2D_SRCALPHA_OP_MASK          (0x00700000)
++#define PSB_2D_SRCALPHA_OP_CLRMASK       (0xFF8FFFFF)
++#define PSB_2D_SRCALPHA_OP_SHIFT         (20)
++#define PSB_2D_SRCALPHA_OP_ONE           (0x00000000)
++#define PSB_2D_SRCALPHA_OP_SRC           (0x00100000)
++#define PSB_2D_SRCALPHA_OP_DST           (0x00200000)
++#define PSB_2D_SRCALPHA_OP_SG            (0x00300000)
++#define PSB_2D_SRCALPHA_OP_DG            (0x00400000)
++#define PSB_2D_SRCALPHA_OP_GBL           (0x00500000)
++#define PSB_2D_SRCALPHA_OP_ZERO          (0x00600000)
++#define PSB_2D_SRCALPHA_INVERT           (0x00800000)
++#define PSB_2D_SRCALPHA_INVERT_CLR       (0xFF7FFFFF)
++#define PSB_2D_DSTALPHA_OP_MASK          (0x07000000)
++#define PSB_2D_DSTALPHA_OP_CLRMASK       (0xF8FFFFFF)
++#define PSB_2D_DSTALPHA_OP_SHIFT         (24)
++#define PSB_2D_DSTALPHA_OP_ONE           (0x00000000)
++#define PSB_2D_DSTALPHA_OP_SRC           (0x01000000)
++#define PSB_2D_DSTALPHA_OP_DST           (0x02000000)
++#define PSB_2D_DSTALPHA_OP_SG            (0x03000000)
++#define PSB_2D_DSTALPHA_OP_DG            (0x04000000)
++#define PSB_2D_DSTALPHA_OP_GBL           (0x05000000)
++#define PSB_2D_DSTALPHA_OP_ZERO          (0x06000000)
++#define PSB_2D_DSTALPHA_INVERT           (0x08000000)
++#define PSB_2D_DSTALPHA_INVERT_CLR       (0xF7FFFFFF)
++
++#define PSB_2D_PRE_MULTIPLICATION_ENABLE  (0x10000000)
++#define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF)
++#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE   (0x20000000)
++#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK  (0xDFFFFFFF)
++
++/*
++ *Source Offset (PSB_2D_SRC_OFF_BH)
++ */
++#define PSB_2D_SRCOFF_XSTART_MASK        ((0x00000FFF) << 12)	
++#define PSB_2D_SRCOFF_XSTART_SHIFT       (12)
++#define PSB_2D_SRCOFF_YSTART_MASK        (0x00000FFF)
++#define PSB_2D_SRCOFF_YSTART_SHIFT       (0)
++
++/*
++ * Mask Offset (PSB_2D_MASK_OFF_BH)
++ */
++#define PSB_2D_MASKOFF_XSTART_MASK       ((0x00000FFF) << 12)	
++#define PSB_2D_MASKOFF_XSTART_SHIFT      (12)
++#define PSB_2D_MASKOFF_YSTART_MASK       (0x00000FFF)
++#define PSB_2D_MASKOFF_YSTART_SHIFT      (0)
++
++/*
++ * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored
++ */
++
++/*
++ *Blit Rectangle (PSB_2D_BLIT_BH)
++ */
++
++#define PSB_2D_ROT_MASK                  (3<<25)
++#define PSB_2D_ROT_CLRMASK               (~PSB_2D_ROT_MASK)
++#define PSB_2D_ROT_NONE                  (0<<25)
++#define PSB_2D_ROT_90DEGS                (1<<25)
++#define PSB_2D_ROT_180DEGS               (2<<25)
++#define PSB_2D_ROT_270DEGS               (3<<25)
++
++#define PSB_2D_COPYORDER_MASK            (3<<23)
++#define PSB_2D_COPYORDER_CLRMASK         (~PSB_2D_COPYORDER_MASK)
++#define PSB_2D_COPYORDER_TL2BR           (0<<23)
++#define PSB_2D_COPYORDER_BR2TL           (1<<23)
++#define PSB_2D_COPYORDER_TR2BL           (2<<23)
++#define PSB_2D_COPYORDER_BL2TR           (3<<23)
++
++#define PSB_2D_DSTCK_CLRMASK             (0xFF9FFFFF)
++#define PSB_2D_DSTCK_DISABLE             (0x00000000)
++#define PSB_2D_DSTCK_PASS                (0x00200000)
++#define PSB_2D_DSTCK_REJECT              (0x00400000)
++
++#define PSB_2D_SRCCK_CLRMASK             (0xFFE7FFFF)
++#define PSB_2D_SRCCK_DISABLE             (0x00000000)
++#define PSB_2D_SRCCK_PASS                (0x00080000)
++#define PSB_2D_SRCCK_REJECT              (0x00100000)
++
++#define PSB_2D_CLIP_ENABLE               (0x00040000)
++
++#define PSB_2D_ALPHA_ENABLE              (0x00020000)
++
++#define PSB_2D_PAT_CLRMASK               (0xFFFEFFFF)
++#define PSB_2D_PAT_MASK                  (0x00010000)
++#define PSB_2D_USE_PAT                   (0x00010000)
++#define PSB_2D_USE_FILL                  (0x00000000)
++/*
++ * Tungsten Graphics note on rop codes: If rop A and rop B are
++ * identical, the mask surface will not be read and need not be
++ * set up.
++ */
++
++#define PSB_2D_ROP3B_MASK                (0x0000FF00)
++#define PSB_2D_ROP3B_CLRMASK             (0xFFFF00FF)
++#define PSB_2D_ROP3B_SHIFT               (8)
++// rop code A
++#define PSB_2D_ROP3A_MASK                (0x000000FF)
++#define PSB_2D_ROP3A_CLRMASK             (0xFFFFFF00)
++#define PSB_2D_ROP3A_SHIFT               (0)
++
++#define PSB_2D_ROP4_MASK                 (0x0000FFFF)
++/*
++ *	DWORD0:	(Only pass if Pattern control == Use Fill Colour)
++ *	Fill Colour RGBA8888
++ */
++#define PSB_2D_FILLCOLOUR_MASK           (0xFFFFFFFF)
++#define PSB_2D_FILLCOLOUR_SHIFT          (0)
++/*
++ *	DWORD1: (Always Present)
++ *	X Start (Dest)
++ *	Y Start (Dest)
++ */
++#define PSB_2D_DST_XSTART_MASK           (0x00FFF000)
++#define PSB_2D_DST_XSTART_CLRMASK        (0xFF000FFF)
++#define PSB_2D_DST_XSTART_SHIFT          (12)
++#define PSB_2D_DST_YSTART_MASK           (0x00000FFF)
++#define PSB_2D_DST_YSTART_CLRMASK        (0xFFFFF000)
++#define PSB_2D_DST_YSTART_SHIFT          (0)
++/*
++ *	DWORD2: (Always Present)
++ *	X Size (Dest)
++ *	Y Size (Dest)
++ */
++#define PSB_2D_DST_XSIZE_MASK            (0x00FFF000)
++#define PSB_2D_DST_XSIZE_CLRMASK         (0xFF000FFF)
++#define PSB_2D_DST_XSIZE_SHIFT           (12)
++#define PSB_2D_DST_YSIZE_MASK            (0x00000FFF)
++#define PSB_2D_DST_YSIZE_CLRMASK         (0xFFFFF000)
++#define PSB_2D_DST_YSIZE_SHIFT           (0)
++
++/*
++ * Source Surface (PSB_2D_SRC_SURF_BH)
++ */
++/*
++ *      WORD 0
++ */
++
++#define PSB_2D_SRC_FORMAT_MASK           (0x00078000)
++#define PSB_2D_SRC_1_PAL                 (0x00000000)
++#define PSB_2D_SRC_2_PAL                 (0x00008000)
++#define PSB_2D_SRC_4_PAL                 (0x00010000)
++#define PSB_2D_SRC_8_PAL                 (0x00018000)
++#define PSB_2D_SRC_8_ALPHA               (0x00020000)
++#define PSB_2D_SRC_4_ALPHA               (0x00028000)
++#define PSB_2D_SRC_332RGB                (0x00030000)
++#define PSB_2D_SRC_4444ARGB              (0x00038000)
++#define PSB_2D_SRC_555RGB                (0x00040000)
++#define PSB_2D_SRC_1555ARGB              (0x00048000)
++#define PSB_2D_SRC_565RGB                (0x00050000)
++#define PSB_2D_SRC_0888ARGB              (0x00058000)
++#define PSB_2D_SRC_8888ARGB              (0x00060000)
++#define PSB_2D_SRC_8888UYVY              (0x00068000)
++#define PSB_2D_SRC_RESERVED              (0x00070000)
++#define PSB_2D_SRC_1555ARGB_LOOKUP       (0x00078000)
++
++
++#define PSB_2D_SRC_STRIDE_MASK           (0x00007FFF)
++#define PSB_2D_SRC_STRIDE_CLRMASK        (0xFFFF8000)
++#define PSB_2D_SRC_STRIDE_SHIFT          (0)
++/*
++ *  WORD 1 - Base Address
++ */
++#define PSB_2D_SRC_ADDR_MASK             (0x0FFFFFFC)
++#define PSB_2D_SRC_ADDR_CLRMASK          (0x00000003)
++#define PSB_2D_SRC_ADDR_SHIFT            (2)
++#define PSB_2D_SRC_ADDR_ALIGNSHIFT       (2)
++
++/*
++ * Pattern Surface (PSB_2D_PAT_SURF_BH)
++ */
++/*
++ *  WORD 0
++ */
++
++#define PSB_2D_PAT_FORMAT_MASK           (0x00078000)
++#define PSB_2D_PAT_1_PAL                 (0x00000000)
++#define PSB_2D_PAT_2_PAL                 (0x00008000)
++#define PSB_2D_PAT_4_PAL                 (0x00010000)
++#define PSB_2D_PAT_8_PAL                 (0x00018000)
++#define PSB_2D_PAT_8_ALPHA               (0x00020000)
++#define PSB_2D_PAT_4_ALPHA               (0x00028000)
++#define PSB_2D_PAT_332RGB                (0x00030000)
++#define PSB_2D_PAT_4444ARGB              (0x00038000)
++#define PSB_2D_PAT_555RGB                (0x00040000)
++#define PSB_2D_PAT_1555ARGB              (0x00048000)
++#define PSB_2D_PAT_565RGB                (0x00050000)
++#define PSB_2D_PAT_0888ARGB              (0x00058000)
++#define PSB_2D_PAT_8888ARGB              (0x00060000)
++
++#define PSB_2D_PAT_STRIDE_MASK           (0x00007FFF)
++#define PSB_2D_PAT_STRIDE_CLRMASK        (0xFFFF8000)
++#define PSB_2D_PAT_STRIDE_SHIFT          (0)
++/*
++ *  WORD 1 - Base Address
++ */
++#define PSB_2D_PAT_ADDR_MASK             (0x0FFFFFFC)
++#define PSB_2D_PAT_ADDR_CLRMASK          (0x00000003)
++#define PSB_2D_PAT_ADDR_SHIFT            (2)
++#define PSB_2D_PAT_ADDR_ALIGNSHIFT       (2)
++
++/*
++ * Destination Surface (PSB_2D_DST_SURF_BH)
++ */
++/*
++ * WORD 0
++ */
++
++#define PSB_2D_DST_FORMAT_MASK           (0x00078000)
++#define PSB_2D_DST_332RGB                (0x00030000)
++#define PSB_2D_DST_4444ARGB              (0x00038000)
++#define PSB_2D_DST_555RGB                (0x00040000)
++#define PSB_2D_DST_1555ARGB              (0x00048000)
++#define PSB_2D_DST_565RGB                (0x00050000)
++#define PSB_2D_DST_0888ARGB              (0x00058000)
++#define PSB_2D_DST_8888ARGB              (0x00060000)
++#define PSB_2D_DST_8888AYUV              (0x00070000)
++
++#define PSB_2D_DST_STRIDE_MASK           (0x00007FFF)
++#define PSB_2D_DST_STRIDE_CLRMASK        (0xFFFF8000)
++#define PSB_2D_DST_STRIDE_SHIFT          (0)
++/*
++ * WORD 1 - Base Address
++ */
++#define PSB_2D_DST_ADDR_MASK             (0x0FFFFFFC)
++#define PSB_2D_DST_ADDR_CLRMASK          (0x00000003)
++#define PSB_2D_DST_ADDR_SHIFT            (2)
++#define PSB_2D_DST_ADDR_ALIGNSHIFT       (2)
++
++/*
++ * Mask Surface (PSB_2D_MASK_SURF_BH)
++ */
++/*
++ * WORD 0
++ */
++#define PSB_2D_MASK_STRIDE_MASK          (0x00007FFF)
++#define PSB_2D_MASK_STRIDE_CLRMASK       (0xFFFF8000)
++#define PSB_2D_MASK_STRIDE_SHIFT         (0)
++/*
++ *  WORD 1 - Base Address
++ */
++#define PSB_2D_MASK_ADDR_MASK            (0x0FFFFFFC)
++#define PSB_2D_MASK_ADDR_CLRMASK         (0x00000003)
++#define PSB_2D_MASK_ADDR_SHIFT           (2)
++#define PSB_2D_MASK_ADDR_ALIGNSHIFT      (2)
++
++/*
++ * Source Palette (PSB_2D_SRC_PAL_BH)
++ */
++
++#define PSB_2D_SRCPAL_ADDR_SHIFT         (0)
++#define PSB_2D_SRCPAL_ADDR_CLRMASK       (0xF0000007)
++#define PSB_2D_SRCPAL_ADDR_MASK          (0x0FFFFFF8)
++#define PSB_2D_SRCPAL_BYTEALIGN          (1024)
++
++/*
++ * Pattern Palette (PSB_2D_PAT_PAL_BH)
++ */
++
++#define PSB_2D_PATPAL_ADDR_SHIFT         (0)
++#define PSB_2D_PATPAL_ADDR_CLRMASK       (0xF0000007)
++#define PSB_2D_PATPAL_ADDR_MASK          (0x0FFFFFF8)
++#define PSB_2D_PATPAL_BYTEALIGN          (1024)
++
++/*
++ * Rop3 Codes (2 LS bytes)
++ */
++
++#define PSB_2D_ROP3_SRCCOPY              (0xCCCC)
++#define PSB_2D_ROP3_PATCOPY              (0xF0F0)
++#define PSB_2D_ROP3_WHITENESS            (0xFFFF)
++#define PSB_2D_ROP3_BLACKNESS            (0x0000)
++#define PSB_2D_ROP3_SRC                  (0xCC)
++#define PSB_2D_ROP3_PAT                  (0xF0)
++#define PSB_2D_ROP3_DST                  (0xAA)
++
++#endif
++
++
--- libdrm-2.3.0.orig/debian/patches/01_default_perms.diff
+++ libdrm-2.3.0/debian/patches/01_default_perms.diff
@@ -0,0 +1,13 @@
+Index: libdrm/libdrm/xf86drm.h
+===================================================================
+--- libdrm.orig/libdrm/xf86drm.h	2007-04-15 12:37:15.000000000 -0400
++++ libdrm/libdrm/xf86drm.h	2007-04-15 12:39:16.000000000 -0400
+@@ -46,7 +46,7 @@
+ /* Default /dev/dri directory permissions 0755 */
+ #define DRM_DEV_DIRMODE	 	\
+ 	(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
+-#define DRM_DEV_MODE	 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
++#define DRM_DEV_MODE	 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
+ 
+ #define DRM_DIR_NAME  "/dev/dri"
+ #define DRM_DEV_NAME  "%s/card%d"
--- libdrm-2.3.0.orig/debian/patches/100_poulsbo_libdrm_update.patch
+++ libdrm-2.3.0/debian/patches/100_poulsbo_libdrm_update.patch
@@ -0,0 +1,428 @@
+diff -Nru libdrm-2.3.0.orig/libdrm/xf86drm.c libdrm-2.3.0/libdrm/xf86drm.c
+--- libdrm-2.3.0.orig/libdrm/xf86drm.c	2006-11-08 13:54:38.000000000 -0800
++++ libdrm-2.3.0/libdrm/xf86drm.c	2007-06-19 11:26:20.000000000 -0700
+@@ -2267,12 +2267,13 @@
+  * DRM_FENCE_MASK_DRIVER
+  */
+ 
+-int drmFenceCreate(int fd, unsigned flags, int class,unsigned type, 
++int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
+ 		   drmFence *fence)
+ {
+     drm_fence_arg_t arg;
+-    
++
+     memset(&arg, 0, sizeof(arg));
++    arg.flags = flags;
+     arg.type = type;
+     arg.class = class;
+     arg.op = drm_fence_create;
+@@ -2290,6 +2291,7 @@
+  * Valid flags are 
+  * DRM_FENCE_FLAG_SHAREABLE
+  * DRM_FENCE_MASK_DRIVER
++ * DRM_FENCE_FLAG_NO_USER
+  */
+ 
+ int drmFenceBuffers(int fd, unsigned flags, drmFence *fence)
+@@ -2301,6 +2303,8 @@
+     arg.op = drm_fence_buffers;
+     if (ioctl(fd, DRM_IOCTL_FENCE, &arg))
+ 	return -errno;
++    if (flags & DRM_FENCE_FLAG_NO_USER) 
++	return 0;
+     fence->handle = arg.handle;
+     fence->class = arg.class;
+     fence->type = arg.type;
+@@ -2410,8 +2414,9 @@
+ int drmFenceEmit(int fd, unsigned flags, drmFence *fence, unsigned emit_type)
+ {
+     drm_fence_arg_t arg;
+-   
++
+     memset(&arg, 0, sizeof(arg));
++    arg.class = fence->class;
+     arg.flags = flags;
+     arg.handle = fence->handle;
+     arg.type = emit_type;
+@@ -2501,7 +2506,7 @@
+ 	DRMLISTDEL(l);
+ 	node = DRMLISTENTRY(drmBONode, l, head);
+ 	free(node);
+-	l = list->free.next;
++	l = list->list.next;
+ 	list->numCurrent--;
+ 	list->numOnList--;
+     }
+@@ -2812,7 +2817,7 @@
+     } while (ret != 0 && errno == EAGAIN);
+ 
+     if (ret) 
+-	return ret;
++	return -errno;
+     if (!arg.handled) 
+ 	return -EFAULT;
+     if (rep->ret)
+@@ -2868,7 +2873,7 @@
+     } while (ret && errno == EAGAIN);
+     
+     if (ret) 
+-	return ret;
++	return -errno;
+     if (!arg.handled)
+ 	return -EFAULT;
+     if (rep->ret)
+@@ -2890,12 +2895,12 @@
+     req->handle = buf->handle;
+     req->mask = flags;
+     req->arg_handle = fenceHandle;
+-    req->op = drm_bo_validate;
++    req->op = drm_bo_fence;
+ 
+     ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
+     
+     if (ret) 
+-	return ret;
++	return -errno;
+     if (!arg.handled)
+ 	return -EFAULT;
+     if (rep->ret)
+@@ -2917,7 +2922,7 @@
+     ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
+     
+     if (ret) 
+-	return ret;
++	return -errno;
+     if (!arg.handled)
+ 	return -EFAULT;
+     if (rep->ret)
+@@ -2945,7 +2950,7 @@
+ 	} while (ret && errno == EAGAIN);
+ 
+ 	if (ret) 
+-	    return ret;
++	    return -errno;
+ 	if (!arg.handled)
+ 	    return -EFAULT;
+ 	if (rep->ret)
+@@ -2970,7 +2975,24 @@
+     }
+ }
+     
+-    
++
++int drmBORmValidateItem(drmBOList *list, drmBO *buf) 
++{
++  drmBONode *node;
++  drmMMListHead *l;
++
++  for (l = list->list.next; l != &list->list; l = l->next) {
++      node = DRMLISTENTRY(drmBONode, l, head);
++      if (node->buf == buf) {	
++	  DRMLISTDEL(l);
++	  DRMLISTADD(l, &list->free);
++	  return drmAdjustListNodes(list);
++      }
++  }
++  return -EINVAL;
++}
++
++
+ int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags, 
+ 		       unsigned mask,
+ 		       int *newItem)
+@@ -3197,7 +3219,7 @@
+ 	ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
+     } while (ret && errno == EAGAIN);
+     
+-    return ret;	
++    return (ret) ? -errno : 0;	
+ }
+ 
+ int drmMMUnlock(int fd, unsigned memType)
+@@ -3213,7 +3235,7 @@
+ 	ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
+     } while (ret && errno == EAGAIN);
+     
+-    return ret;	
++    return (ret) ? -errno : 0;	
+ }
+ 
+ #define DRM_MAX_FDS 16
+diff -Nru libdrm-2.3.0.orig/libdrm/xf86drm.h libdrm-2.3.0/libdrm/xf86drm.h
+--- libdrm-2.3.0.orig/libdrm/xf86drm.h	2006-11-08 13:55:14.000000000 -0800
++++ libdrm-2.3.0/libdrm/xf86drm.h	2007-06-19 11:26:20.000000000 -0700
+@@ -270,6 +270,7 @@
+ typedef enum {
+     DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */
+     DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */
++    DRM_VBLANK_FLIP = 0x8000000,	/**< Scheduled buffer swap should flip */
+     DRM_VBLANK_NEXTONMISS = 0x10000000,	/**< If missed, wait for next vblank */
+     DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
+     DRM_VBLANK_SIGNAL   = 0x40000000	/* Send signal instead of blocking */
+diff -Nru libdrm-2.3.0.orig/libdrm/xf86mm.h libdrm-2.3.0/libdrm/xf86mm.h
+--- libdrm-2.3.0.orig/libdrm/xf86mm.h	2006-11-05 13:02:05.000000000 -0800
++++ libdrm-2.3.0/libdrm/xf86mm.h	2007-06-19 11:26:20.000000000 -0700
+@@ -166,6 +166,7 @@
+ extern void *drmBOListNext(drmBOList *list, void *iterator);
+ extern drmBO *drmBOListBuf(void *iterator);
+ extern int drmBOCreateList(int numTarget, drmBOList *list);
++extern int drmBORmValidateItem(drmBOList *list, drmBO *buf);
+ 
+ /*
+  * Buffer object functions.
+diff -Nru libdrm-2.3.0.orig/shared-core/drm.h libdrm-2.3.0/shared-core/drm.h
+--- libdrm-2.3.0.orig/shared-core/drm.h	2006-11-07 20:05:14.000000000 -0800
++++ libdrm-2.3.0/shared-core/drm.h	2007-06-19 11:25:41.000000000 -0700
+@@ -61,6 +61,9 @@
+ #ifndef __user
+ #define __user
+ #endif
++#ifndef __iomem
++#define __iomem
++#endif
+ 
+ #ifdef __GNUC__
+ # define DEPRECATED  __attribute__ ((deprecated))
+@@ -77,14 +80,7 @@
+ #define DRM_IOC_READWRITE	_IOC_READ|_IOC_WRITE
+ #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+ #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+-#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && defined(IN_MODULE)
+-/* Prevent name collision when including sys/ioccom.h */
+-#undef ioctl
+-#include <sys/ioccom.h>
+-#define ioctl(a,b,c)		xf86ioctl(a,b,c)
+-#else
+ #include <sys/ioccom.h>
+-#endif				/* __FreeBSD__ && xf86ioctl */
+ #define DRM_IOCTL_NR(n)		((n) & 0xff)
+ #define DRM_IOC_VOID		IOC_VOID
+ #define DRM_IOC_READ		IOC_OUT
+@@ -558,6 +554,7 @@
+ typedef enum {
+ 	_DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */
+ 	_DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */
++	_DRM_VBLANK_FLIP = 0x8000000,	/**< Scheduled buffer swap should flip */
+ 	_DRM_VBLANK_NEXTONMISS = 0x10000000,	/**< If missed, wait for next vblank */
+ 	_DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
+ 	_DRM_VBLANK_SIGNAL = 0x40000000	/**< Send signal instead of blocking */
+@@ -667,6 +664,7 @@
+ #define DRM_FENCE_FLAG_SHAREABLE           0x00000002
+ #define DRM_FENCE_FLAG_WAIT_LAZY           0x00000004
+ #define DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS 0x00000008
++#define DRM_FENCE_FLAG_NO_USER             0x00000010
+ 
+ /* Reserved for driver use */
+ #define DRM_FENCE_MASK_DRIVER              0xFF000000
+@@ -675,7 +673,7 @@
+ 
+ typedef struct drm_fence_arg {
+ 	unsigned handle;
+-        int class;
++	int class;
+ 	unsigned type;
+ 	unsigned flags;
+ 	unsigned signaled;
+@@ -694,9 +692,10 @@
+ } drm_fence_arg_t;
+ 
+ /* Buffer permissions, referring to how the GPU uses the buffers.
+-   these translate to fence types used for the buffers. 
+-   Typically a texture buffer is read, A destination buffer is write and
+-   a command (batch-) buffer is exe. Can be or-ed together. */
++ * these translate to fence types used for the buffers.
++ * Typically a texture buffer is read, A destination buffer is write and
++ *  a command (batch-) buffer is exe. Can be or-ed together.
++ */
+ 
+ #define DRM_BO_FLAG_READ        0x00000001
+ #define DRM_BO_FLAG_WRITE       0x00000002
+@@ -704,47 +703,82 @@
+ 
+ /*
+  * Status flags. Can be read to determine the actual state of a buffer.
++ * Can also be set in the buffer mask before validation.
+  */
+ 
+-/* 
+- * Cannot evict this buffer. Not even with force. This type of buffer should
+- * only be available for root, and must be manually removed before buffer
+- * manager shutdown or swapout.
++/*
++ * Mask: Never evict this buffer. Not even with force. This type of buffer is only
++ * available to root and must be manually removed before buffer manager shutdown
++ * or lock.
++ * Flags: Acknowledge
+  */
+ #define DRM_BO_FLAG_NO_EVICT    0x00000010
+-/* Always keep a system memory shadow to a vram buffer */
+-#define DRM_BO_FLAG_SHADOW_VRAM 0x00000020
+-/* The buffer is shareable with other processes */
++
++/*
++ * Mask: Require that the buffer is placed in mappable memory when validated.
++ *       If not set the buffer may or may not be in mappable memory when validated.
++ * Flags: If set, the buffer is in mappable memory.
++ */
++#define DRM_BO_FLAG_MAPPABLE 0x00000020
++
++/* Mask: The buffer should be shareable with other processes.
++ * Flags: The buffer is shareable with other processes.
++ */
+ #define DRM_BO_FLAG_SHAREABLE   0x00000040
+-/* The buffer is currently cached */
++
++/* Mask: If set, place the buffer in cache-coherent memory if available.
++ *       If clear, never place the buffer in cache coherent memory if validated.
++ * Flags: The buffer is currently in cache-coherent memory.
++ */
+ #define DRM_BO_FLAG_CACHED      0x00000080
+-/* Make sure that every time this buffer is validated, it ends up on the same
+- * location. The buffer will also not be evicted when claiming space for
+- * other buffers. Basically a pinned buffer but it may be thrown out as
+- * part of buffer manager shutdown or swapout. Not supported yet.*/
++
++/* Mask: Make sure that every time this buffer is validated,
++ *       it ends up on the same location provided that the memory mask is the same.
++ *       The buffer will also not be evicted when claiming space for
++ *       other buffers. Basically a pinned buffer but it may be thrown out as
++ *       part of buffer manager shutdown or locking.
++ * Flags: Acknowledge.
++ */
+ #define DRM_BO_FLAG_NO_MOVE     0x00000100
+ 
+-/* Make sure the buffer is in cached memory when mapped for reading */
+-#define DRM_BO_FLAG_READ_CACHED 0x00080000
+-/* When there is a choice between VRAM and TT, prefer VRAM. 
+-   The default behaviour is to prefer TT. */
+-#define DRM_BO_FLAG_PREFER_VRAM 0x00040000
+-/* Bind this buffer cached if the hardware supports it. */
+-#define DRM_BO_FLAG_BIND_CACHED 0x0002000
++/* Mask: Make sure the buffer is in cached memory when mapped for reading.
++ * Flags: Acknowledge.
++ */
++#define DRM_BO_FLAG_READ_CACHED    0x00080000
++
++/* Mask: Force DRM_BO_FLAG_CACHED flag strictly also if it is set.
++ * Flags: Acknowledge.
++ */
++#define DRM_BO_FLAG_FORCE_CACHING  0x00002000
++
++/*
++ * Mask: Force DRM_BO_FLAG_MAPPABLE flag strictly also if it is clear.
++ * Flags: Acknowledge.
++ */
++#define DRM_BO_FLAG_FORCE_MAPPABLE 0x00004000
++
++/*
++ * Memory type flags that can be or'ed together in the mask, but only
++ * one appears in flags.
++ */
+ 
+-/* System Memory */
++/* System memory */
+ #define DRM_BO_FLAG_MEM_LOCAL  0x01000000
+ /* Translation table memory */
+ #define DRM_BO_FLAG_MEM_TT     0x02000000
+ /* Vram memory */
+ #define DRM_BO_FLAG_MEM_VRAM   0x04000000
+-/* Unmappable Vram memory */
+-#define DRM_BO_FLAG_MEM_VRAM_NM   0x08000000
++/* Up to the driver to define. */
++#define DRM_BO_FLAG_MEM_PRIV0  0x08000000
++#define DRM_BO_FLAG_MEM_PRIV1  0x10000000
++#define DRM_BO_FLAG_MEM_PRIV2  0x20000000
++#define DRM_BO_FLAG_MEM_PRIV3  0x40000000
++#define DRM_BO_FLAG_MEM_PRIV4  0x80000000
++
+ /* Memory flag mask */
+ #define DRM_BO_MASK_MEM         0xFF000000
++#define DRM_BO_MASK_MEMTYPE     0xFF0000A0
+ 
+-/* When creating a buffer, Avoid system storage even if allowed */
+-#define DRM_BO_HINT_AVOID_LOCAL 0x00000001
+ /* Don't block on validate and map */
+ #define DRM_BO_HINT_DONT_BLOCK  0x00000002
+ /* Don't place this buffer on the unfenced list.*/
+@@ -753,15 +787,13 @@
+ #define DRM_BO_HINT_ALLOW_UNFENCED_MAP 0x00000010
+ 
+ 
+-/* Driver specific flags. Could be for example rendering engine */  
+-#define DRM_BO_MASK_DRIVER      0x00F00000
+-
+ typedef enum {
+ 	drm_bo_type_dc,
+ 	drm_bo_type_user,
+-	drm_bo_type_fake
++	drm_bo_type_fake,
++	drm_bo_type_kernel, /* for initial kernel allocations */
+ }drm_bo_type_t;
+-	
++
+ 
+ typedef struct drm_bo_arg_request {
+ 	unsigned handle; /* User space handle */
+@@ -771,7 +803,7 @@
+ 	drm_bo_type_t type;
+ 	unsigned arg_handle;
+ 	drm_u64_t buffer_start;
+-        unsigned page_alignment;
++	unsigned page_alignment;
+ 	unsigned expand_pad[4]; /*Future expansion */
+ 	enum {
+ 		drm_bo_create,
+@@ -802,17 +834,17 @@
+ 	drm_u64_t size;
+ 	drm_u64_t offset;
+ 	drm_u64_t arg_handle;
+-        unsigned mask;
+-        drm_u64_t buffer_start;
+-        unsigned fence_flags;
+-        unsigned rep_flags;
+-        unsigned page_alignment;
++	unsigned mask;
++	drm_u64_t buffer_start;
++	unsigned fence_flags;
++	unsigned rep_flags;
++	unsigned page_alignment;
+ 	unsigned expand_pad[4]; /*Future expansion */
+ }drm_bo_arg_reply_t;
+-	
++
+ 
+ typedef struct drm_bo_arg{
+-        int handled;
++	int handled;
+ 	drm_u64_t next;
+ 	union {
+ 		drm_bo_arg_request_t req;
+@@ -823,8 +855,13 @@
+ #define DRM_BO_MEM_LOCAL 0
+ #define DRM_BO_MEM_TT 1
+ #define DRM_BO_MEM_VRAM 2
+-#define DRM_BO_MEM_VRAM_NM 3
+-#define DRM_BO_MEM_TYPES 2 /* For now. */
++#define DRM_BO_MEM_PRIV0 3
++#define DRM_BO_MEM_PRIV1 4
++#define DRM_BO_MEM_PRIV2 5
++#define DRM_BO_MEM_PRIV3 6
++#define DRM_BO_MEM_PRIV4 7
++
++#define DRM_BO_MEM_TYPES 8 /* For now. */
+ 
+ typedef union drm_mm_init_arg{
+ 	struct {
+diff -Nru libdrm-2.3.0.orig/shared-core/drm_sarea.h libdrm-2.3.0/shared-core/drm_sarea.h
+--- libdrm-2.3.0.orig/shared-core/drm_sarea.h	2006-11-07 20:03:26.000000000 -0800
++++ libdrm-2.3.0/shared-core/drm_sarea.h	2007-06-19 11:25:41.000000000 -0700
+@@ -41,7 +41,7 @@
+ #define SAREA_MAX                       0x10000	/* 64kB */
+ #else
+ /* Intel 830M driver needs at least 8k SAREA */
+-#define SAREA_MAX                       0x2000
++#define SAREA_MAX                       0x2000UL
+ #endif
+ 
+ /** Maximum number of drawables in the SAREA */
--- libdrm-2.3.0.orig/debian/patches/series
+++ libdrm-2.3.0/debian/patches/series
@@ -0,0 +1,3 @@
+01_default_perms.diff
+100_poulsbo_libdrm_update.patch
+101_poulsbo_headers.patch
--- libdrm-2.3.0.orig/debian/libdrm2.install
+++ libdrm-2.3.0/debian/libdrm2.install
@@ -0,0 +1 @@
+usr/lib/lib*.so.*
--- libdrm-2.3.0.orig/debian/libdrm-dev.dirs
+++ libdrm-2.3.0/debian/libdrm-dev.dirs
@@ -0,0 +1,2 @@
+usr/lib
+usr/include
--- libdrm-2.3.0.orig/debian/compat
+++ libdrm-2.3.0/debian/compat
@@ -0,0 +1 @@
+5
--- libdrm-2.3.0.orig/debian/libdrm2.dirs
+++ libdrm-2.3.0/debian/libdrm2.dirs
@@ -0,0 +1 @@
+usr/lib
--- libdrm-2.3.0.orig/debian/libdrm2.NEWS
+++ libdrm-2.3.0/debian/libdrm2.NEWS
@@ -0,0 +1,8 @@
+libdrm (2.3.0-4) experimental; urgency=low
+
+  * We are now shipping libdrm with the default permissions set to 666,
+    rather than the upstream default of 660. If you have untrusted users,
+    you should configure the X server to explicitly use a mode of 660 in
+    the xorg.conf.
+
+ -- David Nusinow <dnusinow@debian.org>  Wed, 18 Apr 2007 22:44:21 -0400
--- libdrm-2.3.0.orig/debian/libdrm2.shlibs
+++ libdrm-2.3.0/debian/libdrm2.shlibs
@@ -0,0 +1 @@
+libdrm 2 libdrm2 (>= 2.3.0)
--- libdrm-2.3.0.orig/debian/changelog
+++ libdrm-2.3.0/debian/changelog
@@ -0,0 +1,144 @@
+libdrm (2.3.0-4ubuntu1) gutsy; urgency=low
+
+  [ Jacob Pan ]
+  * debian/patches/100_poulsbo_libdrm_update.patch:
+    - Incorporate changes to libdrm for the Poulsbo driver
+  * debian/patches/101_poulsbo_headers.patch:
+    - Header files required to build driver
+
+ -- Bryce Harrington <bryce@ubuntu.com>  Wed,  1 Aug 2007 18:10:14 -0700
+
+libdrm (2.3.0-4) unstable; urgency=low
+
+  [ David Nusinow ]
+  * Add NEWS.Debian explaining the change in the last upload to interested
+    administrators.
+
+  [ Julien Cristau ]
+  * Upload to unstable.
+
+ -- Julien Cristau <jcristau@debian.org>  Fri, 20 Apr 2007 05:06:34 +0200
+
+libdrm (2.3.0-3) experimental; urgency=low
+
+  * Add myself to uploaders
+  * Patch libdrm to default to device permission 666 so we don't have to do it
+    in xorg.conf. The only way libdrm can do anything is through the server
+    anyway. This can still be overridden by a user's xorg.conf. This change
+    also requires adding quilt to the build-depends
+
+ -- David Nusinow <dnusinow@debian.org>  Sun, 15 Apr 2007 13:08:50 -0400
+
+libdrm (2.3.0-2) unstable; urgency=low
+
+  * Update my email address in debian/control.
+  * Add XS-Vcs-Git and XS-Vcs-Browser in debian/control.
+  * Upload to unstable.
+
+ -- Julien Cristau <jcristau@debian.org>  Thu, 12 Apr 2007 19:06:57 +0200
+
+libdrm (2.3.0-1) experimental; urgency=low
+
+  [ Thierry Reding ]
+  * New upstream release.
+  * Set the Debian X Strike Force as maintainer.
+  * Add myself to uploaders.
+  * Add a debugging symbol package for libdrm2.
+
+  [ Julien Cristau ]
+  * Bump shlibs to libdrm2 >= 2.3.0.
+  * Add myself to uploaders.
+  * Add build-dep on dpkg-dev >= 1.13.19 to make sure that the binary:Version
+    substvar is available.
+  * libdrm2-dbg depends on libdrm2 (= ${binary:Version}).
+  * Don't install libdrm.la, and use dh_install --list-missing.
+
+ -- Julien Cristau <julien.cristau@ens-lyon.org>  Thu,  4 Jan 2007 18:56:08 +0100
+
+libdrm (2.2.0-0.1) experimental; urgency=low
+
+  * Non-maintainer upload.
+  * New upstream release.
+  * Bump Standards-Version to 3.7.2, no changes required.
+  * Bump debhelper compatibility to 5 and adjust build-dependency.
+  * Don't try to install pkgconfig files from usr/share/pkgconfig because
+    there is nothing in that directory.
+
+ -- Thierry Reding <thierry@gilfi.de>  Sat, 18 Nov 2006 19:50:26 +0100
+
+libdrm (2.0.2-0.1) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * New upstream release (closes: #377166).
+    - Includes a fix for FTBFS on GNU/kFreeBSD (closes: #332994).
+  * Manually force static build.
+
+ -- Andres Salomon <dilinger@debian.org>  Sat, 23 Sep 2006 06:32:23 +0000
+
+libdrm (2.0.1-1) unstable; urgency=high
+
+  * New upstream release
+    - Fixes a pathological hash table smash discovered by the Coverity scanner
+    - updates the installed header files for various new #defines
+
+ -- David Nusinow <dnusinow@debian.org>  Tue,  4 Apr 2006 23:46:05 -0400
+
+libdrm (2.0-1) experimental; urgency=low
+
+  * First upload to Debian
+
+ -- David Nusinow <dnusinow@debian.org>  Thu,  5 Jan 2006 22:45:27 -0500
+
+libdrm (2.0-0ubuntu1) dapper; urgency=low
+
+  * New upstream release.
+  * Change binary package from libdrm1 to libdrm2, following soversion bump.
+
+ -- Daniel Stone <daniel.stone@ubuntu.com>  Mon, 12 Dec 2005 13:05:22 +1100
+
+libdrm (1.0.5-0ubuntu1) dapper; urgency=low
+
+  * New upstream version.
+
+ -- Daniel Stone <daniel.stone@ubuntu.com>  Wed,  2 Nov 2005 01:56:07 +1100
+
+libdrm (1.0.3-3) unstable; urgency=low
+
+  * Yay for understandable bug reports! *gmprf*
+  * debian/control:libdrm1 =~ s/development/runtime/ (closes: bug#325515)
+
+ -- Marcelo E. Magallon <mmagallo@debian.org>  Fri, 16 Sep 2005 09:46:05 -0600
+
+libdrm (1.0.3-2) unstable; urgency=low
+
+  * libdrm.pc.in: add -ldrm to Libs
+
+ -- Marcelo E. Magallon <mmagallo@debian.org>  Thu, 08 Sep 2005 20:49:01 -0600
+
+libdrm (1.0.3-1) unstable; urgency=low
+
+  * New upstream
+
+ -- Marcelo E. Magallon <mmagallo@debian.org>  Sun, 28 Aug 2005 11:12:07 -0600
+
+libdrm (1.0.2-3) unstable; urgency=low
+
+  * debian/control: it's "Direct Rendering Infraestructure".  I was rather
+    sure it stand for interface... thanks Michel.  (closes: bug#324514)
+  * debian/control: forgot to actually write this in the file.  Build-Depends
+    on libx11-dev.  Thanks Kurt (closes: bug#324560)
+
+ -- Marcelo E. Magallon <mmagallo@debian.org>  Sun, 28 Aug 2005 11:01:41 -0600
+
+libdrm (1.0.2-2) unstable; urgency=low
+
+  * Forgot to fix the other broken bit :-P
+
+ -- Marcelo E. Magallon <mmagallo@debian.org>  Fri, 19 Aug 2005 22:01:32 -0600
+
+libdrm (1.0.2-1) unstable; urgency=low
+
+  * Initial release. Closes: #324074
+
+ -- Marcelo E. Magallon <mmagallo@debian.org>  Fri, 19 Aug 2005 21:11:18 -0600
+
--- libdrm-2.3.0.orig/debian/rules
+++ libdrm-2.3.0/debian/rules
@@ -0,0 +1,83 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+include /usr/share/quilt/quilt.make
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+	CFLAGS += -O0
+else
+	CFLAGS += -O2
+endif
+
+config.status: configure
+	dh_testdir
+	CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info --enable-static=yes
+
+build: patch build-stamp
+build-stamp:  config.status
+	dh_testdir
+	$(MAKE)
+	touch build-stamp
+
+clean: unpatch
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp
+	-$(MAKE) distclean
+ifneq "$(wildcard /usr/share/misc/config.sub)" ""
+	cp -f /usr/share/misc/config.sub config.sub
+endif
+ifneq "$(wildcard /usr/share/misc/config.guess)" ""
+	cp -f /usr/share/misc/config.guess config.guess
+endif
+	dh_clean
+
+install: build
+	dh_testdir
+	dh_testroot
+	dh_clean -k
+	dh_installdirs
+	$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+	dh_testdir
+	dh_testroot
+	dh_installchangelogs
+	dh_installdocs
+	dh_installexamples
+	dh_install --sourcedir=debian/tmp -Xlibdrm.la --list-missing
+	dh_link
+	dh_strip -plibdrm2 --dbg-package=libdrm2-dbg
+	dh_strip
+	dh_compress
+	dh_fixperms
+	dh_makeshlibs
+	dh_installdeb
+	dh_shlibdeps
+	dh_gencontrol
+	dh_md5sums
+	dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install 
--- libdrm-2.3.0.orig/debian/watch
+++ libdrm-2.3.0/debian/watch
@@ -0,0 +1,3 @@
+version=3
+
+http://dri.freedesktop.org/libdrm/libdrm-(.*)\.tar\.gz
--- libdrm-2.3.0.orig/debian/libdrm-dev.install
+++ libdrm-2.3.0/debian/libdrm-dev.install
@@ -0,0 +1,5 @@
+usr/include/*
+usr/lib/lib*.a
+usr/lib/lib*.so
+usr/lib/pkgconfig/*
+usr/lib/*.la
--- libdrm-2.3.0.orig/debian/control
+++ libdrm-2.3.0/debian/control
@@ -0,0 +1,50 @@
+Source: libdrm
+Priority: optional
+Maintainer: Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: Debian X Strike Force <debian-x@lists.debian.org>
+Uploaders: Thierry Reding <thierry@gilfi.de>, Julien Cristau <jcristau@debian.org>, David Nusinow <dnusinow@debian.org>
+Build-Depends: debhelper (>= 5.0.0), autotools-dev, libx11-dev, dpkg-dev (>= 1.13.19), quilt (>= 0.40)
+Standards-Version: 3.7.2
+Section: libs
+XS-Vcs-Git: git://git.debian.org/git/pkg-xorg/lib/libdrm
+XS-Vcs-Browser: http://git.debian.org/?p=pkg-xorg/lib/libdrm.git
+
+Package: libdrm-dev
+Section: libdevel
+Architecture: any
+Depends: libdrm2 (= ${binary:Version})
+Description: Userspace interface to kernel DRM services -- development files
+ This library implements the userspace interface to the kernel DRM
+ services.  DRM stands for "Direct Rendering Manager", which is the
+ kernelspace portion of the "Direct Rendering Infrastructure" (DRI).
+ The DRI is currently used on Linux to provide hardware-accelerated
+ OpenGL drivers.
+ .
+ This package provides the development environment for libdrm.
+
+Package: libdrm2
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Userspace interface to kernel DRM services -- runtime
+ This library implements the userspace interface to the kernel DRM
+ services.  DRM stands for "Direct Rendering Manager", which is the
+ kernelspace portion of the "Direct Rendering Infrastructure" (DRI).
+ The DRI is currently used on Linux to provide hardware-accelerated
+ OpenGL drivers.
+ .
+ This package provides the runtime environment for libdrm.
+
+Package: libdrm2-dbg
+Section: libdevel
+Priority: extra
+Architecture: any
+Depends: libdrm2 (= ${binary:Version})
+Description: Userspace interface to kernel DRM services -- debugging symbols
+ This library implements the userspace interface to the kernel DRM
+ services.  DRM stands for "Direct Rendering Manager", which is the
+ kernelspace portion of the "Direct Rendering Infrastructure" (DRI).
+ The DRI is currently used on Linux to provide hardware-accelerated
+ OpenGL drivers.
+ .
+ This package provides debugging symbols for the libdrm2 package.