xf86-video-intel: Branch 'i810_texman_0_1_branch' - .cvsignore .gitignore ChangeLog configure.ac man/.gitignore man/i810.man src/.cvsignore src/Makefile.am src/common.h src/i810.h src/i810_accel.c src/i810_cursor.c src/i810_dga.c src/i810_dri.c src/i810_driver.c src/i810_hwmc.c src/i810_io.c src/i810_memory.c src/i810_video.c src/i830.h src/i830_3d.c src/i830_accel.c src/i830_common.h src/i830_cursor.c src/i830_dga.c src/i830_dri.c src/i830_dri.h src/i830_driver.c src/i830_memory.c src/i830_modes.c src/i830_randr.c src/i830_reg.h src/i830_rotate.c src/i830_shadow.c src/i830_video.c src/i915_3d.c src/i915_3d.h src/i915_reg.h

Michel Daenzer daenzer at kemper.freedesktop.org
Thu Sep 28 16:49:00 EEST 2006


 .gitignore        |    2 
 ChangeLog         |   65 --
 configure.ac      |   14 
 man/.gitignore    |    2 
 man/i810.man      |   20 
 src/.cvsignore    |    6 
 src/Makefile.am   |    8 
 src/common.h      |   96 +--
 src/i810.h        |    3 
 src/i810_accel.c  |    1 
 src/i810_cursor.c |    1 
 src/i810_dga.c    |    1 
 src/i810_dri.c    |   49 +-
 src/i810_driver.c |   32 -
 src/i810_hwmc.c   |   17 
 src/i810_io.c     |    1 
 src/i810_memory.c |   13 
 src/i810_video.c  |    9 
 src/i830.h        |   64 +-
 src/i830_3d.c     |  131 +++++
 src/i830_accel.c  |    1 
 src/i830_common.h |   38 +
 src/i830_cursor.c |  170 ++++++-
 src/i830_dga.c    |  117 ++++
 src/i830_dri.c    |  436 +++++++++++++-----
 src/i830_dri.h    |    8 
 src/i830_driver.c | 1305 +++++++++++++++++++++++++++++++++++++-----------------
 src/i830_memory.c |  559 ++++++++++++++++++-----
 src/i830_modes.c  |   14 
 src/i830_randr.c  |  355 ++++++++++++++
 src/i830_reg.h    |  637 ++++++++++++++++++++++++++
 src/i830_rotate.c | 1239 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/i830_shadow.c |  253 ----------
 src/i830_video.c  |  915 ++++++++++++++++++++++++++++---------
 src/i915_3d.c     |  107 ++++
 src/i915_3d.h     |  431 +++++++++++++++++
 src/i915_reg.h    |  848 +++++++++++++++++++++++++++++++++++
 37 files changed, 6599 insertions(+), 1369 deletions(-)

New commits:
diff-tree 9de55a44f95f251df365f29884a1ff17492b470d (from d140055f5be6185f634f7d13683c36ed698eb89a)
Author: Michel Daenzer <daenzer at loki.lorrainebruecke.local>
Date:   Wed Jul 26 16:02:07 2006 +0200

    Merge branch 'master' of ssh+git://git.freedesktop.org/git/xorg/driver/xf86-video-intel into i810_texman_0_1_branch
    
    Conflicts:
    
    	ChangeLog - removed
    	src/i810_driver.c
    	src/i830_dri.c
    	src/i830_driver.c
    	src/i830_memory.c

diff --git a/.cvsignore b/.cvsignore
deleted file mode 100644
index c7bcbee..0000000
--- a/.cvsignore
+++ /dev/null
@@ -1,20 +0,0 @@
-Makefile
-Makefile.in
-*.la
-*.lo
-aclocal.m4
-autom4te.cache
-compile
-config.guess
-config.h
-config.h.in
-config.log
-config.status
-config.sub
-configure
-depcomp
-install-sh
-libtool
-ltmain.sh
-missing
-stamp-h1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6f660b9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,22 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.la
+*.lo
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+stamp-h1
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index c187542..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1,65 +0,0 @@
-2006-03-24  Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
-
-	* src/i830_driver.c: (I830BIOSCloseScreen):
-	Fix typo.
-	
-2006-03-22  Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
-
-	* src/i810_driver.c:
-	* src/i830_dri.c: (I830DRIDoMappings):
-	* src/i830_driver.c: (I830DrmMMInit), (I830DrmMMTakedown),
-	(I830BIOSScreenInit), (I830BIOSCloseScreen):
-	* src/i830_memory.c: (I830Allocate3DMemory), (I830FixupOffsets),
-	(I830BindGARTMemory), (I830UnbindGARTMemory):
-	New branch. Initialize the drm memory manager. Don't allocate
-	texture memory.
-	
-2005-12-20  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update package version for X11R7 release.
-
-2005-12-14  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update package version number for final X11R7 release candidate.
-
-2005-12-06  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* man/Makefile.am:
-	Change *man_SOURCES ==> *man_PRE to fix autotools warnings.
-
-2005-12-03  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update package version number for X11R7 RC3 release.
-
-2005-12-01  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Remove extraneous AC_MSG_RESULT.
-
-2005-11-30  Adam Jackson  <ajax at freedesktop.org>
-
-	* configure.ac:
-	Bump libdrm dep to 2.0.
-
-2005-11-29  Adam Jackson  <ajax at freedesktop.org>
-
-	* configure.ac:
-	Only build dlloader modules by default.
-
-2005-11-19  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update dependencies to work with separate build roots.
-
-2005-11-09  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update package version number for X11R7 RC2 release.
-
-2005-11-01  Kevin E. Martin  <kem-at-freedesktop-dot-org>
-
-	* configure.ac:
-	Update pkgcheck dependencies to work with separate build roots.
diff --git a/configure.ac b/configure.ac
index e50b3d1..b1d3524 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-video-i810],
-        1.4.1.3,
+        1.6.1,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-video-i810)
 
@@ -89,6 +89,18 @@ if test x$DRI = xauto; then
 fi
 AC_MSG_RESULT([$DRI])
 
+dnl Use lots of warning flags with GCC
+
+WARN_CFLAGS=""
+
+if test "x$GCC" = "xyes"; then
+	WARN_CFLAGS="-Wall -Wpointer-arith -Wstrict-prototypes \
+	-Wmissing-prototypes -Wmissing-declarations \
+	-Wnested-externs -fno-strict-aliasing"
+fi
+
+CFLAGS="$CFLAGS $WARN_CFLAGS"
+
 AM_CONDITIONAL(DRI, test x$DRI = xyes)
 if test "$DRI" = yes; then
         PKG_CHECK_MODULES(DRI, [libdrm >= 2.0 xf86driproto])
diff --git a/man/.gitignore b/man/.gitignore
new file mode 100644
index 0000000..a438e80
--- /dev/null
+++ b/man/.gitignore
@@ -0,0 +1,2 @@
+i810.4
+i810.4x
diff --git a/man/i810.man b/man/i810.man
index 8c432ef..099e1f8 100644
--- a/man/i810.man
+++ b/man/i810.man
@@ -192,16 +192,18 @@ the machine has booted, but unfortunatel
 is extremely dependent upon the Video BIOS.
 Default: disabled
 .TP
-.BI "Option \*qRotate\*q \*qCW\*q"
+.BI "Option \*qRotate\*q \*q90\*q"
+Rotate the desktop 90 degrees counterclockwise. Other valid options are
+0, 90, 180 and 270 degrees. The RandR extension is used for rotation 
+functionality. So this option allows the Xserver to start with a rotated
+mode of operation.
+Default: 0 degrees.
 .TP
-.BI "Option \*qRotate\*q \*qCCW\*q"
-Rotate the desktop 90 degrees clockwise or counterclockwise.  This option 
-forces the ShadowFB option on, and disables acceleration.
-Default: no rotation.
-.TP
-.BI "Option \*qShadowFB\*q \*q" boolean \*q
-Enable or disable use of the shadow framebuffer layer.  This option
-disables acceleration.  Default: off.
+.BI "Option \*qLinearAlloc\*q \*q" integer \*q
+Allows more memory for the offscreen allocator. This usually helps in
+situations where HDTV movies are required to play but not enough offscreen
+memory is usually available. Set this to 6144 for upto 1920x1080 HDTV support.
+Default 0KB (off).
 
 .SH "SEE ALSO"
 __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
diff --git a/src/.cvsignore b/src/.cvsignore
deleted file mode 100644
index 9730646..0000000
--- a/src/.cvsignore
+++ /dev/null
@@ -1,6 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-*.la
-*.lo
diff --git a/src/Makefile.am b/src/Makefile.am
index fa69592..f97dc52 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,7 +53,13 @@ i810_drv_la_SOURCES = \
          i830_memory.c \
          i830_modes.c \
          i830_video.c \
-         i830_shadow.c
+         i830_rotate.c \
+	 i830_randr.c \
+	 i830_3d.c \
+	 i830_reg.h \
+	 i915_3d.c \
+	 i915_3d.h \
+	 i915_reg.h
 
 if DRI
 i810_drv_la_SOURCES += \
diff --git a/src/common.h b/src/common.h
index 85a24ab..31e67b9 100644
--- a/src/common.h
+++ b/src/common.h
@@ -39,13 +39,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #ifndef _INTEL_COMMON_H_
 #define _INTEL_COMMON_H_
 
-#ifdef __GNUC__
+/* Provide substitutes for gcc's __FUNCTION__ on other compilers */
+#ifndef __GNUC__
+# if defined(__STDC__) && (__STDC_VERSION__>=199901L) /* C99 */
+#  define __FUNCTION__ __func__
+# else
+#  define __FUNCTION__ ""
+# endif
+#endif
+
+
 #define PFX __FILE__,__LINE__,__FUNCTION__
 #define FUNCTION_NAME __FUNCTION__
-#else
-#define PFX __FILE__,__LINE__,""
-#define FUNCTION_NAME ""
-#endif
 
 #ifdef I830DEBUG
 #define MARKER() ErrorF("\n### %s:%d: >>> %s <<< ###\n\n", \
@@ -80,10 +85,10 @@ extern const char *I810ddcSymbols[];
 extern const char *I810fbSymbols[];
 extern const char *I810xaaSymbols[];
 extern const char *I810shadowFBSymbols[];
+extern const char *I810shadowSymbols[];
 #ifdef XF86DRI
 extern const char *I810driSymbols[];
 extern const char *I810drmSymbols[];
-extern const char *I810shadowSymbols[];
 #endif
 
 extern void I830DPRINTF_stub(const char *filename, int line,
@@ -119,29 +124,21 @@ extern void I830DPRINTF_stub(const char 
       ErrorF( "OUT_RING %lx: %x, (mask %x)\n",				\
 		(unsigned long)(outring), (unsigned int)(n), ringmask);	\
    *(volatile unsigned int *)(virt + outring) = n;			\
-   outring += 4;							\
+   outring += 4; ringused += 4;							\
    outring &= ringmask;							\
 } while (0)
 
-#if 1
 #define ADVANCE_LP_RING() do {						\
+   if (ringused > needed)          \
+      ErrorF("%s: ADVANCE_LP_RING: exceeded allocation %d/%d\n ",      \
+	     __FUNCTION__, ringused, needed);     \
    RecPtr->LpRing->tail = outring;					\
+   RecPtr->LpRing->space -= ringused;					\
    if (outring & 0x07)							\
       ErrorF("ADVANCE_LP_RING: "					\
-	     "outring (0x%x) isn't on a QWord boundary", outring);	\
+	     "outring (0x%x) isn't on a QWord boundary\n", outring);	\
    OUTREG(LP_RING + RING_TAIL, outring);				\
 } while (0)
-#else
-#define ADVANCE_LP_RING() {						\
-   RecPtr->LpRing->tail = outring;					\
-   if (outring & 0x07)							\
-      ErrorF("ADVANCE_LP_RING: "					\
-	     "outring (0x%x) isn't on a QWord boundary", outring);	\
-   ErrorF("head is %d, tail is %d [%d]\n", INREG(LP_RING + RING_HEAD), INREG(LP_RING + RING_TAIL), outring); \
-   OUTREG(LP_RING + RING_TAIL, outring);				\
-   ErrorF("head is %d, tail is %d [%d]\n", INREG(LP_RING + RING_HEAD), INREG(LP_RING + RING_TAIL), outring); \
-}
-#endif
 
 /*
  * XXX Note: the head/tail masks are different for 810 and i830.
@@ -158,54 +155,9 @@ extern void I830DPRINTF_stub(const char 
    } while (_head != _tail);						\
 } while( 0)
 
-/*
- * This is for debugging a potential problem writing the tail pointer
- * close to the end of the ring buffer.
- */
-#ifndef AVOID_TAIL_END
-#define AVOID_TAIL_END 0
-#endif
-#ifndef AVOID_SIZE
-#define AVOID_SIZE 64
-#endif
-
-#if AVOID_TAIL_END
-
-#define BEGIN_LP_RING(n)						\
-   unsigned int outring, ringmask;					\
-   volatile unsigned char *virt;					\
-   int needed;							\
-   if ((n) & 1)								\
-      ErrorF("BEGIN_LP_RING called with odd argument: %d\n", n);	\
-   if ((n) > 2 && (I810_DEBUG&DEBUG_ALWAYS_SYNC))			\
-      DO_RING_IDLE();							\
-   needed = (n) * 4;							\
-   if ((RecPtr->LpRing->tail > RecPtr->LpRing->tail_mask - AVOID_SIZE) ||	\
-       (RecPtr->LpRing->tail + needed) >				\
-	RecPtr->LpRing->tail_mask - AVOID_SIZE) {			\
-      needed += RecPtr->LpRing->tail_mask + 1 - RecPtr->LpRing->tail;	\
-      ErrorF("BEGIN_LP_RING: skipping last 64 bytes of "		\
-	     "ring (%d vs %d)\n", needed, (n) * 4);			\
-   }									\
-   if (RecPtr->LpRing->space < needed)					\
-      WaitRingFunc(pScrn, needed, 0);					\
-   RecPtr->LpRing->space -= needed;					\
-   outring = RecPtr->LpRing->tail;					\
-   ringmask = RecPtr->LpRing->tail_mask;				\
-   virt = RecPtr->LpRing->virtual_start;				\
-   while (needed > (n) * 4) {						\
-      ErrorF("BEGIN_LP_RING: putting MI_NOOP at 0x%x (remaining %d)\n",	\
-	     outring, needed - (n) * 4);				\
-      OUT_RING(MI_NOOP);						\
-      needed -= 4;							\
-   }									\
-   if (I810_DEBUG & DEBUG_VERBOSE_RING)					\
-      ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME);
-
-#else /* AVOID_TAIL_END */
 
 #define BEGIN_LP_RING(n)						\
-   unsigned int outring, ringmask;					\
+   unsigned int outring, ringmask, ringused = 0;			\
    volatile unsigned char *virt;					\
    int needed;								\
    if ((n) & 1)								\
@@ -215,14 +167,12 @@ extern void I830DPRINTF_stub(const char 
    needed = (n) * 4;							\
    if (RecPtr->LpRing->space < needed)					\
       WaitRingFunc(pScrn, needed, 0);					\
-   RecPtr->LpRing->space -= needed;					\
    outring = RecPtr->LpRing->tail;					\
    ringmask = RecPtr->LpRing->tail_mask;				\
    virt = RecPtr->LpRing->virtual_start;				\
    if (I810_DEBUG & DEBUG_VERBOSE_RING)					\
       ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME);
 
-#endif /* AVOID_TAIL_END */
 
 
 /* Memory mapped register access macros */
@@ -322,6 +272,11 @@ extern int I810_DEBUG;
 #define PCI_CHIP_I945_G_BRIDGE 0x2770
 #endif
 
+#ifndef PCI_CHIP_I945_GM
+#define PCI_CHIP_I945_GM        0x27A2
+#define PCI_CHIP_I945_GM_BRIDGE 0x27A0
+#endif
+
 #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 ||	\
 			pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \
 			pI810->PciInfo->chipType == PCI_CHIP_I810_E)
@@ -332,11 +287,14 @@ extern int I810_DEBUG;
 #define IS_I852(pI810)  (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME))
 #define IS_I855(pI810)  (pI810->PciInfo->chipType == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME))
 #define IS_I865G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I865_G)
+
 #define IS_I915G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_G || pI810->PciInfo->chipType == PCI_CHIP_E7221_G)
 #define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM)
 #define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G)
+#define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM)
+#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810))
 
-#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810))
+#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810))
 
 #define GTT_PAGE_SIZE			KB(4)
 #define ROUND_TO(x, y)			(((x) + (y) - 1) / (y) * (y))
diff --git a/src/i810.h b/src/i810.h
index 198f0ec..740f38c 100644
--- a/src/i810.h
+++ b/src/i810.h
@@ -39,7 +39,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #ifndef _I810_H_
 #define _I810_H_
 
-#include "xf86_ansic.h"
 #include "compiler.h"
 #include "xf86PciInfo.h"
 #include "xf86Pci.h"
@@ -66,7 +65,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define I810_NAME "I810"
 #define I810_DRIVER_NAME "i810"
 #define I810_MAJOR_VERSION 1
-#define I810_MINOR_VERSION 4
+#define I810_MINOR_VERSION 6
 #define I810_PATCHLEVEL 1
 
 
diff --git a/src/i810_accel.c b/src/i810_accel.c
index f946ae2..efbe290 100644
--- a/src/i810_accel.c
+++ b/src/i810_accel.c
@@ -50,7 +50,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  *
  */
 
-#include "xf86_ansic.h"
 #include "xf86.h"
 #include "xaarop.h"
 #include "i810.h"
diff --git a/src/i810_cursor.c b/src/i810_cursor.c
index 85c4e25..c293a3d 100644
--- a/src/i810_cursor.c
+++ b/src/i810_cursor.c
@@ -55,7 +55,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
-#include "xf86_ansic.h"
 #include "compiler.h"
 
 #include "xf86fbman.h"
diff --git a/src/i810_dga.c b/src/i810_dga.c
index e671333..4ab7a3d 100644
--- a/src/i810_dga.c
+++ b/src/i810_dga.c
@@ -42,7 +42,6 @@
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
-#include "xf86_ansic.h"
 #include "xf86Pci.h"
 #include "xf86PciInfo.h"
 #include "xaa.h"
diff --git a/src/i810_dri.c b/src/i810_dri.c
index f9b95bd..a8c10ff 100644
--- a/src/i810_dri.c
+++ b/src/i810_dri.c
@@ -16,9 +16,13 @@
 #include "config.h"
 #endif
 
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
 #include "xf86.h"
 #include "xf86_OSproc.h"
-#include "xf86_ansic.h"
 #include "xf86Priv.h"
 
 #include "xf86PciInfo.h"
@@ -356,7 +360,7 @@ I810DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION;
    pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION;
    pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL;
-   pDRIInfo->frameBufferPhysicalAddress = pI810->LinearAddr;
+   pDRIInfo->frameBufferPhysicalAddress = (pointer) pI810->LinearAddr;
    pDRIInfo->frameBufferSize = (((pScrn->displayWidth *
 				  pScrn->virtualY * pI810->cpp) +
 				 4096 - 1) / 4096) * 4096;
@@ -481,13 +485,14 @@ I810DRIScreenInit(ScreenPtr pScreen)
 
    pI810DRI->regsSize = I810_REG_SIZE;
    if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->MMIOAddr,
-		 pI810DRI->regsSize, DRM_REGISTERS, 0, &pI810DRI->regs) < 0) {
+		 pI810DRI->regsSize, DRM_REGISTERS, 0, 
+		 (drmAddress) &pI810DRI->regs) < 0) {
       xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n");
       DRICloseScreen(pScreen);
       return FALSE;
    }
    xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
-	      pI810DRI->regs);
+	      (int)pI810DRI->regs);
 
    pI810->backHandle = DRM_AGP_NO_HANDLE;
    pI810->zHandle = DRM_AGP_NO_HANDLE;
@@ -522,11 +527,12 @@ I810DRIScreenInit(ScreenPtr pScreen)
     * under the DRI.
     */
 
-   drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL, &dcacheHandle);
+   drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL, 
+	       (drmAddress) &dcacheHandle);
    pI810->dcacheHandle = dcacheHandle;
 
    xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : 0x%x\n",
-	      dcacheHandle);
+	      (int)dcacheHandle);
 
 #define Elements(x) sizeof(x)/sizeof(*x)
    for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++)
@@ -626,7 +632,8 @@ I810DRIScreenInit(ScreenPtr pScreen)
 		 "[agp] GART: no dcache memory found\n");
    }
 
-   drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, &agpHandle);
+   drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, 
+	       (drmAddress) &agpHandle);
    pI810->backHandle = agpHandle;
 
    if (agpHandle != DRM_AGP_NO_HANDLE) {
@@ -652,7 +659,8 @@ I810DRIScreenInit(ScreenPtr pScreen)
    }
 
    if (dcacheHandle == DRM_AGP_NO_HANDLE) {
-     drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, &agpHandle);
+     drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL,
+		 (drmAddress) &agpHandle);
 
       pI810->zHandle = agpHandle;
 
@@ -681,7 +689,8 @@ I810DRIScreenInit(ScreenPtr pScreen)
    /* Now allocate and bind the agp space.  This memory will include the
     * regular framebuffer as well as texture memory.
     */
-   drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL, &agpHandle);
+   drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL, 
+	       (drmAddress)&agpHandle);
    pI810->sysmemHandle = agpHandle;
    
    if (agpHandle != DRM_AGP_NO_HANDLE) {
@@ -724,7 +733,8 @@ I810DRIScreenInit(ScreenPtr pScreen)
 	 pI810->MC.Size = 8 * 1024 * 1024;
 	 pI810->MC.Start = pI810->FbMapSize - 8 * 1024 * 1024;
       }
-      drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL, &agpHandle);
+      drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL,
+		  (drmAddress) &agpHandle);
       
       pI810->xvmcHandle = agpHandle;
 
@@ -749,7 +759,8 @@ I810DRIScreenInit(ScreenPtr pScreen)
    }
 
    drmAgpAlloc(pI810->drmSubFD, 4096, 2,
-	       (unsigned long *)&pI810->CursorPhysical, &agpHandle);
+	       (unsigned long *)&pI810->CursorPhysical, 
+	       (drmAddress) &agpHandle);
 
    pI810->cursorHandle = agpHandle;
 
@@ -773,7 +784,8 @@ I810DRIScreenInit(ScreenPtr pScreen)
    }
 
    drmAgpAlloc(pI810->drmSubFD, 16384, 2,
-	       (unsigned long *)&pI810->CursorARGBPhysical, &agpHandle);
+	       (unsigned long *)&pI810->CursorARGBPhysical,
+	       (drmAddress) &agpHandle);
 
    pI810->cursorARGBHandle = agpHandle;
 
@@ -851,7 +863,7 @@ I810DRIScreenInit(ScreenPtr pScreen)
 
    if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BackBuffer.Start,
 		 pI810->BackBuffer.Size, DRM_AGP, 0,
-		 &pI810DRI->backbuffer) < 0) {
+		 (drmAddress) &pI810DRI->backbuffer) < 0) {
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[drm] drmAddMap(backbuffer) failed.  Disabling DRI\n");
       DRICloseScreen(pScreen);
@@ -861,7 +873,7 @@ I810DRIScreenInit(ScreenPtr pScreen)
    pI810DRI->depthbufferSize = pI810->DepthBuffer.Size;
    if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->DepthBuffer.Start,
 		 pI810->DepthBuffer.Size, DRM_AGP, 0,
-		 &pI810DRI->depthbuffer) < 0) {
+		 (drmAddress) &pI810DRI->depthbuffer) < 0) {
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[drm] drmAddMap(depthbuffer) failed.  Disabling DRI.\n");
       DRICloseScreen(pScreen);
@@ -890,7 +902,8 @@ I810DRIScreenInit(ScreenPtr pScreen)
       return FALSE;
    }
    if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BufferMem.Start,
-		 pI810->BufferMem.Size, DRM_AGP, 0, &pI810->buffer_map) < 0) {
+		 pI810->BufferMem.Size, DRM_AGP, 0,
+		 (drmAddress) &pI810->buffer_map) < 0) {
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[drm] drmAddMap(buffer_map) failed.  Disabling DRI.\n");
       DRICloseScreen(pScreen);
@@ -901,7 +914,8 @@ I810DRIScreenInit(ScreenPtr pScreen)
    pI810DRI->agp_buf_size = pI810->BufferMem.Size;
 
    if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing->mem.Start,
-		 pI810->LpRing->mem.Size, DRM_AGP, 0, &pI810->ring_map) < 0) {
+		 pI810->LpRing->mem.Size, DRM_AGP, 0, 
+		 (drmAddress) &pI810->ring_map) < 0) {
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[drm] drmAddMap(ring_map) failed.  Disabling DRI.\n");
       DRICloseScreen(pScreen);
@@ -929,7 +943,8 @@ I810DRIScreenInit(ScreenPtr pScreen)
    I810AllocLow(&(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize);
 
    if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->TexMem.Start,
-		 pI810->TexMem.Size, DRM_AGP, 0, &pI810DRI->textures) < 0) {
+		 pI810->TexMem.Size, DRM_AGP, 0, 
+		 (drmAddress) &pI810DRI->textures) < 0) {
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[drm] drmAddMap(textures) failed.  Disabling DRI.\n");
       DRICloseScreen(pScreen);
diff --git a/src/i810_driver.c b/src/i810_driver.c
index 8096612..80ed3bd 100644
--- a/src/i810_driver.c
+++ b/src/i810_driver.c
@@ -60,11 +60,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * DGA
  */
 
+#include <math.h>
+#include <string.h>
+#include <unistd.h>
+
 /*
  * These are X and server generic header files.
  */
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
 #include "xf86RAC.h"
@@ -136,6 +139,7 @@ static SymTabRec I810Chipsets[] = {
    {PCI_CHIP_E7221_G,		"E7221 (i915)"},
    {PCI_CHIP_I915_GM,		"915GM"},
    {PCI_CHIP_I945_G,		"945G"},
+   {PCI_CHIP_I945_GM,		"945GM"},
    {-1,				NULL}
 };
 
@@ -154,6 +158,7 @@ static PciChipsets I810PciChipsets[] = {
    {PCI_CHIP_E7221_G,		PCI_CHIP_E7221_G,	RES_SHARED_VGA},
    {PCI_CHIP_I915_GM,		PCI_CHIP_I915_GM,	RES_SHARED_VGA},
    {PCI_CHIP_I945_G,		PCI_CHIP_I945_G,	RES_SHARED_VGA},
+   {PCI_CHIP_I945_GM,		PCI_CHIP_I945_GM,	RES_SHARED_VGA},
    {-1,				-1, RES_UNDEFINED }
 };
 
@@ -299,6 +304,7 @@ const char *I810drmSymbols[] = {
    "drmGetInterruptFromBusID",
    "drmGetLibVersion",
    "drmGetVersion",
+   "drmRmMap",
    "drmMMInit",
    "drmMMtakedown",
    NULL
@@ -308,6 +314,7 @@ const char *I810drmSymbols[] = {
 const char *I810driSymbols[] = {
    "DRICloseScreen",
    "DRICreateInfoRec",
+   "DRIGetContext",
    "DRIDestroyInfoRec",
    "DRIFinishScreenInit",
    "DRIGetSAREAPrivate",
@@ -319,16 +326,17 @@ const char *I810driSymbols[] = {
    "DRICreatePCIBusID",
    NULL
 };
+#endif 
 
 const char *I810shadowSymbols[] = {
     "shadowInit",
     "shadowSetup",
     "shadowAdd",
+    "shadowRemove",
+    "shadowUpdateRotatePacked",
     NULL
 };
 
-#endif 
-
 #ifndef I810_DEBUG
 int I810_DEBUG = (0
 /*     		  | DEBUG_ALWAYS_SYNC  */
@@ -571,6 +579,7 @@ I810Probe(DriverPtr drv, int flags)
 	    case PCI_CHIP_E7221_G:
 	    case PCI_CHIP_I915_GM:
 	    case PCI_CHIP_I945_G:
+	    case PCI_CHIP_I945_GM:
     	       xf86SetEntitySharable(usedChips[i]);
 
     	       /* Allocate an entity private if necessary */		
@@ -1086,7 +1095,7 @@ I810PreInit(ScrnInfoPtr pScrn, int flags
 #ifdef XF86DRI
    if (!pI810->directRenderingDisabled) {
      pI810->allowPageFlip = enable;
-     if (pI810->allowPageFlip == enable)
+     if (pI810->allowPageFlip == TRUE)
      {
        if (!xf86LoadSubModule(pScrn, "shadowfb")) {
 	 pI810->allowPageFlip = 0;
@@ -1214,21 +1223,24 @@ I810PrintErrorState(ScrnInfoPtr pScrn)
    I810Ptr pI810 = I810PTR(pScrn);
 
    ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
-	  INREG(PGETBL_CTL), INREG(PGE_ERR));
+	  (unsigned long) INREG(PGETBL_CTL), (unsigned long) INREG(PGE_ERR));
 
-   ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR), INREG(IPEHR));
+   ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long) INREG(IPEIR), 
+	  (unsigned long) INREG(IPEHR));
 
    ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
-	  INREG(LP_RING + RING_TAIL),
-	  INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
-	  INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START));
+	  (unsigned long) INREG(LP_RING + RING_TAIL),
+	  (unsigned long) INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
+	  (unsigned long) INREG(LP_RING + RING_LEN), 
+	  (unsigned long) INREG(LP_RING + RING_START));
 
    ErrorF("eir: %x esr: %x emr: %x\n",
 	  INREG16(EIR), INREG16(ESR), INREG16(EMR));
 
    ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
 
-   ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS));
+   ErrorF("memmode: %lx instps: %lx\n", (unsigned long) INREG(MEMMODE), 
+	  (unsigned long) INREG(INST_PS));
 
    ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
 	  INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
diff --git a/src/i810_hwmc.c b/src/i810_hwmc.c
index 5d25323..d56dfc4 100644
--- a/src/i810_hwmc.c
+++ b/src/i810_hwmc.c
@@ -38,10 +38,11 @@ THE USE OR OTHER DEALINGS IN THE SOFTWAR
 #include "config.h"
 #endif
 
+#include <string.h>
+
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
-#include "xf86_ansic.h"
 #include "compiler.h"
 #include "xf86PciInfo.h"
 #include "xf86Pci.h"
@@ -210,12 +211,12 @@ void I810InitMC(ScreenPtr pScreen)
 
   /* Cursor is at a page boundary, Overlay regs are not, don't forget */
   if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->CursorStart,
-                4096, DRM_AGP, 0, &pI810->overlay_map) < 0) {
+                4096, DRM_AGP, 0, (drmAddress) &pI810->overlay_map) < 0) {
     xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(overlay) failed\n");
     return;
   }
   if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->MC.Start,
-                pI810->MC.Size, DRM_AGP, 0, &pI810->mc_map) < 0) {
+                pI810->MC.Size, DRM_AGP, 0, (drmAddress) &pI810->mc_map) < 0) {
     xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(MC) failed\n");
     return;
   }
@@ -245,14 +246,14 @@ int I810XvMCCreateContext (ScrnInfoPtr p
 
 
   if(!pI810->directRenderingEnabled) {
-    xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
         "I810XvMCCreateContext: Cannot use XvMC without DRI!\n");
     return BadAlloc;
   }
 
   /* Context Already in use! */
   if(pI810->xvmcContext) {
-    xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
         "I810XvMCCreateContext: 2 XvMC Contexts Attempted, not supported.\n");
     return BadAlloc;
   }
@@ -267,7 +268,7 @@ int I810XvMCCreateContext (ScrnInfoPtr p
 
   *num_priv = sizeof(I810XvMCCreateContextRec) >> 2;
   if(drmCreateContext(pI810->drmSubFD, &(contextRec->drmcontext) ) < 0) {
-    xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
         "I810XvMCCreateContext: Unable to create DRMContext!\n");
     xfree(*priv);
     return BadAlloc;
@@ -299,7 +300,7 @@ int I810XvMCCreateSurface (ScrnInfoPtr p
   *priv = (long *)xcalloc(2,sizeof(long));
 
   if(!*priv) {
-    xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
         "I810XvMCCreateSurface: Unable to allocate memory!\n");
     *num_priv = 0;
     return BadAlloc;
@@ -345,7 +346,7 @@ int I810XvMCCreateSubpicture (ScrnInfoPt
   *priv = (long *)xcalloc(1,sizeof(long));
 
   if(!*priv) {
-    xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
+    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
         "I810XvMCCreateSubpicture: Unable to allocate memory!\n");
     *num_priv = 0;
     return BadAlloc;
diff --git a/src/i810_io.c b/src/i810_io.c
index 8d097f2..abe1d6f 100644
--- a/src/i810_io.c
+++ b/src/i810_io.c
@@ -50,7 +50,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  */
 
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "xf86_OSproc.h"
 #include "compiler.h"
 
diff --git a/src/i810_memory.c b/src/i810_memory.c
index 816e5d8..82d86eb 100644
--- a/src/i810_memory.c
+++ b/src/i810_memory.c
@@ -50,7 +50,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  */
 
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "xf86_OSproc.h"
 
 #include "i810.h"
@@ -265,7 +264,7 @@ I810SetTiledMemory(ScrnInfoPtr pScrn, in
    CARD32 fence_mask = 0;
 
    if (nr < 0 || nr > 7) {
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex, "%s - fence %d out of range\n",
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s - fence %d out of range\n",
 		 "I810SetTiledMemory", nr);
       return;
    }
@@ -275,21 +274,21 @@ I810SetTiledMemory(ScrnInfoPtr pScrn, in
    fence_mask = ~FENCE_START_MASK;
 
    if (start & fence_mask) {
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "%s %d: start (%x) is not 512k aligned\n",
 		 "I810SetTiledMemory", nr, start);
       return;
    }
 
    if (start % size) {
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "%s %d: start (%x) is not size (%x) aligned\n",
 		 "I810SetTiledMemory", nr, start, size);
       return;
    }
 
    if (pitch & 127) {
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "%s %d: pitch (%x) not a multiple of 128 bytes\n",
 		 "I810SetTiledMemory", nr, pitch);
       return;
@@ -320,7 +319,7 @@ I810SetTiledMemory(ScrnInfoPtr pScrn, in
       val |= FENCE_SIZE_32M;
       break;
    default:
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr,
 		 size);
       return;
@@ -346,7 +345,7 @@ I810SetTiledMemory(ScrnInfoPtr pScrn, in
       val |= FENCE_PITCH_32;
       break;
    default:
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr,
 		 size);
       return;
diff --git a/src/i810_video.c b/src/i810_video.c
index f420d2f..e65a7f6 100644
--- a/src/i810_video.c
+++ b/src/i810_video.c
@@ -38,10 +38,11 @@ THE USE OR OTHER DEALINGS IN THE SOFTWAR
 #include "config.h"
 #endif
 
+#include <string.h>
+
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
-#include "xf86_ansic.h"
 #include "compiler.h"
 #include "xf86PciInfo.h"
 #include "xf86Pci.h"
@@ -75,7 +76,8 @@ static void I810QueryBestSize(ScrnInfoPt
 	short, short, short, short, unsigned int *, unsigned int *, pointer);
 static int I810PutImage( ScrnInfoPtr, 
 	short, short, short, short, short, short, short, short,
-	int, unsigned char*, short, short, Bool, RegionPtr, pointer);
+	int, unsigned char*, short, short, Bool, RegionPtr, pointer,
+	DrawablePtr);
 static int I810QueryImageAttributes(ScrnInfoPtr, 
 	int, unsigned short *, unsigned short *,  int *, int *);
 
@@ -973,7 +975,8 @@ I810PutImage( 
   int id, unsigned char* buf, 
   short width, short height, 
   Bool sync,
-  RegionPtr clipBoxes, pointer data
+  RegionPtr clipBoxes, pointer data,
+  DrawablePtr pDraw
 ){
     I810Ptr pI810 = I810PTR(pScrn);
     I810PortPrivPtr pPriv = (I810PortPrivPtr)data;
diff --git a/src/i830.h b/src/i830.h
index eef28e7..14e921d 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -47,7 +47,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #ifndef _I830_H_
 #define _I830_H_
 
-#include "xf86_ansic.h"
 #include "compiler.h"
 #include "xf86PciInfo.h"
 #include "xf86Pci.h"
@@ -58,6 +57,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "xf86int10.h"
 #include "vbe.h"
 #include "vgaHW.h"
+#include "randrstr.h"
 
 #ifdef XF86DRI
 #include "xf86drm.h"
@@ -168,6 +168,8 @@ typedef struct _I830Rec {
    
    int fixedPipe;
 
+   DisplayModePtr currentMode;
+
    Bool Clone;
    int CloneRefresh;
    int CloneHDisplay;
@@ -214,13 +216,25 @@ typedef struct _I830Rec {
 #ifdef I830_XV
    /* For Xvideo */
    I830MemRange *OverlayMem;
+   I830MemRange LinearMem;
 #endif
+   unsigned int LinearAlloc;
+  
+   XF86ModReqInfo shadowReq; /* to test for later libshadow */
+   I830MemRange RotatedMem;
+   I830MemRange RotatedMem2;
+   Rotation rotation;
+   int InitialRotation;
+   int displayWidth;
+   void (*PointerMoved)(int, int, int);
+   CreateScreenResourcesProcPtr    CreateScreenResources;
+   int *used3D;
 
+   I830MemRange ContextMem;
 #ifdef XF86DRI
    I830MemRange BackBuffer;
    I830MemRange DepthBuffer;
    I830MemRange TexMem;
-   I830MemRange ContextMem;
    int TexGranularity;
    int drmMinor;
    Bool have3DWindows;
@@ -234,6 +248,7 @@ typedef struct _I830Rec {
 
    Bool CursorNeedsPhysical;
    Bool CursorIsARGB;
+   CursorPtr pCurs;
 
    int MonType1;
    int MonType2;
@@ -303,13 +318,6 @@ typedef struct _I830Rec {
 
    /* Broken-out options. */
    OptionInfoPtr Options;
-   int rotate;
-   Bool shadowFB;
-
-   /* Support for shadowFB and rotation. */
-   unsigned char *shadowPtr;
-   int shadowPitch;
-   void (*PointerMoved)(int, int, int);
 
    /* Stolen memory support */
    Bool StolenOnly;
@@ -335,8 +343,9 @@ typedef struct _I830Rec {
    Bool checkDevices;
    int monitorSwitch;
    int operatingDevices;
+   int toggleDevices;
    int savedDevices;
-   int lastDevice1, lastDevice2;
+   int lastDevice0, lastDevice1, lastDevice2;
 
    /* These are indexed by the display types */
    Bool displayAttached[NumDisplayTypes];
@@ -385,7 +394,9 @@ extern void I830PrintErrorState(ScrnInfo
 extern void I830Sync(ScrnInfoPtr pScrn);
 extern void I830InitHWCursor(ScrnInfoPtr pScrn);
 extern Bool I830CursorInit(ScreenPtr pScreen);
+extern void IntelEmitInvarientState(ScrnInfoPtr pScrn);
 extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
+extern void I915EmitInvarientState(ScrnInfoPtr pScrn);
 extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer);
 
 extern void I830RefreshRing(ScrnInfoPtr pScrn);
@@ -399,15 +410,28 @@ extern void I830VideoSwitchModeBefore(Sc
 extern void I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode);
 #endif
 
+extern Bool I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, const int flags);
+extern Bool I830AllocateRotated2Buffer(ScrnInfoPtr pScrn, const int flags);
 #ifdef XF86DRI
 extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags);
+extern Bool I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags);
+extern Bool I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags);
+extern Bool I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags);
 extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn);
 extern Bool I830DRIScreenInit(ScreenPtr pScreen);
+extern Bool I830CheckDRIAvailable(ScrnInfoPtr pScrn);
 extern Bool I830DRIDoMappings(ScreenPtr pScreen);
 extern Bool I830DRIResume(ScreenPtr pScreen);
 extern void I830DRICloseScreen(ScreenPtr pScreen);
 extern Bool I830DRIFinishScreenInit(ScreenPtr pScreen);
+extern Bool I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
+extern void I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
+extern Bool I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea);
+extern void I830DRIUnlock(ScrnInfoPtr pScrn);
+extern Bool I830DRILock(ScrnInfoPtr pScrn);
+extern Bool I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on);
 #endif
+
 extern Bool I830AccelInit(ScreenPtr pScreen);
 extern void I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
 					   int ydir, int rop,
@@ -432,11 +456,13 @@ extern Bool I830UnbindGARTMemory(ScrnInf
 extern unsigned long I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result,
 				     I830MemPool *pool, long size,
 				     unsigned long alignment, int flags);
+extern void I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range);
 
 extern void I830PrintAllRegisters(I830RegPtr i830Reg);
 extern void I830ReadAllRegisters(I830Ptr pI830, I830RegPtr i830Reg);
 
 extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer);
+extern Bool I830IsPrimary(ScrnInfoPtr pScrn);
 
 extern DisplayModePtr I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe,
 					VbeInfoBlock *vbe);
@@ -445,12 +471,18 @@ extern void I830UnsetModeParameters(Scrn
 extern void I830PrintModes(ScrnInfoPtr pScrn);
 extern int I830GetBestRefresh(ScrnInfoPtr pScrn, int refresh);
 extern Bool I830CheckModeSupport(ScrnInfoPtr pScrn, int x, int y, int mode);
-extern void I830PointerMoved(int index, int x, int y);
-extern void I830RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
-extern void I830RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
-extern void I830RefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
-extern void I830RefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
-extern void I830RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
+extern Bool I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode);
+extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
+
+/* i830_memory.c */
+Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
+Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
+
+/* i830_randr.c */
+Bool I830RandRInit(ScreenPtr pScreen, int rotation);
+Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
+			RRScreenSizePtr pSize);
+Rotation I830GetRotation(ScreenPtr pScreen);
 
 /*
  * 12288 is set as the maximum, chosen because it is enough for
diff --git a/src/i830_3d.c b/src/i830_3d.c
new file mode 100644
index 0000000..debad7c
--- /dev/null
+++ b/src/i830_3d.c
@@ -0,0 +1,131 @@
+/**************************************************************************
+ * 
+ * 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.
+ * 
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+
+#include "i830_reg.h"
+
+#define CMD_3D (0x3<<29)
+
+void I830EmitInvarientState( ScrnInfoPtr pScrn )
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   BEGIN_LP_RING(38);
+
+   OUT_RING(_3DSTATE_MAP_CUBE | MAP_UNIT(0));
+   OUT_RING(_3DSTATE_MAP_CUBE | MAP_UNIT(1));
+   OUT_RING(_3DSTATE_MAP_CUBE | MAP_UNIT(2));
+   OUT_RING(_3DSTATE_MAP_CUBE | MAP_UNIT(3));
+
+   OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
+   OUT_RING(0);
+
+   OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
+   OUT_RING(0);
+
+   OUT_RING(_3DSTATE_DFLT_Z_CMD);
+   OUT_RING(0);
+
+   OUT_RING(_3DSTATE_FOG_MODE_CMD);
+   OUT_RING(FOGFUNC_ENABLE |
+	     FOG_LINEAR_CONST | 
+	     FOGSRC_INDEX_Z | 
+	     ENABLE_FOG_DENSITY);
+   OUT_RING(0);
+   OUT_RING(0);
+
+
+   OUT_RING(_3DSTATE_MAP_TEX_STREAM_CMD |
+	     MAP_UNIT(0) |
+	     DISABLE_TEX_STREAM_BUMP |
+	     ENABLE_TEX_STREAM_COORD_SET |
+	     TEX_STREAM_COORD_SET(0) |
+	     ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(0));
+   OUT_RING(_3DSTATE_MAP_TEX_STREAM_CMD |
+	     MAP_UNIT(1) |
+	     DISABLE_TEX_STREAM_BUMP |
+	     ENABLE_TEX_STREAM_COORD_SET |
+	     TEX_STREAM_COORD_SET(1) |
+	     ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(1));
+   OUT_RING(_3DSTATE_MAP_TEX_STREAM_CMD |
+	     MAP_UNIT(2) |
+	     DISABLE_TEX_STREAM_BUMP |
+	     ENABLE_TEX_STREAM_COORD_SET |
+	     TEX_STREAM_COORD_SET(2) |
+	     ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(2));
+   OUT_RING(_3DSTATE_MAP_TEX_STREAM_CMD |
+	     MAP_UNIT(3) |
+	     DISABLE_TEX_STREAM_BUMP |
+	     ENABLE_TEX_STREAM_COORD_SET |
+	     TEX_STREAM_COORD_SET(3) |
+	     ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(3));
+
+   OUT_RING(_3DSTATE_MAP_COORD_TRANSFORM);
+   OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(0));
+   OUT_RING(_3DSTATE_MAP_COORD_TRANSFORM);
+   OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(1));
+   OUT_RING(_3DSTATE_MAP_COORD_TRANSFORM);
+   OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(2));
+   OUT_RING(_3DSTATE_MAP_COORD_TRANSFORM);
+   OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3));
+
+   OUT_RING(_3DSTATE_RASTER_RULES_CMD |
+	     ENABLE_POINT_RASTER_RULE |
+	     OGL_POINT_RASTER_RULE |
+	     ENABLE_LINE_STRIP_PROVOKE_VRTX |
+	     ENABLE_TRI_FAN_PROVOKE_VRTX |
+	     ENABLE_TRI_STRIP_PROVOKE_VRTX |
+	     LINE_STRIP_PROVOKE_VRTX(1) |
+	     TRI_FAN_PROVOKE_VRTX(2) | 
+	     TRI_STRIP_PROVOKE_VRTX(2));
+
+   OUT_RING(_3DSTATE_SCISSOR_ENABLE_CMD | 
+	     DISABLE_SCISSOR_RECT);
+
+   OUT_RING(_3DSTATE_SCISSOR_RECT_0_CMD);
+   OUT_RING(0);
+   OUT_RING(0);
+
+   OUT_RING(_3DSTATE_VERTEX_TRANSFORM);
+   OUT_RING(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
+
+   OUT_RING(_3DSTATE_W_STATE_CMD);
+   OUT_RING(MAGIC_W_STATE_DWORD1);
+   OUT_RING(0x3f800000 /* 1.0 in IEEE float */ );
+
+
+   OUT_RING(_3DSTATE_COLOR_FACTOR_CMD);
+   OUT_RING(0x80808080);	/* .5 required in alpha for GL_DOT3_RGBA_EXT */
+
+   ADVANCE_LP_RING();
+}
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 7211f4b..a11f64b 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -58,7 +58,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  *
  */
 
-#include "xf86_ansic.h"
 #include "xf86.h"
 #include "xaarop.h"
 #include "i830.h"
diff --git a/src/i830_common.h b/src/i830_common.h
index a0a00ff..a27bc01 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -51,6 +51,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DRM_I830_FREE                     0x09
 #define DRM_I830_INIT_HEAP                0x0a
 #define DRM_I830_CMDBUFFER                0x0b
+#define DRM_I830_DESTROY_HEAP             0x0c
+#define DRM_I830_SET_VBLANK_PIPE	  0x0d
+#define DRM_I830_GET_VBLANK_PIPE	  0x0e
+
 
 typedef struct {
    enum {
@@ -87,6 +91,30 @@ typedef struct {
         int pf_active;               
         int pf_current_page;	/* which buffer is being displayed? */
         int perf_boxes;	        /* performance boxes to be displayed */   
+	int width, height;      /* screen size in pixels */
+
+	drm_handle_t front_handle;
+	int front_offset;
+	int front_size;
+
+	drm_handle_t back_handle;
+	int back_offset;
+	int back_size;
+
+	drm_handle_t depth_handle;
+	int depth_offset;
+	int depth_size;
+
+	drm_handle_t tex_handle;
+	int tex_offset;
+	int tex_size;
+	int log_tex_granularity;
+	int pitch;
+	int rotation;           /* 0, 90, 180 or 270 */
+	int rotated_offset;
+	int rotated_size;
+	int rotated_pitch;
+	int virtualX, virtualY;
 } drmI830Sarea;
 
 /* Flags for perf_boxes
@@ -164,5 +192,15 @@ typedef struct {
 	int start;	
 } drmI830MemInitHeap;
 
+typedef struct {
+	int region;
+} drmI830MemDestroyHeap;
+
+#define	DRM_I830_VBLANK_PIPE_A	1
+#define	DRM_I830_VBLANK_PIPE_B	2
+
+typedef struct {
+	int pipe;
+} drmI830VBlankPipe;
 
 #endif /* _I830_DRM_H_ */
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 2411419..e465b98 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -58,9 +58,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "config.h"
 #endif
 
+#include <string.h>
+
 #include "xf86.h"
 #include "xf86_OSproc.h"
-#include "xf86_ansic.h"
 #include "compiler.h"
 
 #include "xf86fbman.h"
@@ -86,12 +87,14 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "I830InitHWCursor\n");
    /* Initialise the HW cursor registers, leaving the cursor hidden. */
-   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
+   if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
       temp = INREG(CURSOR_A_CONTROL);
       temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL |
 		MCURSOR_PIPE_SELECT);
       temp |= CURSOR_MODE_DISABLE;
       temp |= (pI830->pipe << 28);
+      if(pI830->CursorIsARGB)
+         temp |= MCURSOR_GAMMA_ENABLE;
       /* Need to set control, then address. */
       OUTREG(CURSOR_A_CONTROL, temp);
       if (pI830->CursorIsARGB)
@@ -112,6 +115,8 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
       temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
 		CURSOR_ENABLE  | CURSOR_STRIDE_MASK);
       temp |= (CURSOR_FORMAT_3C);
+      if (pI830->CursorIsARGB)
+         temp |= CURSOR_GAMMA_ENABLE;
       /* This initialises the format and leave the cursor disabled. */
       OUTREG(CURSOR_CONTROL, temp);
       /* Need to set address and size after disabling. */
@@ -139,8 +144,8 @@ I830CursorInit(ScreenPtr pScreen)
    if (!infoPtr)
       return FALSE;
 
-   infoPtr->MaxWidth = 64;
-   infoPtr->MaxHeight = 64;
+   infoPtr->MaxWidth = I810_CURSOR_X;
+   infoPtr->MaxHeight = I810_CURSOR_Y;
    infoPtr->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
 		     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
 		     HARDWARE_CURSOR_INVERT_MASK |
@@ -155,6 +160,8 @@ I830CursorInit(ScreenPtr pScreen)
    infoPtr->ShowCursor = I830ShowCursor;
    infoPtr->UseHWCursor = I830UseHWCursor;
 
+   pI830->pCurs = NULL;
+
 #ifdef ARGB_CURSOR
    pI830->CursorIsARGB = FALSE;
 
@@ -179,6 +186,8 @@ I830UseHWCursor(ScreenPtr pScreen, Curso
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
 
+   pI830->pCurs = pCurs;
+
    DPRINTF(PFX, "I830UseHWCursor\n");
    if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) 
       return FALSE;
@@ -198,6 +207,52 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, u
 #ifdef ARGB_CURSOR
    pI830->CursorIsARGB = FALSE;
 #endif
+ 
+   memset(pcurs, 0, 64 * 64 / 4);
+
+#define GetBit(image, x, y)\
+    ((int)((*(image + ((x) / 8) + ((y) * (128/8))) &\
+	    (1 << ( 7 -((x) % 8) ))) ? 1 : 0))
+
+#define SetBit(image, x, y)\
+    (*(image + (x) / 8 + (y) * (128/8)) |=\
+     (int) (1 <<  (7-((x) % 8))))
+
+   switch (pI830->rotation) {
+      case RR_Rotate_90:
+         for (y = 0; y < 64; y++) {
+            for (x = 0; x < 64; x++) {
+               if (GetBit(src, 64 - y - 1, x))
+                  SetBit(pcurs, x, y);
+               if (GetBit(src, 128 - y - 1, x))
+                  SetBit(pcurs, x + 64, y);
+            }
+         }
+
+         return;
+      case RR_Rotate_180:
+         for (y = 0; y < 64; y++) {
+            for (x = 0; x < 64; x++) {
+               if (GetBit(src, 64 - x - 1, 64 - y - 1))
+                  SetBit(pcurs, x, y);
+               if (GetBit(src, 128 - x - 1, 64 - y - 1))
+                  SetBit(pcurs, x + 64, y);
+            }
+         }
+
+         return;
+      case RR_Rotate_270:
+         for (y = 0; y < 64; y++) {
+            for (x = 0; x < 64; x++) {
+               if (GetBit(src, y, 64 - x - 1))
+                  SetBit(pcurs, x, y);
+               if (GetBit(src, y + 64, 64 - x - 1))
+                  SetBit(pcurs, x + 64, y);
+            }
+         }
+
+         return;
+   }
 
    for (y = 0; y < 64; y++) {
       for (x = 0; x < 64 / 4; x++) {
@@ -215,6 +270,9 @@ static Bool I830UseHWCursorARGB (ScreenP
    I830Ptr pI830 = I830PTR(pScrn);
 
    DPRINTF(PFX, "I830UseHWCursorARGB\n");
+
+   pI830->pCurs = pCurs;
+
    if (pScrn->bitsPerPixel == 8)
       return FALSE;
 
@@ -239,13 +297,52 @@ static void I830LoadCursorARGB (ScrnInfo
    if (!image)
 	return;	/* XXX can't happen */
     
-#ifdef ARGB_CURSOR
    pI830->CursorIsARGB = TRUE;
-#endif
 
    w = pCurs->bits->width;
    h = pCurs->bits->height;
 
+   switch (pI830->rotation) {
+      case RR_Rotate_90:
+         for (y = 0; y < h; y++) {
+            for (x = 0; x < w; x++)
+               dst[(y) + ((64 - x - 1) * 64)] = *image++;
+            for(; x < 64; x++)
+               dst[(y) + ((64 - x - 1) * 64)] = 0;
+         }
+         for(; y < 64; y++) {
+   	    for(x = 0; x < 64; x++)
+               dst[(y) + ((64 - x - 1) * 64)] = 0;
+         }
+         return;
+
+      case RR_Rotate_180:
+         for (y = 0; y < h; y++) {
+            for (x = 0; x < w; x++)
+               dst[(64 - x - 1) + ((64 - y - 1) * 64)] = *image++;
+            for(; x < 64; x++)
+               dst[(64 - x - 1) + ((64 - y - 1) * 64)] = 0;
+         }
+         for(; y < 64; y++) {
+            for(x = 0; x < 64; x++)
+               dst[(64 - x - 1) + ((64 - y - 1) * 64)] = 0;
+         }
+         return;
+
+      case RR_Rotate_270:
+         for (y = 0; y < h; y++) {
+            for (x = 0; x < w; x++)
+               dst[(64 - y - 1) + (x * 64)] = *image++;
+            for(; x < 64; x++)
+               dst[(64 - y - 1) + (x * 64)] = 0;
+         }
+         for(; y < 64; y++) {
+            for(x = 0; x < 64; x++)
+               dst[(64 - y - 1) + (x * 64)] = 0;
+         }
+         return;
+   }
+
    for(y = 0; y < h; y++) {
       for(x = 0; x < w; x++)
           *dst++ = *image++;
@@ -265,9 +362,53 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 {
    I830Ptr pI830 = I830PTR(pScrn);
    CARD32 temp = 0;
-   static Bool outsideViewport = FALSE;
    Bool hide = FALSE, show = FALSE;
+   int oldx = x, oldy = y;
+   int hotspotx = 0, hotspoty = 0;
+#if 0
+   static Bool outsideViewport = FALSE;
+#endif
+
+   oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
+   oldy += pScrn->frameY0;
 
+   switch (pI830->rotation) {
+      case RR_Rotate_0:
+         x = oldx;
+         y = oldy;
+         break;
+      case RR_Rotate_90:
+         x = oldy;
+         y = pScrn->pScreen->width - oldx;
+         hotspoty = I810_CURSOR_X;
+         break;
+      case RR_Rotate_180:
+         x = pScrn->pScreen->width - oldx;
+         y = pScrn->pScreen->height - oldy;
+         hotspotx = I810_CURSOR_X;
+         hotspoty = I810_CURSOR_Y;
+         break;
+      case RR_Rotate_270:
+         x = pScrn->pScreen->height - oldy;
+         y = oldx;
+         hotspotx = I810_CURSOR_Y;
+         break;
+   }
+
+   x -= hotspotx;
+   y -= hotspoty;
+
+   /* Now, readjust */
+   x -= pScrn->frameX0;
+   y -= pScrn->frameY0;
+
+   /* Clamp the cursor position to the visible screen area */
+   if (x >= pScrn->currentMode->HDisplay) x = pScrn->currentMode->HDisplay - 1;
+   if (y >= pScrn->currentMode->VDisplay) y = pScrn->currentMode->VDisplay - 1;
+   if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1;
+   if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1;
+
+#if 0
    /*
     * There is a screen display problem when the cursor position is set
     * wholely outside of the viewport.  We trap that here, turning the
@@ -283,6 +424,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
       show = TRUE;
       outsideViewport = FALSE;
    }
+#endif
 
    if (x < 0) {
       temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
@@ -308,7 +450,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
    }
 
    /* have to upload the base for the new position */
-   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+   if (IS_I9XX(pI830)) {
       if (pI830->CursorIsARGB)
          OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
       else
@@ -339,11 +481,11 @@ I830ShowCursor(ScrnInfoPtr pScrn)
 	   pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
 
    pI830->cursorOn = TRUE;
-   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
+   if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
       temp = INREG(CURSOR_A_CONTROL);
       temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
       if (pI830->CursorIsARGB)
-         temp |= CURSOR_MODE_64_ARGB_AX;
+         temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
       else
          temp |= CURSOR_MODE_64_4C_AX;
       temp |= (pI830->pipe << 28); /* Connect to correct pipe */
@@ -367,7 +509,7 @@ I830ShowCursor(ScrnInfoPtr pScrn)
       temp &= ~(CURSOR_FORMAT_MASK);
       temp |= CURSOR_ENABLE;
       if (pI830->CursorIsARGB)
-         temp |= CURSOR_FORMAT_ARGB;
+         temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
       else 
          temp |= CURSOR_FORMAT_3C;
       OUTREG(CURSOR_CONTROL, temp);
@@ -387,9 +529,9 @@ I830HideCursor(ScrnInfoPtr pScrn)
    DPRINTF(PFX, "I830HideCursor\n");
 
    pI830->cursorOn = FALSE;
-   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830)) {
+   if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
       temp = INREG(CURSOR_A_CONTROL);
-      temp &= ~CURSOR_MODE;
+      temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
       temp |= CURSOR_MODE_DISABLE;
       OUTREG(CURSOR_A_CONTROL, temp);
       /* This is needed to flush the above change. */
@@ -406,7 +548,7 @@ I830HideCursor(ScrnInfoPtr pScrn)
       }
    } else {
       temp = INREG(CURSOR_CONTROL);
-      temp &= ~CURSOR_ENABLE;
+      temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
       OUTREG(CURSOR_CONTROL, temp);
    }
 }
diff --git a/src/i830_dga.c b/src/i830_dga.c
index e1991db..1129fa3 100644
--- a/src/i830_dga.c
+++ b/src/i830_dga.c
@@ -42,7 +42,6 @@
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
-#include "xf86_ansic.h"
 #include "xf86Pci.h"
 #include "xf86PciInfo.h"
 #include "xaa.h"
@@ -54,6 +53,7 @@
 
 static Bool I830_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
 				 int *, int *, int *);
+static void I830_CloseFramebuffer(ScrnInfoPtr pScrn);
 static Bool I830_SetMode(ScrnInfoPtr, DGAModePtr);
 static void I830_Sync(ScrnInfoPtr);
 static int I830_GetViewport(ScrnInfoPtr);
@@ -69,7 +69,7 @@ static void I830_BlitTransRect(ScrnInfoP
 static
 DGAFunctionRec I830DGAFuncs = {
    I830_OpenFramebuffer,
-   NULL,
+   I830_CloseFramebuffer,
    I830_SetMode,
    I830_SetViewport,
    I830_GetViewport,
@@ -131,11 +131,22 @@ I830DGAInit(ScreenPtr pScreen)
       currentMode->yViewportStep = 1;
       currentMode->viewportFlags = DGA_FLIP_RETRACE;
       currentMode->offset = 0;
-      currentMode->address = pI830->FbBase + pScrn->fbOffset;
+      if (I830IsPrimary(pScrn)) {
+         currentMode->address = pI830->FbBase + pI830->FrontBuffer.Start;
+      } else {
+         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+         currentMode->address = pI830->FbBase + pI8301->FrontBuffer2.Start;
+      }
 
-      currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
-      currentMode->imageWidth = pI830->FbMemBox.x2;
-      currentMode->imageHeight = pI830->FbMemBox.y2;
+      currentMode->bytesPerScanline = ((pI830->displayWidth * Bpp) + 3) & ~3L;
+      if (I830IsPrimary(pScrn)) {
+         currentMode->imageWidth = pI830->FbMemBox.x2;
+         currentMode->imageHeight = pI830->FbMemBox.y2;
+      } else {
+         I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+         currentMode->imageWidth = pI8301->FbMemBox2.x2;
+         currentMode->imageHeight = pI8301->FbMemBox2.y2;
+      }
       currentMode->pixmapWidth = currentMode->imageWidth;
       currentMode->pixmapHeight = currentMode->imageHeight;
       currentMode->maxViewportX = currentMode->imageWidth -
@@ -168,6 +179,7 @@ I830_SetMode(ScrnInfoPtr pScrn, DGAModeP
    if (!pMode) {			/* restore the original mode */
       DPRINTF(PFX, "Restoring original mode (from DGA mode)\n");
       if (pI830->DGAactive) {
+         I830_CloseFramebuffer(pScrn);
 	 pScrn->currentMode = I830SavedDGAModes[index];
 	 pScrn->SwitchMode(index, pScrn->currentMode, 0);
 	 pScrn->AdjustFrame(index, 0, 0, 0);
@@ -178,6 +190,15 @@ I830_SetMode(ScrnInfoPtr pScrn, DGAModeP
 	 DPRINTF(PFX, "Setting DGA mode\n");
 	 I830SavedDGAModes[index] = pScrn->currentMode;
 	 pI830->DGAactive = TRUE;
+         if (I830IsPrimary(pScrn)) {
+            pScrn->fbOffset = pI830->FrontBuffer.Start;
+         }
+         else {
+            I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+            pScrn->fbOffset = pI8301->FrontBuffer2.Start;
+         }
+         pScrn->displayWidth = pI830->displayWidth;
+         I830SelectBuffer(pScrn, I830_SELECT_FRONT);
       }
 
       pScrn->SwitchMode(index, pMode->mode, 0);
@@ -284,13 +305,19 @@ I830_OpenFramebuffer(ScrnInfoPtr pScrn,
    MARKER();
 
    *name = NULL;			/* no special device */
-   *mem = (unsigned char *)(pI830->LinearAddr + pScrn->fbOffset);
-   if (pI830->init == 0)
+   if (I830IsPrimary(pScrn)) {
       *size = pI830->FrontBuffer.Size;
+      *mem = (unsigned char *)(pI830->LinearAddr + pI830->FrontBuffer.Start);
+      pScrn->fbOffset = pI830->FrontBuffer.Start;
+   }
    else {
       I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
       *size = pI8301->FrontBuffer2.Size;
+      *mem = (unsigned char *)(pI8301->LinearAddr + pI8301->FrontBuffer2.Start);
+      pScrn->fbOffset = pI8301->FrontBuffer2.Start;
    }
+   pScrn->displayWidth = pI830->displayWidth;
+   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
    *offset = 0;
    *flags = DGA_NEED_ROOT;
 
@@ -300,3 +327,77 @@ I830_OpenFramebuffer(ScrnInfoPtr pScrn,
 
    return TRUE;
 }
+
+static void
+I830_CloseFramebuffer(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   int i;
+   /* Good pitches to allow tiling.  Don't care about pitches < 1024. */
+   static const int pitches[] = {
+/*
+	 128 * 2,
+	 128 * 4,
+*/
+	 128 * 8,
+	 128 * 16,
+	 128 * 32,
+	 128 * 64,
+	 0
+   };
+
+   if (I830IsPrimary(pScrn)) {
+      if (pI830->rotation != RR_Rotate_0)
+         pScrn->fbOffset = pI830->RotatedMem.Start;
+      else
+         pScrn->fbOffset = pI830->FrontBuffer.Start;
+   } else {
+      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+
+      if (pI830->rotation != RR_Rotate_0)
+         pScrn->fbOffset = pI8301->RotatedMem2.Start;
+      else
+         pScrn->fbOffset = pI8301->FrontBuffer2.Start;
+   }
+   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+   switch (pI830->rotation) {
+      case RR_Rotate_0:
+         pScrn->displayWidth = pI830->displayWidth;
+         break;
+      case RR_Rotate_90:
+         pScrn->displayWidth = pScrn->pScreen->width;
+         break;
+      case RR_Rotate_180:
+         pScrn->displayWidth = pI830->displayWidth;
+         break;
+      case RR_Rotate_270:
+         pScrn->displayWidth = pScrn->pScreen->width;
+         break;
+   }
+
+   /* As DRI doesn't run on the secondary head, we know that disableTiling
+    * is always TRUE.
+    */
+   if (I830IsPrimary(pScrn) && !pI830->disableTiling) {
+#if 0
+      int dWidth = pScrn->displayWidth; /* save current displayWidth */
+#endif
+
+      for (i = 0; pitches[i] != 0; i++) {
+         if (pitches[i] >= pScrn->displayWidth) {
+            pScrn->displayWidth = pitches[i];
+            break;
+         }
+      }
+
+      /*
+       * If the displayWidth is a tilable pitch, test if there's enough
+       * memory available to enable tiling.
+       */
+      if (pScrn->displayWidth == pitches[i]) {
+  	/* TODO */
+      }
+   }
+
+}
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 092a6ee..8f8449a 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -62,9 +62,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "config.h"
 #endif
 
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
 #include "xf86.h"
 #include "xf86_OSproc.h"
-#include "xf86_ansic.h"
 #include "xf86Priv.h"
 
 #include "xf86PciInfo.h"
@@ -101,7 +104,9 @@ static void I830DRITransitionTo3d(Screen
 static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
 static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
 
+#if 0
 static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf);
+#endif
 
 extern void GlxSetVisualConfigs(int nconfigs,
 				__GLXvisualConfig * configs,
@@ -149,9 +154,9 @@ I830InitDma(ScrnInfoPtr pScrn)
    info.depth_offset = pI830->DepthBuffer.Start;
    info.w = pScrn->virtualX;
    info.h = pScrn->virtualY;
-   info.pitch = pI830->backPitch;
-   info.back_pitch = pI830->backPitch;
-   info.depth_pitch = pI830->backPitch;
+   info.pitch = pI830->displayWidth;
+   info.back_pitch = pI830->displayWidth;
+   info.depth_pitch = pI830->displayWidth;
    info.cpp = pI830->cpp;
 
    if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT,
@@ -405,18 +410,12 @@ I830InitVisualConfigs(ScreenPtr pScreen)
 }
 
 Bool
-I830DRIScreenInit(ScreenPtr pScreen)
+I830CheckDRIAvailable(ScrnInfoPtr pScrn)
 {
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   DRIInfoPtr pDRIInfo;
-   I830DRIPtr pI830DRI;
-
-   DPRINTF(PFX, "I830DRIScreenInit\n");
    /* Hardware 3D rendering only implemented for 16bpp and 32 bpp */
    if (((pScrn->bitsPerPixel / 8) != 2 && pScrn->depth != 16) &&
        (pScrn->bitsPerPixel / 8) != 4) {
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "[drm] Direct rendering only supported in 16 and 32 bpp modes\n");
       return FALSE;
    }
@@ -428,7 +427,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
    if (!xf86LoaderCheckSymbol("drmAvailable"))
       return FALSE;
    if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "[dri] %s failed (libdri.a too old)\n", "I830DRIScreenInit");
       return FALSE;
    }
@@ -439,7 +438,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
 
       DRIQueryVersion(&major, &minor, &patch);
       if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
-	 xf86DrvMsg(pScreen->myNum, X_ERROR,
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "[dri] %s failed because of a version mismatch.\n"
 		    "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n"
 		    "[dri] Disabling DRI.\n",
@@ -449,6 +448,22 @@ I830DRIScreenInit(ScreenPtr pScreen)
       }
    }
 
+   return TRUE;
+}
+
+Bool
+I830DRIScreenInit(ScreenPtr pScreen)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+   DRIInfoPtr pDRIInfo;
+   I830DRIPtr pI830DRI;
+
+   DPRINTF(PFX, "I830DRIScreenInit\n");
+
+   if (!I830CheckDRIAvailable(pScrn))
+      return FALSE;
+
    pDRIInfo = DRICreateInfoRec();
    if (!pDRIInfo) {
       xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -473,11 +488,13 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION;
    pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION;
    pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL;
-   pDRIInfo->frameBufferPhysicalAddress = pI830->LinearAddr +
+#if 1 /* temporary until this gets removed from the libdri layer */
+   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr +
 					  pI830->FrontBuffer.Start;
    pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth *
 					     pScrn->virtualY * pI830->cpp);
    pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp;
+#endif
    pDRIInfo->ddxDrawableTableEntry = I830_MAX_DRAWABLES;
 
    if (SAREA_MAX_DRAWABLES < I830_MAX_DRAWABLES)
@@ -572,11 +589,11 @@ I830DRIScreenInit(ScreenPtr pScreen)
       /* Check the i915 DRM version */
       version = drmGetVersion(pI830->drmSubFD);
       if (version) {
-	 if (version->version_major != 1 || version->version_minor < 1) {
+	 if (version->version_major != 1 || version->version_minor < 4) {
 	    /* incompatible drm version */
 	    xf86DrvMsg(pScreen->myNum, X_ERROR,
 		       "[dri] %s failed because of a version mismatch.\n"
-		       "[dri] i915 kernel module version is %d.%d.%d but version 1.1 or greater is needed.\n"
+		       "[dri] i915 kernel module version is %d.%d.%d but version 1.4 or greater is needed.\n"
 		       "[dri] Disabling DRI.\n",
 		       "I830DRIScreenInit",
 		       version->version_major,
@@ -601,87 +618,185 @@ I830DRIScreenInit(ScreenPtr pScreen)
 }
 
 Bool
-I830DRIDoMappings(ScreenPtr pScreen)
+I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
 {
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   ScreenPtr pScreen = pScrn->pScreen;
    I830Ptr pI830 = I830PTR(pScrn);
-   DRIInfoPtr pDRIInfo = pI830->pDRIInfo;
-   I830DRIPtr pI830DRI = pDRIInfo->devPrivate;
 
-   DPRINTF(PFX, "I830DRIDoMappings\n");
-   pI830DRI->regsSize = I830_REG_SIZE;
-   if (drmAddMap(pI830->drmSubFD, (drm_handle_t)pI830->MMIOAddr,
-		 pI830DRI->regsSize, DRM_REGISTERS, 0, &pI830DRI->regs) < 0) {
-      xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n");
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+              "[drm] Mapping front buffer\n");
+   if (drmAddMap(pI830->drmSubFD,
+                 (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
+                 sarea->front_size,
+                 DRM_FRAME_BUFFER,  /*DRM_AGP,*/
+                 0,
+                 (drmAddress) &sarea->front_handle) < 0) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                 "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
       DRICloseScreen(pScreen);
       return FALSE;
    }
-   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
-	      pI830DRI->regs);
-
-   /*
-    * The tile setup is now initiated from I830BIOSScreenInit().
-    */
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n",
+              (int)sarea->front_handle);
 
-   pI830->backPitch = pScrn->displayWidth;
-
-   pI830DRI->backbufferSize = pI830->BackBuffer.Size;
+   if (drmAddMap(pI830->drmSubFD,
+                 (drm_handle_t)(sarea->back_offset + pI830->LinearAddr),
+                 sarea->back_size, DRM_AGP, 0,
+                 (drmAddress) &sarea->back_handle) < 0) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                 "[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
+      DRICloseScreen(pScreen);
+      return FALSE;
+   }
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Back Buffer = 0x%08x\n",
+              (int)sarea->back_handle);
 
    if (drmAddMap(pI830->drmSubFD,
-		 (drm_handle_t)pI830->BackBuffer.Start + pI830->LinearAddr,
-		 pI830->BackBuffer.Size, DRM_AGP, 0,
-		 &pI830DRI->backbuffer) < 0) {
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
-		 "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n");
+                 (drm_handle_t)sarea->depth_offset + pI830->LinearAddr,
+                 sarea->depth_size, DRM_AGP, 0,
+                 (drmAddress) &sarea->depth_handle) < 0) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                 "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
       DRICloseScreen(pScreen);
       return FALSE;
    }
-   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Back Buffer = 0x%08x\n",
-	      pI830DRI->backbuffer);
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Depth Buffer = 0x%08x\n",
+              (int)sarea->depth_handle);
 
-   pI830DRI->depthbufferSize = pI830->DepthBuffer.Size;
+#ifdef NOTTM
    if (drmAddMap(pI830->drmSubFD,
-		 (drm_handle_t)pI830->DepthBuffer.Start + pI830->LinearAddr,
-		 pI830->DepthBuffer.Size, DRM_AGP, 0,
-		 &pI830DRI->depthbuffer) < 0) {
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
-		 "[drm] drmAddMap(depthbuffer) failed. Disabling DRI\n");
+		 (drm_handle_t)sarea->tex_offset + pI830->LinearAddr,
+		 sarea->tex_size, DRM_AGP, 0,
+		 (drmAddress) &sarea->tex_handle) < 0) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		 "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
       DRICloseScreen(pScreen);
       return FALSE;
    }
-   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Depth Buffer = 0x%08x\n",
-	      pI830DRI->depthbuffer);
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] textures = 0x%08x\n",
+	      (int)sarea->tex_handle);
+#endif
 
+   return TRUE;
+}
+
+
+void
+I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+#if 1
+   if (sarea->front_handle) {
+      drmRmMap(pI830->drmSubFD, sarea->front_handle);
+      sarea->front_handle = 0;
+   }
+#endif
+   if (sarea->back_handle) {
+      drmRmMap(pI830->drmSubFD, sarea->back_handle);
+      sarea->back_handle = 0;
+   }
+   if (sarea->depth_handle) {
+      drmRmMap(pI830->drmSubFD, sarea->depth_handle);
+      sarea->depth_handle = 0;
+   }
+#ifdef NOTTM
+   if (sarea->tex_handle) {
+      drmRmMap(pI830->drmSubFD, sarea->tex_handle);
+      sarea->tex_handle = 0;
+   }
+#endif
+}
+
+#ifdef NOTTM
+static void
+I830InitTextureHeap(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   /* Start up the simple memory manager for agp space */
+   drmI830MemInitHeap drmHeap;
+   drmHeap.region = I830_MEM_REGION_AGP;
+   drmHeap.start  = 0;
+   drmHeap.size   = sarea->tex_size;
+      
+   if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT_HEAP,
+			  &drmHeap, sizeof(drmHeap))) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "[drm] Failed to initialized agp heap manager\n");
+   } else {
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "[drm] Initialized kernel agp heap manager, %d\n",
+		    sarea->tex_size);
+
+      I830SetParam(pScrn, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, 
+		      sarea->log_tex_granularity);
+   }
+}
+#endif
+
+Bool
+I830DRIDoMappings(ScreenPtr pScreen)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+   DRIInfoPtr pDRIInfo = pI830->pDRIInfo;
+   I830DRIPtr pI830DRI = pDRIInfo->devPrivate;
+   drmI830Sarea *sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
+
+   DPRINTF(PFX, "I830DRIDoMappings\n");
+   pI830DRI->regsSize = I830_REG_SIZE;
+   if (drmAddMap(pI830->drmSubFD, (drm_handle_t)pI830->MMIOAddr,
+		 pI830DRI->regsSize, DRM_REGISTERS, 0,
+		 (drmAddress) &pI830DRI->regs) < 0) {
+      xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n");
+      DRICloseScreen(pScreen);
+      return FALSE;
+   }
+   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
+	      (int)pI830DRI->regs);
 
    if (drmAddMap(pI830->drmSubFD,
 		 (drm_handle_t)pI830->LpRing->mem.Start + pI830->LinearAddr,
 		 pI830->LpRing->mem.Size, DRM_AGP, 0,
-		 &pI830->ring_map) < 0) {
+		 (drmAddress) &pI830->ring_map) < 0) {
       xf86DrvMsg(pScreen->myNum, X_ERROR,
 		 "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
       DRICloseScreen(pScreen);
       return FALSE;
    }
    xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08x\n",
-	      pI830->ring_map);
-#ifdef NOTTM
-   pI830DRI->textureSize = pI830->TexMem.Size;
-   pI830DRI->logTextureGranularity = pI830->TexGranularity;
+	      (int)pI830->ring_map);
 
-   if (drmAddMap(pI830->drmSubFD,
-		 (drm_handle_t)pI830->TexMem.Start + pI830->LinearAddr,
-		 pI830->TexMem.Size, DRM_AGP, 0,
-		 &pI830DRI->textures) < 0) {
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
-		 "[drm] drmAddMap(textures) failed. Disabling DRI\n");
+   if (!I830InitDma(pScrn)) {
       DRICloseScreen(pScreen);
       return FALSE;
    }
+#ifdef NOTTM
    xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] textures = 0x%08x\n",
 	      pI830DRI->textures);
 #endif
 
-   if (!I830InitDma(pScrn)) {
+   /* init to zero to be safe */
+   sarea->front_handle = 0;
+   sarea->back_handle = 0;
+   sarea->depth_handle = 0;
+#ifdef NOTTM
+   sarea->tex_handle = 0;
+#endif
+
+   /* Assign pScreen */
+   pScrn->pScreen = pScreen;
+
+   /* Need to initialize pScreen now to let RandR know. */
+   pScrn->pScreen->width = pScrn->virtualX;
+   pScrn->pScreen->height = pScrn->virtualY;
+
+   /* this will map the screen regions */
+   if (!I830UpdateDRIBuffers(pScrn, sarea)) {
+      /* screen mappings probably failed */
+      xf86DrvMsg(pScreen->myNum, X_ERROR,
+		 "[drm] drmAddMap(screen mappings) failed. Disabling DRI\n");
       DRICloseScreen(pScreen);
       return FALSE;
    }
@@ -714,29 +829,6 @@ I830DRIDoMappings(ScreenPtr pScreen)
 		    pI830DRI->irq);
    }
 
-   /* Start up the simple memory manager for agp space */
-   {
-      drmI830MemInitHeap drmHeap;
-      drmHeap.region = I830_MEM_REGION_AGP;
-      drmHeap.start  = 0;
-      drmHeap.size   = pI830DRI->textureSize;
-      
-      if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT_HEAP,
-			  &drmHeap, sizeof(drmHeap))) {
-	 xf86DrvMsg(pScreen->myNum, X_ERROR,
-		    "[drm] Failed to initialized agp heap manager\n");
-      } else {
-	 xf86DrvMsg(pScreen->myNum, X_INFO,
-		    "[drm] Initialized kernel agp heap manager, %d\n",
-		    pI830DRI->textureSize);
-
-	 I830SetParam(pScrn, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, 
-		      pI830->TexGranularity);
-      }
-   }
-
-
-
    pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate;
    pI830DRI->deviceID = pI830->PciInfo->chipType;
    pI830DRI->width = pScrn->virtualX;
@@ -857,23 +949,22 @@ I830DestroyContext(ScreenPtr pScreen, dr
 Bool
 I830DRIFinishScreenInit(ScreenPtr pScreen)
 {
-   drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
    ScrnInfoPtr        pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
 
    DPRINTF(PFX, "I830DRIFinishScreenInit\n");
 
-   memset(sPriv, 0, sizeof(sPriv));
-
    /* Have shadow run only while there is 3d active.
     */
+#if 0
    if (pI830->allowPageFlip && pI830->drmMinor >= 1) {
-      shadowSetup(pScreen);
       shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0);
    }
    else
+#endif
       pI830->allowPageFlip = 0;
 
+
    return DRIFinishScreenInit(pScreen);
 }
 
@@ -968,8 +1059,13 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
    DDXPointPtr pptTmp, pptNew2;
    int xdir, ydir;
 
+#if 0
    int screenwidth = pScrn->virtualX;
    int screenheight = pScrn->virtualY;
+#else
+   int screenwidth = pScreen->width;
+   int screenheight = pScreen->height;
+#endif
 
    BoxPtr pbox = REGION_RECTS(prgnSrc);
    int nbox = REGION_NUM_RECTS(prgnSrc);
@@ -1109,28 +1205,6 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
    pI830->AccelInfoRec->NeedToSync = TRUE;
 }
 
-/* Initialize the first context */
-void
-I830EmitInvarientState(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   CARD32 ctx_addr;
-
-
-   ctx_addr = pI830->ContextMem.Start;
-   /* Align to a 2k boundry */
-   ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;
-
-   {
-      BEGIN_LP_RING(2);
-      OUT_RING(MI_SET_CONTEXT);
-      OUT_RING(ctx_addr |
-	       CTXT_NO_RESTORE |
-	       CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE);
-      ADVANCE_LP_RING();
-   }
-}
-
 /* Use callbacks from dri.c to support pageflipping mode for a single
  * 3d context without need for any specific full-screen extension.
  *
@@ -1154,7 +1228,7 @@ I830EmitInvarientState(ScrnInfoPtr pScrn
  * might be faster, but seems like a lot more work...
  */
 
-
+#if 0
 /* This should be done *before* XAA syncs,
  * Otherwise will have to sync again???
  */
@@ -1163,7 +1237,7 @@ I830DRIShadowUpdate (ScreenPtr pScreen, 
 {
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
-   RegionPtr damage = &pBuf->damage;
+   RegionPtr damage = (RegionPtr) shadowDamage(pBuf);
    int i, num =  REGION_NUM_RECTS(damage);
    BoxPtr pbox = REGION_RECTS(damage);
    drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
@@ -1199,7 +1273,7 @@ I830DRIShadowUpdate (ScreenPtr pScreen, 
       ADVANCE_LP_RING();
    }
 }
-
+#endif
 
 static void
 I830EnablePageFlip(ScreenPtr pScreen)
@@ -1264,7 +1338,6 @@ I830DRITransitionMultiToSingle3d(ScreenP
    I830EnablePageFlip(pScreen);
 }
 
-
 static void
 I830DRITransitionTo3d(ScreenPtr pScreen)
 {
@@ -1297,3 +1370,136 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
 }
 
 
+/**
+ * Update the SAREA fields with the most recent values.
+ * This gets called after the screen orientation/rotation changes.
+ */
+Bool
+I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   ScreenPtr pScreen = pScrn->pScreen;
+   Bool success;
+
+   I830DRIUnmapScreenRegions(pScrn, sarea);
+
+   if (pI830->rotation == RR_Rotate_0) {
+      sarea->front_offset = pI830->FrontBuffer.Start;
+      /* Don't use FrontBuffer.Size here as it includes the pixmap cache area
+       * Instead, calculate the entire framebuffer.
+       */
+      sarea->front_size = pI830->displayWidth * pScrn->virtualY * pI830->cpp;
+   } else {
+      /* Need to deal with rotated2 once we have dual head DRI */
+      sarea->front_offset = pI830->RotatedMem.Start;
+      sarea->front_size = pI830->RotatedMem.Size;
+   }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+              "[drm] init sarea width,height = %d x %d (pitch %d)\n",
+              pScreen->width, pScreen->height,pScrn->displayWidth);
+
+   sarea->width = pScreen->width;
+   sarea->height = pScreen->height;
+   sarea->back_offset = pI830->BackBuffer.Start;
+   sarea->back_size = pI830->BackBuffer.Size;
+   sarea->depth_offset = pI830->DepthBuffer.Start;
+   sarea->depth_size = pI830->DepthBuffer.Size;
+#ifdef NOTTM
+   sarea->tex_offset = pI830->TexMem.Start;
+   sarea->tex_size = pI830->TexMem.Size;
+#endif
+   sarea->log_tex_granularity = pI830->TexGranularity;
+   sarea->pitch = pScrn->displayWidth;
+   sarea->virtualX = pScrn->virtualX;
+   sarea->virtualY = pScrn->virtualY;
+
+   switch (pI830->rotation) {
+      case RR_Rotate_0:
+         sarea->rotation = 0;
+         break;
+      case RR_Rotate_90:
+         sarea->rotation = 90;
+         break;
+      case RR_Rotate_180:
+         sarea->rotation = 180;
+         break;
+      case RR_Rotate_270:
+         sarea->rotation = 270;
+         break;
+      default:
+         sarea->rotation = 0;
+   }
+   if (pI830->rotation == RR_Rotate_0) {
+      sarea->rotated_offset = -1;
+      sarea->rotated_size = 0;
+   }
+   else {
+      sarea->rotated_offset = pI830->FrontBuffer.Start;
+      sarea->rotated_size = pI830->FrontBuffer.Size;
+   }
+
+   /* This is the original pitch */
+   sarea->rotated_pitch = pI830->displayWidth;
+
+   success = I830DRIMapScreenRegions(pScrn, sarea);
+
+#ifdef NOTTM
+   I830InitTextureHeap(pScrn, sarea);
+#endif
+
+   return success;
+}
+
+Bool
+I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    drmI830VBlankPipe pipe;
+
+    if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
+	if (on) {
+	    if (pI830->planeEnabled[1])
+		pipe.pipe = DRM_I830_VBLANK_PIPE_B;
+	    else
+		pipe.pipe = DRM_I830_VBLANK_PIPE_A;
+	} else {
+	    pipe.pipe = 0;
+	}
+	if (drmCommandWrite(pI830->drmSubFD, DRM_I830_SET_VBLANK_PIPE,
+			    &pipe, sizeof (pipe))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Vblank Pipe Setup Failed\n");
+	    return FALSE;
+	}
+    }
+
+    return TRUE;
+}
+
+Bool
+I830DRILock(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   if (pI830->directRenderingEnabled && !pI830->LockHeld) {
+      DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
+      pI830->LockHeld = 1;
+      I830RefreshRing(pScrn);
+      return TRUE;
+   }
+   else
+      return FALSE;
+}
+
+
+
+void
+I830DRIUnlock(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   if (pI830->directRenderingEnabled && pI830->LockHeld) {
+      DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
+      pI830->LockHeld = 0;
+   }
+}
diff --git a/src/i830_dri.h b/src/i830_dri.h
index 5ac99e5..31232b8 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -9,7 +9,7 @@
 #define I830_MAX_DRAWABLES 256
 
 #define I830_MAJOR_VERSION 1
-#define I830_MINOR_VERSION 4
+#define I830_MINOR_VERSION 6
 #define I830_PATCHLEVEL 1
 
 #define I830_REG_SIZE 0x80000
@@ -24,6 +24,9 @@ typedef struct _I830DRIRec {
    drmSize depthbufferSize;
    drm_handle_t depthbuffer;
 
+   drmSize rotatedSize;
+   drm_handle_t rotatedbuffer;
+
    drm_handle_t textures;
    int textureSize;
 
@@ -46,6 +49,9 @@ typedef struct _I830DRIRec {
    int depthOffset;
    int depthPitch;
 
+   int rotatedOffset;
+   int rotatedPitch;
+
    int logTextureGranularity;
    int textureOffset;
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 49a5f05..a9efe99 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -144,8 +144,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
  *        - Fix Xvideo with high-res LFP's
  *        - Add ARGB HW cursor support
  *
- *    30/2005 Alan Hourihane
+ *    05/2005 Alan Hourihane
  *        - Add Intel(R) 945G support.
+ *
+ *    09/2005 Alan Hourihane
+ *        - Add Intel(R) 945GM support.
+ *
  */
 
 #ifdef HAVE_CONFIG_H
@@ -156,8 +160,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define PRINT_MODE_INFO 0
 #endif
 
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
 #include "xf86RAC.h"
@@ -168,14 +176,14 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "mipointer.h"
 #include "micmap.h"
 #include "shadowfb.h"
-
+#include <X11/extensions/randr.h>
 #include "fb.h"
 #include "miscstruct.h"
 #include "xf86xv.h"
 #include <X11/extensions/Xv.h>
 #include "vbe.h"
 #include "vbeModes.h"
-
+#include "shadow.h"
 #include "i830.h"
 
 #ifdef XF86DRI
@@ -196,6 +204,7 @@ static SymTabRec I830BIOSChipsets[] = {
    {PCI_CHIP_E7221_G,		"E7221 (i915)"},
    {PCI_CHIP_I915_GM,		"915GM"},
    {PCI_CHIP_I945_G,		"945G"},
+   {PCI_CHIP_I945_GM,		"945GM"},
    {-1,				NULL}
 };
 
@@ -208,6 +217,7 @@ static PciChipsets I830BIOSPciChipsets[]
    {PCI_CHIP_E7221_G,		PCI_CHIP_E7221_G,	RES_SHARED_VGA},
    {PCI_CHIP_I915_GM,		PCI_CHIP_I915_GM,	RES_SHARED_VGA},
    {PCI_CHIP_I945_G,		PCI_CHIP_I945_G,	RES_SHARED_VGA},
+   {PCI_CHIP_I945_GM,		PCI_CHIP_I945_GM,	RES_SHARED_VGA},
    {-1,				-1,			RES_UNDEFINED}
 };
 
@@ -234,8 +244,8 @@ typedef enum {
    OPTION_CLONE_REFRESH,
    OPTION_CHECKDEVICES,
    OPTION_FIXEDPIPE,
-   OPTION_SHADOW_FB,
-   OPTION_ROTATE
+   OPTION_ROTATE,
+   OPTION_LINEARALLOC
 } I830Opts;
 
 static OptionInfoRec I830BIOSOptions[] = {
@@ -255,8 +265,8 @@ static OptionInfoRec I830BIOSOptions[] =
    {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER,	{0},	FALSE},
    {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_FIXEDPIPE,   "FixedPipe",    OPTV_ANYSTR, 	{0},	FALSE},
-   {OPTION_SHADOW_FB,   "ShadowFB",     OPTV_BOOLEAN,   {0},    FALSE},
    {OPTION_ROTATE,      "Rotate",       OPTV_ANYSTR,    {0},    FALSE},
+   {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
 };
 /* *INDENT-ON* */
@@ -271,10 +281,12 @@ static Bool I830VESASetVBEMode(ScrnInfoP
 			       VbeCRTCInfoBlock *block);
 static CARD32 I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg);
 static Bool SetPipeAccess(ScrnInfoPtr pScrn);
-static Bool IsPrimary(ScrnInfoPtr pScrn);
 
 extern int I830EntityIndex;
 
+/* temporary */
+extern void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y);
+
 
 #ifdef I830DEBUG
 void
@@ -354,10 +366,12 @@ I830BIOSFreeRec(ScrnInfoPtr pScrn)
       } while (mode && mode != pScrn->modes);
    }
 
-   if (pI830->vbeInfo)
-      VBEFreeVBEInfo(pI830->vbeInfo);
-   if (pI830->pVbe)
-      vbeFree(pI830->pVbe);
+   if (I830IsPrimary(pScrn)) {
+      if (pI830->vbeInfo)
+         VBEFreeVBEInfo(pI830->vbeInfo);
+      if (pI830->pVbe)
+         vbeFree(pI830->pVbe);
+   }
 
    pVesa = pI830->vesa;
    if (pVesa->monitor)
@@ -434,6 +448,94 @@ GetToggleList(ScrnInfoPtr pScrn, int tog
 }
 
 static int
+GetNextDisplayDeviceList(ScrnInfoPtr pScrn, int toggle)
+{
+   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+   int devices = 0;
+   int pipe = 0;
+   int i;
+
+   DPRINTF(PFX, "GetNextDisplayDeviceList\n");
+
+   pVbe->pInt10->num = 0x10;
+   pVbe->pInt10->ax = 0x5f64;
+   pVbe->pInt10->bx = 0xA00;
+   pVbe->pInt10->bx |= toggle;
+   pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
+   pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
+
+   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+   if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
+      return 0;
+
+   for (i=0; i<(pVbe->pInt10->cx & 0xff); i++) {
+      CARD32 VODA = (CARD32)((CARD32*)pVbe->memory)[i];
+
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Next ACPI _DGS [%d] 0x%lx\n",
+		 i, (unsigned long) VODA);
+
+      /* Check if it's a custom Video Output Device Attribute */
+      if (!(VODA & 0x80000000)) 
+         continue;
+
+      pipe = (VODA & 0x000000F0) >> 4;
+
+      if (pipe != 0 && pipe != 1) {
+         pipe = 0;
+#if 0
+         ErrorF("PIPE %d\n",pipe);
+#endif
+      }
+
+      switch ((VODA & 0x00000F00) >> 8) {
+      case 0x0:
+      case 0x1: /* CRT */
+         devices |= PIPE_CRT << (pipe == 1 ? 8 : 0);
+         break;
+      case 0x2: /* TV/HDTV */
+         devices |= PIPE_TV << (pipe == 1 ? 8 : 0);
+         break;
+      case 0x3: /* DFP */
+         devices |= PIPE_DFP << (pipe == 1 ? 8 : 0);
+         break;
+      case 0x4: /* LFP */
+         devices |= PIPE_LFP << (pipe == 1 ? 8 : 0);
+         break;
+      }
+   }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ACPI Toggle devices 0x%x\n", devices);
+
+   return devices;
+}
+
+static int
+GetAttachableDisplayDeviceList(ScrnInfoPtr pScrn)
+{
+   vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe;
+   int i;
+
+   DPRINTF(PFX, "GetAttachableDisplayDeviceList\n");
+
+   pVbe->pInt10->num = 0x10;
+   pVbe->pInt10->ax = 0x5f64;
+   pVbe->pInt10->bx = 0x900;
+   pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base);
+   pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base);
+
+   xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn);
+   if (!Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax))
+      return 0;
+
+   for (i=0; i<(pVbe->pInt10->cx & 0xff); i++)
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+		"Attachable device 0x%lx.\n", 
+		   (unsigned long) ((CARD32*)pVbe->memory)[i]);
+
+   return pVbe->pInt10->cx & 0xffff;
+}
+
+static int
 BitToRefresh(int bits)
 {
    int i;
@@ -624,6 +726,7 @@ SetRefreshRate(ScrnInfoPtr pScrn, int mo
       return 0;
 }
 
+#if 0
 static Bool
 SetPowerStatus(ScrnInfoPtr pScrn, int mode)
 {
@@ -640,6 +743,7 @@ SetPowerStatus(ScrnInfoPtr pScrn, int mo
   
    return FALSE;
 }
+#endif
 
 static Bool
 GetModeSupport(ScrnInfoPtr pScrn, int modePipeA, int modePipeB,
@@ -677,6 +781,7 @@ GetModeSupport(ScrnInfoPtr pScrn, int mo
       return FALSE;
 }
 
+#if 0
 static int
 GetLFPCompMode(ScrnInfoPtr pScrn)
 {
@@ -695,7 +800,6 @@ GetLFPCompMode(ScrnInfoPtr pScrn)
       return -1;
 }
 
-#if 0
 static Bool
 SetLFPCompMode(ScrnInfoPtr pScrn, int compMode)
 {
@@ -849,7 +953,25 @@ I830Set640x480(ScrnInfoPtr pScrn)
 	 break;
    }
    m |= (1 << 15) | (1 << 14);
-   return VBESetVBEMode(pI830->pVbe, m, NULL);
+   if (VBESetVBEMode(pI830->pVbe, m, NULL))
+	   return TRUE;
+
+   /* if the first failed, let's try the next - usually 800x600 */
+   m = 0x32;
+   switch (pScrn->depth) {
+   case 15:
+   case 16:
+	 m = 0x42;
+	 break;
+   case 24:
+	 m = 0x52;
+	 break;
+   }
+   m |= (1 << 15) | (1 << 14);
+   if (VBESetVBEMode(pI830->pVbe, m, NULL))
+	   return TRUE;
+
+   return FALSE;
 }
 
 /* This is needed for SetDisplayDevices to work correctly on I915G.
@@ -882,7 +1004,7 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int
       setmode = FALSE;
    if (pI830->closing)
       setmode = FALSE;
-	 
+
    if (setmode) {
       VBEGetVBEMode(pVbe, &getmode1);
       I830Set640x480(pScrn);
@@ -1323,7 +1445,7 @@ I830DetectMemory(ScrnInfoPtr pScrn)
     * The GTT varying according the the FbMapSize and the popup is 4KB */
    range = (pI830->FbMapSize / (1024*1024)) + 4;
 
-   if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+   if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
       switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
       case I855_GMCH_GMS_STOLEN_1M:
 	 memsize = MB(1) - KB(range);
@@ -1341,11 +1463,11 @@ I830DetectMemory(ScrnInfoPtr pScrn)
 	 memsize = MB(32) - KB(range);
 	 break;
       case I915G_GMCH_GMS_STOLEN_48M:
-	 if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+	 if (IS_I9XX(pI830))
 	    memsize = MB(48) - KB(range);
 	 break;
       case I915G_GMCH_GMS_STOLEN_64M:
-	 if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+	 if (IS_I9XX(pI830))
 	    memsize = MB(64) - KB(range);
 	 break;
       }
@@ -1414,7 +1536,7 @@ I830MapMem(ScrnInfoPtr pScrn)
    if (!pI830->FbBase)
       return FALSE;
 
-   if (IsPrimary(pScrn))
+   if (I830IsPrimary(pScrn))
    pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem.Start;
 
    return TRUE;
@@ -1513,6 +1635,9 @@ SaveBIOSMemSize(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "SaveBIOSMemSize\n");
 
+   if (!I830IsPrimary(pScrn))
+      return FALSE;
+
    pI830->useSWF1 = FALSE;
 
 #if HAVE_GET_PUT_BIOSMEMSIZE
@@ -1572,6 +1697,9 @@ TweakMemorySize(ScrnInfoPtr pScrn, CARD3
     
     PCITAG tag =pciTag(0,0,0);
 
+    if (!I830IsPrimary(pScrn))
+       return 0;
+
     if(!pI830->PciInfo 
        || !(IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830)))
 	return 0;
@@ -1618,10 +1746,16 @@ TweakMemorySize(ScrnInfoPtr pScrn, CARD3
 
     if (preinit) {
 	/* reinitialize VBE for new size */
-	VBEFreeVBEInfo(pI830->vbeInfo);
-	vbeFree(pI830->pVbe);
-	pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
-	pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+	if (I830IsPrimary(pScrn)) {
+	   VBEFreeVBEInfo(pI830->vbeInfo);
+	   vbeFree(pI830->pVbe);
+	   pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
+	   pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+	} else {
+           I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+           pI830->pVbe = pI8301->pVbe;
+           pI830->vbeInfo = pI8301->vbeInfo;
+	}
 	
 	/* verify that change was successful */
 	if (pI830->vbeInfo->TotalMemory != (newsize >> 16)){
@@ -1648,8 +1782,11 @@ RestoreBIOSMemSize(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "RestoreBIOSMemSize\n");
 
+   if (!I830IsPrimary(pScrn))
+      return;
+
    if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize,FALSE))
-       return;
+      return;
 
    if (!pI830->overrideBIOSMemSize)
       return;
@@ -1712,6 +1849,8 @@ SetBIOSMemSize(ScrnInfoPtr pScrn, int ne
    }
 }
 
+static CARD32 val8[256];
+
 static void
 I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
 		LOCO * colors, VisualPtr pVisual)
@@ -1786,6 +1925,19 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
       }
       break;
    default:
+#if 1
+      /* Dual head 8bpp modes seem to squish the primary's cmap - reload */
+      if (I830IsPrimary(pScrn) && xf86IsEntityShared(pScrn->entityList[0]) &&
+          pScrn->depth == 8) {
+         for(i = 0; i < numColors; i++) {
+	    index = indices[i];
+	    r = colors[index].red;
+	    g = colors[index].green;
+	    b = colors[index].blue;
+	    val8[index] = (r << 16) | (g << 8) | b;
+        }
+      }
+#endif
       for(i = 0; i < numColors; i++) {
 	 index = indices[i];
 	 r = colors[index].red;
@@ -1793,6 +1945,16 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
 	 b = colors[index].blue;
 	 val = (r << 16) | (g << 8) | b;
 	 OUTREG(palreg + index * 4, val);
+#if 1
+         /* Dual head 8bpp modes seem to squish the primary's cmap - reload */
+         if (!I830IsPrimary(pScrn) && xf86IsEntityShared(pScrn->entityList[0]) &&
+             pScrn->depth == 8) {
+  	    if (palreg == PALETTE_A)
+	       OUTREG(PALETTE_B + index * 4, val8[index]);
+	    else
+	       OUTREG(PALETTE_A + index * 4, val8[index]);
+         }
+#endif
       }
       break;
    }
@@ -1868,30 +2030,32 @@ PreInitCleanup(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
-   if (IsPrimary(pScrn))
+   if (I830IsPrimary(pScrn)) {
+      SetPipeAccess(pScrn);
+
       pI830->entityPrivate->pScrn_1 = NULL;
-   if (IsPrimary(pScrn) && pI830->LpRing) {
-      xfree(pI830->LpRing);
+      if (pI830->LpRing)
+         xfree(pI830->LpRing);
       pI830->LpRing = NULL;
-   }
-   if (IsPrimary(pScrn) && pI830->CursorMem) {
-      xfree(pI830->CursorMem);
+      if (pI830->CursorMem)
+         xfree(pI830->CursorMem);
       pI830->CursorMem = NULL;
-   }
-   if (IsPrimary(pScrn) && pI830->CursorMemARGB) {
-      xfree(pI830->CursorMemARGB);
+      if (pI830->CursorMemARGB) 
+         xfree(pI830->CursorMemARGB);
       pI830->CursorMemARGB = NULL;
-   }
-   if (IsPrimary(pScrn) && pI830->OverlayMem) {
-      xfree(pI830->OverlayMem);
+      if (pI830->OverlayMem)
+         xfree(pI830->OverlayMem);
       pI830->OverlayMem = NULL;
-   }
-   if (IsPrimary(pScrn) && pI830->overlayOn) {
-      xfree(pI830->overlayOn);
+      if (pI830->overlayOn)
+         xfree(pI830->overlayOn);
       pI830->overlayOn = NULL;
+      if (pI830->used3D)
+         xfree(pI830->used3D);
+      pI830->used3D = NULL;
+   } else {
+      if (pI830->entityPrivate)
+         pI830->entityPrivate->pScrn_2 = NULL;
    }
-   if (!IsPrimary(pScrn) && pI830->entityPrivate)
-      pI830->entityPrivate->pScrn_2 = NULL;
    RestoreBIOSMemSize(pScrn);
    if (pI830->swfSaved) {
       OUTREG(SWF0, pI830->saveSWF0);
@@ -1902,8 +2066,8 @@ PreInitCleanup(ScrnInfoPtr pScrn)
    I830BIOSFreeRec(pScrn);
 }
 
-static Bool
-IsPrimary(ScrnInfoPtr pScrn)
+Bool
+I830IsPrimary(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
@@ -1920,7 +2084,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 {
    vgaHWPtr hwp;
    I830Ptr pI830;
-   MessageType from;
+   MessageType from = X_PROBED;
    rgb defaultWeight = { 0, 0, 0 };
    EntityInfoPtr pEnt;
    I830EntPtr pI830Ent = NULL;					
@@ -1974,6 +2138,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    pI830->SaveGeneration = -1;
    pI830->pEnt = pEnt;
 
+   pI830->displayWidth = 640; /* default it */
+
    if (pI830->pEnt->location.type != BUS_PCI)
       return FALSE;
 
@@ -1994,6 +2160,30 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       return FALSE;
    }
 
+   if (xf86IsEntityShared(pScrn->entityList[0])) {
+      if (xf86IsPrimInitDone(pScrn->entityList[0])) {
+	 pI830->init = 1;
+
+         if (!pI830Ent->pScrn_1) {
+            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ 		 "Failed to setup second head due to primary head failure.\n");
+	    return FALSE;
+         }
+      } else {
+         xf86SetPrimInitDone(pScrn->entityList[0]);
+	 pI830->init = 0;
+      }
+   }
+
+   if (xf86IsEntityShared(pScrn->entityList[0])) {
+      if (!I830IsPrimary(pScrn)) {
+         pI830Ent->pScrn_2 = pScrn;
+      } else {
+         pI830Ent->pScrn_1 = pScrn;
+         pI830Ent->pScrn_2 = NULL;
+      }
+   }
+
    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
    pScrn->monitor = pScrn->confScreen->monitor;
    pScrn->progClock = TRUE;
@@ -2039,9 +2229,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    I830SetPIOAccess(pI830);
 
    /* Initialize VBE record */
-   if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VBE initialization failed.\n");
-      return FALSE;
+   if (I830IsPrimary(pScrn)) {
+      if ((pI830->pVbe = VBEInit(NULL, pI830->pEnt->index)) == NULL) {
+         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VBE initialization failed.\n");
+         return FALSE;
+      }
+   } else {
+      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pI830->pVbe = pI8301->pVbe;
    }
 
    switch (pI830->PciInfo->chipType) {
@@ -2090,6 +2285,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    case PCI_CHIP_I945_G:
       chipname = "945G";
       break;
+   case PCI_CHIP_I945_GM:
+      chipname = "945GM";
+      break;
    default:
       chipname = "unknown chipset";
       break;
@@ -2097,7 +2295,12 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	      "Integrated Graphics Chipset: Intel(R) %s\n", chipname);
 
-   pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+   if (I830IsPrimary(pScrn)) {
+      pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+   } else {
+      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pI830->vbeInfo = pI8301->vbeInfo;
+   }
 
    /* Set the Chipset and ChipRev, allowing config file entries to override. */
    if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) {
@@ -2109,6 +2312,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       from = X_CONFIG;
       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
 		 pI830->pEnt->device->chipID);
+      pI830->PciInfo->chipType = pI830->pEnt->device->chipID;
    } else {
       from = X_PROBED;
       pScrn->chipset = (char *)xf86TokenToString(I830BIOSChipsets,
@@ -2127,8 +2331,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       pI830->LinearAddr = pI830->pEnt->device->MemBase;
       from = X_CONFIG;
    } else {
-      if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
-	 pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xF0000000;
+      if (IS_I9XX(pI830)) {
+	 pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xFF000000;
 	 from = X_PROBED;
       } else if (pI830->PciInfo->memBase[1] != 0) {
 	 /* XXX Check mask. */
@@ -2149,7 +2353,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       pI830->MMIOAddr = pI830->pEnt->device->IOBase;
       from = X_CONFIG;
    } else {
-      if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+      if (IS_I9XX(pI830)) {
 	 pI830->MMIOAddr = pI830->PciInfo->memBase[0] & 0xFFF80000;
 	 from = X_PROBED;
       } else if (pI830->PciInfo->memBase[1]) {
@@ -2194,7 +2398,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 	 pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */
       }
    } else {
-      if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+      if (IS_I9XX(pI830)) {
 	 if (pI830->PciInfo->memBase[2] & 0x08000000)
 	    pI830->FbMapSize = 0x8000000;	/* 128MB aperture */
 	 else
@@ -2207,27 +2411,10 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 	 pI830->FbMapSize = 0x8000000;
    }
 
-
-   if (xf86IsEntityShared(pScrn->entityList[0])) {
-      if (xf86IsPrimInitDone(pScrn->entityList[0])) {
-	 pI830->init = 1;
-
-         if (!pI830Ent->pScrn_1) {
-            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		 "Failed to setup second head due to primary head failure.\n");
-	    return FALSE;
-         }
-
-      } else {
-         xf86SetPrimInitDone(pScrn->entityList[0]);
-	 pI830->init = 0;
-      }
-   }
-
    if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
       pI830->availablePipes = 1;
    else
-   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830))
+   if (IS_MOBILE(pI830) || IS_I9XX(pI830))
       pI830->availablePipes = 2;
    else
       pI830->availablePipes = 1;
@@ -2251,7 +2438,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    }
 
    /* Find the maximum amount of agpgart memory available. */
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       mem = I830CheckAvailableMemory(pScrn);
       pI830->StolenOnly = FALSE;
    } else {
@@ -2302,9 +2489,16 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    }
 #endif
 
+   pI830->LinearAlloc = 0;
+   if (xf86GetOptValInteger(pI830->Options, OPTION_LINEARALLOC,
+			    &(pI830->LinearAlloc))) {
+      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %dKbytes of memory\n",
+		 pI830->LinearAlloc);
+   }
+
    pI830->fixedPipe = -1;
    if ((s = xf86GetOptValString(pI830->Options, OPTION_FIXEDPIPE)) &&
-      IsPrimary(pScrn)) {
+      I830IsPrimary(pScrn)) {
 
       if (strstr(s, "A") || strstr(s, "a") || strstr(s, "0"))
          pI830->fixedPipe = 0;
@@ -2317,7 +2511,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    pI830->specifiedMonitor = FALSE;
 
    if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) &&
-      IsPrimary(pScrn)) {
+      I830IsPrimary(pScrn)) {
       char *Mon1;
       char *Mon2;
       char *sub;
@@ -2429,7 +2623,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       return FALSE;
    }
 
-   if ((pI830->entityPrivate && IsPrimary(pScrn)) || pI830->Clone) {
+   if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone) {
       if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout "
 	 		"defined for use in a DualHead or Clone setup.\n");
@@ -2443,37 +2637,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
          PreInitCleanup(pScrn);
          return FALSE;
       }
-    }
-
-    xf86GetOptValBool(pI830->Options, OPTION_SHADOW_FB, &pI830->shadowFB);
-    if (pI830->shadowFB) {
-	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: shadow FB enabled\n");
-    }
-
-    if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
-	if(!xf86NameCmp(s, "CW")) {
-	    /* accel is disabled below for shadowFB */
-	    pI830->shadowFB = TRUE;
-	    pI830->rotate = 1;
-	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
-		"Rotating screen clockwise - acceleration disabled\n");
-	} else if(!xf86NameCmp(s, "CCW")) {
-	    pI830->shadowFB = TRUE;
-	    pI830->rotate = -1;
-	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
-		"counter clockwise - acceleration disabled\n");
-	} else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
-		"value for Option \"Rotate\"\n", s);
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		"Valid options are \"CW\" or \"CCW\"\n");
-	}
-    }
+   }
 
-   if (pI830->shadowFB && !pI830->noAccel) {
-       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-       	   "HW acceleration not supported with \"shadowFB\".\n");
-       pI830->noAccel = TRUE;
+   pI830->rotation = RR_Rotate_0;
+   if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
+      pI830->InitialRotation = 0;
+      if(!xf86NameCmp(s, "CW") || !xf86NameCmp(s, "270"))
+         pI830->InitialRotation = 270;
+      if(!xf86NameCmp(s, "CCW") || !xf86NameCmp(s, "90"))
+         pI830->InitialRotation = 90;
+      if(!xf86NameCmp(s, "180"))
+         pI830->InitialRotation = 180;
    }
 
    /*
@@ -2486,7 +2660,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
          pI830->checkDevices = FALSE;
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitoring connected displays disabled\n");
       } else
-      if (pI830->entityPrivate && !IsPrimary(pScrn) &&
+      if (pI830->entityPrivate && !I830IsPrimary(pScrn) &&
           !I830PTR(pI830->entityPrivate->pScrn_1)->checkDevices) {
          /* If checklid is off, on the primary head, then 
           * turn it off on the secondary*/
@@ -2525,8 +2699,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 	 pScrn->videoRam = I830_DEFAULT_VIDEOMEM_2D;
 
       if (xf86IsEntityShared(pScrn->entityList[0])) {
-         if (IsPrimary(pScrn))
-            pScrn->videoRam *= 2;
+         if (I830IsPrimary(pScrn))
+            pScrn->videoRam += I830_DEFAULT_VIDEOMEM_2D;
       else
             pScrn->videoRam = I830_MAXIMUM_VBIOS_MEM;
       } 
@@ -2538,6 +2712,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       pScrn->videoRam = pI830->pEnt->device->videoRam;
    }
 
+   /* Make sure it's on a page boundary */
+   if (pScrn->videoRam & (GTT_PAGE_SIZE - 1)) {
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "VideoRAM reduced to %d kByte "
+		    "(page aligned - was %d)\n", pScrn->videoRam & ~(GTT_PAGE_SIZE - 1), pScrn->videoRam);
+      pScrn->videoRam &= ~(GTT_PAGE_SIZE - 1);
+   }
+
    DPRINTF(PFX,
 	   "Available memory: %dk\n"
 	   "Requested memory: %dk\n", mem, pScrn->videoRam);
@@ -2597,10 +2779,16 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 	    pI830->overrideBIOSMemSize = TRUE;
 	    SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
 
-	    VBEFreeVBEInfo(pI830->vbeInfo);
-	    vbeFree(pI830->pVbe);
-	    pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
-	    pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+	    if (I830IsPrimary(pScrn)) {
+	       VBEFreeVBEInfo(pI830->vbeInfo);
+	       vbeFree(pI830->pVbe);
+	       pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
+	       pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+	    } else {
+               I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+	       pI830->pVbe = pI8301->pVbe;
+	       pI830->vbeInfo = pI8301->vbeInfo;
+	    }
 
 	    pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64);
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -2698,21 +2886,15 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS Build: %d\n",pI830->bios_version);
 
-   /* Great..
-    * Intel changed the BIOS version codes and started at 1200.
-    * We know that bios codes for 830M started around 2400.
-    * So we test those conditions to make this judgement. Ugh.
-    */
-   if (pI830->availablePipes == 2 && pI830->bios_version < 2000)
+   if (IS_I9XX(pI830))
       pI830->newPipeSwitch = TRUE;
-   else if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) 
+   else
+   if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) {
       /* BIOS build 3062 changed the pipe switching functionality */
       pI830->newPipeSwitch = TRUE;
-   else
-      pI830->newPipeSwitch = FALSE;
-
-   if (pI830->newPipeSwitch)
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using new Pipe switch code\n");
+   } else
+      pI830->newPipeSwitch = FALSE;
 
    pI830->devicePresence = FALSE;
    from = X_DEFAULT;
@@ -2727,7 +2909,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
     * or, at least it's meant to..... alas it doesn't seem to always work.
     */
    if (pI830->devicePresence) {
-      int req, att, enc;
+      int req=0, att=0, enc=0;
       GetDevicePresence(pScrn, &req, &att, &enc);
       for (i = 0; i < NumDisplayTypes; i++) {
          xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -2741,7 +2923,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    /* Save old configuration of detected devices */
    pI830->savedDevices = GetDisplayDevices(pScrn);
 
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       pI830->pipe = pI830->origPipe = GetBIOSPipe(pScrn);
 
       /* Override */
@@ -2783,7 +2965,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 	     "Primary Pipe has been switched from original pipe (%s to %s)\n",
              pI830->origPipe ? "B" : "A", pI830->pipe ? "B" : "A");
    } else {
-      I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
+      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
       pI830->operatingDevices = pI8301->operatingDevices;
       pI830->pipe = !pI8301->pipe;
       pI830->MonType1 = pI8301->MonType1;
@@ -2815,7 +2997,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
       return FALSE;
    }
 
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
  		 "Failed to switch to monitor configuration (0x%x)\n",
@@ -2832,18 +3014,13 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    PrintDisplayDeviceInfo(pScrn);
 
    if (xf86IsEntityShared(pScrn->entityList[0])) {
-      if (!IsPrimary(pScrn)) {
-         pI830Ent->pScrn_2 = pScrn;
-
+      if (!I830IsPrimary(pScrn)) {
 	 /* This could be made to work with a little more fiddling */
 	 pI830->directRenderingDisabled = TRUE;
 
          xf86DrvMsg(pScrn->scrnIndex, from, "Secondary head is using Pipe %s\n",
 		pI830->pipe ? "B" : "A");
       } else {
-         pI830Ent->pScrn_1 = pScrn;
-         pI830Ent->pScrn_2 = NULL;
-
          xf86DrvMsg(pScrn->scrnIndex, from, "Primary head is using Pipe %s\n",
 		pI830->pipe ? "B" : "A");
       }
@@ -2853,14 +3030,15 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    }
 
    /* Alloc our pointers for the primary head */
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       pI830->LpRing = xalloc(sizeof(I830RingBuffer));
       pI830->CursorMem = xalloc(sizeof(I830MemRange));
       pI830->CursorMemARGB = xalloc(sizeof(I830MemRange));
       pI830->OverlayMem = xalloc(sizeof(I830MemRange));
       pI830->overlayOn = xalloc(sizeof(Bool));
+      pI830->used3D = xalloc(sizeof(int));
       if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB ||
-          !pI830->OverlayMem || !pI830->overlayOn) {
+          !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Could not allocate primary data structures.\n");
          PreInitCleanup(pScrn);
@@ -2872,7 +3050,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    }
 
    /* Check if the HW cursor needs physical address. */
-   if (IS_MOBILE(pI830) || IS_I915G(pI830) || IS_I945G(pI830))
+   if (IS_MOBILE(pI830) || IS_I9XX(pI830))
       pI830->CursorNeedsPhysical = TRUE;
    else
       pI830->CursorNeedsPhysical = FALSE;
@@ -2884,8 +3062,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
     * XXX If we knew the pre-initialised GTT format for certain, we could
     * probably figure out the physical address even in the StolenOnly case.
     */
-   if (!IsPrimary(pScrn)) {
-   	I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
+   if (!I830IsPrimary(pScrn)) {
+        I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 	if (!pI8301->SWCursor) {
           xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 		 "Using HW Cursor because it's enabled on primary head.\n");
@@ -3110,7 +3288,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
                   Clock = pMon->Clock;
             } 
 
-            if (DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
+            if (Clock != 100000000 && DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
                ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
 		   p->name, pScrn->monitor->id,
 		   Clock/1000.0, DDCclock);
@@ -3157,13 +3335,18 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
     * for it, and if there's also enough to allow tiling to be enabled.
     */
 #if defined(XF86DRI)
-   if (IsPrimary(pScrn) && !pI830->directRenderingDisabled) {
+   if (!I830CheckDRIAvailable(pScrn))
+      pI830->directRenderingDisabled = TRUE;
+
+   if (I830IsPrimary(pScrn) && !pI830->directRenderingDisabled) {
       int savedDisplayWidth = pScrn->displayWidth;
       int memNeeded = 0;
-      /* Good pitches to allow tiling.  Don't care about pitches < 256. */
+      /* Good pitches to allow tiling.  Don't care about pitches < 1024. */
       static const int pitches[] = {
+/*
 	 128 * 2,
 	 128 * 4,
+*/
 	 128 * 8,
 	 128 * 16,
 	 128 * 32,
@@ -3264,8 +3447,11 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 		       "Unexpected dry run allocation failure (2).\n");
 	 }
       }
-   }
+   } else
 #endif
+      pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
+
+   pI830->displayWidth = pScrn->displayWidth;
 
    SetPipeAccess(pScrn);
    I830PrintModes(pScrn);
@@ -3325,19 +3511,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
    xf86SetOperatingState(resVgaIo, pI830->pEnt->index, ResUnusedOpr);
    xf86SetOperatingState(resVgaMem, pI830->pEnt->index, ResDisableOpr);
 
-   if (pI830->shadowFB) {
-       if (!xf86LoadSubModule(pScrn, "shadowfb")) {
-	   I830BIOSFreeRec(pScrn);
-	   vbeFree(pI830->pVbe);
-	   return FALSE;
-       }
-      xf86LoaderReqSymLists(I810shadowFBSymbols, NULL);
+#if 0
+   if (I830IsPrimary(pScrn)) {
+      VBEFreeVBEInfo(pI830->vbeInfo);
+      vbeFree(pI830->pVbe);
    }
-
-   VBEFreeVBEInfo(pI830->vbeInfo);
    pI830->vbeInfo = NULL;
-   vbeFree(pI830->pVbe);
    pI830->pVbe = NULL;
+#endif
 
    /* Use the VBE mode restore workaround by default. */
    pI830->vbeRestoreWorkaround = TRUE;
@@ -3357,15 +3538,30 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int f
 	 xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL);
       }
    }
+#endif
 
-   if (!pI830->directRenderingDisabled) {
-      if (!xf86LoadSubModule(pScrn, "shadow")) {
-	 PreInitCleanup(pScrn);
-	 return FALSE;
+   /* rotation requires the newer libshadow */
+   if (I830IsPrimary(pScrn)) {
+      int errmaj, errmin;
+      pI830->shadowReq.majorversion = 1;
+      pI830->shadowReq.minorversion = 1;
+
+      if (!LoadSubModule(pScrn->module, "shadow", NULL, NULL, NULL,
+			       &pI830->shadowReq, &errmaj, &errmin)) {
+         pI830->shadowReq.minorversion = 0;
+         if (!LoadSubModule(pScrn->module, "shadow", NULL, NULL, NULL,
+			       &pI830->shadowReq, &errmaj, &errmin)) {
+            LoaderErrorMsg(NULL, "shadow", errmaj, errmin);
+	    return FALSE;
+         }
       }
-      xf86LoaderReqSymLists(I810shadowSymbols, NULL);
+   } else {
+      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pI830->shadowReq.majorversion = pI8301->shadowReq.majorversion;
+      pI830->shadowReq.minorversion = pI8301->shadowReq.minorversion;
+      pI830->shadowReq.patchlevel = pI8301->shadowReq.patchlevel;
    }
-#endif
+   xf86LoaderReqSymLists(I810shadowSymbols, NULL);
 
    pI830->preinit = FALSE;
 
@@ -3383,7 +3579,7 @@ CheckInheritedState(ScrnInfoPtr pScrn)
    int errors = 0, fatal = 0;
    unsigned long temp, head, tail;
 
-   if (!IsPrimary(pScrn)) return TRUE;
+   if (!I830IsPrimary(pScrn)) return TRUE;
 
    /* Check first for page table errors */
    temp = INREG(PGE_ERR);
@@ -3438,7 +3634,7 @@ ResetState(ScrnInfoPtr pScrn, Bool flush
 
    DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush));
 
-   if (!IsPrimary(pScrn)) return;
+   if (!I830IsPrimary(pScrn)) return;
 
    if (pI830->entityPrivate)
       pI830->entityPrivate->RingRunning = 0;
@@ -3460,9 +3656,9 @@ ResetState(ScrnInfoPtr pScrn, Bool flush
    OUTREG(LP_RING + RING_HEAD, 0);
    OUTREG(LP_RING + RING_TAIL, 0);
    OUTREG(LP_RING + RING_START, 0);
-
+  
    if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
-       pI830->CursorInfoRec->HideCursor(pScrn);
+      pI830->CursorInfoRec->HideCursor(pScrn);
 }
 
 static void
@@ -3473,7 +3669,7 @@ SetFenceRegs(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "SetFenceRegs\n");
 
-   if (!IsPrimary(pScrn)) return;
+   if (!I830IsPrimary(pScrn)) return;
 
    for (i = 0; i < 8; i++) {
       OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]);
@@ -3493,7 +3689,7 @@ SetRingRegs(ScrnInfoPtr pScrn)
    if (pI830->noAccel)
       return;
 
-   if (!IsPrimary(pScrn)) return;
+   if (!I830IsPrimary(pScrn)) return;
 
    if (pI830->entityPrivate)
       pI830->entityPrivate->RingRunning = 1;
@@ -3556,7 +3752,7 @@ SaveHWState(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "SaveHWState\n");
 
-   if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
+   if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
       SetBIOSPipe(pScrn, pI830->origPipe);
    else
       SetPipeAccess(pScrn);
@@ -3631,7 +3827,10 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "RestoreHWState\n");
 
-   if (IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
+#ifdef XF86DRI
+   I830DRISetVBlankInterrupt (pScrn, FALSE);
+#endif
+   if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe)
       SetBIOSPipe(pScrn, pI830->origPipe);
    else
       SetPipeAccess(pScrn);
@@ -3745,6 +3944,16 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, in
 
    DPRINTF(PFX, "Setting mode 0x%.8x\n", mode);
 
+#if 0
+   /* Clear the framebuffer (could do this with VBIOS call) */
+   if (I830IsPrimary(pScrn))
+      memset(pI830->FbBase + pI830->FrontBuffer.Start, 0,
+	  pScrn->virtualY * pI830->displayWidth * pI830->cpp);
+   else
+      memset(pI830->FbBase + pI830->FrontBuffer2.Start, 0,
+	  pScrn->virtualY * pI830->displayWidth * pI830->cpp);
+#endif
+
    if (pI830->Clone && pI830->CloneHDisplay && pI830->CloneVDisplay &&
        !pI830->preinit && !pI830->closing) {
       VbeCRTCInfoBlock newblock;
@@ -3814,7 +4023,6 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, in
 		    "Set refresh rate to %dHz on Clone head.\n",
 		    pI830->CloneRefresh);
       }
-
       SetPipeAccess(pScrn);
    }
 
@@ -3894,11 +4102,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
    mode = data->mode | (1 << 15) | (1 << 14);
 
 #ifdef XF86DRI
-   if (pI830->directRenderingEnabled && !pI830->LockHeld) {
-      DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
-      pI830->LockHeld = 1;
-      didLock = TRUE;
-   }
+   didLock = I830DRILock(pScrn);
 #endif
 
    if (pI830->Clone) {
@@ -3925,13 +4129,13 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
     * memory than it's aware of.  We check for this later, and set it
     * explicitly if necessary.
     */
-   if (data->data->XResolution != pScrn->displayWidth) {
+   if (data->data->XResolution != pI830->displayWidth) {
       if (pI830->Clone) {
          SetBIOSPipe(pScrn, !pI830->pipe);
-         VBESetLogicalScanline(pVbe, pScrn->displayWidth);
+         VBESetLogicalScanline(pVbe, pI830->displayWidth);
       }
       SetPipeAccess(pScrn);
-      VBESetLogicalScanline(pVbe, pScrn->displayWidth);
+      VBESetLogicalScanline(pVbe, pI830->displayWidth);
    }
 
    if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) {
@@ -4007,28 +4211,28 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
     * Print out the PIPEACONF and PIPEBCONF registers.
     */
    temp = INREG(PIPEACONF);
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", temp);
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", 
+	      (unsigned long) temp);
    if (pI830->availablePipes == 2) {
       temp = INREG(PIPEBCONF);
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", temp);
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", 
+		 (unsigned long) temp);
    }
 
-
-
    if (xf86IsEntityShared(pScrn->entityList[0])) {
       /* Clean this up !! */
-      if (IsPrimary(pScrn)) {
+      if (I830IsPrimary(pScrn)) {
          CARD32 stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE;
          CARD32 basereg = !pI830->pipe ? DSPABASE : DSPBBASE;
          CARD32 sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
          I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 
          temp = INREG(stridereg);
-         if (temp / pI8301->cpp != (CARD32)(pI830->entityPrivate->pScrn_1->displayWidth)) {
+         if (temp / pI8301->cpp != (CARD32)(pI830->displayWidth)) {
             xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
-		    (int)(temp / pI8301->cpp), pI830->entityPrivate->pScrn_1->displayWidth);
-	    OUTREG(stridereg, pI830->entityPrivate->pScrn_1->displayWidth * pI8301->cpp);
+		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
+		    (int)(temp / pI8301->cpp), pI830->displayWidth);
+	    OUTREG(stridereg, pI830->displayWidth * pI8301->cpp);
          }
          OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
          /* Trigger update */
@@ -4042,11 +4246,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
             sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE;
 
             temp = INREG(stridereg);
-            if (temp / pI8302->cpp != (CARD32)(pI830->entityPrivate->pScrn_2->displayWidth)) {
+            if (temp / pI8302->cpp != (CARD32)(pI8302->displayWidth)) {
 	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
-		    (int)(temp / pI8302->cpp), pI830->entityPrivate->pScrn_2->displayWidth);
-	       OUTREG(stridereg, pI830->entityPrivate->pScrn_2->displayWidth * pI8302->cpp);
+		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
+		    (int)(temp / pI8302->cpp), pI8302->displayWidth);
+	       OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp);
             }
             OUTREG(sizereg, (pI830->entityPrivate->pScrn_2->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_2->currentMode->VDisplay - 1) << 16));
             /* Trigger update */
@@ -4061,11 +4265,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
          I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
 
          temp = INREG(stridereg);
-         if (temp / pI8301->cpp != (CARD32)(pI830->entityPrivate->pScrn_1->displayWidth)) {
+         if (temp / pI8301->cpp != (CARD32)(pI8301->displayWidth)) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe),
-		    (int)(temp / pI8301->cpp), pI830->entityPrivate->pScrn_1->displayWidth);
-	    OUTREG(stridereg, pI830->entityPrivate->pScrn_1->displayWidth * pI8301->cpp);
+		    (int)(temp / pI8301->cpp), pI8301->displayWidth);
+	    OUTREG(stridereg, pI8301->displayWidth * pI8301->cpp);
          }
          OUTREG(sizereg, (pI830->entityPrivate->pScrn_1->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_1->currentMode->VDisplay - 1) << 16));
          /* Trigger update */
@@ -4077,11 +4281,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
          sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE;
 
          temp = INREG(stridereg);
-         if (temp / pI8302->cpp != ((CARD32)pI830->entityPrivate->pScrn_2->displayWidth)) {
+         if (temp / pI8302->cpp != ((CARD32)pI8302->displayWidth)) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe),
-		    (int)(temp / pI8302->cpp), pI830->entityPrivate->pScrn_2->displayWidth);
-	    OUTREG(stridereg, pI830->entityPrivate->pScrn_2->displayWidth * pI8302->cpp);
+		    (int)(temp / pI8302->cpp), pI8302->displayWidth);
+	    OUTREG(stridereg, pI8302->displayWidth * pI8302->cpp);
          }
          OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
          /* Trigger update */
@@ -4098,11 +4302,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
 	    continue;
 
          temp = INREG(stridereg);
-         if (temp / pI830->cpp != (CARD32)pScrn->displayWidth) {
+         if (temp / pI830->cpp != (CARD32)pI830->displayWidth) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		    "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i),
-		    (int)(temp / pI830->cpp), pScrn->displayWidth);
-	    OUTREG(stridereg, pScrn->displayWidth * pI830->cpp);
+		    (int)(temp / pI830->cpp), pI830->displayWidth);
+	    OUTREG(stridereg, pI830->displayWidth * pI830->cpp);
          }
          OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16));
 	 /* Trigger update */
@@ -4211,10 +4415,11 @@ I830VESASetMode(ScrnInfoPtr pScrn, Displ
 #endif
 
 #ifdef XF86DRI
-   if (pI830->directRenderingEnabled && didLock) {
-      DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
-      pI830->LockHeld = 0;
-   }
+   I830DRISetVBlankInterrupt (pScrn, TRUE);
+#endif
+#ifdef XF86DRI
+   if (didLock)
+      I830DRIUnlock(pScrn);
 #endif
 
    pScrn->vtSema = TRUE;
@@ -4228,7 +4433,7 @@ InitRegisterRec(ScrnInfoPtr pScrn)
    I830RegPtr i830Reg = &pI830->ModeReg;
    int i;
 
-   if (!IsPrimary(pScrn)) return;
+   if (!I830IsPrimary(pScrn)) return;
 
    for (i = 0; i < 8; i++)
       i830Reg->Fence[i] = 0;
@@ -4242,21 +4447,24 @@ I830PrintErrorState(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
 
    ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
-	  INREG(PGETBL_CTL), INREG(PGE_ERR));
+	  (unsigned long)INREG(PGETBL_CTL), (unsigned long)INREG(PGE_ERR));
 
-   ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR), INREG(IPEHR));
+   ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long)INREG(IPEIR), 
+	  (unsigned long)INREG(IPEHR));
 
    ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
-	  INREG(LP_RING + RING_TAIL),
-	  INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
-	  INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START));
+	  (unsigned long)INREG(LP_RING + RING_TAIL),
+	  (unsigned long)INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
+	  (unsigned long)INREG(LP_RING + RING_LEN), 
+	  (unsigned long)INREG(LP_RING + RING_START));
 
    ErrorF("eir: %x esr: %x emr: %x\n",
 	  INREG16(EIR), INREG16(ESR), INREG16(EMR));
 
    ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
 
-   ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS));
+   ErrorF("memmode: %lx instps: %lx\n", (unsigned long)INREG(MEMMODE), 
+	  (unsigned long)INREG(INST_PS));
 
    ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
 	  INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
@@ -4511,6 +4719,129 @@ I830DrmMMTakedown(int drmFD)
 
 #endif
 
+static void
+I830PointerMoved(int index, int x, int y)
+{
+   ScrnInfoPtr pScrn = xf86Screens[index];
+   I830Ptr pI830 = I830PTR(pScrn);
+   int newX = x, newY = y;
+
+   switch (pI830->rotation) {
+      case RR_Rotate_0:
+         break;
+      case RR_Rotate_90:
+         newX = y;
+         newY = pScrn->pScreen->width - x - 1;
+         break;
+      case RR_Rotate_180:
+         newX = pScrn->pScreen->width - x - 1;
+         newY = pScrn->pScreen->height - y - 1;
+         break;
+      case RR_Rotate_270:
+         newX = pScrn->pScreen->height - y - 1;
+         newY = x;
+         break;
+   }
+
+   (*pI830->PointerMoved)(index, newX, newY);
+}
+
+static Bool
+I830CreateScreenResources (ScreenPtr pScreen)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   pScreen->CreateScreenResources = pI830->CreateScreenResources;
+   if (!(*pScreen->CreateScreenResources)(pScreen))
+      return FALSE;
+
+   if (pI830->rotation != RR_Rotate_0) {
+      RRScreenSize p;
+      Rotation requestedRotation = pI830->rotation;
+
+      pI830->rotation = RR_Rotate_0;
+
+      /* Just setup enough for an initial rotate */
+      p.width = pScreen->width;
+      p.height = pScreen->height;
+      p.mmWidth = pScreen->mmWidth;
+      p.mmHeight = pScreen->mmHeight;
+
+      pI830->starting = TRUE; /* abuse this for dual head & rotation */
+      I830RandRSetConfig (pScreen, requestedRotation, 0, &p);
+      pI830->starting = FALSE;
+   } 
+
+   return TRUE;
+}
+
+static Bool
+I830InitFBManager(
+    ScreenPtr pScreen,  
+    BoxPtr FullBox
+){
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   RegionRec ScreenRegion;
+   RegionRec FullRegion;
+   BoxRec ScreenBox;
+   Bool ret;
+
+   ScreenBox.x1 = 0;
+   ScreenBox.y1 = 0;
+   ScreenBox.x2 = pScrn->displayWidth;
+   if (pScrn->virtualX > pScrn->virtualY)
+      ScreenBox.y2 = pScrn->virtualX;
+   else
+      ScreenBox.y2 = pScrn->virtualY;
+
+   if((FullBox->x1 >  ScreenBox.x1) || (FullBox->y1 >  ScreenBox.y1) ||
+      (FullBox->x2 <  ScreenBox.x2) || (FullBox->y2 <  ScreenBox.y2)) {
+	return FALSE;   
+   }
+
+   if (FullBox->y2 < FullBox->y1) return FALSE;
+   if (FullBox->x2 < FullBox->x2) return FALSE;
+
+   REGION_INIT(pScreen, &ScreenRegion, &ScreenBox, 1); 
+   REGION_INIT(pScreen, &FullRegion, FullBox, 1); 
+
+   REGION_SUBTRACT(pScreen, &FullRegion, &FullRegion, &ScreenRegion);
+
+   ret = xf86InitFBManagerRegion(pScreen, &FullRegion);
+
+   REGION_UNINIT(pScreen, &ScreenRegion);
+   REGION_UNINIT(pScreen, &FullRegion);
+    
+   return ret;
+}
+
+/* Initialize the first context */
+void
+IntelEmitInvarientState(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   CARD32 ctx_addr;
+
+   ctx_addr = pI830->ContextMem.Start;
+   /* Align to a 2k boundry */
+   ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048;
+
+   {
+      BEGIN_LP_RING(2);
+      OUT_RING(MI_SET_CONTEXT);
+      OUT_RING(ctx_addr |
+	       CTXT_NO_RESTORE |
+	       CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE);
+      ADVANCE_LP_RING();
+   }
+
+   if (IS_I9XX(pI830))
+      I915EmitInvarientState(pScrn);
+   else
+      I830EmitInvarientState(pScrn);
+}
+
 static Bool
 I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 {
@@ -4518,10 +4849,7 @@ I830BIOSScreenInit(int scrnIndex, Screen
    vgaHWPtr hwp;
    I830Ptr pI830;
    VisualPtr visual;
-   I830EntPtr pI830Ent = NULL;
    I830Ptr pI8301 = NULL;
-   int width, height, displayWidth;
-   unsigned char *fbbase;
 #ifdef XF86DRI
    Bool driDisabled;
 #endif
@@ -4530,12 +4858,20 @@ I830BIOSScreenInit(int scrnIndex, Screen
    pI830 = I830PTR(pScrn);
    hwp = VGAHWPTR(pScrn);
 
-   if (xf86IsEntityShared(pScrn->entityList[0])) {
-      pI830Ent = pI830->entityPrivate;
-      pI8301 = I830PTR(pI830Ent->pScrn_1);
+   pScrn->displayWidth = pI830->displayWidth;
+
+   if (I830IsPrimary(pScrn)) {
+      /* Rotated Buffer */
+      memset(&(pI830->RotatedMem), 0, sizeof(pI830->RotatedMem));
+      pI830->RotatedMem.Key = -1;
+      /* Rotated2 Buffer */
+      memset(&(pI830->RotatedMem2), 0, sizeof(pI830->RotatedMem2));
+      pI830->RotatedMem2.Key = -1;
+   }
 
+   if (xf86IsEntityShared(pScrn->entityList[0])) {
       /* PreInit failed on the second head, so make sure we turn it off */
-      if (IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) {
+      if (I830IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) {
          if (pI830->pipe == 0) {
             pI830->operatingDevices &= 0xFF;
          } else {
@@ -4547,7 +4883,7 @@ I830BIOSScreenInit(int scrnIndex, Screen
    pI830->starting = TRUE;
 
    /* Alloc our pointers for the primary head */
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       if (!pI830->LpRing)
          pI830->LpRing = xalloc(sizeof(I830RingBuffer));
       if (!pI830->CursorMem)
@@ -4558,8 +4894,10 @@ I830BIOSScreenInit(int scrnIndex, Screen
          pI830->OverlayMem = xalloc(sizeof(I830MemRange));
       if (!pI830->overlayOn)
          pI830->overlayOn = xalloc(sizeof(Bool));
+      if (!pI830->used3D)
+         pI830->used3D = xalloc(sizeof(int));
       if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB ||
-          !pI830->OverlayMem || !pI830->overlayOn) {
+          !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Could not allocate primary data structures.\n");
          return FALSE;
@@ -4569,31 +4907,47 @@ I830BIOSScreenInit(int scrnIndex, Screen
          pI830->entityPrivate->XvInUse = -1;
    }
 
-   if (xf86IsEntityShared(pScrn->entityList[0])) {
-	/* Make our second head point to the first heads structures */
-	if (!IsPrimary(pScrn)) {
-	   pI830->LpRing = pI8301->LpRing;
-	   pI830->CursorMem = pI8301->CursorMem;
-	   pI830->CursorMemARGB = pI8301->CursorMemARGB;
-	   pI830->OverlayMem = pI8301->OverlayMem;
-           pI830->overlayOn = pI8301->overlayOn;
-	}
+   /* Make our second head point to the first heads structures */
+   if (!I830IsPrimary(pScrn)) {
+      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pI830->LpRing = pI8301->LpRing;
+      pI830->CursorMem = pI8301->CursorMem;
+      pI830->CursorMemARGB = pI8301->CursorMemARGB;
+      pI830->OverlayMem = pI8301->OverlayMem;
+      pI830->overlayOn = pI8301->overlayOn;
+      pI830->used3D = pI8301->used3D;
    }
 
    /*
     * If we're changing the BIOS's view of the video memory size, do that
     * first, then re-initialise the VBE information.
     */
-   if (pI830->pVbe)
-      vbeFree(pI830->pVbe);
-   pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
-   if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
-       SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
+   if (I830IsPrimary(pScrn)) {
+      SetPipeAccess(pScrn);
+      if (pI830->pVbe)
+         vbeFree(pI830->pVbe);
+      pI830->pVbe = VBEInit(NULL, pI830->pEnt->index);
+   } else {
+      pI830->pVbe = pI8301->pVbe;
+   }
+
+   if (I830IsPrimary(pScrn)) {
+      if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
+         SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
+   }
+
    if (!pI830->pVbe)
       return FALSE;
-   if (pI830->vbeInfo)
-      VBEFreeVBEInfo(pI830->vbeInfo);
-   pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+
+   if (I830IsPrimary(pScrn)) {
+      if (pI830->vbeInfo)
+         VBEFreeVBEInfo(pI830->vbeInfo);
+      pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe);
+   } else {
+      pI830->vbeInfo = pI8301->vbeInfo;
+   }
+
+   SetPipeAccess(pScrn);
 
    miClearVisualTypes();
    if (!miSetVisualTypes(pScrn->depth,
@@ -4606,7 +4960,7 @@ I830BIOSScreenInit(int scrnIndex, Screen
 #ifdef I830_XV
    pI830->XvEnabled = !pI830->XvDisabled;
    if (pI830->XvEnabled) {
-      if (!IsPrimary(pScrn)) {
+      if (!I830IsPrimary(pScrn)) {
          if (!pI8301->XvEnabled || pI830->noAccel) {
             pI830->XvEnabled = FALSE;
 	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled.\n");
@@ -4622,7 +4976,7 @@ I830BIOSScreenInit(int scrnIndex, Screen
    pI830->XvEnabled = FALSE;
 #endif
 
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       I830ResetAllocations(pScrn, 0);
 
       if (!I830Allocate2DMemory(pScrn, ALLOC_INITIAL))
@@ -4678,7 +5032,7 @@ I830BIOSScreenInit(int scrnIndex, Screen
     */
 
    if (pI830->directRenderingEnabled) {
-      if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && IsPrimary(pScrn))) {
+      if (pI830->noAccel || pI830->SWCursor || (pI830->StolenOnly && I830IsPrimary(pScrn))) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
 		    "needs HW cursor, 2D accel and AGPGART.\n");
 	 pI830->directRenderingEnabled = FALSE;
@@ -4706,7 +5060,7 @@ I830BIOSScreenInit(int scrnIndex, Screen
     * After the 3D allocations have been done, see if there's any free space
     * that can be added to the framebuffer allocation.
     */
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       I830Allocate2DMemory(pScrn, 0);
 
       DPRINTF(PFX, "assert(if(!I830DoPoolAllocation(pScrn, pI830->StolenPool)))\n");
@@ -4731,10 +5085,9 @@ I830BIOSScreenInit(int scrnIndex, Screen
 
    pScrn->memPhysBase = (unsigned long)pI830->FbBase;
 
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       pScrn->fbOffset = pI830->FrontBuffer.Start;
    } else {
-      I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1);
       pScrn->fbOffset = pI8301->FrontBuffer2.Start;
    }
 
@@ -4756,26 +5109,10 @@ I830BIOSScreenInit(int scrnIndex, Screen
       return FALSE;
 
    DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
-   if (pI830->rotate) {
-       height = pScrn->virtualX;
-       width = pScrn->virtualY;
-   } else {
-       width = pScrn->virtualX;
-       height = pScrn->virtualY;
-   }
-   if (pI830->shadowFB) {
-       pI830->shadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
-       pI830->shadowPtr = xalloc(pI830->shadowPitch * height);
-       displayWidth = pI830->shadowPitch / (pScrn->bitsPerPixel >> 3);
-       fbbase = pI830->shadowPtr;
-   } else {
-       pI830->shadowPtr = NULL;
-       fbbase = pI830->FbBase;
-       displayWidth = pScrn->displayWidth;
-   }
-   if (!fbScreenInit(pScreen, fbbase + pScrn->fbOffset, width, height,
+   if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset, 
+                     pScrn->virtualX, pScrn->virtualY,
 		     pScrn->xDpi, pScrn->yDpi,
-		     displayWidth, pScrn->bitsPerPixel))
+		     pScrn->displayWidth, pScrn->bitsPerPixel))
       return FALSE;
 
    if (pScrn->bitsPerPixel > 8) {
@@ -4797,22 +5134,24 @@ I830BIOSScreenInit(int scrnIndex, Screen
 
    xf86SetBlackWhitePixels(pScreen);
 
-   if (!pI830->shadowFB)
-       I830DGAInit(pScreen);
+   I830DGAInit(pScreen);
 
    DPRINTF(PFX,
-	   "assert( if(!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
-   if (IsPrimary(pScrn)) {
-      if (!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) {
+	   "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n");
+   if (I830IsPrimary(pScrn)) {
+      if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Failed to init memory manager\n");
-         return FALSE;
       }
+
+      if (pI830->LinearAlloc && xf86InitFBManagerLinear(pScreen, pI830->LinearMem.Offset / pI830->cpp, pI830->LinearMem.Size / pI830->cpp))
+            xf86DrvMsg(scrnIndex, X_INFO, 
+			"Using %ld bytes of offscreen memory for linear (offset=0x%lx)\n", pI830->LinearMem.Size, pI830->LinearMem.Offset);
+
    } else {
-      if (!xf86InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
+      if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Failed to init memory manager\n");
-         return FALSE;
       }
    }
 
@@ -4836,31 +5175,6 @@ I830BIOSScreenInit(int scrnIndex, Screen
    } else
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n");
 
-   if (pI830->shadowFB) {
-       RefreshAreaFuncPtr refreshArea = I830RefreshArea;
-       if (pI830->rotate) {
-	   if (!pI830->PointerMoved) {
-	       pI830->PointerMoved = pScrn->PointerMoved;
-	       pScrn->PointerMoved = I830PointerMoved;
-	   }
-	   switch (pScrn->bitsPerPixel) {
-	   case 8:
-	       refreshArea = I830RefreshArea8;
-	       break;
-	   case 16:
-	       refreshArea = I830RefreshArea16;
-	       break;
-	   case 24:
-	       refreshArea = I830RefreshArea24;
-	       break;
-	   case 32:
-	       refreshArea = I830RefreshArea32;
-	       break;
-	   }
-       }
-       ShadowFBInit(pScreen, refreshArea);
-   }
-
    DPRINTF(PFX, "assert( if(!miCreateDefColormap(pScreen)) )\n");
    if (!miCreateDefColormap(pScreen))
       return FALSE;
@@ -4886,12 +5200,13 @@ I830BIOSScreenInit(int scrnIndex, Screen
    }
 #endif
 
+   /* Setup 3D engine, needed for rotation too */
+   IntelEmitInvarientState(pScrn);
+
 #ifdef XF86DRI
    if (pI830->directRenderingEnabled) {
       pI830->directRenderingOpen = TRUE;
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Enabled\n");
-      /* Setup 3D engine */
-      I830EmitInvarientState(pScrn);
    } else {
       if (driDisabled)
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Disabled\n");
@@ -4905,7 +5220,23 @@ I830BIOSScreenInit(int scrnIndex, Screen
    pScreen->SaveScreen = I830BIOSSaveScreen;
    pI830->CloseScreen = pScreen->CloseScreen;
    pScreen->CloseScreen = I830BIOSCloseScreen;
- 
+
+   if (pI830->shadowReq.minorversion >= 1) {
+      /* Rotation */
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandR enabled, ignore the following RandR disabled message.\n");
+      xf86DisableRandR(); /* Disable built-in RandR extension */
+      shadowSetup(pScreen);
+      /* support all rotations */
+      I830RandRInit(pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
+      pI830->PointerMoved = pScrn->PointerMoved;
+      pScrn->PointerMoved = I830PointerMoved;
+      pI830->CreateScreenResources = pScreen->CreateScreenResources;
+      pScreen->CreateScreenResources = I830CreateScreenResources;
+   } else {
+      /* Rotation */
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "libshadow is version %d.%d.%d, required 1.1.0 or greater for rotation.\n",pI830->shadowReq.majorversion,pI830->shadowReq.minorversion,pI830->shadowReq.patchlevel);
+   }
+
    if (serverGeneration == 1)
       xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
 
@@ -4952,6 +5283,30 @@ I830BIOSScreenInit(int scrnIndex, Screen
    }
 #endif
 
+
+   switch (pI830->InitialRotation) {
+      case 0:
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 0 degrees\n");
+         pI830->rotation = RR_Rotate_0;
+         break;
+      case 90:
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 90 degrees\n");
+         pI830->rotation = RR_Rotate_90;
+         break;
+      case 180:
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 180 degrees\n");
+         pI830->rotation = RR_Rotate_180;
+         break;
+      case 270:
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rotating to 270 degrees\n");
+         pI830->rotation = RR_Rotate_270;
+         break;
+      default:
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad rotation setting - defaulting to 0 degrees\n");
+         pI830->rotation = RR_Rotate_0;
+         break;
+   }
+
    return TRUE;
 }
 
@@ -4962,6 +5317,7 @@ I830BIOSAdjustFrame(int scrnIndex, int x
    ScrnInfoPtr pScrn;
    I830Ptr pI830;
    vbeInfoPtr pVbe;
+   unsigned long Start;
 
    pScrn = xf86Screens[scrnIndex];
    pI830 = I830PTR(pScrn);
@@ -4971,46 +5327,35 @@ I830BIOSAdjustFrame(int scrnIndex, int x
 	   x, pI830->xoffset, y, pI830->yoffset);
 
    /* Sync the engine before adjust frame */
-   if (!pI830->noAccel && pI830->AccelInfoRec)
+   if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
       (*pI830->AccelInfoRec->Sync)(pScrn);
+      pI830->AccelInfoRec->NeedToSync = FALSE;
+   }
 
-   /* The i830M just happens to have some problems programming offsets via
-    * this VESA BIOS call. Especially in dual head configurations which
-    * have high resolutions which cause the DSP{A,B}BASE registers to be
-    * programmed incorrectly. Thus, it warrants bypassing the BIOS for i830M
-    * and hitting the DSP{A,B}BASE registers directly. 
-    *
-    * We could probably do this for other platforms too, but we don't
-    * know what else the Video BIOS may do when calling it. It seems safe
-    * though for i830M during testing......
-    *
-    * Also note, calling the Video BIOS version first and then fixing the
-    * registers fail on i830M and eventually cause a lockup of the hardware
-    * in my testing.
+   if (I830IsPrimary(pScrn))
+      Start = pI830->FrontBuffer.Start;
+   else {
+      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      Start = pI8301->FrontBuffer2.Start;
+   }
+
+   /* Sigh...
+    * It seems that there are quite a few Video BIOS' that get this wrong.
+    * So, we'll bypass the VBE call and hit the hardware directly.
     */
 
    if (pI830->Clone) {
-      if (!IS_I830(pI830)) {
-         SetBIOSPipe(pScrn, !pI830->pipe);
-         VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE);
+      if (!pI830->pipe == 0) {
+         OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
       } else {
-         if (!pI830->pipe == 0) {
-            OUTREG(DSPABASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp));
-         } else {
-            OUTREG(DSPBBASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp));
-         }
+         OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
       }
    }
 
-   if (!IS_I830(pI830)) {
-      SetPipeAccess(pScrn);
-      VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE);
+   if (pI830->pipe == 0) {
+      OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
    } else {
-      if (pI830->pipe == 0) {
-         OUTREG(DSPABASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp));
-      } else {
-         OUTREG(DSPBBASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp));
-      }
+      OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
    }
 }
 
@@ -5075,7 +5420,7 @@ I830BIOSLeaveVT(int scrnIndex, int flags
       pI830->CloneVDisplay = 0;
    }
 
-   if (!IsPrimary(pScrn)) {
+   if (!I830IsPrimary(pScrn)) {
    	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 	if (!pI8301->GttBound) {
 		return;
@@ -5084,9 +5429,7 @@ I830BIOSLeaveVT(int scrnIndex, int flags
 
 #ifdef XF86DRI
    if (pI830->directRenderingOpen) {
-      DPRINTF(PFX, "calling dri lock\n");
-      DRILock(screenInfo.screens[scrnIndex], 0);
-      pI830->LockHeld = 1;
+      DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
       
       drmCtlUninstHandler(pI830->drmSubFD);
    }
@@ -5102,7 +5445,7 @@ I830BIOSLeaveVT(int scrnIndex, int flags
 
    ResetState(pScrn, TRUE);
 
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
          xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "Failed to switch back to original display devices (0x%x)\n",
@@ -5115,13 +5458,13 @@ I830BIOSLeaveVT(int scrnIndex, int flags
 
    RestoreHWState(pScrn);
    RestoreBIOSMemSize(pScrn);
-   if (IsPrimary(pScrn))
-      I830UnbindGARTMemory(pScrn);
+   if (I830IsPrimary(pScrn))
+      I830UnbindAGPMemory(pScrn);
    if (pI830->AccelInfoRec)
       pI830->AccelInfoRec->NeedToSync = FALSE;
 
    /* DO IT AGAIN! AS IT SEEMS THAT SOME LFPs FLICKER OTHERWISE */
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       if (!SetDisplayDevices(pScrn, pI830->savedDevices)) {
          xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "Failed to switch back to original display devices (0x%x) (2)\n",
@@ -5215,7 +5558,7 @@ I830DetectMonitorChange(ScrnInfoPtr pScr
                   Clock = pMon->Clock;
             } 
 
-            if (DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
+            if (Clock != 100000000 && DDCclock < 2550 && Clock / 1000.0 > DDCclock) {
                ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n",
 		   p->name, pScrn->monitor->id,
 		   Clock/1000.0, DDCclock);
@@ -5327,7 +5670,13 @@ I830BIOSEnterVT(int scrnIndex, int flags
 
    pI830->leaving = FALSE;
 
-   if (IsPrimary(pScrn)) {
+#if 1
+   /* Clear the framebuffer */
+   memset(pI830->FbBase + pScrn->fbOffset, 0,
+	  pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
+#endif
+
+   if (I830IsPrimary(pScrn)) {
      /* 
       * This is needed for restoring from ACPI modes (especially S3)
       * so that we warmboot the Video BIOS. Some platforms have problems,
@@ -5335,9 +5684,7 @@ I830BIOSEnterVT(int scrnIndex, int flags
       * the Video BIOS with our saved devices, and only when that fails,
       * we'll warm boot it.
       */
-     /* Check Pipe conf registers or possibly HTOTAL/VTOTAL for 0x00000000)*/
-      CARD32 temp = pI830->pipe ? INREG(PIPEBCONF) : INREG(PIPEACONF);
-      if (!I830Set640x480(pScrn) || !(temp & 0x80000000)) {
+      if (!I830Set640x480(pScrn)) {
          xf86Int10InfoPtr pInt;
 
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
@@ -5356,7 +5703,7 @@ I830BIOSEnterVT(int scrnIndex, int flags
 		"Re-POSTing via int10 failed, trying to continue.\n");
          }
       }
-     
+
       /* Finally, re-setup the display devices */
       if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) {
          xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -5366,25 +5713,21 @@ I830BIOSEnterVT(int scrnIndex, int flags
    }
 
    /* Setup for device monitoring status */
-   pI830->monitorSwitch = INREG(SWF0) & 0x0000FFFF;
+   pI830->monitorSwitch = pI830->toggleDevices = INREG(SWF0) & 0x0000FFFF;
 
-   if (IsPrimary(pScrn))
-      if (!I830BindGARTMemory(pScrn))
+   if (I830IsPrimary(pScrn))
+      if (!I830BindAGPMemory(pScrn))
          return FALSE;
 
    CheckInheritedState(pScrn);
-   if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
-       SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
+   if (I830IsPrimary(pScrn)) {
+      if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE))
+         SetBIOSMemSize(pScrn, pI830->newBIOSMemSize);
+   }
 
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
-#if 1
-   /* Clear the framebuffer */
-   memset(pI830->FbBase + pScrn->fbOffset, 0,
-	  pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
-#endif
-
    /* Detect monitor change and switch to suitable mode */
    if (!pI830->starting)
       I830DetectMonitorChange(pScrn);
@@ -5410,21 +5753,28 @@ I830BIOSEnterVT(int scrnIndex, int flags
       if (!pI830->starting) {
 	 I830DRIResume(screenInfo.screens[scrnIndex]);
       
-	 I830EmitInvarientState(pScrn);
 	 I830RefreshRing(pScrn);
 	 I830Sync(pScrn);
 	 DO_RING_IDLE();
 
 	 DPRINTF(PFX, "calling dri unlock\n");
-	 DRIUnlock(screenInfo.screens[scrnIndex]);
+	 DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
       }
       pI830->LockHeld = 0;
    }
 #endif
 
+   /* Needed for rotation */
+   IntelEmitInvarientState(pScrn);
+
    if (pI830->checkDevices)
       pI830->devicesTimer = TimerSet(NULL, 0, 1000, I830CheckDevicesTimer, pScrn);
 
+   pI830->currentMode = pScrn->currentMode;
+
+   /* Force invarient state when rotated to be emitted */
+   *pI830->used3D = 1<<31;
+
    return TRUE;
 }
 
@@ -5434,35 +5784,64 @@ I830BIOSSwitchMode(int scrnIndex, Displa
 
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
-   int ret = TRUE;
+   Bool ret = TRUE;
+   PixmapPtr pspix = (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen);
 
    DPRINTF(PFX, "I830BIOSSwitchMode: mode == %p\n", mode);
 
-   /* Sync the engine before mode switch */
-   if (!pI830->noAccel && pI830->AccelInfoRec)
-      (*pI830->AccelInfoRec->Sync)(pScrn);
-
-#ifndef BINDUNBIND
-#define BINDUNBIND 0
-#endif
-#if BINDUNBIND
-   if (IsPrimary(pScrn))
-      I830UnbindGARTMemory(pScrn);
-#endif
 #ifdef I830_XV
    /* Give the video overlay code a chance to see the new mode. */
    I830VideoSwitchModeBefore(pScrn, mode);
 #endif
-   if (!I830VESASetMode(pScrn, mode))
-      ret = FALSE;
+
+   /* Sync the engine before mode switch */
+   if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+      (*pI830->AccelInfoRec->Sync)(pScrn);
+      pI830->AccelInfoRec->NeedToSync = FALSE;
+   }
+
+   /* Check if our currentmode is about to change. We do this so if we
+    * are rotating, we don't need to call the mode setup again.
+    */
+   if (pI830->currentMode != mode) {
+      if (!I830VESASetMode(pScrn, mode))
+         ret = FALSE;
+   }
+
+   /* Kludge to detect Rotate or Vidmode switch. Not very elegant, but
+    * workable given the implementation currently. We only need to call
+    * the rotation function when we know that the framebuffer has been
+    * disabled by the EnableDisableFBAccess() function.
+    *
+    * The extra WindowTable check detects a rotation at startup.
+    */
+   if ( (!WindowTable[pScrn->scrnIndex] || pspix->devPrivate.ptr == NULL) &&
+         !pI830->DGAactive && (pScrn->PointerMoved == I830PointerMoved) ) {
+      if (!I830Rotate(pScrn, mode))
+         ret = FALSE;
+   }
+
+   /* Either the original setmode or rotation failed, so restore the previous
+    * video mode here, as we'll have already re-instated the original rotation.
+    */
+   if (!ret) {
+      if (!I830VESASetMode(pScrn, pI830->currentMode)) {
+	 xf86DrvMsg(scrnIndex, X_INFO,
+		    "Failed to restore previous mode (SwitchMode)\n");
+      }
+
 #ifdef I830_XV
-   /* Give the video overlay code a chance to see the new mode. */
-   I830VideoSwitchModeAfter(pScrn, mode);
+      /* Give the video overlay code a chance to see the new mode. */
+      I830VideoSwitchModeAfter(pScrn, pI830->currentMode);
 #endif
-#if BINDUNBIND
-   if (IsPrimary(pScrn))
-      I830BindGARTMemory(pScrn);
+   } else {
+      pI830->currentMode = mode;
+
+#ifdef I830_XV
+      /* Give the video overlay code a chance to see the new mode. */
+      I830VideoSwitchModeAfter(pScrn, mode);
 #endif
+   }
 
    return ret;
 }
@@ -5614,7 +5993,7 @@ I830BIOSCloseScreen(int scrnIndex, Scree
       pI830->CursorInfoRec = 0;
    }
 
-   if (IsPrimary(pScrn)) {
+   if (I830IsPrimary(pScrn)) {
       xf86GARTCloseScreen(scrnIndex);
 
       xfree(pI830->LpRing);
@@ -5627,8 +6006,13 @@ I830BIOSCloseScreen(int scrnIndex, Scree
       pI830->OverlayMem = NULL;
       xfree(pI830->overlayOn);
       pI830->overlayOn = NULL;
+      xfree(pI830->used3D);
+      pI830->used3D = NULL;
    }
 
+   if (pI830->shadowReq.minorversion >= 1)
+      pScrn->PointerMoved = pI830->PointerMoved;
+
    pScrn->vtSema = FALSE;
    pI830->closing = FALSE;
    pScreen->CloseScreen = pI830->CloseScreen;
@@ -5667,7 +6051,7 @@ I830PMEvent(int scrnIndex, pmEvent event
    I830Ptr pI830 = I830PTR(pScrn);
 
    DPRINTF(PFX, "Enter VT, event %d, undo: %s\n", event, BOOLTOSTRING(undo));
-
+ 
    switch(event) {
    case XF86_APM_SYS_SUSPEND:
    case XF86_APM_CRITICAL_SUSPEND: /*do we want to delay a critical suspend?*/
@@ -5702,6 +6086,34 @@ I830PMEvent(int scrnIndex, pmEvent event
 	 SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
       }
       break;
+   /* This is currently used for ACPI */
+   case XF86_APM_CAPABILITY_CHANGED:
+#if 0
+      /* If we had status checking turned on, turn it off now */
+      if (pI830->checkDevices) {
+         if (pI830->devicesTimer)
+            TimerCancel(pI830->devicesTimer);
+         pI830->devicesTimer = NULL;
+         pI830->checkDevices = FALSE; 
+      }
+#endif
+      if (!I830IsPrimary(pScrn))
+         return TRUE;
+
+      ErrorF("I830PMEvent: Capability change\n");
+
+      /* ACPI Toggle */
+      pI830->toggleDevices = GetNextDisplayDeviceList(pScrn, 1);
+      if (xf86IsEntityShared(pScrn->entityList[0])) {
+         I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
+         pI8302->toggleDevices = pI830->toggleDevices;
+      }
+
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ACPI Toggle to 0x%x\n",pI830->toggleDevices);
+
+      I830CheckDevicesTimer(NULL, 0, pScrn);
+      SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
+      break;
    default:
       ErrorF("I830PMEvent: received APM event %d\n", event);
    }
@@ -5733,28 +6145,40 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
       CARD32 adjust;
       CARD32 temp = INREG(SWF0) & 0x0000FFFF;
       int fixup = 0;
+      I830Ptr pI8301;
+      I830Ptr pI8302 = NULL;
 
-      /* this avoids a BIOS call if possible */
-      if (pI830->monitorSwitch != temp) {
-         I830Ptr pI8301;
-         I830Ptr pI8302 = NULL;
-         unsigned int toggle = GetToggleList(pScrn, 1);
-
-         GetToggleList(pScrn, 2);
-         GetToggleList(pScrn, 3);
-         GetToggleList(pScrn, 4);
-         
-         if (IsPrimary(pScrn))
-            pI8301 = pI830;
-         else 
-            pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      if (I830IsPrimary(pScrn))
+         pI8301 = pI830;
+      else 
+         pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 
-         if (xf86IsEntityShared(pScrn->entityList[0]))
-            pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
+      if (xf86IsEntityShared(pScrn->entityList[0]))
+         pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
 
+      /* this avoids several BIOS calls if possible */
+      if (pI830->monitorSwitch != temp || pI830->monitorSwitch != pI830->toggleDevices) {
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+		    "Hotkey switch to 0x%lx.\n", (unsigned long) temp);
+
+         if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+            (*pI830->AccelInfoRec->Sync)(pScrn);
+            pI830->AccelInfoRec->NeedToSync = FALSE;
+            if (xf86IsEntityShared(pScrn->entityList[0]))
+               pI8302->AccelInfoRec->NeedToSync = FALSE;
+         }
+
+         GetAttachableDisplayDeviceList(pScrn);
+         
+	 pI8301->lastDevice0 = pI8301->lastDevice1;
          pI8301->lastDevice1 = pI8301->lastDevice2;
          pI8301->lastDevice2 = pI8301->monitorSwitch;
 
+	 if (temp != pI8301->lastDevice1 && 
+	     temp != pI8301->lastDevice2) {
+            xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+			"Detected three device configs.\n");
+	 } else
          if (CountBits(temp & 0xff) > 1) {
             xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
 			"Detected cloned pipe mode (A).\n");
@@ -5783,22 +6207,23 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
          }
 
          if (cloned &&
-             ((CountBits(pI830->lastDevice1 & 0xff) > 1) ||
-             ((CountBits((pI830->lastDevice1 & 0xff00) >> 8) > 1))) ) {
+             ((CountBits(pI8301->lastDevice1 & 0xff) > 1) ||
+             ((CountBits((pI8301->lastDevice1 & 0xff00) >> 8) > 1))) ) {
                xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
 			"Detected duplicate (1).\n");
                cloned = 0;
          } else
          if (cloned &&
-             ((CountBits(pI830->lastDevice2 & 0xff) > 1) ||
-             ((CountBits((pI830->lastDevice2 & 0xff00) >> 8) > 1))) ) {
+             ((CountBits(pI8301->lastDevice2 & 0xff) > 1) ||
+             ((CountBits((pI8301->lastDevice2 & 0xff00) >> 8) > 1))) ) {
                xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
 			"Detected duplicate (2).\n");
                cloned = 0;
          } 
 
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Requested display devices 0x%lx.\n", temp);
+			"Requested display devices 0x%lx.\n", 
+		    (unsigned long) temp);
 
 
          /* If the BIOS doesn't flip between CRT, LFP and CRT+LFP we fake
@@ -5809,9 +6234,23 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
           *
           * Cloned pipe mode should only be done when running single head.
           */
-         if (xf86IsEntityShared(pScrn->entityList[0]))
+         if (xf86IsEntityShared(pScrn->entityList[0])) {
             cloned = 0;
 
+	    /* Some BIOS' don't realize we may be in true dual head mode.
+	     * And only display the primary output on both when switching.
+	     * We detect this here and cycle back to both pipes.
+	     */
+	    if ((pI830->lastDevice0 == temp) &&
+                ((CountBits(pI8301->lastDevice2 & 0xff) > 1) ||
+                ((CountBits((pI8301->lastDevice2 & 0xff00) >> 8) > 1))) ) {
+               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+			"Detected cloned pipe mode when dual head on previous switch. (0x%x -> 0x%x)\n", (int)temp, pI8301->MonType2 << 8 | pI8301->MonType1);
+	       temp = pI8301->MonType2 << 8 | pI8301->MonType1;
+	    }
+	    
+	 }
+
          if (cloned) { 
             if (pI830->Clone)
                temp = pI8301->MonType2 << 8 | pI8301->MonType1;
@@ -5822,19 +6261,39 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
          } 
 
          /* Jump to our next mode if we detect we've been here before */
-         if (temp == pI830->lastDevice1 || temp == pI830->lastDevice2) {
-             temp = toggle;
+         if (temp == pI8301->lastDevice1 || temp == pI8301->lastDevice2) {
+             temp = GetToggleList(pScrn, 1);
              xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-			"Detected duplicate devices. Toggling (0x%lx)\n", temp);
+			"Detected duplicate devices. Toggling (0x%lx)\n", 
+			(unsigned long) temp);
          }
 
          xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
 		"Detected display change operation (0x%x, 0x%x, 0x%lx).\n", 
-                pI8301->lastDevice1, pI8301->lastDevice2, temp);
+                pI8301->lastDevice1, pI8301->lastDevice2, 
+		    (unsigned long) temp);
 
          /* So that if we close on the wrong config, we restore correctly */
          pI830->specifiedMonitor = TRUE;
 
+         if (!xf86IsEntityShared(pScrn->entityList[0])) {
+            if ((temp & 0xFF00) && (temp & 0x00FF)) {
+               pI830->Clone = TRUE;
+               xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting Clone mode\n");
+            } else {
+               pI830->Clone = FALSE;
+               xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clearing Clone mode\n");
+            }
+         }
+
+         {
+            /* Turn Cursor off before switching */
+            Bool on = pI830->cursorOn;
+            if (pI830->CursorInfoRec && pI830->CursorInfoRec->HideCursor)
+               pI830->CursorInfoRec->HideCursor(pScrn);
+            pI830->cursorOn = on;
+         }
+
          /* double check the display devices are what's configured and try
           * not to do it twice because of dual heads with the code above */
          if (!SetDisplayDevices(pScrn, temp)) {
@@ -5843,24 +6302,43 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
                      (CountBits((temp & 0xff00) >> 8) > 1)) ) {
 	       temp = pI8301->lastDevice2 | pI8301->lastDevice1;
                xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cloning failed, "
-                    "trying dual pipe clone mode (0x%lx)\n", temp);
+			  "trying dual pipe clone mode (0x%lx)\n", 
+			  (unsigned long) temp);
                if (!SetDisplayDevices(pScrn, temp))
                     xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch "
- 		    "to configured display devices (0x%lx).\n", temp);
-               else
+ 		    "to configured display devices (0x%lx).\n", 
+			       (unsigned long) temp);
+               else {
                  pI830->Clone = TRUE;
+                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting Clone mode\n");
+               }
             }
          }
+
          pI8301->monitorSwitch = temp;
 	 pI8301->operatingDevices = temp;
+	 pI8301->toggleDevices = temp;
+
          if (xf86IsEntityShared(pScrn->entityList[0])) {
-	    pI8302->operatingDevices = temp;
-            pI8302->monitorSwitch = temp;
+	    pI8302->operatingDevices = pI8301->operatingDevices;
+            pI8302->monitorSwitch = pI8301->monitorSwitch;
+	    pI8302->toggleDevices = pI8301->toggleDevices;
          }
 
          fixup = 1;
+
+#if 0
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+			"ACPI _DGS queried devices is 0x%x, but probed is 0x%x monitorSwitch=0x%x\n", 
+			pI830->toggleDevices, INREG(SWF0), pI830->monitorSwitch);
+#endif
       } else {
-         int offset = pScrn->fbOffset + ((pScrn->frameY0 * pScrn->displayWidth + pScrn->frameX0) * pI830->cpp);
+         int offset = -1;
+         if (I830IsPrimary(pScrn))
+            offset = pI8301->FrontBuffer.Start + ((pScrn->frameY0 * pI830->displayWidth + pScrn->frameX0) * pI830->cpp);
+         else {
+            offset = pI8301->FrontBuffer2.Start + ((pScrn->frameY0 * pI830->displayWidth + pScrn->frameX0) * pI830->cpp);
+	 }
 
          if (pI830->pipe == 0)
             adjust = INREG(DSPABASE);
@@ -5879,6 +6357,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
          ScreenPtr   pCursorScreen;
          int x = 0, y = 0;
 
+
          pCursorScreen = miPointerCurrentScreen();
          if (pScrn->pScreen == pCursorScreen)
             miPointerPosition(&x, &y);
@@ -5893,13 +6372,15 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
 			 "Primary pipe is now %s.\n", pI830->pipe ? "B" : "A");
          } 
 
+         pI830->currentMode = NULL;
          I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0);
          I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0);
+
          if (xf86IsEntityShared(pScrn->entityList[0])) {
 	    ScrnInfoPtr pScrn2;
             I830Ptr pI8302;
 
-            if (IsPrimary(pScrn)) {
+            if (I830IsPrimary(pScrn)) {
 	       pScrn2 = pI830->entityPrivate->pScrn_2;
                pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
             } else {
@@ -5907,8 +6388,16 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
                pI8302 = I830PTR(pI830->entityPrivate->pScrn_1);
             }
 
+            if (pScrn2->pScreen == pCursorScreen)
+               miPointerPosition(&x, &y);
+
+            pI8302->currentMode = NULL;
             I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0);
             I830BIOSAdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0);
+
+ 	    (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE);
+ 	    (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE);
+
             if (pScrn2->pScreen == pCursorScreen) {
                int sigstate = xf86BlockSIGIO ();
                miPointerWarpCursor(pScrn2->pScreen,x,y);
@@ -5917,12 +6406,16 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
                xf86UnblockSIGIO (sigstate);
                if (pI8302->CursorInfoRec && !pI8302->SWCursor && pI8302->cursorOn) {
                   pI8302->CursorInfoRec->HideCursor(pScrn);
+	          xf86SetCursor(pScrn2->pScreen, pI830->pCurs, x, y);
                   pI8302->CursorInfoRec->ShowCursor(pScrn);
                   pI8302->cursorOn = TRUE;
                }
             }
 	 }
 
+ 	 (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, FALSE);
+ 	 (*pScrn->EnableDisableFBAccess) (pScrn->pScreen->myNum, TRUE);
+
          if (pScrn->pScreen == pCursorScreen) {
             int sigstate = xf86BlockSIGIO ();
             miPointerWarpCursor(pScrn->pScreen,x,y);
@@ -5931,12 +6424,14 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
             xf86UnblockSIGIO (sigstate);
             if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) {
                pI830->CursorInfoRec->HideCursor(pScrn);
+	       xf86SetCursor(pScrn->pScreen, pI830->pCurs, x, y);
                pI830->CursorInfoRec->ShowCursor(pScrn);
                pI830->cursorOn = TRUE;
             }
          }
       }
    }
+
   
    return 1000;
 }
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 38b84c0..9b0b2e8 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -54,13 +54,35 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "config.h"
 #endif
 
+#include <string.h>
+
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "xf86_OSproc.h"
 
 #include "i830.h"
 #include "i810_reg.h"
 
+static int nextTile = 0;
+static unsigned int tileGeneration = -1;
+
+#ifndef ALLOCATE_ALL_BIOSMEM
+#define ALLOCATE_ALL_BIOSMEM 1
+#endif
+
+static unsigned long
+GetBestTileAlignment(unsigned long size)
+{
+   unsigned long i;
+
+   for (i = KB(512); i < size; i <<= 1)
+      ;
+
+   if (i > MB(64))
+      i = MB(64);
+
+   return i;
+}
+
 /*
  * Allocate memory from the given pool.  Grow the pool if needed and if
  * possible.
@@ -212,6 +234,59 @@ AllocFromAGP(ScrnInfoPtr pScrn, I830MemR
    return size;
 }
 
+void
+I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   if (!range || range->Size == 0)
+      return;
+
+   if (range->Key != -1)
+      xf86DeallocateGARTMemory(pScrn->scrnIndex, range->Key);
+
+   if (range->Pool) {
+      /* 
+       * This code essentially resets what I830DoPoolAllocation() did.
+       * And if things are freed in the wrong order this can break wildly!
+       * USE CAUTION when changing anything here...
+       */
+      I830MemPool *Pool = range->Pool;
+      if (pI830->overrideBIOSMemSize &&
+          pI830->BIOSMemorySize > pI830->StolenMemory.Size) 
+         Pool->Total.End = pI830->BIOSMemorySize;
+      else 
+         Pool->Total.End = pI830->StolenMemory.End;
+
+      if (pI830->StolenOnly)
+         Pool->Free.End += range->Size;
+      else
+         Pool->Free.End = Pool->Total.End;
+
+      if (Pool->Free.End < Pool->Free.Start) {
+         Pool->Free.End = Pool->Free.Start;
+      }
+
+      Pool->Free.Size = Pool->Free.End - Pool->Free.Start;
+      Pool->Total.Size = Pool->Total.End - Pool->Total.Start;
+
+      if (!pI830->StolenOnly) {
+         pI830->FreeMemory -= Pool->Free.Size;
+         pI830->MemoryAperture.Start -= (range->Size - Pool->Free.Size);
+         pI830->MemoryAperture.Size += (range->Size - Pool->Free.Size);
+      }
+   } else {
+      if (range->Alignment == GTT_PAGE_SIZE)
+         pI830->MemoryAperture.End = range->End;
+      else
+         pI830->MemoryAperture.End = range->End - range->Size + range->Alignment;
+      pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
+   }
+
+   if (!pI830->StolenOnly)
+      pI830->FreeMemory += range->Size;
+   pI830->allocatedMemory -= range->Size;
+}
 
 unsigned long
 I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
@@ -345,25 +420,30 @@ AllocateOverlay(ScrnInfoPtr pScrn, int f
 		     alloced / 1024, pI830->OverlayMem->Start,
 		     pI830->OverlayMem->Physical);
    }
-   return TRUE;
-}
-#endif
 
-static unsigned long
-GetFreeSpace(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   unsigned long extra = 0;
+   /* Clear linearmem info */
+   if (pI830->LinearAlloc) {
+      memset(&(pI830->LinearMem), 0, sizeof(I830MemRange));
+      pI830->LinearMem.Key = -1;
 
-   /* First check for free space in StolenPool. */
-   if (pI830->StolenPool.Free.Size > 0)
-      extra = pI830->StolenPool.Free.Size;
-   /* Next check for unallocated space. */
-   if (pI830->FreeMemory > 0)
-      extra += pI830->FreeMemory;
+      size = KB(pI830->LinearAlloc);
+      alloced = I830AllocVidMem(pScrn, &(pI830->LinearMem), &(pI830->StolenPool),
+				size, GTT_PAGE_SIZE,
+				FROM_ANYWHERE | ALLOCATE_AT_TOP);
+      if (alloced < size) {
+         if (!dryrun) {
+            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate linear buffer space\n");
+         }
+      } else
+         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		    "%sAllocated %ld kB for the linear buffer at 0x%lx\n", s,
+		    alloced / 1024, pI830->LinearMem.Start);
+   }
 
-   return extra;
+   return TRUE;
 }
+#endif
 
 static Bool
 IsTileable(int pitch)
@@ -386,6 +466,150 @@ IsTileable(int pitch)
    }
 }
 
+Bool
+I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, int flags)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   unsigned long size, alloced;
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   int align;
+   Bool tileable;
+   int lines;
+   int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
+
+   /* Rotated Buffer */
+   memset(&(pI830->RotatedMem), 0, sizeof(I830MemRange));
+   pI830->RotatedMem.Key = -1;
+   tileable = !(flags & ALLOC_NO_TILING) &&
+	      IsTileable(pScrn->displayWidth * pI830->cpp);
+   if (tileable) {
+      /* Make the height a multiple of the tile height (16) */
+      lines = (height + 15) / 16 * 16;
+   } else {
+      lines = height;
+   }
+
+   size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
+   /*
+    * Try to allocate on the best tile-friendly boundaries.
+    */
+   alloced = 0;
+   if (tileable) {
+      align = GetBestTileAlignment(size);
+      for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) {
+	 alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem),
+				   &(pI830->StolenPool), size, align,
+				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
+				   ALIGN_BOTH_ENDS);
+	 if (alloced >= size)
+	    break;
+      }
+   }
+   if (alloced < size) {
+      /* Give up on trying to tile */
+      tileable = FALSE;
+      size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
+      align = GTT_PAGE_SIZE;
+      alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem),
+				&(pI830->StolenPool), size, align,
+				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+   }
+   if (alloced < size) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to allocate rotated buffer space.\n");
+      }
+      return FALSE;
+   }
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		  "%sAllocated %ld kB for the rotated buffer at 0x%lx.\n", s,
+		  alloced / 1024, pI830->RotatedMem.Start);
+   return TRUE;
+}
+
+Bool
+I830AllocateRotated2Buffer(ScrnInfoPtr pScrn, int flags)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   unsigned long size, alloced;
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   int align;
+   Bool tileable;
+   int lines;
+   I830EntPtr pI830Ent = pI830->entityPrivate;
+   I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2);
+   int height = (pI8302->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pI830Ent->pScrn_2->virtualY : pI830Ent->pScrn_2->virtualX;
+
+   /* Rotated Buffer */
+   memset(&(pI830->RotatedMem2), 0, sizeof(I830MemRange));
+   pI830->RotatedMem2.Key = -1;
+   tileable = !(flags & ALLOC_NO_TILING) &&
+	      IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp);
+   if (tileable) {
+      /* Make the height a multiple of the tile height (16) */
+      lines = (height + 15) / 16 * 16;
+   } else {
+      lines = height;
+   }
+
+   size = ROUND_TO_PAGE(pI830Ent->pScrn_2->displayWidth * lines * pI8302->cpp);
+   /*
+    * Try to allocate on the best tile-friendly boundaries.
+    */
+   alloced = 0;
+   if (tileable) {
+      align = GetBestTileAlignment(size);
+      for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) {
+	 alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem2),
+				   &(pI830->StolenPool), size, align,
+				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
+				   ALIGN_BOTH_ENDS);
+	 if (alloced >= size)
+	    break;
+      }
+   }
+   if (alloced < size) {
+      /* Give up on trying to tile */
+      tileable = FALSE;
+      size = ROUND_TO_PAGE(pI830Ent->pScrn_2->displayWidth * height * pI8302->cpp);
+      align = GTT_PAGE_SIZE;
+      alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem2),
+				&(pI830->StolenPool), size, align,
+				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+   }
+   if (alloced < size) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to allocate rotated2 buffer space.\n");
+      }
+      return FALSE;
+   }
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		  "%sAllocated %ld kB for the rotated2 buffer at 0x%lx.\n", s,
+		  alloced / 1024, pI830->RotatedMem2.Start);
+   return TRUE;
+}
+
+static unsigned long
+GetFreeSpace(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   unsigned long extra = 0;
+
+   /* First check for free space in StolenPool. */
+   if (pI830->StolenPool.Free.Size > 0)
+      extra = pI830->StolenPool.Free.Size;
+   /* Next check for unallocated space. */
+   if (pI830->FreeMemory > 0)
+      extra += pI830->FreeMemory;
+
+   return extra;
+}
+
 /*
  * Allocate memory for 2D operation.  This includes the (front) framebuffer,
  * ring buffer, scratch memory, HW cursor.
@@ -452,7 +676,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
          pI830->FbMemBox2.x1 = 0;
          pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth;
          pI830->FbMemBox2.y1 = 0;
-         pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY;
+         if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY)
+            pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualX;
+         else
+            pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY;
 
          /*
           * Calculate how much framebuffer memory to allocate.  For the
@@ -511,8 +738,12 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	    alignflags = 0;
          }
 
-         size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines);
+         if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY)
+            size = lineSize * (pI830Ent->pScrn_2->virtualX + cacheLines);
+         else 
+            size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines);
          size = ROUND_TO_PAGE(size);
+
          xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 		     "%sSecondary framebuffer allocation size: %ld kByte\n", s,
 		     size / 1024);
@@ -537,7 +768,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
       pI830->FbMemBox.x1 = 0;
       pI830->FbMemBox.x2 = pScrn->displayWidth;
       pI830->FbMemBox.y1 = 0;
-      pI830->FbMemBox.y2 = pScrn->virtualY;
+      if (pScrn->virtualX > pScrn->virtualY)
+         pI830->FbMemBox.y2 = pScrn->virtualX;
+      else
+         pI830->FbMemBox.y2 = pScrn->virtualY;
 
       /*
        * Calculate how much framebuffer memory to allocate.  For the
@@ -596,8 +830,12 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	 alignflags = 0;
       }
 
-      size = lineSize * (pScrn->virtualY + cacheLines);
+      if (pScrn->virtualX > pScrn->virtualY)
+         size = lineSize * (pScrn->virtualX + cacheLines);
+      else 
+         size = lineSize * (pScrn->virtualY + cacheLines);
       size = ROUND_TO_PAGE(size);
+
       xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 		     "%sInitial framebuffer allocation size: %ld kByte\n", s,
 		     size / 1024);
@@ -633,7 +871,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
       maxFb = ROUND_DOWN_TO(maxFb, lineSize);
       if (maxFb > lineSize * MAX_DISPLAY_HEIGHT)
 	 maxFb = lineSize * MAX_DISPLAY_HEIGHT;
-      if (maxFb > pI830->FrontBuffer.Size) {
+      if (0/*maxFb > pI830->FrontBuffer.Size*/) {
 	 unsigned long oldsize;
 	 /*
 	  * Sanity check -- the fb should be the last thing allocated at
@@ -699,8 +937,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
     */
    if (!dryrun) {
       memset(&(pI830->Dummy), 0, sizeof(pI830->Dummy));
-      pI830->Dummy.Key =
-	   xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
+      pI830->Dummy.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
       pI830->Dummy.Offset = 0;
    }
 #endif
@@ -827,13 +1064,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	      alloced / 1024, pI830->Scratch2.Start);
       }
    }
+
    return TRUE;
 }
 
-#ifndef ALLOCATE_ALL_BIOSMEM
-#define ALLOCATE_ALL_BIOSMEM 1
-#endif
-
 void
 I830ResetAllocations(ScrnInfoPtr pScrn, const int flags)
 {
@@ -870,20 +1104,6 @@ I830GetExcessMemoryAllocations(ScrnInfoP
 }
 
 #ifdef XF86DRI
-static unsigned long
-GetBestTileAlignment(unsigned long size)
-{
-   unsigned long i;
-
-   for (i = KB(512); i < size; i <<= 1)
-      ;
-
-   if (i > MB(64))
-      i = MB(64);
-
-   return i;
-}
-
 static unsigned int
 myLog2(unsigned int n)
 {
@@ -897,18 +1117,16 @@ myLog2(unsigned int n)
 }
 
 Bool
-I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags)
+I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    unsigned long size, alloced, align = 0;
-   int i;
    Bool tileable;
    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
    int verbosity = dryrun ? 4 : 1;
    const char *s = dryrun ? "[dryrun] " : "";
    int lines;
-
-   DPRINTF(PFX, "I830Allocate3DMemory\n");
+   int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
 
    /* Back Buffer */
    memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
@@ -917,9 +1135,9 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, 
 	      IsTileable(pScrn->displayWidth * pI830->cpp);
    if (tileable) {
       /* Make the height a multiple of the tile height (16) */
-      lines = (pScrn->virtualY + 15) / 16 * 16;
+      lines = (height + 15) / 16 * 16;
    } else {
-      lines = pScrn->virtualY;
+      lines = height;
    }
 
    size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
@@ -941,7 +1159,7 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, 
    if (alloced < size) {
       /* Give up on trying to tile */
       tileable = FALSE;
-      size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp);
+      size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
       align = GTT_PAGE_SIZE;
       alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
 				&(pI830->StolenPool), size, align,
@@ -958,16 +1176,41 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, 
 		  "%sAllocated %ld kB for the back buffer at 0x%lx.\n", s,
 		  alloced / 1024, pI830->BackBuffer.Start);
 
+   return TRUE;
+}
+
+Bool
+I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   unsigned long size, alloced, align = 0;
+   Bool tileable;
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   int lines;
+   int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
+
    /* Depth Buffer -- same size as the back buffer */
    memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
    pI830->DepthBuffer.Key = -1;
+   tileable = !(flags & ALLOC_NO_TILING) &&
+	      IsTileable(pScrn->displayWidth * pI830->cpp);
+   if (tileable) {
+      /* Make the height a multiple of the tile height (16) */
+      lines = (height + 15) / 16 * 16;
+   } else {
+      lines = height;
+   }
+
+   size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
    /*
     * Try to allocate on the best tile-friendly boundaries.
     */
    alloced = 0;
    if (tileable) {
-      /* Start with the previous align value. */
-      for (; align >= KB(512); align >>= 1) {
+      align = GetBestTileAlignment(size);
+      for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) {
 	 alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
 				   &(pI830->StolenPool), size, align,
 				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
@@ -979,7 +1222,7 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, 
    if (alloced < size) {
       /* Give up on trying to tile */
       tileable = FALSE;
-      size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp);
+      size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
       align = GTT_PAGE_SIZE;
       alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
 				&(pI830->StolenPool), size, align,
@@ -996,24 +1239,18 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, 
 		  "%sAllocated %ld kB for the depth buffer at 0x%lx.\n", s,
 		  alloced / 1024, pI830->DepthBuffer.Start);
 
-   /* Space for logical context.  32k is fine for right now. */
-   memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
-   pI830->ContextMem.Key = -1;
-   size = KB(32);
-   alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem),
-			     &(pI830->StolenPool), size, GTT_PAGE_SIZE,
-			     flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "Failed to allocate logical context space.\n");
-      }
-      return FALSE;
-   }
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sAllocated %ld kB for the logical context at 0x%lx.\n", s,
-		  alloced / 1024, pI830->ContextMem.Start);
+   return TRUE;
+}
 
+Bool
+I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   unsigned long size, alloced;
+   int i;
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
 
    /* Allocate the remaining space for textures. */
    memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
@@ -1056,6 +1293,47 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, 
 
    return TRUE;
 }
+
+Bool
+I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   unsigned long size, alloced;
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+
+   DPRINTF(PFX, "I830Allocate3DMemory\n");
+
+   /* Space for logical context.  32k is fine for right now. */
+   memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
+   pI830->ContextMem.Key = -1;
+   size = KB(32);
+   alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem),
+			     &(pI830->StolenPool), size, GTT_PAGE_SIZE,
+			     flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+   if (alloced < size) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to allocate logical context space.\n");
+      }
+      return FALSE;
+   }
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		  "%sAllocated %ld kB for the logical context at 0x%lx.\n", s,
+		  alloced / 1024, pI830->ContextMem.Start);
+
+   if (!I830AllocateBackBuffer(pScrn, flags))
+      return FALSE;
+
+   if (!I830AllocateDepthBuffer(pScrn, flags))
+      return FALSE;
+
+   if (!I830AllocateTextureMemory(pScrn, flags))
+      return FALSE;
+
+   return TRUE;
+}
 #endif
 
 /* Allocate pool space that isn't pre-allocated */
@@ -1083,9 +1361,8 @@ I830DoPoolAllocation(ScrnInfoPtr pScrn, 
 
    if (pool->Total.Size > pool->Fixed.Size) {
       pool->Allocated.Size = pool->Total.Size - pool->Fixed.Size;
-      pool->Allocated.Key =
-	    xf86AllocateGARTMemory(pScrn->scrnIndex, pool->Allocated.Size,
-				   0, NULL);
+      pool->Allocated.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, 
+				   pool->Allocated.Size, 0, NULL);
       if (pool->Allocated.Key == -1) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pool allocation failed\n");
 	 return FALSE;
@@ -1119,8 +1396,8 @@ static unsigned long topOfMem = 0;
 #define PACK_RANGES 0
 #define POOL_RANGES 0
 
-static Bool
-FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem)
+Bool
+I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem)
 {
 #if POOL_RANGES
    I830Ptr pI830 = I830PTR(pScrn);
@@ -1190,26 +1467,28 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
 
    topOfMem = pI830->StolenPool.Total.End;
    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-      FixOffset(pScrn, &(pI830->FrontBuffer2));
-   FixOffset(pScrn, &(pI830->FrontBuffer));
-   FixOffset(pScrn, pI830->CursorMem);
-   FixOffset(pScrn, pI830->CursorMemARGB);
-   FixOffset(pScrn, &(pI830->LpRing->mem));
-   FixOffset(pScrn, &(pI830->Scratch));
+      I830FixOffset(pScrn, &(pI830->FrontBuffer2));
+   I830FixOffset(pScrn, &(pI830->FrontBuffer));
+   I830FixOffset(pScrn, pI830->CursorMem);
+   I830FixOffset(pScrn, pI830->CursorMemARGB);
+   I830FixOffset(pScrn, &(pI830->LpRing->mem));
+   I830FixOffset(pScrn, &(pI830->Scratch));
    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-      FixOffset(pScrn, &(pI830->Scratch2));
+      I830FixOffset(pScrn, &(pI830->Scratch2));
 #ifdef I830_XV
    if (pI830->XvEnabled) {
-      FixOffset(pScrn, pI830->OverlayMem);
+      I830FixOffset(pScrn, pI830->OverlayMem);
+      if (pI830->LinearAlloc)
+         I830FixOffset(pScrn, &(pI830->LinearMem));
    }
 #endif
 #ifdef XF86DRI
    if (pI830->directRenderingEnabled) {
-      FixOffset(pScrn, &(pI830->BackBuffer));
-      FixOffset(pScrn, &(pI830->DepthBuffer));
-      FixOffset(pScrn, &(pI830->ContextMem));
+      I830FixOffset(pScrn, &(pI830->ContextMem));
+      I830FixOffset(pScrn, &(pI830->BackBuffer));
+      I830FixOffset(pScrn, &(pI830->DepthBuffer));
 #ifdef NOTTM
-      FixOffset(pScrn, &(pI830->TexMem));
+      I830FixOffset(pScrn, &(pI830->TexMem));
 #endif
    }
 #endif
@@ -1238,34 +1517,34 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
 	   nr, start, pitch, size / 1024);
 
    if (nr < 0 || nr > 7) {
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "SetFence: fence %d out of range\n",nr);
       return;
    }
 
    i830Reg->Fence[nr] = 0;
 
-   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+   if (IS_I9XX(pI830))
    	fence_mask = ~I915G_FENCE_START_MASK;
    else
    	fence_mask = ~I830_FENCE_START_MASK;
 
    if (start & fence_mask) {
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "SetFence: %d: start (0x%08x) is not %s aligned\n",
-		 nr, start, (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) ? "1MB" : "512k");
+		 nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
       return;
    }
 
    if (start % size) {
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
 		 nr, start, size / 1024);
       return;
    }
 
    if (pitch & 127) {
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
 		 nr, pitch);
       return;
@@ -1273,7 +1552,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
 
    val = (start | FENCE_X_MAJOR | FENCE_VALID);
 
-   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+   if (IS_I9XX(pI830)) {
    	switch (size) {
 	   case MB(1):
       		val |= I915G_FENCE_SIZE_1M;
@@ -1297,7 +1576,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
       		val |= I915G_FENCE_SIZE_64M;
       		break;
    	   default:
-      		xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
       		return;
    	}
@@ -1328,13 +1607,13 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
       		val |= FENCE_SIZE_64M;
       		break;
    	   default:
-      		xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
       		return;
    	}
    }
 
-   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+   if (IS_I9XX(pI830))
 	fence_pitch = pitch / 512;
    else
 	fence_pitch = pitch / 128;
@@ -1362,7 +1641,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsi
       val |= FENCE_PITCH_64;
       break;
    default:
-      xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
+      xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
       return;
    }
@@ -1375,8 +1654,6 @@ MakeTiles(ScrnInfoPtr pScrn, I830MemRang
 {
    I830Ptr pI830 = I830PTR(pScrn);
    int pitch, ntiles, i;
-   static int nextTile = 0;
-   static unsigned int tileGeneration = -1;
 
 #if 0
    /* Hack to "improve" the alignment of the front buffer.
@@ -1411,6 +1688,14 @@ void
 I830SetupMemoryTiling(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+   int i;
+
+   /* Clear out */
+   for (i = 0; i < 8; i++)
+      pI830->ModeReg.Fence[i] = 0;
+
+   nextTile = 0;
+   tileGeneration = -1;
 
    /* We currently only attempt to tile the back and depth buffers. */
    if (!pI830->directRenderingEnabled)
@@ -1464,10 +1749,31 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
 		    "Activating tiled memory for the depth buffer.\n");
       } else {
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "MakeTiles failed for the back buffer.\n");
+		    "MakeTiles failed for the depth buffer.\n");
       }
    }
 	
+   if (pI830->RotatedMem.Alignment >= KB(512)) {
+      if (MakeTiles(pScrn, &(pI830->RotatedMem))) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Activating tiled memory for the rotated buffer.\n");
+      } else {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "MakeTiles failed for the rotated buffer.\n");
+      }
+   }
+
+#if 0
+   if (pI830->RotatedMem2.Alignment >= KB(512)) {
+      if (MakeTiles(pScrn, &(pI830->RotatedMem2))) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Activating tiled memory for the rotated2 buffer.\n");
+      } else {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "MakeTiles failed for the rotated buffer.\n");
+      }
+   }
+#endif
 }
 #endif /* XF86DRI */
 
@@ -1484,12 +1790,12 @@ BindMemRange(ScrnInfoPtr pScrn, I830MemR
 }
 
 Bool
-I830BindGARTMemory(ScrnInfoPtr pScrn)
+I830BindAGPMemory(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
    DPRINTF(PFX,
-	   "I830BindGARTMemory: StolenOnly is %s, pI830->GttBound is %s\n",
+	   "I830BindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n",
 	   BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
 
    if (pI830->StolenOnly == TRUE)
@@ -1523,17 +1829,29 @@ I830BindGARTMemory(ScrnInfoPtr pScrn)
          if (!BindMemRange(pScrn, &(pI830->Scratch2)))
 	    return FALSE;
 #ifdef I830_XV
-      if (!BindMemRange(pScrn, pI830->OverlayMem))
-	 return FALSE;
+      if (pI830->XvEnabled) {
+         if (!BindMemRange(pScrn, pI830->OverlayMem))
+	    return FALSE;
+         if (pI830->LinearAlloc)
+            if (!BindMemRange(pScrn, &(pI830->LinearMem)))
+	       return FALSE;
+      }
 #endif
+      if (pI830->RotatedMem.Start)
+         if (!BindMemRange(pScrn, &(pI830->RotatedMem)))
+	    return FALSE;
+      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2 &&
+	  pI830->RotatedMem2.Start)
+         if (!BindMemRange(pScrn, &(pI830->RotatedMem2)))
+	    return FALSE;
 #ifdef XF86DRI
       if (pI830->directRenderingEnabled) {
+	 if (!BindMemRange(pScrn, &(pI830->ContextMem)))
+	    return FALSE;
 	 if (!BindMemRange(pScrn, &(pI830->BackBuffer)))
 	    return FALSE;
 	 if (!BindMemRange(pScrn, &(pI830->DepthBuffer)))
 	    return FALSE;
-	 if (!BindMemRange(pScrn, &(pI830->ContextMem)))
-	    return FALSE;
 #ifdef NOTTM
 	 if (!BindMemRange(pScrn, &(pI830->TexMem)))
 	    return FALSE;
@@ -1560,12 +1878,12 @@ UnbindMemRange(ScrnInfoPtr pScrn, I830Me
 
 
 Bool
-I830UnbindGARTMemory(ScrnInfoPtr pScrn)
+I830UnbindAGPMemory(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
    DPRINTF(PFX,
-	   "I830UnbindGARTMemory: StolenOnly is %s, pI830->GttBound is %s\n",
+	   "I830UnbindAGPMemory: StolenOnly is %s, pI830->GttBound is %s\n",
 	   BOOLTOSTRING(pI830->StolenOnly), BOOLTOSTRING(pI830->GttBound));
 
    if (pI830->StolenOnly == TRUE)
@@ -1597,17 +1915,29 @@ I830UnbindGARTMemory(ScrnInfoPtr pScrn)
          if (!UnbindMemRange(pScrn, &(pI830->Scratch2)))
 	    return FALSE;
 #ifdef I830_XV
-      if (!UnbindMemRange(pScrn, pI830->OverlayMem))
-	 return FALSE;
+      if (pI830->XvEnabled) {
+         if (!UnbindMemRange(pScrn, pI830->OverlayMem))
+	    return FALSE;
+         if (pI830->LinearAlloc)
+            if (!UnbindMemRange(pScrn, &(pI830->LinearMem)))
+   	       return FALSE;
+      }
 #endif
+      if (pI830->RotatedMem.Start)
+         if (!UnbindMemRange(pScrn, &(pI830->RotatedMem)))
+	    return FALSE;
+      if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2 &&
+	  pI830->RotatedMem2.Start)
+         if (!UnbindMemRange(pScrn, &(pI830->RotatedMem2)))
+	    return FALSE;
 #ifdef XF86DRI
       if (pI830->directRenderingEnabled) {
+	 if (!UnbindMemRange(pScrn, &(pI830->ContextMem)))
+	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &(pI830->BackBuffer)))
 	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer)))
 	    return FALSE;
-	 if (!UnbindMemRange(pScrn, &(pI830->ContextMem)))
-	    return FALSE;
 #ifdef NOTTM
 	 if (!UnbindMemRange(pScrn, &(pI830->TexMem)))
 	    return FALSE;
@@ -1627,7 +1957,7 @@ long
 I830CheckAvailableMemory(ScrnInfoPtr pScrn)
 {
    AgpInfoPtr agpinf;
-   long maxPages;
+   int maxPages;
 
    if (!xf86AgpGARTSupported() ||
        !xf86AcquireGART(pScrn->scrnIndex) ||
@@ -1636,9 +1966,8 @@ I830CheckAvailableMemory(ScrnInfoPtr pSc
       return -1;
 
    maxPages = agpinf->totalPages - agpinf->usedPages;
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, 
-   	"Checking Available AGP Memory: %ld kB available (total %ld kB, used %ld kB)\n",
-	maxPages * 4, agpinf->totalPages * 4, agpinf->usedPages * 4);
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "%s: %d kB available\n",
+		  "I830CheckAvailableMemory", maxPages * 4);
 
    return maxPages * 4;
 }
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 457b583..97e40e0 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -38,8 +38,10 @@
 #include "config.h"
 #endif
 
+#include <stdio.h>
+#include <string.h>
+
 #include "xf86.h"
-#include "xf86_ansic.h"
 #include "vbe.h"
 #include "vbeModes.h"
 #include "i830.h"
@@ -346,7 +348,7 @@ I830GetGTF (int h_pixels, int v_lines, f
     m->Clock   = (int)(pixel_freq * 1000);
     m->SynthClock   = m->Clock;
     m->HSync = h_freq;
-    m->VRefresh = freq;
+    m->VRefresh = v_frame_rate /* freq */;
 
     snprintf(modename, sizeof(modename), "%dx%d", m->HDisplay,m->VDisplay);
     m->name = xnfstrdup(modename);
@@ -512,7 +514,7 @@ CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr 
     xf86ErrorFVerb(DEBUG_VERB,
 	    "	WinBSegment: 0x%x\n", mode->WinBSegment);
     xf86ErrorFVerb(DEBUG_VERB,
-	    "	WinFuncPtr: 0x%lx\n", mode->WinFuncPtr);
+		   "	WinFuncPtr: 0x%lx\n", (unsigned long)mode->WinFuncPtr);
     xf86ErrorFVerb(DEBUG_VERB,
 	    "	BytesPerScanline: %d\n", mode->BytesPerScanline);
     xf86ErrorFVerb(DEBUG_VERB,
@@ -555,7 +557,8 @@ CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr 
 	    "	DirectColorModeInfo: %d\n", mode->DirectColorModeInfo);
     if (major >= 2) {
 	xf86ErrorFVerb(DEBUG_VERB,
-		"	PhysBasePtr: 0x%lx\n", mode->PhysBasePtr);
+		       "	PhysBasePtr: 0x%lx\n", 
+		       (unsigned long)mode->PhysBasePtr);
 	if (major >= 3) {
 	    xf86ErrorFVerb(DEBUG_VERB,
 		    "	LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine);
@@ -580,7 +583,8 @@ CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr 
 	    xf86ErrorFVerb(DEBUG_VERB,
 		    "	LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition);
 	    xf86ErrorFVerb(DEBUG_VERB,
-		    "	MaxPixelClock: %ld\n", mode->MaxPixelClock);
+			   "	MaxPixelClock: %ld\n", (unsigned long)
+			   mode->MaxPixelClock);
 	}
     }
 
diff --git a/src/i830_randr.c b/src/i830_randr.c
new file mode 100644
index 0000000..0311f2b
--- /dev/null
+++ b/src/i830_randr.c
@@ -0,0 +1,355 @@
+/* $XdotOrg: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.3 2004/07/30 21:53:09 eich Exp $ */
+/*
+ * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.7tsi Exp $
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "xf86.h"
+#include "os.h"
+#include "mibank.h"
+#include "globals.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86DDC.h"
+#include "mipointer.h"
+#include "windowstr.h"
+#include <randrstr.h>
+
+#include "i830.h"
+
+typedef struct _i830RandRInfo {
+    int				    virtualX;
+    int				    virtualY;
+    int				    mmWidth;
+    int				    mmHeight;
+    int				    maxX;
+    int				    maxY;
+    Rotation			    rotation; /* current mode */
+    Rotation                        supported_rotations; /* driver supported */
+} XF86RandRInfoRec, *XF86RandRInfoPtr;
+    
+static int	    i830RandRIndex;
+static int	    i830RandRGeneration;
+
+#define XF86RANDRINFO(p)    ((XF86RandRInfoPtr) (p)->devPrivates[i830RandRIndex].ptr)
+
+static int
+I830RandRModeRefresh (DisplayModePtr mode)
+{
+    if (mode->VRefresh)
+	return (int) (mode->VRefresh + 0.5);
+    else
+	return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
+}
+
+static Bool
+I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+{
+    RRScreenSizePtr	    pSize;
+    ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
+    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
+    DisplayModePtr	    mode;
+    int			    refresh0 = 60;
+    int			    maxX = 0, maxY = 0;
+    
+    *rotations = randrp->supported_rotations;
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1) 
+    {
+	randrp->virtualX = scrp->virtualX;
+	randrp->virtualY = scrp->virtualY;
+    }
+
+    for (mode = scrp->modes; ; mode = mode->next)
+    {
+	int refresh = I830RandRModeRefresh (mode);
+	if (randrp->maxX == 0 || randrp->maxY == 0)
+	{
+		if (maxX < mode->HDisplay)
+			maxX = mode->HDisplay;
+		if (maxY < mode->VDisplay)
+			maxY = mode->VDisplay;
+	}
+	if (mode == scrp->modes)
+	    refresh0 = refresh;
+	pSize = RRRegisterSize (pScreen,
+				mode->HDisplay, mode->VDisplay,
+				randrp->mmWidth, randrp->mmHeight);
+	if (!pSize)
+	    return FALSE;
+	RRRegisterRate (pScreen, pSize, refresh);
+	if (mode == scrp->currentMode &&
+	    mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY)
+	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
+	if (mode->next == scrp->modes)
+	    break;
+    }
+
+    if (randrp->maxX == 0 || randrp->maxY == 0)
+    {
+	randrp->maxX = maxX;
+	randrp->maxY = maxY;
+    }
+   
+    if (scrp->currentMode->HDisplay != randrp->virtualX ||
+	scrp->currentMode->VDisplay != randrp->virtualY)
+    {
+	mode = scrp->modes;
+	pSize = RRRegisterSize (pScreen,
+				randrp->virtualX, randrp->virtualY,
+				randrp->mmWidth,
+				randrp->mmHeight);
+	if (!pSize)
+	    return FALSE;
+	RRRegisterRate (pScreen, pSize, refresh0);
+	if (scrp->virtualX == randrp->virtualX && 
+	    scrp->virtualY == randrp->virtualY)
+	{
+	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
+	}
+    }
+
+    return TRUE;
+}
+
+static Bool
+I830RandRSetMode (ScreenPtr	    pScreen,
+		  DisplayModePtr    mode,
+		  Bool		    useVirtual,
+		  int		    mmWidth,
+		  int		    mmHeight)
+{
+    ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    int			oldWidth = pScreen->width;
+    int			oldHeight = pScreen->height;
+    int			oldmmWidth = pScreen->mmWidth;
+    int			oldmmHeight = pScreen->mmHeight;
+    WindowPtr		pRoot = WindowTable[pScreen->myNum];
+    DisplayModePtr      currentMode = NULL;
+    Bool 		ret = TRUE;
+    PixmapPtr 		pspix = NULL;
+    
+    if (pRoot)
+	(*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+    if (useVirtual)
+    {
+	scrp->virtualX = randrp->virtualX;
+	scrp->virtualY = randrp->virtualY;
+    }
+    else
+    {
+	scrp->virtualX = mode->HDisplay;
+	scrp->virtualY = mode->VDisplay;
+    }
+    if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
+    {
+	/* If the screen is rotated 90 or 270 degrees, swap the sizes. */
+	pScreen->width = scrp->virtualY;
+	pScreen->height = scrp->virtualX;
+	pScreen->mmWidth = mmHeight;
+	pScreen->mmHeight = mmWidth;
+    }
+    else
+    {
+	pScreen->width = scrp->virtualX;
+	pScreen->height = scrp->virtualY;
+	pScreen->mmWidth = mmWidth;
+	pScreen->mmHeight = mmHeight;
+    }
+    if (scrp->currentMode == mode) {
+        /* Save current mode */
+        currentMode = scrp->currentMode;
+        /* Reset, just so we ensure the drivers SwitchMode is called */
+        scrp->currentMode = NULL;
+    }
+    /*
+     * We know that if the driver failed to SwitchMode to the rotated
+     * version, then it should revert back to it's prior mode.
+     */
+    if (!xf86SwitchMode (pScreen, mode))
+    {
+        ret = FALSE;
+	scrp->virtualX = pScreen->width = oldWidth;
+	scrp->virtualY = pScreen->height = oldHeight;
+	pScreen->mmWidth = oldmmWidth;
+	pScreen->mmHeight = oldmmHeight;
+        scrp->currentMode = currentMode;
+    }
+    /*
+     * Get the new Screen pixmap ptr as SwitchMode might have called
+     * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back...
+     * Unfortunately.
+     */
+    pspix = (*pScreen->GetScreenPixmap) (pScreen);
+    if (pspix->devPrivate.ptr)
+       scrp->pixmapPrivate = pspix->devPrivate;
+    
+    /*
+     * Make sure the layout is correct
+     */
+    xf86ReconfigureLayout();
+
+    /*
+     * Make sure the whole screen is visible
+     */
+    xf86SetViewport (pScreen, pScreen->width, pScreen->height);
+    xf86SetViewport (pScreen, 0, 0);
+    if (pRoot)
+	(*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+    return ret;
+}
+
+Bool
+I830RandRSetConfig (ScreenPtr		pScreen,
+		    Rotation		rotation,
+		    int			rate,
+		    RRScreenSizePtr	pSize)
+{
+    ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
+    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
+    DisplayModePtr	    mode;
+    int			    px, py;
+    Bool		    useVirtual = FALSE;
+    int			    maxX = 0, maxY = 0;
+    Rotation		    oldRotation = randrp->rotation;
+
+    randrp->rotation = rotation;
+
+    if (randrp->virtualX == -1 || randrp->virtualY == -1) 
+    {
+	randrp->virtualX = scrp->virtualX;
+	randrp->virtualY = scrp->virtualY;
+    }
+
+    miPointerPosition (&px, &py);
+    for (mode = scrp->modes; ; mode = mode->next)
+    {
+	if (randrp->maxX == 0 || randrp->maxY == 0)
+	{
+		if (maxX < mode->HDisplay)
+			maxX = mode->HDisplay;
+		if (maxY < mode->VDisplay)
+			maxY = mode->VDisplay;
+	}
+	if (mode->HDisplay == pSize->width && 
+	    mode->VDisplay == pSize->height &&
+	    (rate == 0 || I830RandRModeRefresh (mode) == rate))
+	    break;
+	if (mode->next == scrp->modes)
+	{
+	    if (pSize->width == randrp->virtualX &&
+		pSize->height == randrp->virtualY)
+	    {
+		mode = scrp->modes;
+		useVirtual = TRUE;
+		break;
+	    }
+    	    if (randrp->maxX == 0 || randrp->maxY == 0)
+    	    {
+		randrp->maxX = maxX;
+		randrp->maxY = maxY;
+    	    }
+	    return FALSE;
+	}
+    }
+
+    if (randrp->maxX == 0 || randrp->maxY == 0)
+    {
+	randrp->maxX = maxX;
+	randrp->maxY = maxY;
+    }
+
+    if (!I830RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) {
+        randrp->rotation = oldRotation;
+	return FALSE;
+    }
+
+    /*
+     * Move the cursor back where it belongs; SwitchMode repositions it
+     */
+    if (pScreen == miPointerCurrentScreen ())
+    {
+        px = (px >= pScreen->width ? (pScreen->width - 1) : px);
+        py = (py >= pScreen->height ? (pScreen->height - 1) : py);
+
+	xf86SetViewport(pScreen, px, py);
+
+	(*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
+    }
+
+    return TRUE;
+}
+
+Rotation
+I830GetRotation(ScreenPtr pScreen)
+{
+    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
+
+    return randrp->rotation;
+}
+
+Bool
+I830RandRInit (ScreenPtr    pScreen, int rotation)
+{
+    rrScrPrivPtr	rp;
+    XF86RandRInfoPtr	randrp;
+    
+#ifdef PANORAMIX
+    /* XXX disable RandR when using Xinerama */
+    if (!noPanoramiXExtension)
+	return TRUE;
+#endif
+    if (i830RandRGeneration != serverGeneration)
+    {
+	i830RandRIndex = AllocateScreenPrivateIndex();
+	i830RandRGeneration = serverGeneration;
+    }
+    
+    randrp = xalloc (sizeof (XF86RandRInfoRec));
+    if (!randrp)
+	return FALSE;
+			
+    if (!RRScreenInit(pScreen))
+    {
+	xfree (randrp);
+	return FALSE;
+    }
+    rp = rrGetScrPriv(pScreen);
+    rp->rrGetInfo = I830RandRGetInfo;
+    rp->rrSetConfig = I830RandRSetConfig;
+
+    randrp->virtualX = -1;
+    randrp->virtualY = -1;
+    randrp->mmWidth = pScreen->mmWidth;
+    randrp->mmHeight = pScreen->mmHeight;
+    
+    randrp->rotation = RR_Rotate_0; /* initial rotated mode */
+
+    randrp->supported_rotations = rotation;
+
+    randrp->maxX = randrp->maxY = 0;
+
+    pScreen->devPrivates[i830RandRIndex].ptr = randrp;
+
+    return TRUE;
+}
diff --git a/src/i830_reg.h b/src/i830_reg.h
new file mode 100644
index 0000000..be12e76
--- /dev/null
+++ b/src/i830_reg.h
@@ -0,0 +1,637 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#ifndef _I830_REG_H_
+#define _I830_REG_H_
+
+#define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
+
+#define _3DSTATE_AA_CMD			(CMD_3D | (0x06<<24))
+#define AA_LINE_ECAAR_WIDTH_ENABLE	(1<<16)
+#define AA_LINE_ECAAR_WIDTH_0_5 	0
+#define AA_LINE_ECAAR_WIDTH_1_0		(1<<14)
+#define AA_LINE_ECAAR_WIDTH_2_0 	(2<<14)
+#define AA_LINE_ECAAR_WIDTH_4_0 	(3<<14)
+#define AA_LINE_REGION_WIDTH_ENABLE	(1<<8)
+#define AA_LINE_REGION_WIDTH_0_5	0
+#define AA_LINE_REGION_WIDTH_1_0	(1<<6)
+#define AA_LINE_REGION_WIDTH_2_0	(2<<6)
+#define AA_LINE_REGION_WIDTH_4_0	(3<<6)
+#define AA_LINE_ENABLE			((1<<1) | 1)
+#define AA_LINE_DISABLE			(1<<1)
+
+#define _3DSTATE_BUF_INFO_CMD	(CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
+/* Dword 1 */
+#define BUF_3D_ID_COLOR_BACK	(0x3<<24)
+#define BUF_3D_ID_DEPTH 	(0x7<<24)
+#define BUF_3D_USE_FENCE	(1<<23)
+#define BUF_3D_TILED_SURFACE	(1<<22)
+#define BUF_3D_TILE_WALK_X	0
+#define BUF_3D_TILE_WALK_Y	(1<<21)
+#define BUF_3D_PITCH(x)         (((x)/4)<<2)
+/* Dword 2 */
+#define BUF_3D_ADDR(x)		((x) & ~0x3)
+
+
+#define _3DSTATE_COLOR_FACTOR_CMD	(CMD_3D | (0x1d<<24) | (0x1<<16))
+
+#define _3DSTATE_COLOR_FACTOR_N_CMD(stage)	(CMD_3D | (0x1d<<24) | \
+					         ((0x90+(stage))<<16))
+
+#define _3DSTATE_CONST_BLEND_COLOR_CMD	(CMD_3D | (0x1d<<24) | (0x88<<16))
+
+#define _3DSTATE_DFLT_DIFFUSE_CMD	(CMD_3D | (0x1d<<24) | (0x99<<16))
+
+#define _3DSTATE_DFLT_SPEC_CMD		(CMD_3D | (0x1d<<24) | (0x9a<<16))
+
+#define _3DSTATE_DFLT_Z_CMD		(CMD_3D | (0x1d<<24) | (0x98<<16))
+
+
+#define _3DSTATE_DST_BUF_VARS_CMD	(CMD_3D | (0x1d<<24) | (0x85<<16))
+/* Dword 1 */
+#define DSTORG_HORT_BIAS(x)		((x)<<20)
+#define DSTORG_VERT_BIAS(x)		((x)<<16)
+#define COLOR_4_2_2_CHNL_WRT_ALL	0
+#define COLOR_4_2_2_CHNL_WRT_Y		(1<<12)
+#define COLOR_4_2_2_CHNL_WRT_CR		(2<<12)
+#define COLOR_4_2_2_CHNL_WRT_CB		(3<<12)
+#define COLOR_4_2_2_CHNL_WRT_CRCB	(4<<12)
+#define COLR_BUF_8BIT			0
+#define COLR_BUF_RGB555 		(1<<8)
+#define COLR_BUF_RGB565 		(2<<8)
+#define COLR_BUF_ARGB8888		(3<<8)
+#define DEPTH_IS_Z			0
+#define DEPTH_IS_W			(1<<6)
+#define DEPTH_FRMT_16_FIXED		0
+#define DEPTH_FRMT_16_FLOAT		(1<<2)
+#define DEPTH_FRMT_24_FIXED_8_OTHER	(2<<2)
+#define DEPTH_FRMT_24_FLOAT_8_OTHER	(3<<2)
+#define VERT_LINE_STRIDE_1		(1<<1)
+#define VERT_LINE_STRIDE_0		0
+#define VERT_LINE_STRIDE_OFS_1		1
+#define VERT_LINE_STRIDE_OFS_0		0
+
+
+#define _3DSTATE_DRAW_RECT_CMD		(CMD_3D|(0x1d<<24)|(0x80<<16)|3)
+/* Dword 1 */
+#define DRAW_RECT_DIS_DEPTH_OFS 	(1<<30)
+#define DRAW_DITHER_OFS_X(x)		((x)<<26)
+#define DRAW_DITHER_OFS_Y(x)		((x)<<24)
+/* Dword 2 */
+#define DRAW_YMIN(x)			((x)<<16)
+#define DRAW_XMIN(x)			(x)
+/* Dword 3 */
+#define DRAW_YMAX(x)			((x)<<16)
+#define DRAW_XMAX(x)			(x)
+/* Dword 4 */
+#define DRAW_YORG(x)			((x)<<16)
+#define DRAW_XORG(x)			(x)
+
+
+#define _3DSTATE_ENABLES_1_CMD		(CMD_3D|(0x3<<24))
+#define ENABLE_LOGIC_OP_MASK		((1<<23)|(1<<22))
+#define ENABLE_LOGIC_OP 		((1<<23)|(1<<22))
+#define DISABLE_LOGIC_OP		(1<<23)
+#define ENABLE_STENCIL_TEST		((1<<21)|(1<<20))
+#define DISABLE_STENCIL_TEST		(1<<21)
+#define ENABLE_DEPTH_BIAS		((1<<11)|(1<<10))
+#define DISABLE_DEPTH_BIAS		(1<<11)
+#define ENABLE_SPEC_ADD_MASK		((1<<9)|(1<<8))
+#define ENABLE_SPEC_ADD 		((1<<9)|(1<<8))
+#define DISABLE_SPEC_ADD		(1<<9)
+#define ENABLE_DIS_FOG_MASK		((1<<7)|(1<<6))
+#define ENABLE_FOG			((1<<7)|(1<<6))
+#define DISABLE_FOG			(1<<7)
+#define ENABLE_DIS_ALPHA_TEST_MASK	((1<<5)|(1<<4))
+#define ENABLE_ALPHA_TEST		((1<<5)|(1<<4))
+#define DISABLE_ALPHA_TEST		(1<<5)
+#define ENABLE_DIS_CBLEND_MASK		((1<<3)|(1<<2))
+#define ENABLE_COLOR_BLEND		((1<<3)|(1<<2))
+#define DISABLE_COLOR_BLEND		(1<<3)
+#define ENABLE_DIS_DEPTH_TEST_MASK	((1<<1)|1)
+#define ENABLE_DEPTH_TEST		((1<<1)|1)
+#define DISABLE_DEPTH_TEST		(1<<1)
+
+/* _3DSTATE_ENABLES_2, p138 */
+#define _3DSTATE_ENABLES_2_CMD		(CMD_3D|(0x4<<24))
+#define ENABLE_STENCIL_WRITE		((1<<21)|(1<<20))
+#define DISABLE_STENCIL_WRITE		(1<<21)
+#define ENABLE_TEX_CACHE		((1<<17)|(1<<16))
+#define DISABLE_TEX_CACHE		(1<<17)
+#define ENABLE_DITHER			((1<<9)|(1<<8))
+#define DISABLE_DITHER			(1<<9)
+#define ENABLE_COLOR_MASK		(1<<10)
+#define WRITEMASK_ALPHA			(1<<7)
+#define WRITEMASK_ALPHA_SHIFT		7
+#define WRITEMASK_RED			(1<<6)
+#define WRITEMASK_RED_SHIFT		6
+#define WRITEMASK_GREEN 		(1<<5)
+#define WRITEMASK_GREEN_SHIFT		5
+#define WRITEMASK_BLUE			(1<<4)
+#define WRITEMASK_BLUE_SHIFT		4
+#define WRITEMASK_MASK			((1<<4)|(1<<5)|(1<<6)|(1<<7))
+#define ENABLE_COLOR_WRITE		((1<<3)|(1<<2))
+#define DISABLE_COLOR_WRITE		(1<<3)
+#define ENABLE_DIS_DEPTH_WRITE_MASK	0x3
+#define ENABLE_DEPTH_WRITE		((1<<1)|1)
+#define DISABLE_DEPTH_WRITE		(1<<1)
+
+/* _3DSTATE_FOG_COLOR, p139 */
+#define _3DSTATE_FOG_COLOR_CMD		(CMD_3D|(0x15<<24))
+#define FOG_COLOR_RED(x)		((x)<<16)
+#define FOG_COLOR_GREEN(x)		((x)<<8)
+#define FOG_COLOR_BLUE(x)		(x)
+
+/* _3DSTATE_FOG_MODE, p140 */
+#define _3DSTATE_FOG_MODE_CMD		(CMD_3D|(0x1d<<24)|(0x89<<16)|2)
+/* Dword 1 */
+#define FOGFUNC_ENABLE			(1<<31)
+#define FOGFUNC_VERTEX			0
+#define FOGFUNC_PIXEL_EXP		(1<<28)
+#define FOGFUNC_PIXEL_EXP2		(2<<28)
+#define FOGFUNC_PIXEL_LINEAR		(3<<28)
+#define FOGSRC_INDEX_Z			(1<<27)
+#define FOGSRC_INDEX_W			((1<<27)|(1<<25))
+#define FOG_LINEAR_CONST		(1<<24)
+#define FOG_CONST_1(x)			((x)<<4)
+#define ENABLE_FOG_DENSITY		(1<<23)
+/* Dword 2 */
+#define FOG_CONST_2(x)			(x)
+/* Dword 3 */
+#define FOG_DENSITY(x)			(x)
+
+/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p142 */
+#define _3DSTATE_INDPT_ALPHA_BLEND_CMD	(CMD_3D|(0x0b<<24))
+#define ENABLE_INDPT_ALPHA_BLEND	((1<<23)|(1<<22))
+#define DISABLE_INDPT_ALPHA_BLEND	(1<<23)
+#define ALPHA_BLENDFUNC_MASK		0x3f0000
+#define ENABLE_ALPHA_BLENDFUNC		(1<<21)
+#define ABLENDFUNC_ADD			0
+#define ABLENDFUNC_SUB			(1<<16)
+#define ABLENDFUNC_RVSE_SUB		(2<<16)
+#define ABLENDFUNC_MIN			(3<<16)
+#define ABLENDFUNC_MAX			(4<<16)
+#define SRC_DST_ABLEND_MASK		0xfff
+#define ENABLE_SRC_ABLEND_FACTOR	(1<<11)
+#define SRC_ABLEND_FACT(x)		((x)<<6)
+#define ENABLE_DST_ABLEND_FACTOR	(1<<5)
+#define DST_ABLEND_FACT(x)		(x)
+
+
+/* _3DSTATE_MAP_BLEND_ARG, p152 */
+#define _3DSTATE_MAP_BLEND_ARG_CMD(stage)	(CMD_3D|(0x0e<<24)|((stage)<<20))
+
+#define TEXPIPE_COLOR			0
+#define TEXPIPE_ALPHA			(1<<18)
+#define TEXPIPE_KILL			(2<<18)
+#define TEXBLEND_ARG0			0
+#define TEXBLEND_ARG1			(1<<15)
+#define TEXBLEND_ARG2			(2<<15)
+#define TEXBLEND_ARG3			(3<<15)
+#define TEXBLENDARG_MODIFY_PARMS	(1<<6)
+#define TEXBLENDARG_REPLICATE_ALPHA 	(1<<5)
+#define TEXBLENDARG_INV_ARG 		(1<<4)
+#define TEXBLENDARG_ONE 		0
+#define TEXBLENDARG_FACTOR		0x01
+#define TEXBLENDARG_ACCUM		0x02
+#define TEXBLENDARG_DIFFUSE		0x03
+#define TEXBLENDARG_SPEC		0x04
+#define TEXBLENDARG_CURRENT		0x05
+#define TEXBLENDARG_TEXEL0		0x06
+#define TEXBLENDARG_TEXEL1		0x07
+#define TEXBLENDARG_TEXEL2		0x08
+#define TEXBLENDARG_TEXEL3		0x09
+#define TEXBLENDARG_FACTOR_N		0x0e
+
+/* _3DSTATE_MAP_BLEND_OP, p155 */
+#define _3DSTATE_MAP_BLEND_OP_CMD(stage)	(CMD_3D|(0x0d<<24)|((stage)<<20))
+#if 0
+#   define TEXPIPE_COLOR		0
+#   define TEXPIPE_ALPHA		(1<<18)
+#   define TEXPIPE_KILL			(2<<18)
+#endif
+#define ENABLE_TEXOUTPUT_WRT_SEL	(1<<17)
+#define TEXOP_OUTPUT_CURRENT		0
+#define TEXOP_OUTPUT_ACCUM		(1<<15)
+#define ENABLE_TEX_CNTRL_STAGE		((1<<12)|(1<<11))
+#define DISABLE_TEX_CNTRL_STAGE		(1<<12)
+#define TEXOP_SCALE_SHIFT		9
+#define TEXOP_SCALE_1X			(0 << TEXOP_SCALE_SHIFT)
+#define TEXOP_SCALE_2X			(1 << TEXOP_SCALE_SHIFT)
+#define TEXOP_SCALE_4X			(2 << TEXOP_SCALE_SHIFT)
+#define TEXOP_MODIFY_PARMS		(1<<8)
+#define TEXOP_LAST_STAGE		(1<<7)
+#define TEXBLENDOP_KILLPIXEL		0x02
+#define TEXBLENDOP_ARG1 		0x01
+#define TEXBLENDOP_ARG2 		0x02
+#define TEXBLENDOP_MODULATE		0x03
+#define TEXBLENDOP_ADD			0x06
+#define TEXBLENDOP_ADDSIGNED		0x07
+#define TEXBLENDOP_BLEND		0x08
+#define TEXBLENDOP_BLEND_AND_ADD	0x09
+#define TEXBLENDOP_SUBTRACT		0x0a
+#define TEXBLENDOP_DOT3 		0x0b
+#define TEXBLENDOP_DOT4 		0x0c
+#define TEXBLENDOP_MODULATE_AND_ADD	0x0d
+#define TEXBLENDOP_MODULATE_2X_AND_ADD	0x0e
+#define TEXBLENDOP_MODULATE_4X_AND_ADD	0x0f
+
+/* _3DSTATE_MAP_BUMP_TABLE, p160 TODO */
+/* _3DSTATE_MAP_COLOR_CHROMA_KEY, p161 TODO */
+
+#define _3DSTATE_MAP_COORD_TRANSFORM	((3<<29)|(0x1d<<24)|(0x8c<<16))
+#define DISABLE_TEX_TRANSFORM		(1<<28)
+#define TEXTURE_SET(x)			(x<<29)
+
+#define _3DSTATE_VERTEX_TRANSFORM	((3<<29)|(0x1d<<24)|(0x8b<<16))
+#define DISABLE_VIEWPORT_TRANSFORM	(1<<31)
+#define DISABLE_PERSPECTIVE_DIVIDE	(1<<29)
+
+
+/* _3DSTATE_MAP_COORD_SET_BINDINGS, p162 */
+#define _3DSTATE_MAP_COORD_SETBIND_CMD	(CMD_3D|(0x1d<<24)|(0x02<<16))
+#define TEXBIND_MASK3			((1<<15)|(1<<14)|(1<<13)|(1<<12))
+#define TEXBIND_MASK2			((1<<11)|(1<<10)|(1<<9)|(1<<8))
+#define TEXBIND_MASK1			((1<<7)|(1<<6)|(1<<5)|(1<<4))
+#define TEXBIND_MASK0			((1<<3)|(1<<2)|(1<<1)|1)
+
+#define TEXBIND_SET3(x) 		((x)<<12)
+#define TEXBIND_SET2(x) 		((x)<<8)
+#define TEXBIND_SET1(x) 		((x)<<4)
+#define TEXBIND_SET0(x) 		(x)
+
+#define TEXCOORDSRC_KEEP		0
+#define TEXCOORDSRC_DEFAULT		0x01
+#define TEXCOORDSRC_VTXSET_0		0x08
+#define TEXCOORDSRC_VTXSET_1		0x09
+#define TEXCOORDSRC_VTXSET_2		0x0a
+#define TEXCOORDSRC_VTXSET_3		0x0b
+#define TEXCOORDSRC_VTXSET_4		0x0c
+#define TEXCOORDSRC_VTXSET_5		0x0d
+#define TEXCOORDSRC_VTXSET_6		0x0e
+#define TEXCOORDSRC_VTXSET_7		0x0f
+
+#define MAP_UNIT(unit)			((unit)<<16)
+#define MAP_UNIT_MASK			(0x7<<16)
+
+/* _3DSTATE_MAP_COORD_SETS, p164 */
+#define _3DSTATE_MAP_COORD_SET_CMD	(CMD_3D|(0x1c<<24)|(0x01<<19))
+#define ENABLE_TEXCOORD_PARAMS		(1<<15)
+#define TEXCOORDS_ARE_NORMAL		(1<<14)
+#define TEXCOORDS_ARE_IN_TEXELUNITS	0
+#define TEXCOORDTYPE_CARTESIAN		0
+#define TEXCOORDTYPE_HOMOGENEOUS	(1<<11)
+#define TEXCOORDTYPE_VECTOR		(2<<11)
+#define TEXCOORDTYPE_MASK	        (0x7<<11)
+#define ENABLE_ADDR_V_CNTL		(1<<7)
+#define ENABLE_ADDR_U_CNTL		(1<<3)
+#define TEXCOORD_ADDR_V_MODE(x) 	((x)<<4)
+#define TEXCOORD_ADDR_U_MODE(x) 	(x)
+#define TEXCOORDMODE_WRAP		0
+#define TEXCOORDMODE_MIRROR		1
+#define TEXCOORDMODE_CLAMP		2
+#define TEXCOORDMODE_WRAP_SHORTEST	3
+#define TEXCOORDMODE_CLAMP_BORDER	4
+#define TEXCOORD_ADDR_V_MASK		0x70
+#define TEXCOORD_ADDR_U_MASK		0x7
+
+/* _3DSTATE_MAP_CUBE, p168 TODO */
+#define _3DSTATE_MAP_CUBE		(CMD_3D|(0x1c<<24)|(0x0a<<19))
+#define CUBE_NEGX_ENABLE                (1<<5)
+#define CUBE_POSX_ENABLE                (1<<4)
+#define CUBE_NEGY_ENABLE                (1<<3)
+#define CUBE_POSY_ENABLE                (1<<2)
+#define CUBE_NEGZ_ENABLE                (1<<1)
+#define CUBE_POSZ_ENABLE                (1<<0)
+
+
+/* _3DSTATE_MODES_1, p190 */
+#define _3DSTATE_MODES_1_CMD		(CMD_3D|(0x08<<24))
+#define BLENDFUNC_MASK			0x3f0000
+#define ENABLE_COLR_BLND_FUNC		(1<<21)
+#define BLENDFUNC_ADD			0
+#define BLENDFUNC_SUB			(1<<16)
+#define BLENDFUNC_RVRSE_SUB		(2<<16)
+#define BLENDFUNC_MIN			(3<<16)
+#define BLENDFUNC_MAX			(4<<16)
+#define SRC_DST_BLND_MASK		0xfff
+#define ENABLE_SRC_BLND_FACTOR		(1<<11)
+#define ENABLE_DST_BLND_FACTOR		(1<<5)
+#define SRC_BLND_FACT(x)		((x)<<6)
+#define DST_BLND_FACT(x)		(x)
+
+
+/* _3DSTATE_MODES_2, p192 */
+#define _3DSTATE_MODES_2_CMD		(CMD_3D|(0x0f<<24))
+#define ENABLE_GLOBAL_DEPTH_BIAS	(1<<22)
+#define GLOBAL_DEPTH_BIAS(x)		((x)<<14)
+#define ENABLE_ALPHA_TEST_FUNC		(1<<13)
+#define ENABLE_ALPHA_REF_VALUE		(1<<8)
+#define ALPHA_TEST_FUNC(x)		((x)<<9)
+#define ALPHA_REF_VALUE(x)		(x)
+
+#define ALPHA_TEST_REF_MASK		0x3fff
+
+/* _3DSTATE_MODES_3, p193 */
+#define _3DSTATE_MODES_3_CMD		(CMD_3D|(0x02<<24))
+#define DEPTH_TEST_FUNC_MASK		0x1f0000
+#define ENABLE_DEPTH_TEST_FUNC		(1<<20)
+/* Uses COMPAREFUNC */
+#define DEPTH_TEST_FUNC(x)		((x)<<16)
+#define ENABLE_ALPHA_SHADE_MODE 	(1<<11)
+#define ENABLE_FOG_SHADE_MODE		(1<<9)
+#define ENABLE_SPEC_SHADE_MODE		(1<<7)
+#define ENABLE_COLOR_SHADE_MODE 	(1<<5)
+#define ALPHA_SHADE_MODE(x)		((x)<<10)
+#define FOG_SHADE_MODE(x)		((x)<<8)
+#define SPEC_SHADE_MODE(x)		((x)<<6)
+#define COLOR_SHADE_MODE(x)		((x)<<4)
+#define CULLMODE_MASK			0xf
+#define ENABLE_CULL_MODE		(1<<3)
+#define CULLMODE_BOTH			0
+#define CULLMODE_NONE			1
+#define CULLMODE_CW			2
+#define CULLMODE_CCW			3
+
+#define SHADE_MODE_LINEAR		0
+#define SHADE_MODE_FLAT 		0x1
+
+/* _3DSTATE_MODES_4, p195 */
+#define _3DSTATE_MODES_4_CMD		(CMD_3D|(0x16<<24))
+#define ENABLE_LOGIC_OP_FUNC		(1<<23)
+#define LOGIC_OP_FUNC(x)		((x)<<18)
+#define LOGICOP_MASK			((1<<18)|(1<<19)|(1<<20)|(1<<21))
+#define LOGICOP_CLEAR			0
+#define LOGICOP_NOR			0x1
+#define LOGICOP_AND_INV 		0x2
+#define LOGICOP_COPY_INV		0x3
+#define LOGICOP_AND_RVRSE		0x4
+#define LOGICOP_INV			0x5
+#define LOGICOP_XOR			0x6
+#define LOGICOP_NAND			0x7
+#define LOGICOP_AND			0x8
+#define LOGICOP_EQUIV			0x9
+#define LOGICOP_NOOP			0xa
+#define LOGICOP_OR_INV			0xb
+#define LOGICOP_COPY			0xc
+#define LOGICOP_OR_RVRSE		0xd
+#define LOGICOP_OR			0xe
+#define LOGICOP_SET			0xf
+#define MODE4_ENABLE_STENCIL_TEST_MASK	((1<<17)|(0xff00))
+#define ENABLE_STENCIL_TEST_MASK	(1<<17)
+#define STENCIL_TEST_MASK(x)		((x)<<8)
+#define MODE4_ENABLE_STENCIL_WRITE_MASK	((1<<16)|(0x00ff))
+#define ENABLE_STENCIL_WRITE_MASK	(1<<16)
+#define STENCIL_WRITE_MASK(x)		((x)&0xff)
+
+/* _3DSTATE_MODES_5, p196 */
+#define _3DSTATE_MODES_5_CMD		(CMD_3D|(0x0c<<24))
+#define ENABLE_SPRITE_POINT_TEX 	(1<<23)
+#define SPRITE_POINT_TEX_ON		(1<<22)
+#define SPRITE_POINT_TEX_OFF		0
+#define FLUSH_RENDER_CACHE		(1<<18)
+#define FLUSH_TEXTURE_CACHE		(1<<16)
+#define FIXED_LINE_WIDTH_MASK		0xfc00
+#define ENABLE_FIXED_LINE_WIDTH 	(1<<15)
+#define FIXED_LINE_WIDTH(x)		((x)<<10)
+#define FIXED_POINT_WIDTH_MASK		0x3ff
+#define ENABLE_FIXED_POINT_WIDTH	(1<<9)
+#define FIXED_POINT_WIDTH(x)		(x)
+
+/* _3DSTATE_RASTERIZATION_RULES, p198 */
+#define _3DSTATE_RASTER_RULES_CMD	(CMD_3D|(0x07<<24))
+#define ENABLE_POINT_RASTER_RULE	(1<<15)
+#define OGL_POINT_RASTER_RULE		(1<<13)
+#define ENABLE_LINE_STRIP_PROVOKE_VRTX	(1<<8)
+#define ENABLE_TRI_FAN_PROVOKE_VRTX	(1<<5)
+#define ENABLE_TRI_STRIP_PROVOKE_VRTX	(1<<2)
+#define LINE_STRIP_PROVOKE_VRTX(x)	((x)<<6)
+#define TRI_FAN_PROVOKE_VRTX(x) 	((x)<<3)
+#define TRI_STRIP_PROVOKE_VRTX(x)	(x)
+
+/* _3DSTATE_SCISSOR_ENABLE, p200 */
+#define _3DSTATE_SCISSOR_ENABLE_CMD	(CMD_3D|(0x1c<<24)|(0x10<<19))
+#define ENABLE_SCISSOR_RECT		((1<<1) | 1)
+#define DISABLE_SCISSOR_RECT		(1<<1)
+
+/* _3DSTATE_SCISSOR_RECTANGLE_0, p201 */
+#define _3DSTATE_SCISSOR_RECT_0_CMD	(CMD_3D|(0x1d<<24)|(0x81<<16)|1)
+/* Dword 1 */
+#define SCISSOR_RECT_0_YMIN(x)		((x)<<16)
+#define SCISSOR_RECT_0_XMIN(x)		(x)
+/* Dword 2 */
+#define SCISSOR_RECT_0_YMAX(x)		((x)<<16)
+#define SCISSOR_RECT_0_XMAX(x)		(x)
+
+/* _3DSTATE_STENCIL_TEST, p202 */
+#define _3DSTATE_STENCIL_TEST_CMD	(CMD_3D|(0x09<<24))
+#define ENABLE_STENCIL_PARMS		(1<<23)
+#define STENCIL_OPS_MASK		(0xffc000)
+#define STENCIL_FAIL_OP(x)		((x)<<20)
+#define STENCIL_PASS_DEPTH_FAIL_OP(x)	((x)<<17)
+#define STENCIL_PASS_DEPTH_PASS_OP(x)	((x)<<14)
+
+#define ENABLE_STENCIL_TEST_FUNC_MASK	((1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9))
+#define ENABLE_STENCIL_TEST_FUNC	(1<<13)
+/* Uses COMPAREFUNC */
+#define STENCIL_TEST_FUNC(x)		((x)<<9)
+#define STENCIL_REF_VALUE_MASK		((1<<8)|0xff)
+#define ENABLE_STENCIL_REF_VALUE	(1<<8)
+#define STENCIL_REF_VALUE(x)		(x)
+
+/* _3DSTATE_VERTEX_FORMAT, p204 */
+#define _3DSTATE_VFT0_CMD	(CMD_3D|(0x05<<24))
+#define VFT0_POINT_WIDTH	(1<<12)
+#define VFT0_TEX_COUNT_MASK    	(7<<8)
+#define VFT0_TEX_COUNT_SHIFT    8
+#define VFT0_TEX_COUNT(x) 	((x)<<8)
+#define VFT0_SPEC		(1<<7)
+#define VFT0_DIFFUSE		(1<<6)
+#define VFT0_DEPTH_OFFSET  	(1<<5)
+#define VFT0_XYZ		(1<<1)
+#define VFT0_XYZW		(2<<1)
+#define VFT0_XY			(3<<1)
+#define VFT0_XYW		(4<<1)
+#define VFT0_XYZW_MASK          (7<<1)
+
+/* _3DSTATE_VERTEX_FORMAT_2, p206 */
+#define _3DSTATE_VFT1_CMD	(CMD_3D|(0x0a<<24))
+#define VFT1_TEX7_FMT(x)	((x)<<14)
+#define VFT1_TEX6_FMT(x)	((x)<<12)
+#define VFT1_TEX5_FMT(x)	((x)<<10)
+#define VFT1_TEX4_FMT(x)	((x)<<8)
+#define VFT1_TEX3_FMT(x)	((x)<<6)
+#define VFT1_TEX2_FMT(x)	((x)<<4)
+#define VFT1_TEX1_FMT(x)	((x)<<2)
+#define VFT1_TEX0_FMT(x)	(x)
+#define VFT1_TEX0_MASK          3
+#define VFT1_TEX1_SHIFT         2
+#define TEXCOORDFMT_2D		0
+#define TEXCOORDFMT_3D		1
+#define TEXCOORDFMT_4D		2
+#define TEXCOORDFMT_1D		3
+
+/*New stuff picked up along the way */
+
+#define MLC_LOD_BIAS_MASK ((1<<7)-1)
+
+
+/* _3DSTATE_VERTEX_TRANSFORM, p207 */
+#define _3DSTATE_VERTEX_TRANS_CMD	(CMD_3D|(0x1d<<24)|(0x8b<<16)|0)
+#define _3DSTATE_VERTEX_TRANS_MTX_CMD	(CMD_3D|(0x1d<<24)|(0x8b<<16)|6)
+/* Dword 1 */
+#define ENABLE_VIEWPORT_TRANSFORM	((1<<31)|(1<<30))
+#define DISABLE_VIEWPORT_TRANSFORM	(1<<31)
+#define ENABLE_PERSP_DIVIDE		((1<<29)|(1<<28))
+#define DISABLE_PERSP_DIVIDE		(1<<29)
+#define VRTX_TRANS_LOAD_MATRICES	0x7421
+#define VRTX_TRANS_NO_LOAD_MATRICES	0x0000
+/* Dword 2 -> 7  are matrix elements */
+
+/* _3DSTATE_W_STATE, p209 */
+#define _3DSTATE_W_STATE_CMD		(CMD_3D|(0x1d<<24)|(0x8d<<16)|1)
+/* Dword 1 */
+#define MAGIC_W_STATE_DWORD1		0x00000008
+/* Dword 2 */
+#define WFAR_VALUE(x)			(x)
+
+
+/* Stipple command, carried over from the i810, apparently:
+ */
+#define _3DSTATE_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define ST1_ENABLE               (1<<16)
+#define ST1_MASK                 (0xffff)
+
+
+
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_2      ((0x3<<29)|(0x1d<<24)|(0x03<<16))
+#define LOAD_TEXTURE_MAP0                   (1<<11)
+#define LOAD_GLOBAL_COLOR_FACTOR            (1<<6)
+
+#define TM0S0_ADDRESS_MASK              0xfffffffc
+#define TM0S0_USE_FENCE                 (1<<1)
+
+#define TM0S1_HEIGHT_SHIFT              21
+#define TM0S1_WIDTH_SHIFT               10
+#define TM0S1_PALETTE_SELECT            (1<<9)
+#define TM0S1_MAPSURF_FORMAT_MASK       (0x7 << 6)
+#define TM0S1_MAPSURF_FORMAT_SHIFT      6
+#define    MAPSURF_8BIT_INDEXED		   (0<<6)
+#define    MAPSURF_8BIT		 	   (1<<6)
+#define    MAPSURF_16BIT		   (2<<6)
+#define    MAPSURF_32BIT		   (3<<6)
+#define    MAPSURF_411			   (4<<6)
+#define    MAPSURF_422			   (5<<6)
+#define    MAPSURF_COMPRESSED		   (6<<6)
+#define    MAPSURF_4BIT_INDEXED		   (7<<6)
+#define TM0S1_MT_FORMAT_MASK         (0x7 << 3)
+#define TM0S1_MT_FORMAT_SHIFT        3
+#define    MT_4BIT_IDX_ARGB8888	           (7<<3) /* SURFACE_4BIT_INDEXED */
+#define    MT_8BIT_IDX_RGB565	           (0<<3) /* SURFACE_8BIT_INDEXED */
+#define    MT_8BIT_IDX_ARGB1555	           (1<<3)
+#define    MT_8BIT_IDX_ARGB4444	           (2<<3)
+#define    MT_8BIT_IDX_AY88		   (3<<3)
+#define    MT_8BIT_IDX_ABGR8888	           (4<<3)
+#define    MT_8BIT_IDX_BUMP_88DVDU 	   (5<<3)
+#define    MT_8BIT_IDX_BUMP_655LDVDU	   (6<<3)
+#define    MT_8BIT_IDX_ARGB8888	           (7<<3)
+#define    MT_8BIT_I8		           (0<<3) /* SURFACE_8BIT */
+#define    MT_8BIT_L8		           (1<<3)
+#define    MT_16BIT_RGB565 		   (0<<3) /* SURFACE_16BIT */
+#define    MT_16BIT_ARGB1555		   (1<<3)
+#define    MT_16BIT_ARGB4444		   (2<<3)
+#define    MT_16BIT_AY88		   (3<<3)
+#define    MT_16BIT_DIB_ARGB1555_8888      (4<<3)
+#define    MT_16BIT_BUMP_88DVDU	           (5<<3)
+#define    MT_16BIT_BUMP_655LDVDU	   (6<<3)
+#define    MT_16BIT_DIB_RGB565_8888	   (7<<3)
+#define    MT_32BIT_ARGB8888		   (0<<3) /* SURFACE_32BIT */
+#define    MT_32BIT_ABGR8888		   (1<<3)
+#define    MT_32BIT_BUMP_XLDVDU_8888	   (6<<3)
+#define    MT_32BIT_DIB_8888		   (7<<3)
+#define    MT_411_YUV411		   (0<<3) /* SURFACE_411 */
+#define    MT_422_YCRCB_SWAPY	           (0<<3) /* SURFACE_422 */
+#define    MT_422_YCRCB_NORMAL	           (1<<3)
+#define    MT_422_YCRCB_SWAPUV	           (2<<3)
+#define    MT_422_YCRCB_SWAPUVY	           (3<<3)
+#define    MT_COMPRESS_DXT1		   (0<<3) /* SURFACE_COMPRESSED */
+#define    MT_COMPRESS_DXT2_3	           (1<<3)
+#define    MT_COMPRESS_DXT4_5	           (2<<3)
+#define    MT_COMPRESS_FXT1		   (3<<3)
+#define TM0S1_COLORSPACE_CONVERSION     (1 << 2)
+#define TM0S1_TILED_SURFACE             (1 << 1)
+#define TM0S1_TILE_WALK                 (1 << 0)
+
+#define TM0S2_PITCH_SHIFT               21
+#define TM0S2_CUBE_FACE_ENA_SHIFT       15
+#define TM0S2_CUBE_FACE_ENA_MASK        (1<<15)
+#define TM0S2_MAP_FORMAT                (1<<14)
+#define TM0S2_VERTICAL_LINE_STRIDE      (1<<13)
+#define TM0S2_VERITCAL_LINE_STRIDE_OFF  (1<<12)
+#define TM0S2_OUTPUT_CHAN_SHIFT         10
+#define TM0S2_OUTPUT_CHAN_MASK          (3<<10)
+
+#define TM0S3_MIP_FILTER_MASK           (0x3<<30)
+#define TM0S3_MIP_FILTER_SHIFT          30
+#define MIPFILTER_NONE		0
+#define MIPFILTER_NEAREST	1
+#define MIPFILTER_LINEAR	3
+#define TM0S3_MAG_FILTER_MASK           (0x3<<28)
+#define TM0S3_MAG_FILTER_SHIFT          28
+#define TM0S3_MIN_FILTER_MASK           (0x3<<26)
+#define TM0S3_MIN_FILTER_SHIFT          26
+#define FILTER_NEAREST		0
+#define FILTER_LINEAR		1
+#define FILTER_ANISOTROPIC	2
+
+#define TM0S3_LOD_BIAS_SHIFT		17
+#define TM0S3_LOD_BIAS_MASK		(0x1ff<<17)
+#define TM0S3_MAX_MIP_SHIFT		9
+#define TM0S3_MAX_MIP_MASK		(0xff<<9)
+#define TM0S3_MIN_MIP_SHIFT		3
+#define TM0S3_MIN_MIP_MASK		(0x3f<<3)
+#define TM0S3_KILL_PIXEL		(1<<2)
+#define TM0S3_KEYED_FILTER		(1<<1)
+#define TM0S3_CHROMA_KEY		(1<<0)
+
+
+/* _3DSTATE_MAP_TEXEL_STREAM, p188 */
+#define _3DSTATE_MAP_TEX_STREAM_CMD	(CMD_3D|(0x1c<<24)|(0x05<<19))
+#define DISABLE_TEX_STREAM_BUMP 	(1<<12)
+#define ENABLE_TEX_STREAM_BUMP		((1<<12)|(1<<11))
+#define TEX_MODIFY_UNIT_0		0
+#define TEX_MODIFY_UNIT_1		(1<<8)
+#define ENABLE_TEX_STREAM_COORD_SET	(1<<7)
+#define TEX_STREAM_COORD_SET(x) 	((x)<<4)
+#define ENABLE_TEX_STREAM_MAP_IDX	(1<<3)
+#define TEX_STREAM_MAP_IDX(x)		(x)
+
+
+#define FLUSH_MAP_CACHE    (1<<0)
+
+#endif
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
new file mode 100644
index 0000000..5d29059
--- /dev/null
+++ b/src/i830_rotate.c
@@ -0,0 +1,1239 @@
+/* -*- c-basic-offset: 3 -*- */
+/**************************************************************************
+
+Copyright 2005 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 THE COPYRIGHT HOLDERS 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.
+
+**************************************************************************/
+
+/*
+ * Reformatted with GNU indent (2.2.8), using the following options:
+ *
+ *    -bad -bap -c41 -cd0 -ncdb -ci6 -cli0 -cp0 -ncs -d0 -di3 -i3 -ip3 -l78
+ *    -lp -npcs -psl -sob -ss -br -ce -sc -hnl
+ *
+ * This provides a good match with the original i810 code and preferred
+ * XFree86 formatting conventions.
+ *
+ * When editing this driver, please follow the existing formatting, and edit
+ * with <TAB> characters expanded at 8-column intervals.
+ */
+
+/*
+ * Authors:
+ *   Alan Hourihane <alanh at tungstengraphics.com>
+ *   Brian Paul <brian.paul at tungstengraphics.com>
+ *   Keith Whitwell <keith at tungstengraphics.com>
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "servermd.h"
+#include "shadow.h"
+
+#include "i830.h"
+#include "i915_reg.h"
+#include "i915_3d.h"
+
+#ifdef XF86DRI
+#include "dri.h"
+#endif
+
+static void *
+I830WindowLinear (ScreenPtr pScreen,
+		 CARD32    row,
+		 CARD32    offset,
+		 int	   mode,
+		 CARD32    *size,
+		 void	   *closure)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+   CARD8 *ptr;
+
+   *size = (pScrn->bitsPerPixel * pI830->displayWidth >> 3);
+   if (I830IsPrimary(pScrn))
+      ptr = (CARD8 *) (pI830->FbBase + pI830->FrontBuffer.Start) + row * (*size) + offset;
+   else {
+      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      ptr = (CARD8 *) (pI830->FbBase + pI8301->FrontBuffer2.Start) + row * (*size) + offset;
+   }
+   return (void *)ptr;
+}
+
+struct matrix23
+{
+	int m00, m01, m02;
+	int m10, m11, m12;
+};
+
+static void
+matrix23Set(struct matrix23 *m,
+            int m00, int m01, int m02,
+            int m10, int m11, int m12)
+{
+   m->m00 = m00;   m->m01 = m01;   m->m02 = m02;
+   m->m10 = m10;   m->m11 = m11;   m->m12 = m12;
+}
+
+
+/*
+ * Transform (x,y) coordinate by the given matrix.
+ */
+static void
+matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y)
+{
+   const float x0 = *x;
+   const float y0 = *y;
+
+   *x = m->m00 * x0 + m->m01 * y0 + m->m02;
+   *y = m->m10 * x0 + m->m11 * y0 + m->m12;
+}
+
+/*
+ * Make rotation matrix for width X height screen.
+ */
+static void
+matrix23Rotate(struct matrix23 *m, int width, int height, int angle)
+{
+   switch (angle) {
+   case 0:
+      matrix23Set(m, 1, 0, 0, 0, 1, 0);
+      break;
+   case 90:
+      matrix23Set(m, 0, 1, 0,  -1, 0, width);
+      break;
+   case 180:
+      matrix23Set(m, -1, 0, width,  0, -1, height);
+      break;
+   case 270:
+      matrix23Set(m, 0, -1, height,  1, 0, 0);
+      break;
+   default:
+      break;
+   }
+}
+
+/* Doesn't matter on the order for our purposes */
+typedef struct {
+   unsigned char red, green, blue, alpha;
+} intel_color_t;
+
+/* Vertex format */
+typedef union {
+   struct {
+      float x, y, z, w;
+      intel_color_t color;
+      intel_color_t specular;
+      float u0, v0;
+      float u1, v1;
+      float u2, v2;
+      float u3, v3;
+   } v;
+   float f[24];
+   unsigned int  ui[24];
+   unsigned char ub4[24][4];
+} intelVertex, *intelVertexPtr;
+
+static void draw_poly(CARD32 *vb,
+                      float verts[][2],
+                      float texcoords[][2])
+{
+   int vertex_size = 8;
+   intelVertex tmp;
+   int i, k;
+
+   /* initial constant vertex fields */
+   tmp.v.z = 1.0;
+   tmp.v.w = 1.0; 
+   tmp.v.color.red = 255;
+   tmp.v.color.green = 255;
+   tmp.v.color.blue = 255;
+   tmp.v.color.alpha = 255;
+   tmp.v.specular.red = 0;
+   tmp.v.specular.green = 0;
+   tmp.v.specular.blue = 0;
+   tmp.v.specular.alpha = 0;
+
+   for (k = 0; k < 4; k++) {
+      tmp.v.x = verts[k][0];
+      tmp.v.y = verts[k][1];
+      tmp.v.u0 = texcoords[k][0];
+      tmp.v.v0 = texcoords[k][1];
+
+      for (i = 0 ; i < vertex_size ; i++)
+         vb[i] = tmp.ui[i];
+
+      vb += vertex_size;
+   }
+}
+
+static void
+I915UpdateRotate (ScreenPtr      pScreen,
+                 shadowBufPtr   pBuf)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+   ScrnInfoPtr pScrn1 = pScrn;
+   I830Ptr pI8301 = NULL;
+   RegionPtr	damage = shadowDamage(pBuf);
+   int		nbox = REGION_NUM_RECTS (damage);
+   BoxPtr		pbox = REGION_RECTS (damage);
+   int		box_x1, box_x2, box_y1, box_y2;
+   CARD32	vb[32];	/* 32 dword vertex buffer */
+   float verts[4][2], tex[4][2];
+   struct matrix23 rotMatrix;
+   int j;
+   int use_fence;
+   Bool updateInvarient = FALSE;
+#ifdef XF86DRI
+   drmI830Sarea *sarea = NULL;
+   drm_context_t myContext = 0;
+#endif
+   Bool didLock = FALSE;
+
+   if (I830IsPrimary(pScrn)) {
+      pI8301 = pI830;
+   } else {
+      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pScrn1 = pI830->entityPrivate->pScrn_1;
+   }
+
+   switch (pI830->rotation) {
+      case RR_Rotate_90:
+         matrix23Rotate(&rotMatrix,
+                     pScreen->width, pScreen->height,
+                     90);
+	 break;
+      case RR_Rotate_180:
+         matrix23Rotate(&rotMatrix,
+                     pScreen->width, pScreen->height,
+                     180);
+	 break;
+      case RR_Rotate_270:
+         matrix23Rotate(&rotMatrix,
+                     pScreen->width, pScreen->height,
+                     270);
+	 break;
+      default:
+	 break;
+   }
+
+#ifdef XF86DRI
+   if (pI8301->directRenderingEnabled) {
+      sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
+      myContext = DRIGetContext(pScrn1->pScreen);
+      didLock = I830DRILock(pScrn1);
+   }
+#endif
+
+   if (pScrn->scrnIndex != *pI830->used3D)
+      updateInvarient = TRUE;
+ 
+#ifdef XF86DRI
+   if (sarea && sarea->ctxOwner != myContext)
+      updateInvarient = TRUE;
+#endif
+
+   if (updateInvarient) {
+      FS_LOCALS(3);
+      *pI830->used3D = pScrn->scrnIndex;
+#ifdef XF86DRI
+      if (sarea)
+         sarea->ctxOwner = myContext;
+#endif
+      BEGIN_LP_RING(54);
+      /* invarient state */
+      OUT_RING(MI_NOOP);
+      OUT_RING(_3DSTATE_AA_CMD |
+	       AA_LINE_ECAAR_WIDTH_ENABLE | AA_LINE_ECAAR_WIDTH_1_0 |
+	       AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
+
+      OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
+      OUT_RING(0x00000000);
+
+      OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
+      OUT_RING(0x00000000);
+
+      OUT_RING(_3DSTATE_DFLT_Z_CMD);
+      OUT_RING(0x00000000);
+
+      OUT_RING(_3DSTATE_COORD_SET_BINDINGS |
+	       CSB_TCB(0, 0) | CSB_TCB(1, 1) |
+	       CSB_TCB(2, 2) | CSB_TCB(3, 3) |
+	       CSB_TCB(4, 4) | CSB_TCB(5, 5) |
+	       CSB_TCB(6, 6) | CSB_TCB(7, 7));
+
+      OUT_RING(_3DSTATE_RASTER_RULES_CMD |
+	       ENABLE_TRI_FAN_PROVOKE_VRTX | TRI_FAN_PROVOKE_VRTX(2) |
+	       ENABLE_LINE_STRIP_PROVOKE_VRTX | LINE_STRIP_PROVOKE_VRTX(1) |
+	       ENABLE_TEXKILL_3D_4D | TEXKILL_4D |
+	       ENABLE_POINT_RASTER_RULE | OGL_POINT_RASTER_RULE);
+
+      OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 1);
+      OUT_RING(0x00000000);
+
+      /* flush map & render cache */
+      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      OUT_RING(0x00000000);
+
+      /* draw rect */
+      OUT_RING(_3DSTATE_DRAW_RECT_CMD);
+      OUT_RING(DRAW_DITHER_OFS_X(0) | DRAW_DITHER_OFS_Y(0));
+      OUT_RING(DRAW_XMIN(0) | DRAW_YMIN(0));
+      OUT_RING(DRAW_XMAX(pScrn->virtualX - 1) |
+	       DRAW_YMAX(pScrn->virtualY - 1));
+      OUT_RING(DRAW_XORG(0) | DRAW_YORG(0));
+
+      OUT_RING(MI_NOOP);
+
+      OUT_RING(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+      OUT_RING(_3DSTATE_SCISSOR_RECT_0_CMD);
+      OUT_RING(0x00000000); /* ymin, xmin */
+      OUT_RING(0x00000000); /* ymax, xmax */
+
+      OUT_RING(0x7c000003); /* XXX: magic numbers */
+      OUT_RING(0x7d070000);
+      OUT_RING(0x00000000);
+      OUT_RING(0x68000002);
+
+      /* context setup */
+      OUT_RING(_3DSTATE_MODES_4_CMD |
+	       ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) |
+	       MODE4_ENABLE_STENCIL_WRITE_MASK |
+	       MODE4_ENABLE_STENCIL_TEST_MASK);
+
+      OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+	       I1_LOAD_S(2) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 4);
+
+      OUT_RING(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
+	       S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
+	       S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) |
+	       S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) |
+	       S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) |
+	       S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) |
+	       S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) |
+	       S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT));
+      OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
+	       S4_CULLMODE_NONE | S4_VFMT_SPEC_FOG | S4_VFMT_COLOR |
+	       S4_VFMT_XYZW);
+      OUT_RING(0x00000000); /* S5 -- enable bits */
+      OUT_RING((2 << S6_DEPTH_TEST_FUNC_SHIFT) |
+	       (2 << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
+	       (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) | S6_COLOR_WRITE_ENABLE |
+	       (2 << S6_TRISTRIP_PV_SHIFT));
+
+      OUT_RING(_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
+	       IAB_MODIFY_ENABLE |
+	       IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
+	       IAB_MODIFY_SRC_FACTOR |
+	       (BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT) |
+	       IAB_MODIFY_DST_FACTOR |
+	       (BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT));
+
+      OUT_RING(_3DSTATE_CONST_BLEND_COLOR_CMD);
+      OUT_RING(0x00000000);
+
+      OUT_RING(_3DSTATE_DST_BUF_VARS_CMD);
+      if (pI830->cpp == 1) {
+	 OUT_RING(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) |
+		  DSTORG_VERT_BIAS(0x8) | COLR_BUF_8BIT);
+      } else if (pI830->cpp == 2) {
+	 OUT_RING(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) |
+		  DSTORG_VERT_BIAS(0x8) | COLR_BUF_RGB565);
+      } else {
+	 OUT_RING(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) |
+		  DSTORG_VERT_BIAS(0x8) | COLR_BUF_ARGB8888 |
+		  DEPTH_FRMT_24_FIXED_8_OTHER);
+      }
+
+      OUT_RING(_3DSTATE_STIPPLE);
+      OUT_RING(0x00000000);
+
+      /* texture sampler state */
+      OUT_RING(_3DSTATE_SAMPLER_STATE | 3);
+      OUT_RING(0x00000001);
+      OUT_RING(0x00000000);
+      OUT_RING(0x00000000);
+      OUT_RING(0x00000000);
+
+      /* front buffer, pitch, offset */
+      OUT_RING(_3DSTATE_BUF_INFO_CMD);
+      OUT_RING(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
+	       BUF_3D_PITCH(pI830->displayWidth * pI830->cpp));
+      if (I830IsPrimary(pScrn))
+         OUT_RING(pI830->FrontBuffer.Start);
+      else 
+         OUT_RING(pI8301->FrontBuffer2.Start);
+
+      /* Set the entire frontbuffer up as a texture */
+      OUT_RING(_3DSTATE_MAP_STATE | 3);
+      OUT_RING(0x00000001);
+
+      if (I830IsPrimary(pScrn)) 
+         OUT_RING(pI830->RotatedMem.Start);
+      else 
+	 OUT_RING(pI8301->RotatedMem2.Start);
+
+      if (pI830->disableTiling)
+         use_fence = 0;
+      else
+         use_fence = 4;
+      
+      if (pI830->cpp == 1)
+	 use_fence |= MAPSURF_8BIT;
+      else
+      if (pI830->cpp == 2)
+	 use_fence |= MAPSURF_16BIT;
+      else
+	 use_fence |= MAPSURF_32BIT;
+      OUT_RING(use_fence | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10);
+      OUT_RING(((((pScrn->displayWidth * pI830->cpp) / 4) - 1) << 21));
+      ADVANCE_LP_RING();
+
+      /* fragment program - texture blend replace*/
+      FS_BEGIN();
+      i915_fs_dcl(FS_S0);
+      i915_fs_dcl(FS_T0);
+      i915_fs_texld(FS_OC, FS_S0, FS_T0);
+      FS_END();
+   }
+   
+   {
+      BEGIN_LP_RING(2);
+      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      OUT_RING(0x00000000);
+      ADVANCE_LP_RING();
+   }
+
+   while (nbox--)
+   {
+      box_x1 = pbox->x1;
+      box_y1 = pbox->y1;
+      box_x2 = pbox->x2;
+      box_y2 = pbox->y2;
+      pbox++;
+
+      BEGIN_LP_RING(40);
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+
+      /* vertex data */
+      OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (32 - 1));
+      verts[0][0] = box_x1; verts[0][1] = box_y1;
+      verts[1][0] = box_x2; verts[1][1] = box_y1;
+      verts[2][0] = box_x2; verts[2][1] = box_y2;
+      verts[3][0] = box_x1; verts[3][1] = box_y2;
+      tex[0][0] = box_x1; tex[0][1] = box_y1;
+      tex[1][0] = box_x2; tex[1][1] = box_y1;
+      tex[2][0] = box_x2; tex[2][1] = box_y2;
+      tex[3][0] = box_x1; tex[3][1] = box_y2;
+
+      /* transform coordinates to rotated versions, but leave texcoords unchanged */
+      for (j = 0; j < 4; j++)
+         matrix23TransformCoordf(&rotMatrix, &verts[j][0], &verts[j][1]);
+
+      /* emit vertex buffer */
+      draw_poly(vb, verts, tex);
+      for (j = 0; j < 32; j++)
+         OUT_RING(vb[j]);
+
+      ADVANCE_LP_RING();
+   }
+
+#ifdef XF86DRI
+   if (didLock)
+      I830DRIUnlock(pScrn1);
+#endif
+}
+
+static void
+I830UpdateRotate (ScreenPtr      pScreen,
+                 shadowBufPtr   pBuf)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+   I830Ptr pI8301 = NULL;
+   ScrnInfoPtr pScrn1 = pScrn;
+   RegionPtr	damage = shadowDamage(pBuf);
+   int		nbox = REGION_NUM_RECTS (damage);
+   BoxPtr		pbox = REGION_RECTS (damage);
+   int		box_x1, box_x2, box_y1, box_y2;
+   CARD32	vb[32];	/* 32 dword vertex buffer */
+   float verts[4][2], tex[4][2];
+   struct matrix23 rotMatrix;
+   Bool updateInvarient = FALSE;
+   int use_fence;
+   int j;
+#ifdef XF86DRI
+   drmI830Sarea *sarea = NULL;
+   drm_context_t myContext = 0;
+#endif
+   Bool didLock = FALSE;
+
+   if (I830IsPrimary(pScrn)) {
+      pI8301 = pI830;
+   } else {
+      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pScrn1 = pI830->entityPrivate->pScrn_1;
+   }
+
+   switch (pI830->rotation) {
+      case RR_Rotate_90:
+         matrix23Rotate(&rotMatrix,
+                     pScreen->width, pScreen->height,
+                     90);
+	 break;
+      case RR_Rotate_180:
+         matrix23Rotate(&rotMatrix,
+                     pScreen->width, pScreen->height,
+                     180);
+	 break;
+      case RR_Rotate_270:
+         matrix23Rotate(&rotMatrix,
+                     pScreen->width, pScreen->height,
+                     270);
+	 break;
+      default:
+	 break;
+   }
+
+#ifdef XF86DRI
+   if (pI8301->directRenderingEnabled) {
+      sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
+      myContext = DRIGetContext(pScrn1->pScreen);
+      didLock = I830DRILock(pScrn1);
+   }
+#endif
+
+   if (pScrn->scrnIndex != *pI830->used3D)
+      updateInvarient = TRUE;
+
+#ifdef XF86DRI
+   if (sarea && sarea->ctxOwner != myContext)
+      updateInvarient = TRUE;
+#endif
+
+   if (updateInvarient) {
+      *pI830->used3D = pScrn->scrnIndex;
+#ifdef XF86DRI
+      if (sarea)
+         sarea->ctxOwner = myContext;
+#endif
+      
+      BEGIN_LP_RING(48);
+      OUT_RING(0x682008a1);
+      OUT_RING(0x6f402100);
+      OUT_RING(0x62120aa9);
+      OUT_RING(0x76b3ffff);
+      OUT_RING(0x6c818a01);
+      OUT_RING(0x6ba008a1);
+      OUT_RING(0x69802100);
+      OUT_RING(0x63a00aaa);
+      OUT_RING(0x6423070e);
+      OUT_RING(0x66014142);
+      OUT_RING(0x75000000);
+      OUT_RING(0x7d880000);
+      OUT_RING(0x00000000);
+      OUT_RING(0x650001c4);
+      OUT_RING(0x6a000000);
+      OUT_RING(0x7d020000);
+      OUT_RING(0x0000ba98);
+
+      /* flush map & render cache */
+      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      OUT_RING(0x00000000);
+      /* draw rect */
+      OUT_RING(0x7d800003);
+      OUT_RING(0x00000000);
+      OUT_RING(0x00000000);
+      OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16);
+      OUT_RING(0x00000000);
+      OUT_RING(0x00000000);
+
+      /* front buffer */
+      OUT_RING(0x7d8e0001);
+      OUT_RING(0x03800000 | (((pI830->displayWidth * pI830->cpp) / 4) << 2));
+      if (I830IsPrimary(pScrn))
+	 OUT_RING(pI830->FrontBuffer.Start);
+      else 
+	 OUT_RING(pI8301->FrontBuffer2.Start);
+      OUT_RING(0x7d850000);
+      if (pI830->cpp == 1)
+	 OUT_RING(0x00880000);
+      else
+	 if (pI830->cpp == 2)
+	    OUT_RING(0x00880200);
+	 else
+	    OUT_RING(0x00880308);
+      /* scissor */
+      OUT_RING(0x7c800002);
+      OUT_RING(0x7d810001);
+      OUT_RING(0x00000000);
+      OUT_RING(0x00000000);
+      /* stipple */
+      OUT_RING(0x7d830000);
+      OUT_RING(0x00000000);
+
+      /* texture blend replace */
+      OUT_RING(0x7c088088);
+      OUT_RING(0x00000000);
+      OUT_RING(0x6d021181);
+      OUT_RING(0x6d060101);
+      OUT_RING(0x6e008046);
+      OUT_RING(0x6e048046);
+
+
+      /* Set the entire frontbuffer up as a texture */
+      OUT_RING(0x7d030804);
+
+      if (pI830->disableTiling)
+         use_fence = 0;
+      else
+         use_fence = 2;
+
+      if (I830IsPrimary(pScrn)) 
+         OUT_RING(pI830->RotatedMem.Start | use_fence);
+      else 
+	 OUT_RING(pI8301->RotatedMem2.Start | use_fence);
+
+      if (pI830->cpp == 1)
+         OUT_RING(0x40 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10);
+      else if (pI830->cpp == 2)
+         OUT_RING(0x80 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10);
+      else
+         OUT_RING(0xc0 | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10);
+
+      OUT_RING((((pScrn->displayWidth * pI830->cpp / 4) - 1) << 21));
+      OUT_RING(0x00000000);
+      OUT_RING(0x00000000);
+
+
+      ADVANCE_LP_RING();
+   }
+
+   {
+      BEGIN_LP_RING(2);
+      /* flush map & render cache */
+      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      OUT_RING(0x00000000);
+      ADVANCE_LP_RING();
+   }
+
+   while (nbox--)
+   {
+      box_x1 = pbox->x1;
+      box_y1 = pbox->y1;
+      box_x2 = pbox->x2;
+      box_y2 = pbox->y2;
+      pbox++;
+
+      BEGIN_LP_RING(40);
+
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+      OUT_RING(MI_NOOP);
+
+      /* vertex data */
+      OUT_RING(0x7f0c001f);
+      verts[0][0] = box_x1; verts[0][1] = box_y1;
+      verts[1][0] = box_x2; verts[1][1] = box_y1;
+      verts[2][0] = box_x2; verts[2][1] = box_y2;
+      verts[3][0] = box_x1; verts[3][1] = box_y2;
+      tex[0][0] = box_x1; tex[0][1] = box_y1;
+      tex[1][0] = box_x2; tex[1][1] = box_y1;
+      tex[2][0] = box_x2; tex[2][1] = box_y2;
+      tex[3][0] = box_x1; tex[3][1] = box_y2;
+
+      /* transform coordinates to rotated versions, but leave texcoords unchanged */
+      for (j = 0; j < 4; j++)
+         matrix23TransformCoordf(&rotMatrix, &verts[j][0], &verts[j][1]);
+
+      /* emit vertex buffer */
+      draw_poly(vb, verts, tex);
+      for (j = 0; j < 32; j++)
+         OUT_RING(vb[j]);
+
+      OUT_RING(0x05000000);
+      OUT_RING(0x00000000);
+
+      ADVANCE_LP_RING();
+   }
+
+   {
+      BEGIN_LP_RING(2);
+      /* flush map & render cache */
+      OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+      OUT_RING(0x00000000);
+      ADVANCE_LP_RING();
+   }
+
+#ifdef XF86DRI
+   if (didLock)
+      I830DRIUnlock(pScrn1);
+#endif
+}
+
+Bool
+I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   I830Ptr pI8301 = NULL;
+   I830Ptr pI8302 = NULL;
+   ScrnInfoPtr pScrn1 = NULL;
+   ScrnInfoPtr pScrn2 = NULL;
+   int i;
+   ShadowUpdateProc func = NULL;
+   Rotation oldRotation = pI830->rotation; /* save old state */
+   int displayWidth = pScrn->displayWidth; /* save displayWidth */
+   Bool reAllocate = TRUE;
+   Bool didLock = FALSE;
+
+   /* Good pitches to allow tiling.  Don't care about pitches < 1024. */
+   static const int pitches[] = {
+/*
+	 128 * 2,
+	 128 * 4,
+*/
+	 128 * 8,
+	 128 * 16,
+	 128 * 32,
+	 128 * 64,
+	 0
+   };
+
+   if (pI830->noAccel)
+	   func = LoaderSymbol("shadowUpdateRotatePacked");
+   else
+	   if (IS_I9XX(pI830))
+		   func = I915UpdateRotate;
+	   else
+		   func = I830UpdateRotate;
+
+   if (I830IsPrimary(pScrn)) {
+      pI8301 = pI830;
+      pScrn1 = pScrn;
+      if (pI830->entityPrivate) {
+         pI8302 = I830PTR(pI830->entityPrivate->pScrn_2);
+         pScrn2 = pI830->entityPrivate->pScrn_2;
+      }
+   } else {
+      pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pScrn1 = pI830->entityPrivate->pScrn_1;
+      pI8302 = pI830;
+      pScrn2 = pScrn;
+   }
+
+   pI830->rotation = I830GetRotation(pScrn->pScreen);
+
+   /* Check if we've still got the same orientation, or same mode */
+   if (pI830->rotation == oldRotation && pI830->currentMode == mode)
+#if 0
+	reAllocate = FALSE;
+#else
+	return TRUE;
+#endif
+
+   /* 
+    * We grab the DRI lock when reallocating buffers to avoid DRI clients
+    * getting bogus information.
+    */
+#ifdef XF86DRI
+   if (pI8301->directRenderingEnabled && reAllocate) {
+      didLock = I830DRILock(pScrn1);
+      
+#ifdef NO_TTM
+      /* Do heap teardown here
+       */
+      {
+	 drmI830MemDestroyHeap destroy;
+	 destroy.region = I830_MEM_REGION_AGP;
+	 
+	 if (drmCommandWrite(pI8301->drmSubFD, 
+			     DRM_I830_DESTROY_HEAP, 
+			     &destroy, sizeof(destroy))) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "[dri] I830 destroy heap failed\n");
+	 }
+      }
+#endif
+      
+      if (pI8301->TexMem.Key != -1)
+         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key);
+      I830FreeVidMem(pScrn1, &(pI8301->TexMem));
+      if (pI8301->StolenPool.Allocated.Key != -1) {
+         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key);
+         xf86DeallocateGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key);
+      }
+      if (pI8301->DepthBuffer.Key != -1)
+         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key);
+      I830FreeVidMem(pScrn1, &(pI8301->DepthBuffer));
+      if (pI8301->BackBuffer.Key != -1)
+         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key);
+      I830FreeVidMem(pScrn1, &(pI8301->BackBuffer));
+   }
+#endif
+
+   if (reAllocate) {
+      *pI830->used3D |= 1<<31; /* use high bit to denote new rotation occured */
+
+      if (pI8301->RotatedMem.Key != -1)
+         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key);
+ 
+      I830FreeVidMem(pScrn1, &(pI8301->RotatedMem));
+      memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem));
+      pI8301->RotatedMem.Key = -1;
+
+      if (pI830->entityPrivate) {
+         if (pI8301->RotatedMem2.Key != -1)
+            xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key);
+ 
+         I830FreeVidMem(pScrn1, &(pI8301->RotatedMem2));
+         memset(&(pI8301->RotatedMem2), 0, sizeof(pI8301->RotatedMem2));
+         pI8301->RotatedMem2.Key = -1;
+      }
+   }
+
+   switch (pI830->rotation) {
+      case RR_Rotate_0:
+         if (reAllocate)
+            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Rotating Screen to 0 degrees\n");
+         pScrn->displayWidth = pI830->displayWidth;
+         break;
+      case RR_Rotate_90:
+         if (reAllocate)
+            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Rotating Screen to 90 degrees\n");
+         pScrn->displayWidth = pScrn->pScreen->width;
+         break;
+      case RR_Rotate_180:
+         if (reAllocate)
+            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Rotating Screen to 180 degrees\n");
+         pScrn->displayWidth = pI830->displayWidth;
+         break;
+      case RR_Rotate_270:
+         if (reAllocate)
+            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Rotating Screen to 270 degrees\n");
+         pScrn->displayWidth = pScrn->pScreen->width;
+         break;
+   }
+
+   /* As DRI doesn't run on the secondary head, we know that disableTiling
+    * is always TRUE.
+    */
+   if (I830IsPrimary(pScrn) && !pI830->disableTiling) {
+#if 0
+      int dWidth = pScrn->displayWidth; /* save current displayWidth */
+#endif
+
+      for (i = 0; pitches[i] != 0; i++) {
+         if (pitches[i] >= pScrn->displayWidth) {
+            pScrn->displayWidth = pitches[i];
+            break;
+         }
+      }
+
+      /*
+       * If the displayWidth is a tilable pitch, test if there's enough
+       * memory available to enable tiling.
+       */
+      if (pScrn->displayWidth == pitches[i]) {
+  	/* TODO */
+      }
+   }
+
+   if (reAllocate) {
+      if (pI830->entityPrivate) {
+         if (pI8302->rotation != RR_Rotate_0) {
+            if (!I830AllocateRotated2Buffer(pScrn1, 
+			      pI8302->disableTiling ? ALLOC_NO_TILING : 0))
+               goto BAIL0;
+
+            I830FixOffset(pScrn1, &(pI8301->RotatedMem2));
+            if (pI8301->RotatedMem2.Key != -1)
+               xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key, pI8301->RotatedMem2.Offset);
+         }
+      }
+
+      if (pI8301->rotation != RR_Rotate_0) {
+         if (!I830AllocateRotatedBuffer(pScrn1, 
+			      (pI8301->disableTiling ? ALLOC_NO_TILING : 0)))
+            goto BAIL1;
+
+         I830FixOffset(pScrn1, &(pI8301->RotatedMem));
+         if (pI8301->RotatedMem.Key != -1)
+            xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key, pI8301->RotatedMem.Offset);
+      }
+   }
+   
+   shadowRemove (pScrn->pScreen, NULL);
+   if (pI830->rotation != RR_Rotate_0)
+      shadowAdd (pScrn->pScreen, 
+                    (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), 
+                    func, I830WindowLinear, pI830->rotation, 0);
+
+   if (I830IsPrimary(pScrn)) {
+      if (pI830->rotation != RR_Rotate_0)
+         pScrn->fbOffset = pI830->RotatedMem.Start;
+      else
+         pScrn->fbOffset = pI830->FrontBuffer.Start;
+      if (pI830->entityPrivate) {
+         if (pI8302->rotation != RR_Rotate_0) 
+            pScrn2->fbOffset = pI8301->RotatedMem2.Start;
+         else
+            pScrn2->fbOffset = pI8301->FrontBuffer2.Start;
+         I830SelectBuffer(pScrn2, I830_SELECT_FRONT);
+      }
+   } else {
+      if (pI830->rotation != RR_Rotate_0)
+         pScrn->fbOffset = pI8301->RotatedMem2.Start;
+      else
+         pScrn->fbOffset = pI8301->FrontBuffer2.Start;
+      if (pI8301->rotation != RR_Rotate_0)
+         pScrn1->fbOffset = pI8301->RotatedMem.Start;
+      else
+         pScrn1->fbOffset = pI8301->FrontBuffer.Start;
+      I830SelectBuffer(pScrn1, I830_SELECT_FRONT);
+   }
+   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+#ifdef XF86DRI
+   if (pI8301->directRenderingEnabled && reAllocate) {
+      if (!I830AllocateBackBuffer(pScrn1,
+			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
+         goto BAIL2;
+
+      if (!I830AllocateDepthBuffer(pScrn1,
+			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
+         goto BAIL3;
+
+      if (!I830AllocateTextureMemory(pScrn1,
+			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
+         goto BAIL4;
+
+      I830DoPoolAllocation(pScrn1, &(pI8301->StolenPool));
+
+      I830FixOffset(pScrn1, &(pI8301->BackBuffer));
+      I830FixOffset(pScrn1, &(pI8301->DepthBuffer));
+
+      if (pI8301->BackBuffer.Key != -1)
+         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key, pI8301->BackBuffer.Offset);
+      if (pI8301->DepthBuffer.Key != -1)
+         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key, pI8301->DepthBuffer.Offset);
+      if (pI8301->StolenPool.Allocated.Key != -1)
+         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key, pI8301->StolenPool.Allocated.Offset);
+      if (pI8301->TexMem.Key != -1)
+         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.Offset);
+      I830SetupMemoryTiling(pScrn1);
+      /* update fence registers */
+      for (i = 0; i < 8; i++) 
+         OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]);
+      {
+         drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
+         I830UpdateDRIBuffers(pScrn1, sarea );
+      }
+      
+      if (didLock)
+	 I830DRIUnlock(pScrn1);
+   }
+#endif
+
+#if 0
+   if (I830IsPrimary(pScrn)) {
+      pI830->xoffset = (pI830->FrontBuffer.Start / pI830->cpp) % pI830->displayWidth;
+      pI830->yoffset = (pI830->FrontBuffer.Start / pI830->cpp) / pI830->displayWidth;
+   } else {
+      I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+      pI830->xoffset = (pI8301->FrontBuffer2.Start / pI830->cpp) % pI830->displayWidth;
+      pI830->yoffset = (pI8301->FrontBuffer2.Start / pI830->cpp) / pI830->displayWidth;
+   }
+#endif
+
+   pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen), pScrn->pScreen->width,
+		    pScrn->pScreen->height, pScrn->pScreen->rootDepth, pScrn->bitsPerPixel,
+		    PixmapBytePad(pScrn->displayWidth, pScrn->pScreen->rootDepth), 
+		    (pointer)(pI8301->FbBase + pScrn->fbOffset));
+
+   if (pI830->entityPrivate) {
+      if (I830IsPrimary(pScrn)) {
+         if (!pI830->starting) {
+            pScrn2->pScreen->ModifyPixmapHeader((*pScrn2->pScreen->GetScreenPixmap)(pScrn2->pScreen), pScrn2->pScreen->width,
+		    pScrn2->pScreen->height, pScrn2->pScreen->rootDepth, pScrn2->bitsPerPixel,
+		    PixmapBytePad(pScrn2->displayWidth, pScrn2->pScreen->rootDepth), 
+		    (pointer)(pI8301->FbBase + pScrn2->fbOffset));
+
+            /* Repaint the second head */
+            (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE);
+            (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE);
+         }
+      } else {
+         if (!pI830->starting) {
+            pScrn1->pScreen->ModifyPixmapHeader((*pScrn1->pScreen->GetScreenPixmap)(pScrn1->pScreen), pScrn1->pScreen->width,
+		    pScrn1->pScreen->height, pScrn1->pScreen->rootDepth, pScrn1->bitsPerPixel,
+		    PixmapBytePad(pScrn1->displayWidth, pScrn1->pScreen->rootDepth), 
+		    (pointer)(pI8301->FbBase + pScrn1->fbOffset));
+
+            /* Repaint the first head */
+            (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, FALSE);
+            (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, TRUE);
+         }
+      }
+   }
+
+   /* Don't allow pixmap cache or offscreen pixmaps when rotated */
+   /* XAA needs some serious fixing for this to happen */
+   if (pI830->rotation == RR_Rotate_0) {
+      pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE;
+      pI830->AccelInfoRec->UsingPixmapCache = TRUE;
+      /* funny as it seems this will enable XAA's createpixmap */
+      pI830->AccelInfoRec->maxOffPixWidth = 0;
+      pI830->AccelInfoRec->maxOffPixHeight = 0;
+   } else {
+      pI830->AccelInfoRec->Flags = LINEAR_FRAMEBUFFER;
+      pI830->AccelInfoRec->UsingPixmapCache = FALSE;
+      /* funny as it seems this will disable XAA's createpixmap */
+      pI830->AccelInfoRec->maxOffPixWidth = 1;
+      pI830->AccelInfoRec->maxOffPixHeight = 1;
+   }
+
+   return TRUE;
+
+BAIL4:
+#ifdef XF86DRI
+   if (pI8301->directRenderingEnabled)
+      I830FreeVidMem(pScrn1, &(pI8301->DepthBuffer));
+#endif
+BAIL3:
+#ifdef XF86DRI
+   if (pI8301->directRenderingEnabled)
+      I830FreeVidMem(pScrn1, &(pI8301->BackBuffer));
+#endif
+BAIL2:
+   if (pI8301->rotation != RR_Rotate_0) {
+      if (pI8301->RotatedMem.Key != -1)
+         xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key);
+  
+      I830FreeVidMem(pScrn1, &(pI8301->RotatedMem));
+      memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem));
+      pI8301->RotatedMem.Key = -1;
+   }
+BAIL1:
+   if (pI830->entityPrivate) {
+      if (pI8302->rotation != RR_Rotate_0) {
+         if (pI8301->RotatedMem.Key != -1)
+            xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key);
+
+         I830FreeVidMem(pScrn1, &(pI8301->RotatedMem));
+         memset(&(pI8301->RotatedMem), 0, sizeof(pI8301->RotatedMem));
+         pI8301->RotatedMem.Key = -1;
+      }
+   }
+BAIL0:
+   pScrn->displayWidth = displayWidth;
+
+   /* must flip mmWidth & mmHeight */
+   if ( ((oldRotation & (RR_Rotate_90 | RR_Rotate_270)) &&
+	 (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))) ||
+        ((oldRotation & (RR_Rotate_0 | RR_Rotate_180)) &&
+	 (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270))) ) {
+      int tmp = pScrn->pScreen->mmWidth;
+      pScrn->pScreen->mmWidth = pScrn->pScreen->mmHeight;
+      pScrn->pScreen->mmHeight = tmp;
+   }
+
+   if (oldRotation & (RR_Rotate_0 | RR_Rotate_180)) {
+      pScrn->pScreen->width = pScrn->virtualX;
+      pScrn->pScreen->height = pScrn->virtualY;
+   } else {
+      pScrn->pScreen->width = pScrn->virtualY;
+      pScrn->pScreen->height = pScrn->virtualX;
+   }
+
+   pI830->rotation = oldRotation;
+
+   if (pI830->entityPrivate) {
+      if (pI8302->rotation != RR_Rotate_0) {
+         if (!I830AllocateRotated2Buffer(pScrn1, 
+			      pI8302->disableTiling ? ALLOC_NO_TILING : 0))
+            xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+		    "Oh dear, the rotated2 buffer failed - badness\n");
+
+         I830FixOffset(pScrn1, &(pI8301->RotatedMem2));
+         if (pI8301->RotatedMem2.Key != -1)
+            xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem2.Key, pI8301->RotatedMem2.Offset);
+      }
+   }
+
+   if (pI8301->rotation != RR_Rotate_0) {
+      if (!I830AllocateRotatedBuffer(pScrn1, 
+			      (pI8301->disableTiling ? ALLOC_NO_TILING : 0)))
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+		    "Oh dear, the rotated buffer failed - badness\n");
+
+      I830FixOffset(pScrn1, &(pI8301->RotatedMem));
+      if (pI8301->RotatedMem.Key != -1)
+         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->RotatedMem.Key, pI8301->RotatedMem.Offset);
+   }
+
+   shadowRemove (pScrn->pScreen, NULL);
+   if (pI830->rotation != RR_Rotate_0)
+      shadowAdd (pScrn->pScreen, 
+                    (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), 
+                    func, I830WindowLinear, pI830->rotation, 0);
+
+   if (I830IsPrimary(pScrn)) {
+      if (pI830->rotation != RR_Rotate_0)
+         pScrn->fbOffset = pI830->RotatedMem.Start;
+      else
+         pScrn->fbOffset = pI830->FrontBuffer.Start;
+      if (pI830->entityPrivate) {
+         if (pI8302->rotation != RR_Rotate_0) 
+            pScrn2->fbOffset = pI8301->RotatedMem2.Start;
+         else
+            pScrn2->fbOffset = pI8301->FrontBuffer2.Start;
+         I830SelectBuffer(pScrn2, I830_SELECT_FRONT);
+      }
+   } else {
+      if (pI830->rotation != RR_Rotate_0)
+         pScrn->fbOffset = pI8301->RotatedMem2.Start;
+      else
+         pScrn->fbOffset = pI8301->FrontBuffer2.Start;
+      if (pI8301->rotation != RR_Rotate_0)
+         pScrn1->fbOffset = pI8301->RotatedMem.Start;
+      else
+         pScrn1->fbOffset = pI8301->FrontBuffer.Start;
+      I830SelectBuffer(pScrn1, I830_SELECT_FRONT);
+   }
+   I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Reverting to previous configured mode\n");
+
+   switch (oldRotation) {
+      case RR_Rotate_0:
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Rotating Screen back to 0 degrees\n");
+         break;
+      case RR_Rotate_90:
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Rotating Screen back to 90 degrees\n");
+         break;
+      case RR_Rotate_180:
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Rotating Screen back to 180 degrees\n");
+         break;
+      case RR_Rotate_270:
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Rotating Screen back to 270 degrees\n");
+         break;
+   }
+
+#ifdef XF86DRI
+   if (pI8301->directRenderingEnabled) {
+      if (!I830AllocateBackBuffer(pScrn1,
+			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
+         xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 
+		    "Oh dear, the back buffer failed - badness\n");
+
+      if (!I830AllocateDepthBuffer(pScrn1,
+			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
+         xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 
+		    "Oh dear, the depth buffer failed - badness\n");
+
+      if (!I830AllocateTextureMemory(pScrn1,
+			      pI8301->disableTiling ? ALLOC_NO_TILING : 0))
+         xf86DrvMsg(pScrn1->scrnIndex, X_INFO, 
+		    "Oh dear, the texture cache failed - badness\n");
+
+      I830DoPoolAllocation(pScrn1, &(pI8301->StolenPool));
+
+      I830FixOffset(pScrn1, &(pI8301->BackBuffer));
+      I830FixOffset(pScrn1, &(pI8301->DepthBuffer));
+
+      if (pI8301->BackBuffer.Key != -1)
+         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->BackBuffer.Key, pI8301->BackBuffer.Offset);
+      if (pI8301->DepthBuffer.Key != -1)
+         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->DepthBuffer.Key, pI8301->DepthBuffer.Offset);
+      if (pI8301->StolenPool.Allocated.Key != -1)
+         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->StolenPool.Allocated.Key, pI8301->StolenPool.Allocated.Offset);
+      if (pI8301->TexMem.Key != -1)
+         xf86BindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key, pI8301->TexMem.Offset);
+      I830SetupMemoryTiling(pScrn1);
+      /* update fence registers */
+      for (i = 0; i < 8; i++) 
+         OUTREG(FENCE + i * 4, pI8301->ModeReg.Fence[i]);
+      { 
+         drmI830Sarea *sarea = DRIGetSAREAPrivate(pScrn1->pScreen);
+         I830UpdateDRIBuffers(pScrn1, sarea );
+      }
+      
+      if (didLock)
+	 I830DRIUnlock(pScrn1);
+   }
+#endif
+
+   pScrn->pScreen->ModifyPixmapHeader((*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen), pScrn->pScreen->width,
+		    pScrn->pScreen->height, pScrn->pScreen->rootDepth, pScrn->bitsPerPixel,
+		    PixmapBytePad(pScrn->displayWidth, pScrn->pScreen->rootDepth), 
+		    (pointer)(pI8301->FbBase + pScrn->fbOffset));
+
+   if (pI830->entityPrivate) {
+      if (I830IsPrimary(pScrn)) {
+         pScrn2->pScreen->ModifyPixmapHeader((*pScrn2->pScreen->GetScreenPixmap)(pScrn2->pScreen), pScrn2->pScreen->width,
+		    pScrn2->pScreen->height, pScrn2->pScreen->rootDepth, pScrn2->bitsPerPixel,
+		    PixmapBytePad(pScrn2->displayWidth, pScrn2->pScreen->rootDepth), 
+		    (pointer)(pI8301->FbBase + pScrn2->fbOffset));
+
+         /* Repaint the second head */
+         (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE);
+         (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE);
+      } else {
+         pScrn1->pScreen->ModifyPixmapHeader((*pScrn1->pScreen->GetScreenPixmap)(pScrn1->pScreen), pScrn1->pScreen->width,
+		    pScrn1->pScreen->height, pScrn1->pScreen->rootDepth, pScrn1->bitsPerPixel,
+		    PixmapBytePad(pScrn1->displayWidth, pScrn1->pScreen->rootDepth), 
+		    (pointer)(pI8301->FbBase + pScrn1->fbOffset));
+
+         /* Repaint the first head */
+         (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, FALSE);
+         (*pScrn1->EnableDisableFBAccess) (pScrn1->pScreen->myNum, TRUE);
+      }
+   }
+
+   return FALSE;
+}
diff --git a/src/i830_shadow.c b/src/i830_shadow.c
deleted file mode 100644
index 93c72c5..0000000
--- a/src/i830_shadow.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_shadow.c,v 1.3 2000/03/31 20:13:33 dawes Exp $ */
-
-/*
-   Copyright (c) 1999,2000  The XFree86 Project Inc. 
-   based on code written by Mark Vojkovich <markv at valinux.com>
-*/
-
-/*
- * Ported from the savage driver to the I830 by
- * Helmar Spangenberg <hspangenberg at frey.de> and Dima Dorfman
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "xf86.h"
-#include "i830.h"
-#include "shadowfb.h"
-#include "servermd.h"
-
-
-void
-I830RefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    int width, height, Bpp, FBPitch;
-    unsigned char *src, *dst;
-   
-    Bpp = pScrn->bitsPerPixel >> 3;
-    FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
-
-    while(num--) {
-	width = (pbox->x2 - pbox->x1) * Bpp;
-	height = pbox->y2 - pbox->y1;
-	src = pI830->shadowPtr + (pbox->y1 * pI830->shadowPitch) + 
-						(pbox->x1 * Bpp);
-	dst = pI830->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
-
-	while(height--) {
-	    memcpy(dst, src, width);
-	    dst += FBPitch;
-	    src += pI830->shadowPitch;
-	}
-	
-	pbox++;
-    }
-} 
-
-
-void
-I830PointerMoved(int index, int x, int y)
-{
-    ScrnInfoPtr pScrn = xf86Screens[index];
-    I830Ptr pI830 = I830PTR(pScrn);
-    int newX, newY;
-
-    if(pI830->rotate == 1) {
-	newX = pScrn->pScreen->height - y - 1;
-	newY = x;
-    } else {
-	newX = y;
-	newY = pScrn->pScreen->width - x - 1;
-    }
-
-    (*pI830->PointerMoved)(index, newX, newY);
-}
-
-void
-I830RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    int count, width, height, y1, y2, dstPitch, srcPitch;
-    CARD8 *dstPtr, *srcPtr, *src;
-    CARD32 *dst;
-
-    dstPitch = pScrn->displayWidth;
-    srcPitch = -pI830->rotate * pI830->shadowPitch;
-
-    while(num--) {
-	width = pbox->x2 - pbox->x1;
-	y1 = pbox->y1 & ~3;
-	y2 = (pbox->y2 + 3) & ~3;
-	height = (y2 - y1) >> 2;  /* in dwords */
-
-	if(pI830->rotate == 1) {
-	    dstPtr = pI830->FbBase + 
-			(pbox->x1 * dstPitch) + pScrn->virtualX - y2;
-	    srcPtr = pI830->shadowPtr + ((1 - y2) * srcPitch) + pbox->x1;
-	} else {
-	    dstPtr = pI830->FbBase + 
-			((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
-	    srcPtr = pI830->shadowPtr + (y1 * srcPitch) + pbox->x2 - 1;
-	}
-
-	while(width--) {
-	    src = srcPtr;
-	    dst = (CARD32*)dstPtr;
-	    count = height;
-	    while(count--) {
-		*(dst++) = src[0] | (src[srcPitch] << 8) | 
-					(src[srcPitch * 2] << 16) | 
-					(src[srcPitch * 3] << 24);
-		src += srcPitch * 4;
-	    }
-	    srcPtr += pI830->rotate;
-	    dstPtr += dstPitch;
-	}
-
-	pbox++;
-    }
-} 
-
-
-void
-I830RefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    int count, width, height, y1, y2, dstPitch, srcPitch;
-    CARD16 *dstPtr, *srcPtr, *src;
-    CARD32 *dst;
-
-    dstPitch = pScrn->displayWidth;
-    srcPitch = -pI830->rotate * pI830->shadowPitch >> 1;
-
-    while(num--) {
-	width = pbox->x2 - pbox->x1;
-	y1 = pbox->y1 & ~1;
-	y2 = (pbox->y2 + 1) & ~1;
-	height = (y2 - y1) >> 1;  /* in dwords */
-
-	if(pI830->rotate == 1) {
-	    dstPtr = (CARD16*)pI830->FbBase + 
-			(pbox->x1 * dstPitch) + pScrn->virtualX - y2;
-	    srcPtr = (CARD16*)pI830->shadowPtr + 
-			((1 - y2) * srcPitch) + pbox->x1;
-	} else {
-	    dstPtr = (CARD16*)pI830->FbBase + 
-			((pScrn->virtualY - pbox->x2) * dstPitch) + y1;
-	    srcPtr = (CARD16*)pI830->shadowPtr + 
-			(y1 * srcPitch) + pbox->x2 - 1;
-	}
-
-	while(width--) {
-	    src = srcPtr;
-	    dst = (CARD32*)dstPtr;
-	    count = height;
-	    while(count--) {
-		*(dst++) = src[0] | (src[srcPitch] << 16);
-		src += srcPitch * 2;
-	    }
-	    srcPtr += pI830->rotate;
-	    dstPtr += dstPitch;
-	}
-
-	pbox++;
-    }
-}
-
-
-/* this one could be faster */
-void
-I830RefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    int count, width, height, y1, y2, dstPitch, srcPitch;
-    CARD8 *dstPtr, *srcPtr, *src;
-    CARD32 *dst;
-
-    dstPitch = BitmapBytePad(pScrn->displayWidth * 24);
-    srcPitch = -pI830->rotate * pI830->shadowPitch;
-
-    while(num--) {
-        width = pbox->x2 - pbox->x1;
-        y1 = pbox->y1 & ~3;
-        y2 = (pbox->y2 + 3) & ~3;
-        height = (y2 - y1) >> 2;  /* blocks of 3 dwords */
-
-	if(pI830->rotate == 1) {
-	    dstPtr = pI830->FbBase + 
-			(pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3);
-	    srcPtr = pI830->shadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3);
-	} else {
-	    dstPtr = pI830->FbBase + 
-			((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3);
-	    srcPtr = pI830->shadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3;
-	}
-
-	while(width--) {
-	    src = srcPtr;
-	    dst = (CARD32*)dstPtr;
-	    count = height;
-	    while(count--) {
-		dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) |
-				(src[srcPitch] << 24);		
-		dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) |
-				(src[srcPitch * 2] << 16) |
-				(src[(srcPitch * 2) + 1] << 24);		
-		dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) |
-				(src[(srcPitch * 3) + 1] << 16) |
-				(src[(srcPitch * 3) + 2] << 24);	
-		dst += 3;
-		src += srcPitch * 4;
-	    }
-	    srcPtr += pI830->rotate * 3;
-	    dstPtr += dstPitch; 
-	}
-
-	pbox++;
-    }
-}
-
-void
-I830RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    int count, width, height, dstPitch, srcPitch;
-    CARD32 *dstPtr, *srcPtr, *src, *dst;
-
-    dstPitch = pScrn->displayWidth;
-    srcPitch = -pI830->rotate * pI830->shadowPitch >> 2;
-
-    while(num--) {
-	width = pbox->x2 - pbox->x1;
-	height = pbox->y2 - pbox->y1;
-
-	if(pI830->rotate == 1) {
-	    dstPtr = (CARD32*)pI830->FbBase + 
-			(pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2;
-	    srcPtr = (CARD32*)pI830->shadowPtr + 
-			((1 - pbox->y2) * srcPitch) + pbox->x1;
-	} else {
-	    dstPtr = (CARD32*)pI830->FbBase + 
-			((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1;
-	    srcPtr = (CARD32*)pI830->shadowPtr + 
-			(pbox->y1 * srcPitch) + pbox->x2 - 1;
-	}
-
-	while(width--) {
-	    src = srcPtr;
-	    dst = dstPtr;
-	    count = height;
-	    while(count--) {
-		*(dst++) = *src;
-		src += srcPitch;
-	    }
-	    srcPtr += pI830->rotate;
-	    dstPtr += dstPitch;
-	}
-
-	pbox++;
-    }
-}
diff --git a/src/i830_video.c b/src/i830_video.c
index 12c25e0..a608a7e 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -64,16 +64,18 @@ THE USE OR OTHER DEALINGS IN THE SOFTWAR
 #include "config.h"
 #endif
 
+#include <math.h>
+#include <string.h>
+
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
-#include "xf86_ansic.h"
 #include "compiler.h"
 #include "xf86PciInfo.h"
 #include "xf86Pci.h"
 #include "xf86fbman.h"
 #include "regionstr.h"
-
+#include "randrstr.h"
 #include "i830.h"
 #include "xf86xv.h"
 #include <X11/extensions/Xv.h>
@@ -106,7 +108,7 @@ static void I830QueryBestSize(ScrnInfoPt
 			      unsigned int *, pointer);
 static int I830PutImage(ScrnInfoPtr, short, short, short, short, short, short,
 			short, short, int, unsigned char *, short, short,
-			Bool, RegionPtr, pointer);
+			Bool, RegionPtr, pointer, DrawablePtr);
 static int I830QueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
 				    unsigned short *, int *, int *);
 
@@ -114,12 +116,13 @@ static void I830BlockHandler(int, pointe
 
 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
-static Atom xvBrightness, xvContrast, xvColorKey, xvPipe;
+static Atom xvBrightness, xvContrast, xvColorKey, xvPipe, xvDoubleBuffer;
 static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5;
 
-#define IMAGE_MAX_WIDTH		1440
-#define IMAGE_MAX_HEIGHT	1080
-#define Y_BUF_SIZE		(IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT)
+#define IMAGE_MAX_WIDTH		1920
+#define IMAGE_MAX_HEIGHT	1088
+#define IMAGE_MAX_WIDTH_LEGACY	1024
+#define IMAGE_MAX_HEIGHT_LEGACY	1088
 
 #if !VIDEO_DEBUG
 #define ErrorF Edummy
@@ -138,13 +141,13 @@ Edummy(const char *dummy, ...)
  * all modes of server exit.
  */
 
-#define OVERLAY_UPDATE							\
+#define OVERLAY_UPDATE						\
    do { 								\
       BEGIN_LP_RING(6);							\
       OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);			\
       OUT_RING(MI_NOOP);						\
       if (!*pI830->overlayOn) {						\
-	 OUT_RING(MI_NOOP);						\
+         OUT_RING(MI_NOOP);						\
 	 OUT_RING(MI_NOOP);						\
 	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON);		\
 	 ErrorF("Overlay goes from off to on\n");			\
@@ -154,7 +157,7 @@ Edummy(const char *dummy, ...)
 	 OUT_RING(MI_NOOP);						\
 	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);		\
       }									\
-      OUT_RING(pI830->OverlayMem->Physical | 1);			\
+      OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); 		\
       ADVANCE_LP_RING();						\
       ErrorF("OVERLAY_UPDATE\n");					\
    } while(0)
@@ -162,18 +165,28 @@ Edummy(const char *dummy, ...)
 #define OVERLAY_OFF							\
    do { 								\
       if (*pI830->overlayOn) {						\
-	 BEGIN_LP_RING(8);						\
+	 int spin = 1000000;						\
+	 BEGIN_LP_RING(12);						\
 	 OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE);			\
 	 OUT_RING(MI_NOOP);						\
 	 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);	\
 	 OUT_RING(MI_NOOP);						\
+	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE);		\
+         OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); 		\
+	 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);	\
+	 OUT_RING(MI_NOOP);						\
 	 OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF);		\
-	 OUT_RING(pI830->OverlayMem->Physical);				\
+         OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); 		\
 	 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);	\
 	 OUT_RING(MI_NOOP);						\
 	 ADVANCE_LP_RING();						\
 	 *pI830->overlayOn = FALSE;					\
 	 ErrorF("Overlay goes from on to off\n");			\
+         while (spin != 0 && (INREG(OCMD_REGISTER) & OVERLAY_ENABLE)){	\
+		ErrorF("SPIN %d\n",spin);				\
+		spin--;							\
+ 	 }								\
+	 if (spin == 0) ErrorF("OVERLAY FAILED TO GO OFF\n");		\
 	 ErrorF("OVERLAY_OFF\n");					\
       }									\
    } while(0)
@@ -181,6 +194,7 @@ Edummy(const char *dummy, ...)
 /*
  * OCMD - Overlay Command Register
  */
+#define OCMD_REGISTER		0x30168
 #define MIRROR_MODE		(0x3<<17)
 #define MIRROR_HORIZONTAL	(0x1<<17)
 #define MIRROR_VERTICAL		(0x2<<17)
@@ -212,11 +226,15 @@ Edummy(const char *dummy, ...)
 #define FIELD1			(0x1<<1)
 #define OVERLAY_ENABLE		0x1
 
+#define OFC_UPDATE		0x1
+
 /* OCONFIG register */
 #define CC_OUT_8BIT		(0x1<<3)
 #define OVERLAY_PIPE_MASK	(0x1<<18)		
 #define OVERLAY_PIPE_A		(0x0<<18)		
 #define OVERLAY_PIPE_B		(0x1<<18)		
+#define THREE_LINE_BUFFERS	(0x1<<0)
+#define TWO_LINE_BUFFERS	(0x0<<0)
 
 /* DCLRKM register */
 #define DEST_KEY_ENABLE		(0x1<<31)
@@ -260,11 +278,12 @@ static XF86AttributeRec CloneAttributes[
    {XvSettable | XvGettable, 0, 1, "XV_PIPE"}
 };
 
-#define NUM_ATTRIBUTES 3
+#define NUM_ATTRIBUTES 4
 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {
    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
    {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
-   {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
+   {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"},
+   {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}
 };
 
 #define GAMMA_ATTRIBUTES 6
@@ -355,6 +374,7 @@ typedef struct {
    int brightness;
    int contrast;
    int pipe;
+   int doubleBuffer;
 
    RegionRec clip;
    CARD32 colorKey;
@@ -390,7 +410,7 @@ CompareOverlay(I830Ptr pI830, CARD32 * o
    for (i = 0; i < size; i += 4) {
       val = INREG(0x30100 + i);
       if (val != overlay[i / 4]) {
-	 ErrorF("0x%05x value doesn't match (0x%08x != 0x%08x)\n",
+	 ErrorF("0x%05x value doesn't match (0x%lx != 0x%lx)\n",
 		0x30100 + i, val, overlay[i / 4]);
 	 bad++;
       }
@@ -463,7 +483,7 @@ I830ResetVideo(ScrnInfoPtr pScrn)
    I830OverlayRegPtr overlay =
 	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
 
-   DPRINTF(PFX, "I830ResetVideo: base: %p, offset: 0x%08x, obase: %p\n",
+   DPRINTF(PFX, "I830ResetVideo: base: %p, offset: 0x%lx, obase: %p\n",
 	   pI830->FbBase, pI830->OverlayMem->Start, overlay);
    /*
     * Default to maximum image size in YV12
@@ -475,10 +495,10 @@ I830ResetVideo(ScrnInfoPtr pScrn)
    overlay->HORZ_PH = 0;
    overlay->INIT_PHS = 0;
    overlay->DWINPOS = 0;
-   overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH;
-   overlay->SWIDTH = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 16);
-   overlay->SWIDTHSW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12);
-   overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15);
+   overlay->DWINSZ = 0;
+   overlay->SWIDTH = 0;
+   overlay->SWIDTHSW = 0;
+   overlay->SHEIGHT = 0;
    overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
    overlay->OCLRC1 = 0x00000080;	/* saturation: bypass */
    overlay->AWINPOS = 0;
@@ -532,7 +552,7 @@ I830ResetVideo(ScrnInfoPtr pScrn)
    {
       int i;
       for (i = 0x30000; i < 0x31000; i += 4)
-	 ErrorF("0x%x 0x%08x\n", i, INREG(i));
+	 ErrorF("0x%x 0x%lx\n", i, INREG(i));
    }
 #endif
 }
@@ -572,18 +592,53 @@ I830SetOneLineModeRatio(ScrnInfoPtr pScr
       pPriv->oneLineMode = FALSE;
 }
 
+static CARD32 I830BoundGammaElt (CARD32 elt, CARD32 eltPrev)
+{
+   elt &= 0xff;
+   eltPrev &= 0xff;
+   if (elt < eltPrev)
+      elt = eltPrev;
+   else if ((elt - eltPrev) > 0x7e)
+      elt = eltPrev + 0x7e;
+   return elt;
+}
+
+static CARD32 I830BoundGamma (CARD32 gamma, CARD32 gammaPrev)
+{
+   return (I830BoundGammaElt (gamma >> 24, gammaPrev >> 24) << 24 |
+	   I830BoundGammaElt (gamma >> 16, gammaPrev >> 16) << 16 |
+	   I830BoundGammaElt (gamma >>  8, gammaPrev >>  8) <<  8 |
+	   I830BoundGammaElt (gamma      , gammaPrev      ));
+}
+
 static void
 I830UpdateGamma(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-
-   OUTREG(OGAMC5, pPriv->gamma5);
-   OUTREG(OGAMC4, pPriv->gamma4);
-   OUTREG(OGAMC3, pPriv->gamma3);
-   OUTREG(OGAMC2, pPriv->gamma2);
-   OUTREG(OGAMC1, pPriv->gamma1);
-   OUTREG(OGAMC0, pPriv->gamma0);
+   CARD32   gamma0 = pPriv->gamma0;
+   CARD32   gamma1 = pPriv->gamma1;
+   CARD32   gamma2 = pPriv->gamma2;
+   CARD32   gamma3 = pPriv->gamma3;
+   CARD32   gamma4 = pPriv->gamma4;
+   CARD32   gamma5 = pPriv->gamma5;
+
+   ErrorF ("Original gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+	   gamma0, gamma1, gamma2, gamma3, gamma4, gamma5);
+   gamma1 = I830BoundGamma (gamma1, gamma0);
+   gamma2 = I830BoundGamma (gamma2, gamma1);
+   gamma3 = I830BoundGamma (gamma3, gamma2);
+   gamma4 = I830BoundGamma (gamma4, gamma3);
+   gamma5 = I830BoundGamma (gamma5, gamma4);
+   ErrorF ("Bounded  gamma: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+	   gamma0, gamma1, gamma2, gamma3, gamma4, gamma5);
+
+   OUTREG(OGAMC5, gamma5);
+   OUTREG(OGAMC4, gamma4);
+   OUTREG(OGAMC3, gamma3);
+   OUTREG(OGAMC2, gamma2);
+   OUTREG(OGAMC1, gamma1);
+   OUTREG(OGAMC0, gamma0);
 }
 
 static XF86VideoAdaptorPtr
@@ -602,10 +657,15 @@ I830SetupImageVideo(ScreenPtr pScreen)
       return NULL;
 
    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
-   adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+   adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/;
    adapt->name = "Intel(R) Video Overlay";
    adapt->nEncodings = 1;
    adapt->pEncodings = DummyEncoding;
+   /* update the DummyEncoding for these two chipsets */
+   if (IS_845G(pI830) || IS_I830(pI830)) {
+      adapt->pEncodings->width = IMAGE_MAX_WIDTH_LEGACY;
+      adapt->pEncodings->height = IMAGE_MAX_HEIGHT_LEGACY;
+   }
    adapt->nFormats = NUM_FORMATS;
    adapt->pFormats = Formats;
    adapt->nPorts = 1;
@@ -617,7 +677,7 @@ I830SetupImageVideo(ScreenPtr pScreen)
    adapt->nAttributes = NUM_ATTRIBUTES;
    if (pI830->Clone)
       adapt->nAttributes += CLONE_ATTRIBUTES;
-   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))
+   if (IS_I9XX(pI830))
       adapt->nAttributes += GAMMA_ATTRIBUTES; /* has gamma */
    adapt->pAttributes = xnfalloc(sizeof(XF86AttributeRec) * adapt->nAttributes);
    /* Now copy the attributes */
@@ -628,7 +688,7 @@ I830SetupImageVideo(ScreenPtr pScreen)
       memcpy((char*)att, (char*)CloneAttributes, sizeof(XF86AttributeRec) * CLONE_ATTRIBUTES);
       att+=CLONE_ATTRIBUTES;
    }
-   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+   if (IS_I9XX(pI830)) {
       memcpy((char*)att, (char*)GammaAttributes, sizeof(XF86AttributeRec) * GAMMA_ATTRIBUTES);
       att+=GAMMA_ATTRIBUTES;
    }
@@ -658,6 +718,7 @@ I830SetupImageVideo(ScreenPtr pScreen)
    pPriv->gamma2 = 0x202020;
    pPriv->gamma1 = 0x101010;
    pPriv->gamma0 = 0x080808;
+   pPriv->doubleBuffer = 1;
 
    /* gotta uninit this someplace */
    REGION_NULL(pScreen, &pPriv->clip);
@@ -680,15 +741,16 @@ I830SetupImageVideo(ScreenPtr pScreen)
    pI830->BlockHandler = pScreen->BlockHandler;
    pScreen->BlockHandler = I830BlockHandler;
 
+   xvColorKey = MAKE_ATOM("XV_COLORKEY");
    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
    xvContrast = MAKE_ATOM("XV_CONTRAST");
-   xvColorKey = MAKE_ATOM("XV_COLORKEY");
+   xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
 
    /* Allow the pipe to be switched from pipe A to B when in clone mode */
    if (pI830->Clone)
      xvPipe = MAKE_ATOM("XV_PIPE");
-
-   if (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830)) {
+   
+   if (IS_I9XX(pI830)) {
      xvGamma0 = MAKE_ATOM("XV_GAMMA0");
      xvGamma1 = MAKE_ATOM("XV_GAMMA1");
      xvGamma2 = MAKE_ATOM("XV_GAMMA2");
@@ -747,10 +809,12 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer
 
    if (shutdown) {
       if (pPriv->videoStatus & CLIENT_VIDEO_ON) {
+
 	 overlay->OCMD &= ~OVERLAY_ENABLE;
 	 OVERLAY_UPDATE;
-
+#if 1
 	 OVERLAY_OFF;
+#endif
 
          if (pI830->entityPrivate)
             pI830->entityPrivate->XvInUse = -1;
@@ -783,15 +847,23 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	 return BadValue;
       pPriv->brightness = value;
       overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-      if (pPriv->overlayOK)
-         OVERLAY_UPDATE;
+      ErrorF("BRIGHTNESS\n");
+      overlay->OCMD &= ~OVERLAY_ENABLE;
+      OVERLAY_UPDATE;
+#if 1
+      OVERLAY_OFF;
+#endif
    } else if (attribute == xvContrast) {
       if ((value < 0) || (value > 255))
 	 return BadValue;
       pPriv->contrast = value;
       overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff);
-      if (pPriv->overlayOK)
-         OVERLAY_UPDATE;
+      ErrorF("CONTRAST\n");
+      overlay->OCMD &= ~OVERLAY_ENABLE;
+      OVERLAY_UPDATE;
+#if 1
+      OVERLAY_OFF;
+#endif
    } else if (pI830->Clone && attribute == xvPipe) {
       if ((value < 0) || (value > 1))
          return BadValue;
@@ -804,52 +876,24 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
          overlay->OCONFIG |= OVERLAY_PIPE_A;
       else 
          overlay->OCONFIG |= OVERLAY_PIPE_B;
-      if (pPriv->overlayOK)
-         OVERLAY_UPDATE;
-   } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
-      /* Avoid video anomalies, so set gamma registers when overlay is off */
-      /* We also clamp the values if they are outside the ranges */
-      if (!*pI830->overlayOn) {
-         pPriv->gamma0 = value;
-	 if (pPriv->gamma1 - pPriv->gamma0 > 0x7d)
-	   pPriv->gamma1 = pPriv->gamma0 + 0x7d;
-      } else
-         return BadRequest;
-   } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
-      if (!*pI830->overlayOn) {
-         pPriv->gamma1 = value;
-         if (pPriv->gamma1 - pPriv->gamma0 > 0x7d)
-           pPriv->gamma0 = pPriv->gamma1 - 0x7d;
-      } else
-         return BadRequest;
-   } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
-      if (!*pI830->overlayOn) {
-         pPriv->gamma2 = value;
-         if (pPriv->gamma3 - pPriv->gamma2 > 0x7d)
-            pPriv->gamma3 = pPriv->gamma2 + 0x7d;
-      } else
-         return BadRequest;
-   } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
-      if (!*pI830->overlayOn) {
-         pPriv->gamma3 = value;
-         if (pPriv->gamma3 - pPriv->gamma2 > 0x7d)
-            pPriv->gamma2 = pPriv->gamma3 - 0x7d;
-      } else
-         return BadRequest;
-   } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
-      if (!*pI830->overlayOn) {
-         pPriv->gamma4 = value;
-         if (pPriv->gamma5 - pPriv->gamma4 > 0x7d)
-            pPriv->gamma5 = pPriv->gamma4 + 0x7d;
-      } else
-         return BadRequest;
-   } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
-      if (!*pI830->overlayOn) {
-         pPriv->gamma5 = value;
-         if (pPriv->gamma5 - pPriv->gamma4 > 0x7d)
-            pPriv->gamma4 = pPriv->gamma5 - 0x7d;
-      } else
-         return BadRequest;
+      ErrorF("PIPE CHANGE\n");
+      overlay->OCMD &= ~OVERLAY_ENABLE;
+      OVERLAY_UPDATE;
+#if 1
+      OVERLAY_OFF;
+#endif
+   } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
+      pPriv->gamma0 = value; 
+   } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
+      pPriv->gamma1 = value;
+   } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) {
+      pPriv->gamma2 = value;
+   } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) {
+      pPriv->gamma3 = value;
+   } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) {
+      pPriv->gamma4 = value;
+   } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) {
+      pPriv->gamma5 = value;
    } else if (attribute == xvColorKey) {
       pPriv->colorKey = value;
       switch (pScrn->depth) {
@@ -863,9 +907,19 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
 	 overlay->DCLRKV = pPriv->colorKey;
 	 break;
       }
-      if (pPriv->overlayOK)
-         OVERLAY_UPDATE;
+      ErrorF("COLORKEY\n");
+      overlay->OCMD &= ~OVERLAY_ENABLE;
+      OVERLAY_UPDATE;
+#if 1
+      OVERLAY_OFF;
+#endif
       REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+   } else if(attribute == xvDoubleBuffer) {
+      if ((value < 0) || (value > 1))
+         return BadValue;
+      /* Do not allow buffer change while playing video */
+      if(!*pI830->overlayOn)
+     	 pPriv->doubleBuffer = value;
    } else
       return BadMatch;
 
@@ -875,7 +929,13 @@ I830SetPortAttribute(ScrnInfoPtr pScrn,
         attribute == xvGamma2 ||
         attribute == xvGamma3 ||
         attribute == xvGamma4 ||
-        attribute == xvGamma5) && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+        attribute == xvGamma5) && (IS_I9XX(pI830))) {
+        ErrorF("GAMMA\n");
+        overlay->OCMD &= ~OVERLAY_ENABLE;
+        OVERLAY_UPDATE;
+#if 1
+        OVERLAY_OFF;
+#endif
 	I830UpdateGamma(pScrn);
    }
 
@@ -895,21 +955,23 @@ I830GetPortAttribute(ScrnInfoPtr pScrn,
       *value = pPriv->contrast;
    } else if (pI830->Clone && attribute == xvPipe) {
       *value = pPriv->pipe;
-   } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+   } else if (attribute == xvGamma0 && (IS_I9XX(pI830))) {
       *value = pPriv->gamma0;
-   } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+   } else if (attribute == xvGamma1 && (IS_I9XX(pI830))) {
       *value = pPriv->gamma1;
-   } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+   } else if (attribute == xvGamma2 && (IS_I9XX(pI830))) {
       *value = pPriv->gamma2;
-   } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+   } else if (attribute == xvGamma3 && (IS_I9XX(pI830))) {
       *value = pPriv->gamma3;
-   } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+   } else if (attribute == xvGamma4 && (IS_I9XX(pI830))) {
       *value = pPriv->gamma4;
-   } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830) || IS_I945G(pI830))) {
+   } else if (attribute == xvGamma5 && (IS_I9XX(pI830))) {
       *value = pPriv->gamma5;
    } else if (attribute == xvColorKey) {
       *value = pPriv->colorKey;
-   } else
+   } else if (attribute == xvDoubleBuffer) {
+      *value = pPriv->doubleBuffer;
+   } else 
       return BadMatch;
 
    return Success;
@@ -940,8 +1002,10 @@ I830CopyPackedData(ScrnInfoPtr pScrn,
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
    unsigned char *src, *dst;
+   int i,j;
+   unsigned char *s;
 
-   DPRINTF(PFX, "I830CopyPackedData: (%d,%d) (%d,%d)\n"
+   ErrorF("I830CopyPackedData: (%d,%d) (%d,%d)\n"
 	   "srcPitch: %d, dstPitch: %d\n", top, left, h, w, srcPitch, dstPitch);
 
    src = buf + (top * srcPitch) + (left << 1);
@@ -951,11 +1015,76 @@ I830CopyPackedData(ScrnInfoPtr pScrn,
    else
       dst = pI830->FbBase + pPriv->YBuf1offset;
 
-   w <<= 1;
-   while (h--) {
-      memcpy(dst, src, w);
-      src += srcPitch;
-      dst += dstPitch;
+   switch (pI830->rotation) {
+      case RR_Rotate_0:
+         w <<= 1;
+         for (i = 0; i < h; i++) {
+            memcpy(dst, src, w);
+            src += srcPitch;
+            dst += dstPitch;
+         }
+	 break;
+      case RR_Rotate_90:
+         h <<= 1;
+         for (i = 0; i < h; i+=2) {
+            s = src;
+            for (j = 0; j < w; j++) {
+		/* Copy Y */
+               dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++; 
+		(void)*s++;
+            }
+            src += srcPitch;
+         }
+         h >>= 1;
+   	 src = buf + (top * srcPitch) + (left << 1);
+         for (i = 0; i < h; i+=2) {
+            for (j = 0; j < w; j+=2) {
+		/* Copy U */
+		dst[((i*2) + 1) + ((w - j - 1) * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)];
+		dst[((i*2) + 1) + ((w - j - 2) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)];
+		/* Copy V */
+		dst[((i*2) + 3) + ((w - j - 1) * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)];
+		dst[((i*2) + 3) + ((w - j - 2) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)];
+            }
+         }
+         break;
+      case RR_Rotate_180:
+         w <<= 1;
+         for (i = 0; i < h; i++) {
+            s = src;
+            for (j = 0; j < w; j+=4) {
+               dst[(w - j - 4) + ((h - i - 1) * dstPitch)] = *s++;
+               dst[(w - j - 3) + ((h - i - 1) * dstPitch)] = *s++;
+               dst[(w - j - 2) + ((h - i - 1) * dstPitch)] = *s++;
+               dst[(w - j - 1) + ((h - i - 1) * dstPitch)] = *s++;
+            }
+            src += srcPitch;
+         }
+         break;
+      case RR_Rotate_270:
+         h <<= 1;
+         for (i = 0; i < h; i+=2) {
+            s = src;
+            for (j = 0; j < w; j++) {
+		/* Copy Y */
+               dst[(h - i - 2) + (j * dstPitch)] = *s++;
+		(void)*s++;
+            }
+            src += srcPitch;
+         }
+         h >>= 1;
+   	 src = buf + (top * srcPitch) + (left << 1);
+         for (i = 0; i < h; i+=2) {
+            for (j = 0; j < w; j+=2) {
+		/* Copy U */
+		dst[(((h - i)*2) - 3) + (j * dstPitch)] = src[(j*2) + 1 + (i * srcPitch)];
+		dst[(((h - i)*2) - 3) + ((j - 1) * dstPitch)] = src[(j*2) + 1 + ((i+1) * srcPitch)];
+		/* Copy V */
+		dst[(((h - i)*2) - 1) + (j * dstPitch)] = src[(j*2) + 3 + (i * srcPitch)];
+		dst[(((h - i)*2) - 1) + ((j - 1) * dstPitch)] = src[(j*2) + 3 + ((i+1) * srcPitch)];
+            }
+         }
+         break;
    }
 }
 
@@ -966,8 +1095,10 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, un
 {
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr;
-   int i;
+   int i, j = 0;
    unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3;
+   unsigned char *s;
+   int dstPitch2 = dstPitch << 1;
 
    ErrorF("I830CopyPlanarData: srcPitch %d, srcPitch %d, dstPitch %d\n"
 	   "nlines %d, npixels %d, top %d, left %d\n", srcPitch, srcPitch2, dstPitch,
@@ -975,22 +1106,53 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, un
 
    /* Copy Y data */
    src1 = buf + (top * srcPitch) + left;
-   ErrorF("src1 is %p, offset is %d\n", src1,
+   ErrorF("src1 is %p, offset is %ld\n", src1,
 	  (unsigned long)src1 - (unsigned long)buf);
    if (pPriv->currentBuf == 0)
       dst1 = pI830->FbBase + pPriv->YBuf0offset;
    else
       dst1 = pI830->FbBase + pPriv->YBuf1offset;
 
-   for (i = 0; i < h; i++) {
-      memcpy(dst1, src1, w);
-      src1 += srcPitch;
-      dst1 += dstPitch << 1;
+   switch (pI830->rotation) {
+      case RR_Rotate_0:
+         for (i = 0; i < h; i++) {
+            memcpy(dst1, src1, w);
+            src1 += srcPitch;
+            dst1 += dstPitch2;
+         }
+	 break;
+      case RR_Rotate_90:
+         for (i = 0; i < h; i++) {
+            s = src1;
+            for (j = 0; j < w; j++) {
+               dst1[(i) + ((w - j - 1) * dstPitch2)] = *s++;
+            }
+            src1 += srcPitch;
+         }
+         break;
+      case RR_Rotate_180:
+         for (i = 0; i < h; i++) {
+            s = src1;
+            for (j = 0; j < w; j++) {
+               dst1[(w - j - 1) + ((h - i - 1) * dstPitch2)] = *s++;
+            }
+            src1 += srcPitch;
+         }
+         break;
+      case RR_Rotate_270:
+         for (i = 0; i < h; i++) {
+            s = src1;
+            for (j = 0; j < w; j++) {
+               dst1[(h - i - 1) + (j * dstPitch2)] = *s++;
+            }
+            src1 += srcPitch;
+         }
+         break;
    }
 
    /* Copy V data for YV12, or U data for I420 */
    src2 = buf + (srcH * srcPitch) + ((top * srcPitch) >> 2) + (left >> 1);
-   ErrorF("src2 is %p, offset is %d\n", src2,
+   ErrorF("src2 is %p, offset is %ld\n", src2,
 	  (unsigned long)src2 - (unsigned long)buf);
    if (pPriv->currentBuf == 0) {
       if (id == FOURCC_I420)
@@ -1004,16 +1166,47 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, un
 	 dst2 = pI830->FbBase + pPriv->VBuf1offset;
    }
 
-   for (i = 0; i < h / 2; i++) {
-      memcpy(dst2, src2, w / 2);
-      src2 += srcPitch2;
-      dst2 += dstPitch;
+   switch (pI830->rotation) {
+      case RR_Rotate_0:
+         for (i = 0; i < h / 2; i++) {
+            memcpy(dst2, src2, w / 2);
+            src2 += srcPitch2;
+            dst2 += dstPitch;
+         }
+         break;
+      case RR_Rotate_90:
+         for (i = 0; i < (h/2); i++) {
+            s = src2;
+            for (j = 0; j < (w/2); j++) {
+               dst2[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++;
+            }
+            src2 += srcPitch2;
+         }
+         break;
+      case RR_Rotate_180:
+         for (i = 0; i < (h/2); i++) {
+            s = src2;
+            for (j = 0; j < (w/2); j++) {
+               dst2[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++;
+            }
+            src2 += srcPitch2;
+         }
+         break;
+      case RR_Rotate_270:
+         for (i = 0; i < (h/2); i++) {
+            s = src2;
+            for (j = 0; j < (w/2); j++) {
+               dst2[((h/2) - i - 1) + (j * dstPitch)] = *s++;
+            }
+            src2 += srcPitch2;
+         }
+         break;
    }
 
    /* Copy U data for YV12, or V data for I420 */
    src3 = buf + (srcH * srcPitch) + ((srcH >> 1) * srcPitch2) +
 	 ((top * srcPitch) >> 2) + (left >> 1);
-   ErrorF("src3 is %p, offset is %d\n", src3,
+   ErrorF("src3 is %p, offset is %ld\n", src3,
 	  (unsigned long)src3 - (unsigned long)buf);
    if (pPriv->currentBuf == 0) {
       if (id == FOURCC_I420)
@@ -1027,10 +1220,41 @@ I830CopyPlanarData(ScrnInfoPtr pScrn, un
 	 dst3 = pI830->FbBase + pPriv->UBuf1offset;
    }
 
-   for (i = 0; i < h / 2; i++) {
-      memcpy(dst3, src3, w / 2);
-      src3 += srcPitch2;
-      dst3 += dstPitch;
+   switch (pI830->rotation) {
+      case RR_Rotate_0:
+         for (i = 0; i < h / 2; i++) {
+            memcpy(dst3, src3, w / 2);
+            src3 += srcPitch2;
+            dst3 += dstPitch;
+         }
+         break;
+      case RR_Rotate_90:
+         for (i = 0; i < (h/2); i++) {
+            s = src3;
+            for (j = 0; j < (w/2); j++) {
+               dst3[(i) + (((w/2) - j - 1) * (dstPitch))] = *s++;
+            }
+            src3 += srcPitch2;
+         }
+         break;
+      case RR_Rotate_180:
+         for (i = 0; i < (h/2); i++) {
+            s = src3;
+            for (j = 0; j < (w/2); j++) {
+               dst3[((w/2) - j - 1) + (((h/2) - i - 1) * dstPitch)] = *s++;
+            }
+            src3 += srcPitch2;
+         }
+         break;
+      case RR_Rotate_270:
+         for (i = 0; i < (h/2); i++) {
+            s = src3;
+            for (j = 0; j < (w/2); j++) {
+               dst3[((h/2) - i - 1) + (j * dstPitch)] = *s++;
+            }
+            src3 += srcPitch2;
+         }
+         break;
    }
 }
 
@@ -1175,6 +1399,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
 	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
    unsigned int swidth;
    unsigned int mask, shift, offsety, offsetu;
+   int tmp;
 
    ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height,
 	   dstPitch);
@@ -1182,7 +1407,157 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    if (!pPriv->overlayOK)
       return;
 
-   if (IS_I915G(pI830) || IS_I915GM(pI830)) {
+#if VIDEO_DEBUG
+   CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
+#endif
+
+   /* When in dual head with different bpp setups we need to refresh the
+    * color key, so let's reset the video parameters and refresh here */
+   if (pI830->entityPrivate)
+      I830ResetVideo(pScrn);
+
+   /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */
+   if (!*pI830->overlayOn)
+      OVERLAY_UPDATE;
+
+   switch (pI830->rotation) {
+	case RR_Rotate_0:
+		dstBox->x1 -= pScrn->frameX0;
+		dstBox->x2 -= pScrn->frameX0;
+		dstBox->y1 -= pScrn->frameY0;
+		dstBox->y2 -= pScrn->frameY0;
+		break;
+	case RR_Rotate_90:
+		tmp = dstBox->x1;
+		dstBox->x1 = dstBox->y1 - pScrn->frameX0;
+		dstBox->y1 = pScrn->virtualY - tmp - pScrn->frameY0;
+		tmp = dstBox->x2;
+		dstBox->x2 = dstBox->y2 - pScrn->frameX0;
+		dstBox->y2 = pScrn->virtualY - tmp - pScrn->frameY0;
+		tmp = dstBox->y1;
+		dstBox->y1 = dstBox->y2;
+		dstBox->y2 = tmp;
+		break;
+	case RR_Rotate_180:
+		tmp = dstBox->x1;
+		dstBox->x1 = pScrn->virtualX - dstBox->x2 - pScrn->frameX0;
+		dstBox->x2 = pScrn->virtualX - tmp - pScrn->frameX0;
+		tmp = dstBox->y1;
+		dstBox->y1 = pScrn->virtualY - dstBox->y2 - pScrn->frameY0;
+		dstBox->y2 = pScrn->virtualY - tmp - pScrn->frameY0;
+		break;
+	case RR_Rotate_270:
+		tmp = dstBox->x1;
+		dstBox->x1 = pScrn->virtualX - dstBox->y1 - pScrn->frameX0;
+		dstBox->y1 = tmp - pScrn->frameY0;
+		tmp = dstBox->x2;
+		dstBox->x2 = pScrn->virtualX - dstBox->y2 - pScrn->frameX0;
+		dstBox->y2 = tmp - pScrn->frameY0;
+		tmp = dstBox->x1;
+		dstBox->x1 = dstBox->x2;
+		dstBox->x2 = tmp;
+		break;
+   }
+
+   /* Fix up the dstBox if outside the visible screen */
+   {
+      int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0;
+      int offset_y = (dstBox->y1 < 0) ? -dstBox->y1 : 0;
+      int offset, offset2;
+
+      /* align */
+      offset_x = (offset_x + 3) & ~3;
+      offset_y = (offset_y + 3) & ~3;
+
+      if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+         height -= offset_x;
+         width -= offset_y;
+      } else {
+         height -= offset_y;
+         width -= offset_x;
+      }
+
+      if (id == FOURCC_I420 || id == FOURCC_YV12) {
+         offset = ((offset_x/2) + (dstPitch * offset_y)) * 2;
+         offset2 = ((offset_x/2) + ((dstPitch/2) * offset_y));
+      } else {
+         offset = ((offset_x*2) + (dstPitch * offset_y));
+         offset2 = ((offset_x*2) + ((dstPitch/2) * offset_y));
+      }
+
+      /* buffer locations */
+      pPriv->YBuf0offset += offset;
+      pPriv->UBuf0offset += offset2;
+      pPriv->VBuf0offset += offset2;
+
+      if(pPriv->doubleBuffer) {
+         pPriv->YBuf1offset += offset;
+         pPriv->UBuf1offset += offset2;
+         pPriv->VBuf1offset += offset2;
+      }
+   }
+
+   if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+      tmp = width;
+      width = height;
+      height = tmp;
+      tmp = drw_w;
+      drw_w = drw_h;
+      drw_h = tmp;
+      tmp = src_w;
+      src_w = src_h;
+      src_h = tmp;
+   }
+
+   if (pPriv->oneLineMode) {
+      /* change the coordinates with panel fitting active */
+      dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1;
+      dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1;
+ 
+      /* Now, alter the height, so we scale to the correct size */
+      drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
+   }
+
+   {
+      /* Keep the engine happy and clip to the real vertical size just
+       * in case an LFP is in use and it's not at it's native resolution.
+       */
+      int vactive = pI830->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF);
+
+      vactive += 1;
+
+      if (dstBox->y1 < 0) dstBox->y1 = 0;
+      if (dstBox->y2 < 0) dstBox->y2 = 0;
+      if (dstBox->x1 < 0) dstBox->x1 = 0;
+      if (dstBox->x2 < 0) dstBox->x2 = 0;
+      if (dstBox->y1 > vactive) dstBox->y1 = vactive;
+      if (dstBox->y2 > vactive) dstBox->y2 = vactive;
+      if (dstBox->x1 > pScrn->currentMode->HDisplay) dstBox->x1 = pScrn->currentMode->HDisplay - 1;
+      if (dstBox->x2 > pScrn->currentMode->HDisplay) dstBox->x2 = pScrn->currentMode->HDisplay - 1;
+
+      /* nothing do to */
+      if ((!dstBox->x1 && !dstBox->x2) || (!dstBox->y1 && !dstBox->y2)) {
+         ErrorF("NOTHING TO DO\n");
+         return;
+      }
+      if ((dstBox->x1 == (pScrn->currentMode->HDisplay - 1) && 
+           dstBox->x2 == (pScrn->currentMode->HDisplay - 1)) || 
+          (dstBox->y1 == vactive && 
+           dstBox->y2 == vactive)) {
+         ErrorF("NOTHING TO DO\n");
+         return;
+      }
+      if ((dstBox->y2 - dstBox->y1) <= N_VERT_Y_TAPS) {
+         ErrorF("NOTHING TO DO\n");
+         return;
+      }
+      if ((dstBox->x2 - dstBox->x1) <= 2) {
+         ErrorF("NOTHING TO DO\n");
+         return;
+      }
+   }
+
+   if (IS_I9XX(pI830)) {
       shift = 6;
       mask = 0x3f;
    } else {
@@ -1198,17 +1573,6 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       offsetu = pPriv->UBuf1offset;
    }
 
-#if VIDEO_DEBUG
-   CompareOverlay(pI830, (CARD32 *) overlay, 0x100);
-#endif
-
-   /* When in dual head with different bpp setups we need to refresh the
-    * color key, so let's reset the video parameters and refresh here */
-#if 0
-   if (pI830->entityPrivate)
-#endif
-      I830ResetVideo(pScrn);
-
    switch (id) {
    case FOURCC_YV12:
    case FOURCC_I420:
@@ -1221,7 +1585,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       swidth = ((offsety + width + mask) >> shift) -
 	    (offsety >> shift);
 
-      if (IS_I915G(pI830) || IS_I915GM(pI830))
+      if (IS_I9XX(pI830))
          swidth <<= 1;
 
       swidth -= 1;
@@ -1233,7 +1597,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       swidth = ((offsetu + (width / 2) + mask) >> shift) -
 	    (offsetu >> shift);
 
-      if (IS_I915G(pI830) || IS_I915GM(pI830))
+      if (IS_I9XX(pI830))
          swidth <<= 1;
 
       swidth -= 1;
@@ -1257,7 +1621,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       swidth = ((offsety + (width << 1) + mask) >> shift) -
 	    (offsety >> shift);
 
-      if (IS_I915G(pI830) || IS_I915GM(pI830))
+      if (IS_I9XX(pI830))
          swidth <<= 1;
 
       swidth -= 1;
@@ -1272,19 +1636,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       break;
    }
 
-   if (pPriv->oneLineMode) {
-      /* change the coordinates with panel fitting active */
-      dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1;
-      dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1;
- 
-      /* Now, alter the height, so we scale to the correct size */
-      drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1;
-
-      /* Keep the engine happy */
-      if (dstBox->y1 < 0) dstBox->y1 = 0;
-      if (dstBox->y2 < 0) dstBox->y2 = 0;
-   }
-
+   overlay->OCMD = OVERLAY_ENABLE;
 
    overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1;
 
@@ -1299,13 +1651,15 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    overlay->OBUF_0U = pPriv->UBuf0offset;
    overlay->OBUF_0V = pPriv->VBuf0offset;
 
-   overlay->OBUF_1Y = pPriv->YBuf1offset;
-   overlay->OBUF_1U = pPriv->UBuf1offset;
-   overlay->OBUF_1V = pPriv->VBuf1offset;
+   if(pPriv->doubleBuffer) {
+      overlay->OBUF_1Y = pPriv->YBuf1offset;
+      overlay->OBUF_1U = pPriv->UBuf1offset;
+      overlay->OBUF_1V = pPriv->VBuf1offset;
+   }
 
-   ErrorF("Buffers: Y0: 0x%08x, U0: 0x%08x, V0: 0x%08x\n", overlay->OBUF_0Y,
+   ErrorF("Buffers: Y0: 0x%lx, U0: 0x%lx, V0: 0x%lx\n", overlay->OBUF_0Y,
 	  overlay->OBUF_0U, overlay->OBUF_0V);
-   ErrorF("Buffers: Y1: 0x%08x, U1: 0x%08x, V1: 0x%08x\n", overlay->OBUF_1Y,
+   ErrorF("Buffers: Y1: 0x%lx, U1: 0x%lx, V1: 0x%lx\n", overlay->OBUF_1Y,
 	  overlay->OBUF_1U, overlay->OBUF_1V);
 
 #if 0
@@ -1330,11 +1684,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    }
 #endif
 
-#if 1
-   overlay->OCMD = OVERLAY_ENABLE;
-#endif
-
-   ErrorF("pos: 0x%08x, size: 0x%08x\n", overlay->DWINPOS, overlay->DWINSZ);
+   ErrorF("pos: 0x%lx, size: 0x%lx\n", overlay->DWINPOS, overlay->DWINSZ);
    ErrorF("dst: %d x %d, src: %d x %d\n", drw_w, drw_h, src_w, src_h);
 
    /* 
@@ -1383,6 +1733,18 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
       ErrorF("UV xscale: %x.%03x, UV yscale: %x.%03x\n", xscaleIntUV,
 	     xscaleFractUV & 0xFFF, yscaleIntUV, yscaleFractUV & 0xFFF);
 
+      /* shouldn't get here */
+      if (xscaleInt > 7) { 
+         ErrorF("xscale: bad scale\n");
+	 return;
+      }
+
+      /* shouldn't get here */
+      if (xscaleIntUV > 7) { 
+         ErrorF("xscaleUV: bad scale\n");
+         return;
+      }
+
       newval = (xscaleInt << 16) |
 	    ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
       if (newval != overlay->YRGBSCALE) {
@@ -1480,7 +1842,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int 
    else
       overlay->OCMD |= BUFFER1;
 
-   ErrorF("OCMD is 0x%08x\n", overlay->OCMD);
+   ErrorF("OCMD is 0x%lx\n", overlay->OCMD);
 
    OVERLAY_UPDATE;
 }
@@ -1489,7 +1851,7 @@ static FBLinearPtr
 I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
 {
    ScreenPtr pScreen;
-   FBLinearPtr new_linear;
+   FBLinearPtr new_linear = NULL;
 
    DPRINTF(PFX, "I830AllocateMemory\n");
 
@@ -1514,8 +1876,10 @@ I830AllocateMemory(ScrnInfoPtr pScrn, FB
       xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4,
 				      PRIORITY_EXTREME);
 
-      if (max_size < size)
+      if (max_size < size) {
+         ErrorF("No memory available\n");
 	 return NULL;
+      }
 
       xf86PurgeUnlockedOffscreenAreas(pScreen);
       new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
@@ -1533,11 +1897,14 @@ I830PutImage(ScrnInfoPtr pScrn,
 	     short drw_w, short drw_h,
 	     int id, unsigned char *buf,
 	     short width, short height,
-	     Bool sync, RegionPtr clipBoxes, pointer data)
+	     Bool sync, RegionPtr clipBoxes, pointer data,
+	     DrawablePtr pDraw)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv = (I830PortPrivPtr) data;
    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+   I830OverlayRegPtr overlay =
+	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
    INT32 x1, x2, y1, y2;
    int srcPitch, srcPitch2 = 0, dstPitch;
    int top, left, npixels, nlines, size, loops;
@@ -1585,68 +1952,106 @@ I830PutImage(ScrnInfoPtr pScrn,
 			      width, height))
       return Success;
 
-   dstBox.x1 -= pScrn->frameX0;
-   dstBox.x2 -= pScrn->frameX0;
-   dstBox.y1 -= pScrn->frameY0;
-   dstBox.y2 -= pScrn->frameY0;
-
    switch (id) {
    case FOURCC_YV12:
    case FOURCC_I420:
       srcPitch = (width + 3) & ~3;
       srcPitch2 = ((width >> 1) + 3) & ~3;
-      dstPitch = ((width / 2) + 63) & ~63;	/* of chroma */
-      size = dstPitch * height * 3;
+#if 1
+      if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+         dstPitch = ((height / 2) + 63) & ~63;
+         size = dstPitch * width * 3;
+      } else {
+         dstPitch = ((width / 2) + 63) & ~63;	/* of chroma */
+         size = dstPitch * height * 3;
+      }
+#else
+      if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+         dstPitch = ((height / 2) + 511) & ~511;
+         size = dstPitch * width * 3;
+      } else {
+         dstPitch = ((width / 2) + 511) & ~511;	/* of chroma */
+         size = dstPitch * height * 3;
+      }
+#endif
       break;
    case FOURCC_UYVY:
    case FOURCC_YUY2:
    default:
       srcPitch = width << 1;
-      dstPitch = (srcPitch + 63) & ~63;	/* of chroma */
-      size = dstPitch * height;
+#if 1
+      if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+         dstPitch = ((height << 1) + 63) & ~63;
+         size = dstPitch * width;
+      } else {
+         dstPitch = ((width << 1) + 63) & ~63;	/* of chroma */
+         size = dstPitch * height;
+      }
+#else
+      if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+         dstPitch = ((height << 1) + 511) & ~511;
+         size = dstPitch * width;
+      } else {
+         dstPitch = ((width << 1) + 511) & ~511;	/* of chroma */
+         size = dstPitch * height;
+      }
+#endif
       break;
    }
    ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size);
 
    /* size is multiplied by 2 because we have two buffers that are flipping */
-   if (!(pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, size * 2 / pI830->cpp)))
+   pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear,
+		   (pPriv->doubleBuffer ? size * 2 : size) / pI830->cpp);
+
+   if(!pPriv->linear || pPriv->linear->offset < (pScrn->virtualX * pScrn->virtualY))
       return BadAlloc;
 
    /* fixup pointers */
-   pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp;
-   pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
-   pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2);
-
-   pPriv->YBuf1offset = pPriv->YBuf0offset + size;
-   pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
-   pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2);
-
-   /* XXX We could potentially use MI_WAIT_FOR_OVERLAY here instead
-    * of this code....*/
+   pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear->offset * pI830->cpp;
+   if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+      pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width);
+      pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2);
+      if(pPriv->doubleBuffer) {
+         pPriv->YBuf1offset = pPriv->YBuf0offset + size;
+         pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * width);
+         pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * width / 2);
+      }
+   } else {
+      pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);
+      pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height / 2);
+      if(pPriv->doubleBuffer) {
+         pPriv->YBuf1offset = pPriv->YBuf0offset + size;
+         pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);
+         pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height / 2);
+      }
+   }
 
    /* Make sure this buffer isn't in use */
    loops = 0;
-   while (loops < 1000000) {
+   if (*pI830->overlayOn && pPriv->doubleBuffer && (overlay->OCMD & OVERLAY_ENABLE)) {
+      while (loops < 1000000) {
 #if USE_USLEEP_FOR_VIDEO
-      usleep(10);
+         usleep(10);
 #endif
-      if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) {
-	 break;
+         if (((INREG(DOVSTA) & OC_BUF) >> 20) == pPriv->currentBuf) {
+	    break;
+         }
+         loops++;
       }
-      loops++;
-   }
-   if (loops >= 1000000) {
-      ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf);
+      if (loops >= 1000000) {
+         ErrorF("loops (1) maxed out for buffer %d\n", pPriv->currentBuf);
 #if 0
-      pPriv->currentBuf = !pPriv->currentBuf;
+         pPriv->currentBuf = !pPriv->currentBuf;
 #endif
-   }
+      }
 
-   /* buffer swap */
-   if (pPriv->currentBuf == 0)
-      pPriv->currentBuf = 1;
-   else
-      pPriv->currentBuf = 0;
+      /* buffer swap */
+      if (pPriv->currentBuf == 0)
+         pPriv->currentBuf = 1;
+      else
+         pPriv->currentBuf = 0;
+   }
 
    /* copy data */
    top = y1 >> 16;
@@ -1690,14 +2095,22 @@ I830QueryImageAttributes(ScrnInfoPtr pSc
 			 unsigned short *w, unsigned short *h,
 			 int *pitches, int *offsets)
 {
+   I830Ptr pI830 = I830PTR(pScrn);
    int size, tmp;
 
-   DPRINTF(PFX, "I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
+   ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h);
 
+   if (IS_845G(pI830) || IS_I830(pI830)) {
+   if (*w > IMAGE_MAX_WIDTH_LEGACY)
+      *w = IMAGE_MAX_WIDTH_LEGACY;
+   if (*h > IMAGE_MAX_HEIGHT_LEGACY)
+      *h = IMAGE_MAX_HEIGHT_LEGACY;
+   } else {
    if (*w > IMAGE_MAX_WIDTH)
       *w = IMAGE_MAX_WIDTH;
    if (*h > IMAGE_MAX_HEIGHT)
       *h = IMAGE_MAX_HEIGHT;
+   }
 
    *w = (*w + 1) & ~1;
    if (offsets)
@@ -1767,24 +2180,25 @@ I830BlockHandler(int i,
    pScreen->BlockHandler = I830BlockHandler;
 
    if (pPriv->videoStatus & TIMER_MASK) {
-      UpdateCurrentTime();
+      Time now = currentTime.milliseconds;
       if (pPriv->videoStatus & OFF_TIMER) {
-	 if (pPriv->offTime < currentTime.milliseconds) {
+	 if (pPriv->offTime < now) {
 	    /* Turn off the overlay */
+	    ErrorF("BLOCKHANDLER\n");
 	    overlay->OCMD &= ~OVERLAY_ENABLE;
-
-	    OVERLAY_UPDATE;
-
-	    OVERLAY_OFF;
+            OVERLAY_UPDATE;
+#if 1
+            OVERLAY_OFF;
+#endif
 
 	    pPriv->videoStatus = FREE_TIMER;
-	    pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+	    pPriv->freeTime = now + FREE_DELAY;
        
             if (pI830->entityPrivate)
                pI830->entityPrivate->XvInUse = -1;
 	 }
       } else {				/* FREE_TIMER */
-	 if (pPriv->freeTime < currentTime.milliseconds) {
+	 if (pPriv->freeTime < now) {
 	    if (pPriv->linear) {
 	       xf86FreeOffscreenLinear(pPriv->linear);
 	       pPriv->linear = NULL;
@@ -1815,9 +2229,18 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
    OffscreenPrivPtr pPriv;
    I830Ptr pI830 = I830PTR(pScrn);
 
-   DPRINTF(PFX, "I830AllocateSurface\n");
+   ErrorF("I830AllocateSurface\n");
+
+   if (IS_845G(pI830) || IS_I830(pI830)) {
+      if ((w > IMAGE_MAX_WIDTH_LEGACY) || (h > IMAGE_MAX_HEIGHT_LEGACY))
+         return BadAlloc;
+   } else {
+      if ((w > IMAGE_MAX_WIDTH) || (h > IMAGE_MAX_HEIGHT))
+         return BadAlloc;
+   }
 
-   if ((w > 1024) || (h > 1024))
+   /* What to do when rotated ?? */
+   if (pI830->rotation != RR_Rotate_0)
       return BadAlloc;
 
    w = (w + 1) & ~1;
@@ -1857,7 +2280,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn,
    surface->offsets[0] = linear->offset * bpp;
    surface->devPrivate.ptr = (pointer) pPriv;
 
-   memset(pI830->FbBase + pScrn->fbOffset + surface->offsets[0], 0, size);
+   memset(pI830->FbBase + pI830->FrontBuffer.Start + surface->offsets[0], 0, size);
 
    return Success;
 }
@@ -1874,11 +2297,12 @@ I830StopSurface(XF86SurfacePtr surface)
       I830OverlayRegPtr overlay =
 	    (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
 
+      ErrorF("StopSurface\n");
       overlay->OCMD &= ~OVERLAY_ENABLE;
-
       OVERLAY_UPDATE;
-
+#if 1
       OVERLAY_OFF;
+#endif
 
       if (pI830->entityPrivate)
          pI830->entityPrivate->XvInUse = -1;
@@ -1929,11 +2353,13 @@ I830DisplaySurface(XF86SurfacePtr surfac
    ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn);
+   I830OverlayRegPtr overlay =
+	 (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start);
    INT32 x1, y1, x2, y2;
    INT32 loops = 0;
    BoxRec dstBox;
 
-   DPRINTF(PFX, "I830DisplaySurface\n");
+   ErrorF("I830DisplaySurface\n");
 
    if (pI830->entityPrivate) {
 	 if (pI830->entityPrivate->XvInUse != -1 &&
@@ -1965,35 +2391,35 @@ I830DisplaySurface(XF86SurfacePtr surfac
 			      surface->width, surface->height))
       return Success;
 
-   dstBox.x1 -= pScrn->frameX0;
-   dstBox.x2 -= pScrn->frameX0;
-   dstBox.y1 -= pScrn->frameY0;
-   dstBox.y2 -= pScrn->frameY0;
-
    /* fixup pointers */
    pI830Priv->YBuf0offset = surface->offsets[0];
    pI830Priv->YBuf1offset = pI830Priv->YBuf0offset;
 
-   /* XXX We could potentially use MI_WAIT_FOR_OVERLAY here instead
-    * of this code....*/
-
-   /* wait for the last rendered buffer to be flipped in */
-   while (((INREG(DOVSTA) & OC_BUF) >> 20) != pI830Priv->currentBuf) {
+   /* Make sure this buffer isn't in use */
+   loops = 0;
+   if (*pI830->overlayOn && pI830Priv->doubleBuffer && (overlay->OCMD & OVERLAY_ENABLE)) {
+      while (loops < 1000000) {
 #if USE_USLEEP_FOR_VIDEO
-      usleep(10);
+         usleep(10);
+#endif
+         if (((INREG(DOVSTA) & OC_BUF) >> 20) == pI830Priv->currentBuf) {
+	    break;
+         }
+         loops++;
+      }
+      if (loops >= 1000000) {
+         ErrorF("loops (1) maxed out for buffer %d\n", pI830Priv->currentBuf);
+#if 0
+         pI830Priv->currentBuf = !pI830Priv->currentBuf;
 #endif
-      if (loops == 200000) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");
-	 break;
       }
-      loops++;
-   }
 
-   /* buffer swap */
-   if (pI830Priv->currentBuf == 0)
-      pI830Priv->currentBuf = 1;
-   else
-      pI830Priv->currentBuf = 0;
+      /* buffer swap */
+      if (pI830Priv->currentBuf == 0)
+         pI830Priv->currentBuf = 1;
+      else
+         pI830Priv->currentBuf = 0;
+   }
 
    I830DisplayVideo(pScrn, surface->id, surface->width, surface->height,
 		    surface->pitches[0], x1, y1, x2, y2, &dstBox,
@@ -2018,6 +2444,8 @@ static void
 I830InitOffscreenImages(ScreenPtr pScreen)
 {
    XF86OffscreenImagePtr offscreenImages;
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
 
    /* need to free this someplace */
    if (!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) {
@@ -2025,15 +2453,20 @@ I830InitOffscreenImages(ScreenPtr pScree
    }
 
    offscreenImages[0].image = &Images[0];
-   offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+   offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/;
    offscreenImages[0].alloc_surface = I830AllocateSurface;
    offscreenImages[0].free_surface = I830FreeSurface;
    offscreenImages[0].display = I830DisplaySurface;
    offscreenImages[0].stop = I830StopSurface;
    offscreenImages[0].setAttribute = I830SetSurfaceAttribute;
    offscreenImages[0].getAttribute = I830GetSurfaceAttribute;
-   offscreenImages[0].max_width = 1024;
-   offscreenImages[0].max_height = 1024;
+   if (IS_845G(pI830) || IS_I830(pI830)) {
+      offscreenImages[0].max_width = IMAGE_MAX_WIDTH_LEGACY;
+      offscreenImages[0].max_height = IMAGE_MAX_HEIGHT_LEGACY;
+   } else {
+      offscreenImages[0].max_width = IMAGE_MAX_WIDTH;
+      offscreenImages[0].max_height = IMAGE_MAX_HEIGHT; 
+   }
    offscreenImages[0].num_attributes = 1;
    offscreenImages[0].attributes = Attributes;
 
@@ -2043,9 +2476,10 @@ I830InitOffscreenImages(ScreenPtr pScree
 void
 I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode)
 {
+   I830Ptr pI830 = I830PTR(pScrn);
    I830PortPrivPtr pPriv;
 
-   if (!I830PTR(pScrn)->adaptor) {
+   if (!pI830->adaptor) {
       return;
    }
 
@@ -2062,6 +2496,8 @@ I830VideoSwitchModeBefore(ScrnInfoPtr pS
     */
    I830StopVideo(pScrn, pPriv, TRUE);
 
+   pPriv->overlayOK = FALSE;
+
    pPriv->oneLineMode = FALSE;
 }
 
@@ -2079,6 +2515,17 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
    if (!pPriv)
       return;
 
+   pPriv->overlayOK = TRUE;
+
+   /* ensure pipe is updated on mode switch */
+   if (!pI830->Clone) {
+      if (pPriv->pipe != pI830->pipe) {
+         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+	   "Changing XVideo pipe (%d to %d).\n", pPriv->pipe, pI830->pipe);
+         pPriv->pipe = pI830->pipe;
+      }
+   }
+
    if (pPriv->pipe == 0) {
       if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) {
          xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff --git a/src/i915_3d.c b/src/i915_3d.c
new file mode 100644
index 0000000..b1f30ef
--- /dev/null
+++ b/src/i915_3d.c
@@ -0,0 +1,107 @@
+/**************************************************************************
+ * 
+ * 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.
+ * 
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+
+#include "i915_reg.h"
+
+void I915EmitInvarientState( ScrnInfoPtr pScrn )
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   BEGIN_LP_RING(20);
+
+   OUT_RING(_3DSTATE_AA_CMD |
+	     AA_LINE_ECAAR_WIDTH_ENABLE |
+	     AA_LINE_ECAAR_WIDTH_1_0 |
+	     AA_LINE_REGION_WIDTH_ENABLE |
+	     AA_LINE_REGION_WIDTH_1_0);
+
+   OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD);
+   OUT_RING(0);
+
+   OUT_RING(_3DSTATE_DFLT_SPEC_CMD);
+   OUT_RING(0);
+
+   OUT_RING(_3DSTATE_DFLT_Z_CMD);
+   OUT_RING(0);
+
+   /* Don't support texture crossbar yet */
+   OUT_RING(_3DSTATE_COORD_SET_BINDINGS |
+	     CSB_TCB(0, 0) |
+	     CSB_TCB(1, 1) |
+	     CSB_TCB(2, 2) |
+	     CSB_TCB(3, 3) |
+	     CSB_TCB(4, 4) |
+	     CSB_TCB(5, 5) |
+	     CSB_TCB(6, 6) |
+	     CSB_TCB(7, 7));
+
+   OUT_RING(_3DSTATE_RASTER_RULES_CMD |
+	     ENABLE_POINT_RASTER_RULE |
+	     OGL_POINT_RASTER_RULE |
+	     ENABLE_LINE_STRIP_PROVOKE_VRTX |
+	     ENABLE_TRI_FAN_PROVOKE_VRTX |
+	     LINE_STRIP_PROVOKE_VRTX(1) |
+	     TRI_FAN_PROVOKE_VRTX(2) | 
+	     ENABLE_TEXKILL_3D_4D |
+	     TEXKILL_4D);
+
+   /* Need to initialize this to zero.
+    */
+   OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 
+	     I1_LOAD_S(3) |
+	     (1));
+   OUT_RING(0);
+ 
+   /* XXX: Use this */
+   OUT_RING(_3DSTATE_SCISSOR_ENABLE_CMD | 
+	     DISABLE_SCISSOR_RECT);
+
+   OUT_RING(_3DSTATE_SCISSOR_RECT_0_CMD);
+   OUT_RING(0);
+   OUT_RING(0);
+
+   OUT_RING(_3DSTATE_DEPTH_SUBRECT_DISABLE);
+
+   OUT_RING(_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */
+   OUT_RING(0);
+
+   /* Don't support twosided stencil yet */
+   OUT_RING(_3DSTATE_BACKFACE_STENCIL_OPS |
+	     BFO_ENABLE_STENCIL_TWO_SIDE |
+	     0 );
+
+   OUT_RING(0);
+   
+   ADVANCE_LP_RING();
+}
diff --git a/src/i915_3d.h b/src/i915_3d.h
new file mode 100644
index 0000000..fc4ca60
--- /dev/null
+++ b/src/i915_3d.h
@@ -0,0 +1,431 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+/* MASK_* are the unshifted bitmasks of the destination mask in arithmetic
+ * operations
+ */
+#define MASK_X			0x1
+#define MASK_Y			0x2
+#define MASK_Z			0x4
+#define MASK_W			0x8
+#define MASK_XYZ		(MASK_X | MASK_Y | MASK_W)
+#define MASK_XYZW		(MASK_XYZ | MASK_W)
+#define MASK_SATURATE		0x10
+
+/* Temporary, undeclared regs. Preserved between phases */
+#define FS_R0			((REG_TYPE_R << 8) | 0)
+#define FS_R1			((REG_TYPE_R << 8) | 1)
+#define FS_R2			((REG_TYPE_R << 8) | 2)
+#define FS_R3			((REG_TYPE_R << 8) | 3)
+
+/* Texture coordinate regs.  Must be declared. */
+#define FS_T0			((REG_TYPE_T << 8) | 0)
+#define FS_T1			((REG_TYPE_T << 8) | 1)
+#define FS_T2			((REG_TYPE_T << 8) | 2)
+#define FS_T3			((REG_TYPE_T << 8) | 3)
+#define FS_T4			((REG_TYPE_T << 8) | 4)
+#define FS_T5			((REG_TYPE_T << 8) | 5)
+#define FS_T6			((REG_TYPE_T << 8) | 6)
+#define FS_T7			((REG_TYPE_T << 8) | 7)
+#define FS_T8			((REG_TYPE_T << 8) | 8)
+#define FS_T9			((REG_TYPE_T << 8) | 9)
+#define FS_T10			((REG_TYPE_T << 8) | 10)
+
+/* Constant values */
+#define FS_C0			((REG_TYPE_CONST << 8) | 0)
+#define FS_C1			((REG_TYPE_CONST << 8) | 1)
+#define FS_C2			((REG_TYPE_CONST << 8) | 2)
+#define FS_C3			((REG_TYPE_CONST << 8) | 3)
+
+/* Sampler regs */
+#define FS_S0			((REG_TYPE_S << 8) | 0)
+#define FS_S1			((REG_TYPE_S << 8) | 1)
+#define FS_S2			((REG_TYPE_S << 8) | 2)
+#define FS_S3			((REG_TYPE_S << 8) | 3)
+
+/* Output color */
+#define FS_OC			((REG_TYPE_OC << 8) | 0)
+
+/* Output depth */
+#define FS_OD			((REG_TYPE_OD << 8) | 0)
+
+/* Unpreserved temporary regs */
+#define FS_U0			((REG_TYPE_U << 8) | 0)
+#define FS_U1			((REG_TYPE_U << 8) | 1)
+#define FS_U2			((REG_TYPE_U << 8) | 2)
+#define FS_U3			((REG_TYPE_U << 8) | 3)
+
+#define REG_TYPE(reg)		((reg) >> 8)
+#define REG_NR(reg)		((reg) & 0xff)
+
+struct i915_fs_op {
+    CARD32 ui[3];
+};
+
+#define X_CHANNEL_VAL		1
+#define Y_CHANNEL_VAL		2
+#define Z_CHANNEL_VAL		3
+#define W_CHANNEL_VAL		4
+#define ZERO_CHANNEL_VAL	5
+#define ONE_CHANNEL_VAL		6
+
+/**
+ * This structure represents the contents of an operand to an i915 fragment
+ * shader.
+ *
+ * It is not a hardware representation, though closely related.
+ */
+struct i915_fs_operand {
+    /**< REG_TYPE_* register type */
+    int reg;
+    /**< *_CHANNEL_VAL swizzle value, with optional negation */
+    int x;
+    /**< *_CHANNEL_VAL swizzle value, with optional negation */
+    int y;
+    /**< *_CHANNEL_VAL swizzle value, with optional negation */
+    int z;
+    /**< *_CHANNEL_VAL swizzle value, with optional negation */
+    int w;
+};
+
+/**
+ * Construct an operand description for the fragment shader.
+ *
+ * \param regtype FS_* register used as the source value for X/Y/Z/W sources.
+ * \param x *_CHANNEL_VAL swizzle value prefix for operand X channel, with
+ *          optional negation.
+ * \param y *_CHANNEL_VAL swizzle value prefix for operand Y channel, with
+ *          optional negation.
+ * \param z *_CHANNEL_VAL swizzle value prefix for operand Z channel, with
+ *          optional negation.
+ * \param w *_CHANNEL_VAL swizzle value prefix for operand W channel, with
+ *          optional negation.
+ */
+#define i915_fs_operand(reg, x, y, z, w)				\
+    _i915_fs_operand(reg,						\
+		     x##_CHANNEL_VAL, y##_CHANNEL_VAL,			\
+		     z##_CHANNEL_VAL, w##_CHANNEL_VAL)
+
+/**
+ * Construct an oeprand description for using a register with no swizzling
+ */
+#define i915_fs_operand_reg(reg)					\
+    i915_fs_operand(reg, X, Y, Z, W)
+
+static inline struct i915_fs_operand
+_i915_fs_operand(int reg, int x, int y, int z, int w)
+{
+    struct i915_fs_operand operand;
+
+    operand.reg = reg;
+    operand.x = x;
+    operand.y = y;
+    operand.z = z;
+    operand.w = w;
+
+    return operand;
+}
+
+/**
+ * Returns an operand containing (0.0, 0.0, 0.0, 0.0).
+ */
+static inline struct i915_fs_operand
+i915_fs_operand_zero(void)
+{
+    return i915_fs_operand(FS_R0, ZERO, ZERO, ZERO, ZERO);
+}
+
+/**
+ * Returns an unused operand
+ */
+#define i915_fs_operand_none() i915_fs_operand_zero()
+
+/**
+ * Returns an operand containing (1.0, 1.0, 1.0, 1.0).
+ */
+static inline struct i915_fs_operand
+i915_fs_operand_one(void)
+{
+    return i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE);
+}
+
+static inline int
+i915_get_hardware_channel_val(int channel_val)
+{
+    if (channel_val < 0)
+	channel_val = -channel_val;
+
+    switch (channel_val) {
+    case X_CHANNEL_VAL:
+	return SRC_X;
+    case Y_CHANNEL_VAL:
+	return SRC_Y;
+    case Z_CHANNEL_VAL:
+	return SRC_Z;
+    case W_CHANNEL_VAL:
+	return SRC_W;
+    case ZERO_CHANNEL_VAL:
+	return SRC_ZERO;
+    case ONE_CHANNEL_VAL:
+	return SRC_ONE;
+    }
+    FatalError("Bad channel value %d\n", channel_val);
+}
+
+/**
+ * Outputs a fragment shader command to declare a sampler or texture register.
+ */
+#define i915_fs_dcl(reg)						\
+do {									\
+    FS_OUT(_i915_fs_dcl(reg));						\
+} while (0)
+
+/**
+ * Constructs a fragment shader command to declare a sampler or texture
+ * register.
+ */
+static inline struct i915_fs_op
+_i915_fs_dcl(int reg)
+{
+    struct i915_fs_op op;
+
+    op.ui[0] = D0_DCL | (REG_TYPE(reg) << D0_TYPE_SHIFT) |
+	(REG_NR(reg) << D0_NR_SHIFT);
+    op.ui[1] = 0;
+    op.ui[2] = 0;
+    if (REG_TYPE(reg) != REG_TYPE_S)
+	op.ui[0] |= D0_CHANNEL_ALL;
+
+    return op;
+}
+
+/**
+ * Constructs a fragment shader command to load from a texture sampler.
+ */
+#define i915_fs_texld(dest_reg, sampler_reg, address_reg)		\
+do {									\
+     FS_OUT(_i915_fs_texld(T0_TEXLD, dest_reg, sampler_reg, address_reg)); \
+} while (0)
+
+static inline struct i915_fs_op
+_i915_fs_texld(int load_op, int dest_reg, int sampler_reg, int address_reg)
+{
+    struct i915_fs_op op;
+
+    op.ui[0] = 0;
+    op.ui[1] = 0;
+    op.ui[2] = 0;
+
+    if (REG_TYPE(sampler_reg) != REG_TYPE_S)
+	FatalError("Bad sampler reg type\n");
+
+    op.ui[0] |= load_op;
+    op.ui[0] |= REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT;
+    op.ui[0] |= REG_NR(dest_reg) << T0_DEST_NR_SHIFT;
+    op.ui[0] |= REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT;
+    op.ui[1] |= REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT;
+    op.ui[1] |= REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT;
+
+    return op;
+}
+
+#define i915_fs_arith(op, dest_reg, operand0, operand1, operand2)	\
+    _i915_fs_arith(A0_##op, dest_reg, operand0, operand1, operand2)
+
+static inline struct i915_fs_op
+_i915_fs_arith(int cmd, int dest_reg,
+	       struct i915_fs_operand operand0,
+	       struct i915_fs_operand operand1,
+	       struct i915_fs_operand operand2)
+{
+    struct i915_fs_op op;
+
+    op.ui[0] = 0;
+    op.ui[1] = 0;
+    op.ui[2] = 0;
+
+    /* Set up destination register and write mask */
+    op.ui[0] |= cmd;
+    op.ui[0] |= REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT;
+    op.ui[0] |= REG_NR(dest_reg) << A0_DEST_NR_SHIFT;
+    op.ui[0] |= A0_DEST_CHANNEL_ALL;
+
+    /* Set up operand 0 */
+    op.ui[0] |= REG_TYPE(operand0.reg) << A0_SRC0_TYPE_SHIFT;
+    op.ui[0] |= REG_NR(operand0.reg) << A0_SRC0_NR_SHIFT;
+
+    op.ui[1] |= i915_get_hardware_channel_val(operand0.x) <<
+	A1_SRC0_CHANNEL_X_SHIFT;
+    if (operand0.x < 0)
+	op.ui[1] |= A1_SRC0_CHANNEL_X_NEGATE;
+
+    op.ui[1] |= i915_get_hardware_channel_val(operand0.y) <<
+	A1_SRC0_CHANNEL_Y_SHIFT;
+    if (operand0.y < 0)
+	op.ui[1] |= A1_SRC0_CHANNEL_Y_NEGATE;
+
+    op.ui[1] |= i915_get_hardware_channel_val(operand0.z) <<
+	A1_SRC0_CHANNEL_Z_SHIFT;
+    if (operand0.z < 0)
+	op.ui[1] |= A1_SRC0_CHANNEL_Z_NEGATE;
+
+    op.ui[1] |= i915_get_hardware_channel_val(operand0.w) <<
+	A1_SRC0_CHANNEL_W_SHIFT;
+    if (operand0.w < 0)
+	op.ui[1] |= A1_SRC0_CHANNEL_W_NEGATE;
+
+    /* Set up operand 1 */
+    op.ui[1] |= REG_TYPE(operand1.reg) << A1_SRC1_TYPE_SHIFT;
+    op.ui[1] |= REG_NR(operand1.reg) << A1_SRC1_NR_SHIFT;
+
+    op.ui[1] |= i915_get_hardware_channel_val(operand1.x) <<
+	A1_SRC1_CHANNEL_X_SHIFT;
+    if (operand1.x < 0)
+	op.ui[1] |= A1_SRC1_CHANNEL_X_NEGATE;
+
+    op.ui[1] |= i915_get_hardware_channel_val(operand1.y) <<
+	A1_SRC1_CHANNEL_Y_SHIFT;
+    if (operand1.y < 0)
+	op.ui[1] |= A1_SRC1_CHANNEL_Y_NEGATE;
+
+    op.ui[2] |= i915_get_hardware_channel_val(operand1.z) <<
+	A2_SRC1_CHANNEL_Z_SHIFT;
+    if (operand1.z < 0)
+	op.ui[2] |= A2_SRC1_CHANNEL_Z_NEGATE;
+
+    op.ui[2] |= i915_get_hardware_channel_val(operand1.w) <<
+	A2_SRC1_CHANNEL_W_SHIFT;
+    if (operand1.w < 0)
+	op.ui[2] |= A2_SRC1_CHANNEL_W_NEGATE;
+
+    /* Set up operand 2 */
+    op.ui[2] |= REG_TYPE(operand2.reg) << A2_SRC2_TYPE_SHIFT;
+    op.ui[2] |= REG_NR(operand2.reg) << A2_SRC2_NR_SHIFT;
+
+    op.ui[2] |= i915_get_hardware_channel_val(operand2.x) <<
+	A2_SRC2_CHANNEL_X_SHIFT;
+    if (operand2.x < 0)
+	op.ui[2] |= A2_SRC2_CHANNEL_X_NEGATE;
+
+    op.ui[2] |= i915_get_hardware_channel_val(operand2.y) <<
+	A2_SRC2_CHANNEL_Y_SHIFT;
+    if (operand2.y < 0)
+	op.ui[2] |= A2_SRC2_CHANNEL_Y_NEGATE;
+
+    op.ui[2] |= i915_get_hardware_channel_val(operand2.z) <<
+	A2_SRC2_CHANNEL_Z_SHIFT;
+    if (operand2.z < 0)
+	op.ui[2] |= A2_SRC2_CHANNEL_Z_NEGATE;
+
+    op.ui[2] |= i915_get_hardware_channel_val(operand2.w) <<
+	A2_SRC2_CHANNEL_W_SHIFT;
+    if (operand2.w < 0)
+	op.ui[2] |= A2_SRC2_CHANNEL_W_NEGATE;
+
+    return op;
+}
+
+/**
+ * Move the values in operand0 to the dest reg with the masking/saturation
+ * specified.
+ */
+#define i915_fs_mov_masked(dest_reg, dest_mask, operand0)		\
+do {									\
+    struct i915_fs_op op;						\
+									\
+    op = i915_fs_arith(MOV, dest_reg, operand0, i915_fs_operand_none(),	\
+		       i915_fs_operand_none());				\
+    op.ui[0] &= ~A0_DEST_CHANNEL_ALL;					\
+    op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \
+    if ((dest_mask) & MASK_SATURATE)					\
+	op.ui[0] |= A0_DEST_SATURATE;					\
+									\
+    FS_OUT(op);								\
+} while (0)
+
+/** Add operand0 and operand1 and put the result in dest_reg */
+#define i915_fs_add(dest_reg, operand0, operand1)			\
+do {									\
+    FS_OUT(i915_fs_arith(ADD, dest_reg, operand0, operand1,		\
+			 i915_fs_operand_none()));			\
+} while (0)
+
+/**
+ * Perform a 3-component dot-product of operand0 and operand1 and put the
+ * resulting scalar in the channels of dest_reg specified by the dest_mask.
+ */
+#define i915_fs_dp3_masked(dest_reg, dest_mask, operand0, operand1)	\
+do {									\
+    struct i915_fs_op op;						\
+									\
+    op = i915_fs_arith(DP3, dest_reg, operand0, i915_fs_operand_none(),	\
+		       i915_fs_operand_none());				\
+    op.ui[0] &= ~A0_DEST_CHANNEL_ALL;					\
+    op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \
+    if ((dest_mask) & MASK_SATURATE)					\
+	op.ui[0] |= A0_DEST_SATURATE;					\
+									\
+    FS_OUT(op);								\
+} while (0)
+
+/**
+ * Sets up local state for accumulating a fragment shader buffer.
+ *
+ * \param x maximum number of shader commands that may be used between
+ *        a FS_START and FS_END
+ */
+#define FS_LOCALS(x)							\
+    CARD32 _shader_buf[(x) * 3];					\
+    int _max_shader_commands = x;					\
+    int _cur_shader_commands
+
+#define FS_BEGIN()							\
+do {									\
+    _cur_shader_commands = 0;						\
+} while (0)
+
+#define FS_OUT(_shaderop)						\
+do {									\
+    _shader_buf[_cur_shader_commands * 3 + 0] = _shaderop.ui[0];	\
+    _shader_buf[_cur_shader_commands * 3 + 1] = _shaderop.ui[1];	\
+    _shader_buf[_cur_shader_commands * 3 + 2] = _shaderop.ui[2];	\
+    if (++_cur_shader_commands > _max_shader_commands)			\
+	 FatalError("fragment shader command buffer exceeded (%d)\n",	\
+		    _cur_shader_commands);				\
+} while (0)
+
+#define FS_END()							\
+do {									\
+    int _i;								\
+    BEGIN_LP_RING(_cur_shader_commands * 3 + 1);			\
+    OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |				\
+	     (_cur_shader_commands * 3 - 1));				\
+    for (_i = 0; _i < _cur_shader_commands * 3; _i++)			\
+	OUT_RING(_shader_buf[_i]);					\
+    ADVANCE_LP_RING();							\
+} while (0);
diff --git a/src/i915_reg.h b/src/i915_reg.h
new file mode 100644
index 0000000..6d4f8fc
--- /dev/null
+++ b/src/i915_reg.h
@@ -0,0 +1,848 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#ifndef _I915_REG_H_
+#define _I915_REG_H_
+
+#define I915_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
+
+#define CMD_3D (0x3<<29)
+
+#define PRIM3D_INLINE		(CMD_3D | (0x1f<<24))
+#define PRIM3D_TRILIST		(0x0<<18)
+#define PRIM3D_TRISTRIP 	(0x1<<18)
+#define PRIM3D_TRISTRIP_RVRSE	(0x2<<18)
+#define PRIM3D_TRIFAN		(0x3<<18)
+#define PRIM3D_POLY		(0x4<<18)
+#define PRIM3D_LINELIST 	(0x5<<18)
+#define PRIM3D_LINESTRIP	(0x6<<18)
+#define PRIM3D_RECTLIST 	(0x7<<18)
+#define PRIM3D_POINTLIST	(0x8<<18)
+#define PRIM3D_DIB		(0x9<<18)
+#define PRIM3D_CLEAR_RECT	(0xa<<18)
+#define PRIM3D_ZONE_INIT	(0xd<<18)
+#define PRIM3D_MASK		(0x1f<<18)
+
+/* p137 */
+#define _3DSTATE_AA_CMD			(CMD_3D | (0x06<<24))
+#define AA_LINE_ECAAR_WIDTH_ENABLE	(1<<16)
+#define AA_LINE_ECAAR_WIDTH_0_5 	0
+#define AA_LINE_ECAAR_WIDTH_1_0		(1<<14)
+#define AA_LINE_ECAAR_WIDTH_2_0 	(2<<14)
+#define AA_LINE_ECAAR_WIDTH_4_0 	(3<<14)
+#define AA_LINE_REGION_WIDTH_ENABLE	(1<<8)
+#define AA_LINE_REGION_WIDTH_0_5	0
+#define AA_LINE_REGION_WIDTH_1_0	(1<<6)
+#define AA_LINE_REGION_WIDTH_2_0	(2<<6)
+#define AA_LINE_REGION_WIDTH_4_0	(3<<6)
+
+/* 3DSTATE_BACKFACE_STENCIL_OPS, p138*/
+#define _3DSTATE_BACKFACE_STENCIL_OPS    (CMD_3D | (0x8<<24))
+#define BFO_ENABLE_STENCIL_REF          (1<<23)
+#define BFO_STENCIL_REF_SHIFT           15
+#define BFO_STENCIL_REF_MASK            (0xff<<15)
+#define BFO_ENABLE_STENCIL_FUNCS        (1<<14)
+#define BFO_STENCIL_TEST_SHIFT          11
+#define BFO_STENCIL_TEST_MASK           (0x7<<11)
+#define BFO_STENCIL_FAIL_SHIFT          8
+#define BFO_STENCIL_FAIL_MASK           (0x7<<8)
+#define BFO_STENCIL_PASS_Z_FAIL_SHIFT   5
+#define BFO_STENCIL_PASS_Z_FAIL_MASK    (0x7<<5)
+#define BFO_STENCIL_PASS_Z_PASS_SHIFT   2
+#define BFO_STENCIL_PASS_Z_PASS_MASK    (0x7<<2)
+#define BFO_ENABLE_STENCIL_TWO_SIDE     (1<<1)
+#define BFO_STENCIL_TWO_SIDE            (1<<0)
+
+
+/* 3DSTATE_BACKFACE_STENCIL_MASKS, p140 */
+#define _3DSTATE_BACKFACE_STENCIL_MASKS    (CMD_3D | (0x9<<24))
+#define BFM_ENABLE_STENCIL_TEST_MASK      (1<<17)
+#define BFM_ENABLE_STENCIL_WRITE_MASK     (1<<16)
+#define BFM_STENCIL_TEST_MASK_SHIFT       8
+#define BFM_STENCIL_TEST_MASK_MASK        (0xff<<8)
+#define BFM_STENCIL_WRITE_MASK_SHIFT      0
+#define BFM_STENCIL_WRITE_MASK_MASK       (0xff<<0)
+
+
+
+/* 3DSTATE_BIN_CONTROL p141 */
+
+/* p143 */
+#define _3DSTATE_BUF_INFO_CMD	(CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
+/* Dword 1 */
+#define BUF_3D_ID_COLOR_BACK	(0x3<<24)
+#define BUF_3D_ID_DEPTH 	(0x7<<24)
+#define BUF_3D_USE_FENCE	(1<<23)
+#define BUF_3D_TILED_SURFACE	(1<<22)
+#define BUF_3D_TILE_WALK_X	0
+#define BUF_3D_TILE_WALK_Y	(1<<21)
+#define BUF_3D_PITCH(x)         (((x)/4)<<2)
+/* Dword 2 */
+#define BUF_3D_ADDR(x)		((x) & ~0x3)
+
+
+/* 3DSTATE_CHROMA_KEY */
+
+/* 3DSTATE_CLEAR_PARAMETERS, p150 */
+
+/* 3DSTATE_CONSTANT_BLEND_COLOR, p153 */
+#define _3DSTATE_CONST_BLEND_COLOR_CMD	(CMD_3D | (0x1d<<24) | (0x88<<16))
+
+
+
+/* 3DSTATE_COORD_SET_BINDINGS, p154 */
+#define _3DSTATE_COORD_SET_BINDINGS      (CMD_3D | (0x16<<24))
+#define CSB_TCB(iunit, eunit)           ((eunit)<<(iunit*3))
+
+/* p156 */
+#define _3DSTATE_DFLT_DIFFUSE_CMD	(CMD_3D | (0x1d<<24) | (0x99<<16))
+
+/* p157 */
+#define _3DSTATE_DFLT_SPEC_CMD		(CMD_3D | (0x1d<<24) | (0x9a<<16))
+
+/* p158 */
+#define _3DSTATE_DFLT_Z_CMD		(CMD_3D | (0x1d<<24) | (0x98<<16))
+
+
+/* 3DSTATE_DEPTH_OFFSET_SCALE, p159 */
+#define _3DSTATE_DEPTH_OFFSET_SCALE       (CMD_3D | (0x1d<<24) | (0x97<<16))
+/* scale in dword 1 */
+
+
+/* 3DSTATE_DEPTH_SUBRECT_DISABLE, p160 */
+#define _3DSTATE_DEPTH_SUBRECT_DISABLE    (CMD_3D | (0x1c<<24) | (0x11<19) | 0x2)
+
+/* p161 */
+#define _3DSTATE_DST_BUF_VARS_CMD	(CMD_3D | (0x1d<<24) | (0x85<<16))
+/* Dword 1 */
+#define TEX_DEFAULT_COLOR_OGL           (0<<30)
+#define TEX_DEFAULT_COLOR_D3D           (1<<30)
+#define ZR_EARLY_DEPTH                  (1<<29)
+#define LOD_PRECLAMP_OGL                (1<<28)
+#define LOD_PRECLAMP_D3D                (0<<28)
+#define DITHER_FULL_ALWAYS              (0<<26)
+#define DITHER_FULL_ON_FB_BLEND         (1<<26)
+#define DITHER_CLAMPED_ALWAYS           (2<<26)
+#define LINEAR_GAMMA_BLEND_32BPP        (1<<25)
+#define DEBUG_DISABLE_ENH_DITHER        (1<<24)
+#define DSTORG_HORT_BIAS(x)		((x)<<20)
+#define DSTORG_VERT_BIAS(x)		((x)<<16)
+#define COLOR_4_2_2_CHNL_WRT_ALL	0
+#define COLOR_4_2_2_CHNL_WRT_Y		(1<<12)
+#define COLOR_4_2_2_CHNL_WRT_CR		(2<<12)
+#define COLOR_4_2_2_CHNL_WRT_CB		(3<<12)
+#define COLOR_4_2_2_CHNL_WRT_CRCB	(4<<12)
+#define COLR_BUF_8BIT			0
+#define COLR_BUF_RGB555 		(1<<8)
+#define COLR_BUF_RGB565 		(2<<8)
+#define COLR_BUF_ARGB8888		(3<<8)
+#define DEPTH_FRMT_16_FIXED		0
+#define DEPTH_FRMT_16_FLOAT		(1<<2)
+#define DEPTH_FRMT_24_FIXED_8_OTHER	(2<<2)
+#define VERT_LINE_STRIDE_1		(1<<1)
+#define VERT_LINE_STRIDE_0		(0<<1)
+#define VERT_LINE_STRIDE_OFS_1		1
+#define VERT_LINE_STRIDE_OFS_0		0
+
+/* p166 */
+#define _3DSTATE_DRAW_RECT_CMD		(CMD_3D|(0x1d<<24)|(0x80<<16)|3)
+/* Dword 1 */
+#define DRAW_RECT_DIS_DEPTH_OFS 	(1<<30)
+#define DRAW_DITHER_OFS_X(x)		((x)<<26)
+#define DRAW_DITHER_OFS_Y(x)		((x)<<24)
+/* Dword 2 */
+#define DRAW_YMIN(x)			((x)<<16)
+#define DRAW_XMIN(x)			(x)
+/* Dword 3 */
+#define DRAW_YMAX(x)			((x)<<16)
+#define DRAW_XMAX(x)			(x)
+/* Dword 4 */
+#define DRAW_YORG(x)			((x)<<16)
+#define DRAW_XORG(x)			(x)
+
+
+/* 3DSTATE_FILTER_COEFFICIENTS_4X4, p170 */
+
+/* 3DSTATE_FILTER_COEFFICIENTS_6X5, p172 */
+
+
+/* _3DSTATE_FOG_COLOR, p173 */
+#define _3DSTATE_FOG_COLOR_CMD		(CMD_3D|(0x15<<24))
+#define FOG_COLOR_RED(x)		((x)<<16)
+#define FOG_COLOR_GREEN(x)		((x)<<8)
+#define FOG_COLOR_BLUE(x)		(x)
+
+/* _3DSTATE_FOG_MODE, p174 */
+#define _3DSTATE_FOG_MODE_CMD		(CMD_3D|(0x1d<<24)|(0x89<<16)|2)
+/* Dword 1 */
+#define FMC1_FOGFUNC_MODIFY_ENABLE	(1<<31)
+#define FMC1_FOGFUNC_VERTEX		(0<<28)
+#define FMC1_FOGFUNC_PIXEL_EXP		(1<<28)
+#define FMC1_FOGFUNC_PIXEL_EXP2		(2<<28)
+#define FMC1_FOGFUNC_PIXEL_LINEAR	(3<<28)
+#define FMC1_FOGFUNC_MASK		(3<<28)
+#define FMC1_FOGINDEX_MODIFY_ENABLE     (1<<27)
+#define FMC1_FOGINDEX_Z		        (0<<25)
+#define FMC1_FOGINDEX_W   		(1<<25)
+#define FMC1_C1_C2_MODIFY_ENABLE	(1<<24)
+#define FMC1_DENSITY_MODIFY_ENABLE	(1<<23)
+#define FMC1_C1_ONE      	        (1<<13)
+#define FMC1_C1_MASK		        (0xffff<<4)
+/* Dword 2 */
+#define FMC2_C2_ONE		        (1<<16)
+/* Dword 3 */
+#define FMC3_D_ONE      		(1<<16)
+
+
+
+/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p177 */
+#define _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD	(CMD_3D|(0x0b<<24))
+#define IAB_MODIFY_ENABLE	        (1<<23)
+#define IAB_ENABLE       	        (1<<22)
+#define IAB_MODIFY_FUNC         	(1<<21)
+#define IAB_FUNC_SHIFT          	16
+#define IAB_MODIFY_SRC_FACTOR   	(1<<11)
+#define IAB_SRC_FACTOR_SHIFT		6
+#define IAB_SRC_FACTOR_MASK		(BLENDFACT_MASK<<6)
+#define IAB_MODIFY_DST_FACTOR	        (1<<5)
+#define IAB_DST_FACTOR_SHIFT		0
+#define IAB_DST_FACTOR_MASK		(BLENDFACT_MASK<<0)
+
+#define BLENDFACT_ZERO			0x01
+#define BLENDFACT_ONE			0x02
+#define BLENDFACT_SRC_COLR		0x03
+#define BLENDFACT_INV_SRC_COLR 		0x04
+#define BLENDFACT_SRC_ALPHA		0x05
+#define BLENDFACT_INV_SRC_ALPHA 	0x06
+#define BLENDFACT_DST_ALPHA		0x07
+#define BLENDFACT_INV_DST_ALPHA 	0x08
+#define BLENDFACT_DST_COLR		0x09
+#define BLENDFACT_INV_DST_COLR		0x0a
+#define BLENDFACT_SRC_ALPHA_SATURATE	0x0b
+#define BLENDFACT_CONST_COLOR		0x0c
+#define BLENDFACT_INV_CONST_COLOR	0x0d
+#define BLENDFACT_CONST_ALPHA		0x0e
+#define BLENDFACT_INV_CONST_ALPHA	0x0f
+#define BLENDFACT_MASK          	0x0f
+
+#define BLENDFUNC_ADD			0x0
+#define BLENDFUNC_SUBTRACT		0x1
+#define BLENDFUNC_REVERSE_SUBTRACT	0x2
+#define BLENDFUNC_MIN			0x3
+#define BLENDFUNC_MAX			0x4
+#define BLENDFUNC_MASK			0x7
+
+/* 3DSTATE_LOAD_INDIRECT, p180 */
+
+#define _3DSTATE_LOAD_INDIRECT	        (CMD_3D|(0x1d<<24)|(0x7<<16))
+#define LI0_STATE_STATIC_INDIRECT       (0x01<<8)
+#define LI0_STATE_DYNAMIC_INDIRECT      (0x02<<8)
+#define LI0_STATE_SAMPLER               (0x04<<8)
+#define LI0_STATE_MAP                   (0x08<<8)
+#define LI0_STATE_PROGRAM               (0x10<<8)
+#define LI0_STATE_CONSTANTS             (0x20<<8)
+
+#define SIS0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define SIS0_FORCE_LOAD                 (1<<1)
+#define SIS0_BUFFER_VALID               (1<<0)
+#define SIS1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+#define DIS0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define DIS0_BUFFER_RESET               (1<<1)
+#define DIS0_BUFFER_VALID               (1<<0)
+
+#define SSB0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define SSB0_FORCE_LOAD                 (1<<1)
+#define SSB0_BUFFER_VALID               (1<<0)
+#define SSB1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+#define MSB0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define MSB0_FORCE_LOAD                 (1<<1)
+#define MSB0_BUFFER_VALID               (1<<0)
+#define MSB1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+#define PSP0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define PSP0_FORCE_LOAD                 (1<<1)
+#define PSP0_BUFFER_VALID               (1<<0)
+#define PSP1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+#define PSC0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define PSC0_FORCE_LOAD                 (1<<1)
+#define PSC0_BUFFER_VALID               (1<<0)
+#define PSC1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+
+
+
+
+/* _3DSTATE_RASTERIZATION_RULES */
+#define _3DSTATE_RASTER_RULES_CMD	(CMD_3D|(0x07<<24))
+#define ENABLE_POINT_RASTER_RULE	(1<<15)
+#define OGL_POINT_RASTER_RULE		(1<<13)
+#define ENABLE_TEXKILL_3D_4D            (1<<10)
+#define TEXKILL_3D                      (0<<9)
+#define TEXKILL_4D                      (1<<9)
+#define ENABLE_LINE_STRIP_PROVOKE_VRTX	(1<<8)
+#define ENABLE_TRI_FAN_PROVOKE_VRTX	(1<<5)
+#define LINE_STRIP_PROVOKE_VRTX(x)	((x)<<6)
+#define TRI_FAN_PROVOKE_VRTX(x) 	((x)<<3)
+
+/* _3DSTATE_SCISSOR_ENABLE, p256 */
+#define _3DSTATE_SCISSOR_ENABLE_CMD	(CMD_3D|(0x1c<<24)|(0x10<<19))
+#define ENABLE_SCISSOR_RECT		((1<<1) | 1)
+#define DISABLE_SCISSOR_RECT		(1<<1)
+
+/* _3DSTATE_SCISSOR_RECTANGLE_0, p257 */
+#define _3DSTATE_SCISSOR_RECT_0_CMD	(CMD_3D|(0x1d<<24)|(0x81<<16)|1)
+/* Dword 1 */
+#define SCISSOR_RECT_0_YMIN(x)		((x)<<16)
+#define SCISSOR_RECT_0_XMIN(x)		(x)
+/* Dword 2 */
+#define SCISSOR_RECT_0_YMAX(x)		((x)<<16)
+#define SCISSOR_RECT_0_XMAX(x)		(x)
+
+/* p189 */
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_1   ((0x3<<29)|(0x1d<<24)|(0x04<<16))
+#define I1_LOAD_S(n)                      (1<<(4+n))
+
+#define S0_VB_OFFSET_MASK              0xffffffc
+#define S0_AUTO_CACHE_INV_DISABLE      (1<<0)
+
+#define S1_VERTEX_WIDTH_SHIFT          24
+#define S1_VERTEX_WIDTH_MASK           (0x3f<<24)
+#define S1_VERTEX_PITCH_SHIFT          16
+#define S1_VERTEX_PITCH_MASK           (0x3f<<16)
+
+#define TEXCOORDFMT_2D                 0x0
+#define TEXCOORDFMT_3D                 0x1
+#define TEXCOORDFMT_4D                 0x2
+#define TEXCOORDFMT_1D                 0x3
+#define TEXCOORDFMT_2D_16              0x4
+#define TEXCOORDFMT_4D_16              0x5
+#define TEXCOORDFMT_NOT_PRESENT        0xf
+#define S2_TEXCOORD_FMT0_MASK            0xf
+#define S2_TEXCOORD_FMT1_SHIFT           4
+#define S2_TEXCOORD_FMT(unit, type)    ((type)<<(unit*4))
+#define S2_TEXCOORD_NONE               (~0)
+
+/* S3 not interesting */
+
+#define S4_POINT_WIDTH_SHIFT           23
+#define S4_POINT_WIDTH_MASK            (0x1ff<<23)
+#define S4_LINE_WIDTH_SHIFT            19
+#define S4_LINE_WIDTH_ONE              (0x2<<19)
+#define S4_LINE_WIDTH_MASK             (0xf<<19)
+#define S4_FLATSHADE_ALPHA             (1<<18)
+#define S4_FLATSHADE_FOG               (1<<17)
+#define S4_FLATSHADE_SPECULAR          (1<<16)
+#define S4_FLATSHADE_COLOR             (1<<15)
+#define S4_CULLMODE_BOTH	       (0<<13)
+#define S4_CULLMODE_NONE	       (1<<13)
+#define S4_CULLMODE_CW		       (2<<13)
+#define S4_CULLMODE_CCW		       (3<<13)
+#define S4_CULLMODE_MASK	       (3<<13)
+#define S4_VFMT_POINT_WIDTH            (1<<12)
+#define S4_VFMT_SPEC_FOG               (1<<11)
+#define S4_VFMT_COLOR                  (1<<10)
+#define S4_VFMT_DEPTH_OFFSET           (1<<9)
+#define S4_VFMT_XYZ     	       (1<<6)
+#define S4_VFMT_XYZW     	       (2<<6)
+#define S4_VFMT_XY     		       (3<<6)
+#define S4_VFMT_XYW     	       (4<<6)
+#define S4_VFMT_XYZW_MASK              (7<<6)
+#define S4_FORCE_DEFAULT_DIFFUSE       (1<<5)
+#define S4_FORCE_DEFAULT_SPECULAR      (1<<4)
+#define S4_LOCAL_DEPTH_OFFSET_ENABLE   (1<<3)
+#define S4_VFMT_FOG_PARAM              (1<<2)
+#define S4_SPRITE_POINT_ENABLE         (1<<1)
+#define S4_LINE_ANTIALIAS_ENABLE       (1<<0)
+
+#define S4_VFMT_MASK (S4_VFMT_POINT_WIDTH   | 	\
+		      S4_VFMT_SPEC_FOG      |	\
+		      S4_VFMT_COLOR         |	\
+		      S4_VFMT_DEPTH_OFFSET  |	\
+		      S4_VFMT_XYZW_MASK     |	\
+		      S4_VFMT_FOG_PARAM)
+
+
+#define S5_WRITEDISABLE_ALPHA          (1<<31)
+#define S5_WRITEDISABLE_RED            (1<<30)
+#define S5_WRITEDISABLE_GREEN          (1<<29)
+#define S5_WRITEDISABLE_BLUE           (1<<28)
+#define S5_WRITEDISABLE_MASK           (0xf<<28)
+#define S5_FORCE_DEFAULT_POINT_SIZE    (1<<27)
+#define S5_LAST_PIXEL_ENABLE           (1<<26)
+#define S5_GLOBAL_DEPTH_OFFSET_ENABLE  (1<<25)
+#define S5_FOG_ENABLE                  (1<<24)
+#define S5_STENCIL_REF_SHIFT           16
+#define S5_STENCIL_REF_MASK            (0xff<<16)
+#define S5_STENCIL_TEST_FUNC_SHIFT     13
+#define S5_STENCIL_TEST_FUNC_MASK      (0x7<<13)
+#define S5_STENCIL_FAIL_SHIFT          10
+#define S5_STENCIL_FAIL_MASK           (0x7<<10)
+#define S5_STENCIL_PASS_Z_FAIL_SHIFT   7
+#define S5_STENCIL_PASS_Z_FAIL_MASK    (0x7<<7)
+#define S5_STENCIL_PASS_Z_PASS_SHIFT   4
+#define S5_STENCIL_PASS_Z_PASS_MASK    (0x7<<4)
+#define S5_STENCIL_WRITE_ENABLE        (1<<3)
+#define S5_STENCIL_TEST_ENABLE         (1<<2)
+#define S5_COLOR_DITHER_ENABLE         (1<<1)
+#define S5_LOGICOP_ENABLE              (1<<0)
+
+
+#define S6_ALPHA_TEST_ENABLE           (1<<31)
+#define S6_ALPHA_TEST_FUNC_SHIFT       28
+#define S6_ALPHA_TEST_FUNC_MASK        (0x7<<28)
+#define S6_ALPHA_REF_SHIFT             20
+#define S6_ALPHA_REF_MASK              (0xff<<20)
+#define S6_DEPTH_TEST_ENABLE           (1<<19)
+#define S6_DEPTH_TEST_FUNC_SHIFT       16
+#define S6_DEPTH_TEST_FUNC_MASK        (0x7<<16)
+#define S6_CBUF_BLEND_ENABLE           (1<<15)
+#define S6_CBUF_BLEND_FUNC_SHIFT       12
+#define S6_CBUF_BLEND_FUNC_MASK        (0x7<<12)
+#define S6_CBUF_SRC_BLEND_FACT_SHIFT   8
+#define S6_CBUF_SRC_BLEND_FACT_MASK    (0xf<<8)
+#define S6_CBUF_DST_BLEND_FACT_SHIFT   4
+#define S6_CBUF_DST_BLEND_FACT_MASK    (0xf<<4)
+#define S6_DEPTH_WRITE_ENABLE          (1<<3)
+#define S6_COLOR_WRITE_ENABLE          (1<<2)
+#define S6_TRISTRIP_PV_SHIFT           0
+#define S6_TRISTRIP_PV_MASK            (0x3<<0)
+
+#define S7_DEPTH_OFFSET_CONST_MASK     ~0
+
+/* 3DSTATE_MAP_DEINTERLACER_PARAMETERS */
+/* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */
+
+
+/* _3DSTATE_MODES_4, p218 */
+#define _3DSTATE_MODES_4_CMD		(CMD_3D|(0x0d<<24))
+#define ENABLE_LOGIC_OP_FUNC		(1<<23)
+#define LOGIC_OP_FUNC(x)		((x)<<18)
+#define LOGICOP_MASK			(0xf<<18)
+#define LOGICOP_COPY			0xc
+#define MODE4_ENABLE_STENCIL_TEST_MASK	((1<<17)|(0xff00))
+#define ENABLE_STENCIL_TEST_MASK	(1<<17)
+#define STENCIL_TEST_MASK(x)		((x)<<8)
+#define MODE4_ENABLE_STENCIL_WRITE_MASK	((1<<16)|(0x00ff))
+#define ENABLE_STENCIL_WRITE_MASK	(1<<16)
+#define STENCIL_WRITE_MASK(x)		((x)&0xff)
+
+/* _3DSTATE_MODES_5, p220 */
+#define _3DSTATE_MODES_5_CMD		(CMD_3D|(0x0c<<24))
+#define PIPELINE_FLUSH_RENDER_CACHE	(1<<18)
+#define PIPELINE_FLUSH_TEXTURE_CACHE	(1<<16)
+
+
+/* p221 */
+#define _3DSTATE_PIXEL_SHADER_CONSTANTS  (CMD_3D|(0x1d<<24)|(0x6<<16))
+#define PS1_REG(n)                      (1<<(n))
+#define PS2_CONST_X(n)                  (n)
+#define PS3_CONST_Y(n)                  (n)
+#define PS4_CONST_Z(n)                  (n)
+#define PS5_CONST_W(n)                  (n)
+
+/* p222 */
+
+
+#define I915_MAX_TEX_INDIRECT 4
+#define I915_MAX_TEX_INSN     32     
+#define I915_MAX_ALU_INSN     64
+#define I915_MAX_DECL_INSN    27
+#define I915_MAX_TEMPORARY    16
+
+
+/* Each instruction is 3 dwords long, though most don't require all
+ * this space.  Maximum of 123 instructions.  Smaller maxes per insn
+ * type.
+ */
+#define _3DSTATE_PIXEL_SHADER_PROGRAM    (CMD_3D|(0x1d<<24)|(0x5<<16))
+
+#define REG_TYPE_R                 0 /* temporary regs, no need to
+				      * dcl, must be written before
+				      * read -- Preserved between
+				      * phases. 
+				      */
+#define REG_TYPE_T                 1 /* Interpolated values, must be
+				      * dcl'ed before use.
+				      *
+				      * 0..7: texture coord,
+				      * 8: diffuse spec,
+				      * 9: specular color,
+				      * 10: fog parameter in w.
+				      */
+#define REG_TYPE_CONST             2 /* Restriction: only one const
+				      * can be referenced per
+				      * instruction, though it may be
+				      * selected for multiple inputs.
+				      * Constants not initialized
+				      * default to zero.
+				      */
+#define REG_TYPE_S                 3 /* sampler */
+#define REG_TYPE_OC                4 /* output color (rgba) */
+#define REG_TYPE_OD                5 /* output depth (w), xyz are
+				      * temporaries.  If not written,
+				      * interpolated depth is used?
+				      */
+#define REG_TYPE_U                 6 /* unpreserved temporaries */
+#define REG_TYPE_MASK              0x7
+#define REG_NR_MASK                0xf
+
+
+/* REG_TYPE_T:
+ */
+#define T_TEX0     0
+#define T_TEX1     1
+#define T_TEX2     2
+#define T_TEX3     3
+#define T_TEX4     4
+#define T_TEX5     5
+#define T_TEX6     6
+#define T_TEX7     7
+#define T_DIFFUSE  8
+#define T_SPECULAR 9
+#define T_FOG_W    10		/* interpolated fog is in W coord */
+
+/* Arithmetic instructions */
+
+/* .replicate_swizzle == selection and replication of a particular
+ * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww 
+ */
+#define A0_NOP    (0x0<<24)		/* no operation */
+#define A0_ADD    (0x1<<24)		/* dst = src0 + src1 */
+#define A0_MOV    (0x2<<24)		/* dst = src0 */
+#define A0_MUL    (0x3<<24)		/* dst = src0 * src1 */
+#define A0_MAD    (0x4<<24)		/* dst = src0 * src1 + src2 */
+#define A0_DP2ADD (0x5<<24)		/* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */
+#define A0_DP3    (0x6<<24)		/* dst.xyzw = src0.xyz dot src1.xyz */
+#define A0_DP4    (0x7<<24)		/* dst.xyzw = src0.xyzw dot src1.xyzw */
+#define A0_FRC    (0x8<<24)		/* dst = src0 - floor(src0) */
+#define A0_RCP    (0x9<<24)		/* dst.xyzw = 1/(src0.replicate_swizzle) */
+#define A0_RSQ    (0xa<<24)		/* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */
+#define A0_EXP    (0xb<<24)		/* dst.xyzw = exp2(src0.replicate_swizzle) */
+#define A0_LOG    (0xc<<24)		/* dst.xyzw = log2(abs(src0.replicate_swizzle)) */
+#define A0_CMP    (0xd<<24)		/* dst = (src0 >= 0.0) ? src1 : src2 */
+#define A0_MIN    (0xe<<24)		/* dst = (src0 < src1) ? src0 : src1 */
+#define A0_MAX    (0xf<<24)		/* dst = (src0 >= src1) ? src0 : src1 */
+#define A0_FLR    (0x10<<24)		/* dst = floor(src0) */
+#define A0_MOD    (0x11<<24)		/* dst = src0 fmod 1.0 */
+#define A0_TRC    (0x12<<24)		/* dst = int(src0) */
+#define A0_SGE    (0x13<<24)		/* dst = src0 >= src1 ? 1.0 : 0.0 */
+#define A0_SLT    (0x14<<24)		/* dst = src0 < src1 ? 1.0 : 0.0 */
+#define A0_DEST_SATURATE                 (1<<22)
+#define A0_DEST_TYPE_SHIFT                19
+/* Allow: R, OC, OD, U */
+#define A0_DEST_NR_SHIFT                 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define A0_DEST_CHANNEL_X                (1<<10)
+#define A0_DEST_CHANNEL_Y                (2<<10)
+#define A0_DEST_CHANNEL_Z                (4<<10)
+#define A0_DEST_CHANNEL_W                (8<<10)
+#define A0_DEST_CHANNEL_ALL              (0xf<<10)
+#define A0_DEST_CHANNEL_SHIFT            10
+#define A0_SRC0_TYPE_SHIFT               7
+#define A0_SRC0_NR_SHIFT                 2
+
+#define A0_DEST_CHANNEL_XY              (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y)
+#define A0_DEST_CHANNEL_XYZ             (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z)
+
+
+#define SRC_X        0
+#define SRC_Y        1
+#define SRC_Z        2
+#define SRC_W        3
+#define SRC_ZERO     4
+#define SRC_ONE      5
+
+#define A1_SRC0_CHANNEL_X_NEGATE         (1<<31)
+#define A1_SRC0_CHANNEL_X_SHIFT          28
+#define A1_SRC0_CHANNEL_Y_NEGATE         (1<<27)
+#define A1_SRC0_CHANNEL_Y_SHIFT          24
+#define A1_SRC0_CHANNEL_Z_NEGATE         (1<<23)
+#define A1_SRC0_CHANNEL_Z_SHIFT          20
+#define A1_SRC0_CHANNEL_W_NEGATE         (1<<19)
+#define A1_SRC0_CHANNEL_W_SHIFT          16
+#define A1_SRC1_TYPE_SHIFT               13
+#define A1_SRC1_NR_SHIFT                 8
+#define A1_SRC1_CHANNEL_X_NEGATE         (1<<7)
+#define A1_SRC1_CHANNEL_X_SHIFT          4
+#define A1_SRC1_CHANNEL_Y_NEGATE         (1<<3)
+#define A1_SRC1_CHANNEL_Y_SHIFT          0
+
+#define A2_SRC1_CHANNEL_Z_NEGATE         (1<<31)
+#define A2_SRC1_CHANNEL_Z_SHIFT          28
+#define A2_SRC1_CHANNEL_W_NEGATE         (1<<27)
+#define A2_SRC1_CHANNEL_W_SHIFT          24
+#define A2_SRC2_TYPE_SHIFT               21
+#define A2_SRC2_NR_SHIFT                 16
+#define A2_SRC2_CHANNEL_X_NEGATE         (1<<15)
+#define A2_SRC2_CHANNEL_X_SHIFT          12
+#define A2_SRC2_CHANNEL_Y_NEGATE         (1<<11)
+#define A2_SRC2_CHANNEL_Y_SHIFT          8
+#define A2_SRC2_CHANNEL_Z_NEGATE         (1<<7)
+#define A2_SRC2_CHANNEL_Z_SHIFT          4
+#define A2_SRC2_CHANNEL_W_NEGATE         (1<<3)
+#define A2_SRC2_CHANNEL_W_SHIFT          0
+
+
+
+/* Texture instructions */
+#define T0_TEXLD     (0x15<<24)	/* Sample texture using predeclared
+				 * sampler and address, and output
+				 * filtered texel data to destination
+				 * register */
+#define T0_TEXLDP    (0x16<<24)	/* Same as texld but performs a
+				 * perspective divide of the texture
+				 * coordinate .xyz values by .w before
+				 * sampling. */
+#define T0_TEXLDB    (0x17<<24)	/* Same as texld but biases the
+				 * computed LOD by w.  Only S4.6 two's
+				 * comp is used.  This implies that a
+				 * float to fixed conversion is
+				 * done. */
+#define T0_TEXKILL   (0x18<<24)	/* Does not perform a sampling
+				 * operation.  Simply kills the pixel
+				 * if any channel of the address
+				 * register is < 0.0. */
+#define T0_DEST_TYPE_SHIFT                19
+/* Allow: R, OC, OD, U */
+/* Note: U (unpreserved) regs do not retain their values between
+ * phases (cannot be used for feedback) 
+ *
+ * Note: oC and OD registers can only be used as the destination of a
+ * texture instruction once per phase (this is an implementation
+ * restriction). 
+ */
+#define T0_DEST_NR_SHIFT                 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define T0_SAMPLER_NR_SHIFT              0 /* This field ignored for TEXKILL */
+#define T0_SAMPLER_NR_MASK               (0xf<<0)
+
+#define T1_ADDRESS_REG_TYPE_SHIFT        24 /* Reg to use as texture coord */
+/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */
+#define T1_ADDRESS_REG_NR_SHIFT          17
+#define T2_MBZ                           0
+
+/* Declaration instructions */
+#define D0_DCL       (0x19<<24)	/* Declare a t (interpolated attrib)
+				 * register or an s (sampler)
+				 * register. */
+#define D0_SAMPLE_TYPE_SHIFT              22
+#define D0_SAMPLE_TYPE_2D                 (0x0<<22)
+#define D0_SAMPLE_TYPE_CUBE               (0x1<<22)
+#define D0_SAMPLE_TYPE_VOLUME             (0x2<<22)
+#define D0_SAMPLE_TYPE_MASK               (0x3<<22)
+
+#define D0_TYPE_SHIFT                19
+/* Allow: T, S */
+#define D0_NR_SHIFT                  14
+/* Allow T: 0..10, S: 0..15 */
+#define D0_CHANNEL_X                (1<<10)
+#define D0_CHANNEL_Y                (2<<10)
+#define D0_CHANNEL_Z                (4<<10)
+#define D0_CHANNEL_W                (8<<10)
+#define D0_CHANNEL_ALL              (0xf<<10)
+#define D0_CHANNEL_NONE             (0<<10)
+
+#define D0_CHANNEL_XY               (D0_CHANNEL_X|D0_CHANNEL_Y)
+#define D0_CHANNEL_XYZ              (D0_CHANNEL_XY|D0_CHANNEL_Z)
+
+/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse
+ * or specular declarations. 
+ *
+ * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw) 
+ *
+ * Must be zero for S (sampler) dcls
+ */
+#define D1_MBZ                          0
+#define D2_MBZ                          0
+
+
+
+/* p207 */
+#define _3DSTATE_MAP_STATE               (CMD_3D|(0x1d<<24)|(0x0<<16))
+
+#define MS1_MAPMASK_SHIFT               0
+#define MS1_MAPMASK_MASK                (0x8fff<<0)
+
+#define MS2_UNTRUSTED_SURFACE           (1<<31)
+#define MS2_ADDRESS_MASK                0xfffffffc
+#define MS2_VERTICAL_LINE_STRIDE        (1<<1)
+#define MS2_VERTICAL_OFFSET             (1<<1)
+
+#define MS3_HEIGHT_SHIFT              21
+#define MS3_WIDTH_SHIFT               10
+#define MS3_PALETTE_SELECT            (1<<9)
+#define MS3_MAPSURF_FORMAT_SHIFT      7
+#define MS3_MAPSURF_FORMAT_MASK       (0x7<<7)
+#define    MAPSURF_8BIT		 	   (1<<7)
+#define    MAPSURF_16BIT		   (2<<7)
+#define    MAPSURF_32BIT		   (3<<7)
+#define    MAPSURF_422			   (5<<7)
+#define    MAPSURF_COMPRESSED		   (6<<7)
+#define    MAPSURF_4BIT_INDEXED		   (7<<7)
+#define MS3_MT_FORMAT_MASK         (0x7 << 3)
+#define MS3_MT_FORMAT_SHIFT        3
+#define    MT_4BIT_IDX_ARGB8888	           (7<<3) /* SURFACE_4BIT_INDEXED */
+#define    MT_8BIT_I8		           (0<<3) /* SURFACE_8BIT */
+#define    MT_8BIT_L8		           (1<<3)
+#define    MT_8BIT_A8		           (4<<3)
+#define    MT_8BIT_MONO8	           (5<<3)
+#define    MT_16BIT_RGB565 		   (0<<3) /* SURFACE_16BIT */
+#define    MT_16BIT_ARGB1555		   (1<<3)
+#define    MT_16BIT_ARGB4444		   (2<<3)
+#define    MT_16BIT_AY88		   (3<<3)
+#define    MT_16BIT_88DVDU	           (5<<3)
+#define    MT_16BIT_BUMP_655LDVDU	   (6<<3)
+#define    MT_16BIT_I16	                   (7<<3)
+#define    MT_16BIT_L16	                   (8<<3)
+#define    MT_16BIT_A16	                   (9<<3)
+#define    MT_32BIT_ARGB8888		   (0<<3) /* SURFACE_32BIT */
+#define    MT_32BIT_ABGR8888		   (1<<3)
+#define    MT_32BIT_XRGB8888		   (2<<3)
+#define    MT_32BIT_XBGR8888		   (3<<3)
+#define    MT_32BIT_QWVU8888		   (4<<3)
+#define    MT_32BIT_AXVU8888		   (5<<3)
+#define    MT_32BIT_LXVU8888	           (6<<3)
+#define    MT_32BIT_XLVU8888	           (7<<3)
+#define    MT_32BIT_ARGB2101010	           (8<<3)
+#define    MT_32BIT_ABGR2101010	           (9<<3)
+#define    MT_32BIT_AWVU2101010	           (0xA<<3)
+#define    MT_32BIT_GR1616	           (0xB<<3)
+#define    MT_32BIT_VU1616	           (0xC<<3)
+#define    MT_32BIT_xI824	           (0xD<<3)
+#define    MT_32BIT_xA824	           (0xE<<3)
+#define    MT_32BIT_xL824	           (0xF<<3)
+#define    MT_422_YCRCB_SWAPY	           (0<<3) /* SURFACE_422 */
+#define    MT_422_YCRCB_NORMAL	           (1<<3)
+#define    MT_422_YCRCB_SWAPUV	           (2<<3)
+#define    MT_422_YCRCB_SWAPUVY	           (3<<3)
+#define    MT_COMPRESS_DXT1		   (0<<3) /* SURFACE_COMPRESSED */
+#define    MT_COMPRESS_DXT2_3	           (1<<3)
+#define    MT_COMPRESS_DXT4_5	           (2<<3)
+#define    MT_COMPRESS_FXT1		   (3<<3)
+#define    MT_COMPRESS_DXT1_RGB		   (4<<3)
+#define MS3_USE_FENCE_REGS              (1<<2)
+#define MS3_TILED_SURFACE             (1<<1)
+#define MS3_TILE_WALK                 (1<<0)
+
+#define MS4_PITCH_SHIFT                 21
+#define MS4_CUBE_FACE_ENA_NEGX          (1<<20)
+#define MS4_CUBE_FACE_ENA_POSX          (1<<19)
+#define MS4_CUBE_FACE_ENA_NEGY          (1<<18)
+#define MS4_CUBE_FACE_ENA_POSY          (1<<17)
+#define MS4_CUBE_FACE_ENA_NEGZ          (1<<16)
+#define MS4_CUBE_FACE_ENA_POSZ          (1<<15)
+#define MS4_CUBE_FACE_ENA_MASK          (0x3f<<15)
+#define MS4_MAX_LOD_SHIFT		9
+#define MS4_MAX_LOD_MASK		(0x3f<<9)
+#define MS4_MIP_LAYOUT_LEGACY           (0<<8)
+#define MS4_MIP_LAYOUT_BELOW_LPT        (0<<8)
+#define MS4_MIP_LAYOUT_RIGHT_LPT        (1<<8)
+#define MS4_VOLUME_DEPTH_SHIFT          0    
+#define MS4_VOLUME_DEPTH_MASK           (0xff<<0)
+
+/* p244 */
+#define _3DSTATE_SAMPLER_STATE         (CMD_3D|(0x1d<<24)|(0x1<<16))
+
+#define SS1_MAPMASK_SHIFT               0
+#define SS1_MAPMASK_MASK                (0x8fff<<0)
+
+#define SS2_REVERSE_GAMMA_ENABLE        (1<<31)
+#define SS2_PACKED_TO_PLANAR_ENABLE     (1<<30)
+#define SS2_COLORSPACE_CONVERSION       (1<<29)
+#define SS2_CHROMAKEY_SHIFT             27
+#define SS2_BASE_MIP_LEVEL_SHIFT        22
+#define SS2_BASE_MIP_LEVEL_MASK         (0x1f<<22)
+#define SS2_MIP_FILTER_SHIFT            20
+#define SS2_MIP_FILTER_MASK             (0x3<<20)
+#define   MIPFILTER_NONE       	0
+#define   MIPFILTER_NEAREST	1
+#define   MIPFILTER_LINEAR	3
+#define SS2_MAG_FILTER_SHIFT          17
+#define SS2_MAG_FILTER_MASK           (0x7<<17)
+#define   FILTER_NEAREST	0
+#define   FILTER_LINEAR		1
+#define   FILTER_ANISOTROPIC	2
+#define   FILTER_4X4_1    	3
+#define   FILTER_4X4_2    	4
+#define   FILTER_4X4_FLAT 	5
+#define   FILTER_6X5_MONO   	6 /* XXX - check */
+#define SS2_MIN_FILTER_SHIFT          14
+#define SS2_MIN_FILTER_MASK           (0x7<<14)
+#define SS2_LOD_BIAS_SHIFT            5
+#define SS2_LOD_BIAS_ONE              (0x10<<5)
+#define SS2_LOD_BIAS_MASK             (0x1ff<<5)
+/* Shadow requires:
+ *  MT_X8{I,L,A}24 or MT_{I,L,A}16 texture format
+ *  FILTER_4X4_x  MIN and MAG filters
+ */
+#define SS2_SHADOW_ENABLE             (1<<4)
+#define SS2_MAX_ANISO_MASK            (1<<3)
+#define SS2_MAX_ANISO_2               (0<<3)
+#define SS2_MAX_ANISO_4               (1<<3)
+#define SS2_SHADOW_FUNC_SHIFT         0
+#define SS2_SHADOW_FUNC_MASK          (0x7<<0)
+/* SS2_SHADOW_FUNC values: see COMPAREFUNC_* */
+
+#define SS3_MIN_LOD_SHIFT            24
+#define SS3_MIN_LOD_ONE              (0x10<<24)
+#define SS3_MIN_LOD_MASK             (0xff<<24)
+#define SS3_KILL_PIXEL_ENABLE        (1<<17)
+#define SS3_TCX_ADDR_MODE_SHIFT      12
+#define SS3_TCX_ADDR_MODE_MASK       (0x7<<12)
+#define   TEXCOORDMODE_WRAP		0
+#define   TEXCOORDMODE_MIRROR		1
+#define   TEXCOORDMODE_CLAMP_EDGE	2
+#define   TEXCOORDMODE_CUBE       	3
+#define   TEXCOORDMODE_CLAMP_BORDER	4
+#define   TEXCOORDMODE_MIRROR_ONCE      5
+#define SS3_TCY_ADDR_MODE_SHIFT      9
+#define SS3_TCY_ADDR_MODE_MASK       (0x7<<9)
+#define SS3_TCZ_ADDR_MODE_SHIFT      6
+#define SS3_TCZ_ADDR_MODE_MASK       (0x7<<6)
+#define SS3_NORMALIZED_COORDS        (1<<5)
+#define SS3_TEXTUREMAP_INDEX_SHIFT   1
+#define SS3_TEXTUREMAP_INDEX_MASK    (0xf<<1)
+#define SS3_DEINTERLACER_ENABLE      (1<<0)
+
+#define SS4_BORDER_COLOR_MASK        (~0)
+
+/* 3DSTATE_SPAN_STIPPLE, p258
+ */
+#define _3DSTATE_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define ST1_ENABLE               (1<<16)
+#define ST1_MASK                 (0xffff)
+
+
+#define FLUSH_MAP_CACHE    (1<<0)
+#define FLUSH_RENDER_CACHE (1<<1)
+
+
+#endif



More information about the xorg-commit mailing list