diff -ruN drivers/char/drm-4.2/Makefile drivers/char/drm/Makefile
--- drivers/char/drm-4.2/Makefile	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/Makefile	2003-01-14 07:01:16.000000000 +0900
@@ -7,12 +7,12 @@
 
 gamma-objs  := gamma_drv.o gamma_dma.o
 tdfx-objs   := tdfx_drv.o
-r128-objs   := r128_drv.o r128_cce.o r128_state.o
-mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o
+r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o
+mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
 i810-objs   := i810_drv.o i810_dma.o
-i830-objs   := i830_drv.o i830_dma.o
+i830-objs   := i830_drv.o i830_dma.o i830_irq.o
 
-radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o
+radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
 ffb-objs    := ffb_drv.o ffb_context.o
 sis-objs    := sis_drv.o sis_ds.o sis_mm.o
 
diff -ruN drivers/char/drm-4.2/ati_pcigart.h drivers/char/drm/ati_pcigart.h
--- drivers/char/drm-4.2/ati_pcigart.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/ati_pcigart.h	2003-01-14 07:01:00.000000000 +0900
@@ -27,14 +27,15 @@
  *   Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 #if PAGE_SIZE == 65536
-# define ATI_PCIGART_TABLE_ORDER 	0
-# define ATI_PCIGART_TABLE_PAGES 	(1 << 0)
+# define ATI_PCIGART_TABLE_ORDER	0
+# define ATI_PCIGART_TABLE_PAGES	(1 << 0)
 #elif PAGE_SIZE == 16384
-# define ATI_PCIGART_TABLE_ORDER 	1
-# define ATI_PCIGART_TABLE_PAGES 	(1 << 1)
+# define ATI_PCIGART_TABLE_ORDER	1
+# define ATI_PCIGART_TABLE_PAGES	(1 << 1)
 #elif PAGE_SIZE == 8192
 # define ATI_PCIGART_TABLE_ORDER 	2
 # define ATI_PCIGART_TABLE_PAGES 	(1 << 2)
diff -ruN drivers/char/drm-4.2/dristat.c drivers/char/drm/dristat.c
--- drivers/char/drm-4.2/dristat.c	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/dristat.c	2003-01-14 07:00:59.000000000 +0900
@@ -0,0 +1,280 @@
+/* dristat.c -- 
+ * Created: Mon Jan 15 05:05:07 2001 by faith@acm.org
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
+ * 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "../../../xf86drm.h"
+#include "../xf86drmRandom.c"
+#include "../xf86drmHash.c"
+#include "../xf86drm.c"
+
+#define DRM_VERSION 0x00000001
+#define DRM_MEMORY  0x00000002
+#define DRM_CLIENTS 0x00000004
+#define DRM_STATS   0x00000008
+#define DRM_BUSID   0x00000010
+
+static void getversion(int fd)
+{
+    drmVersionPtr version;
+    
+    version = drmGetVersion(fd);
+    if (version) {
+	printf("  Version information:\n");
+	printf("    Name: %s\n", version->name ? version->name : "?");
+	printf("    Version: %d.%d.%d\n",
+	       version->version_major,
+	       version->version_minor,
+	       version->version_patchlevel);
+	printf("    Date: %s\n", version->date ? version->date : "?");
+	printf("    Desc: %s\n", version->desc ? version->desc : "?");
+	drmFreeVersion(version);
+    } else {
+	printf("  No version information available\n");
+    }
+}
+
+static void getbusid(int fd)
+{
+    const char *busid = drmGetBusid(fd);
+    
+    printf("  Busid: %s\n", *busid ? busid : "(not set)");
+    drmFreeBusid(busid);
+}
+
+#if 0
+typedef struct {
+    unsigned long	offset;	 /* Requested physical address (0 for SAREA)*/
+    unsigned long	size;	 /* Requested physical size (bytes)	    */
+    drm_map_type_t	type;	 /* Type of memory to map		    */
+    drm_map_flags_t flags;	 /* Flags				    */
+    void		*handle; /* User-space: "Handle" to pass to mmap    */
+    /* Kernel-space: kernel-virtual address    */
+    int		mtrr;	 /* MTRR slot used			    */
+				 /* Private data			    */
+} drmVmRec, *drmVmPtr;
+#endif
+
+static void getvm(int fd)
+{
+    int             i;
+    const char      *typename;
+    char            flagname[33];
+    drmHandle       offset;
+    drmSize         size;
+    drmMapType      type;
+    drmMapFlags     flags;
+    drmHandle       handle;
+    int             mtrr;
+
+    printf("  VM map information (Restricted locked kernel WC Lock):\n");
+    printf("    slot     offset       size type flags    address mtrr\n");
+
+    for (i = 0;
+	 !drmGetMap(fd, i, &offset, &size, &type, &flags, &handle, &mtrr);
+	 i++) {
+	
+	switch (type) {
+	case DRM_FRAME_BUFFER: typename = "FB";  break;
+	case DRM_REGISTERS:    typename = "REG"; break;
+	case DRM_SHM:          typename = "SHM"; break;
+	case DRM_AGP:          typename = "AGP"; break;
+	default:               typename = "???"; break;
+	}
+
+	flagname[0] = (flags & DRM_RESTRICTED)      ? 'R' : ' ';
+	flagname[1] = (flags & DRM_READ_ONLY)       ? 'r' : 'w';
+	flagname[2] = (flags & DRM_LOCKED)          ? 'l' : ' ';
+	flagname[3] = (flags & DRM_KERNEL)          ? 'k' : ' ';
+	flagname[4] = (flags & DRM_WRITE_COMBINING) ? 'W' : ' ';
+	flagname[5] = (flags & DRM_CONTAINS_LOCK)   ? 'L' : ' ';
+	flagname[6] = '\0';
+	
+	printf("    %4d 0x%08lx 0x%08lx %3.3s %6.6s 0x%08lx ",
+	       i, offset, (unsigned long)size, typename, flagname, handle);
+	if (mtrr < 0) printf("none\n");
+	else          printf("%4d\n", mtrr);
+    }
+}
+
+static void getclients(int fd)
+{
+    int           i;
+    int           auth;
+    int           pid;
+    int           uid;
+    unsigned long magic;
+    unsigned long iocs;
+    char          buf[64];
+    char          cmd[40];
+    int           procfd;
+    
+    printf("  DRI client information:\n");
+    printf("    a   pid   uid      magic     ioctls   prog\n");
+
+    for (i = 0; !drmGetClient(fd, i, &auth, &pid, &uid, &magic, &iocs); i++) {
+	sprintf(buf, "/proc/%d/cmdline", pid);
+	memset(cmd, sizeof(cmd), 0);
+	if ((procfd = open(buf, O_RDONLY, 0)) >= 0) {
+	    read(procfd, cmd, sizeof(cmd)-1);
+	    close(procfd);
+	}
+	if (*cmd) {
+	    char *pt;
+
+	    for (pt = cmd; *pt; pt++) if (!isprint(*pt)) *pt = ' ';
+	    printf("    %c %5d %5d %10lu %10lu   %s\n",
+		   auth ? 'y' : 'n', pid, uid, magic, iocs, cmd);
+	} else {
+	    printf("    %c %5d %5d %10lu %10lu\n",
+		   auth ? 'y' : 'n', pid, uid, magic, iocs);
+	}
+    }
+}
+
+static void printhuman(unsigned long value, const char *name, int mult)
+{
+    const char *p;
+    double     f;
+				/* Print width 5 number in width 6 space */
+    if (value < 100000) {
+	printf(" %5lu", value);
+	return;
+    }
+
+    p = name;
+    f = (double)value / (double)mult;
+    if (f < 10.0) {
+	printf(" %4.2f%c", f, *p);
+	return;
+    }
+
+    p++;
+    f = (double)value / (double)mult;
+    if (f < 10.0) {
+	printf(" %4.2f%c", f, *p);
+	return;
+    }
+    
+    p++;
+    f = (double)value / (double)mult;
+    if (f < 10.0) {
+	printf(" %4.2f%c", f, *p);
+	return;
+    }
+}
+
+static void getstats(int fd, int i)
+{
+    drmStatsT prev, curr;
+    int       j;
+    double    rate;
+    
+    printf("  System statistics:\n");
+
+    if (drmGetStats(fd, &prev)) return;
+    if (!i) {
+	for (j = 0; j < prev.count; j++) {
+	    printf("    ");
+	    printf(prev.data[j].long_format, prev.data[j].long_name);
+	    if (prev.data[j].isvalue) printf(" 0x%08lx\n", prev.data[j].value);
+	    else                      printf(" %10lu\n", prev.data[j].value);
+	}
+	return;
+    }
+
+    printf("    ");
+    for (j = 0; j < prev.count; j++)
+	if (!prev.data[j].verbose) {
+	    printf(" ");
+	    printf(prev.data[j].rate_format, prev.data[j].rate_name);
+	}
+    printf("\n");
+    
+    for (;;) {
+	sleep(i);
+	if (drmGetStats(fd, &curr)) return;
+	printf("    ");
+	for (j = 0; j < curr.count; j++) {
+	    if (curr.data[j].verbose) continue;
+	    if (curr.data[j].isvalue) {
+		printf(" %08lx", curr.data[j].value);
+	    } else {
+		rate = (curr.data[j].value - prev.data[j].value) / (double)i;
+		printhuman(rate, curr.data[j].mult_names, curr.data[j].mult);
+	    }
+	}
+	printf("\n");
+	memcpy(&prev, &curr, sizeof(prev));
+    }
+    
+}
+
+int main(int argc, char **argv)
+{
+    int  c;
+    int  mask     = 0;
+    int  minor    = 0;
+    int  interval = 0;
+    int  fd;
+    char buf[64];
+    int  i;
+
+    while ((c = getopt(argc, argv, "avmcsbM:i:")) != EOF)
+	switch (c) {
+	case 'a': mask = ~0;                          break;
+	case 'v': mask |= DRM_VERSION;                break;
+	case 'm': mask |= DRM_MEMORY;                 break;
+	case 'c': mask |= DRM_CLIENTS;                break;
+	case 's': mask |= DRM_STATS;                  break;
+	case 'b': mask |= DRM_BUSID;                  break;
+	case 'i': interval = strtol(optarg, NULL, 0); break;
+	case 'M': minor = strtol(optarg, NULL, 0);    break;
+	default:
+	    fprintf( stderr, "Usage: dristat [options]\n" );
+	    return 1;
+	}
+
+    for (i = 0; i < 16; i++) if (!minor || i == minor) {
+	sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i);
+	fd = drmOpenMinor(i, 1);
+	if (fd >= 0) {
+	    printf("%s\n", buf);
+	    if (mask & DRM_BUSID)   getbusid(fd);
+	    if (mask & DRM_VERSION) getversion(fd);
+	    if (mask & DRM_MEMORY)  getvm(fd);
+	    if (mask & DRM_CLIENTS) getclients(fd);
+	    if (mask & DRM_STATS)   getstats(fd, interval);
+	    close(fd);
+	}
+    }
+
+    return 0; 
+}
diff -ruN drivers/char/drm-4.2/drm.h drivers/char/drm/drm.h
--- drivers/char/drm-4.2/drm.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm.h	2003-01-14 07:01:00.000000000 +0900
@@ -38,10 +38,27 @@
 #if defined(__linux__)
 #include <linux/config.h>
 #include <asm/ioctl.h>		/* For _IO* macros */
-#define DRM_IOCTL_NR(n)	     _IOC_NR(n)
-#elif defined(__FreeBSD__)
+#define DRM_IOCTL_NR(n)		_IOC_NR(n)
+#define DRM_IOC_VOID		_IOC_NONE
+#define DRM_IOC_READ		_IOC_READ
+#define DRM_IOC_WRITE		_IOC_WRITE
+#define DRM_IOC_READWRITE	_IOC_READ|_IOC_WRITE
+#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+#if defined(__FreeBSD__) && defined(XFree86Server)
+/* Prevent name collision when including sys/ioccom.h */
+#undef ioctl
 #include <sys/ioccom.h>
-#define DRM_IOCTL_NR(n)	     ((n) & 0xff)
+#define ioctl(a,b,c)		xf86ioctl(a,b,c)
+#else
+#include <sys/ioccom.h>
+#endif /* __FreeBSD__ && xf86ioctl */
+#define DRM_IOCTL_NR(n)		((n) & 0xff)
+#define DRM_IOC_VOID		IOC_VOID
+#define DRM_IOC_READ		IOC_OUT
+#define DRM_IOC_WRITE		IOC_IN
+#define DRM_IOC_READWRITE	IOC_INOUT
+#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
 #endif
 
 #define XFREE86_VERSION(major,minor,patch,snap) \
@@ -84,6 +101,10 @@
 /* Warning: If you change this structure, make sure you change
  * XF86DRIClipRectRec in the server as well */
 
+/* KW: Actually it's illegal to change either for
+ * backwards-compatibility reasons.
+ */
+
 typedef struct drm_clip_rect {
 	unsigned short	x1;
 	unsigned short	y1;
@@ -99,14 +120,6 @@
 	unsigned int	age;
 } drm_tex_region_t;
 
-/* Seperate include files for the i810/mga/r128 specific structures */
-#include "mga_drm.h"
-#include "i810_drm.h"
-#include "r128_drm.h"
-#include "radeon_drm.h"
-#include "sis_drm.h"
-#include "i830_drm.h"
-
 typedef struct drm_version {
 	int    version_major;	  /* Major version			    */
 	int    version_minor;	  /* Minor version			    */
@@ -332,6 +345,32 @@
 	int funcnum;
 } drm_irq_busid_t;
 
+typedef enum {
+    _DRM_VBLANK_ABSOLUTE = 0x0,		/* Wait for specific vblank sequence number */
+    _DRM_VBLANK_RELATIVE = 0x1,		/* Wait for given number of vblanks */
+    _DRM_VBLANK_SIGNAL   = 0x40000000	/* Send signal instead of blocking */
+} drm_vblank_seq_type_t;
+
+#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
+
+struct drm_wait_vblank_request {
+	drm_vblank_seq_type_t type;
+	unsigned int sequence;
+	unsigned long signal;
+};
+
+struct drm_wait_vblank_reply {
+	drm_vblank_seq_type_t type;
+	unsigned int sequence;
+	long tval_sec;
+	long tval_usec;
+};
+
+typedef union drm_wait_vblank {
+	struct drm_wait_vblank_request request;
+	struct drm_wait_vblank_reply reply;
+} drm_wait_vblank_t;
+
 typedef struct drm_agp_mode {
 	unsigned long mode;
 } drm_agp_mode_t;
@@ -371,10 +410,9 @@
 
 #define DRM_IOCTL_BASE			'd'
 #define DRM_IO(nr)			_IO(DRM_IOCTL_BASE,nr)
-#define DRM_IOR(nr,size)		_IOR(DRM_IOCTL_BASE,nr,size)
-#define DRM_IOW(nr,size)		_IOW(DRM_IOCTL_BASE,nr,size)
-#define DRM_IOWR(nr,size)		_IOWR(DRM_IOCTL_BASE,nr,size)
-
+#define DRM_IOR(nr,type)		_IOR(DRM_IOCTL_BASE,nr,type)
+#define DRM_IOW(nr,type)		_IOW(DRM_IOCTL_BASE,nr,type)
+#define DRM_IOWR(nr,type)		_IOWR(DRM_IOCTL_BASE,nr,type)
 
 #define DRM_IOCTL_VERSION		DRM_IOWR(0x00, drm_version_t)
 #define DRM_IOCTL_GET_UNIQUE		DRM_IOWR(0x01, drm_unique_t)
@@ -427,86 +465,10 @@
 #define DRM_IOCTL_SG_ALLOC		DRM_IOW( 0x38, drm_scatter_gather_t)
 #define DRM_IOCTL_SG_FREE		DRM_IOW( 0x39, drm_scatter_gather_t)
 
-/* MGA specific ioctls */
-#define DRM_IOCTL_MGA_INIT		DRM_IOW( 0x40, drm_mga_init_t)
-#define DRM_IOCTL_MGA_FLUSH		DRM_IOW( 0x41, drm_lock_t)
-#define DRM_IOCTL_MGA_RESET		DRM_IO(  0x42)
-#define DRM_IOCTL_MGA_SWAP		DRM_IO(  0x43)
-#define DRM_IOCTL_MGA_CLEAR		DRM_IOW( 0x44, drm_mga_clear_t)
-#define DRM_IOCTL_MGA_VERTEX		DRM_IOW( 0x45, drm_mga_vertex_t)
-#define DRM_IOCTL_MGA_INDICES		DRM_IOW( 0x46, drm_mga_indices_t)
-#define DRM_IOCTL_MGA_ILOAD		DRM_IOW( 0x47, drm_mga_iload_t)
-#define DRM_IOCTL_MGA_BLIT		DRM_IOW( 0x48, drm_mga_blit_t)
-
-/* i810 specific ioctls */
-#define DRM_IOCTL_I810_INIT		DRM_IOW( 0x40, drm_i810_init_t)
-#define DRM_IOCTL_I810_VERTEX		DRM_IOW( 0x41, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_CLEAR		DRM_IOW( 0x42, drm_i810_clear_t)
-#define DRM_IOCTL_I810_FLUSH		DRM_IO(  0x43)
-#define DRM_IOCTL_I810_GETAGE		DRM_IO(  0x44)
-#define DRM_IOCTL_I810_GETBUF		DRM_IOWR(0x45, drm_i810_dma_t)
-#define DRM_IOCTL_I810_SWAP		DRM_IO(  0x46)
-#define DRM_IOCTL_I810_COPY		DRM_IOW( 0x47, drm_i810_copy_t)
-#define DRM_IOCTL_I810_DOCOPY		DRM_IO(  0x48)
-#define DRM_IOCTL_I810_OV0INFO		DRM_IOR( 0x49, drm_i810_overlay_t)
-#define DRM_IOCTL_I810_FSTATUS		DRM_IO ( 0x4a)
-#define DRM_IOCTL_I810_OV0FLIP		DRM_IO ( 0x4b)
-#define DRM_IOCTL_I810_MC		DRM_IOW( 0x4c, drm_i810_mc_t)
-#define DRM_IOCTL_I810_RSTATUS		DRM_IO ( 0x4d )
-
-
-/* Rage 128 specific ioctls */
-#define DRM_IOCTL_R128_INIT		DRM_IOW( 0x40, drm_r128_init_t)
-#define DRM_IOCTL_R128_CCE_START	DRM_IO(  0x41)
-#define DRM_IOCTL_R128_CCE_STOP		DRM_IOW( 0x42, drm_r128_cce_stop_t)
-#define DRM_IOCTL_R128_CCE_RESET	DRM_IO(  0x43)
-#define DRM_IOCTL_R128_CCE_IDLE		DRM_IO(  0x44)
-#define DRM_IOCTL_R128_RESET		DRM_IO(  0x46)
-#define DRM_IOCTL_R128_SWAP		DRM_IO(  0x47)
-#define DRM_IOCTL_R128_CLEAR		DRM_IOW( 0x48, drm_r128_clear_t)
-#define DRM_IOCTL_R128_VERTEX		DRM_IOW( 0x49, drm_r128_vertex_t)
-#define DRM_IOCTL_R128_INDICES		DRM_IOW( 0x4a, drm_r128_indices_t)
-#define DRM_IOCTL_R128_BLIT		DRM_IOW( 0x4b, drm_r128_blit_t)
-#define DRM_IOCTL_R128_DEPTH		DRM_IOW( 0x4c, drm_r128_depth_t)
-#define DRM_IOCTL_R128_STIPPLE		DRM_IOW( 0x4d, drm_r128_stipple_t)
-#define DRM_IOCTL_R128_INDIRECT		DRM_IOWR(0x4f, drm_r128_indirect_t)
-#define DRM_IOCTL_R128_FULLSCREEN	DRM_IOW( 0x50, drm_r128_fullscreen_t)
-
-/* Radeon specific ioctls */
-#define DRM_IOCTL_RADEON_CP_INIT	DRM_IOW( 0x40, drm_radeon_init_t)
-#define DRM_IOCTL_RADEON_CP_START	DRM_IO(  0x41)
-#define DRM_IOCTL_RADEON_CP_STOP	DRM_IOW( 0x42, drm_radeon_cp_stop_t)
-#define DRM_IOCTL_RADEON_CP_RESET	DRM_IO(  0x43)
-#define DRM_IOCTL_RADEON_CP_IDLE	DRM_IO(  0x44)
-#define DRM_IOCTL_RADEON_RESET		DRM_IO(  0x45)
-#define DRM_IOCTL_RADEON_FULLSCREEN	DRM_IOW( 0x46, drm_radeon_fullscreen_t)
-#define DRM_IOCTL_RADEON_SWAP		DRM_IO(  0x47)
-#define DRM_IOCTL_RADEON_CLEAR		DRM_IOW( 0x48, drm_radeon_clear_t)
-#define DRM_IOCTL_RADEON_VERTEX		DRM_IOW( 0x49, drm_radeon_vertex_t)
-#define DRM_IOCTL_RADEON_INDICES	DRM_IOW( 0x4a, drm_radeon_indices_t)
-#define DRM_IOCTL_RADEON_STIPPLE	DRM_IOW( 0x4c, drm_radeon_stipple_t)
-#define DRM_IOCTL_RADEON_INDIRECT	DRM_IOWR(0x4d, drm_radeon_indirect_t)
-#define DRM_IOCTL_RADEON_TEXTURE	DRM_IOWR(0x4e, drm_radeon_texture_t)
-
-/* SiS specific ioctls */
-#define SIS_IOCTL_FB_ALLOC		DRM_IOWR(0x44, drm_sis_mem_t)
-#define SIS_IOCTL_FB_FREE		DRM_IOW( 0x45, drm_sis_mem_t)
-#define SIS_IOCTL_AGP_INIT		DRM_IOWR(0x53, drm_sis_agp_t)
-#define SIS_IOCTL_AGP_ALLOC		DRM_IOWR(0x54, drm_sis_mem_t)
-#define SIS_IOCTL_AGP_FREE		DRM_IOW( 0x55, drm_sis_mem_t)
-#define SIS_IOCTL_FLIP			DRM_IOW( 0x48, drm_sis_flip_t)
-#define SIS_IOCTL_FLIP_INIT		DRM_IO(  0x49)
-#define SIS_IOCTL_FLIP_FINAL		DRM_IO(  0x50)
-
-/* I830 specific ioctls */
-#define DRM_IOCTL_I830_INIT		DRM_IOW( 0x40, drm_i830_init_t)
-#define DRM_IOCTL_I830_VERTEX		DRM_IOW( 0x41, drm_i830_vertex_t)
-#define DRM_IOCTL_I830_CLEAR		DRM_IOW( 0x42, drm_i830_clear_t)
-#define DRM_IOCTL_I830_FLUSH		DRM_IO ( 0x43)
-#define DRM_IOCTL_I830_GETAGE		DRM_IO ( 0x44)
-#define DRM_IOCTL_I830_GETBUF		DRM_IOWR(0x45, drm_i830_dma_t)
-#define DRM_IOCTL_I830_SWAP		DRM_IO ( 0x46)
-#define DRM_IOCTL_I830_COPY		DRM_IOW( 0x47, drm_i830_copy_t)
-#define DRM_IOCTL_I830_DOCOPY		DRM_IO ( 0x48)
+#define DRM_IOCTL_WAIT_VBLANK		DRM_IOWR(0x3a, drm_wait_vblank_t)
+
+/* Device specfic ioctls should only be in their respective headers
+ * The device specific ioctl range is 0x40 to 0x79.                  */
+#define DRM_COMMAND_BASE                0x40
 
 #endif
diff -ruN drivers/char/drm-4.2/drmP.h drivers/char/drm/drmP.h
--- drivers/char/drm-4.2/drmP.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drmP.h	2003-01-14 07:01:00.000000000 +0900
@@ -53,6 +53,7 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>	/* For (un)lock_kernel */
 #include <linux/mm.h>
+#include <linux/pagemap.h>
 #if defined(__alpha__) || defined(__powerpc__)
 #include <asm/pgtable.h> /* For pte_wrprotect */
 #endif
@@ -71,10 +72,7 @@
 #include <asm/pgalloc.h>
 #include "drm.h"
 
-/* page_to_bus for earlier kernels, not optimal in all cases */
-#ifndef page_to_bus
-#define page_to_bus(page)	((unsigned int)(virt_to_bus(page_address(page))))
-#endif
+#include "drm_os_linux.h"
 
 /* DRM template customization defaults
  */
@@ -106,109 +104,7 @@
 #define __REALLY_HAVE_AGP	(__HAVE_AGP && (defined(CONFIG_AGP) || \
 						defined(CONFIG_AGP_MODULE)))
 #define __REALLY_HAVE_MTRR	(__HAVE_MTRR && defined(CONFIG_MTRR))
-
-
-				/* Generic cmpxchg added in 2.3.x */
-#ifndef __HAVE_ARCH_CMPXCHG
-				/* Include this here so that driver can be
-                                   used with older kernels. */
-#if defined(__alpha__)
-static __inline__ unsigned long
-__cmpxchg_u32(volatile int *m, int old, int new)
-{
-	unsigned long prev, cmp;
-
-	__asm__ __volatile__(
-	"1:	ldl_l %0,%2\n"
-	"	cmpeq %0,%3,%1\n"
-	"	beq %1,2f\n"
-	"	mov %4,%1\n"
-	"	stl_c %1,%2\n"
-	"	beq %1,3f\n"
-	"2:	mb\n"
-	".subsection 2\n"
-	"3:	br 1b\n"
-	".previous"
-	: "=&r"(prev), "=&r"(cmp), "=m"(*m)
-	: "r"((long) old), "r"(new), "m"(*m));
-
-	return prev;
-}
-
-static __inline__ unsigned long
-__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
-{
-	unsigned long prev, cmp;
-
-	__asm__ __volatile__(
-	"1:	ldq_l %0,%2\n"
-	"	cmpeq %0,%3,%1\n"
-	"	beq %1,2f\n"
-	"	mov %4,%1\n"
-	"	stq_c %1,%2\n"
-	"	beq %1,3f\n"
-	"2:	mb\n"
-	".subsection 2\n"
-	"3:	br 1b\n"
-	".previous"
-	: "=&r"(prev), "=&r"(cmp), "=m"(*m)
-	: "r"((long) old), "r"(new), "m"(*m));
-
-	return prev;
-}
-
-static __inline__ unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-	switch (size) {
-		case 4:
-			return __cmpxchg_u32(ptr, old, new);
-		case 8:
-			return __cmpxchg_u64(ptr, old, new);
-	}
-	return old;
-}
-#define cmpxchg(ptr,o,n)						 \
-  ({									 \
-     __typeof__(*(ptr)) _o_ = (o);					 \
-     __typeof__(*(ptr)) _n_ = (n);					 \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,		 \
-				    (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-#elif __i386__
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-				      unsigned long new, int size)
-{
-	unsigned long prev;
-	switch (size) {
-	case 1:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 2:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 4:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	}
-	return old;
-}
-
-#define cmpxchg(ptr,o,n)						\
-  ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),		\
-				 (unsigned long)(n),sizeof(*(ptr))))
-#endif /* i386 & alpha */
-#endif
+#define __REALLY_HAVE_SG	(__HAVE_SG)
 
 /* Begin the DRM...
  */
@@ -251,41 +147,64 @@
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
 
-#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
+				/* Backward compatibility section */
+#ifndef minor
+#define minor(x) MINOR((x))
+#endif
 
-/* Macros to make printk easier */
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(x) 
+#endif
 
-#if ( __GNUC__ > 2 )
+#ifndef preempt_disable
+#define preempt_disable()
+#define preempt_enable()
+#endif
 
-#define DRM_ERROR(fmt, arg...) \
-	printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__, ##arg)
-#define DRM_MEM_ERROR(area, fmt, arg...) \
-	printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
-	       DRM(mem_stats)[area].name , ##arg)
-#define DRM_INFO(fmt, arg...)  printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
+#ifndef pte_offset_map 
+#define pte_offset_map pte_offset
+#define pte_unmap(pte)
+#endif
 
-#if DRM_DEBUG_CODE
-#define DRM_DEBUG(fmt, arg...)						\
-	do {								\
-		if ( DRM(flags) & DRM_FLAG_DEBUG )			\
-			printk(KERN_DEBUG				\
-			       "[" DRM_NAME ":%s] " fmt ,		\
-			       __FUNCTION__,				\
-			       ##arg);					\
-	} while (0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
+static inline struct page * vmalloc_to_page(void * vmalloc_addr)
+{
+	unsigned long addr = (unsigned long) vmalloc_addr;
+	struct page *page = NULL;
+	pgd_t *pgd = pgd_offset_k(addr);
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+  
+	if (!pgd_none(*pgd)) {
+		pmd = pmd_offset(pgd, addr);
+		if (!pmd_none(*pmd)) {
+			preempt_disable();
+			ptep = pte_offset_map(pmd, addr);
+			pte = *ptep;
+			if (pte_present(pte))
+				page = pte_page(pte);
+			pte_unmap(ptep);
+			preempt_enable();
+		}
+	}
+	return page;
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#define DRM_RPR_ARG(vma)
 #else
-#define DRM_DEBUG(fmt, arg...)		 do { } while (0)
+#define DRM_RPR_ARG(vma) vma,
 #endif
 
-#else	/* Gcc 2.x */
 
-/* Work around a C preprocessor bug */
+#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
 
 				/* Macros to make printk easier */
 #define DRM_ERROR(fmt, arg...) \
-	printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg)
+	printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
 #define DRM_MEM_ERROR(area, fmt, arg...) \
-	printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ ":%s] *ERROR* " fmt , \
+	printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
 	       DRM(mem_stats)[area].name , ##arg)
 #define DRM_INFO(fmt, arg...)  printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
 
@@ -294,16 +213,13 @@
 	do {								\
 		if ( DRM(flags) & DRM_FLAG_DEBUG )			\
 			printk(KERN_DEBUG				\
-			       "[" DRM_NAME ":" __FUNCTION__ "] " fmt ,	\
-			       ##arg);					\
+			       "[" DRM_NAME ":%s] " fmt ,	\
+			       __FUNCTION__ , ##arg);			\
 	} while (0)
 #else
 #define DRM_DEBUG(fmt, arg...)		 do { } while (0)
 #endif
 
-#endif	/* Gcc 2.x */
-
-
 #define DRM_PROC_LIMIT (PAGE_SIZE-80)
 
 #define DRM_PROC_PRINT(fmt, arg...)					\
@@ -318,6 +234,9 @@
 #define DRM_IOREMAP(map)						\
 	(map)->handle = DRM(ioremap)( (map)->offset, (map)->size )
 
+#define DRM_IOREMAP_NOCACHE(map)					\
+	(map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size)
+
 #define DRM_IOREMAPFREE(map)						\
 	do {								\
 		if ( (map)->handle && (map)->size )			\
@@ -569,7 +488,6 @@
 
 typedef struct drm_agp_head {
 	agp_kern_info      agp_info;
-	const char         *chipset;
 	drm_agp_mem_t      *memory;
 	unsigned long      mode;
 	int                enabled;
@@ -599,6 +517,17 @@
 	drm_map_t		*map;
 } drm_map_list_t;
 
+#if __HAVE_VBL_IRQ
+
+typedef struct drm_vbl_sig {
+	struct list_head	head;
+	unsigned int		sequence;
+	struct siginfo		info;
+	struct task_struct	*task;
+} drm_vbl_sig_t;
+
+#endif
+
 typedef struct drm_device {
 	const char	  *name;	/* Simple driver name		   */
 	char		  *unique;	/* Unique identifier: e.g., busid  */
@@ -658,6 +587,12 @@
 	int		  last_context;	/* Last current context		   */
 	unsigned long	  last_switch;	/* jiffies at last context switch  */
 	struct tq_struct  tq;
+#if __HAVE_VBL_IRQ
+   	wait_queue_head_t vbl_queue;
+   	atomic_t          vbl_received;
+	spinlock_t        vbl_lock;
+	drm_vbl_sig_t     vbl_sigs;
+#endif
 	cycles_t	  ctx_start;
 	cycles_t	  lck_start;
 #if __HAVE_DMA_HISTOGRAM
@@ -679,8 +614,12 @@
 #endif
 	struct pci_dev *pdev;
 #ifdef __alpha__
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
+	struct pci_controler *hose;
+#else
 	struct pci_controller *hose;
 #endif
+#endif
 	drm_sg_mem_t      *sg;  /* Scatter gather memory */
 	unsigned long     *ctx_bitmap;
 	void		  *dev_private;
@@ -725,16 +664,16 @@
 				/* Mapping support (drm_vm.h) */
 extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
 				   unsigned long address,
-				   int unused);
+				   int write_access);
 extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
 				       unsigned long address,
-				       int unused);
+				       int write_access);
 extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
 				       unsigned long address,
-				       int unused);
+				       int write_access);
 extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
 				      unsigned long address,
-				      int unused);
+				      int write_access);
 extern void	     DRM(vm_open)(struct vm_area_struct *vma);
 extern void	     DRM(vm_close)(struct vm_area_struct *vma);
 extern void	     DRM(vm_shm_close)(struct vm_area_struct *vma);
@@ -756,6 +695,7 @@
 extern void	     DRM(free_pages)(unsigned long address, int order,
 				     int area);
 extern void	     *DRM(ioremap)(unsigned long offset, unsigned long size);
+extern void	     *DRM(ioremap_nocache)(unsigned long offset, unsigned long size);
 extern void	     DRM(ioremapfree)(void *pt, unsigned long size);
 
 #if __REALLY_HAVE_AGP
@@ -885,6 +825,15 @@
 extern int           DRM(irq_uninstall)( drm_device_t *dev );
 extern void          DRM(dma_service)( int irq, void *device,
 				       struct pt_regs *regs );
+extern void          DRM(driver_irq_preinstall)( drm_device_t *dev );
+extern void          DRM(driver_irq_postinstall)( drm_device_t *dev );
+extern void          DRM(driver_irq_uninstall)( drm_device_t *dev );
+#if __HAVE_VBL_IRQ
+extern int           DRM(wait_vblank)(struct inode *inode, struct file *filp,
+				      unsigned int cmd, unsigned long arg);
+extern int           DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
+extern void          DRM(vbl_send_signals)( drm_device_t *dev );
+#endif
 #if __HAVE_DMA_IRQ_BH
 extern void          DRM(dma_immediate_bh)( void *dev );
 #endif
diff -ruN drivers/char/drm-4.2/drm_agpsupport.h drivers/char/drm/drm_agpsupport.h
--- drivers/char/drm-4.2/drm_agpsupport.h	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/drm_agpsupport.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,6 +29,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 #include <linux/module.h>
 
@@ -259,63 +260,17 @@
 			return NULL;
 		}
 		head->memory = NULL;
-		switch (head->agp_info.chipset) {
-		case INTEL_GENERIC:	head->chipset = "Intel";         break;
-		case INTEL_LX:		head->chipset = "Intel 440LX";   break;
-		case INTEL_BX:		head->chipset = "Intel 440BX";   break;
-		case INTEL_GX:		head->chipset = "Intel 440GX";   break;
-		case INTEL_I810:	head->chipset = "Intel i810";    break;
-		case INTEL_I815:	head->chipset = "Intel i815";	 break;
-	 	case INTEL_I820:	head->chipset = "Intel i820";	 break;
-		case INTEL_I840:	head->chipset = "Intel i840";    break;
-		case INTEL_I845:	head->chipset = "Intel i845";    break;
-		case INTEL_I850:	head->chipset = "Intel i850";	 break;
-
-		case VIA_GENERIC:	head->chipset = "VIA";           break;
-		case VIA_VP3:		head->chipset = "VIA VP3";       break;
-		case VIA_MVP3:		head->chipset = "VIA MVP3";      break;
-		case VIA_MVP4:		head->chipset = "VIA MVP4";      break;
-		case VIA_APOLLO_KX133:	head->chipset = "VIA Apollo KX133";
-			break;
-		case VIA_APOLLO_KT133:	head->chipset = "VIA Apollo KT133";
-			break;
-		case VIA_APOLLO_PRO: 	head->chipset = "VIA Apollo Pro";
-			break;
-
-		case SIS_GENERIC:	head->chipset = "SiS";           break;
-		case AMD_GENERIC:	head->chipset = "AMD";           break;
-		case AMD_IRONGATE:	head->chipset = "AMD Irongate";  break;
-		case AMD_8151:		head->chipset = "AMD 8151";      break;
-		case ALI_GENERIC:	head->chipset = "ALi";           break;
-		case ALI_M1541: 	head->chipset = "ALi M1541";     break;
-
-		case ALI_M1621: 	head->chipset = "ALi M1621";	 break;
-		case ALI_M1631: 	head->chipset = "ALi M1631";	 break;
-		case ALI_M1632: 	head->chipset = "ALi M1632";	 break;
-		case ALI_M1641: 	head->chipset = "ALi M1641";	 break;
-		case ALI_M1644: 	head->chipset = "ALi M1644";	 break;
-		case ALI_M1647: 	head->chipset = "ALi M1647";	 break;
-		case ALI_M1651: 	head->chipset = "ALi M1651";	 break;
-
-		case SVWRKS_HE: 	head->chipset = "Serverworks HE";
-			break;
-		case SVWRKS_LE: 	head->chipset = "Serverworks LE";
-			break;
-		case SVWRKS_GENERIC: 	head->chipset = "Serverworks Generic";
-			break;
-
-		case HP_ZX1:		head->chipset = "HP ZX1";	 break;
-
-		default:		head->chipset = "Unknown";       break;
-		}
-
+#if LINUX_VERSION_CODE <= 0x020408
+		head->cant_use_aperture = 0;
+		head->page_mask = ~(0xfff);
+#else
 		head->cant_use_aperture = head->agp_info.cant_use_aperture;
 		head->page_mask = head->agp_info.page_mask;
+#endif
 
-		DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMB\n",
+		DRM_INFO("AGP %d.%d aperture @ 0x%08lx %ZuMB\n",
 			 head->agp_info.version.major,
 			 head->agp_info.version.minor,
-			 head->chipset,
 			 head->agp_info.aper_base,
 			 head->agp_info.aper_size);
 	}
diff -ruN drivers/char/drm-4.2/drm_auth.h drivers/char/drm/drm_auth.h
--- drivers/char/drm-4.2/drm_auth.h	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/drm_auth.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,6 +29,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 static int DRM(hash_magic)(drm_magic_t magic)
diff -ruN drivers/char/drm-4.2/drm_bufs.h drivers/char/drm/drm_bufs.h
--- drivers/char/drm-4.2/drm_bufs.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_bufs.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,6 +29,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include <linux/vmalloc.h>
 #include "drmP.h"
 
@@ -136,6 +137,7 @@
 		}
 		map->offset = (unsigned long)map->handle;
 		if ( map->flags & _DRM_CONTAINS_LOCK ) {
+			dev->sigdata.lock =
 			dev->lock.hw_lock = map->handle; /* Pointer to lock */
 		}
 		break;
@@ -1058,18 +1060,34 @@
 				goto done;
 			}
 
+#if LINUX_VERSION_CODE <= 0x020402
+			down( &current->mm->mmap_sem );
+#else
 			down_write( &current->mm->mmap_sem );
+#endif
 			virtual = do_mmap( filp, 0, map->size,
 					   PROT_READ | PROT_WRITE,
 					   MAP_SHARED,
 					   (unsigned long)map->offset );
+#if LINUX_VERSION_CODE <= 0x020402
+			up( &current->mm->mmap_sem );
+#else
 			up_write( &current->mm->mmap_sem );
+#endif
 		} else {
+#if LINUX_VERSION_CODE <= 0x020402
+			down( &current->mm->mmap_sem );
+#else
 			down_write( &current->mm->mmap_sem );
+#endif
 			virtual = do_mmap( filp, 0, dma->byte_count,
 					   PROT_READ | PROT_WRITE,
 					   MAP_SHARED, 0 );
+#if LINUX_VERSION_CODE <= 0x020402
+			up( &current->mm->mmap_sem );
+#else
 			up_write( &current->mm->mmap_sem );
+#endif
 		}
 		if ( virtual > -1024UL ) {
 			/* Real error */
diff -ruN drivers/char/drm-4.2/drm_context.h drivers/char/drm/drm_context.h
--- drivers/char/drm-4.2/drm_context.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_context.h	2003-01-14 07:01:00.000000000 +0900
@@ -33,6 +33,7 @@
  *		needed by SiS driver's memory management.
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 #if __HAVE_CTX_BITMAP
@@ -554,7 +555,7 @@
 				/* Allocate a new queue */
 	down(&dev->struct_sem);
 
-	queue = gamma_alloc(sizeof(*queue), DRM_MEM_QUEUES);
+	queue = DRM(alloc)(sizeof(*queue), DRM_MEM_QUEUES);
 	memset(queue, 0, sizeof(*queue));
 	atomic_set(&queue->use_count, 1);
 
diff -ruN drivers/char/drm-4.2/drm_dma.h drivers/char/drm/drm_dma.h
--- drivers/char/drm-4.2/drm_dma.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_dma.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,6 +29,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 #include <linux/interrupt.h>	/* For task queue support */
@@ -537,8 +538,16 @@
 	dev->tq.data = dev;
 #endif
 
+#if __HAVE_VBL_IRQ
+	init_waitqueue_head(&dev->vbl_queue);
+
+	spin_lock_init( &dev->vbl_lock );
+
+	INIT_LIST_HEAD( &dev->vbl_sigs.head );
+#endif
+
 				/* Before installing handler */
-	DRIVER_PREINSTALL();
+	DRM(driver_irq_preinstall)(dev);
 
 				/* Install handler */
 	ret = request_irq( dev->irq, DRM(dma_service),
@@ -551,7 +560,7 @@
 	}
 
 				/* After installing handler */
-	DRIVER_POSTINSTALL();
+	DRM(driver_irq_postinstall)(dev);
 
 	return 0;
 }
@@ -570,7 +579,7 @@
 
 	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
 
-	DRIVER_UNINSTALL();
+	DRM(driver_irq_uninstall)( dev );
 
 	free_irq( irq, dev );
 
@@ -597,6 +606,117 @@
 	}
 }
 
+#if __HAVE_VBL_IRQ
+
+int DRM(wait_vblank)( DRM_IOCTL_ARGS )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_wait_vblank_t vblwait;
+	struct timeval now;
+	int ret = 0;
+	unsigned int flags;
+
+	if (!dev->irq)
+		return -EINVAL;
+
+	DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
+				  sizeof(vblwait) );
+
+	switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
+	case _DRM_VBLANK_RELATIVE:
+		vblwait.request.sequence += atomic_read( &dev->vbl_received );
+	case _DRM_VBLANK_ABSOLUTE:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+	
+	if ( flags & _DRM_VBLANK_SIGNAL ) {
+		unsigned long irqflags;
+		drm_vbl_sig_t *vbl_sig = DRM_MALLOC( sizeof( drm_vbl_sig_t ) );
+
+		if ( !vbl_sig )
+			return -ENOMEM;
+
+		memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
+
+		vbl_sig->sequence = vblwait.request.sequence;
+		vbl_sig->info.si_signo = vblwait.request.signal;
+		vbl_sig->task = current;
+
+		vblwait.reply.sequence = atomic_read( &dev->vbl_received );
+
+		/* Hook signal entry into list */
+		spin_lock_irqsave( &dev->vbl_lock, irqflags );
+
+		list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
+
+		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+	} else {
+		ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
+
+		do_gettimeofday( &now );
+		vblwait.reply.tval_sec = now.tv_sec;
+		vblwait.reply.tval_usec = now.tv_usec;
+	}
+
+	DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
+				sizeof(vblwait) );
+
+	return ret;
+}
+
+void DRM(vbl_send_signals)( drm_device_t *dev )
+{
+	struct list_head *entry, *tmp;
+	drm_vbl_sig_t *vbl_sig;
+	unsigned int vbl_seq = atomic_read( &dev->vbl_received );
+	unsigned long flags;
+
+	spin_lock_irqsave( &dev->vbl_lock, flags );
+
+	list_for_each_safe( entry, tmp, &dev->vbl_sigs.head ) {
+
+		vbl_sig = (drm_vbl_sig_t *) entry;
+
+		if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
+
+			vbl_sig->info.si_code = atomic_read( &dev->vbl_received );
+			send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
+
+			list_del( entry );
+
+			DRM_FREE( entry );
+		}
+	}
+
+	spin_unlock_irqrestore( &dev->vbl_lock, flags );
+}
+
+#endif	/* __HAVE_VBL_IRQ */
+
+#else
+
+int DRM(control)( struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg )
+{
+	drm_control_t ctl;
+
+	if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
+		return -EFAULT;
+
+	switch ( ctl.func ) {
+	case DRM_INST_HANDLER:
+	case DRM_UNINST_HANDLER:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 #endif /* __HAVE_DMA_IRQ */
 
 #endif /* __HAVE_DMA */
diff -ruN drivers/char/drm-4.2/drm_drawable.h drivers/char/drm/drm_drawable.h
--- drivers/char/drm-4.2/drm_drawable.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_drawable.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,6 +29,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 int DRM(adddraw)(struct inode *inode, struct file *filp,
diff -ruN drivers/char/drm-4.2/drm_drv.h drivers/char/drm/drm_drv.h
--- drivers/char/drm-4.2/drm_drv.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_drv.h	2003-01-14 07:01:00.000000000 +0900
@@ -115,18 +115,34 @@
 #ifndef DRIVER_FOPS
 #define DRIVER_FOPS				\
 static struct file_operations	DRM(fops) = {	\
-	owner:   THIS_MODULE,			\
-	open:	 DRM(open),			\
-	flush:	 DRM(flush),			\
-	release: DRM(release),			\
-	ioctl:	 DRM(ioctl),			\
-	mmap:	 DRM(mmap),			\
-	read:	 DRM(read),			\
-	fasync:	 DRM(fasync),			\
-	poll:	 DRM(poll),			\
+	.owner   = THIS_MODULE,			\
+	.open	 = DRM(open),			\
+	.flush	 = DRM(flush),			\
+	.release = DRM(release),		\
+	.ioctl	 = DRM(ioctl),			\
+	.mmap	 = DRM(mmap),			\
+	.read	 = DRM(read),			\
+	.fasync  = DRM(fasync),			\
+	.poll	 = DRM(poll),			\
 }
 #endif
 
+#ifndef MODULE
+/* DRM(options) is called by the kernel to parse command-line options
+ * passed via the boot-loader (e.g., LILO).  It calls the insmod option
+ * routine, drm_parse_drm.
+ */
+/* Use an additional macro to avoid preprocessor troubles */
+#define DRM_OPTIONS_FUNC DRM(options)
+static int __init DRM(options)( char *str )
+{
+	DRM(parse_options)( str );
+	return 1;
+}
+
+__setup( DRIVER_NAME "=", DRM_OPTIONS_FUNC );
+#undef DRM_OPTIONS_FUNC
+#endif
 
 /*
  * The default number of instances (minor numbers) to initialize.
@@ -187,10 +203,8 @@
 
 	/* The DRM_IOCTL_DMA ioctl should be defined by the driver.
 	 */
-#if __HAVE_DMA_IRQ
 	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { DRM(control),     1, 1 },
 #endif
-#endif
 
 #if __REALLY_HAVE_AGP
 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { DRM(agp_acquire), 1, 1 },
@@ -208,6 +222,10 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free),     1, 1 },
 #endif
 
+#if __HAVE_VBL_IRQ
+	[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)]   = { DRM(wait_vblank), 0, 0 },
+#endif
+
 	DRIVER_IOCTLS
 };
 
@@ -292,7 +310,7 @@
 	dev->map_count = 0;
 
 	dev->vmalist = NULL;
-	dev->lock.hw_lock = NULL;
+	dev->sigdata.lock = dev->lock.hw_lock = NULL;
 	init_waitqueue_head( &dev->lock.lock_queue );
 	dev->queue_count = 0;
 	dev->queue_reserved = 0;
@@ -477,7 +495,7 @@
 	DRM(dma_takedown)( dev );
 #endif
 	if ( dev->lock.hw_lock ) {
-		dev->lock.hw_lock = NULL; /* SHM removed */
+		dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
 		dev->lock.pid = 0;
 		wake_up_interruptible( &dev->lock.lock_queue );
 	}
@@ -705,7 +723,7 @@
 	int i;
 
 	for (i = 0; i < DRM(numdevs); i++) {
-		if (MINOR(inode->i_rdev) == DRM(minor)[i]) {
+		if (minor(inode->i_rdev) == DRM(minor)[i]) {
 			dev = &(DRM(device)[i]);
 			break;
 		}
@@ -747,8 +765,8 @@
 	 * Begin inline drm_release
 	 */
 
-	DRM_DEBUG( "pid = %d, device = 0x%x, open_count = %d\n",
-		   current->pid, dev->device, dev->open_count );
+	DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
+		   current->pid, (long)dev->device, dev->open_count );
 
 	if ( dev->lock.hw_lock &&
 	     _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
@@ -873,8 +891,9 @@
 	atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
 	++priv->ioctl_count;
 
-	DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%x, auth=%d\n",
-		   current->pid, cmd, nr, dev->device, priv->authenticated );
+	DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
+		   current->pid, cmd, nr, (long)dev->device, 
+		   priv->authenticated );
 
 	if ( nr >= DRIVER_IOCTL_COUNT ) {
 		retcode = -EINVAL;
@@ -1027,6 +1046,25 @@
 
 	atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
 
+#if __HAVE_KERNEL_CTX_SWITCH
+	/* We no longer really hold it, but if we are the next
+	 * agent to request it then we should just be able to
+	 * take it immediately and not eat the ioctl.
+	 */
+	dev->lock.pid = 0;
+	{
+		__volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
+		unsigned int old, new, prev, ctx;
+
+		ctx = lock.context;
+		do {
+			old  = *plock;
+			new  = ctx;
+			prev = cmpxchg(plock, old, new);
+		} while (prev != old);
+	}
+	wake_up_interruptible(&dev->lock.lock_queue);
+#else
 	DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
 			    DRM_KERNEL_CONTEXT );
 #if __HAVE_DMA_SCHEDULE
@@ -1041,6 +1079,7 @@
 			DRM_ERROR( "\n" );
 		}
 	}
+#endif /* !__HAVE_KERNEL_CTX_SWITCH */
 
 	unblock_all_signals();
 	return 0;
diff -ruN drivers/char/drm-4.2/drm_fops.h drivers/char/drm/drm_fops.h
--- drivers/char/drm-4.2/drm_fops.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_fops.h	2003-01-14 07:01:00.000000000 +0900
@@ -30,6 +30,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 #include <linux/poll.h>
 
@@ -37,7 +38,7 @@
 
 int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
 {
-	kdev_t	     minor = MINOR(inode->i_rdev);
+	int	     minor = minor(inode->i_rdev);
 	drm_file_t   *priv;
 
 	if (filp->f_flags & O_EXCL)   return -EBUSY; /* No exclusive opens */
@@ -94,25 +95,8 @@
 	drm_file_t    *priv   = filp->private_data;
 	drm_device_t  *dev    = priv->dev;
 
-	DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
-		  current->pid, dev->device, dev->open_count);
-	if ( dev->lock.hw_lock &&
-	     _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
-	     dev->lock.pid == current->pid ) {
-		DRM_DEBUG( "Process %d closed fd, freeing lock for context %d\n",
-			   current->pid,
-			   _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
-#if __HAVE_RELEASE
-		DRIVER_RELEASE();
-#endif
-		DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
-				_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
-
-				/* FIXME: may require heavy-handed reset of
-                                   hardware at this point, possibly
-                                   processed via a callback to the X
-                                   server. */
-	}
+	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+		  current->pid, (long)dev->device, dev->open_count);
 	return 0;
 }
 
@@ -122,7 +106,7 @@
 	drm_device_t  *dev    = priv->dev;
 	int	      retcode;
 
-	DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device);
+	DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)dev->device);
 	retcode = fasync_helper(fd, filp, on, &dev->buf_async);
 	if (retcode < 0) return retcode;
 	return 0;
@@ -141,31 +125,21 @@
 	int	      avail;
 	int	      send;
 	int	      cur;
-	DECLARE_WAITQUEUE(wait, current);
 
 	DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
 
-	add_wait_queue(&dev->buf_readers, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
 	while (dev->buf_rp == dev->buf_wp) {
 		DRM_DEBUG("  sleeping\n");
 		if (filp->f_flags & O_NONBLOCK) {
-			remove_wait_queue(&dev->buf_readers, &wait);
-			set_current_state(TASK_RUNNING);
 			return -EAGAIN;
 		}
-		schedule(); /* wait for dev->buf_readers */
+		interruptible_sleep_on(&dev->buf_readers);
 		if (signal_pending(current)) {
 			DRM_DEBUG("  interrupted\n");
-			remove_wait_queue(&dev->buf_readers, &wait);
-			set_current_state(TASK_RUNNING);
 			return -ERESTARTSYS;
 		}
 		DRM_DEBUG("  awake\n");
-		set_current_state(TASK_INTERRUPTIBLE);
 	}
-	remove_wait_queue(&dev->buf_readers, &wait);
-	set_current_state(TASK_RUNNING);
 
 	left  = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
 	avail = DRM_BSZ - left;
diff -ruN drivers/char/drm-4.2/drm_init.h drivers/char/drm/drm_init.h
--- drivers/char/drm-4.2/drm_init.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_init.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,6 +29,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 #if 0
diff -ruN drivers/char/drm-4.2/drm_ioctl.h drivers/char/drm/drm_ioctl.h
--- drivers/char/drm-4.2/drm_ioctl.h	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/drm_ioctl.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,8 +29,10 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
+
 int DRM(irq_busid)(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg)
 {
@@ -111,7 +113,7 @@
 
 	do {
 		struct pci_dev *pci_dev;
-                int b, d, f;
+                int domain, b, d, f;
                 char *p;
  
                 for(p = dev->unique; p && *p && *p != ':'; p++);
@@ -123,6 +125,27 @@
                 f = (int)simple_strtoul(p+1, &p, 10);
                 if (*p) break;
  
+		domain = b >> 8;
+		b &= 0xff;
+
+#ifdef __alpha__
+		/*
+		 * Find the hose the device is on (the domain number is the
+		 * hose index) and offset the bus by the root bus of that
+		 * hose.
+		 */
+                for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
+                    pci_dev;
+                    pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) {
+			struct pci_controller *hose = pci_dev->sysdata;
+			
+			if (hose->index == domain) {
+				b += hose->bus->number;
+				break;
+			}
+		}
+#endif
+
                 pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
                 if (pci_dev) {
 			dev->pdev = pci_dev;
diff -ruN drivers/char/drm-4.2/drm_lists.h drivers/char/drm/drm_lists.h
--- drivers/char/drm-4.2/drm_lists.h	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/drm_lists.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,6 +29,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 #if __HAVE_DMA_WAITLIST
diff -ruN drivers/char/drm-4.2/drm_lock.h drivers/char/drm/drm_lock.h
--- drivers/char/drm-4.2/drm_lock.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_lock.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,6 +29,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 int DRM(block)(struct inode *inode, struct file *filp, unsigned int cmd,
@@ -236,7 +237,7 @@
 
 
 				/* Allow signal delivery if lock isn't held */
-	if (!_DRM_LOCK_IS_HELD(s->lock->lock)
+	if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
 	    || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
 
 				/* Otherwise, set flag to force call to
diff -ruN drivers/char/drm-4.2/drm_memory.h drivers/char/drm/drm_memory.h
--- drivers/char/drm-4.2/drm_memory.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_memory.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,6 +29,7 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include <linux/config.h>
 #include "drmP.h"
 #include <linux/wrapper.h>
@@ -313,6 +314,29 @@
 	return pt;
 }
 
+void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size)
+{
+	void *pt;
+
+	if (!size) {
+		DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+			      "Mapping 0 bytes at 0x%08lx\n", offset);
+		return NULL;
+	}
+
+	if (!(pt = ioremap_nocache(offset, size))) {
+		spin_lock(&DRM(mem_lock));
+		++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
+		spin_unlock(&DRM(mem_lock));
+		return NULL;
+	}
+	spin_lock(&DRM(mem_lock));
+	++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
+	DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
+	spin_unlock(&DRM(mem_lock));
+	return pt;
+}
+
 void DRM(ioremapfree)(void *pt, unsigned long size)
 {
 	int alloc_count;
diff -ruN drivers/char/drm-4.2/drm_os_linux.h drivers/char/drm/drm_os_linux.h
--- drivers/char/drm-4.2/drm_os_linux.h	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/drm_os_linux.h	2003-01-14 07:01:00.000000000 +0900
@@ -0,0 +1,90 @@
+#define __NO_VERSION__
+
+#include <linux/interrupt.h>	/* For task queue support */
+#include <linux/delay.h>
+
+#define DRM_IOCTL_ARGS			struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data
+#define DRM_ERR(d)			-(d)
+#define DRM_CURRENTPID			current->pid
+#define DRM_UDELAY(d)			udelay(d)
+#define DRM_READ8(addr)			readb(addr)
+#define DRM_READ32(addr)		readl(addr)
+#define DRM_WRITE8(addr, val)		writeb(val, addr)
+#define DRM_WRITE32(addr, val)		writel(val, addr)
+#define DRM_READMEMORYBARRIER()		mb()
+#define DRM_WRITEMEMORYBARRIER()	wmb()
+#define DRM_DEVICE	drm_file_t	*priv	= filp->private_data; \
+			drm_device_t	*dev	= priv->dev
+
+#define DRM_IRQ_ARGS	        int irq, void *arg, struct pt_regs *regs
+#define DRM_TASKQUEUE_ARGS	void *arg
+
+/* For data going from/to the kernel through the ioctl argument */
+#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3)	\
+	if ( copy_from_user(&arg1, arg2, arg3) )	\
+		return -EFAULT
+#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3)	\
+	if ( copy_to_user(arg1, &arg2, arg3) )		\
+		return -EFAULT
+/* Other copying of data from/to kernel space */
+#define DRM_COPY_FROM_USER(arg1, arg2, arg3)		\
+	copy_from_user(arg1, arg2, arg3)
+#define DRM_COPY_TO_USER(arg1, arg2, arg3)		\
+	copy_to_user(arg1, arg2, arg3)
+/* Macros for copyfrom user, but checking readability only once */
+#define DRM_VERIFYAREA_READ( uaddr, size ) 		\
+	verify_area( VERIFY_READ, uaddr, size )
+#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) 	\
+	__copy_from_user(arg1, arg2, arg3)
+#define DRM_GET_USER_UNCHECKED(val, uaddr)		\
+	__get_user(val, uaddr)
+
+
+/* malloc/free without the overhead of DRM(alloc) */
+#define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL)
+#define DRM_FREE(x) kfree(x)
+
+#define DRM_GETSAREA()							 \
+do { 									 \
+	struct list_head *list;						 \
+	list_for_each( list, &dev->maplist->head ) {			 \
+		drm_map_list_t *entry = (drm_map_list_t *)list;		 \
+		if ( entry->map &&					 \
+		     entry->map->type == _DRM_SHM &&			 \
+		     (entry->map->flags & _DRM_CONTAINS_LOCK) ) {	 \
+			dev_priv->sarea = entry->map;			 \
+ 			break;						 \
+ 		}							 \
+ 	}								 \
+} while (0)
+
+#define DRM_HZ HZ
+
+#define DRM_WAIT_ON( ret, queue, timeout, condition )	\
+do {							\
+	DECLARE_WAITQUEUE(entry, current);		\
+	unsigned long end = jiffies + (timeout);	\
+	add_wait_queue(&(queue), &entry);		\
+							\
+	for (;;) {					\
+		current->state = TASK_INTERRUPTIBLE;	\
+		if (condition) 				\
+			break;				\
+		if((signed)(end - jiffies) <= 0) {	\
+			ret = -EBUSY;			\
+			break;				\
+		}					\
+		schedule_timeout((HZ/100 > 1) ? HZ/100 : 1);	\
+		if (signal_pending(current)) {		\
+			ret = -EINTR;			\
+			break;				\
+		}					\
+	}						\
+	current->state = TASK_RUNNING;			\
+	remove_wait_queue(&(queue), &entry);		\
+} while (0)
+
+
+#define DRM_WAKEUP( queue ) wake_up_interruptible( queue )
+#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
+ 
diff -ruN drivers/char/drm-4.2/drm_proc.h drivers/char/drm/drm_proc.h
--- drivers/char/drm-4.2/drm_proc.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_proc.h	2003-01-14 07:01:00.000000000 +0900
@@ -33,6 +33,7 @@
  *    the problem with the proc files not outputting all their information.
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 static int	   DRM(name_info)(char *buf, char **start, off_t offset,
@@ -147,10 +148,10 @@
 	*eof   = 0;
 
 	if (dev->unique) {
-		DRM_PROC_PRINT("%s 0x%x %s\n",
-			       dev->name, dev->device, dev->unique);
+		DRM_PROC_PRINT("%s 0x%lx %s\n",
+			       dev->name, (long)dev->device, dev->unique);
 	} else {
-		DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device);
+		DRM_PROC_PRINT("%s 0x%lx\n", dev->name, (long)dev->device);
 	}
 
 	if (len > request + offset) return request;
@@ -448,7 +449,8 @@
 		for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
 			pgd = pgd_offset(vma->vm_mm, i);
 			pmd = pmd_offset(pgd, i);
-			pte = pte_offset(pmd, i);
+			preempt_disable();
+			pte = pte_offset_map(pmd, i);
 			if (pte_present(*pte)) {
 				address = __pa(pte_page(*pte))
 					+ (i & (PAGE_SIZE-1));
@@ -464,6 +466,8 @@
 			} else {
 				DRM_PROC_PRINT("      0x%08lx\n", i);
 			}
+			pte_unmap(pte);
+			preempt_enable();
 		}
 #endif
 	}
diff -ruN drivers/char/drm-4.2/drm_sarea.h drivers/char/drm/drm_sarea.h
--- drivers/char/drm-4.2/drm_sarea.h	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/drm_sarea.h	2003-01-14 07:01:00.000000000 +0900
@@ -0,0 +1,57 @@
+/* sarea.h -- SAREA definitions -*- linux-c -*-
+ *
+ * Copyright 2002 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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  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.
+ *
+ * Authors:
+ *    Michel Dänzer <michel@daenzer.net>
+ */
+
+#ifndef _DRM_SAREA_H_
+#define _DRM_SAREA_H_
+
+#define SAREA_MAX_DRAWABLES 		256
+
+typedef struct _drm_sarea_drawable_t {
+    unsigned int	stamp;
+    unsigned int	flags;
+} drm_sarea_drawable_t;
+
+typedef struct _dri_sarea_frame_t {
+    unsigned int        x;
+    unsigned int        y;
+    unsigned int        width;
+    unsigned int        height;
+    unsigned int        fullscreen;
+} drm_sarea_frame_t;
+
+typedef struct _drm_sarea_t {
+    /* first thing is always the drm locking structure */
+    drm_hw_lock_t		lock;
+		/* NOT_DONE: Use readers/writer lock for drawable_lock */
+    drm_hw_lock_t		drawable_lock;
+    drm_sarea_drawable_t	drawableTable[SAREA_MAX_DRAWABLES];
+    drm_sarea_frame_t		frame;
+    drm_context_t		dummy_context;
+} drm_sarea_t;
+
+#endif	/* _DRM_SAREA_H_ */
diff -ruN drivers/char/drm-4.2/drm_scatter.h drivers/char/drm/drm_scatter.h
--- drivers/char/drm-4.2/drm_scatter.h	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/drm_scatter.h	2003-01-14 07:01:00.000000000 +0900
@@ -27,6 +27,7 @@
  *   Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/vmalloc.h>
 #include "drmP.h"
diff -ruN drivers/char/drm-4.2/drm_stub.h drivers/char/drm/drm_stub.h
--- drivers/char/drm-4.2/drm_stub.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/drm_stub.h	2003-01-14 07:01:00.000000000 +0900
@@ -28,6 +28,7 @@
  *
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 #define DRM_STUB_MAXCARDS 16	/* Enough for one machine */
@@ -48,7 +49,7 @@
 
 static int DRM(stub_open)(struct inode *inode, struct file *filp)
 {
-	int                    minor = MINOR(inode->i_rdev);
+	int                    minor = minor(inode->i_rdev);
 	int                    err   = -ENODEV;
 	struct file_operations *old_fops;
 
@@ -65,8 +66,8 @@
 }
 
 static struct file_operations DRM(stub_fops) = {
-	owner:   THIS_MODULE,
-	open:	 DRM(stub_open)
+	.owner = THIS_MODULE,
+	.open  = DRM(stub_open)
 };
 
 static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
diff -ruN drivers/char/drm-4.2/drm_vm.h drivers/char/drm/drm_vm.h
--- drivers/char/drm-4.2/drm_vm.h	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/drm_vm.h	2003-01-14 07:01:00.000000000 +0900
@@ -29,35 +29,36 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "drmP.h"
 
 struct vm_operations_struct   DRM(vm_ops) = {
-	nopage:	 DRM(vm_nopage),
-	open:	 DRM(vm_open),
-	close:	 DRM(vm_close),
+	.nopage = DRM(vm_nopage),
+	.open	= DRM(vm_open),
+	.close	= DRM(vm_close),
 };
 
 struct vm_operations_struct   DRM(vm_shm_ops) = {
-	nopage:	 DRM(vm_shm_nopage),
-	open:	 DRM(vm_open),
-	close:	 DRM(vm_shm_close),
+	.nopage = DRM(vm_shm_nopage),
+	.open	= DRM(vm_open),
+	.close	= DRM(vm_shm_close),
 };
 
 struct vm_operations_struct   DRM(vm_dma_ops) = {
-	nopage:	 DRM(vm_dma_nopage),
-	open:	 DRM(vm_open),
-	close:	 DRM(vm_close),
+	.nopage = DRM(vm_dma_nopage),
+	.open	= DRM(vm_open),
+	.close	= DRM(vm_close),
 };
 
 struct vm_operations_struct   DRM(vm_sg_ops) = {
-	nopage:  DRM(vm_sg_nopage),
-	open:    DRM(vm_open),
-	close:   DRM(vm_close),
+	.nopage = DRM(vm_sg_nopage),
+	.open   = DRM(vm_open),
+	.close  = DRM(vm_close),
 };
 
 struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
 			    unsigned long address,
-			    int unused)
+			    int write_access)
 {
 #if __REALLY_HAVE_AGP
 	drm_file_t *priv  = vma->vm_file->private_data;
@@ -70,7 +71,7 @@
          * Find the right map
          */
 
-	if(!dev->agp->cant_use_aperture) goto vm_nopage_error;
+	if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error;
 
 	list_for_each(list, &dev->maplist->head) {
 		r_list = (drm_map_list_t *)list;
@@ -141,9 +142,7 @@
 		return NOPAGE_OOM;
 	get_page(page);
 
-#if 0	/* XXX page_to_bus is not a portable interface available on all platforms. */
-	DRM_DEBUG("0x%08lx => 0x%08llx\n", address, (u64)page_to_bus(page));
-#endif
+	DRM_DEBUG("shm_nopage 0x%lx\n", address);
 	return page;
 }
 
@@ -245,10 +244,7 @@
 
 	get_page(page);
 
-#if 0	/* XXX page_to_bus is not a portable interface available on all platforms. */
-	DRM_DEBUG("0x%08lx (page %lu) => 0x%08llx\n", address, page_nr, 
-		  (u64)page_to_bus(page));
-#endif
+	DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr);
 	return page;
 }
 
@@ -346,7 +342,13 @@
 	unlock_kernel();
 
 	vma->vm_ops   = &DRM(vm_dma_ops);
+
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
+	vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+#else
 	vma->vm_flags |= VM_RESERVED; /* Don't swap */
+#endif
+
 	vma->vm_file  =	 filp;	/* Needed for drm_vm_open() */
 	DRM(vm_open)(vma);
 	return 0;
@@ -449,12 +451,12 @@
 		}
 		offset = DRIVER_GET_REG_OFS();
 #ifdef __sparc__
-		if (io_remap_page_range(vma->vm_start,
+		if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
 					VM_OFFSET(vma) + offset,
 					vma->vm_end - vma->vm_start,
 					vma->vm_page_prot, 0))
 #else
-		if (remap_page_range(vma->vm_start,
+		if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
 				     VM_OFFSET(vma) + offset,
 				     vma->vm_end - vma->vm_start,
 				     vma->vm_page_prot))
@@ -471,15 +473,29 @@
 		vma->vm_private_data = (void *)map;
 				/* Don't let this area swap.  Change when
 				   DRM_KERNEL advisory is supported. */
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
+		vma->vm_flags |= VM_LOCKED;
+#else
+		vma->vm_flags |= VM_RESERVED;
+#endif
 		break;
 	case _DRM_SCATTER_GATHER:
 		vma->vm_ops = &DRM(vm_sg_ops);
 		vma->vm_private_data = (void *)map;
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
+		vma->vm_flags |= VM_LOCKED;
+#else
+		vma->vm_flags |= VM_RESERVED;
+#endif
                 break;
 	default:
 		return -EINVAL;	/* This should never happen. */
 	}
+#if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */
+	vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+#else
 	vma->vm_flags |= VM_RESERVED; /* Don't swap */
+#endif
 
 	vma->vm_file  =	 filp;	/* Needed for drm_vm_open() */
 	DRM(vm_open)(vma);
diff -ruN drivers/char/drm-4.2/drmstat.c drivers/char/drm/drmstat.c
--- drivers/char/drm-4.2/drmstat.c	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/drmstat.c	2003-01-14 07:00:59.000000000 +0900
@@ -0,0 +1,416 @@
+/* drmstat.c -- DRM device status and testing program
+ * Created: Tue Jan  5 08:19:24 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
+ * 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <getopt.h>
+#include <strings.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include "xf86drm.h"
+
+int sigio_fd;
+
+static double usec(struct timeval *end, struct timeval *start)
+{
+    double e = end->tv_sec   * 1000000 + end->tv_usec;
+    double s = start->tv_sec * 1000000 + start->tv_usec;
+
+    return e - s;
+}
+
+static void getversion(int fd)
+{
+    drmVersionPtr version;
+    
+    version = drmGetVersion(fd);
+    if (version) {
+	printf( "Name: %s\n", version->name ? version->name : "?" );
+	printf( "    Version: %d.%d.%d\n",
+		version->version_major,
+		version->version_minor,
+		version->version_patchlevel );
+	printf( "    Date: %s\n", version->date ? version->date : "?" );
+	printf( "    Desc: %s\n", version->desc ? version->desc : "?" );
+	drmFreeVersion(version);
+    } else {
+	printf( "No driver available\n" );
+    }
+}
+	
+void handler(int fd, void *oldctx, void *newctx)
+{
+    printf("Got fd %d\n", fd);
+}
+
+void process_sigio(char *device)
+{
+    int              fd;
+
+    if ((fd = open(device, 0)) < 0) {
+	drmError(-errno, __FUNCTION__);
+	exit(1);
+    }
+
+    sigio_fd = fd;
+    drmInstallSIGIOHandler(fd, handler);
+    for (;;) sleep(60);
+}
+
+int main(int argc, char **argv)
+{
+    int            c;
+    int            r  = 0;
+    int            fd = -1;
+    drmHandle      handle;
+    void           *address;
+    char           *pt;
+    unsigned long  count;
+    unsigned long  offset;
+    unsigned long  size;
+    drmContext     context;
+    int            loops;
+    char           buf[1024];
+    int            i;
+    drmBufInfoPtr  info;
+    drmBufMapPtr   bufs;
+    drmLockPtr     lock;
+    int            secs;
+
+    while ((c = getopt(argc, argv,
+		       "lc:vo:O:f:s:w:W:b:r:R:P:L:C:XS:B:F:")) != EOF)
+	switch (c) {
+	case 'F':
+	    count  = strtoul(optarg, NULL, 0);
+	    if (!fork()) {
+		dup(fd);
+		sleep(count);
+	    }
+	    close(fd);
+	    break;
+	case 'v': getversion(fd);                                        break;
+	case 'X':
+	    if ((r = drmCreateContext(fd, &context))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    printf( "Got %d\n", context);
+	    break;
+	case 'S':
+	    process_sigio(optarg);
+	    break;
+	case 'C':
+	    if ((r = drmSwitchToContext(fd, strtoul(optarg, NULL, 0)))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    break;
+	case 'c':
+	    if ((r = drmSetBusid(fd,optarg))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    break;
+	case 'o':
+	    if ((fd = drmOpen(optarg, NULL)) < 0) {
+		drmError(fd, argv[0]);
+		return 1;
+	    }
+	    break;
+	case 'O':
+	    if ((fd = drmOpen(NULL, optarg)) < 0) {
+		drmError(fd, argv[0]);
+		return 1;
+	    }
+	    break;
+	case 'B':		/* Test buffer allocation */
+	    count  = strtoul(optarg, &pt, 0);
+	    size   = strtoul(pt+1, &pt, 0);
+	    secs   = strtoul(pt+1, NULL, 0);
+	    {
+		drmDMAReq      dma;
+		int            *indices, *sizes;
+
+		indices = alloca(sizeof(*indices) * count);
+		sizes   = alloca(sizeof(*sizes)   * count);
+		dma.context         = context;
+		dma.send_count      = 0;
+		dma.request_count   = count;
+		dma.request_size    = size;
+		dma.request_list    = indices;
+		dma.request_sizes   = sizes;
+		dma.flags           = DRM_DMA_WAIT;
+		if ((r = drmDMA(fd, &dma))) {
+		    drmError(r, argv[0]);
+		    return 1;
+		}
+		for (i = 0; i < dma.granted_count; i++) {
+		    printf("%5d: index = %d, size = %d\n",
+			   i, dma.request_list[i], dma.request_sizes[i]);
+		}
+		sleep(secs);
+		drmFreeBufs(fd, dma.granted_count, indices);
+	    }
+	    break;
+	case 'b':
+	    count   = strtoul(optarg, &pt, 0);
+	    size    = strtoul(pt+1, NULL, 0);
+	    if ((r = drmAddBufs(fd, count, size, 0, 65536)) < 0) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    if (!(info = drmGetBufInfo(fd))) {
+		drmError(0, argv[0]);
+		return 1;
+	    }
+	    for (i = 0; i < info->count; i++) {
+		printf("%5d buffers of size %6d (low = %d, high = %d)\n",
+		       info->list[i].count,
+		       info->list[i].size,
+		       info->list[i].low_mark,
+		       info->list[i].high_mark);
+	    }
+	    if ((r = drmMarkBufs(fd, 0.50, 0.80))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    if (!(info = drmGetBufInfo(fd))) {
+		drmError(0, argv[0]);
+		return 1;
+	    }
+	    for (i = 0; i < info->count; i++) {
+		printf("%5d buffers of size %6d (low = %d, high = %d)\n",
+		       info->list[i].count,
+		       info->list[i].size,
+		       info->list[i].low_mark,
+		       info->list[i].high_mark);
+	    }
+	    printf("===== /proc/dri/0/mem =====\n");
+	    sprintf(buf, "cat /proc/dri/0/mem");
+	    system(buf);
+#if 1
+	    if (!(bufs = drmMapBufs(fd))) {
+		drmError(0, argv[0]);
+		return 1;
+	    }
+	    printf("===============================\n");
+	    printf( "%d bufs\n", bufs->count);
+	    for (i = 0; i < bufs->count; i++) {
+		printf( "  %4d: %8d bytes at %p\n",
+			i,
+			bufs->list[i].total,
+			bufs->list[i].address);
+	    }
+	    printf("===== /proc/dri/0/vma =====\n");
+	    sprintf(buf, "cat /proc/dri/0/vma");
+	    system(buf);
+#endif
+	    break;
+	case 'f':
+	    offset  = strtoul(optarg, &pt, 0);
+	    size    = strtoul(pt+1, NULL, 0);
+	    handle  = 0;
+	    if ((r = drmAddMap(fd, offset, size,
+			       DRM_FRAME_BUFFER, 0, &handle))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    printf("0x%08lx:0x%04lx added\n", offset, size);
+	    printf("===== /proc/dri/0/mem =====\n");
+	    sprintf(buf, "cat /proc/dri/0/mem");
+	    system(buf);
+	    break;
+	case 'r':
+	case 'R':
+	    offset  = strtoul(optarg, &pt, 0);
+	    size    = strtoul(pt+1, NULL, 0);
+	    handle  = 0;
+	    if ((r = drmAddMap(fd, offset, size,
+			       DRM_REGISTERS,
+			       c == 'R' ? DRM_READ_ONLY : 0,
+			       &handle))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    printf("0x%08lx:0x%04lx added\n", offset, size);
+	    printf("===== /proc/dri/0/mem =====\n");
+	    sprintf(buf, "cat /proc/dri/0/mem");
+	    system(buf);
+	    break;
+	case 's':
+	    size = strtoul(optarg, &pt, 0);
+	    handle = 0;
+	    if ((r = drmAddMap(fd, 0, size,
+			       DRM_SHM, DRM_CONTAINS_LOCK,
+			       &handle))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    printf("0x%04lx byte shm added at 0x%08lx\n", size, handle);
+	    sprintf(buf, "cat /proc/dri/0/vm");
+	    system(buf);
+	    break;
+	case 'P':
+	    offset  = strtoul(optarg, &pt, 0);
+	    size    = strtoul(pt+1, NULL, 0);
+	    address = NULL;
+	    if ((r = drmMap(fd, offset, size, &address))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    printf("0x%08lx:0x%04lx mapped at %p for pid %d\n",
+		   offset, size, address, getpid());
+	    printf("===== /proc/dri/0/vma =====\n");
+	    sprintf(buf, "cat /proc/dri/0/vma");
+	    system(buf);
+	    mprotect((void *)offset, size, PROT_READ);
+	    printf("===== /proc/dri/0/vma =====\n");
+	    sprintf(buf, "cat /proc/dri/0/vma");
+	    system(buf);
+	    break;
+	case 'w':
+	case 'W':
+	    offset  = strtoul(optarg, &pt, 0);
+	    size    = strtoul(pt+1, NULL, 0);
+	    address = NULL;
+	    if ((r = drmMap(fd, offset, size, &address))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    printf("0x%08lx:0x%04lx mapped at %p for pid %d\n",
+		   offset, size, address, getpid());
+	    printf("===== /proc/%d/maps =====\n", getpid());
+	    sprintf(buf, "cat /proc/%d/maps", getpid());
+	    system(buf);
+	    printf("===== /proc/grphics/0/mem =====\n");
+	    sprintf(buf, "cat /proc/dri/0/mem");
+	    system(buf);
+	    printf("===== /proc/dri/0/vma =====\n");
+	    sprintf(buf, "cat /proc/dri/0/vma");
+	    system(buf);
+	    printf("===== READING =====\n");
+	    for (i = 0; i < 0x10; i++)
+		printf("%02x ", (unsigned int)((unsigned char *)address)[i]);
+	    printf("\n");
+	    if (c == 'w') {
+		printf("===== WRITING =====\n");
+		for (i = 0; i < size; i+=2) {
+		    ((char *)address)[i]   = i & 0xff;
+		    ((char *)address)[i+1] = i & 0xff;
+		}
+	    }
+	    printf("===== READING =====\n");
+	    for (i = 0; i < 0x10; i++)
+		printf("%02x ", (unsigned int)((unsigned char *)address)[i]);
+	    printf("\n");
+	    printf("===== /proc/dri/0/vma =====\n");
+	    sprintf(buf, "cat /proc/dri/0/vma");
+	    system(buf);
+	    break;
+	case 'L':
+	    context = strtoul(optarg, &pt, 0);
+	    offset  = strtoul(pt+1, &pt, 0);
+	    size    = strtoul(pt+1, &pt, 0);
+	    loops   = strtoul(pt+1, NULL, 0);
+	    address = NULL;
+	    if ((r = drmMap(fd, offset, size, &address))) {
+		drmError(r, argv[0]);
+		return 1;
+	    }
+	    lock       = address;
+#if 1
+	    {
+		int            counter = 0;
+		struct timeval loop_start, loop_end;
+		struct timeval lock_start, lock_end;
+		double         wt;
+#define HISTOSIZE 9
+		int            histo[HISTOSIZE];
+		int            output = 0;
+		int            fast   = 0;
+
+		if (loops < 0) {
+		    loops = -loops;
+		    ++output;
+		}
+
+		for (i = 0; i < HISTOSIZE; i++) histo[i] = 0;
+
+		gettimeofday(&loop_start, NULL);
+		for (i = 0; i < loops; i++) {
+		    gettimeofday(&lock_start, NULL);
+		    DRM_LIGHT_LOCK_COUNT(fd,lock,context,fast);
+		    gettimeofday(&lock_end, NULL);
+		    DRM_UNLOCK(fd,lock,context);
+		    ++counter;
+		    wt = usec(&lock_end, &lock_start);
+		    if      (wt <=      2.5) ++histo[8];
+		    if      (wt <       5.0) ++histo[0];
+		    else if (wt <      50.0) ++histo[1];
+		    else if (wt <     500.0) ++histo[2];
+		    else if (wt <    5000.0) ++histo[3];
+		    else if (wt <   50000.0) ++histo[4];
+		    else if (wt <  500000.0) ++histo[5];
+		    else if (wt < 5000000.0) ++histo[6];
+		    else                     ++histo[7];
+		    if (output) printf( "%.2f uSec, %d fast\n", wt, fast);
+		}
+		gettimeofday(&loop_end, NULL);
+		printf( "Average wait time = %.2f usec, %d fast\n",
+			usec(&loop_end, &loop_start) /  counter, fast);
+		printf( "%9d <=     2.5 uS\n", histo[8]);
+		printf( "%9d <        5 uS\n", histo[0]);
+		printf( "%9d <       50 uS\n", histo[1]);
+		printf( "%9d <      500 uS\n", histo[2]);
+		printf( "%9d <     5000 uS\n", histo[3]);
+		printf( "%9d <    50000 uS\n", histo[4]);
+		printf( "%9d <   500000 uS\n", histo[5]);
+		printf( "%9d <  5000000 uS\n", histo[6]);
+		printf( "%9d >= 5000000 uS\n", histo[7]);
+	    }
+#else
+	    printf( "before lock: 0x%08x\n", lock->lock);
+	    printf( "lock: 0x%08x\n", lock->lock);
+	    sleep(5);
+	    printf( "unlock: 0x%08x\n", lock->lock);
+#endif
+	    break;
+	default:
+	    fprintf( stderr, "Usage: drmstat [options]\n" );
+	    return 1;
+	}
+
+    return r; 
+}
diff -ruN drivers/char/drm-4.2/gamma.h drivers/char/drm/gamma.h
--- drivers/char/drm-4.2/gamma.h	2001-08-09 01:42:14.000000000 +0900
+++ drivers/char/drm/gamma.h	2003-01-14 07:01:00.000000000 +0900
@@ -38,9 +38,36 @@
  */
 #define __HAVE_MTRR			1
 
+#define DRIVER_AUTHOR		"VA Linux Systems Inc."
+
+#define DRIVER_NAME		"gamma"
+#define DRIVER_DESC		"3DLabs gamma"
+#define DRIVER_DATE		"20010624"
+
+#define DRIVER_MAJOR		2
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	0
+
+#define DRIVER_IOCTLS							  \
+	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	     = { gamma_dma,	  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_GAMMA_INIT)] = { gamma_dma_init,  1, 1 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_GAMMA_COPY)] = { gamma_dma_copy,  1, 1 }
+
+#define IOCTL_TABLE_NAME	DRM(ioctls)
+#define IOCTL_FUNC_NAME 	DRM(ioctl)
+
+#define __HAVE_COUNTERS		5
+#define __HAVE_COUNTER6		_DRM_STAT_IRQ
+#define __HAVE_COUNTER7		_DRM_STAT_DMA
+#define __HAVE_COUNTER8		_DRM_STAT_PRIMARY
+#define __HAVE_COUNTER9		_DRM_STAT_SPECIAL
+#define __HAVE_COUNTER10	_DRM_STAT_MISSED
+
 /* DMA customization:
  */
 #define __HAVE_DMA			1
+#define __HAVE_AGP			1
+#define __MUST_HAVE_AGP			0
 #define __HAVE_OLD_DMA			1
 #define __HAVE_PCI_DMA			1
 
@@ -61,33 +88,61 @@
 #define __HAVE_DMA_QUIESCENT		1
 #define DRIVER_DMA_QUIESCENT() do {					\
 	/* FIXME ! */ 							\
-	gamma_dma_quiescent_dual(dev);					\
+	gamma_dma_quiescent_single(dev);					\
 	return 0;							\
 } while (0)
 
 #define __HAVE_DMA_IRQ			1
 #define __HAVE_DMA_IRQ_BH		1
+
+#if 1
 #define DRIVER_PREINSTALL() do {					\
 	drm_gamma_private_t *dev_priv =					\
 				(drm_gamma_private_t *)dev->dev_private;\
-	GAMMA_WRITE( GAMMA_GCOMMANDMODE,	0x00000000 );		\
+	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);			\
+	GAMMA_WRITE( GAMMA_GCOMMANDMODE,	0x00000004 );		\
 	GAMMA_WRITE( GAMMA_GDMACONTROL,		0x00000000 );		\
 } while (0)
-
 #define DRIVER_POSTINSTALL() do {					\
 	drm_gamma_private_t *dev_priv =					\
 				(drm_gamma_private_t *)dev->dev_private;\
+	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);			\
+	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);			\
 	GAMMA_WRITE( GAMMA_GINTENABLE,		0x00002001 );		\
 	GAMMA_WRITE( GAMMA_COMMANDINTENABLE,	0x00000008 );		\
 	GAMMA_WRITE( GAMMA_GDELAYTIMER,		0x00039090 );		\
 } while (0)
+#else
+#define DRIVER_POSTINSTALL() do {					\
+	drm_gamma_private_t *dev_priv =					\
+				(drm_gamma_private_t *)dev->dev_private;\
+	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);			\
+	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);			\
+	GAMMA_WRITE( GAMMA_GINTENABLE,		0x00002000 );		\
+	GAMMA_WRITE( GAMMA_COMMANDINTENABLE,	0x00000004 );		\
+} while (0)
+
+#define DRIVER_PREINSTALL() do {					\
+	drm_gamma_private_t *dev_priv =					\
+				(drm_gamma_private_t *)dev->dev_private;\
+	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);			\
+	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);			\
+	GAMMA_WRITE( GAMMA_GCOMMANDMODE,	GAMMA_QUEUED_DMA_MODE );\
+	GAMMA_WRITE( GAMMA_GDMACONTROL,		0x00000000 );\
+} while (0)
+#endif
 
 #define DRIVER_UNINSTALL() do {						\
 	drm_gamma_private_t *dev_priv =					\
 				(drm_gamma_private_t *)dev->dev_private;\
+	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 2);			\
+	while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);			\
 	GAMMA_WRITE( GAMMA_GDELAYTIMER,		0x00000000 );		\
 	GAMMA_WRITE( GAMMA_COMMANDINTENABLE,	0x00000000 );		\
 	GAMMA_WRITE( GAMMA_GINTENABLE,		0x00000000 );		\
 } while (0)
 
+#define DRIVER_AGP_BUFFERS_MAP( dev )					\
+	((drm_gamma_private_t *)((dev)->dev_private))->buffers
+
 #endif /* __GAMMA_H__ */
diff -ruN drivers/char/drm-4.2/gamma_dma.c drivers/char/drm/gamma_dma.c
--- drivers/char/drm-4.2/gamma_dma.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/gamma_dma.c	2003-01-14 07:00:59.000000000 +0900
@@ -29,35 +29,35 @@
  *
  */
 
+#define __NO_VERSION__
 #include "gamma.h"
 #include "drmP.h"
+#include "drm.h"
+#include "gamma_drm.h"
 #include "gamma_drv.h"
 
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/delay.h>
 
-
 static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address,
 				      unsigned long length)
 {
 	drm_gamma_private_t *dev_priv =
-		(drm_gamma_private_t *)dev->dev_private;
-
-	GAMMA_WRITE(GAMMA_DMAADDRESS, virt_to_phys((void *)address));
-	while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4)
-		;
+				(drm_gamma_private_t *)dev->dev_private;
+	mb();
+	while ( GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+	GAMMA_WRITE(GAMMA_DMAADDRESS, address);
+	while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4);
 	GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
 }
 
 void gamma_dma_quiescent_single(drm_device_t *dev)
 {
 	drm_gamma_private_t *dev_priv =
-		(drm_gamma_private_t *)dev->dev_private;
+				(drm_gamma_private_t *)dev->dev_private;
+	while (GAMMA_READ(GAMMA_DMACOUNT));
 
-	while (GAMMA_READ(GAMMA_DMACOUNT))
-		;
-	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
-		;
+	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
 
 	GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
 	GAMMA_WRITE(GAMMA_SYNC, 0);
@@ -71,56 +71,50 @@
 void gamma_dma_quiescent_dual(drm_device_t *dev)
 {
 	drm_gamma_private_t *dev_priv =
-		(drm_gamma_private_t *)dev->dev_private;
+				(drm_gamma_private_t *)dev->dev_private;
+	while (GAMMA_READ(GAMMA_DMACOUNT));
 
-	while (GAMMA_READ(GAMMA_DMACOUNT))
-		;
-	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
-		;
+	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
 
 	GAMMA_WRITE(GAMMA_BROADCASTMASK, 3);
-
 	GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
 	GAMMA_WRITE(GAMMA_SYNC, 0);
 
-				/* Read from first MX */
+	/* Read from first MX */
 	do {
-		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
-			;
+		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS));
 	} while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
 
-				/* Read from second MX */
+	/* Read from second MX */
 	do {
-		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
-			;
+		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000));
 	} while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
 }
 
 void gamma_dma_ready(drm_device_t *dev)
 {
 	drm_gamma_private_t *dev_priv =
-		(drm_gamma_private_t *)dev->dev_private;
-
-	while (GAMMA_READ(GAMMA_DMACOUNT))
-		;
+				(drm_gamma_private_t *)dev->dev_private;
+	while (GAMMA_READ(GAMMA_DMACOUNT));
 }
 
 static inline int gamma_dma_is_ready(drm_device_t *dev)
 {
 	drm_gamma_private_t *dev_priv =
-		(drm_gamma_private_t *)dev->dev_private;
-
-	return !GAMMA_READ(GAMMA_DMACOUNT);
+				(drm_gamma_private_t *)dev->dev_private;
+	return(!GAMMA_READ(GAMMA_DMACOUNT));
 }
 
 void gamma_dma_service(int irq, void *device, struct pt_regs *regs)
 {
-	drm_device_t	    *dev      = (drm_device_t *)device;
-	drm_device_dma_t    *dma      = dev->dma;
+	drm_device_t	 *dev = (drm_device_t *)device;
+	drm_device_dma_t *dma = dev->dma;
 	drm_gamma_private_t *dev_priv =
-		(drm_gamma_private_t *)dev->dev_private;
+				(drm_gamma_private_t *)dev->dev_private;
 
 	atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */
+
+	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
 	GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
 	GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
 	GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
@@ -164,7 +158,9 @@
 	}
 
 	buf	= dma->next_buffer;
-	address = (unsigned long)buf->address;
+	/* WE NOW ARE ON LOGICAL PAGES!! - using page table setup in dma_init */
+	/* So we pass the buffer index value into the physical page offset */
+	address = buf->idx << 12;
 	length	= buf->used;
 
 	DRM_DEBUG("context %d, buffer %d (%ld bytes)\n",
@@ -231,6 +227,9 @@
 	buf->time_dispatched = get_cycles();
 #endif
 
+	/* WE NOW ARE ON LOGICAL PAGES!!! - overriding address */
+	address = buf->idx << 12;
+
 	gamma_dma_dispatch(dev, address, length);
 	gamma_free_buffer(dev, dma->this_buffer);
 	dma->this_buffer = buf;
@@ -523,11 +522,11 @@
 			}
 		}
 		if (retcode) {
-			DRM_ERROR("ctx%d w%d p%d c%d i%d l%d %d/%d\n",
+			DRM_ERROR("ctx%d w%d p%d c%ld i%d l%d %d/%d\n",
 				  d->context,
 				  last_buf->waiting,
 				  last_buf->pending,
-				  DRM_WAITCOUNT(dev, d->context),
+				  (long)DRM_WAITCOUNT(dev, d->context),
 				  last_buf->idx,
 				  last_buf->list,
 				  last_buf->pid,
@@ -581,3 +580,255 @@
 
 	return retcode;
 }
+
+/* =============================================================
+ * DMA initialization, cleanup
+ */
+
+static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
+{
+	drm_gamma_private_t *dev_priv;
+	drm_device_dma_t    *dma = dev->dma;
+	drm_buf_t	    *buf;
+	int i;
+	struct list_head    *list;
+	unsigned long	    *pgt;
+
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	dev_priv = DRM(alloc)( sizeof(drm_gamma_private_t),
+							DRM_MEM_DRIVER );
+	if ( !dev_priv )
+		return -ENOMEM;
+
+	dev->dev_private = (void *)dev_priv;
+
+	memset( dev_priv, 0, sizeof(drm_gamma_private_t) );
+
+	list_for_each(list, &dev->maplist->head) {
+		drm_map_list_t *r_list = (drm_map_list_t *)list;
+		if( r_list->map &&
+		    r_list->map->type == _DRM_SHM &&
+		    r_list->map->flags & _DRM_CONTAINS_LOCK ) {
+			dev_priv->sarea = r_list->map;
+ 			break;
+ 		}
+ 	}
+
+	DRM_FIND_MAP( dev_priv->mmio0, init->mmio0 );
+	DRM_FIND_MAP( dev_priv->mmio1, init->mmio1 );
+	DRM_FIND_MAP( dev_priv->mmio2, init->mmio2 );
+	DRM_FIND_MAP( dev_priv->mmio3, init->mmio3 );
+
+	dev_priv->sarea_priv = (drm_gamma_sarea_t *)
+		((u8 *)dev_priv->sarea->handle +
+		 init->sarea_priv_offset);
+
+	if (init->pcimode) {
+		buf = dma->buflist[GLINT_DRI_BUF_COUNT];
+		pgt = buf->address;
+
+ 		for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
+			buf = dma->buflist[i];
+			*pgt = virt_to_phys((void*)buf->address) | 0x07;
+			pgt++;
+		}
+
+		buf = dma->buflist[GLINT_DRI_BUF_COUNT];
+	} else {
+		DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+
+		DRM_IOREMAP( dev_priv->buffers );
+
+		buf = dma->buflist[GLINT_DRI_BUF_COUNT];
+		pgt = buf->address;
+
+ 		for (i = 0; i < GLINT_DRI_BUF_COUNT; i++) {
+			buf = dma->buflist[i];
+			*pgt = (unsigned long)buf->address + 0x07;
+			pgt++;
+		}
+
+		buf = dma->buflist[GLINT_DRI_BUF_COUNT];
+
+		while (GAMMA_READ(GAMMA_INFIFOSPACE) < 1);
+		GAMMA_WRITE( GAMMA_GDMACONTROL, 0xe);
+	}
+	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 2);
+	GAMMA_WRITE( GAMMA_PAGETABLEADDR, virt_to_phys((void*)buf->address) );
+	GAMMA_WRITE( GAMMA_PAGETABLELENGTH, 2 );
+
+	return 0;
+}
+
+int gamma_do_cleanup_dma( drm_device_t *dev )
+{
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( dev->dev_private ) {
+		drm_gamma_private_t *dev_priv = dev->dev_private;
+
+		DRM_IOREMAPFREE( dev_priv->buffers );
+
+		DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
+			   DRM_MEM_DRIVER );
+		dev->dev_private = NULL;
+	}
+
+	return 0;
+}
+
+int gamma_dma_init( struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_gamma_init_t init;
+
+	if ( copy_from_user( &init, (drm_gamma_init_t *)arg, sizeof(init) ) )
+		return -EFAULT;
+
+	switch ( init.func ) {
+	case GAMMA_INIT_DMA:
+		return gamma_do_init_dma( dev, &init );
+	case GAMMA_CLEANUP_DMA:
+		return gamma_do_cleanup_dma( dev );
+	}
+
+	return -EINVAL;
+}
+
+static int gamma_do_copy_dma( drm_device_t *dev, drm_gamma_copy_t *copy )
+{
+	drm_device_dma_t    *dma = dev->dma;
+	unsigned int        *screenbuf;
+
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	/* We've DRM_RESTRICTED this DMA buffer */
+
+	screenbuf = dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ]->address;
+
+#if 0
+	*buffer++ = 0x180;	/* Tag (FilterMode) */
+	*buffer++ = 0x200;	/* Allow FBColor through */
+	*buffer++ = 0x53B;	/* Tag */
+	*buffer++ = copy->Pitch;
+	*buffer++ = 0x53A;	/* Tag */
+	*buffer++ = copy->SrcAddress;
+	*buffer++ = 0x539;	/* Tag */
+	*buffer++ = copy->WidthHeight; /* Initiates transfer */
+	*buffer++ = 0x53C;	/* Tag - DMAOutputAddress */
+	*buffer++ = virt_to_phys((void*)screenbuf);
+	*buffer++ = 0x53D;	/* Tag - DMAOutputCount */
+	*buffer++ = copy->Count; /* Reads HostOutFifo BLOCKS until ..*/
+
+	/* Data now sitting in dma->buflist[ GLINT_DRI_BUF_COUNT + 1 ] */
+	/* Now put it back to the screen */
+
+	*buffer++ = 0x180;	/* Tag (FilterMode) */
+	*buffer++ = 0x400;	/* Allow Sync through */
+	*buffer++ = 0x538;	/* Tag - DMARectangleReadTarget */
+	*buffer++ = 0x155;	/* FBSourceData | count */
+	*buffer++ = 0x537;	/* Tag */
+	*buffer++ = copy->Pitch;
+	*buffer++ = 0x536;	/* Tag */
+	*buffer++ = copy->DstAddress;
+	*buffer++ = 0x535;	/* Tag */
+	*buffer++ = copy->WidthHeight; /* Initiates transfer */
+	*buffer++ = 0x530;	/* Tag - DMAAddr */
+	*buffer++ = virt_to_phys((void*)screenbuf);
+	*buffer++ = 0x531;
+	*buffer++ = copy->Count; /* initiates DMA transfer of color data */
+#endif
+
+	/* need to dispatch it now */
+
+	return 0;
+}
+
+int gamma_dma_copy( struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_gamma_copy_t copy;
+
+	if ( copy_from_user( &copy, (drm_gamma_copy_t *)arg, sizeof(copy) ) )
+		return -EFAULT;
+
+	return gamma_do_copy_dma( dev, &copy );
+}
+
+/* =============================================================
+ * Per Context SAREA Support
+ */
+
+int gamma_getsareactx(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+{
+	drm_file_t	*priv	= filp->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_ctx_priv_map_t request;
+	drm_map_t *map;
+
+	if (copy_from_user(&request,
+			   (drm_ctx_priv_map_t *)arg,
+			   sizeof(request)))
+		return -EFAULT;
+
+	down(&dev->struct_sem);
+	if ((int)request.ctx_id >= dev->max_context) {
+		up(&dev->struct_sem);
+		return -EINVAL;
+	}
+
+	map = dev->context_sareas[request.ctx_id];
+	up(&dev->struct_sem);
+
+	request.handle = map->handle;
+	if (copy_to_user((drm_ctx_priv_map_t *)arg, &request, sizeof(request)))
+		return -EFAULT;
+	return 0;
+}
+
+int gamma_setsareactx(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+{
+	drm_file_t	*priv	= filp->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_ctx_priv_map_t request;
+	drm_map_t *map = NULL;
+	drm_map_list_t *r_list;
+	struct list_head *list;
+
+	if (copy_from_user(&request,
+			   (drm_ctx_priv_map_t *)arg,
+			   sizeof(request)))
+		return -EFAULT;
+
+	down(&dev->struct_sem);
+	r_list = NULL;
+	list_for_each(list, &dev->maplist->head) {
+		r_list = (drm_map_list_t *)list;
+		if(r_list->map &&
+		   r_list->map->handle == request.handle) break;
+	}
+	if (list == &(dev->maplist->head)) {
+		up(&dev->struct_sem);
+		return -EINVAL;
+	}
+	map = r_list->map;
+	up(&dev->struct_sem);
+
+	if (!map) return -EINVAL;
+
+	down(&dev->struct_sem);
+	if ((int)request.ctx_id >= dev->max_context) {
+		up(&dev->struct_sem);
+		return -EINVAL;
+	}
+	dev->context_sareas[request.ctx_id] = map;
+	up(&dev->struct_sem);
+	return 0;
+}
diff -ruN drivers/char/drm-4.2/gamma_drm.h drivers/char/drm/gamma_drm.h
--- drivers/char/drm-4.2/gamma_drm.h	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/gamma_drm.h	2003-01-14 07:01:00.000000000 +0900
@@ -0,0 +1,89 @@
+#ifndef _GAMMA_DRM_H_
+#define _GAMMA_DRM_H_
+
+typedef struct _drm_gamma_tex_region {
+	unsigned char next, prev; /* indices to form a circular LRU  */
+	unsigned char in_use;	/* owned by a client, or free? */
+	int age;		/* tracked by clients to update local LRU's */
+} drm_gamma_tex_region_t;
+
+typedef struct {
+	unsigned int	GDeltaMode;
+	unsigned int	GDepthMode;
+	unsigned int	GGeometryMode;
+	unsigned int	GTransformMode;
+} drm_gamma_context_regs_t;
+
+typedef struct _drm_gamma_sarea {
+   	drm_gamma_context_regs_t context_state;
+
+	unsigned int dirty;
+
+
+	/* Maintain an LRU of contiguous regions of texture space.  If
+	 * you think you own a region of texture memory, and it has an
+	 * age different to the one you set, then you are mistaken and
+	 * it has been stolen by another client.  If global texAge
+	 * hasn't changed, there is no need to walk the list.
+	 *
+	 * These regions can be used as a proxy for the fine-grained
+	 * texture information of other clients - by maintaining them
+	 * in the same lru which is used to age their own textures,
+	 * clients have an approximate lru for the whole of global
+	 * texture space, and can make informed decisions as to which
+	 * areas to kick out.  There is no need to choose whether to
+	 * kick out your own texture or someone else's - simply eject
+	 * them all in LRU order.  
+	 */
+   
+#define GAMMA_NR_TEX_REGIONS 64
+	drm_gamma_tex_region_t texList[GAMMA_NR_TEX_REGIONS+1]; 
+				/* Last elt is sentinal */
+        int texAge;		/* last time texture was uploaded */
+        int last_enqueue;	/* last time a buffer was enqueued */
+	int last_dispatch;	/* age of the most recently dispatched buffer */
+	int last_quiescent;     /*  */
+	int ctxOwner;		/* last context to upload state */
+
+	int vertex_prim;
+} drm_gamma_sarea_t;
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmGamma.h)
+ */
+
+/* Gamma specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_IOCTL_GAMMA_INIT		DRM_IOW( 0x40, drm_gamma_init_t)
+#define DRM_IOCTL_GAMMA_COPY		DRM_IOW( 0x41, drm_gamma_copy_t)
+
+typedef struct drm_gamma_copy {
+	unsigned int	DMAOutputAddress;
+	unsigned int	DMAOutputCount;
+	unsigned int	DMAReadGLINTSource;
+	unsigned int	DMARectangleWriteAddress;
+	unsigned int	DMARectangleWriteLinePitch;
+	unsigned int	DMARectangleWrite;
+	unsigned int	DMARectangleReadAddress;
+	unsigned int	DMARectangleReadLinePitch;
+	unsigned int	DMARectangleRead;
+	unsigned int	DMARectangleReadTarget;
+} drm_gamma_copy_t;
+
+typedef struct drm_gamma_init {
+   	enum {
+	   	GAMMA_INIT_DMA    = 0x01,
+	       	GAMMA_CLEANUP_DMA = 0x02
+	} func;
+
+   	int sarea_priv_offset;
+	int pcimode;
+	unsigned int mmio0;
+	unsigned int mmio1;
+	unsigned int mmio2;
+	unsigned int mmio3;
+	unsigned int buffers_offset;
+} drm_gamma_init_t;
+
+#endif /* _GAMMA_DRM_H_ */
diff -ruN drivers/char/drm-4.2/gamma_drv.c drivers/char/drm/gamma_drv.c
--- drivers/char/drm-4.2/gamma_drv.c	2001-08-09 01:42:14.000000000 +0900
+++ drivers/char/drm/gamma_drv.c	2003-01-14 07:00:59.000000000 +0900
@@ -32,57 +32,18 @@
 #include <linux/config.h>
 #include "gamma.h"
 #include "drmP.h"
+#include "drm.h"
+#include "gamma_drm.h"
 #include "gamma_drv.h"
 
-#define DRIVER_AUTHOR		"VA Linux Systems Inc."
-
-#define DRIVER_NAME		"gamma"
-#define DRIVER_DESC		"3DLabs gamma"
-#define DRIVER_DATE		"20010216"
-
-#define DRIVER_MAJOR		1
-#define DRIVER_MINOR		0
-#define DRIVER_PATCHLEVEL	0
-
-#define DRIVER_IOCTLS							  \
-	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	     = { gamma_dma,	  1, 0 }
-
-
-#define __HAVE_COUNTERS		5
-#define __HAVE_COUNTER6		_DRM_STAT_IRQ
-#define __HAVE_COUNTER7		_DRM_STAT_DMA
-#define __HAVE_COUNTER8		_DRM_STAT_PRIMARY
-#define __HAVE_COUNTER9		_DRM_STAT_SPECIAL
-#define __HAVE_COUNTER10	_DRM_STAT_MISSED
-
-
 #include "drm_auth.h"
+#include "drm_agpsupport.h"
 #include "drm_bufs.h"
 #include "drm_context.h"
 #include "drm_dma.h"
 #include "drm_drawable.h"
 #include "drm_drv.h"
 
-#ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO).  It calls the insmod option
- * routine, drm_parse_drm.
- */
-
-/* JH- We have to hand expand the string ourselves because of the cpp.  If
- * anyone can think of a way that we can fit into the __setup macro without
- * changing it, then please send the solution my way.
- */
-static int __init gamma_options( char *str )
-{
-	DRM(parse_options)( str );
-	return 1;
-}
-
-__setup( DRIVER_NAME "=", gamma_options );
-#endif
-
-
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
diff -ruN drivers/char/drm-4.2/gamma_drv.h drivers/char/drm/gamma_drv.h
--- drivers/char/drm-4.2/gamma_drv.h	2001-08-09 01:42:14.000000000 +0900
+++ drivers/char/drm/gamma_drv.h	2003-01-14 07:01:00.000000000 +0900
@@ -32,8 +32,9 @@
 #ifndef _GAMMA_DRV_H_
 #define _GAMMA_DRV_H_
 
-
 typedef struct drm_gamma_private {
+	drm_gamma_sarea_t *sarea_priv;
+	drm_map_t *sarea;
 	drm_map_t *buffers;
 	drm_map_t *mmio0;
 	drm_map_t *mmio1;
@@ -51,6 +52,11 @@
 	}								\
 } while (0)
 
+				/* gamma_dma.c */
+extern int gamma_dma_init( struct inode *inode, struct file *filp,
+			 unsigned int cmd, unsigned long arg );
+extern int gamma_dma_copy( struct inode *inode, struct file *filp,
+			 unsigned int cmd, unsigned long arg );
 
 extern void gamma_dma_ready(drm_device_t *dev);
 extern void gamma_dma_quiescent_single(drm_device_t *dev);
@@ -63,6 +69,7 @@
 extern int  gamma_find_devices(void);
 extern int  gamma_found(void);
 
+#define GLINT_DRI_BUF_COUNT 256
 
 #define GAMMA_OFF(reg)						   \
 	((reg < 0x1000)						   \
@@ -78,7 +85,6 @@
 			   ((reg < 0x10000)  ? dev_priv->mmio1->handle :     \
 			    ((reg < 0x11000) ? dev_priv->mmio2->handle :     \
 					       dev_priv->mmio3->handle))))
-	
 #define GAMMA_ADDR(reg)	 (GAMMA_BASE(reg) + GAMMA_OFF(reg))
 #define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg)
 #define GAMMA_READ(reg)	 GAMMA_DEREF(reg)
@@ -91,9 +97,11 @@
 #define GAMMA_FILTERMODE       0x8c00
 #define GAMMA_GCOMMANDINTFLAGS 0x0c50
 #define GAMMA_GCOMMANDMODE     0x0c40
+#define		GAMMA_QUEUED_DMA_MODE		1<<1
 #define GAMMA_GCOMMANDSTATUS   0x0c60
 #define GAMMA_GDELAYTIMER      0x0c38
 #define GAMMA_GDMACONTROL      0x0060
+#define 	GAMMA_USE_AGP			1<<1
 #define GAMMA_GINTENABLE       0x0808
 #define GAMMA_GINTFLAGS	       0x0810
 #define GAMMA_INFIFOSPACE      0x0018
@@ -101,5 +109,12 @@
 #define GAMMA_OUTPUTFIFO       0x2000
 #define GAMMA_SYNC	       0x8c40
 #define GAMMA_SYNC_TAG	       0x0188
+#define GAMMA_PAGETABLEADDR    0x0C00
+#define GAMMA_PAGETABLELENGTH  0x0C08
+
+#define GAMMA_PASSTHROUGH	0x1FE
+#define GAMMA_DMAADDRTAG	0x530
+#define GAMMA_DMACOUNTTAG	0x531
+#define GAMMA_COMMANDINTTAG	0x532
 
 #endif
diff -ruN drivers/char/drm-4.2/i810.h drivers/char/drm/i810.h
--- drivers/char/drm-4.2/i810.h	2001-08-09 01:42:14.000000000 +0900
+++ drivers/char/drm/i810.h	2003-01-14 07:01:00.000000000 +0900
@@ -41,6 +41,47 @@
 #define __HAVE_MTRR		1
 #define __HAVE_CTX_BITMAP	1
 
+#define DRIVER_AUTHOR		"VA Linux Systems Inc."
+
+#define DRIVER_NAME		"i810"
+#define DRIVER_DESC		"Intel i810"
+#define DRIVER_DATE		"20020211"
+
+/* Interface history
+ *
+ * 1.1   - XFree86 4.1
+ * 1.2   - XvMC interfaces
+ *       - XFree86 4.2
+ * 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility)
+ *       - Remove requirement for interrupt (leave stubs again)
+ */
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		2
+#define DRIVER_PATCHLEVEL	1
+
+#define DRIVER_IOCTLS							    \
+	[DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)]   = { i810_dma_init,    1, 1 }, \
+   	[DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex,  1, 0 }, \
+   	[DRM_IOCTL_NR(DRM_IOCTL_I810_CLEAR)]  = { i810_clear_bufs,  1, 0 }, \
+      	[DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)]  = { i810_flush_ioctl, 1, 0 }, \
+   	[DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage,      1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf,      1, 0 }, \
+   	[DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)]   = { i810_swap_bufs,   1, 0 }, \
+   	[DRM_IOCTL_NR(DRM_IOCTL_I810_COPY)]   = { i810_copybuf,     1, 0 }, \
+   	[DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy,      1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I810_OV0INFO)] = { i810_ov0_info,   1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I810_FSTATUS)] = { i810_fstatus,    1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I810_OV0FLIP)] = { i810_ov0_flip,   1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I810_MC)]      = { i810_dma_mc,     1, 1 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus,    1, 0 }
+
+
+#define __HAVE_COUNTERS         4
+#define __HAVE_COUNTER6         _DRM_STAT_IRQ
+#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
+#define __HAVE_COUNTER9         _DRM_STAT_DMA
+
 /* Driver customization:
  */
 #define __HAVE_RELEASE		1
@@ -60,50 +101,10 @@
 	i810_dma_quiescent( dev );					\
 } while (0)
 
-#define __HAVE_DMA_IRQ		1
-#define __HAVE_DMA_IRQ_BH	1
-#define __HAVE_SHARED_IRQ       1
-#define DRIVER_PREINSTALL() do {					\
-	drm_i810_private_t *dev_priv =					\
-		(drm_i810_private_t *)dev->dev_private;			\
-	u16 tmp;							\
-   	tmp = I810_READ16( I810REG_HWSTAM );				\
-   	tmp = tmp & 0x6000;						\
-   	I810_WRITE16( I810REG_HWSTAM, tmp );				\
-									\
-      	tmp = I810_READ16( I810REG_INT_MASK_R );			\
-   	tmp = tmp & 0x6000;		/* Unmask interrupts */		\
-   	I810_WRITE16( I810REG_INT_MASK_R, tmp );			\
-   	tmp = I810_READ16( I810REG_INT_ENABLE_R );			\
-   	tmp = tmp & 0x6000;		/* Disable all interrupts */	\
-      	I810_WRITE16( I810REG_INT_ENABLE_R, tmp );			\
-} while (0)
-
-#define DRIVER_POSTINSTALL() do {					\
-	drm_i810_private_t *dev_priv =					\
-		(drm_i810_private_t *)dev->dev_private;			\
-	u16 tmp;							\
-   	tmp = I810_READ16( I810REG_INT_ENABLE_R );			\
-   	tmp = tmp & 0x6000;						\
-   	tmp = tmp | 0x0003;	/* Enable bp & user interrupts */	\
-   	I810_WRITE16( I810REG_INT_ENABLE_R, tmp );			\
-} while (0)
-
-#define DRIVER_UNINSTALL() do {						\
-	drm_i810_private_t *dev_priv =					\
-		(drm_i810_private_t *)dev->dev_private;			\
-	u16 tmp;							\
-	if ( dev_priv ) {						\
-		tmp = I810_READ16( I810REG_INT_IDENTITY_R );		\
-		tmp = tmp & ~(0x6000);	/* Clear all interrupts */	\
-		if ( tmp != 0 )						\
-			I810_WRITE16( I810REG_INT_IDENTITY_R, tmp );	\
-									\
-		tmp = I810_READ16( I810REG_INT_ENABLE_R );		\
-		tmp = tmp & 0x6000;	/* Disable all interrupts */	\
-		I810_WRITE16( I810REG_INT_ENABLE_R, tmp );		\
-	}								\
-} while (0)
+/* Don't need an irq any more.  The template code will make sure that
+ * a noop stub is generated for compatibility.
+ */
+#define __HAVE_DMA_IRQ		0
 
 /* Buffer customization:
  */
diff -ruN drivers/char/drm-4.2/i810_dma.c drivers/char/drm/i810_dma.c
--- drivers/char/drm-4.2/i810_dma.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/i810_dma.c	2003-01-14 07:00:59.000000000 +0900
@@ -26,20 +26,24 @@
  *
  * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
  *	    Jeff Hartmann <jhartmann@valinux.com>
- *          Keith Whitwell <keithw@valinux.com>
+ *          Keith Whitwell <keith@tungstengraphics.com>
  *
  */
 
-#include <linux/config.h>
+#define __NO_VERSION__
 #include "i810.h"
 #include "drmP.h"
+#include "drm.h"
+#include "i810_drm.h"
 #include "i810_drv.h"
 #include <linux/interrupt.h>	/* For task queue support */
-#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/pagemap.h>
 
-/* in case we don't have a 2.3.99-pre6 kernel or later: */
-#ifndef VM_DONTCOPY
-#define VM_DONTCOPY 0
+#ifdef DO_MUNMAP_4_ARGS
+#define DO_MUNMAP(m, a, l)	do_munmap(m, a, l, 1)
+#else
+#define DO_MUNMAP(m, a, l)	do_munmap(m, a, l)
 #endif
 
 #define I810_BUF_FREE		2
@@ -49,32 +53,10 @@
 #define I810_BUF_UNMAPPED 0
 #define I810_BUF_MAPPED   1
 
-#define RING_LOCALS	unsigned int outring, ringmask; volatile char *virt;
-
-#define BEGIN_LP_RING(n) do {				\
-	if (I810_VERBOSE)				\
-		DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n",	\
-			  n, __FUNCTION__);		\
-	if (dev_priv->ring.space < n*4) 		\
-		i810_wait_ring(dev, n*4);		\
-	dev_priv->ring.space -= n*4;			\
-	outring = dev_priv->ring.tail;			\
-	ringmask = dev_priv->ring.tail_mask;		\
-	virt = dev_priv->ring.virtual_start;		\
-} while (0)
-
-#define ADVANCE_LP_RING() do {					\
-	if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n");	\
-	dev_priv->ring.tail = outring;				\
-	I810_WRITE(LP_RING + RING_TAIL, outring);		\
-} while(0)
-
-#define OUT_RING(n) do {						\
-	if (I810_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));	\
-	*(volatile unsigned int *)(virt + outring) = n;			\
-	outring += 4;							\
-	outring &= ringmask;						\
-} while (0)
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
+#define down_write down
+#define up_write up
+#endif
 
 static inline void i810_print_status_page(drm_device_t *dev)
 {
@@ -135,14 +117,14 @@
 }
 
 static struct file_operations i810_buffer_fops = {
-	open:	 DRM(open),
-	flush:	 DRM(flush),
-	release: DRM(release),
-	ioctl:	 DRM(ioctl),
-	mmap:	 i810_mmap_buffers,
-	read:	 DRM(read),
-	fasync:	 DRM(fasync),
-      	poll:	 DRM(poll),
+	.open	 = DRM(open),
+	.flush	 = DRM(flush),
+	.release = DRM(release),
+	.ioctl	 = DRM(ioctl),
+	.mmap	 = i810_mmap_buffers,
+	.read	 = DRM(read),
+	.fasync  = DRM(fasync),
+      	.poll	 = DRM(poll),
 };
 
 int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
@@ -165,7 +147,7 @@
    	buf_priv->currently_mapped = I810_BUF_MAPPED;
 	unlock_kernel();
 
-	if (remap_page_range(vma->vm_start,
+	if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
 			     VM_OFFSET(vma),
 			     vma->vm_end - vma->vm_start,
 			     vma->vm_page_prot)) return -EAGAIN;
@@ -183,28 +165,24 @@
 
 	if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
 
-	if(VM_DONTCOPY != 0) {
-		down_write( &current->mm->mmap_sem );
-		old_fops = filp->f_op;
-		filp->f_op = &i810_buffer_fops;
-		dev_priv->mmap_buffer = buf;
-		buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
-						    PROT_READ|PROT_WRITE,
-						    MAP_SHARED,
-						    buf->bus_address);
-		dev_priv->mmap_buffer = NULL;
-   		filp->f_op = old_fops;
-		if ((unsigned long)buf_priv->virtual > -1024UL) {
-			/* Real error */
-			DRM_DEBUG("mmap error\n");
-			retcode = (signed int)buf_priv->virtual;
-			buf_priv->virtual = 0;
-		}
-		up_write( &current->mm->mmap_sem );
-	} else {
-		buf_priv->virtual = buf_priv->kernel_virtual;
-   		buf_priv->currently_mapped = I810_BUF_MAPPED;
+	down_write( &current->mm->mmap_sem );
+	old_fops = filp->f_op;
+	filp->f_op = &i810_buffer_fops;
+	dev_priv->mmap_buffer = buf;
+	buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
+					    PROT_READ|PROT_WRITE,
+					    MAP_SHARED,
+					    buf->bus_address);
+	dev_priv->mmap_buffer = NULL;
+	filp->f_op = old_fops;
+	if ((unsigned long)buf_priv->virtual > -1024UL) {
+		/* Real error */
+		DRM_ERROR("mmap error\n");
+		retcode = (signed int)buf_priv->virtual;
+		buf_priv->virtual = 0;
 	}
+	up_write( &current->mm->mmap_sem );
+
 	return retcode;
 }
 
@@ -213,15 +191,15 @@
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	int retcode = 0;
 
-	if(VM_DONTCOPY != 0) {
-		if(buf_priv->currently_mapped != I810_BUF_MAPPED)
-			return -EINVAL;
-		down_write( &current->mm->mmap_sem );
-        	retcode = do_munmap(current->mm,
-				    (unsigned long)buf_priv->virtual,
-				    (size_t) buf->total);
-		up_write( &current->mm->mmap_sem );
-	}
+	if(buf_priv->currently_mapped != I810_BUF_MAPPED)
+		return -EINVAL;
+
+	down_write(&current->mm->mmap_sem);
+	retcode = DO_MUNMAP(current->mm,
+			    (unsigned long)buf_priv->virtual,
+			    (size_t) buf->total);
+	up_write(&current->mm->mmap_sem);
+
    	buf_priv->currently_mapped = I810_BUF_UNMAPPED;
    	buf_priv->virtual = 0;
 
@@ -246,7 +224,7 @@
 	retcode = i810_map_buffer(buf, filp);
 	if(retcode) {
 		i810_freelist_put(dev, buf);
-	   	DRM_DEBUG("mapbuf failed, retcode %d\n", retcode);
+	   	DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
 		return retcode;
 	}
 	buf->pid     = priv->pid;
@@ -273,8 +251,9 @@
 					 dev_priv->ring.Size);
 		}
 	   	if(dev_priv->hw_status_page != 0UL) {
-		   	pci_free_consistent(dev->pdev, PAGE_SIZE, (void *)dev_priv->hw_status_page,
-		   		dev_priv->dma_status_page);
+		   	pci_free_consistent(dev->pdev, PAGE_SIZE,
+					    (void *)dev_priv->hw_status_page,
+					    dev_priv->dma_status_page);
 		   	/* Need to rewrite hardware status page */
 		   	I810_WRITE(0x02080, 0x1ffff000);
 		}
@@ -301,8 +280,6 @@
 
 	end = jiffies + (HZ*3);
    	while (ring->space < n) {
-	   	int i;
-
 	   	ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 	   	ring->space = ring->head - (ring->tail+8);
 		if (ring->space < 0) ring->space += ring->Size;
@@ -311,13 +288,12 @@
 		   end = jiffies + (HZ*3);
 
 	   	iters++;
-		if((signed)(end - jiffies) <= 0) {
+		if(time_before(end, jiffies)) {
 		   	DRM_ERROR("space: %d wanted %d\n", ring->space, n);
 		   	DRM_ERROR("lockup\n");
 		   	goto out_wait_ring;
 		}
-
-	   	for (i = 0 ; i < 2000 ; i++) ;
+		udelay(1);
 	}
 
 out_wait_ring:
@@ -405,9 +381,6 @@
 		((u8 *)dev_priv->sarea_map->handle +
 		 init->sarea_priv_offset);
 
-   	atomic_set(&dev_priv->flush_done, 0);
-	init_waitqueue_head(&dev_priv->flush_queue);
-
    	dev_priv->ring.Start = init->ring_start;
    	dev_priv->ring.End = init->ring_end;
    	dev_priv->ring.Size = init->ring_size;
@@ -440,8 +413,9 @@
 	dev_priv->zi1 = init->depth_offset | init->pitch_bits;
 
    	/* Program Hardware Status Page */
-   	dev_priv->hw_status_page = (unsigned long)pci_alloc_consistent(dev->pdev, PAGE_SIZE,
-   			&dev_priv->dma_status_page);
+   	dev_priv->hw_status_page =
+		(unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+						&dev_priv->dma_status_page);
    	if(dev_priv->hw_status_page == 0UL) {
 		dev->dev_private = (void *)dev_priv;
 		i810_dma_cleanup(dev);
@@ -451,7 +425,7 @@
    	memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
    	DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
 
-   	I810_WRITE(0x02080, dev_priv->dma_status_page);
+	I810_WRITE(0x02080, dev_priv->dma_status_page);
    	DRM_DEBUG("Enabled hardware status page\n");
 
    	/* Now we need to init our freelist */
@@ -467,15 +441,6 @@
    	return 0;
 }
 
-#ifdef CONFIG_DRM_I810_XFREE_41
-int xfreeversion = 41;
-#else
-int xfreeversion = -1;
-#endif
-
-MODULE_PARM(xfreeversion, "i");
-MODULE_PARM_DESC(xfreeversion, "The version of XFree86 that needs to be supported");
-
 int i810_dma_init(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
@@ -487,28 +452,6 @@
 
   	if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init)))
 		return -EFAULT;
-		
-	if ((xfreeversion == 41) ||
-	    ((xfreeversion == -1) && (init.pitch == 0))) {
-		/*
-		 * Ok we have a problem here.  Someone decided it was
-		 * funny to add two fields in the middle of the
-		 * drm_i810_init_it structure in the transition between
-		 * XFree86 4.1.0 and 4.2.0.
-		 *
-		 * The code below tries to fix this ABI breakage up as
-		 * good as possible, unfortionatly it's impossible to
-		 * autodetect which interface the user wants, hence the
-		 * module parameter -- Arjan
-		 */
-
-	 	init.pitch_bits = init.h;
-	 	init.pitch = init.w;
-	 	init.h = init.overlay_physical;
-	 	init.w = init.overlay_offset;
-	 	init.overlay_physical = 0;
-	 	init.overlay_offset = 0;
-	}
 
    	switch(init.func) {
 	 	case I810_INIT_DMA:
@@ -532,16 +475,12 @@
 
 /* Most efficient way to verify state for the i810 is as it is
  * emitted.  Non-conformant state is silently dropped.
- *
- * Use 'volatile' & local var tmp to force the emitted values to be
- * identical to the verified ones.
  */
 static void i810EmitContextVerified( drm_device_t *dev,
-				     volatile unsigned int *code )
+				     unsigned int *code )
 {
    	drm_i810_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
-	unsigned int tmp;
 	RING_LOCALS;
 
 	BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
@@ -553,14 +492,13 @@
 	OUT_RING( code[I810_CTXREG_ST1] );
 
 	for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
-		tmp = code[i];
-
-		if ((tmp & (7<<29)) == (3<<29) &&
-		    (tmp & (0x1f<<24)) < (0x1d<<24))
+		if ((code[i] & (7<<29)) == (3<<29) &&
+		    (code[i] & (0x1f<<24)) < (0x1d<<24))
 		{
-			OUT_RING( tmp );
+			OUT_RING( code[i] );
 			j++;
 		}
+		else printk("constext state dropped!!!\n");
 	}
 
 	if (j & 1)
@@ -574,7 +512,6 @@
 {
    	drm_i810_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
-	unsigned int tmp;
 	RING_LOCALS;
 
 	BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
@@ -585,14 +522,14 @@
 	OUT_RING( code[I810_TEXREG_MI3] );
 
 	for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
-		tmp = code[i];
 
-		if ((tmp & (7<<29)) == (3<<29) &&
-		    (tmp & (0x1f<<24)) < (0x1d<<24))
+		if ((code[i] & (7<<29)) == (3<<29) &&
+		    (code[i] & (0x1f<<24)) < (0x1d<<24))
 		{
-			OUT_RING( tmp );
+			OUT_RING( code[i] );
 			j++;
 		}
+		else printk("texture state dropped!!!\n");
 	}
 
 	if (j & 1)
@@ -617,9 +554,9 @@
 	if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
 		OUT_RING( CMD_OP_DESTBUFFER_INFO );
 		OUT_RING( tmp );
-	} else
-	   DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
-		     tmp, dev_priv->front_di1, dev_priv->back_di1);
+	} 
+	else
+	   printk("buffer state dropped\n");
 
 	/* invarient:
 	 */
@@ -704,7 +641,6 @@
 			continue;
 
 	   	if ( flags & I810_FRONT ) {
-		   	DRM_DEBUG("clear front\n");
 			BEGIN_LP_RING( 6 );
 			OUT_RING( BR00_BITBLT_CLIENT |
 				  BR00_OP_COLOR_BLT | 0x3 );
@@ -717,7 +653,6 @@
 		}
 
 		if ( flags & I810_BACK ) {
-			DRM_DEBUG("clear back\n");
 			BEGIN_LP_RING( 6 );
 			OUT_RING( BR00_BITBLT_CLIENT |
 				  BR00_OP_COLOR_BLT | 0x3 );
@@ -730,7 +665,6 @@
 		}
 
 		if ( flags & I810_DEPTH ) {
-			DRM_DEBUG("clear depth\n");
 			BEGIN_LP_RING( 6 );
 			OUT_RING( BR00_BITBLT_CLIENT |
 				  BR00_OP_COLOR_BLT | 0x3 );
@@ -756,8 +690,6 @@
 	int i;
 	RING_LOCALS;
 
-	DRM_DEBUG("swapbuffers\n");
-
   	i810_kernel_lost_context(dev);
 
       	if (nbox > I810_NR_SAREA_CLIPRECTS)
@@ -776,10 +708,6 @@
 		    pbox->y2 > dev_priv->h)
 			continue;
 
-	   	DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
-			  pbox[i].x1, pbox[i].y1,
-			  pbox[i].x2, pbox[i].y2);
-
 		BEGIN_LP_RING( 6 );
 		OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
 		OUT_RING( pitch | (0xCC << 16));
@@ -804,7 +732,7 @@
    	int nbox = sarea_priv->nbox;
 	unsigned long address = (unsigned long)buf->bus_address;
 	unsigned long start = address - dev->agp->base;
-	int i = 0, u;
+	int i = 0;
    	RING_LOCALS;
 
    	i810_kernel_lost_context(dev);
@@ -812,33 +740,16 @@
    	if (nbox > I810_NR_SAREA_CLIPRECTS)
 		nbox = I810_NR_SAREA_CLIPRECTS;
 
-	if (discard) {
-		u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
-			    I810_BUF_HARDWARE);
-		if(u != I810_BUF_CLIENT) {
-			DRM_DEBUG("xxxx 2\n");
-		}
-	}
-
 	if (used > 4*1024)
 		used = 0;
 
 	if (sarea_priv->dirty)
 	   i810EmitState( dev );
 
-  	DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
-		  address, used, nbox);
-
-   	dev_priv->counter++;
-   	DRM_DEBUG(  "dispatch counter : %ld\n", dev_priv->counter);
-   	DRM_DEBUG(  "i810_dma_dispatch\n");
-   	DRM_DEBUG(  "start : %lx\n", start);
-	DRM_DEBUG(  "used : %d\n", used);
-   	DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
-
 	if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
-		*(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
-					     sarea_priv->vertex_prim |
+		unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
+
+		*(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | prim | 
 					     ((used/4)-2));
 
 		if (used & 4) {
@@ -871,154 +782,62 @@
 		} while (++i < nbox);
 	}
 
-	BEGIN_LP_RING(10);
-	OUT_RING( CMD_STORE_DWORD_IDX );
-	OUT_RING( 20 );
-	OUT_RING( dev_priv->counter );
-	OUT_RING( 0 );
-
 	if (discard) {
+		dev_priv->counter++;
+
+		(void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+			       I810_BUF_HARDWARE);
+
+		BEGIN_LP_RING(8);
+		OUT_RING( CMD_STORE_DWORD_IDX );
+		OUT_RING( 20 );
+		OUT_RING( dev_priv->counter );
 		OUT_RING( CMD_STORE_DWORD_IDX );
 		OUT_RING( buf_priv->my_use_idx );
 		OUT_RING( I810_BUF_FREE );
+		OUT_RING( CMD_REPORT_HEAD );
 		OUT_RING( 0 );
+		ADVANCE_LP_RING();
 	}
-
-      	OUT_RING( CMD_REPORT_HEAD );
-	OUT_RING( 0 );
-   	ADVANCE_LP_RING();
 }
 
 
-/* Interrupts are only for flushing */
-void i810_dma_service(int irq, void *device, struct pt_regs *regs)
-{
-	drm_device_t	 *dev = (drm_device_t *)device;
-      	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-   	u16 temp;
-
-	atomic_inc(&dev->counts[_DRM_STAT_IRQ]);
-      	temp = I810_READ16(I810REG_INT_IDENTITY_R);
-   	temp = temp & ~(0x6000);
-   	if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R,
-				   temp); /* Clear all interrupts */
-	else
-	   return;
-
-   	queue_task(&dev->tq, &tq_immediate);
-   	mark_bh(IMMEDIATE_BH);
-}
-
-void i810_dma_immediate_bh(void *device)
-{
-	drm_device_t *dev = (drm_device_t *) device;
-      	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-
-   	atomic_set(&dev_priv->flush_done, 1);
-   	wake_up_interruptible(&dev_priv->flush_queue);
-}
-
-static inline void i810_dma_emit_flush(drm_device_t *dev)
-{
-   	drm_i810_private_t *dev_priv = dev->dev_private;
-   	RING_LOCALS;
-
-   	i810_kernel_lost_context(dev);
-
-   	BEGIN_LP_RING(2);
-      	OUT_RING( CMD_REPORT_HEAD );
-      	OUT_RING( GFX_OP_USER_INTERRUPT );
-      	ADVANCE_LP_RING();
-
-/*  	i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
-/*     	atomic_set(&dev_priv->flush_done, 1); */
-/*     	wake_up_interruptible(&dev_priv->flush_queue); */
-}
-
-static inline void i810_dma_quiescent_emit(drm_device_t *dev)
+void i810_dma_quiescent(drm_device_t *dev)
 {
       	drm_i810_private_t *dev_priv = dev->dev_private;
    	RING_LOCALS;
 
+/*  	printk("%s\n", __FUNCTION__); */
+
   	i810_kernel_lost_context(dev);
 
    	BEGIN_LP_RING(4);
    	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
    	OUT_RING( CMD_REPORT_HEAD );
       	OUT_RING( 0 );
-      	OUT_RING( GFX_OP_USER_INTERRUPT );
+      	OUT_RING( 0 );
    	ADVANCE_LP_RING();
 
-/*  	i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
-/*     	atomic_set(&dev_priv->flush_done, 1); */
-/*     	wake_up_interruptible(&dev_priv->flush_queue); */
-}
-
-void i810_dma_quiescent(drm_device_t *dev)
-{
-      	DECLARE_WAITQUEUE(entry, current);
-  	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-	unsigned long end;
-
-   	if(dev_priv == NULL) {
-	   	return;
-	}
-      	atomic_set(&dev_priv->flush_done, 0);
-   	add_wait_queue(&dev_priv->flush_queue, &entry);
-   	end = jiffies + (HZ*3);
-
-   	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
-	      	i810_dma_quiescent_emit(dev);
-	   	if (atomic_read(&dev_priv->flush_done) == 1) break;
-		if((signed)(end - jiffies) <= 0) {
-		   	DRM_ERROR("lockup\n");
-		   	break;
-		}
-	      	schedule_timeout(HZ*3);
-	      	if (signal_pending(current)) {
-		   	break;
-		}
-	}
-
-   	current->state = TASK_RUNNING;
-   	remove_wait_queue(&dev_priv->flush_queue, &entry);
-
-   	return;
+	i810_wait_ring( dev, dev_priv->ring.Size - 8 );
 }
 
 static int i810_flush_queue(drm_device_t *dev)
 {
-   	DECLARE_WAITQUEUE(entry, current);
-  	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+   	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
-	unsigned long end;
    	int i, ret = 0;
+   	RING_LOCALS;
+	
+/*  	printk("%s\n", __FUNCTION__); */
 
-   	if(dev_priv == NULL) {
-	   	return 0;
-	}
-      	atomic_set(&dev_priv->flush_done, 0);
-   	add_wait_queue(&dev_priv->flush_queue, &entry);
-   	end = jiffies + (HZ*3);
-   	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
-	      	i810_dma_emit_flush(dev);
-	   	if (atomic_read(&dev_priv->flush_done) == 1) break;
-		if((signed)(end - jiffies) <= 0) {
-		   	DRM_ERROR("lockup\n");
-		   	break;
-		}
-	      	schedule_timeout(HZ*3);
-	      	if (signal_pending(current)) {
-		   	ret = -EINTR; /* Can't restart */
-		   	break;
-		}
-	}
+   	i810_kernel_lost_context(dev);
 
-   	current->state = TASK_RUNNING;
-   	remove_wait_queue(&dev_priv->flush_queue, &entry);
+   	BEGIN_LP_RING(2);
+      	OUT_RING( CMD_REPORT_HEAD );
+      	OUT_RING( 0 );
+      	ADVANCE_LP_RING();
 
+	i810_wait_ring( dev, dev_priv->ring.Size - 8 );
 
    	for (i = 0; i < dma->buf_count; i++) {
 	   	drm_buf_t *buf = dma->buflist[ i ];
@@ -1030,7 +849,7 @@
 		if (used == I810_BUF_HARDWARE)
 			DRM_DEBUG("reclaimed from HARDWARE\n");
 		if (used == I810_BUF_CLIENT)
-			DRM_DEBUG("still on client HARDWARE\n");
+			DRM_DEBUG("still on client\n");
 	}
 
    	return ret;
@@ -1070,7 +889,6 @@
    	drm_file_t	  *priv	  = filp->private_data;
    	drm_device_t	  *dev	  = priv->dev;
 
-   	DRM_DEBUG("i810_flush_ioctl\n");
    	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
 		DRM_ERROR("i810_flush_ioctl called without lock held\n");
 		return -EINVAL;
@@ -1101,9 +919,6 @@
 		return -EINVAL;
 	}
 
-	DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
-		  vertex.idx, vertex.used, vertex.discard);
-
 	if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
 
 	i810_dma_dispatch_vertex( dev,
@@ -1152,8 +967,6 @@
 	drm_file_t *priv = filp->private_data;
 	drm_device_t *dev = priv->dev;
 
-	DRM_DEBUG("i810_swap_bufs\n");
-
    	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
 		DRM_ERROR("i810_swap_buf called without lock held\n");
 		return -EINVAL;
@@ -1189,7 +1002,6 @@
    	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
      					dev_priv->sarea_priv;
 
-	DRM_DEBUG("getbuf\n");
    	if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d)))
 		return -EFAULT;
 
@@ -1202,9 +1014,6 @@
 
 	retcode = i810_dma_get_buffer(dev, &d, filp);
 
-	DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
-		  current->pid, retcode, d.granted);
-
 	if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
 		return -EFAULT;
    	sarea_priv->last_dispatch = (int) hw_status[5];
@@ -1212,47 +1021,19 @@
 	return retcode;
 }
 
-int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
+int i810_copybuf(struct inode *inode,
+		 struct file *filp, 
+		 unsigned int cmd,
+		 unsigned long arg)
 {
-	drm_file_t	  *priv	    = filp->private_data;
-	drm_device_t	  *dev	    = priv->dev;
-	drm_i810_copy_t	  d;
-   	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-   	u32 *hw_status = (u32 *)dev_priv->hw_status_page;
-   	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
-     					dev_priv->sarea_priv;
-	drm_buf_t *buf;
-	drm_i810_buf_priv_t *buf_priv;
-	drm_device_dma_t *dma = dev->dma;
-
-	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("i810_dma called without lock held\n");
-		return -EINVAL;
-	}
-
-   	if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d)))
-		return -EFAULT;
-
-        if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL;
-	buf = dma->buflist[ d.idx ];
-   	buf_priv = buf->dev_private;
-	if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM;
-
-	if(d.used < 0 || d.used > buf->total) return -EINVAL;
-
-   	if (copy_from_user(buf_priv->virtual, d.address, d.used))
-		return -EFAULT;
-
-   	sarea_priv->last_dispatch = (int) hw_status[5];
-
+	/* Never copy - 2.4.x doesn't need it */
 	return 0;
 }
 
 int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
-	if(VM_DONTCOPY == 0) return 1;
+	/* Never copy - 2.4.x doesn't need it */
 	return 0;
 }
 
@@ -1371,7 +1152,8 @@
 
 	data.offset = dev_priv->overlay_offset;
 	data.physical = dev_priv->overlay_physical;
-	copy_to_user((drm_i810_overlay_t *)arg,&data,sizeof(data));
+	if (copy_to_user((drm_i810_overlay_t *)arg,&data,sizeof(data)))
+		return -EFAULT;
 	return 0;
 }
 
diff -ruN drivers/char/drm-4.2/i810_drm.h drivers/char/drm/i810_drm.h
--- drivers/char/drm-4.2/i810_drm.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/i810_drm.h	2003-01-14 07:01:00.000000000 +0900
@@ -88,6 +88,8 @@
 #define I810_TEXREG_MCS  7	/* GFX_OP_MAP_COORD_SETS ??? */
 #define I810_TEX_SETUP_SIZE 8
 
+/* Flags for clear ioctl
+ */
 #define I810_FRONT   0x1
 #define I810_BACK    0x2
 #define I810_DEPTH   0x4
@@ -166,14 +168,34 @@
 
 } drm_i810_sarea_t;
 
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmMga.h)
+ */
+
+/* i810 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_IOCTL_I810_INIT		DRM_IOW( 0x40, drm_i810_init_t)
+#define DRM_IOCTL_I810_VERTEX		DRM_IOW( 0x41, drm_i810_vertex_t)
+#define DRM_IOCTL_I810_CLEAR		DRM_IOW( 0x42, drm_i810_clear_t)
+#define DRM_IOCTL_I810_FLUSH		DRM_IO(  0x43)
+#define DRM_IOCTL_I810_GETAGE		DRM_IO(  0x44)
+#define DRM_IOCTL_I810_GETBUF		DRM_IOWR(0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP		DRM_IO(  0x46)
+#define DRM_IOCTL_I810_COPY		DRM_IOW( 0x47, drm_i810_copy_t)
+#define DRM_IOCTL_I810_DOCOPY		DRM_IO(  0x48)
+#define DRM_IOCTL_I810_OV0INFO		DRM_IOR( 0x49, drm_i810_overlay_t)
+#define DRM_IOCTL_I810_FSTATUS		DRM_IO ( 0x4a)
+#define DRM_IOCTL_I810_OV0FLIP		DRM_IO ( 0x4b)
+#define DRM_IOCTL_I810_MC		DRM_IOW( 0x4c, drm_i810_mc_t)
+#define DRM_IOCTL_I810_RSTATUS		DRM_IO ( 0x4d )
+
 typedef struct _drm_i810_clear {
 	int clear_color;
 	int clear_depth;
 	int flags;
 } drm_i810_clear_t;
 
-
-
 /* These may be placeholders if we have more cliprects than
  * I810_NR_SAREA_CLIPRECTS.  In that case, the client sets discard to
  * false, indicating that the buffer will be dispatched again with a
@@ -191,6 +213,17 @@
 	void *address;		/* Address to copy from */
 } drm_i810_copy_t;
 
+#define PR_TRIANGLES         (0x0<<18)
+#define PR_TRISTRIP_0        (0x1<<18)
+#define PR_TRISTRIP_1        (0x2<<18)
+#define PR_TRIFAN            (0x3<<18)
+#define PR_POLYGON           (0x4<<18)
+#define PR_LINES             (0x5<<18)
+#define PR_LINESTRIP         (0x6<<18)
+#define PR_RECTS             (0x7<<18)
+#define PR_MASK              (0x7<<18)
+
+
 typedef struct drm_i810_dma {
 	void *virtual;
 	int request_idx;
diff -ruN drivers/char/drm-4.2/i810_drv.c drivers/char/drm/i810_drv.c
--- drivers/char/drm-4.2/i810_drv.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/i810_drv.c	2003-01-14 07:00:59.000000000 +0900
@@ -33,42 +33,10 @@
 #include <linux/config.h>
 #include "i810.h"
 #include "drmP.h"
+#include "drm.h"
+#include "i810_drm.h"
 #include "i810_drv.h"
 
-#define DRIVER_AUTHOR		"VA Linux Systems Inc."
-
-#define DRIVER_NAME		"i810"
-#define DRIVER_DESC		"Intel i810"
-#define DRIVER_DATE		"20010920"
-
-#define DRIVER_MAJOR		1
-#define DRIVER_MINOR		2	
-#define DRIVER_PATCHLEVEL	0
-
-#define DRIVER_IOCTLS							    \
-	[DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)]   = { i810_dma_init,    1, 1 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex,  1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I810_CLEAR)]  = { i810_clear_bufs,  1, 0 }, \
-      	[DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)]  = { i810_flush_ioctl, 1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage,      1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf,      1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)]   = { i810_swap_bufs,   1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I810_COPY)]   = { i810_copybuf,     1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy,      1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_I810_OV0INFO)] = { i810_ov0_info,   1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_I810_FSTATUS)] = { i810_fstatus,    1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_I810_OV0FLIP)] = { i810_ov0_flip,   1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_I810_MC)]      = { i810_dma_mc,     1, 1 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus,    1, 0 }
-
-
-#define __HAVE_COUNTERS         4
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-#define __HAVE_COUNTER9         _DRM_STAT_DMA
-
-
 #include "drm_agpsupport.h"
 #include "drm_auth.h"
 #include "drm_bufs.h"
@@ -77,25 +45,6 @@
 #include "drm_drawable.h"
 #include "drm_drv.h"
 
-#ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO).  It calls the insmod option
- * routine, drm_parse_drm.
- */
-
-/* JH- We have to hand expand the string ourselves because of the cpp.  If
- * anyone can think of a way that we can fit into the __setup macro without
- * changing it, then please send the solution my way.
- */
-static int __init i810_options( char *str )
-{
-	DRM(parse_options)( str );
-	return 1;
-}
-
-__setup( DRIVER_NAME "=", i810_options );
-#endif
-
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
diff -ruN drivers/char/drm-4.2/i810_drv.h drivers/char/drm/i810_drv.h
--- drivers/char/drm-4.2/i810_drv.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/i810_drv.h	2003-01-14 07:01:00.000000000 +0900
@@ -63,10 +63,9 @@
 
       	unsigned long hw_status_page;
    	unsigned long counter;
-   	dma_addr_t dma_status_page;
 
-   	atomic_t flush_done;
-   	wait_queue_head_t flush_queue;	/* Processes waiting until flush    */
+	dma_addr_t dma_status_page;
+
 	drm_buf_t *mmap_buffer;
 
 
@@ -78,6 +77,7 @@
 	int overlay_physical;
 	int w, h;
 	int pitch;
+
 } drm_i810_private_t;
 
 				/* i810_dma.c */
@@ -92,8 +92,13 @@
 extern int  i810_getage(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg);
 extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
+
+/* Obsolete:
+ */
 extern int i810_copybuf(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg);
+/* Obsolete:
+ */
 extern int i810_docopy(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg);
 
@@ -111,9 +116,6 @@
 
 extern void i810_dma_quiescent(drm_device_t *dev);
 
-#define I810_VERBOSE 0
-
-
 int i810_dma_vertex(struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg);
 
@@ -134,6 +136,33 @@
 #define I810_READ16(reg)	I810_DEREF16(reg)
 #define I810_WRITE16(reg,val)	do { I810_DEREF16(reg) = val; } while (0)
 
+#define I810_VERBOSE 0
+#define RING_LOCALS	unsigned int outring, ringmask; \
+                        volatile char *virt;
+
+#define BEGIN_LP_RING(n) do {						\
+	if (I810_VERBOSE)                                               \
+           DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__);	\
+	if (dev_priv->ring.space < n*4)					\
+		i810_wait_ring(dev, n*4);				\
+	dev_priv->ring.space -= n*4;					\
+	outring = dev_priv->ring.tail;					\
+	ringmask = dev_priv->ring.tail_mask;				\
+	virt = dev_priv->ring.virtual_start;				\
+} while (0)
+
+#define ADVANCE_LP_RING() do {				        \
+	if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n");    	\
+	dev_priv->ring.tail = outring;		        	\
+	I810_WRITE(LP_RING + RING_TAIL, outring);	        \
+} while(0)
+
+#define OUT_RING(n) do {  				                \
+	if (I810_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));	\
+	*(volatile unsigned int *)(virt + outring) = n;	                \
+	outring += 4;					                \
+	outring &= ringmask;			                        \
+} while (0)
 
 #define GFX_OP_USER_INTERRUPT 		((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
@@ -196,6 +225,7 @@
 
 #define CMD_OP_Z_BUFFER_INFO     ((0x0<<29)|(0x16<<23))
 #define CMD_OP_DESTBUFFER_INFO   ((0x0<<29)|(0x15<<23))
+#define CMD_OP_FRONTBUFFER_INFO  ((0x0<<29)|(0x14<<23))
 
 #define BR00_BITBLT_CLIENT   0x40000000
 #define BR00_OP_COLOR_BLT    0x10000000
diff -ruN drivers/char/drm-4.2/i830.h drivers/char/drm/i830.h
--- drivers/char/drm-4.2/i830.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/i830.h	2003-01-14 07:01:00.000000000 +0900
@@ -41,6 +41,48 @@
 #define __HAVE_MTRR		1
 #define __HAVE_CTX_BITMAP	1
 
+#define DRIVER_AUTHOR		"VA Linux Systems Inc."
+
+#define DRIVER_NAME		"i830"
+#define DRIVER_DESC		"Intel 830M"
+#define DRIVER_DATE		"20021108"
+
+/* Interface history:
+ *
+ * 1.1: Original.
+ * 1.2: ?
+ * 1.3: New irq emit/wait ioctls.
+ *      New pageflip ioctl.
+ *      New getparam ioctl.
+ *      State for texunits 3&4 in sarea.
+ *      New (alternative) layout for texture state.
+ */
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		3
+#define DRIVER_PATCHLEVEL	2
+
+#define DRIVER_IOCTLS							    \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)]   = { i830_dma_init,    1, 1 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex,  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)]  = { i830_clear_bufs,  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)]  = { i830_flush_ioctl, 1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage,      1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_GETBUF)] = { i830_getbuf,      1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)]   = { i830_swap_bufs,   1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)]   = { i830_copybuf,     1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy,      1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_FLIP)]   = { i830_flip_bufs,   1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_IRQ_EMIT)] = { i830_irq_emit,  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_IRQ_WAIT)] = { i830_irq_wait,  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_GETPARAM)] = { i830_getparam,  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I830_SETPARAM)] = { i830_setparam,  1, 0 } 
+
+#define __HAVE_COUNTERS         4
+#define __HAVE_COUNTER6         _DRM_STAT_IRQ
+#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
+#define __HAVE_COUNTER9         _DRM_STAT_DMA
+
 /* Driver customization:
  */
 #define __HAVE_RELEASE		1
@@ -60,51 +102,50 @@
 	i830_dma_quiescent( dev );					\
 } while (0)
 
+
+/* Driver will work either way: IRQ's save cpu time when waiting for
+ * the card, but are subject to subtle interactions between bios,
+ * hardware and the driver.
+ */
+#define USE_IRQS 0
+
+
+#if USE_IRQS
 #define __HAVE_DMA_IRQ		1
-#define __HAVE_DMA_IRQ_BH	1
-#define __HAVE_SHARED_IRQ       1
-#define DRIVER_PREINSTALL() do {					\
-	drm_i830_private_t *dev_priv =					\
-		(drm_i830_private_t *)dev->dev_private;			\
-	u16 tmp;							\
-   	tmp = I830_READ16( I830REG_HWSTAM );				\
-   	tmp = tmp & 0x6000;						\
-   	I830_WRITE16( I830REG_HWSTAM, tmp );				\
-									\
-      	tmp = I830_READ16( I830REG_INT_MASK_R );			\
-   	tmp = tmp & 0x6000;		/* Unmask interrupts */		\
-   	I830_WRITE16( I830REG_INT_MASK_R, tmp );			\
-   	tmp = I830_READ16( I830REG_INT_ENABLE_R );			\
-   	tmp = tmp & 0x6000;		/* Disable all interrupts */	\
-      	I830_WRITE16( I830REG_INT_ENABLE_R, tmp );			\
-} while (0)
+#define __HAVE_SHARED_IRQ	1
 
-#define DRIVER_POSTINSTALL() do {					\
-	drm_i830_private_t *dev_priv =					\
+#define DRIVER_PREINSTALL() do {			\
+	drm_i830_private_t *dev_priv =			\
 		(drm_i830_private_t *)dev->dev_private;	\
-	u16 tmp;							\
-   	tmp = I830_READ16( I830REG_INT_ENABLE_R );			\
-   	tmp = tmp & 0x6000;						\
-   	tmp = tmp | 0x0003;	/* Enable bp & user interrupts */	\
-   	I830_WRITE16( I830REG_INT_ENABLE_R, tmp );			\
+							\
+   	I830_WRITE16( I830REG_HWSTAM, 0xffff );	\
+        I830_WRITE16( I830REG_INT_MASK_R, 0x0 );	\
+      	I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );	\
 } while (0)
 
-#define DRIVER_UNINSTALL() do {						\
-	drm_i830_private_t *dev_priv =					\
-		(drm_i830_private_t *)dev->dev_private;			\
-	u16 tmp;							\
-	if ( dev_priv ) {						\
-		tmp = I830_READ16( I830REG_INT_IDENTITY_R );		\
-		tmp = tmp & ~(0x6000);	/* Clear all interrupts */	\
-		if ( tmp != 0 )						\
-			I830_WRITE16( I830REG_INT_IDENTITY_R, tmp );	\
-									\
-		tmp = I830_READ16( I830REG_INT_ENABLE_R );		\
-		tmp = tmp & 0x6000;	/* Disable all interrupts */	\
-		I830_WRITE16( I830REG_INT_ENABLE_R, tmp );		\
-	}								\
+
+#define DRIVER_POSTINSTALL() do {				\
+	drm_i830_private_t *dev_priv =				\
+		(drm_i830_private_t *)dev->dev_private;		\
+   	I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );		\
+   	atomic_set(&dev_priv->irq_received, 0);			\
+   	atomic_set(&dev_priv->irq_emitted, 0);			\
+	init_waitqueue_head(&dev_priv->irq_queue);		\
 } while (0)
 
+
+/* This gets called too late to be useful: dev_priv has already been
+ * freed.
+ */
+#define DRIVER_UNINSTALL() do {					\
+} while (0)
+
+#else
+#define __HAVE_DMA_IRQ          0
+#endif
+
+
+
 /* Buffer customization:
  */
 
diff -ruN drivers/char/drm-4.2/i830_dma.c drivers/char/drm/i830_dma.c
--- drivers/char/drm-4.2/i830_dma.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/i830_dma.c	2003-01-14 07:00:59.000000000 +0900
@@ -26,19 +26,25 @@
  *
  * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
  *	    Jeff Hartmann <jhartmann@valinux.com>
- *      Keith Whitwell <keithw@valinux.com>
- *      Abraham vd Merwe <abraham@2d3d.co.za>
+ *	    Keith Whitwell <keith@tungstengraphics.com>
+ *	    Abraham vd Merwe <abraham@2d3d.co.za>
  *
  */
 
+#define __NO_VERSION__
 #include "i830.h"
 #include "drmP.h"
+#include "drm.h"
+#include "i830_drm.h"
 #include "i830_drv.h"
 #include <linux/interrupt.h>	/* For task queue support */
+#include <linux/pagemap.h>     /* For FASTCALL on unlock_page() */
 #include <linux/delay.h>
-/* in case we don't have a 2.3.99-pre6 kernel or later: */
-#ifndef VM_DONTCOPY
-#define VM_DONTCOPY 0
+
+#ifdef DO_MUNMAP_4_ARGS
+#define DO_MUNMAP(m, a, l)	do_munmap(m, a, l, 1)
+#else
+#define DO_MUNMAP(m, a, l)	do_munmap(m, a, l)
 #endif
 
 #define I830_BUF_FREE		2
@@ -48,54 +54,24 @@
 #define I830_BUF_UNMAPPED 0
 #define I830_BUF_MAPPED   1
 
-#define RING_LOCALS	unsigned int outring, ringmask; volatile char *virt;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
+#define down_write down
+#define up_write up
+#endif
 
+#ifndef LockPage
+#define LockPage(page)		set_bit(PG_locked, &(page)->flags)
+#endif
+#ifndef UnlockPage
+#define UnlockPage(page)	unlock_page(page)
+#endif
 
-#define DO_IDLE_WORKAROUND()					\
-do {								\
-   int _head;							\
-   int _tail;							\
-   do { 							\
-      _head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;	\
-      _tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;	\
-      udelay(1);						\
-   } while(_head != _tail);					\
-} while(0)
-
-#define I830_SYNC_WORKAROUND 0
-
-#define BEGIN_LP_RING(n) do {				\
-	if (I830_VERBOSE)				\
-		DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n",	\
-			  n, __FUNCTION__);		\
-	if (I830_SYNC_WORKAROUND)			\
-		DO_IDLE_WORKAROUND();			\
-	if (dev_priv->ring.space < n*4) 		\
-		i830_wait_ring(dev, n*4);		\
-	dev_priv->ring.space -= n*4;			\
-	outring = dev_priv->ring.tail;			\
-	ringmask = dev_priv->ring.tail_mask;		\
-	virt = dev_priv->ring.virtual_start;		\
-} while (0)
-
-#define ADVANCE_LP_RING() do {					\
-	if (I830_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n");	\
-	dev_priv->ring.tail = outring;				\
-	I830_WRITE(LP_RING + RING_TAIL, outring);		\
-} while(0)
-
-#define OUT_RING(n) do {						\
-	if (I830_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));	\
-	*(volatile unsigned int *)(virt + outring) = n;			\
-	outring += 4;							\
-	outring &= ringmask;						\
-} while (0);
 
 static inline void i830_print_status_page(drm_device_t *dev)
 {
    	drm_device_dma_t *dma = dev->dma;
       	drm_i830_private_t *dev_priv = dev->dev_private;
-	u8 *temp = dev_priv->hw_status_page;
+	u32 *temp = (u32 *)dev_priv->hw_status_page;
    	int i;
 
    	DRM_DEBUG(  "hw_status: Interrupt Status : %x\n", temp[0]);
@@ -149,14 +125,14 @@
 }
 
 static struct file_operations i830_buffer_fops = {
-	open:	 DRM(open),
-	flush:	 DRM(flush),
-	release: DRM(release),
-	ioctl:	 DRM(ioctl),
-	mmap:	 i830_mmap_buffers,
-	read:	 DRM(read),
-	fasync:	 DRM(fasync),
-      	poll:	 DRM(poll),
+	.open	 = DRM(open),
+	.flush	 = DRM(flush),
+	.release = DRM(release),
+	.ioctl	 = DRM(ioctl),
+	.mmap	 = i830_mmap_buffers,
+	.read	 = DRM(read),
+	.fasync	 = DRM(fasync),
+      	.poll	 = DRM(poll),
 };
 
 int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
@@ -179,7 +155,7 @@
    	buf_priv->currently_mapped = I830_BUF_MAPPED;
 	unlock_kernel();
 
-	if (remap_page_range(vma->vm_start,
+	if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
 			     VM_OFFSET(vma),
 			     vma->vm_end - vma->vm_start,
 			     vma->vm_page_prot)) return -EAGAIN;
@@ -197,28 +173,24 @@
 
 	if(buf_priv->currently_mapped == I830_BUF_MAPPED) return -EINVAL;
 
-	if(VM_DONTCOPY != 0) {
-		down_write( &current->mm->mmap_sem );
-		old_fops = filp->f_op;
-		filp->f_op = &i830_buffer_fops;
-		dev_priv->mmap_buffer = buf;
-		buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, 
-						    PROT_READ|PROT_WRITE,
-						    MAP_SHARED, 
-						    buf->bus_address);
-		dev_priv->mmap_buffer = NULL;
-   		filp->f_op = old_fops;
-		if ((unsigned long)buf_priv->virtual > -1024UL) {
-			/* Real error */
-			DRM_DEBUG("mmap error\n");
-			retcode = (signed int)buf_priv->virtual;
-			buf_priv->virtual = 0;
-		}
-		up_write( &current->mm->mmap_sem );
-	} else {
-		buf_priv->virtual = buf_priv->kernel_virtual;
-   		buf_priv->currently_mapped = I830_BUF_MAPPED;
+	down_write( &current->mm->mmap_sem );
+	old_fops = filp->f_op;
+	filp->f_op = &i830_buffer_fops;
+	dev_priv->mmap_buffer = buf;
+	buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, 
+					    PROT_READ|PROT_WRITE,
+					    MAP_SHARED, 
+					    buf->bus_address);
+	dev_priv->mmap_buffer = NULL;
+	filp->f_op = old_fops;
+	if ((unsigned long)buf_priv->virtual > -1024UL) {
+		/* Real error */
+		DRM_ERROR("mmap error\n");
+		retcode = (signed int)buf_priv->virtual;
+		buf_priv->virtual = 0;
 	}
+	up_write( &current->mm->mmap_sem );
+
 	return retcode;
 }
 
@@ -227,15 +199,15 @@
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	int retcode = 0;
 
-	if(VM_DONTCOPY != 0) {
-		if(buf_priv->currently_mapped != I830_BUF_MAPPED) 
-			return -EINVAL;
-		down_write( &current->mm->mmap_sem );
-        	retcode = do_munmap(current->mm, 
-				    (unsigned long)buf_priv->virtual, 
-				    (size_t) buf->total);
-   		up_write( &current->mm->mmap_sem );
-	}
+	if(buf_priv->currently_mapped != I830_BUF_MAPPED) 
+		return -EINVAL;
+
+	down_write(&current->mm->mmap_sem);
+	retcode = DO_MUNMAP(current->mm,
+			    (unsigned long)buf_priv->virtual,
+			    (size_t) buf->total);
+	up_write(&current->mm->mmap_sem);
+
    	buf_priv->currently_mapped = I830_BUF_UNMAPPED;
    	buf_priv->virtual = 0;
 
@@ -260,7 +232,7 @@
 	retcode = i830_map_buffer(buf, filp);
 	if(retcode) {
 		i830_freelist_put(dev, buf);
-	   	DRM_DEBUG("mapbuf failed, retcode %d\n", retcode);
+	   	DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
 		return retcode;
 	}
 	buf->pid     = priv->pid;
@@ -286,12 +258,22 @@
 		   	DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
 					 dev_priv->ring.Size);
 		}
-	   	if(dev_priv->hw_status_page != NULL) {
-	   		pci_free_consistent(dev->pdev, PAGE_SIZE, 
-	   		    dev_priv->hw_status_page, dev_priv->dma_status_page);
+	   	if(dev_priv->hw_status_page != 0UL) {
+			pci_free_consistent(dev->pdev, PAGE_SIZE,
+					    (void *)dev_priv->hw_status_page,
+					    dev_priv->dma_status_page);
 		   	/* Need to rewrite hardware status page */
 		   	I830_WRITE(0x02080, 0x1ffff000);
 		}
+
+		/* Disable interrupts here because after dev_private
+		 * is freed, it's too late.
+		 */
+		if (dev->irq) {
+			I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
+			I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
+		}
+
 	   	DRM(free)(dev->dev_private, sizeof(drm_i830_private_t), 
 			 DRM_MEM_DRIVER);
 	   	dev->dev_private = NULL;
@@ -305,7 +287,7 @@
    	return 0;
 }
 
-static int i830_wait_ring(drm_device_t *dev, int n)
+int i830_wait_ring(drm_device_t *dev, int n, const char *caller)
 {
    	drm_i830_private_t *dev_priv = dev->dev_private;
    	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -314,7 +296,7 @@
 	unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 
 	end = jiffies + (HZ*3);
-   	while (ring->space < n) {
+   	while (ring->space < n) {	
 	   	ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 	   	ring->space = ring->head - (ring->tail+8);
 		if (ring->space < 0) ring->space += ring->Size;
@@ -325,13 +307,13 @@
 		}
 	  
 	   	iters++;
-		if(time_before(end,jiffies)) {
+		if(time_before(end, jiffies)) {
 		   	DRM_ERROR("space: %d wanted %d\n", ring->space, n);
 		   	DRM_ERROR("lockup\n");
 		   	goto out_wait_ring;
 		}
-
-	   	udelay(1);
+		udelay(1);
+		dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
 	}
 
 out_wait_ring:   
@@ -344,9 +326,12 @@
    	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
       
    	ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-     	ring->tail = I830_READ(LP_RING + RING_TAIL);
+     	ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
      	ring->space = ring->head - (ring->tail+8);
      	if (ring->space < 0) ring->space += ring->Size;
+
+	if (ring->head == ring->tail)
+		dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
 }
 
 static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv)
@@ -420,9 +405,6 @@
 		((u8 *)dev_priv->sarea_map->handle +
 		 init->sarea_priv_offset);
 
-   	atomic_set(&dev_priv->flush_done, 0);
-	init_waitqueue_head(&dev_priv->flush_queue);
-
    	dev_priv->ring.Start = init->ring_start;
    	dev_priv->ring.End = init->ring_end;
    	dev_priv->ring.Size = init->ring_size;
@@ -446,11 +428,17 @@
 	dev_priv->pitch = init->pitch;
 	dev_priv->back_offset = init->back_offset;
 	dev_priv->depth_offset = init->depth_offset;
+	dev_priv->front_offset = init->front_offset;
 
 	dev_priv->front_di1 = init->front_offset | init->pitch_bits;
 	dev_priv->back_di1 = init->back_offset | init->pitch_bits;
 	dev_priv->zi1 = init->depth_offset | init->pitch_bits;
 
+	DRM_DEBUG("front_di1 %x\n",    dev_priv->front_di1);
+	DRM_DEBUG("back_offset %x\n", dev_priv->back_offset);
+	DRM_DEBUG("back_di1 %x\n",    dev_priv->back_di1);
+	DRM_DEBUG("pitch_bits %x\n",    init->pitch_bits);
+
 	dev_priv->cpp = init->cpp;
 	/* We are using seperate values as placeholders for mechanisms for
 	 * private backbuffer/depthbuffer usage.
@@ -458,20 +446,23 @@
 
 	dev_priv->back_pitch = init->back_pitch;
 	dev_priv->depth_pitch = init->depth_pitch;
+	dev_priv->do_boxes = 0;
+	dev_priv->use_mi_batchbuffer_start = 0;
 
    	/* Program Hardware Status Page */
-   	dev_priv->hw_status_page = pci_alloc_consistent(dev->pdev, PAGE_SIZE, 
+   	dev_priv->hw_status_page =
+		(unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE,
 						&dev_priv->dma_status_page);
-   	if(dev_priv->hw_status_page == NULL) {
+   	if(dev_priv->hw_status_page == 0UL) {
 		dev->dev_private = (void *)dev_priv;
 		i830_dma_cleanup(dev);
 		DRM_ERROR("Can not allocate hardware status page\n");
 		return -ENOMEM;
 	}
-   	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+   	memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
+	DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
    
-   	I830_WRITE(0x02080, dev_priv->dma_status_page);
+   	I830_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
 	DRM_DEBUG("Enabled hardware status page\n");
    
    	/* Now we need to init our freelist */
@@ -517,83 +508,107 @@
    	return retcode;
 }
 
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define ST1_ENABLE               (1<<16)
+#define ST1_MASK                 (0xffff)
+
 /* Most efficient way to verify state for the i830 is as it is
  * emitted.  Non-conformant state is silently dropped.
- *
- * Use 'volatile' & local var tmp to force the emitted values to be
- * identical to the verified ones.
  */
-static void i830EmitContextVerified( drm_device_t *dev, 
-				     volatile unsigned int *code )
+static void i830EmitContextVerified( drm_device_t *dev,
+				     unsigned int *code )
 {
    	drm_i830_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	unsigned int tmp;
 	RING_LOCALS;
 
-	BEGIN_LP_RING( I830_CTX_SETUP_SIZE );
-	for ( i = 0 ; i < I830_CTX_SETUP_SIZE ; i++ ) {
+	BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 4 );
+
+	for ( i = 0 ; i < I830_CTXREG_BLENDCOLR0 ; i++ ) {
 		tmp = code[i];
+		if ((tmp & (7<<29)) == CMD_3D &&
+		    (tmp & (0x1f<<24)) < (0x1d<<24)) {
+			OUT_RING( tmp ); 
+			j++;
+		} else {
+			DRM_ERROR("Skipping %d\n", i);
+		}
+	}
 
-#if 0
-		if ((tmp & (7<<29)) == (3<<29) &&
+	OUT_RING( STATE3D_CONST_BLEND_COLOR_CMD ); 
+	OUT_RING( code[I830_CTXREG_BLENDCOLR] ); 
+	j += 2;
+
+	for ( i = I830_CTXREG_VF ; i < I830_CTXREG_MCSB0 ; i++ ) {
+		tmp = code[i];
+		if ((tmp & (7<<29)) == CMD_3D &&
 		    (tmp & (0x1f<<24)) < (0x1d<<24)) {
 			OUT_RING( tmp ); 
 			j++;
 		} else {
-			printk("Skipping %d\n", i);
+			DRM_ERROR("Skipping %d\n", i);
 		}
-#else
-		OUT_RING( tmp ); 
-		j++;
-#endif
 	}
 
+	OUT_RING( STATE3D_MAP_COORD_SETBIND_CMD ); 
+	OUT_RING( code[I830_CTXREG_MCSB1] ); 
+	j += 2;
+
 	if (j & 1) 
 		OUT_RING( 0 ); 
 
 	ADVANCE_LP_RING();
 }
 
-static void i830EmitTexVerified( drm_device_t *dev, 
-				 volatile unsigned int *code ) 
+static void i830EmitTexVerified( drm_device_t *dev, unsigned int *code ) 
 {
    	drm_i830_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	unsigned int tmp;
 	RING_LOCALS;
 
-	BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
-
-	OUT_RING( GFX_OP_MAP_INFO );
-	OUT_RING( code[I830_TEXREG_MI1] );
-	OUT_RING( code[I830_TEXREG_MI2] );
-	OUT_RING( code[I830_TEXREG_MI3] );
-	OUT_RING( code[I830_TEXREG_MI4] );
-	OUT_RING( code[I830_TEXREG_MI5] );
-
-	for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
-		tmp = code[i];
-		OUT_RING( tmp ); 
-		j++;
-	} 
+	if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
+	    (code[I830_TEXREG_MI0] & ~(0xf*LOAD_TEXTURE_MAP0)) == 
+	    (STATE3D_LOAD_STATE_IMMEDIATE_2|4)) {
+
+		BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
+
+		OUT_RING( code[I830_TEXREG_MI0] ); /* TM0LI */
+		OUT_RING( code[I830_TEXREG_MI1] ); /* TM0S0 */
+		OUT_RING( code[I830_TEXREG_MI2] ); /* TM0S1 */
+		OUT_RING( code[I830_TEXREG_MI3] ); /* TM0S2 */
+		OUT_RING( code[I830_TEXREG_MI4] ); /* TM0S3 */
+		OUT_RING( code[I830_TEXREG_MI5] ); /* TM0S4 */
+		
+		for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
+			tmp = code[i];
+			OUT_RING( tmp ); 
+			j++;
+		} 
 
-	if (j & 1) 
-		OUT_RING( 0 ); 
+		if (j & 1) 
+			OUT_RING( 0 ); 
 
-	ADVANCE_LP_RING();
+		ADVANCE_LP_RING();
+	}
+	else
+		printk("rejected packet %x\n", code[0]);
 }
 
 static void i830EmitTexBlendVerified( drm_device_t *dev, 
-				     volatile unsigned int *code,
-				     volatile unsigned int num)
+				      unsigned int *code,
+				      unsigned int num)
 {
    	drm_i830_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	unsigned int tmp;
 	RING_LOCALS;
 
-	BEGIN_LP_RING( num );
+	if (!num)
+		return;
+
+	BEGIN_LP_RING( num + 1 );
 
 	for ( i = 0 ; i < num ; i++ ) {
 		tmp = code[i];
@@ -616,6 +631,8 @@
 	int i;
 	RING_LOCALS;
 
+	return;
+
 	BEGIN_LP_RING( 258 );
 
 	if(is_shared == 1) {
@@ -629,44 +646,43 @@
 		OUT_RING(palette[i]);
 	}
 	OUT_RING(0);
+	/* KW:  WHERE IS THE ADVANCE_LP_RING?  This is effectively a noop! 
+	 */
 }
 
 /* Need to do some additional checking when setting the dest buffer.
  */
 static void i830EmitDestVerified( drm_device_t *dev, 
-				  volatile unsigned int *code ) 
+				  unsigned int *code ) 
 {	
    	drm_i830_private_t *dev_priv = dev->dev_private;
 	unsigned int tmp;
 	RING_LOCALS;
 
-	BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 6 );
+	BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 10 );
+
 
 	tmp = code[I830_DESTREG_CBUFADDR];
-	if (tmp == dev_priv->front_di1) {
-		/* Don't use fence when front buffer rendering */
-		OUT_RING( CMD_OP_DESTBUFFER_INFO );
-		OUT_RING( BUF_3D_ID_COLOR_BACK | 
-			  BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) );
-		OUT_RING( tmp );
+	if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
+		if (((int)outring) & 8) {
+			OUT_RING(0);
+			OUT_RING(0);
+		}
 
 		OUT_RING( CMD_OP_DESTBUFFER_INFO );
-		OUT_RING( BUF_3D_ID_DEPTH |
-			  BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
-		OUT_RING( dev_priv->zi1 );
-	} else if(tmp == dev_priv->back_di1) {
-		OUT_RING( CMD_OP_DESTBUFFER_INFO );
 		OUT_RING( BUF_3D_ID_COLOR_BACK | 
 			  BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
 			  BUF_3D_USE_FENCE);
 		OUT_RING( tmp );
+		OUT_RING( 0 );
 
 		OUT_RING( CMD_OP_DESTBUFFER_INFO );
 		OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE | 
 			  BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
 		OUT_RING( dev_priv->zi1 );
+		OUT_RING( 0 );
 	} else {
-		DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
+		DRM_ERROR("bad di1 %x (allow %x or %x)\n",
 			  tmp, dev_priv->front_di1, dev_priv->back_di1);
 	}
 
@@ -688,25 +704,39 @@
 	if((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
 		OUT_RING( tmp );
 	} else {
-		DRM_DEBUG("bad scissor enable\n");
+		DRM_ERROR("bad scissor enable\n");
 		OUT_RING( 0 );
 	}
 
-	OUT_RING( code[I830_DESTREG_SENABLE] );
-
 	OUT_RING( GFX_OP_SCISSOR_RECT );
 	OUT_RING( code[I830_DESTREG_SR1] );
 	OUT_RING( code[I830_DESTREG_SR2] );
+	OUT_RING( 0 );
 
 	ADVANCE_LP_RING();
 }
 
+static void i830EmitStippleVerified( drm_device_t *dev, 
+				     unsigned int *code ) 
+{
+   	drm_i830_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	BEGIN_LP_RING( 2 );
+	OUT_RING( GFX_OP_STIPPLE );
+	OUT_RING( code[1] );
+	ADVANCE_LP_RING();	
+}
+
+
 static void i830EmitState( drm_device_t *dev )
 {
    	drm_i830_private_t *dev_priv = dev->dev_private;
       	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int dirty = sarea_priv->dirty;
 
+	DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
+
 	if (dirty & I830_UPLOAD_BUFFERS) {
 		i830EmitDestVerified( dev, sarea_priv->BufferState );
 		sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
@@ -740,17 +770,154 @@
 	}
 
 	if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
-	   i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
+		i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
+	} else {
+		if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
+			i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
+			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
+		}
+		if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
+			i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
+			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
+		}
+
+		/* 1.3:
+		 */
+#if 0
+		if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) {
+			i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0);
+			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
+		}
+		if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) {
+			i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0);
+			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
+		}
+#endif
+	}
+
+	/* 1.3:
+	 */
+	if (dirty & I830_UPLOAD_STIPPLE) {
+		i830EmitStippleVerified( dev, 
+					 sarea_priv->StippleState);
+		sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
+	}
+
+	if (dirty & I830_UPLOAD_TEX2) {
+		i830EmitTexVerified( dev, sarea_priv->TexState2 );
+		sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
+	}
+
+	if (dirty & I830_UPLOAD_TEX3) {
+		i830EmitTexVerified( dev, sarea_priv->TexState3 );
+		sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
+	}
+
+
+	if (dirty & I830_UPLOAD_TEXBLEND2) {
+		i830EmitTexBlendVerified( 
+			dev, 
+			sarea_priv->TexBlendState2,
+			sarea_priv->TexBlendStateWordsUsed2);
+
+		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
+	}
+
+	if (dirty & I830_UPLOAD_TEXBLEND3) {
+		i830EmitTexBlendVerified( 
+			dev, 
+			sarea_priv->TexBlendState3,
+			sarea_priv->TexBlendStateWordsUsed3);
+		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
+	}
+}
+
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void i830_fill_box( drm_device_t *dev,
+			   int x, int y, int w, int h,
+			   int r, int g, int b )
+{
+   	drm_i830_private_t *dev_priv = dev->dev_private;
+	u32 color;
+	unsigned int BR13, CMD;
+	RING_LOCALS;
+
+	BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1<<24);
+	CMD = XY_COLOR_BLT_CMD;
+	x += dev_priv->sarea_priv->boxes[0].x1;
+	y += dev_priv->sarea_priv->boxes[0].y1;
+
+	if (dev_priv->cpp == 4) {
+		BR13 |= (1<<25);
+		CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
+		color = (((0xff) << 24) | (r << 16) | (g <<  8) | b);	
 	} else {
-	   if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
-	      i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
-	      sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
-	   }
-	   if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
-	      i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
-	      sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
-	   }
+		color = (((r & 0xf8) << 8) |
+			 ((g & 0xfc) << 3) |
+			 ((b & 0xf8) >> 3));
+	}
+
+	BEGIN_LP_RING( 6 );	    
+	OUT_RING( CMD );
+	OUT_RING( BR13 );
+	OUT_RING( (y << 16) | x );
+	OUT_RING( ((y+h) << 16) | (x+w) );
+
+ 	if ( dev_priv->current_page == 1 ) { 
+		OUT_RING( dev_priv->front_offset );
+ 	} else {	 
+		OUT_RING( dev_priv->back_offset );
+ 	} 
+
+	OUT_RING( color );
+	ADVANCE_LP_RING();
+}
+
+static void i830_cp_performance_boxes( drm_device_t *dev )
+{
+   	drm_i830_private_t *dev_priv = dev->dev_private;
+
+	/* Purple box for page flipping
+	 */
+	if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP ) 
+		i830_fill_box( dev, 4, 4, 8, 8, 255, 0, 255 );
+
+	/* Red box if we have to wait for idle at any point
+	 */
+	if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT ) 
+		i830_fill_box( dev, 16, 4, 8, 8, 255, 0, 0 );
+
+	/* Blue box: lost context?
+	 */
+	if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT ) 
+		i830_fill_box( dev, 28, 4, 8, 8, 0, 0, 255 );
+
+	/* Yellow box for texture swaps
+	 */
+	if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD ) 
+		i830_fill_box( dev, 40, 4, 8, 8, 255, 255, 0 );
+
+	/* Green box if hardware never idles (as far as we can tell)
+	 */
+	if ( !(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY) ) 
+		i830_fill_box( dev, 64, 4, 8, 8, 0, 255, 0 );
+
+
+	/* Draw bars indicating number of buffers allocated 
+	 * (not a great measure, easily confused)
+	 */
+	if (dev_priv->dma_used) {
+		int bar = dev_priv->dma_used / 10240;
+		if (bar > 100) bar = 100;
+		if (bar < 1) bar = 1;
+		i830_fill_box( dev, 4, 16, bar, 4, 196, 128, 128 );
+		dev_priv->dma_used = 0;
 	}
+
+	dev_priv->sarea_priv->perf_boxes = 0;
 }
 
 static void i830_dma_dispatch_clear( drm_device_t *dev, int flags, 
@@ -768,6 +935,15 @@
 	unsigned int BR13, CMD, D_CMD;
 	RING_LOCALS;
 
+
+	if ( dev_priv->current_page == 1 ) {
+		unsigned int tmp = flags;
+
+		flags &= ~(I830_FRONT | I830_BACK);
+		if ( tmp & I830_FRONT ) flags |= I830_BACK;
+		if ( tmp & I830_BACK )  flags |= I830_FRONT;
+	}
+
   	i830_kernel_lost_context(dev);
 
 	switch(cpp) {
@@ -808,7 +984,7 @@
 			OUT_RING( BR13 );
 			OUT_RING( (pbox->y1 << 16) | pbox->x1 );
 			OUT_RING( (pbox->y2 << 16) | pbox->x2 );
-			OUT_RING( 0 );
+			OUT_RING( dev_priv->front_offset );
 			OUT_RING( clear_color );
 			ADVANCE_LP_RING();
 		}
@@ -847,13 +1023,17 @@
 	drm_clip_rect_t *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = dev_priv->cpp;
-	int ofs = dev_priv->back_offset;
 	int i;
 	unsigned int CMD, BR13;
 	RING_LOCALS;
 
 	DRM_DEBUG("swapbuffers\n");
 
+  	i830_kernel_lost_context(dev);
+
+	if (dev_priv->do_boxes)
+		i830_cp_performance_boxes( dev );
+
 	switch(cpp) {
 	case 2: 
 		BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
@@ -870,7 +1050,6 @@
 		break;
 	}
 
-  	i830_kernel_lost_context(dev);
 
       	if (nbox > I830_NR_SAREA_CLIPRECTS)
      		nbox = I830_NR_SAREA_CLIPRECTS;
@@ -890,23 +1069,72 @@
 		BEGIN_LP_RING( 8 );
 		OUT_RING( CMD );
 		OUT_RING( BR13 );
+		OUT_RING( (pbox->y1 << 16) | pbox->x1 );
+		OUT_RING( (pbox->y2 << 16) | pbox->x2 );
 
-		OUT_RING( (pbox->y1 << 16) |
-			  pbox->x1 );
-		OUT_RING( (pbox->y2 << 16) |
-			  pbox->x2 );
-
-		OUT_RING( 0 /* front ofs always zero */ );
-		OUT_RING( (pbox->y1 << 16) |
-			  pbox->x1 );
+		if (dev_priv->current_page == 0) 
+			OUT_RING( dev_priv->front_offset );
+		else
+			OUT_RING( dev_priv->back_offset );			
 
+		OUT_RING( (pbox->y1 << 16) | pbox->x1 );
 		OUT_RING( BR13 & 0xffff );
-		OUT_RING( ofs );
+
+		if (dev_priv->current_page == 0) 
+			OUT_RING( dev_priv->back_offset );			
+		else
+			OUT_RING( dev_priv->front_offset );
 
 		ADVANCE_LP_RING();
 	}
 }
 
+static void i830_dma_dispatch_flip( drm_device_t *dev )
+{
+   	drm_i830_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", 
+		   __FUNCTION__, 
+		   dev_priv->current_page,
+		   dev_priv->sarea_priv->pf_current_page);
+
+  	i830_kernel_lost_context(dev);
+
+	if (dev_priv->do_boxes) {
+		dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
+		i830_cp_performance_boxes( dev );
+	}
+
+
+	BEGIN_LP_RING( 2 );
+    	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); 
+	OUT_RING( 0 );
+	ADVANCE_LP_RING();
+
+	BEGIN_LP_RING( 6 );
+	OUT_RING( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP );	
+	OUT_RING( 0 );
+	if ( dev_priv->current_page == 0 ) {
+		OUT_RING( dev_priv->back_offset );
+		dev_priv->current_page = 1;
+	} else {
+		OUT_RING( dev_priv->front_offset );
+		dev_priv->current_page = 0;
+	}
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+
+	BEGIN_LP_RING( 2 );
+	OUT_RING( MI_WAIT_FOR_EVENT |
+		  MI_WAIT_FOR_PLANE_A_FLIP );
+	OUT_RING( 0 );
+	ADVANCE_LP_RING();
+	
+
+	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+}
 
 static void i830_dma_dispatch_vertex(drm_device_t *dev, 
 				     drm_buf_t *buf,
@@ -936,7 +1164,7 @@
 		}
 	}
 
-	if (used > 4*1024) 
+	if (used > 4*1023) 
 		used = 0;
 
 	if (sarea_priv->dirty)
@@ -953,12 +1181,19 @@
    	DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
 
 	if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
-		*(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
-					     sarea_priv->vertex_prim |
-					     ((used/4)-2));
+		u32 *vp = buf_priv->virtual;
+
+		vp[0] = (GFX_OP_PRIMITIVE |
+			 sarea_priv->vertex_prim |
+			 ((used/4)-2));
+
+		if (dev_priv->use_mi_batchbuffer_start) {
+			vp[used/4] = MI_BATCH_BUFFER_END; 
+			used += 4; 
+		}
 		
 		if (used & 4) {
-			*(u32 *)((u32)buf_priv->virtual + used) = 0;
+			vp[used/4] = 0;
 			used += 4;
 		}
 
@@ -978,80 +1213,45 @@
 				ADVANCE_LP_RING();
 			}
 
-			BEGIN_LP_RING(4);
+			if (dev_priv->use_mi_batchbuffer_start) {
+				BEGIN_LP_RING(2);
+				OUT_RING( MI_BATCH_BUFFER_START | (2<<6) );
+				OUT_RING( start | MI_BATCH_NON_SECURE );
+				ADVANCE_LP_RING();
+			} 
+			else {
+				BEGIN_LP_RING(4);
+				OUT_RING( MI_BATCH_BUFFER );
+				OUT_RING( start | MI_BATCH_NON_SECURE );
+				OUT_RING( start + used - 4 );
+				OUT_RING( 0 );
+				ADVANCE_LP_RING();
+			}
 
-			OUT_RING( MI_BATCH_BUFFER );
-			OUT_RING( start | MI_BATCH_NON_SECURE );
-			OUT_RING( start + used - 4 );
-			OUT_RING( 0 );
-			ADVANCE_LP_RING();
-			
 		} while (++i < nbox);
 	}
 
-	BEGIN_LP_RING(10);
-	OUT_RING( CMD_STORE_DWORD_IDX );
-	OUT_RING( 20 );
-	OUT_RING( dev_priv->counter );
-	OUT_RING( 0 );
-
 	if (discard) {
+		dev_priv->counter++;
+
+		(void) cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+			       I830_BUF_HARDWARE);
+
+		BEGIN_LP_RING(8);
+		OUT_RING( CMD_STORE_DWORD_IDX );
+		OUT_RING( 20 );
+		OUT_RING( dev_priv->counter );
 		OUT_RING( CMD_STORE_DWORD_IDX );
 		OUT_RING( buf_priv->my_use_idx );
 		OUT_RING( I830_BUF_FREE );
+		OUT_RING( CMD_REPORT_HEAD );
 		OUT_RING( 0 );
+		ADVANCE_LP_RING();
 	}
-
-      	OUT_RING( CMD_REPORT_HEAD );
-	OUT_RING( 0 );
-   	ADVANCE_LP_RING();
-}
-
-/* Interrupts are only for flushing */
-void i830_dma_service(int irq, void *device, struct pt_regs *regs)
-{
-	drm_device_t	 *dev = (drm_device_t *)device;
-      	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
-   	u16 temp;
-   
-      	temp = I830_READ16(I830REG_INT_IDENTITY_R);
-   	temp = temp & ~(0x6000);
-   	if(temp != 0) I830_WRITE16(I830REG_INT_IDENTITY_R, 
-				   temp); /* Clear all interrupts */
-	else
-	   return;
- 
-   	queue_task(&dev->tq, &tq_immediate);
-   	mark_bh(IMMEDIATE_BH);
 }
 
-void DRM(dma_immediate_bh)(void *device)
-{
-	drm_device_t *dev = (drm_device_t *) device;
-      	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
-
-   	atomic_set(&dev_priv->flush_done, 1);
-   	wake_up_interruptible(&dev_priv->flush_queue);
-}
-
-static inline void i830_dma_emit_flush(drm_device_t *dev)
-{
-   	drm_i830_private_t *dev_priv = dev->dev_private;
-   	RING_LOCALS;
-
-   	i830_kernel_lost_context(dev);
-
-   	BEGIN_LP_RING(2);
-      	OUT_RING( CMD_REPORT_HEAD );
-      	OUT_RING( GFX_OP_USER_INTERRUPT );
-      	ADVANCE_LP_RING();
-
-	i830_wait_ring( dev, dev_priv->ring.Size - 8 );
-	atomic_set(&dev_priv->flush_done, 1);
-	wake_up_interruptible(&dev_priv->flush_queue);
-}
 
-static inline void i830_dma_quiescent_emit(drm_device_t *dev)
+void i830_dma_quiescent(drm_device_t *dev)
 {
       	drm_i830_private_t *dev_priv = dev->dev_private;
    	RING_LOCALS;
@@ -1062,79 +1262,27 @@
    	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
    	OUT_RING( CMD_REPORT_HEAD );
       	OUT_RING( 0 );
-      	OUT_RING( GFX_OP_USER_INTERRUPT );
+      	OUT_RING( 0 );
    	ADVANCE_LP_RING();
 
-	i830_wait_ring( dev, dev_priv->ring.Size - 8 );
-	atomic_set(&dev_priv->flush_done, 1);
-	wake_up_interruptible(&dev_priv->flush_queue);
-}
-
-void i830_dma_quiescent(drm_device_t *dev)
-{
-      	DECLARE_WAITQUEUE(entry, current);
-  	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
-	unsigned long end;      
-
-   	if(dev_priv == NULL) {
-	   	return;
-	}
-      	atomic_set(&dev_priv->flush_done, 0);
-   	add_wait_queue(&dev_priv->flush_queue, &entry);
-   	end = jiffies + (HZ*3);
-   
-   	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
-	      	i830_dma_quiescent_emit(dev);
-	   	if (atomic_read(&dev_priv->flush_done) == 1) break;
-		if(time_before(end, jiffies)) {
-		   	DRM_ERROR("lockup\n");
-		   	break;
-		}	   
-	      	schedule_timeout(HZ*3);
-	      	if (signal_pending(current)) {
-		   	break;
-		}
-	}
-   
-   	current->state = TASK_RUNNING;
-   	remove_wait_queue(&dev_priv->flush_queue, &entry);
-   
-   	return;
+	i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
 }
 
 static int i830_flush_queue(drm_device_t *dev)
 {
-   	DECLARE_WAITQUEUE(entry, current);
-  	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+   	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
-	unsigned long end;
-   	int i, ret = 0;      
+   	int i, ret = 0;
+   	RING_LOCALS;
+	
+   	i830_kernel_lost_context(dev);
 
-   	if(dev_priv == NULL) {
-	   	return 0;
-	}
-      	atomic_set(&dev_priv->flush_done, 0);
-   	add_wait_queue(&dev_priv->flush_queue, &entry);
-   	end = jiffies + (HZ*3);
-   	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
-	      	i830_dma_emit_flush(dev);
-	   	if (atomic_read(&dev_priv->flush_done) == 1) break;
-		if(time_before(end, jiffies)) {
-		   	DRM_ERROR("lockup\n");
-		   	break;
-		}	   
-	      	schedule_timeout(HZ*3);
-	      	if (signal_pending(current)) {
-		   	ret = -EINTR; /* Can't restart */
-		   	break;
-		}
-	}
-   
-   	current->state = TASK_RUNNING;
-   	remove_wait_queue(&dev_priv->flush_queue, &entry);
+   	BEGIN_LP_RING(2);
+      	OUT_RING( CMD_REPORT_HEAD );
+      	OUT_RING( 0 );
+      	ADVANCE_LP_RING();
 
+	i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
 
    	for (i = 0; i < dma->buf_count; i++) {
 	   	drm_buf_t *buf = dma->buflist[ i ];
@@ -1146,7 +1294,7 @@
 		if (used == I830_BUF_HARDWARE)
 			DRM_DEBUG("reclaimed from HARDWARE\n");
 		if (used == I830_BUF_CLIENT)
-			DRM_DEBUG("still on client HARDWARE\n");
+			DRM_DEBUG("still on client\n");
 	}
 
    	return ret;
@@ -1185,8 +1333,7 @@
 {
    	drm_file_t	  *priv	  = filp->private_data;
    	drm_device_t	  *dev	  = priv->dev;
-   
-   	DRM_DEBUG("i830_flush_ioctl\n");
+
    	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
 		DRM_ERROR("i830_flush_ioctl called without lock held\n");
 		return -EINVAL;
@@ -1275,6 +1422,53 @@
    	return 0;
 }
 
+
+
+/* Not sure why this isn't set all the time:
+ */ 
+static void i830_do_init_pageflip( drm_device_t *dev )
+{
+	drm_i830_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+	dev_priv->page_flipping = 1;
+	dev_priv->current_page = 0;
+	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+}
+
+int i830_do_cleanup_pageflip( drm_device_t *dev )
+{
+	drm_i830_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+	if (dev_priv->current_page != 0)
+		i830_dma_dispatch_flip( dev );
+
+	dev_priv->page_flipping = 0;
+	return 0;
+}
+
+int i830_flip_bufs(struct inode *inode, struct file *filp,
+		   unsigned int cmd, unsigned long arg)
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_i830_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+   	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+		DRM_ERROR("i830_flip_buf called without lock held\n");
+		return -EINVAL;
+	}
+
+	if (!dev_priv->page_flipping) 
+		i830_do_init_pageflip( dev );
+
+	i830_dma_dispatch_flip( dev );
+   	return 0;
+}
+
 int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
@@ -1324,46 +1518,80 @@
 	return retcode;
 }
 
-int i830_copybuf(struct inode *inode, struct file *filp, unsigned int cmd,
+int i830_copybuf(struct inode *inode,
+		 struct file *filp, 
+		 unsigned int cmd,
+		 unsigned long arg)
+{
+	/* Never copy - 2.4.x doesn't need it */
+	return 0;
+}
+
+int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
+	return 0;
+}
+
+
+
+int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
+		      unsigned long arg )
+{
 	drm_file_t	  *priv	    = filp->private_data;
 	drm_device_t	  *dev	    = priv->dev;
-	drm_i830_copy_t	  d;
-   	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
-   	u32 *hw_status = (u32 *)dev_priv->hw_status_page;
-   	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
-     					dev_priv->sarea_priv; 
-	drm_buf_t *buf;
-	drm_i830_buf_priv_t *buf_priv;
-	drm_device_dma_t *dma = dev->dma;
+	drm_i830_private_t *dev_priv = dev->dev_private;
+	drm_i830_getparam_t param;
+	int value;
 
-	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("i830_dma called without lock held\n");
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
 		return -EINVAL;
 	}
-   
-   	if (copy_from_user(&d, (drm_i830_copy_t *)arg, sizeof(d)))
-		return -EFAULT;
-
-	if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL;
-	buf = dma->buflist[ d.idx ];
-   	buf_priv = buf->dev_private;
-	if (buf_priv->currently_mapped != I830_BUF_MAPPED) return -EPERM;
-
-	if(d.used < 0 || d.used > buf->total) return -EINVAL;
 
-   	if (copy_from_user(buf_priv->virtual, d.address, d.used))
+	if (copy_from_user(&param, (drm_i830_getparam_t *)arg, sizeof(param) ))
 		return -EFAULT;
 
-   	sarea_priv->last_dispatch = (int) hw_status[5];
+	switch( param.param ) {
+	case I830_PARAM_IRQ_ACTIVE:
+		value = dev->irq ? 1 : 0;
+		break;
+	default:
+		return -EINVAL;
+	}
 
+	if ( copy_to_user( param.value, &value, sizeof(int) ) ) {
+		DRM_ERROR( "copy_to_user\n" );
+		return -EFAULT;
+	}
+	
 	return 0;
 }
 
-int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
+
+int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd,
+		   unsigned long arg )
 {
-	if(VM_DONTCOPY == 0) return 1;
+	drm_file_t	  *priv	    = filp->private_data;
+	drm_device_t	  *dev	    = priv->dev;
+	drm_i830_private_t *dev_priv = dev->dev_private;
+	drm_i830_setparam_t param;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&param, (drm_i830_setparam_t *)arg, sizeof(param) ))
+		return -EFAULT;
+
+	switch( param.param ) {
+	case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
+		dev_priv->use_mi_batchbuffer_start = param.value;
+		break;
+	default:
+		return -EINVAL;
+	}
+
 	return 0;
 }
diff -ruN drivers/char/drm-4.2/i830_drm.h drivers/char/drm/i830_drm.h
--- drivers/char/drm-4.2/i830_drm.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/i830_drm.h	2003-01-14 07:01:00.000000000 +0900
@@ -3,6 +3,9 @@
 
 /* WARNING: These defines must be the same as what the Xserver uses.
  * if you change them, you must change the defines in the Xserver.
+ *
+ * KW: Actually, you can't ever change them because doing so would
+ * break backwards compatibility.
  */
 
 #ifndef _I830_DEFINES_
@@ -18,14 +21,12 @@
 #define I830_NR_TEX_REGIONS 64
 #define I830_LOG_MIN_TEX_REGION_SIZE 16
 
-/* if defining I830_ENABLE_4_TEXTURES, do it in i830_3d_reg.h, too */
-#if !defined(I830_ENABLE_4_TEXTURES)
+/* KW: These aren't correct but someone set them to two and then
+ * released the module.  Now we can't change them as doing so would
+ * break backwards compatibility.
+ */
 #define I830_TEXTURE_COUNT	2
-#define I830_TEXBLEND_COUNT	2	/* always same as TEXTURE_COUNT? */
-#else /* defined(I830_ENABLE_4_TEXTURES) */
-#define I830_TEXTURE_COUNT	4
-#define I830_TEXBLEND_COUNT	4	/* always same as TEXTURE_COUNT? */
-#endif /* I830_ENABLE_4_TEXTURES */
+#define I830_TEXBLEND_COUNT	I830_TEXTURE_COUNT
 
 #define I830_TEXBLEND_SIZE	12	/* (4 args + op) * 2 + COLOR_FACTOR */
 
@@ -57,6 +58,7 @@
 #define I830_UPLOAD_TEXBLEND_MASK	0xf00000
 #define I830_UPLOAD_TEX_PALETTE_N(n)    (0x1000000 << (n))
 #define I830_UPLOAD_TEX_PALETTE_SHARED	0x4000000
+#define I830_UPLOAD_STIPPLE         	0x8000000
 
 /* Indices into buf.Setup where various bits of state are mirrored per
  * context and per buffer.  These can be fired at the card as a unit,
@@ -73,7 +75,6 @@
  */
 
 #define I830_DESTREG_CBUFADDR 0
-/* Invarient */
 #define I830_DESTREG_DBUFADDR 1
 #define I830_DESTREG_DV0 2
 #define I830_DESTREG_DV1 3
@@ -109,6 +110,13 @@
 #define I830_CTXREG_MCSB1		16
 #define I830_CTX_SETUP_SIZE		17
 
+/* 1.3: Stipple state
+ */ 
+#define I830_STPREG_ST0 0
+#define I830_STPREG_ST1 1
+#define I830_STP_SETUP_SIZE 2
+
+
 /* Texture state (per tex unit)
  */
 
@@ -124,6 +132,18 @@
 #define I830_TEXREG_MCS	9	/* GFX_OP_MAP_COORD_SETS */
 #define I830_TEX_SETUP_SIZE 10
 
+#define I830_TEXREG_TM0LI      0 /* load immediate 2 texture map n */
+#define I830_TEXREG_TM0S0      1
+#define I830_TEXREG_TM0S1      2
+#define I830_TEXREG_TM0S2      3
+#define I830_TEXREG_TM0S3      4
+#define I830_TEXREG_TM0S4      5
+#define I830_TEXREG_NOP0       6       /* noop */
+#define I830_TEXREG_NOP1       7       /* noop */
+#define I830_TEXREG_NOP2       8       /* noop */
+#define __I830_TEXREG_MCS      9       /* GFX_OP_MAP_COORD_SETS -- shared */
+#define __I830_TEX_SETUP_SIZE   10
+
 #define I830_FRONT   0x1
 #define I830_BACK    0x2
 #define I830_DEPTH   0x4
@@ -199,8 +219,53 @@
 	int ctxOwner;		/* last context to upload state */
 
 	int vertex_prim;
+
+        int pf_enabled;               /* is pageflipping allowed? */
+        int pf_active;               
+        int pf_current_page;	    /* which buffer is being displayed? */
+
+        int perf_boxes;             /* performance boxes to be displayed */
+   
+        /* Here's the state for texunits 2,3:
+	 */
+	unsigned int TexState2[I830_TEX_SETUP_SIZE];
+	unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
+	unsigned int TexBlendStateWordsUsed2;
+
+	unsigned int TexState3[I830_TEX_SETUP_SIZE];
+	unsigned int TexBlendState3[I830_TEXBLEND_SIZE];
+	unsigned int TexBlendStateWordsUsed3;
+
+	unsigned int StippleState[I830_STP_SETUP_SIZE];
 } drm_i830_sarea_t;
 
+/* Flags for perf_boxes
+ */
+#define I830_BOX_RING_EMPTY    0x1 /* populated by kernel */
+#define I830_BOX_FLIP          0x2 /* populated by kernel */
+#define I830_BOX_WAIT          0x4 /* populated by kernel & client */
+#define I830_BOX_TEXTURE_LOAD  0x8 /* populated by kernel */
+#define I830_BOX_LOST_CONTEXT  0x10 /* populated by client */
+
+
+/* I830 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_IOCTL_I830_INIT		DRM_IOW( 0x40, drm_i830_init_t)
+#define DRM_IOCTL_I830_VERTEX		DRM_IOW( 0x41, drm_i830_vertex_t)
+#define DRM_IOCTL_I830_CLEAR		DRM_IOW( 0x42, drm_i830_clear_t)
+#define DRM_IOCTL_I830_FLUSH		DRM_IO ( 0x43)
+#define DRM_IOCTL_I830_GETAGE		DRM_IO ( 0x44)
+#define DRM_IOCTL_I830_GETBUF		DRM_IOWR(0x45, drm_i830_dma_t)
+#define DRM_IOCTL_I830_SWAP		DRM_IO ( 0x46)
+#define DRM_IOCTL_I830_COPY		DRM_IOW( 0x47, drm_i830_copy_t)
+#define DRM_IOCTL_I830_DOCOPY		DRM_IO ( 0x48)
+#define DRM_IOCTL_I830_FLIP		DRM_IO ( 0x49)
+#define DRM_IOCTL_I830_IRQ_EMIT         DRM_IOWR(0x4a, drm_i830_irq_emit_t)
+#define DRM_IOCTL_I830_IRQ_WAIT         DRM_IOW( 0x4b, drm_i830_irq_wait_t)
+#define DRM_IOCTL_I830_GETPARAM         DRM_IOWR(0x4c, drm_i830_getparam_t)
+#define DRM_IOCTL_I830_SETPARAM         DRM_IOWR(0x4d, drm_i830_setparam_t)
+
 typedef struct _drm_i830_clear {
 	int clear_color;
 	int clear_depth;
@@ -235,4 +300,36 @@
 	int granted;
 } drm_i830_dma_t;
 
+
+/* 1.3: Userspace can request & wait on irq's:
+ */
+typedef struct drm_i830_irq_emit {
+	int *irq_seq;
+} drm_i830_irq_emit_t;
+
+typedef struct drm_i830_irq_wait {
+	int irq_seq;
+} drm_i830_irq_wait_t;
+
+
+/* 1.3: New ioctl to query kernel params:
+ */
+#define I830_PARAM_IRQ_ACTIVE            1
+
+typedef struct drm_i830_getparam {
+	int param;
+	int *value;
+} drm_i830_getparam_t;
+
+
+/* 1.3: New ioctl to set kernel params:
+ */
+#define I830_SETPARAM_USE_MI_BATCHBUFFER_START            1
+
+typedef struct drm_i830_setparam {
+	int param;
+	int value;
+} drm_i830_setparam_t;
+
+
 #endif /* _I830_DRM_H_ */
diff -ruN drivers/char/drm-4.2/i830_drv.c drivers/char/drm/i830_drv.c
--- drivers/char/drm-4.2/i830_drv.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/i830_drv.c	2003-01-14 07:00:59.000000000 +0900
@@ -29,41 +29,16 @@
  *    Jeff Hartmann <jhartmann@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
  *    Abraham vd Merwe <abraham@2d3d.co.za>
+ *    Keith Whitwell <keith@tungstengraphics.com>
  */
 
 #include <linux/config.h>
 #include "i830.h"
 #include "drmP.h"
+#include "drm.h"
+#include "i830_drm.h"
 #include "i830_drv.h"
 
-#define DRIVER_AUTHOR		"VA Linux Systems Inc."
-
-#define DRIVER_NAME		"i830"
-#define DRIVER_DESC		"Intel 830M"
-#define DRIVER_DATE		"20011004"
-
-#define DRIVER_MAJOR		1
-#define DRIVER_MINOR		2
-#define DRIVER_PATCHLEVEL	0
-
-#define DRIVER_IOCTLS							    \
-	[DRM_IOCTL_NR(DRM_IOCTL_I830_INIT)]   = { i830_dma_init,    1, 1 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I830_VERTEX)] = { i830_dma_vertex,  1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I830_CLEAR)]  = { i830_clear_bufs,  1, 0 }, \
-      	[DRM_IOCTL_NR(DRM_IOCTL_I830_FLUSH)]  = { i830_flush_ioctl, 1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I830_GETAGE)] = { i830_getage,      1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_I830_GETBUF)] = { i830_getbuf,      1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I830_SWAP)]   = { i830_swap_bufs,   1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I830_COPY)]   = { i830_copybuf,     1, 0 }, \
-   	[DRM_IOCTL_NR(DRM_IOCTL_I830_DOCOPY)] = { i830_docopy,      1, 0 },
-
-#define __HAVE_COUNTERS         4
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-#define __HAVE_COUNTER9         _DRM_STAT_DMA
-
-
 #include "drm_agpsupport.h"
 #include "drm_auth.h"
 #include "drm_bufs.h"
@@ -72,25 +47,6 @@
 #include "drm_drawable.h"
 #include "drm_drv.h"
 
-#ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO).  It calls the insmod option
- * routine, drm_parse_drm.
- */
-
-/* JH- We have to hand expand the string ourselves because of the cpp.  If
- * anyone can think of a way that we can fit into the __setup macro without
- * changing it, then please send the solution my way.
- */
-static int __init i830_options( char *str )
-{
-   DRM(parse_options)( str );
-   return 1;
-}
-
-__setup( DRIVER_NAME "=", i830_options );
-#endif
-
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
diff -ruN drivers/char/drm-4.2/i830_drv.h drivers/char/drm/i830_drv.h
--- drivers/char/drm-4.2/i830_drv.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/i830_drv.h	2003-01-14 07:01:00.000000000 +0900
@@ -61,24 +61,36 @@
 	drm_i830_sarea_t *sarea_priv;
    	drm_i830_ring_buffer_t ring;
 
-      	u8 *hw_status_page;
+      	unsigned long hw_status_page;
    	unsigned long counter;
-   	
-   	dma_addr_t dma_status_page;
 
-   	atomic_t flush_done;
-   	wait_queue_head_t flush_queue;	/* Processes waiting until flush    */
+	dma_addr_t dma_status_page;
+
 	drm_buf_t *mmap_buffer;
 	
 	u32 front_di1, back_di1, zi1;
 	
 	int back_offset;
 	int depth_offset;
+	int front_offset;
 	int w, h;
 	int pitch;
 	int back_pitch;
 	int depth_pitch;
 	unsigned int cpp;
+
+	int do_boxes;
+	int dma_used;
+
+	int current_page;
+	int page_flipping;
+
+	wait_queue_head_t irq_queue;
+   	atomic_t irq_received;
+   	atomic_t irq_emitted;
+
+	int use_mi_batchbuffer_start;
+
 } drm_i830_private_t;
 
 				/* i830_dma.c */
@@ -109,24 +121,81 @@
 extern int i830_clear_bufs(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg);
 
-#define I830_VERBOSE 0
+extern int i830_flip_bufs(struct inode *inode, struct file *filp,
+			 unsigned int cmd, unsigned long arg);
+
+extern int i830_getparam( struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg );
+
+extern int i830_setparam( struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg );
+
+/* i830_irq.c */
+extern int i830_irq_emit( struct inode *inode, struct file *filp, 
+			  unsigned int cmd, unsigned long arg );
+extern int i830_irq_wait( struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg );
+extern int i830_wait_irq(drm_device_t *dev, int irq_nr);
+extern int i830_emit_irq(drm_device_t *dev);
+
 
 #define I830_BASE(reg)		((unsigned long) \
 				dev_priv->mmio_map->handle)
 #define I830_ADDR(reg)		(I830_BASE(reg) + reg)
-#define I830_DEREF(reg)		*(__volatile__ int *)I830_ADDR(reg)
-#define I830_READ(reg)		I830_DEREF(reg)
-#define I830_WRITE(reg,val) 	do { I830_DEREF(reg) = val; } while (0)
+#define I830_DEREF(reg)		*(__volatile__ unsigned int *)I830_ADDR(reg)
+#define I830_READ(reg)		readl((volatile u32 *)I830_ADDR(reg))
+#define I830_WRITE(reg,val) 	writel(val, (volatile u32 *)I830_ADDR(reg))
 #define I830_DEREF16(reg)	*(__volatile__ u16 *)I830_ADDR(reg)
 #define I830_READ16(reg) 	I830_DEREF16(reg)
 #define I830_WRITE16(reg,val)	do { I830_DEREF16(reg) = val; } while (0)
 
+
+
+#define I830_VERBOSE 0
+
+#define RING_LOCALS	unsigned int outring, ringmask, outcount; \
+                        volatile char *virt;
+
+#define BEGIN_LP_RING(n) do {				\
+	if (I830_VERBOSE)				\
+		printk("BEGIN_LP_RING(%d) in %s\n",	\
+			  n, __FUNCTION__);		\
+	if (dev_priv->ring.space < n*4)			\
+		i830_wait_ring(dev, n*4, __FUNCTION__);		\
+	outcount = 0;					\
+	outring = dev_priv->ring.tail;			\
+	ringmask = dev_priv->ring.tail_mask;		\
+	virt = dev_priv->ring.virtual_start;		\
+} while (0)
+
+
+#define OUT_RING(n) do {					\
+	if (I830_VERBOSE) printk("   OUT_RING %x\n", (int)(n));	\
+	*(volatile unsigned int *)(virt + outring) = n;		\
+        outcount++;						\
+	outring += 4;						\
+	outring &= ringmask;					\
+} while (0)
+
+#define ADVANCE_LP_RING() do {						\
+	if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring);	\
+	dev_priv->ring.tail = outring;					\
+	dev_priv->ring.space -= outcount * 4;				\
+	I830_WRITE(LP_RING + RING_TAIL, outring);			\
+} while(0)
+
+extern int i830_wait_ring(drm_device_t *dev, int n, const char *caller);
+
+
 #define GFX_OP_USER_INTERRUPT 		((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
 #define CMD_REPORT_HEAD			(7<<23)
 #define CMD_STORE_DWORD_IDX		((0x21<<23) | 0x1)
 #define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
 
+#define STATE3D_LOAD_STATE_IMMEDIATE_2      ((0x3<<29)|(0x1d<<24)|(0x03<<16))
+#define LOAD_TEXTURE_MAP0                   (1<<11)
+
 #define INST_PARSER_CLIENT   0x00000000
 #define INST_OP_FLUSH        0x02000000
 #define INST_FLUSH_MAP_CACHE 0x00000001
@@ -142,18 +211,21 @@
 #define I830REG_INT_MASK_R 	0x020a8
 #define I830REG_INT_ENABLE_R	0x020a0
 
+#define I830_IRQ_RESERVED ((1<<13)|(3<<2))
+
+
 #define LP_RING     		0x2030
 #define HP_RING     		0x2040
 #define RING_TAIL      		0x00
-#define TAIL_ADDR		0x000FFFF8
+#define TAIL_ADDR		0x001FFFF8
 #define RING_HEAD      		0x04
 #define HEAD_WRAP_COUNT     	0xFFE00000
 #define HEAD_WRAP_ONE       	0x00200000
 #define HEAD_ADDR           	0x001FFFFC
 #define RING_START     		0x08
-#define START_ADDR          	0x00FFFFF8
+#define START_ADDR          	0x0xFFFFF000
 #define RING_LEN       		0x0C
-#define RING_NR_PAGES       	0x000FF000 
+#define RING_NR_PAGES       	0x001FF000 
 #define RING_REPORT_MASK    	0x00000006
 #define RING_REPORT_64K     	0x00000002
 #define RING_REPORT_128K    	0x00000004
@@ -184,6 +256,12 @@
 
 #define CMD_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
 
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define ASYNC_FLIP                (1<<22)
+
+#define CMD_3D                          (0x3<<29)
+#define STATE3D_CONST_BLEND_COLOR_CMD   (CMD_3D|(0x1d<<24)|(0x88<<16))
+#define STATE3D_MAP_COORD_SETBIND_CMD   (CMD_3D|(0x1d<<24)|(0x02<<16))
 
 #define BR00_BITBLT_CLIENT   0x40000000
 #define BR00_OP_COLOR_BLT    0x10000000
@@ -208,8 +286,15 @@
 #define XY_SRC_COPY_BLT_WRITE_RGB       (1<<20)
 
 #define MI_BATCH_BUFFER 	((0x30<<23)|1)
+#define MI_BATCH_BUFFER_START 	(0x31<<23)
+#define MI_BATCH_BUFFER_END 	(0xA<<23)
 #define MI_BATCH_NON_SECURE	(1)
 
+#define MI_WAIT_FOR_EVENT       ((0x3<<23))
+#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2) 
+#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1) 
+
+#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
 
 #endif
 
diff -ruN drivers/char/drm-4.2/i830_irq.c drivers/char/drm/i830_irq.c
--- drivers/char/drm-4.2/i830_irq.c	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/i830_irq.c	2003-01-14 07:00:59.000000000 +0900
@@ -0,0 +1,178 @@
+/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
+ *
+ * Copyright 2002 Tungsten Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  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.
+ *
+ * Authors: Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#define __NO_VERSION__
+#include "i830.h"
+#include "drmP.h"
+#include "drm.h"
+#include "i830_drm.h"
+#include "i830_drv.h"
+#include <linux/interrupt.h>	/* For task queue support */
+#include <linux/delay.h>
+
+
+void DRM(dma_service)(int irq, void *device, struct pt_regs *regs)
+{
+	drm_device_t	 *dev = (drm_device_t *)device;
+      	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
+   	u16 temp;
+   
+      	temp = I830_READ16(I830REG_INT_IDENTITY_R);
+	printk("%s: %x\n", __FUNCTION__, temp);
+	
+   	if(temp == 0) 
+	   return;
+
+	I830_WRITE16(I830REG_INT_IDENTITY_R, temp); 
+
+	if (temp & 2) {
+		atomic_inc(&dev_priv->irq_received);
+		wake_up_interruptible(&dev_priv->irq_queue); 
+	}
+}
+
+
+int i830_emit_irq(drm_device_t *dev)
+{
+	drm_i830_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+	atomic_inc(&dev_priv->irq_emitted);
+
+   	BEGIN_LP_RING(2);
+      	OUT_RING( 0 );
+      	OUT_RING( GFX_OP_USER_INTERRUPT );
+      	ADVANCE_LP_RING();
+
+	return atomic_read(&dev_priv->irq_emitted);
+}
+
+
+int i830_wait_irq(drm_device_t *dev, int irq_nr)
+{
+  	drm_i830_private_t *dev_priv = 
+	   (drm_i830_private_t *)dev->dev_private;
+	DECLARE_WAITQUEUE(entry, current);
+	unsigned long end = jiffies + HZ*3;
+	int ret = 0;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+ 	if (atomic_read(&dev_priv->irq_received) >= irq_nr)  
+ 		return 0; 
+
+	dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
+
+	add_wait_queue(&dev_priv->irq_queue, &entry);
+
+	for (;;) {
+		current->state = TASK_INTERRUPTIBLE;
+	   	if (atomic_read(&dev_priv->irq_received) >= irq_nr) 
+		   break;
+		if((signed)(end - jiffies) <= 0) {
+			DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
+				  I830_READ16( I830REG_INT_IDENTITY_R ),
+				  I830_READ16( I830REG_INT_MASK_R ),
+				  I830_READ16( I830REG_INT_ENABLE_R ),
+				  I830_READ16( I830REG_HWSTAM ));
+
+		   	ret = -EBUSY;	/* Lockup?  Missed irq? */
+			break;
+		}
+	      	schedule_timeout(HZ*3);
+	      	if (signal_pending(current)) {
+		   	ret = -EINTR;
+			break;
+		}
+	}
+
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&dev_priv->irq_queue, &entry);
+	return ret;
+}
+
+
+/* Needs the lock as it touches the ring.
+ */
+int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd,
+		   unsigned long arg )
+{
+	drm_file_t	  *priv	    = filp->private_data;
+	drm_device_t	  *dev	    = priv->dev;
+	drm_i830_private_t *dev_priv = dev->dev_private;
+	drm_i830_irq_emit_t emit;
+	int result;
+
+   	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+		DRM_ERROR("i830_irq_emit called without lock held\n");
+		return -EINVAL;
+	}
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if (copy_from_user( &emit, (drm_i830_irq_emit_t *)arg, sizeof(emit) ))
+		return -EFAULT;
+
+	result = i830_emit_irq( dev );
+
+	if ( copy_to_user( emit.irq_seq, &result, sizeof(int) ) ) {
+		DRM_ERROR( "copy_to_user\n" );
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+
+/* Doesn't need the hardware lock.
+ */
+int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
+		   unsigned long arg )
+{
+	drm_file_t	  *priv	    = filp->private_data;
+	drm_device_t	  *dev	    = priv->dev;
+	drm_i830_private_t *dev_priv = dev->dev_private;
+	drm_i830_irq_wait_t irqwait;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return -EINVAL;
+	}
+
+	if (copy_from_user( &irqwait, (drm_i830_irq_wait_t *)arg, 
+			    sizeof(irqwait) ))
+		return -EFAULT;
+
+	return i830_wait_irq( dev, irqwait.irq_seq );
+}
+
diff -ruN drivers/char/drm-4.2/mga.h drivers/char/drm/mga.h
--- drivers/char/drm-4.2/mga.h	2001-08-09 01:42:15.000000000 +0900
+++ drivers/char/drm/mga.h	2003-01-14 07:01:00.000000000 +0900
@@ -41,6 +41,34 @@
 #define __HAVE_MTRR		1
 #define __HAVE_CTX_BITMAP	1
 
+#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
+
+#define DRIVER_NAME		"mga"
+#define DRIVER_DESC		"Matrox G200/G400"
+#define DRIVER_DATE		"20021029"
+
+#define DRIVER_MAJOR		3
+#define DRIVER_MINOR		1
+#define DRIVER_PATCHLEVEL	0
+
+#define DRIVER_IOCTLS							   \
+	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	      = { mga_dma_buffers, 1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)]    = { mga_dma_init,    1, 1 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)]   = { mga_dma_flush,   1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_RESET)]   = { mga_dma_reset,   1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)]    = { mga_dma_swap,    1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)]   = { mga_dma_clear,   1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)]  = { mga_dma_vertex,  1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)]   = { mga_dma_iload,   1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)]    = { mga_dma_blit,    1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_MGA_GETPARAM)]= { mga_getparam,    1, 0 },
+
+#define __HAVE_COUNTERS         3
+#define __HAVE_COUNTER6         _DRM_STAT_IRQ
+#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
+
 /* Driver customization:
  */
 #define DRIVER_PRETAKEDOWN() do {					\
@@ -50,6 +78,9 @@
 /* DMA customization:
  */
 #define __HAVE_DMA		1
+#define __HAVE_DMA_IRQ		1
+#define __HAVE_VBL_IRQ		1
+#define __HAVE_SHARED_IRQ       1
 
 #define __HAVE_DMA_QUIESCENT	1
 #define DRIVER_DMA_QUIESCENT() do {					\
diff -ruN drivers/char/drm-4.2/mga_dma.c drivers/char/drm/mga_dma.c
--- drivers/char/drm-4.2/mga_dma.c	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/mga_dma.c	2003-01-14 07:00:59.000000000 +0900
@@ -35,11 +35,10 @@
 
 #include "mga.h"
 #include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
 #include "mga_drv.h"
 
-#include <linux/interrupt.h>	/* For task queue support */
-#include <linux/delay.h>
-
 #define MGA_DEFAULT_USEC_TIMEOUT	10000
 #define MGA_FREELIST_DEBUG		0
 
@@ -52,7 +51,7 @@
 {
 	u32 status = 0;
 	int i;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
 		status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
@@ -60,32 +59,32 @@
 			MGA_WRITE8( MGA_CRTC_INDEX, 0 );
 			return 0;
 		}
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 #if MGA_DMA_DEBUG
 	DRM_ERROR( "failed!\n" );
 	DRM_INFO( "   status=0x%08x\n", status );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 int mga_do_dma_idle( drm_mga_private_t *dev_priv )
 {
 	u32 status = 0;
 	int i;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
 		status = MGA_READ( MGA_STATUS ) & MGA_DMA_IDLE_MASK;
 		if ( status == MGA_ENDPRDMASTS ) return 0;
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 #if MGA_DMA_DEBUG
 	DRM_ERROR( "failed! status=0x%08x\n", status );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 int mga_do_dma_reset( drm_mga_private_t *dev_priv )
@@ -93,7 +92,7 @@
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	/* The primary DMA stream should look like new right about now.
 	 */
@@ -114,13 +113,13 @@
 
 int mga_do_engine_reset( drm_mga_private_t *dev_priv )
 {
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	/* Okay, so we've completely screwed up and locked the engine.
 	 * How about we clean up after ourselves?
 	 */
 	MGA_WRITE( MGA_RST, MGA_SOFTRESET );
-	udelay( 15 );				/* Wait at least 10 usecs */
+	DRM_UDELAY( 15 );				/* Wait at least 10 usecs */
 	MGA_WRITE( MGA_RST, 0 );
 
 	/* Initialize the registers that get clobbered by the soft
@@ -160,14 +159,14 @@
 	u32 head, tail;
 	u32 status = 0;
 	int i;
-	DMA_LOCALS;
-	DRM_DEBUG( "%s:\n", __FUNCTION__ );
+ 	DMA_LOCALS;
+	DRM_DEBUG( "\n" );
 
         /* We need to wait so that we can do an safe flush */
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
 		status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
 		if ( status == MGA_ENDPRDMASTS ) break;
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 	if ( primary->tail == primary->last_flush ) {
@@ -207,7 +206,7 @@
 	mga_flush_write_combine();
 	MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
 
-	DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
+	DRM_DEBUG( "done.\n" );
 }
 
 void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
@@ -215,7 +214,7 @@
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 	u32 head, tail;
 	DMA_LOCALS;
-	DRM_DEBUG( "%s:\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	BEGIN_DMA_WRAP();
 
@@ -250,7 +249,7 @@
 	MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
 
 	set_bit( 0, &primary->wrapped );
-	DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
+	DRM_DEBUG( "done.\n" );
 }
 
 void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
@@ -258,7 +257,7 @@
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	u32 head = dev_priv->primary->offset;
-	DRM_DEBUG( "%s:\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	sarea_priv->last_wrap++;
 	DRM_DEBUG( "   wrap = %d\n", sarea_priv->last_wrap );
@@ -267,7 +266,7 @@
 	MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );
 
 	clear_bit( 0, &primary->wrapped );
-	DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
+	DRM_DEBUG( "done.\n" );
 }
 
 
@@ -307,13 +306,12 @@
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_freelist_t *entry;
 	int i;
-	DRM_DEBUG( "%s: count=%d\n",
-		   __FUNCTION__, dma->buf_count );
+	DRM_DEBUG( "count=%d\n", dma->buf_count );
 
 	dev_priv->head = DRM(alloc)( sizeof(drm_mga_freelist_t),
 				     DRM_MEM_DRIVER );
 	if ( dev_priv->head == NULL )
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 
 	memset( dev_priv->head, 0, sizeof(drm_mga_freelist_t) );
 	SET_AGE( &dev_priv->head->age, MGA_BUFFER_USED, 0 );
@@ -325,7 +323,7 @@
 		entry = DRM(alloc)( sizeof(drm_mga_freelist_t),
 				    DRM_MEM_DRIVER );
 		if ( entry == NULL )
-			return -ENOMEM;
+			return DRM_ERR(ENOMEM);
 
 		memset( entry, 0, sizeof(drm_mga_freelist_t) );
 
@@ -354,7 +352,7 @@
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_freelist_t *entry;
 	drm_mga_freelist_t *next;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	entry = dev_priv->head;
 	while ( entry ) {
@@ -392,7 +390,7 @@
 	drm_mga_freelist_t *prev;
 	drm_mga_freelist_t *tail = dev_priv->tail;
 	u32 head, wrap;
-	DRM_DEBUG( "%s:\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	head = MGA_READ( MGA_PRIMADDRESS );
 	wrap = dev_priv->sarea_priv->last_wrap;
@@ -424,8 +422,7 @@
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
 	drm_mga_freelist_t *head, *entry, *prev;
 
-	DRM_DEBUG( "%s: age=0x%06lx wrap=%d\n",
-		   __FUNCTION__,
+	DRM_DEBUG( "age=0x%06lx wrap=%d\n",
 		   buf_priv->list_entry->age.head -
 		   dev_priv->primary->offset,
 		   buf_priv->list_entry->age.wrap );
@@ -458,13 +455,12 @@
 static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
 {
 	drm_mga_private_t *dev_priv;
-	struct list_head *list;
 	int ret;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
 	if ( !dev_priv )
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 
 	memset( dev_priv, 0, sizeof(drm_mga_private_t) );
 
@@ -494,21 +490,14 @@
 	dev_priv->texture_offset = init->texture_offset[0];
 	dev_priv->texture_size = init->texture_size[0];
 
-	list_for_each( list, &dev->maplist->head ) {
-		drm_map_list_t *entry = (drm_map_list_t *)list;
-		if ( entry->map &&
-		     entry->map->type == _DRM_SHM &&
-		     (entry->map->flags & _DRM_CONTAINS_LOCK) ) {
-			dev_priv->sarea = entry->map;
- 			break;
- 		}
- 	}
+	DRM_GETSAREA();
+
 	if(!dev_priv->sarea) {
 		DRM_ERROR( "failed to find sarea!\n" );
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
 		mga_do_cleanup_dma( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
@@ -517,7 +506,7 @@
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
 		mga_do_cleanup_dma( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
 	if(!dev_priv->mmio) {
@@ -525,7 +514,7 @@
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
 		mga_do_cleanup_dma( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->status, init->status_offset );
 	if(!dev_priv->status) {
@@ -533,7 +522,7 @@
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
 		mga_do_cleanup_dma( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
@@ -542,7 +531,7 @@
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
 		mga_do_cleanup_dma( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
 	if(!dev_priv->primary) {
@@ -550,7 +539,7 @@
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
 		mga_do_cleanup_dma( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
 	if(!dev_priv->buffers) {
@@ -558,7 +547,7 @@
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
 		mga_do_cleanup_dma( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	dev_priv->sarea_priv =
@@ -576,7 +565,7 @@
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
 		mga_do_cleanup_dma( dev );
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 	}
 
 	ret = mga_warp_install_microcode( dev_priv );
@@ -626,8 +615,6 @@
 
 	dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
 
-	spin_lock_init( &dev_priv->prim.list_lock );
-
 	dev_priv->prim.status[0] = dev_priv->primary->offset;
 	dev_priv->prim.status[1] = 0;
 
@@ -640,7 +627,7 @@
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
 		mga_do_cleanup_dma( dev );
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 	}
 
 	/* Make dev_private visable to others. */
@@ -650,7 +637,7 @@
 
 int mga_do_cleanup_dma( drm_device_t *dev )
 {
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	if ( dev->dev_private ) {
 		drm_mga_private_t *dev_priv = dev->dev_private;
@@ -671,15 +658,12 @@
 	return 0;
 }
 
-int mga_dma_init( struct inode *inode, struct file *filp,
-		  unsigned int cmd, unsigned long arg )
+int mga_dma_init( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_mga_init_t init;
 
-	if ( copy_from_user( &init, (drm_mga_init_t *)arg, sizeof(init) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) );
 
 	switch ( init.func ) {
 	case MGA_INIT_DMA:
@@ -688,7 +672,7 @@
 		return mga_do_cleanup_dma( dev );
 	}
 
-	return -EINVAL;
+	return DRM_ERR(EINVAL);
 }
 
 
@@ -696,21 +680,17 @@
  * Primary DMA stream management
  */
 
-int mga_dma_flush( struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg )
+int mga_dma_flush( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
 	drm_lock_t lock;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &lock, (drm_lock_t *)arg, sizeof(lock) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( lock, (drm_lock_t *)data, sizeof(lock) );
 
-	DRM_DEBUG( "%s: %s%s%s\n",
-		   __FUNCTION__,
+	DRM_DEBUG( "%s%s%s\n",
 		   (lock.flags & _DRM_LOCK_FLUSH) ?	"flush, " : "",
 		   (lock.flags & _DRM_LOCK_FLUSH_ALL) ?	"flush all, " : "",
 		   (lock.flags & _DRM_LOCK_QUIESCENT) ?	"idle, " : "" );
@@ -725,7 +705,7 @@
 #if MGA_DMA_DEBUG
 		int ret = mga_do_wait_for_idle( dev_priv );
 		if ( ret < 0 )
-			DRM_INFO( __FUNCTION__": -EBUSY\n" );
+			DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );
 		return ret;
 #else
 		return mga_do_wait_for_idle( dev_priv );
@@ -735,11 +715,9 @@
 	}
 }
 
-int mga_dma_reset( struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg )
+int mga_dma_reset( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
 
 	LOCK_TEST_WITH_RETURN( dev );
@@ -759,27 +737,25 @@
 
 	for ( i = d->granted_count ; i < d->request_count ; i++ ) {
 		buf = mga_freelist_get( dev );
-		if ( !buf ) return -EAGAIN;
+		if ( !buf ) return DRM_ERR(EAGAIN);
 
-		buf->pid = current->pid;
+		buf->pid = DRM_CURRENTPID;
 
-		if ( copy_to_user( &d->request_indices[i],
+		if ( DRM_COPY_TO_USER( &d->request_indices[i],
 				   &buf->idx, sizeof(buf->idx) ) )
-			return -EFAULT;
-		if ( copy_to_user( &d->request_sizes[i],
+			return DRM_ERR(EFAULT);
+		if ( DRM_COPY_TO_USER( &d->request_sizes[i],
 				   &buf->total, sizeof(buf->total) ) )
-			return -EFAULT;
+			return DRM_ERR(EFAULT);
 
 		d->granted_count++;
 	}
 	return 0;
 }
 
-int mga_dma_buffers( struct inode *inode, struct file *filp,
-		     unsigned int cmd, unsigned long arg )
+int mga_dma_buffers( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_device_dma_t *dma = dev->dma;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
 	drm_dma_t d;
@@ -787,23 +763,22 @@
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *)data, sizeof(d) );
 
 	/* Please don't send us buffers.
 	 */
 	if ( d.send_count != 0 ) {
 		DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
-			   current->pid, d.send_count );
-		return -EINVAL;
+			   DRM_CURRENTPID, d.send_count );
+		return DRM_ERR(EINVAL);
 	}
 
 	/* We'll send you buffers.
 	 */
 	if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
 		DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
-			   current->pid, d.request_count, dma->buf_count );
-		return -EINVAL;
+			   DRM_CURRENTPID, d.request_count, dma->buf_count );
+		return DRM_ERR(EINVAL);
 	}
 
 	WRAP_TEST_WITH_RETURN( dev_priv );
@@ -814,8 +789,7 @@
 		ret = mga_dma_get_buffers( dev, &d );
 	}
 
-	if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
-		return -EFAULT;
+	DRM_COPY_TO_USER_IOCTL( (drm_dma_t *)data, d, sizeof(d) );
 
 	return ret;
 }
diff -ruN drivers/char/drm-4.2/mga_drm.h drivers/char/drm/mga_drm.h
--- drivers/char/drm-4.2/mga_drm.h	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/mga_drm.h	2003-01-14 07:01:00.000000000 +0900
@@ -38,6 +38,7 @@
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the Xserver file (mga_sarea.h)
  */
+
 #ifndef __MGA_SAREA_DEFINES__
 #define __MGA_SAREA_DEFINES__
 
@@ -225,6 +226,21 @@
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the Xserver file (xf86drmMga.h)
  */
+
+/* MGA specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_IOCTL_MGA_INIT		DRM_IOW( 0x40, drm_mga_init_t)
+#define DRM_IOCTL_MGA_FLUSH		DRM_IOW( 0x41, drm_lock_t)
+#define DRM_IOCTL_MGA_RESET		DRM_IO(  0x42)
+#define DRM_IOCTL_MGA_SWAP		DRM_IO(  0x43)
+#define DRM_IOCTL_MGA_CLEAR		DRM_IOW( 0x44, drm_mga_clear_t)
+#define DRM_IOCTL_MGA_VERTEX		DRM_IOW( 0x45, drm_mga_vertex_t)
+#define DRM_IOCTL_MGA_INDICES		DRM_IOW( 0x46, drm_mga_indices_t)
+#define DRM_IOCTL_MGA_ILOAD		DRM_IOW( 0x47, drm_mga_iload_t)
+#define DRM_IOCTL_MGA_BLIT		DRM_IOW( 0x48, drm_mga_blit_t)
+#define DRM_IOCTL_MGA_GETPARAM		DRM_IOWR(0x49, drm_mga_getparam_t)
+
 typedef struct _drm_mga_warp_index {
    	int installed;
    	unsigned long phys_addr;
@@ -307,4 +323,14 @@
 	int source_pitch, dest_pitch;
 } drm_mga_blit_t;
 
+/* 3.1: An ioctl to get parameters that aren't available to the 3d
+ * client any other way.  
+ */
+#define MGA_PARAM_IRQ_NR            1
+
+typedef struct drm_mga_getparam {
+	int param;
+	int *value;
+} drm_mga_getparam_t;
+
 #endif
diff -ruN drivers/char/drm-4.2/mga_drv.c drivers/char/drm/mga_drv.c
--- drivers/char/drm-4.2/mga_drv.c	2001-08-09 01:42:15.000000000 +0900
+++ drivers/char/drm/mga_drv.c	2003-01-14 07:00:59.000000000 +0900
@@ -32,37 +32,9 @@
 #include <linux/config.h>
 #include "mga.h"
 #include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
 #include "mga_drv.h"
-
-#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
-
-#define DRIVER_NAME		"mga"
-#define DRIVER_DESC		"Matrox G200/G400"
-#define DRIVER_DATE		"20010321"
-
-#define DRIVER_MAJOR		3
-#define DRIVER_MINOR		0
-#define DRIVER_PATCHLEVEL	2
-
-#define DRIVER_IOCTLS							   \
-	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	      = { mga_dma_buffers, 1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)]    = { mga_dma_init,    1, 1 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)]   = { mga_dma_flush,   1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_RESET)]   = { mga_dma_reset,   1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)]    = { mga_dma_swap,    1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)]   = { mga_dma_clear,   1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)]  = { mga_dma_vertex,  1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_dma_indices, 1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)]   = { mga_dma_iload,   1, 0 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)]    = { mga_dma_blit,    1, 0 },
-
-
-#define __HAVE_COUNTERS         3
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-
-
 #include "drm_agpsupport.h"
 #include "drm_auth.h"
 #include "drm_bufs.h"
@@ -70,27 +42,6 @@
 #include "drm_dma.h"
 #include "drm_drawable.h"
 #include "drm_drv.h"
-
-#ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO).  It calls the insmod option
- * routine, drm_parse_drm.
- */
-
-/* JH- We have to hand expand the string ourselves because of the cpp.  If
- * anyone can think of a way that we can fit into the __setup macro without
- * changing it, then please send the solution my way.
- */
-static int __init mga_options( char *str )
-{
-	DRM(parse_options)( str );
-	return 1;
-}
-
-__setup( DRIVER_NAME "=", mga_options );
-#endif
-
-
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
diff -ruN drivers/char/drm-4.2/mga_drv.h drivers/char/drm/mga_drv.h
--- drivers/char/drm-4.2/mga_drv.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/mga_drv.h	2003-01-14 07:01:00.000000000 +0900
@@ -46,8 +46,6 @@
 	u32 last_wrap;
 
 	u32 high_mark;
-
-	spinlock_t list_lock;
 } drm_mga_primary_buffer_t;
 
 typedef struct drm_mga_freelist {
@@ -103,14 +101,10 @@
 } drm_mga_private_t;
 
 				/* mga_dma.c */
-extern int mga_dma_init( struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg );
-extern int mga_dma_flush( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int mga_dma_reset( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int mga_dma_buffers( struct inode *inode, struct file *filp,
-			    unsigned int cmd, unsigned long arg );
+extern int mga_dma_init( DRM_IOCTL_ARGS );
+extern int mga_dma_flush( DRM_IOCTL_ARGS );
+extern int mga_dma_reset( DRM_IOCTL_ARGS );
+extern int mga_dma_buffers( DRM_IOCTL_ARGS );
 
 extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv );
 extern int mga_do_dma_idle( drm_mga_private_t *dev_priv );
@@ -125,24 +119,19 @@
 extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf );
 
 				/* mga_state.c */
-extern int  mga_dma_clear( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int  mga_dma_swap( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int  mga_dma_vertex( struct inode *inode, struct file *filp,
-			    unsigned int cmd, unsigned long arg );
-extern int  mga_dma_indices( struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg );
-extern int  mga_dma_iload( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int  mga_dma_blit( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
+extern int  mga_dma_clear( DRM_IOCTL_ARGS );
+extern int  mga_dma_swap( DRM_IOCTL_ARGS );
+extern int  mga_dma_vertex( DRM_IOCTL_ARGS );
+extern int  mga_dma_indices( DRM_IOCTL_ARGS );
+extern int  mga_dma_iload( DRM_IOCTL_ARGS );
+extern int  mga_dma_blit( DRM_IOCTL_ARGS );
+extern int  mga_getparam( DRM_IOCTL_ARGS );
 
 				/* mga_warp.c */
 extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
 extern int mga_warp_init( drm_mga_private_t *dev_priv );
 
-#define mga_flush_write_combine()	mb()
+#define mga_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
 
 
 #define MGA_BASE( reg )		((unsigned long)(dev_priv->mmio->handle))
@@ -153,17 +142,19 @@
 
 #ifdef __alpha__
 #define MGA_READ( reg )		(_MGA_READ((u32 *)MGA_ADDR(reg)))
-#define MGA_WRITE( reg, val )	do { wmb(); MGA_DEREF( reg ) = val; } while (0)
-#define MGA_WRITE8( reg, val )  do { wmb(); MGA_DEREF8( reg ) = val; } while (0)
+#define MGA_READ8( reg )	(_MGA_READ((u8 *)MGA_ADDR(reg)))
+#define MGA_WRITE( reg, val )	do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
+#define MGA_WRITE8( reg, val )  do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
 
 static inline u32 _MGA_READ(u32 *addr)
 {
-	mb();
+	DRM_READMEMORYBARRIER();
 	return *(volatile u32 *)addr;
 }
 
 #else
 #define MGA_READ( reg )		MGA_DEREF( reg )
+#define MGA_READ8( reg )	MGA_DEREF8( reg )
 #define MGA_WRITE( reg, val )	do { MGA_DEREF( reg ) = val; } while (0)
 #define MGA_WRITE8( reg, val )  do { MGA_DEREF8( reg ) = val; } while (0)
 #endif
@@ -198,10 +189,10 @@
 #define LOCK_TEST_WITH_RETURN( dev )					\
 do {									\
 	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||		\
-	     dev->lock.pid != current->pid ) {				\
+	     dev->lock.pid != DRM_CURRENTPID ) {				\
 		DRM_ERROR( "%s called without lock held\n",		\
-			   __FUNCTION__ );				\
-		return -EINVAL;						\
+			   __FUNCTION__ );					\
+		return DRM_ERR(EINVAL);				\
 	}								\
 } while (0)
 
@@ -214,7 +205,7 @@
 			    dev_priv->prim.high_mark ) {		\
 			if ( MGA_DMA_DEBUG )				\
 				DRM_INFO( "%s: wrap...\n", __FUNCTION__ );	\
-			return -EBUSY;					\
+			return DRM_ERR(EBUSY);			\
 		}							\
 	}								\
 } while (0)
@@ -225,7 +216,7 @@
 		if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {		\
 			if ( MGA_DMA_DEBUG )				\
 				DRM_INFO( "%s: wrap...\n", __FUNCTION__ );	\
-			return -EBUSY;					\
+			return DRM_ERR(EBUSY);			\
 		}							\
 		mga_do_dma_wrap_end( dev_priv );			\
 	}								\
@@ -257,7 +248,7 @@
 #define BEGIN_DMA_WRAP()						\
 do {									\
 	if ( MGA_VERBOSE ) {						\
-		DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ );	\
+		DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ );		\
 		DRM_INFO( "   space=0x%x\n", dev_priv->prim.space );	\
 	}								\
 	prim = dev_priv->prim.start;					\
@@ -276,7 +267,7 @@
 #define FLUSH_DMA()							\
 do {									\
 	if ( 0 ) {							\
-		DRM_INFO( "%s:\n" , __FUNCTION__);			\
+		DRM_INFO( "%s:\n", __FUNCTION__ );				\
 		DRM_INFO( "   tail=0x%06x head=0x%06lx\n",		\
 			  dev_priv->prim.tail,				\
 			  MGA_READ( MGA_PRIMADDRESS ) -			\
@@ -357,6 +348,11 @@
 /* A reduced set of the mga registers.
  */
 #define MGA_CRTC_INDEX			0x1fd4
+#define MGA_CRTC_DATA			0x1fd5
+
+/* CRTC11 */
+#define MGA_VINTCLR			(1 << 4)
+#define MGA_VINTEN			(1 << 5)
 
 #define MGA_ALPHACTRL 			0x2c7c
 #define MGA_AR0 			0x1c60
@@ -428,8 +424,10 @@
 
 #define MGA_ICLEAR 			0x1e18
 #	define MGA_SOFTRAPICLR			(1 << 0)
+#	define MGA_VLINEICLR			(1 << 5)
 #define MGA_IEN 			0x1e1c
 #	define MGA_SOFTRAPIEN			(1 << 0)
+#	define MGA_VLINEIEN			(1 << 5)
 
 #define MGA_LEN 			0x1c5c
 
@@ -468,6 +466,8 @@
 #	define MGA_SRCACC_AGP			(1 << 1)
 #define MGA_STATUS 			0x1e14
 #	define MGA_SOFTRAPEN			(1 << 0)
+#	define MGA_VSYNCPEN			(1 << 4)
+#	define MGA_VLINEPEN			(1 << 5)
 #	define MGA_DWGENGSTS			(1 << 16)
 #	define MGA_ENDPRDMASTS			(1 << 17)
 #define MGA_STENCIL			0x2cc8
@@ -634,7 +634,7 @@
 
 /* Simple idle test.
  */
-static inline int mga_is_idle( drm_mga_private_t *dev_priv )
+static __inline__ int mga_is_idle( drm_mga_private_t *dev_priv )
 {
 	u32 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
 	return ( status == MGA_ENDPRDMASTS );
diff -ruN drivers/char/drm-4.2/mga_irq.c drivers/char/drm/mga_irq.c
--- drivers/char/drm-4.2/mga_irq.c	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/mga_irq.c	2003-01-14 07:00:59.000000000 +0900
@@ -0,0 +1,100 @@
+/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ * 
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#include "mga.h"
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+
+void mga_dma_service( DRM_IRQ_ARGS )
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_mga_private_t *dev_priv = 
+	   (drm_mga_private_t *)dev->dev_private;
+	int status;
+
+	status = MGA_READ( MGA_STATUS );
+	
+	/* VBLANK interrupt */
+	if ( status & MGA_VLINEPEN ) {
+		MGA_WRITE( MGA_ICLEAR, MGA_VLINEICLR );
+		atomic_inc(&dev->vbl_received);
+		DRM_WAKEUP(&dev->vbl_queue);
+		DRM(vbl_send_signals)( dev );
+	}
+}
+
+int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks... 
+	 */
+	DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, 
+		     ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+			 - *sequence ) <= (1<<23) ) );
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+void mga_driver_irq_preinstall( drm_device_t *dev ) {
+  	drm_mga_private_t *dev_priv = 
+	   (drm_mga_private_t *)dev->dev_private;
+
+	/* Disable *all* interrupts */
+      	MGA_WRITE( MGA_IEN, 0 );
+	/* Clear bits if they're already high */
+   	MGA_WRITE( MGA_ICLEAR, ~0 );
+}
+
+void mga_driver_irq_postinstall( drm_device_t *dev ) {
+  	drm_mga_private_t *dev_priv = 
+	   (drm_mga_private_t *)dev->dev_private;
+
+	/* Turn on VBL interrupt */
+   	MGA_WRITE( MGA_IEN, MGA_VLINEIEN );
+}
+
+void mga_driver_irq_uninstall( drm_device_t *dev ) {
+  	drm_mga_private_t *dev_priv = 
+	   (drm_mga_private_t *)dev->dev_private;
+	if ( dev_priv ) {
+		/* Disable *all* interrupts */
+		MGA_WRITE( MGA_IEN, 0 );
+	}
+}
diff -ruN drivers/char/drm-4.2/mga_state.c drivers/char/drm/mga_state.c
--- drivers/char/drm-4.2/mga_state.c	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/mga_state.c	2003-01-14 07:00:59.000000000 +0900
@@ -34,8 +34,9 @@
 
 #include "mga.h"
 #include "drmP.h"
-#include "mga_drv.h"
 #include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
 
 
 /* ================================================================
@@ -68,7 +69,7 @@
 	ADVANCE_DMA();
 }
 
-static inline void mga_g200_emit_context( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g200_emit_context( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -94,7 +95,7 @@
 	ADVANCE_DMA();
 }
 
-static inline void mga_g400_emit_context( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g400_emit_context( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -125,7 +126,7 @@
 	ADVANCE_DMA();
 }
 
-static inline void mga_g200_emit_tex0( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g200_emit_tex0( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
@@ -156,12 +157,15 @@
 	ADVANCE_DMA();
 }
 
-static inline void mga_g400_emit_tex0( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g400_emit_tex0( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
 	DMA_LOCALS;
 
+/*  	printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */
+/*  	       tex->texctl, tex->texctl2); */
+
 	BEGIN_DMA( 6 );
 
 	DMA_BLOCK( MGA_TEXCTL2,		tex->texctl2 | MGA_G400_TC2_MAGIC,
@@ -197,12 +201,15 @@
 	ADVANCE_DMA();
 }
 
-static inline void mga_g400_emit_tex1( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g400_emit_tex1( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
 	DMA_LOCALS;
 
+/*  	printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg,  */
+/*  	       tex->texctl, tex->texctl2); */
+
 	BEGIN_DMA( 5 );
 
 	DMA_BLOCK( MGA_TEXCTL2,		(tex->texctl2 |
@@ -235,7 +242,7 @@
 	ADVANCE_DMA();
 }
 
-static inline void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int pipe = sarea_priv->warp_pipe;
@@ -265,12 +272,14 @@
 	ADVANCE_DMA();
 }
 
-static inline void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
+static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int pipe = sarea_priv->warp_pipe;
 	DMA_LOCALS;
 
+/*  	printk("mga_g400_emit_pipe %x\n", pipe); */
+
 	BEGIN_DMA( 10 );
 
 	DMA_BLOCK( MGA_WIADDR2,	MGA_WMODE_SUSPEND,
@@ -411,7 +420,7 @@
 			   ctx->dstorg, dev_priv->front_offset,
 			   dev_priv->back_offset );
 		ctx->dstorg = 0;
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	return 0;
@@ -431,7 +440,7 @@
 		DRM_ERROR( "*** bad TEXORG: 0x%x, unit %d\n",
 			   tex->texorg, unit );
 		tex->texorg = 0;
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	return 0;
@@ -473,13 +482,13 @@
 	     dstorg + length > (dev_priv->texture_offset +
 				dev_priv->texture_size) ) {
 		DRM_ERROR( "*** bad iload DSTORG: 0x%x\n", dstorg );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	if ( length & MGA_ILOAD_MASK ) {
 		DRM_ERROR( "*** bad iload length: 0x%x\n",
 			   length & MGA_ILOAD_MASK );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	return 0;
@@ -492,7 +501,7 @@
 	     (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) {
 		DRM_ERROR( "*** bad blit: src=0x%x dst=0x%x\n",
 			   srcorg, dstorg );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	return 0;
 }
@@ -512,7 +521,7 @@
 	int nbox = sarea_priv->nbox;
 	int i;
 	DMA_LOCALS;
-	DRM_DEBUG("%s:\n" , __FUNCTION__);
+	DRM_DEBUG( "\n" );
 
 	BEGIN_DMA( 1 );
 
@@ -606,7 +615,7 @@
 	int nbox = sarea_priv->nbox;
 	int i;
 	DMA_LOCALS;
-	DRM_DEBUG( "%s:\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	sarea_priv->last_frame.head = dev_priv->prim.tail;
 	sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
@@ -760,8 +769,7 @@
 	u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM;
 	u32 y2;
 	DMA_LOCALS;
-	DRM_DEBUG( "%s: buf=%d used=%d\n",
-		   __FUNCTION__, buf->idx, buf->used );
+	DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used );
 
 	y2 = length / 64;
 
@@ -815,7 +823,7 @@
 	int nbox = sarea_priv->nbox;
 	u32 scandir = 0, i;
 	DMA_LOCALS;
-	DRM_DEBUG( "%s:\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	BEGIN_DMA( 4 + nbox );
 
@@ -872,19 +880,16 @@
  *
  */
 
-int mga_dma_clear( struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg )
+int mga_dma_clear( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_clear_t clear;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &clear, (drm_mga_clear_t *) arg, sizeof(clear) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( clear, (drm_mga_clear_t *)data, sizeof(clear) );
 
 	if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
@@ -900,11 +905,9 @@
 	return 0;
 }
 
-int mga_dma_swap( struct inode *inode, struct file *filp,
-		  unsigned int cmd, unsigned long arg )
+int mga_dma_swap( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 
@@ -924,11 +927,9 @@
 	return 0;
 }
 
-int mga_dma_vertex( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int mga_dma_vertex( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -937,12 +938,11 @@
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &vertex,
-			     (drm_mga_vertex_t *)arg,
-			     sizeof(vertex) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( vertex,
+			     (drm_mga_vertex_t *)data,
+			     sizeof(vertex) );
 
-        if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
+        if(vertex.idx < 0 || vertex.idx > dma->buf_count) return DRM_ERR(EINVAL);
 	buf = dma->buflist[vertex.idx];
 	buf_priv = buf->dev_private;
 
@@ -956,7 +956,7 @@
 			buf_priv->dispatched = 0;
 			mga_freelist_put( dev, buf );
 		}
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	WRAP_TEST_WITH_RETURN( dev_priv );
@@ -966,11 +966,9 @@
 	return 0;
 }
 
-int mga_dma_indices( struct inode *inode, struct file *filp,
-		     unsigned int cmd, unsigned long arg )
+int mga_dma_indices( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -979,12 +977,11 @@
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &indices,
-			     (drm_mga_indices_t *)arg,
-			     sizeof(indices) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( indices,
+			     (drm_mga_indices_t *)data,
+			     sizeof(indices) );
 
-        if(indices.idx < 0 || indices.idx > dma->buf_count) return -EINVAL;
+        if(indices.idx < 0 || indices.idx > dma->buf_count) return DRM_ERR(EINVAL);
 
 	buf = dma->buflist[indices.idx];
 	buf_priv = buf->dev_private;
@@ -998,7 +995,7 @@
 			buf_priv->dispatched = 0;
 			mga_freelist_put( dev, buf );
 		}
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	WRAP_TEST_WITH_RETURN( dev_priv );
@@ -1008,38 +1005,35 @@
 	return 0;
 }
 
-int mga_dma_iload( struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg )
+int mga_dma_iload( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_device_dma_t *dma = dev->dma;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_buf_t *buf;
 	drm_mga_buf_priv_t *buf_priv;
 	drm_mga_iload_t iload;
-	DRM_DEBUG( "%s:\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &iload, (drm_mga_iload_t *)arg, sizeof(iload) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( iload, (drm_mga_iload_t *)data, sizeof(iload) );
 
 #if 0
 	if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {
 		if ( MGA_DMA_DEBUG )
-			DRM_INFO( "%s: -EBUSY\n" , __FUNCTION__);
-		return -EBUSY;
+			DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ );
+		return DRM_ERR(EBUSY);
 	}
 #endif
-        if(iload.idx < 0 || iload.idx > dma->buf_count) return -EINVAL;
+        if(iload.idx < 0 || iload.idx > dma->buf_count) return DRM_ERR(EINVAL);
 
 	buf = dma->buflist[iload.idx];
 	buf_priv = buf->dev_private;
 
 	if ( mga_verify_iload( dev_priv, iload.dstorg, iload.length ) ) {
 		mga_freelist_put( dev, buf );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	WRAP_TEST_WITH_RETURN( dev_priv );
@@ -1053,26 +1047,23 @@
 	return 0;
 }
 
-int mga_dma_blit( struct inode *inode, struct file *filp,
-		  unsigned int cmd, unsigned long arg )
+int mga_dma_blit( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_blit_t blit;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &blit, (drm_mga_blit_t *)arg, sizeof(blit) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( blit, (drm_mga_blit_t *)data, sizeof(blit) );
 
 	if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 
 	if ( mga_verify_blit( dev_priv, blit.srcorg, blit.dstorg ) )
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 
 	WRAP_TEST_WITH_RETURN( dev_priv );
 
@@ -1084,3 +1075,36 @@
 
 	return 0;
 }
+
+int mga_getparam( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_getparam_t param;
+	int value;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t *)data,
+			     sizeof(param) );
+
+	DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
+
+	switch( param.param ) {
+	case MGA_PARAM_IRQ_NR:
+		value = dev->irq;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
+		DRM_ERROR( "copy_to_user\n" );
+		return DRM_ERR(EFAULT);
+	}
+	
+	return 0;
+}
diff -ruN drivers/char/drm-4.2/mga_warp.c drivers/char/drm/mga_warp.c
--- drivers/char/drm-4.2/mga_warp.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/mga_warp.c	2003-01-14 07:00:59.000000000 +0900
@@ -27,8 +27,11 @@
  *    Gareth Hughes <gareth@valinux.com>
  */
 
+#define __NO_VERSION__
 #include "mga.h"
 #include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
 #include "mga_drv.h"
 #include "mga_ucode.h"
 
@@ -104,7 +107,7 @@
 	if ( size > dev_priv->warp->size ) {
 		DRM_ERROR( "microcode too large! (%u > %lu)\n",
 			   size, dev_priv->warp->size );
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 	}
 
 	memset( dev_priv->warp_pipe_phys, 0,
@@ -141,7 +144,7 @@
 	if ( size > dev_priv->warp->size ) {
 		DRM_ERROR( "microcode too large! (%u > %lu)\n",
 			   size, dev_priv->warp->size );
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 	}
 
 	memset( dev_priv->warp_pipe_phys, 0,
@@ -167,7 +170,7 @@
 	case MGA_CARD_TYPE_G200:
 		return mga_warp_install_g200_microcode( dev_priv );
 	default:
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 }
 
@@ -192,7 +195,7 @@
 		MGA_WRITE( MGA_WVRTXSZ, 7 );
 		break;
 	default:
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	MGA_WRITE( MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
@@ -202,7 +205,7 @@
 	if ( wmisc != WMISC_EXPECTED ) {
 		DRM_ERROR( "WARP engine config failed! 0x%x != 0x%x\n",
 			   wmisc, WMISC_EXPECTED );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	return 0;
diff -ruN drivers/char/drm-4.2/picker.c drivers/char/drm/picker.c
--- drivers/char/drm-4.2/picker.c	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/picker.c	2003-01-14 07:00:59.000000000 +0900
@@ -0,0 +1,30 @@
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#ifndef CONFIG_SMP
+#define CONFIG_SMP 0
+#endif
+
+#ifndef CONFIG_MODULES
+#define CONFIG_MODULES 0
+#endif
+
+#ifndef CONFIG_MODVERSIONS
+#define CONFIG_MODVERSIONS 0
+#endif
+
+#ifndef CONFIG_AGP_MODULE
+#define CONFIG_AGP_MODULE 0
+#endif
+
+#ifndef CONFIG_AGP
+#define CONFIG_AGP 0
+#endif
+
+SMP = CONFIG_SMP
+MODULES = CONFIG_MODULES
+MODVERSIONS = CONFIG_MODVERSIONS
+AGP = CONFIG_AGP
+AGP_MODULE = CONFIG_AGP_MODULE
+RELEASE = UTS_RELEASE
diff -ruN drivers/char/drm-4.2/r128.h drivers/char/drm/r128.h
--- drivers/char/drm-4.2/r128.h	2001-08-09 01:42:15.000000000 +0900
+++ drivers/char/drm/r128.h	2003-01-14 07:01:00.000000000 +0900
@@ -43,6 +43,36 @@
 #define __HAVE_SG		1
 #define __HAVE_PCI_DMA		1
 
+#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
+
+#define DRIVER_NAME		"r128"
+#define DRIVER_DESC		"ATI Rage 128"
+#define DRIVER_DATE		"20021029"
+
+#define DRIVER_MAJOR		2
+#define DRIVER_MINOR		3
+#define DRIVER_PATCHLEVEL	0
+
+
+#define DRIVER_IOCTLS							    \
+   [DRM_IOCTL_NR(DRM_IOCTL_DMA)]             = { r128_cce_buffers,  1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)]       = { r128_cce_init,     1, 1 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)]  = { r128_cce_start,    1, 1 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)]   = { r128_cce_stop,     1, 1 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)]  = { r128_cce_reset,    1, 1 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)]   = { r128_cce_idle,     1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)]      = { r128_engine_reset, 1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)] = { r128_fullscreen,   1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)]       = { r128_cce_swap,     1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)]      = { r128_cce_clear,    1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)]     = { r128_cce_vertex,   1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)]    = { r128_cce_indices,  1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)]       = { r128_cce_blit,     1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)]      = { r128_cce_depth,    1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)]    = { r128_cce_stipple,  1, 0 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 }, \
+   [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)]   = { r128_getparam, 1, 0 },
+
 /* Driver customization:
  */
 #define DRIVER_PRERELEASE() do {					\
@@ -61,6 +91,9 @@
 /* DMA customization:
  */
 #define __HAVE_DMA		1
+#define __HAVE_DMA_IRQ		1
+#define __HAVE_VBL_IRQ		1
+#define __HAVE_SHARED_IRQ       1
 
 #if 0
 /* GH: Remove this for now... */
diff -ruN drivers/char/drm-4.2/r128_cce.c drivers/char/drm/r128_cce.c
--- drivers/char/drm-4.2/r128_cce.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/r128_cce.c	2003-01-14 07:00:59.000000000 +0900
@@ -30,14 +30,12 @@
 
 #include "r128.h"
 #include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
 #include "r128_drv.h"
 
-#include <linux/interrupt.h>	/* For task queue support */
-#include <linux/delay.h>
-
 #define R128_FIFO_DEBUG		0
 
-
 /* CCE microcode (from ATI) */
 static u32 r128_cce_microcode[] = {
 	0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
@@ -83,6 +81,7 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+int r128_do_wait_for_idle( drm_r128_private_t *dev_priv );
 
 int R128_READ_PLL(drm_device_t *dev, int addr)
 {
@@ -127,13 +126,13 @@
 		if ( !(R128_READ( R128_PC_NGUI_CTLSTAT ) & R128_PC_BUSY) ) {
 			return 0;
 		}
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 #if R128_FIFO_DEBUG
-	DRM_ERROR( "%s failed!\n", __FUNCTION__ );
+	DRM_ERROR( "failed!\n" );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries )
@@ -143,13 +142,13 @@
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
 		int slots = R128_READ( R128_GUI_STAT ) & R128_GUI_FIFOCNT_MASK;
 		if ( slots >= entries ) return 0;
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 #if R128_FIFO_DEBUG
-	DRM_ERROR( "%s failed!\n", __FUNCTION__ );
+	DRM_ERROR( "failed!\n" );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
@@ -157,20 +156,20 @@
 	int i, ret;
 
 	ret = r128_do_wait_for_fifo( dev_priv, 64 );
-	if ( ret < 0 ) return ret;
+	if ( ret ) return ret;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
 		if ( !(R128_READ( R128_GUI_STAT ) & R128_GUI_ACTIVE) ) {
 			r128_do_pixcache_flush( dev_priv );
 			return 0;
 		}
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 #if R128_FIFO_DEBUG
-	DRM_ERROR( "%s failed!\n", __FUNCTION__ );
+	DRM_ERROR( "failed!\n" );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 
@@ -183,7 +182,7 @@
 {
 	int i;
 
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	r128_do_wait_for_idle( dev_priv );
 
@@ -224,14 +223,14 @@
 				return r128_do_pixcache_flush( dev_priv );
 			}
 		}
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 #if R128_FIFO_DEBUG
 	DRM_ERROR( "failed!\n" );
 	r128_status( dev_priv );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 /* Start the Concurrent Command Engine.
@@ -319,7 +318,7 @@
 	u32 ring_start;
 	u32 tmp;
 
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	/* The manual (p. 2) says this address is in "VM space".  This
 	 * means it's an offset from the start of AGP space.
@@ -351,8 +350,8 @@
 
 		R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
      			    entry->busaddr[page_ofs]);
-		DRM_DEBUG( "ring rptr: offset=0x%08llx handle=0x%08lx\n",
-			   (u64)entry->busaddr[page_ofs],
+		DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
+			   entry->busaddr[page_ofs],
      			   entry->handle + tmp_ofs );
 	}
 
@@ -374,13 +373,12 @@
 static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 {
 	drm_r128_private_t *dev_priv;
-	struct list_head *list;
 
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
 	if ( dev_priv == NULL )
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 
 	memset( dev_priv, 0, sizeof(drm_r128_private_t) );
 
@@ -390,7 +388,7 @@
 		DRM_ERROR( "PCI GART memory not allocated!\n" );
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	dev_priv->usec_timeout = init->usec_timeout;
@@ -399,7 +397,7 @@
 		DRM_DEBUG( "TIMEOUT problem!\n" );
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	dev_priv->cce_mode = init->cce_mode;
@@ -419,7 +417,7 @@
 		DRM_DEBUG( "Bad cce_mode!\n" );
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	switch ( init->cce_mode ) {
@@ -481,20 +479,13 @@
 	dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
 					 (dev_priv->span_offset >> 5));
 
-	list_for_each(list, &dev->maplist->head) {
-		drm_map_list_t *r_list = (drm_map_list_t *)list;
-		if( r_list->map &&
-		    r_list->map->type == _DRM_SHM &&
-		    r_list->map->flags & _DRM_CONTAINS_LOCK ) {
-			dev_priv->sarea = r_list->map;
- 			break;
- 		}
- 	}
+	DRM_GETSAREA();
+	
 	if(!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
@@ -502,35 +493,35 @@
 		DRM_ERROR("could not find framebuffer!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->cce_ring, init->ring_offset );
 	if(!dev_priv->cce_ring) {
 		DRM_ERROR("could not find cce ring region!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
 	if(!dev_priv->ring_rptr) {
 		DRM_ERROR("could not find ring read pointer!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
 	if(!dev_priv->buffers) {
 		DRM_ERROR("could not find dma buffer region!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	if ( !dev_priv->is_pci ) {
@@ -540,7 +531,7 @@
 			DRM_ERROR("could not find agp texture region!\n");
 			dev->dev_private = (void *)dev_priv;
 			r128_do_cleanup_cce( dev );
-			return -EINVAL;
+			return DRM_ERR(EINVAL);
 		}
 	}
 
@@ -558,7 +549,7 @@
 			DRM_ERROR("Could not ioremap agp regions!\n");
 			dev->dev_private = (void *)dev_priv;
 			r128_do_cleanup_cce( dev );
-			return -ENOMEM;
+			return DRM_ERR(ENOMEM);
 		}
 	} else {
 		dev_priv->cce_ring->handle =
@@ -596,16 +587,18 @@
 	R128_WRITE( R128_LAST_DISPATCH_REG,
 		    dev_priv->sarea_priv->last_dispatch );
 
+#if __REALLY_HAVE_SG
 	if ( dev_priv->is_pci ) {
 		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
      					    &dev_priv->bus_pci_gart) ) {
 			DRM_ERROR( "failed to init PCI GART!\n" );
 			dev->dev_private = (void *)dev_priv;
 			r128_do_cleanup_cce( dev );
-			return -ENOMEM;
+			return DRM_ERR(ENOMEM);
 		}
 		R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
 	}
+#endif
 
 	r128_cce_init_ring_buffer( dev, dev_priv );
 	r128_cce_load_microcode( dev_priv );
@@ -622,16 +615,20 @@
 	if ( dev->dev_private ) {
 		drm_r128_private_t *dev_priv = dev->dev_private;
 
+#if __REALLY_HAVE_SG
 		if ( !dev_priv->is_pci ) {
+#endif
 			DRM_IOREMAPFREE( dev_priv->cce_ring );
 			DRM_IOREMAPFREE( dev_priv->ring_rptr );
 			DRM_IOREMAPFREE( dev_priv->buffers );
+#if __REALLY_HAVE_SG
 		} else {
 			if (!DRM(ati_pcigart_cleanup)( dev,
 						dev_priv->phys_pci_gart,
 						dev_priv->bus_pci_gart ))
 				DRM_ERROR( "failed to cleanup PCI GART!\n" );
 		}
+#endif
 
 		DRM(free)( dev->dev_private, sizeof(drm_r128_private_t),
 			   DRM_MEM_DRIVER );
@@ -641,17 +638,14 @@
 	return 0;
 }
 
-int r128_cce_init( struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg )
+int r128_cce_init( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_init_t init;
 
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
-	if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) );
 
 	switch ( init.func ) {
 	case R128_INIT_CCE:
@@ -660,16 +654,14 @@
 		return r128_do_cleanup_cce( dev );
 	}
 
-	return -EINVAL;
+	return DRM_ERR(EINVAL);
 }
 
-int r128_cce_start( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int r128_cce_start( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
@@ -686,20 +678,17 @@
 /* Stop the CCE.  The engine must have been idled before calling this
  * routine.
  */
-int r128_cce_stop( struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg )
+int r128_cce_stop( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_cce_stop_t stop;
 	int ret;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &stop, (drm_r128_init_t *)arg, sizeof(stop) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t *)data, sizeof(stop) );
 
 	/* Flush any pending CCE commands.  This ensures any outstanding
 	 * commands are exectuted by the engine before we turn it off.
@@ -713,7 +702,7 @@
 	 */
 	if ( stop.idle ) {
 		ret = r128_do_cce_idle( dev_priv );
-		if ( ret < 0 ) return ret;
+		if ( ret ) return ret;
 	}
 
 	/* Finally, we can turn off the CCE.  If the engine isn't idle,
@@ -730,19 +719,17 @@
 
 /* Just reset the CCE ring.  Called as part of an X Server engine reset.
  */
-int r128_cce_reset( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int r128_cce_reset( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( !dev_priv ) {
 		DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	r128_do_cce_reset( dev_priv );
@@ -753,13 +740,11 @@
 	return 0;
 }
 
-int r128_cce_idle( struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg )
+int r128_cce_idle( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
@@ -770,12 +755,10 @@
 	return r128_do_cce_idle( dev_priv );
 }
 
-int r128_engine_reset( struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg )
+int r128_engine_reset( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEVICE;
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
@@ -790,7 +773,7 @@
 static int r128_do_init_pageflip( drm_device_t *dev )
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	dev_priv->crtc_offset =      R128_READ( R128_CRTC_OFFSET );
 	dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
@@ -808,7 +791,7 @@
 int r128_do_cleanup_pageflip( drm_device_t *dev )
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	R128_WRITE( R128_CRTC_OFFSET,      dev_priv->crtc_offset );
 	R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
@@ -819,17 +802,14 @@
 	return 0;
 }
 
-int r128_fullscreen( struct inode *inode, struct file *filp,
-		     unsigned int cmd, unsigned long arg )
+int r128_fullscreen( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_fullscreen_t fs;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &fs, (drm_r128_fullscreen_t *)arg, sizeof(fs) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( fs, (drm_r128_fullscreen_t *)data, sizeof(fs) );
 
 	switch ( fs.func ) {
 	case R128_INIT_FULLSCREEN:
@@ -838,7 +818,7 @@
 		return r128_do_cleanup_pageflip( dev );
 	}
 
-	return -EINVAL;
+	return DRM_ERR(EINVAL);
 }
 
 
@@ -861,7 +841,7 @@
 	dev_priv->head = DRM(alloc)( sizeof(drm_r128_freelist_t),
 				     DRM_MEM_DRIVER );
 	if ( dev_priv->head == NULL )
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 
 	memset( dev_priv->head, 0, sizeof(drm_r128_freelist_t) );
 	dev_priv->head->age = R128_BUFFER_USED;
@@ -872,7 +852,7 @@
 
 		entry = DRM(alloc)( sizeof(drm_r128_freelist_t),
 				    DRM_MEM_DRIVER );
-		if ( !entry ) return -ENOMEM;
+		if ( !entry ) return DRM_ERR(ENOMEM);
 
 		entry->age = R128_BUFFER_FREE;
 		entry->buf = buf;
@@ -927,7 +907,7 @@
 				return buf;
 			}
 		}
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 	DRM_ERROR( "returning NULL!\n" );
@@ -960,12 +940,12 @@
 		r128_update_ring_snapshot( ring );
 		if ( ring->space >= n )
 			return 0;
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 	/* FIXME: This is being ignored... */
 	DRM_ERROR( "failed!\n" );
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 static int r128_cce_get_buffers( drm_device_t *dev, drm_dma_t *d )
@@ -975,50 +955,47 @@
 
 	for ( i = d->granted_count ; i < d->request_count ; i++ ) {
 		buf = r128_freelist_get( dev );
-		if ( !buf ) return -EAGAIN;
+		if ( !buf ) return DRM_ERR(EAGAIN);
 
-		buf->pid = current->pid;
+		buf->pid = DRM_CURRENTPID;
 
-		if ( copy_to_user( &d->request_indices[i], &buf->idx,
+		if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
 				   sizeof(buf->idx) ) )
-			return -EFAULT;
-		if ( copy_to_user( &d->request_sizes[i], &buf->total,
+			return DRM_ERR(EFAULT);
+		if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
 				   sizeof(buf->total) ) )
-			return -EFAULT;
+			return DRM_ERR(EFAULT);
 
 		d->granted_count++;
 	}
 	return 0;
 }
 
-int r128_cce_buffers( struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg )
+int r128_cce_buffers( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_device_dma_t *dma = dev->dma;
 	int ret = 0;
 	drm_dma_t d;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *) data, sizeof(d) );
 
 	/* Please don't send us buffers.
 	 */
 	if ( d.send_count != 0 ) {
 		DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
-			   current->pid, d.send_count );
-		return -EINVAL;
+			   DRM_CURRENTPID, d.send_count );
+		return DRM_ERR(EINVAL);
 	}
 
 	/* We'll send you buffers.
 	 */
 	if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
 		DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
-			   current->pid, d.request_count, dma->buf_count );
-		return -EINVAL;
+			   DRM_CURRENTPID, d.request_count, dma->buf_count );
+		return DRM_ERR(EINVAL);
 	}
 
 	d.granted_count = 0;
@@ -1027,8 +1004,7 @@
 		ret = r128_cce_get_buffers( dev, &d );
 	}
 
-	if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) )
-		return -EFAULT;
+	DRM_COPY_TO_USER_IOCTL((drm_dma_t *) data, d, sizeof(d) );
 
 	return ret;
 }
diff -ruN drivers/char/drm-4.2/r128_drm.h drivers/char/drm/r128_drm.h
--- drivers/char/drm-4.2/r128_drm.h	2001-08-09 01:42:15.000000000 +0900
+++ drivers/char/drm/r128_drm.h	2003-01-14 07:01:00.000000000 +0900
@@ -170,6 +170,28 @@
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the Xserver file (xf86drmR128.h)
  */
+
+/* Rage 128 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_IOCTL_R128_INIT		DRM_IOW( 0x40, drm_r128_init_t)
+#define DRM_IOCTL_R128_CCE_START	DRM_IO(  0x41)
+#define DRM_IOCTL_R128_CCE_STOP		DRM_IOW( 0x42, drm_r128_cce_stop_t)
+#define DRM_IOCTL_R128_CCE_RESET	DRM_IO(  0x43)
+#define DRM_IOCTL_R128_CCE_IDLE		DRM_IO(  0x44)
+#define DRM_IOCTL_R128_RESET		DRM_IO(  0x46)
+#define DRM_IOCTL_R128_SWAP		DRM_IO(  0x47)
+#define DRM_IOCTL_R128_CLEAR		DRM_IOW( 0x48, drm_r128_clear_t)
+#define DRM_IOCTL_R128_VERTEX		DRM_IOW( 0x49, drm_r128_vertex_t)
+#define DRM_IOCTL_R128_INDICES		DRM_IOW( 0x4a, drm_r128_indices_t)
+#define DRM_IOCTL_R128_BLIT		DRM_IOW( 0x4b, drm_r128_blit_t)
+#define DRM_IOCTL_R128_DEPTH		DRM_IOW( 0x4c, drm_r128_depth_t)
+#define DRM_IOCTL_R128_STIPPLE		DRM_IOW( 0x4d, drm_r128_stipple_t)
+#define DRM_IOCTL_R128_INDIRECT		DRM_IOWR(0x4f, drm_r128_indirect_t)
+#define DRM_IOCTL_R128_FULLSCREEN	DRM_IOW( 0x50, drm_r128_fullscreen_t)
+#define DRM_IOCTL_R128_CLEAR2		DRM_IOW( 0x51, drm_r128_clear2_t)
+#define DRM_IOCTL_R128_GETPARAM		DRM_IOW( 0x52, drm_r128_getparam_t)
+
 typedef struct drm_r128_init {
 	enum {
 		R128_INIT_CCE    = 0x01,
@@ -284,4 +306,14 @@
 	} func;
 } drm_r128_fullscreen_t;
 
+/* 2.3: An ioctl to get parameters that aren't available to the 3d
+ * client any other way.  
+ */
+#define R128_PARAM_IRQ_NR            1
+
+typedef struct drm_r128_getparam {
+	int param;
+	int *value;
+} drm_r128_getparam_t;
+
 #endif
diff -ruN drivers/char/drm-4.2/r128_drv.c drivers/char/drm/r128_drv.c
--- drivers/char/drm-4.2/r128_drv.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/r128_drv.c	2003-01-14 07:00:59.000000000 +0900
@@ -32,48 +32,11 @@
 #include <linux/config.h>
 #include "r128.h"
 #include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
 #include "r128_drv.h"
 #include "ati_pcigart.h"
 
-#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
-
-#define DRIVER_NAME		"r128"
-#define DRIVER_DESC		"ATI Rage 128"
-#define DRIVER_DATE		"20010917"
-
-#define DRIVER_MAJOR		2
-#define DRIVER_MINOR		2
-#define DRIVER_PATCHLEVEL	0
-
-#define DRIVER_IOCTLS							    \
-   [DRM_IOCTL_NR(DRM_IOCTL_DMA)]             = { r128_cce_buffers,  1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)]       = { r128_cce_init,     1, 1 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)]  = { r128_cce_start,    1, 1 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)]   = { r128_cce_stop,     1, 1 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)]  = { r128_cce_reset,    1, 1 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)]   = { r128_cce_idle,     1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)]      = { r128_engine_reset, 1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_FULLSCREEN)] = { r128_fullscreen,   1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)]       = { r128_cce_swap,     1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)]      = { r128_cce_clear,    1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)]     = { r128_cce_vertex,   1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)]    = { r128_cce_indices,  1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)]       = { r128_cce_blit,     1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)]      = { r128_cce_depth,    1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)]    = { r128_cce_stipple,  1, 0 }, \
-   [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 },
-
-
-#if 0
-/* GH: Count data sent to card via ring or vertex/indirect buffers.
- */
-#define __HAVE_COUNTERS         3
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-#endif
-
-
 #include "drm_agpsupport.h"
 #include "drm_auth.h"
 #include "drm_bufs.h"
@@ -81,26 +44,6 @@
 #include "drm_dma.h"
 #include "drm_drawable.h"
 #include "drm_drv.h"
-
-#ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO).  It calls the insmod option
- * routine, drm_parse_drm.
- */
-
-/* JH- We have to hand expand the string ourselves because of the cpp.  If
- * anyone can think of a way that we can fit into the __setup macro without
- * changing it, then please send the solution my way.
- */
-static int __init r128_options( char *str )
-{
-	DRM(parse_options)( str );
-	return 1;
-}
-
-__setup( DRIVER_NAME "=", r128_options );
-#endif
-
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
diff -ruN drivers/char/drm-4.2/r128_drv.h drivers/char/drm/r128_drv.h
--- drivers/char/drm-4.2/r128_drv.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/r128_drv.h	2003-01-14 07:01:00.000000000 +0900
@@ -34,8 +34,8 @@
 #ifndef __R128_DRV_H__
 #define __R128_DRV_H__
 
-#define GET_RING_HEAD( ring )		le32_to_cpu( *(ring)->head )
-#define SET_RING_HEAD( ring, val )	*(ring)->head = cpu_to_le32( val )
+#define GET_RING_HEAD(ring)		DRM_READ32(  (volatile u32 *) (ring)->head )
+#define SET_RING_HEAD(ring,val)		DRM_WRITE32( (volatile u32 *) (ring)->head, (val) )
 
 typedef struct drm_r128_freelist {
    	unsigned int age;
@@ -116,29 +116,22 @@
 } drm_r128_buf_priv_t;
 
 				/* r128_cce.c */
-extern int r128_cce_init( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int r128_cce_start( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int r128_cce_stop( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int r128_cce_reset( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int r128_cce_idle( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int r128_engine_reset( struct inode *inode, struct file *filp,
-			      unsigned int cmd, unsigned long arg );
-extern int r128_fullscreen( struct inode *inode, struct file *filp,
-			    unsigned int cmd, unsigned long arg );
-extern int r128_cce_buffers( struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg );
+extern int r128_cce_init( DRM_IOCTL_ARGS );
+extern int r128_cce_start( DRM_IOCTL_ARGS );
+extern int r128_cce_stop( DRM_IOCTL_ARGS );
+extern int r128_cce_reset( DRM_IOCTL_ARGS );
+extern int r128_cce_idle( DRM_IOCTL_ARGS );
+extern int r128_engine_reset( DRM_IOCTL_ARGS );
+extern int r128_fullscreen( DRM_IOCTL_ARGS );
+extern int r128_cce_buffers( DRM_IOCTL_ARGS );
+extern int r128_getparam( DRM_IOCTL_ARGS );
 
 extern void r128_freelist_reset( drm_device_t *dev );
 extern drm_buf_t *r128_freelist_get( drm_device_t *dev );
 
 extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
 
-static inline void
+static __inline__ void
 r128_update_ring_snapshot( drm_r128_ring_buffer_t *ring )
 {
 	ring->space = (GET_RING_HEAD( ring ) - ring->tail) * sizeof(u32);
@@ -151,22 +144,14 @@
 extern int r128_do_cleanup_pageflip( drm_device_t *dev );
 
 				/* r128_state.c */
-extern int r128_cce_clear( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int r128_cce_swap( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int r128_cce_vertex( struct inode *inode, struct file *filp,
-			    unsigned int cmd, unsigned long arg );
-extern int r128_cce_indices( struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg );
-extern int r128_cce_blit( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int r128_cce_depth( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int r128_cce_stipple( struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg );
-extern int r128_cce_indirect( struct inode *inode, struct file *filp,
-			      unsigned int cmd, unsigned long arg );
+extern int r128_cce_clear( DRM_IOCTL_ARGS );
+extern int r128_cce_swap( DRM_IOCTL_ARGS );
+extern int r128_cce_vertex( DRM_IOCTL_ARGS );
+extern int r128_cce_indices( DRM_IOCTL_ARGS );
+extern int r128_cce_blit( DRM_IOCTL_ARGS );
+extern int r128_cce_depth( DRM_IOCTL_ARGS );
+extern int r128_cce_stipple( DRM_IOCTL_ARGS );
+extern int r128_cce_indirect( DRM_IOCTL_ARGS );
 
 
 /* Register definitions, register access macros and drmAddMap constants
@@ -229,6 +214,11 @@
 #define R128_DST_PITCH_OFFSET_C		0x1c80
 #	define R128_DST_TILE			(1 << 31)
 
+#define R128_GEN_INT_CNTL		0x0040
+#	define R128_CRTC_VBLANK_INT_EN		(1 <<  0)
+#define R128_GEN_INT_STATUS		0x0044
+#	define R128_CRTC_VBLANK_INT		(1 <<  0)
+#	define R128_CRTC_VBLANK_INT_AK		(1 <<  0)
 #define R128_GEN_RESET_CNTL		0x00f0
 #	define R128_SOFT_RESET_GUI		(1 <<  0)
 
@@ -384,44 +374,11 @@
 #define R128_BASE(reg)		((unsigned long)(dev_priv->mmio->handle))
 #define R128_ADDR(reg)		(R128_BASE( reg ) + reg)
 
-#define R128_DEREF(reg)		*(volatile u32 *)R128_ADDR( reg )
-#ifdef __alpha__
-#define R128_READ(reg)		(_R128_READ((u32 *)R128_ADDR(reg)))
-static inline u32 _R128_READ(u32 *addr)
-{
-	mb();
-	return *(volatile u32 *)addr;
-}
-#define R128_WRITE(reg,val)						\
-do {									\
-	wmb();								\
-	R128_DEREF(reg) = val;						\
-} while (0)
-#else
-#define R128_READ(reg)		le32_to_cpu( R128_DEREF( reg ) )
-#define R128_WRITE(reg,val)						\
-do {									\
-	R128_DEREF( reg ) = cpu_to_le32( val );				\
-} while (0)
-#endif
+#define R128_READ(reg)		DRM_READ32(  (volatile u32 *) R128_ADDR(reg) )
+#define R128_WRITE(reg,val)	DRM_WRITE32( (volatile u32 *) R128_ADDR(reg), (val) )
 
-#define R128_DEREF8(reg)	*(volatile u8 *)R128_ADDR( reg )
-#ifdef __alpha__
-#define R128_READ8(reg)		_R128_READ8((u8 *)R128_ADDR(reg))
-static inline u8 _R128_READ8(u8 *addr)
-{
-	mb();
-	return *(volatile u8 *)addr;
-}
-#define R128_WRITE8(reg,val)						\
-do {									\
-	wmb();								\
-	R128_DEREF8(reg) = val;						\
-} while (0)
-#else
-#define R128_READ8(reg)		R128_DEREF8( reg )
-#define R128_WRITE8(reg,val)	do { R128_DEREF8( reg ) = val; } while (0)
-#endif
+#define R128_READ8(reg)		DRM_READ8(  (volatile u8 *) R128_ADDR(reg) )
+#define R128_WRITE8(reg,val)	DRM_WRITE8( (volatile u8 *) R128_ADDR(reg), (val) )
 
 #define R128_WRITE_PLL(addr,val)					\
 do {									\
@@ -449,10 +406,9 @@
 #define LOCK_TEST_WITH_RETURN( dev )					\
 do {									\
 	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||		\
-	     dev->lock.pid != current->pid ) {				\
-		DRM_ERROR( "%s called without lock held\n",		\
-			   __FUNCTION__ );				\
-		return -EINVAL;						\
+	     dev->lock.pid != DRM_CURRENTPID ) {			\
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );	\
+		return DRM_ERR(EINVAL);				\
 	}								\
 } while (0)
 
@@ -464,12 +420,13 @@
 			r128_update_ring_snapshot( ring );		\
 			if ( ring->space >= ring->high_mark )		\
 				goto __ring_space_done;			\
-			udelay( 1 );					\
+			DRM_UDELAY(1);				\
 		}							\
 		DRM_ERROR( "ring space check failed!\n" );		\
-		return -EBUSY;						\
+		return DRM_ERR(EBUSY);				\
 	}								\
- __ring_space_done: ;							\
+ __ring_space_done:							\
+	;								\
 } while (0)
 
 #define VB_AGE_TEST_WITH_RETURN( dev_priv )				\
@@ -477,7 +434,7 @@
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;		\
 	if ( sarea_priv->last_dispatch >= R128_MAX_VB_AGE ) {		\
 		int __ret = r128_do_cce_idle( dev_priv );		\
-		if ( __ret < 0 ) return __ret;				\
+		if ( __ret ) return __ret;				\
 		sarea_priv->last_dispatch = 0;				\
 		r128_freelist_reset( dev );				\
 	}								\
@@ -493,7 +450,11 @@
  * Ring control
  */
 
-#define r128_flush_write_combine()	mb()
+#if defined(__powerpc__)
+#define r128_flush_write_combine()	(void) GET_RING_HEAD( &dev_priv->ring )
+#else
+#define r128_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
+#endif
 
 
 #define R128_VERBOSE	0
diff -ruN drivers/char/drm-4.2/r128_irq.c drivers/char/drm/r128_irq.c
--- drivers/char/drm-4.2/r128_irq.c	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/r128_irq.c	2003-01-14 07:00:59.000000000 +0900
@@ -0,0 +1,100 @@
+/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ * 
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#include "r128.h"
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+#include "r128_drv.h"
+
+void r128_dma_service( DRM_IRQ_ARGS )
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_r128_private_t *dev_priv = 
+	   (drm_r128_private_t *)dev->dev_private;
+	int status;
+
+	status = R128_READ( R128_GEN_INT_STATUS );
+	
+	/* VBLANK interrupt */
+	if ( status & R128_CRTC_VBLANK_INT ) {
+		R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
+		atomic_inc(&dev->vbl_received);
+		DRM_WAKEUP(&dev->vbl_queue);
+		DRM(vbl_send_signals)( dev );
+	}
+}
+
+int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+{
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks... 
+	 */
+	DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, 
+		     ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+			 - *sequence ) <= (1<<23) ) );
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+void r128_driver_irq_preinstall( drm_device_t *dev ) {
+  	drm_r128_private_t *dev_priv = 
+	   (drm_r128_private_t *)dev->dev_private;
+
+	/* Disable *all* interrupts */
+      	R128_WRITE( R128_GEN_INT_CNTL, 0 );
+	/* Clear vblank bit if it's already high */
+   	R128_WRITE( R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK );
+}
+
+void r128_driver_irq_postinstall( drm_device_t *dev ) {
+  	drm_r128_private_t *dev_priv = 
+	   (drm_r128_private_t *)dev->dev_private;
+
+	/* Turn on VBL interrupt */
+   	R128_WRITE( R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN );
+}
+
+void r128_driver_irq_uninstall( drm_device_t *dev ) {
+  	drm_r128_private_t *dev_priv = 
+	   (drm_r128_private_t *)dev->dev_private;
+	if ( dev_priv ) {
+		/* Disable *all* interrupts */
+		R128_WRITE( R128_GEN_INT_CNTL, 0 );
+	}
+}
diff -ruN drivers/char/drm-4.2/r128_state.c drivers/char/drm/r128_state.c
--- drivers/char/drm-4.2/r128_state.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/r128_state.c	2003-01-14 07:00:59.000000000 +0900
@@ -29,9 +29,9 @@
 
 #include "r128.h"
 #include "drmP.h"
-#include "r128_drv.h"
 #include "drm.h"
-#include <linux/delay.h>
+#include "r128_drm.h"
+#include "r128_drv.h"
 
 
 /* ================================================================
@@ -81,7 +81,7 @@
 	ADVANCE_RING();
 }
 
-static inline void r128_emit_core( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_core( drm_r128_private_t *dev_priv )
 {
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -96,7 +96,7 @@
 	ADVANCE_RING();
 }
 
-static inline void r128_emit_context( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_context( drm_r128_private_t *dev_priv )
 {
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -122,7 +122,7 @@
 	ADVANCE_RING();
 }
 
-static inline void r128_emit_setup( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_setup( drm_r128_private_t *dev_priv )
 {
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -138,7 +138,7 @@
 	ADVANCE_RING();
 }
 
-static inline void r128_emit_masks( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_masks( drm_r128_private_t *dev_priv )
 {
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -157,7 +157,7 @@
 	ADVANCE_RING();
 }
 
-static inline void r128_emit_window( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_window( drm_r128_private_t *dev_priv )
 {
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -172,7 +172,7 @@
 	ADVANCE_RING();
 }
 
-static inline void r128_emit_tex0( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_tex0( drm_r128_private_t *dev_priv )
 {
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
@@ -199,7 +199,7 @@
 	ADVANCE_RING();
 }
 
-static inline void r128_emit_tex1( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_tex1( drm_r128_private_t *dev_priv )
 {
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
@@ -223,7 +223,7 @@
 	ADVANCE_RING();
 }
 
-static inline void r128_emit_state( drm_r128_private_t *dev_priv )
+static __inline__ void r128_emit_state( drm_r128_private_t *dev_priv )
 {
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int dirty = sarea_priv->dirty;
@@ -528,7 +528,7 @@
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
-	DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
+	DRM_DEBUG( "page=%d\n", dev_priv->current_page );
 
 #if R128_PERFORMANCE_BOXES
 	/* Do some trivial performance monitoring...
@@ -577,8 +577,7 @@
 	int prim = buf_priv->prim;
 	int i = 0;
 	RING_LOCALS;
-	DRM_DEBUG( "%s: buf=%d nbox=%d\n",
-		   __FUNCTION__, buf->idx, sarea_priv->nbox );
+	DRM_DEBUG( "buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox );
 
 	if ( 0 )
 		r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
@@ -789,7 +788,7 @@
 	u32 *data;
 	int dword_shift, dwords;
 	RING_LOCALS;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	/* The compiler won't optimize away a division by a variable,
 	 * even if the only legal values are powers of two.  Thus, we'll
@@ -810,7 +809,7 @@
 		break;
 	default:
 		DRM_ERROR( "invalid blit format %d\n", blit->format );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	/* Flush the pixel cache, and mark the contents as Read Invalid.
@@ -830,14 +829,14 @@
 	buf = dma->buflist[blit->idx];
 	buf_priv = buf->dev_private;
 
-	if ( buf->pid != current->pid ) {
+	if ( buf->pid != DRM_CURRENTPID ) {
 		DRM_ERROR( "process %d using buffer owned by %d\n",
-			   current->pid, buf->pid );
-		return -EINVAL;
+			   DRM_CURRENTPID, buf->pid );
+		return DRM_ERR(EINVAL);
 	}
 	if ( buf->pending ) {
 		DRM_ERROR( "sending pending buffer %d\n", blit->idx );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	buf_priv->discard = 1;
@@ -899,36 +898,36 @@
 	u8 *mask;
 	int i;
 	RING_LOCALS;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	count = depth->n;
-	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
-		return -EFAULT;
+	if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
+		return DRM_ERR(EFAULT);
 	}
-	if ( copy_from_user( &y, depth->y, sizeof(y) ) ) {
-		return -EFAULT;
+	if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
+		return DRM_ERR(EFAULT);
 	}
 
-	buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL );
+	buffer = DRM_MALLOC( depth->n * sizeof(u32) );
 	if ( buffer == NULL )
-		return -ENOMEM;
-	if ( copy_from_user( buffer, depth->buffer,
+		return DRM_ERR(ENOMEM);
+	if ( DRM_COPY_FROM_USER( buffer, depth->buffer,
 			     depth->n * sizeof(u32) ) ) {
-		kfree( buffer );
-		return -EFAULT;
+		DRM_FREE( buffer );
+		return DRM_ERR(EFAULT);
 	}
 
 	if ( depth->mask ) {
-		mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL );
+		mask = DRM_MALLOC( depth->n * sizeof(u8) );
 		if ( mask == NULL ) {
-			kfree( buffer );
-			return -ENOMEM;
+			DRM_FREE( buffer );
+			return DRM_ERR(ENOMEM);
 		}
-		if ( copy_from_user( mask, depth->mask,
+		if ( DRM_COPY_FROM_USER( mask, depth->mask,
 				     depth->n * sizeof(u8) ) ) {
-			kfree( buffer );
-			kfree( mask );
-			return -EFAULT;
+			DRM_FREE( buffer );
+			DRM_FREE( mask );
+			return DRM_ERR(EFAULT);
 		}
 
 		for ( i = 0 ; i < count ; i++, x++ ) {
@@ -954,7 +953,7 @@
 			}
 		}
 
-		kfree( mask );
+		DRM_FREE( mask );
 	} else {
 		for ( i = 0 ; i < count ; i++, x++ ) {
 			BEGIN_RING( 6 );
@@ -978,7 +977,7 @@
 		}
 	}
 
-	kfree( buffer );
+	DRM_FREE( buffer );
 
 	return 0;
 }
@@ -992,59 +991,59 @@
 	u8 *mask;
 	int i;
 	RING_LOCALS;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	count = depth->n;
 
-	x = kmalloc( count * sizeof(*x), GFP_KERNEL );
+	x = DRM_MALLOC( count * sizeof(*x) );
 	if ( x == NULL ) {
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 	}
-	y = kmalloc( count * sizeof(*y), GFP_KERNEL );
+	y = DRM_MALLOC( count * sizeof(*y) );
 	if ( y == NULL ) {
-		kfree( x );
-		return -ENOMEM;
+		DRM_FREE( x );
+		return DRM_ERR(ENOMEM);
 	}
-	if ( copy_from_user( x, depth->x, count * sizeof(int) ) ) {
-		kfree( x );
-		kfree( y );
-		return -EFAULT;
+	if ( DRM_COPY_FROM_USER( x, depth->x, count * sizeof(int) ) ) {
+		DRM_FREE( x );
+		DRM_FREE( y );
+		return DRM_ERR(EFAULT);
 	}
-	if ( copy_from_user( y, depth->y, count * sizeof(int) ) ) {
-		kfree( x );
-		kfree( y );
-		return -EFAULT;
+	if ( DRM_COPY_FROM_USER( y, depth->y, count * sizeof(int) ) ) {
+		DRM_FREE( x );
+		DRM_FREE( y );
+		return DRM_ERR(EFAULT);
 	}
 
-	buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL );
+	buffer = DRM_MALLOC( depth->n * sizeof(u32) );
 	if ( buffer == NULL ) {
-		kfree( x );
-		kfree( y );
-		return -ENOMEM;
+		DRM_FREE( x );
+		DRM_FREE( y );
+		return DRM_ERR(ENOMEM);
 	}
-	if ( copy_from_user( buffer, depth->buffer,
+	if ( DRM_COPY_FROM_USER( buffer, depth->buffer,
 			     depth->n * sizeof(u32) ) ) {
-		kfree( x );
-		kfree( y );
-		kfree( buffer );
-		return -EFAULT;
+		DRM_FREE( x );
+		DRM_FREE( y );
+		DRM_FREE( buffer );
+		return DRM_ERR(EFAULT);
 	}
 
 	if ( depth->mask ) {
-		mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL );
+		mask = DRM_MALLOC( depth->n * sizeof(u8) );
 		if ( mask == NULL ) {
-			kfree( x );
-			kfree( y );
-			kfree( buffer );
-			return -ENOMEM;
+			DRM_FREE( x );
+			DRM_FREE( y );
+			DRM_FREE( buffer );
+			return DRM_ERR(ENOMEM);
 		}
-		if ( copy_from_user( mask, depth->mask,
+		if ( DRM_COPY_FROM_USER( mask, depth->mask,
 				     depth->n * sizeof(u8) ) ) {
-			kfree( x );
-			kfree( y );
-			kfree( buffer );
-			kfree( mask );
-			return -EFAULT;
+			DRM_FREE( x );
+			DRM_FREE( y );
+			DRM_FREE( buffer );
+			DRM_FREE( mask );
+			return DRM_ERR(EFAULT);
 		}
 
 		for ( i = 0 ; i < count ; i++ ) {
@@ -1070,7 +1069,7 @@
 			}
 		}
 
-		kfree( mask );
+		DRM_FREE( mask );
 	} else {
 		for ( i = 0 ; i < count ; i++ ) {
 			BEGIN_RING( 6 );
@@ -1094,9 +1093,9 @@
 		}
 	}
 
-	kfree( x );
-	kfree( y );
-	kfree( buffer );
+	DRM_FREE( x );
+	DRM_FREE( y );
+	DRM_FREE( buffer );
 
 	return 0;
 }
@@ -1107,14 +1106,14 @@
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	int count, x, y;
 	RING_LOCALS;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	count = depth->n;
-	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
-		return -EFAULT;
+	if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
+		return DRM_ERR(EFAULT);
 	}
-	if ( copy_from_user( &y, depth->y, sizeof(y) ) ) {
-		return -EFAULT;
+	if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
+		return DRM_ERR(EFAULT);
 	}
 
 	BEGIN_RING( 7 );
@@ -1156,24 +1155,24 @@
 		count = dev_priv->depth_pitch;
 	}
 
-	x = kmalloc( count * sizeof(*x), GFP_KERNEL );
+	x = DRM_MALLOC( count * sizeof(*x) );
 	if ( x == NULL ) {
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 	}
-	y = kmalloc( count * sizeof(*y), GFP_KERNEL );
+	y = DRM_MALLOC( count * sizeof(*y) );
 	if ( y == NULL ) {
-		kfree( x );
-		return -ENOMEM;
+		DRM_FREE( x );
+		return DRM_ERR(ENOMEM);
 	}
-	if ( copy_from_user( x, depth->x, count * sizeof(int) ) ) {
-		kfree( x );
-		kfree( y );
-		return -EFAULT;
-	}
-	if ( copy_from_user( y, depth->y, count * sizeof(int) ) ) {
-		kfree( x );
-		kfree( y );
-		return -EFAULT;
+	if ( DRM_COPY_FROM_USER( x, depth->x, count * sizeof(int) ) ) {
+		DRM_FREE( x );
+		DRM_FREE( y );
+		return DRM_ERR(EFAULT);
+	}
+	if ( DRM_COPY_FROM_USER( y, depth->y, count * sizeof(int) ) ) {
+		DRM_FREE( x );
+		DRM_FREE( y );
+		return DRM_ERR(EFAULT);
 	}
 
 	for ( i = 0 ; i < count ; i++ ) {
@@ -1200,8 +1199,8 @@
 		ADVANCE_RING();
 	}
 
-	kfree( x );
-	kfree( y );
+	DRM_FREE( x );
+	DRM_FREE( y );
 
 	return 0;
 }
@@ -1233,21 +1232,18 @@
  * IOCTL functions
  */
 
-int r128_cce_clear( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int r128_cce_clear( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_r128_clear_t clear;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &clear, (drm_r128_clear_t *) arg,
-			     sizeof(clear) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t *) data,
+			     sizeof(clear) );
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
@@ -1263,11 +1259,9 @@
 	return 0;
 }
 
-int r128_cce_swap( struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg )
+int r128_cce_swap( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
@@ -1290,11 +1284,9 @@
 	return 0;
 }
 
-int r128_cce_vertex( struct inode *inode, struct file *filp,
-		     unsigned int cmd, unsigned long arg )
+int r128_cce_vertex( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -1305,26 +1297,25 @@
 
 	if ( !dev_priv ) {
 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
-	if ( copy_from_user( &vertex, (drm_r128_vertex_t *)arg,
-			     sizeof(vertex) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_r128_vertex_t *) data,
+			     sizeof(vertex) );
 
-	DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n",
-		   __FUNCTION__, current->pid,
+	DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
+		   DRM_CURRENTPID,
 		   vertex.idx, vertex.count, vertex.discard );
 
 	if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
 		DRM_ERROR( "buffer index %d (of %d max)\n",
 			   vertex.idx, dma->buf_count - 1 );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	if ( vertex.prim < 0 ||
 	     vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
 		DRM_ERROR( "buffer prim %d\n", vertex.prim );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
@@ -1333,14 +1324,14 @@
 	buf = dma->buflist[vertex.idx];
 	buf_priv = buf->dev_private;
 
-	if ( buf->pid != current->pid ) {
+	if ( buf->pid != DRM_CURRENTPID ) {
 		DRM_ERROR( "process %d using buffer owned by %d\n",
-			   current->pid, buf->pid );
-		return -EINVAL;
+			   DRM_CURRENTPID, buf->pid );
+		return DRM_ERR(EINVAL);
 	}
 	if ( buf->pending ) {
 		DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	buf->used = vertex.count;
@@ -1352,11 +1343,9 @@
 	return 0;
 }
 
-int r128_cce_indices( struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg )
+int r128_cce_indices( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -1368,26 +1357,24 @@
 
 	if ( !dev_priv ) {
 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
-	if ( copy_from_user( &elts, (drm_r128_indices_t *)arg,
-			     sizeof(elts) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( elts, (drm_r128_indices_t *) data,
+			     sizeof(elts) );
 
-	DRM_DEBUG( "%s: pid=%d buf=%d s=%d e=%d d=%d\n",
-		   __FUNCTION__, current->pid,
+	DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
 		   elts.idx, elts.start, elts.end, elts.discard );
 
 	if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
 		DRM_ERROR( "buffer index %d (of %d max)\n",
 			   elts.idx, dma->buf_count - 1 );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	if ( elts.prim < 0 ||
 	     elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
 		DRM_ERROR( "buffer prim %d\n", elts.prim );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
@@ -1396,14 +1383,14 @@
 	buf = dma->buflist[elts.idx];
 	buf_priv = buf->dev_private;
 
-	if ( buf->pid != current->pid ) {
+	if ( buf->pid != DRM_CURRENTPID ) {
 		DRM_ERROR( "process %d using buffer owned by %d\n",
-			   current->pid, buf->pid );
-		return -EINVAL;
+			   DRM_CURRENTPID, buf->pid );
+		return DRM_ERR(EINVAL);
 	}
 	if ( buf->pending ) {
 		DRM_ERROR( "sending pending buffer %d\n", elts.idx );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	count = (elts.end - elts.start) / sizeof(u16);
@@ -1411,11 +1398,11 @@
 
 	if ( elts.start & 0x7 ) {
 		DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	if ( elts.start < buf->used ) {
 		DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	buf->used = elts.end;
@@ -1427,28 +1414,24 @@
 	return 0;
 }
 
-int r128_cce_blit( struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg )
+int r128_cce_blit( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_device_dma_t *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_blit_t blit;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &blit, (drm_r128_blit_t *)arg,
-			     sizeof(blit) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t *) data,
+			     sizeof(blit) );
 
-	DRM_DEBUG( "%s: pid=%d index=%d\n",
-		   __FUNCTION__, current->pid, blit.idx );
+	DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID, blit.idx );
 
 	if ( blit.idx < 0 || blit.idx >= dma->buf_count ) {
 		DRM_ERROR( "buffer index %d (of %d max)\n",
 			   blit.idx, dma->buf_count - 1 );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
@@ -1457,19 +1440,16 @@
 	return r128_cce_dispatch_blit( dev, &blit );
 }
 
-int r128_cce_depth( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int r128_cce_depth( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_depth_t depth;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &depth, (drm_r128_depth_t *)arg,
-			     sizeof(depth) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t *) data,
+			     sizeof(depth) );
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
@@ -1484,27 +1464,24 @@
 		return r128_cce_dispatch_read_pixels( dev, &depth );
 	}
 
-	return -EINVAL;
+	return DRM_ERR(EINVAL);
 }
 
-int r128_cce_stipple( struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg )
+int r128_cce_stipple( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_stipple_t stipple;
 	u32 mask[32];
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &stipple, (drm_r128_stipple_t *)arg,
-			     sizeof(stipple) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t *) data,
+			     sizeof(stipple) );
 
-	if ( copy_from_user( &mask, stipple.mask,
+	if ( DRM_COPY_FROM_USER( &mask, stipple.mask,
 			     32 * sizeof(u32) ) )
-		return -EFAULT;
+		return DRM_ERR( EFAULT );
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
@@ -1513,11 +1490,9 @@
 	return 0;
 }
 
-int r128_cce_indirect( struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg )
+int r128_cce_indirect( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
@@ -1531,12 +1506,11 @@
 
 	if ( !dev_priv ) {
 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
-	if ( copy_from_user( &indirect, (drm_r128_indirect_t *)arg,
-			     sizeof(indirect) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( indirect, (drm_r128_indirect_t *) data,
+			     sizeof(indirect) );
 
 	DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
 		   indirect.idx, indirect.start,
@@ -1545,26 +1519,26 @@
 	if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
 		DRM_ERROR( "buffer index %d (of %d max)\n",
 			   indirect.idx, dma->buf_count - 1 );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	buf = dma->buflist[indirect.idx];
 	buf_priv = buf->dev_private;
 
-	if ( buf->pid != current->pid ) {
+	if ( buf->pid != DRM_CURRENTPID ) {
 		DRM_ERROR( "process %d using buffer owned by %d\n",
-			   current->pid, buf->pid );
-		return -EINVAL;
+			   DRM_CURRENTPID, buf->pid );
+		return DRM_ERR(EINVAL);
 	}
 	if ( buf->pending ) {
 		DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	if ( indirect.start < buf->used ) {
 		DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
 			   indirect.start, buf->used );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
@@ -1590,3 +1564,36 @@
 
 	return 0;
 }
+
+int r128_getparam( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	drm_r128_getparam_t param;
+	int value;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t *)data,
+			     sizeof(param) );
+
+	DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
+
+	switch( param.param ) {
+	case R128_PARAM_IRQ_NR:
+		value = dev->irq;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
+		DRM_ERROR( "copy_to_user\n" );
+		return DRM_ERR(EFAULT);
+	}
+	
+	return 0;
+}
diff -ruN drivers/char/drm-4.2/radeon.h drivers/char/drm/radeon.h
--- drivers/char/drm-4.2/radeon.h	2003-01-14 06:55:43.000000000 +0900
+++ drivers/char/drm/radeon.h	2003-01-14 07:01:00.000000000 +0900
@@ -44,7 +44,78 @@
 #define __HAVE_SG		1
 #define __HAVE_PCI_DMA		1
 
-/* Driver customization:
+#define DRIVER_AUTHOR		"Gareth Hughes, Keith Whitwell, others."
+
+#define DRIVER_NAME		"radeon"
+#define DRIVER_DESC		"ATI Radeon"
+#define DRIVER_DATE		"20020828"
+
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		7
+#define DRIVER_PATCHLEVEL	0
+
+/* Interface history:
+ *
+ * 1.1 - ??
+ * 1.2 - Add vertex2 ioctl (keith)
+ *     - Add stencil capability to clear ioctl (gareth, keith)
+ *     - Increase MAX_TEXTURE_LEVELS (brian)
+ * 1.3 - Add cmdbuf ioctl (keith)
+ *     - Add support for new radeon packets (keith)
+ *     - Add getparam ioctl (keith)
+ *     - Add flip-buffers ioctl, deprecate fullscreen foo (keith).
+ * 1.4 - Add scratch registers to get_param ioctl.
+ * 1.5 - Add r200 packets to cmdbuf ioctl
+ *     - Add r200 function to init ioctl
+ *     - Add 'scalar2' instruction to cmdbuf
+ * 1.6 - Add static agp memory manager
+ *       Add irq handler (won't be turned on unless X server knows to)
+ *       Add irq ioctls and irq_active getparam.
+ *       Add wait command for cmdbuf ioctl
+ *       Add agp offset query for getparam
+ * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5]
+ *       and R200_PP_CUBIC_OFFSET_F1_[0..5].
+ *       Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and
+ *       R200_EMIT_PP_CUBIC_OFFSETS_[0..5].  (brian)
+ */
+#define DRIVER_IOCTLS							     \
+ [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)]    = { radeon_cp_init,     1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)]   = { radeon_cp_start,    1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)]    = { radeon_cp_stop,     1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)]   = { radeon_cp_reset,    1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)]    = { radeon_cp_idle,     1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)]    = { radeon_engine_reset,  1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen,  1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)]       = { radeon_cp_swap,     1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)]      = { radeon_cp_clear,    1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)]     = { radeon_cp_vertex,   1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)]    = { radeon_cp_indices,  1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_TEXTURE)]    = { radeon_cp_texture,  1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)]    = { radeon_cp_stipple,  1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)]   = { radeon_cp_indirect, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX2)]    = { radeon_cp_vertex2,  1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CMDBUF)]     = { radeon_cp_cmdbuf,   1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_GETPARAM)]   = { radeon_cp_getparam, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FLIP)]       = { radeon_cp_flip,     1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_ALLOC)]      = { radeon_mem_alloc,   1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)]       = { radeon_mem_free,    1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)]  = { radeon_mem_init_heap, 1, 1 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)]   = { radeon_irq_emit, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait, 1, 0 },
+
+
+#define USE_IRQS 1
+#if USE_IRQS
+#define __HAVE_DMA_IRQ		1
+#define __HAVE_VBL_IRQ		1
+#define __HAVE_SHARED_IRQ       1
+
+/* When a client dies:
+ *    - Check for and clean up flipped page state
+ *    - Free any alloced agp memory.
+ *
+ * DRM infrastructure takes care of reclaiming dma buffers.
  */
 #define DRIVER_PRERELEASE() do {					\
 	if ( dev->dev_private ) {					\
@@ -52,31 +123,36 @@
 		if ( dev_priv->page_flipping ) {			\
 			radeon_do_cleanup_pageflip( dev );		\
 		}							\
+                radeon_mem_release( dev_priv->agp_heap );		\
 	}								\
 } while (0)
 
+/* On unloading the module:
+ *    - Free memory heap structure
+ *    - Remove mappings made at startup and free dev_private.
+ */
 #define DRIVER_PRETAKEDOWN() do {					\
-	if ( dev->dev_private ) radeon_do_cleanup_cp( dev );		\
+	if ( dev->dev_private ) {					\
+		drm_radeon_private_t *dev_priv = dev->dev_private;	\
+		radeon_mem_takedown( &(dev_priv->agp_heap) );		\
+		radeon_do_cleanup_cp( dev );				\
+	}								\
 } while (0)
 
+#else
+#define __HAVE_DMA_IRQ 0
+#endif
+
 /* DMA customization:
  */
 #define __HAVE_DMA		1
 
-#if 0
-/* GH: Remove this for now... */
-#define __HAVE_DMA_QUIESCENT	1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	drm_radeon_private_t *dev_priv = dev->dev_private;		\
-	return radeon_do_cp_idle( dev_priv );				\
-} while (0)
-#endif
 
 /* Buffer customization:
  */
 #define DRIVER_BUF_PRIV_T	drm_radeon_buf_priv_t
 
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
+#define DRIVER_AGP_BUFFERS_MAP( dev )				\
 	((drm_radeon_private_t *)((dev)->dev_private))->buffers
 
 #endif
diff -ruN drivers/char/drm-4.2/radeon_cp.c drivers/char/drm/radeon_cp.c
--- drivers/char/drm-4.2/radeon_cp.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/radeon_cp.c	2003-01-14 07:00:59.000000000 +0900
@@ -30,14 +30,13 @@
 
 #include "radeon.h"
 #include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
 #include "radeon_drv.h"
 
-#include <linux/interrupt.h>	/* For task queue support */
-#include <linux/delay.h>
-
 #define RADEON_FIFO_DEBUG	0
 
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__powerpc__)
 # define PCIGART_ENABLED
 #else
 # undef PCIGART_ENABLED
@@ -45,6 +44,266 @@
 
 
 /* CP microcode (from ATI) */
+static u32 R200_cp_microcode[][2] = {
+	{ 0x21007000, 0000000000 },        
+	{ 0x20007000, 0000000000 }, 
+	{ 0x000000ab, 0x00000004 },
+	{ 0x000000af, 0x00000004 },
+	{ 0x66544a49, 0000000000 },
+	{ 0x49494174, 0000000000 },
+	{ 0x54517d83, 0000000000 },
+	{ 0x498d8b64, 0000000000 },
+	{ 0x49494949, 0000000000 },
+	{ 0x49da493c, 0000000000 },
+	{ 0x49989898, 0000000000 },
+	{ 0xd34949d5, 0000000000 },
+	{ 0x9dc90e11, 0000000000 },
+	{ 0xce9b9b9b, 0000000000 },
+	{ 0x000f0000, 0x00000016 },
+	{ 0x352e232c, 0000000000 },
+	{ 0x00000013, 0x00000004 },
+	{ 0x000f0000, 0x00000016 },
+	{ 0x352e272c, 0000000000 },
+	{ 0x000f0001, 0x00000016 },
+	{ 0x3239362f, 0000000000 },
+	{ 0x000077ef, 0x00000002 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x00000020, 0x0000001a },
+	{ 0x00004000, 0x0000001e },
+	{ 0x00061000, 0x00000002 },
+	{ 0x00000020, 0x0000001a },
+	{ 0x00004000, 0x0000001e },
+	{ 0x00061000, 0x00000002 },
+	{ 0x00000020, 0x0000001a },
+	{ 0x00004000, 0x0000001e },
+	{ 0x00000016, 0x00000004 },
+	{ 0x0003802a, 0x00000002 },
+	{ 0x040067e0, 0x00000002 },
+	{ 0x00000016, 0x00000004 },
+	{ 0x000077e0, 0x00000002 },
+	{ 0x00065000, 0x00000002 },
+	{ 0x000037e1, 0x00000002 },
+	{ 0x040067e1, 0x00000006 },
+	{ 0x000077e0, 0x00000002 },
+	{ 0x000077e1, 0x00000002 },
+	{ 0x000077e1, 0x00000006 },
+	{ 0xffffffff, 0000000000 },
+	{ 0x10000000, 0000000000 },
+	{ 0x0003802a, 0x00000002 },
+	{ 0x040067e0, 0x00000006 },
+	{ 0x00007675, 0x00000002 },
+	{ 0x00007676, 0x00000002 },
+	{ 0x00007677, 0x00000002 },
+	{ 0x00007678, 0x00000006 },
+	{ 0x0003802b, 0x00000002 },
+	{ 0x04002676, 0x00000002 },
+	{ 0x00007677, 0x00000002 },
+	{ 0x00007678, 0x00000006 },
+	{ 0x0000002e, 0x00000018 },
+	{ 0x0000002e, 0x00000018 },
+	{ 0000000000, 0x00000006 },
+	{ 0x0000002f, 0x00000018 },
+	{ 0x0000002f, 0x00000018 },
+	{ 0000000000, 0x00000006 },
+	{ 0x01605000, 0x00000002 },
+	{ 0x00065000, 0x00000002 },
+	{ 0x00098000, 0x00000002 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x64c0603d, 0x00000004 },
+	{ 0x00080000, 0x00000016 },
+	{ 0000000000, 0000000000 },
+	{ 0x0400251d, 0x00000002 },
+	{ 0x00007580, 0x00000002 },
+	{ 0x00067581, 0x00000002 },
+	{ 0x04002580, 0x00000002 },
+	{ 0x00067581, 0x00000002 },
+	{ 0x00000046, 0x00000004 },
+	{ 0x00005000, 0000000000 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x0000750e, 0x00000002 },
+	{ 0x00019000, 0x00000002 },
+	{ 0x00011055, 0x00000014 },
+	{ 0x00000055, 0x00000012 },
+	{ 0x0400250f, 0x00000002 },
+	{ 0x0000504a, 0x00000004 },
+	{ 0x00007565, 0x00000002 },
+	{ 0x00007566, 0x00000002 },
+	{ 0x00000051, 0x00000004 },
+	{ 0x01e655b4, 0x00000002 },
+	{ 0x4401b0dc, 0x00000002 },
+	{ 0x01c110dc, 0x00000002 },
+	{ 0x2666705d, 0x00000018 },
+	{ 0x040c2565, 0x00000002 },
+	{ 0x0000005d, 0x00000018 },
+	{ 0x04002564, 0x00000002 },
+	{ 0x00007566, 0x00000002 },
+	{ 0x00000054, 0x00000004 },
+	{ 0x00401060, 0x00000008 },
+	{ 0x00101000, 0x00000002 },
+	{ 0x000d80ff, 0x00000002 },
+	{ 0x00800063, 0x00000008 },
+	{ 0x000f9000, 0x00000002 },
+	{ 0x000e00ff, 0x00000002 },
+	{ 0000000000, 0x00000006 },
+	{ 0x00000080, 0x00000018 },
+	{ 0x00000054, 0x00000004 },
+	{ 0x00007576, 0x00000002 },
+	{ 0x00065000, 0x00000002 },
+	{ 0x00009000, 0x00000002 },
+	{ 0x00041000, 0x00000002 },
+	{ 0x0c00350e, 0x00000002 },
+	{ 0x00049000, 0x00000002 },
+	{ 0x00051000, 0x00000002 },
+	{ 0x01e785f8, 0x00000002 },
+	{ 0x00200000, 0x00000002 },
+	{ 0x00600073, 0x0000000c },
+	{ 0x00007563, 0x00000002 },
+	{ 0x006075f0, 0x00000021 },
+	{ 0x20007068, 0x00000004 },
+	{ 0x00005068, 0x00000004 },
+	{ 0x00007576, 0x00000002 },
+	{ 0x00007577, 0x00000002 },
+	{ 0x0000750e, 0x00000002 },
+	{ 0x0000750f, 0x00000002 },
+	{ 0x00a05000, 0x00000002 },
+	{ 0x00600076, 0x0000000c },
+	{ 0x006075f0, 0x00000021 },
+	{ 0x000075f8, 0x00000002 },
+	{ 0x00000076, 0x00000004 },
+	{ 0x000a750e, 0x00000002 },
+	{ 0x0020750f, 0x00000002 },
+	{ 0x00600079, 0x00000004 },
+	{ 0x00007570, 0x00000002 },
+	{ 0x00007571, 0x00000002 },
+	{ 0x00007572, 0x00000006 },
+	{ 0x00005000, 0x00000002 },
+	{ 0x00a05000, 0x00000002 },
+	{ 0x00007568, 0x00000002 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x00000084, 0x0000000c },
+	{ 0x00058000, 0x00000002 },
+	{ 0x0c607562, 0x00000002 },
+	{ 0x00000086, 0x00000004 },
+	{ 0x00600085, 0x00000004 },
+	{ 0x400070dd, 0000000000 },
+	{ 0x000380dd, 0x00000002 },
+	{ 0x00000093, 0x0000001c },
+	{ 0x00065095, 0x00000018 },
+	{ 0x040025bb, 0x00000002 },
+	{ 0x00061096, 0x00000018 },
+	{ 0x040075bc, 0000000000 },
+	{ 0x000075bb, 0x00000002 },
+	{ 0x000075bc, 0000000000 },
+	{ 0x00090000, 0x00000006 },
+	{ 0x00090000, 0x00000002 },
+	{ 0x000d8002, 0x00000006 },
+	{ 0x00005000, 0x00000002 },
+	{ 0x00007821, 0x00000002 },
+	{ 0x00007800, 0000000000 },
+	{ 0x00007821, 0x00000002 },
+	{ 0x00007800, 0000000000 },
+	{ 0x01665000, 0x00000002 },
+	{ 0x000a0000, 0x00000002 },
+	{ 0x000671cc, 0x00000002 },
+	{ 0x0286f1cd, 0x00000002 },
+	{ 0x000000a3, 0x00000010 },
+	{ 0x21007000, 0000000000 },
+	{ 0x000000aa, 0x0000001c },
+	{ 0x00065000, 0x00000002 },
+	{ 0x000a0000, 0x00000002 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x000b0000, 0x00000002 },
+	{ 0x38067000, 0x00000002 },
+	{ 0x000a00a6, 0x00000004 },
+	{ 0x20007000, 0000000000 },
+	{ 0x01200000, 0x00000002 },
+	{ 0x20077000, 0x00000002 },
+	{ 0x01200000, 0x00000002 },
+	{ 0x20007000, 0000000000 },
+	{ 0x00061000, 0x00000002 },
+	{ 0x0120751b, 0x00000002 },
+	{ 0x8040750a, 0x00000002 },
+	{ 0x8040750b, 0x00000002 },
+	{ 0x00110000, 0x00000002 },
+	{ 0x000380dd, 0x00000002 },
+	{ 0x000000bd, 0x0000001c },
+	{ 0x00061096, 0x00000018 },
+	{ 0x844075bd, 0x00000002 },
+	{ 0x00061095, 0x00000018 },
+	{ 0x840075bb, 0x00000002 },
+	{ 0x00061096, 0x00000018 },
+	{ 0x844075bc, 0x00000002 },
+	{ 0x000000c0, 0x00000004 },
+	{ 0x804075bd, 0x00000002 },
+	{ 0x800075bb, 0x00000002 },
+	{ 0x804075bc, 0x00000002 },
+	{ 0x00108000, 0x00000002 },
+	{ 0x01400000, 0x00000002 },
+	{ 0x006000c4, 0x0000000c },
+	{ 0x20c07000, 0x00000020 },
+	{ 0x000000c6, 0x00000012 },
+	{ 0x00800000, 0x00000006 },
+	{ 0x0080751d, 0x00000006 },
+	{ 0x000025bb, 0x00000002 },
+	{ 0x000040c0, 0x00000004 },
+	{ 0x0000775c, 0x00000002 },
+	{ 0x00a05000, 0x00000002 },
+	{ 0x00661000, 0x00000002 },
+	{ 0x0460275d, 0x00000020 },
+	{ 0x00004000, 0000000000 },
+	{ 0x00007999, 0x00000002 },
+	{ 0x00a05000, 0x00000002 },
+	{ 0x00661000, 0x00000002 },
+	{ 0x0460299b, 0x00000020 },
+	{ 0x00004000, 0000000000 },
+	{ 0x01e00830, 0x00000002 },
+	{ 0x21007000, 0000000000 },
+	{ 0x00005000, 0x00000002 },
+	{ 0x00038042, 0x00000002 },
+	{ 0x040025e0, 0x00000002 },
+	{ 0x000075e1, 0000000000 },
+	{ 0x00000001, 0000000000 },
+	{ 0x000380d9, 0x00000002 },
+	{ 0x04007394, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+	{ 0000000000, 0000000000 },
+};
+
+
 static u32 radeon_cp_microcode[][2] = {
 	{ 0x21007000, 0000000000 },
 	{ 0x20007000, 0000000000 },
@@ -346,6 +605,8 @@
 	u32 tmp;
 	int i;
 
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
 	tmp  = RADEON_READ( RADEON_RB2D_DSTCACHE_CTLSTAT );
 	tmp |= RADEON_RB2D_DC_FLUSH_ALL;
 	RADEON_WRITE( RADEON_RB2D_DSTCACHE_CTLSTAT, tmp );
@@ -355,14 +616,14 @@
 		       & RADEON_RB2D_DC_BUSY) ) {
 			return 0;
 		}
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 #if RADEON_FIFO_DEBUG
 	DRM_ERROR( "failed!\n" );
 	radeon_status( dev_priv );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 static int radeon_do_wait_for_fifo( drm_radeon_private_t *dev_priv,
@@ -370,26 +631,30 @@
 {
 	int i;
 
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
 		int slots = ( RADEON_READ( RADEON_RBBM_STATUS )
 			      & RADEON_RBBM_FIFOCNT_MASK );
 		if ( slots >= entries ) return 0;
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 #if RADEON_FIFO_DEBUG
 	DRM_ERROR( "failed!\n" );
 	radeon_status( dev_priv );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 static int radeon_do_wait_for_idle( drm_radeon_private_t *dev_priv )
 {
 	int i, ret;
 
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
 	ret = radeon_do_wait_for_fifo( dev_priv, 64 );
-	if ( ret < 0 ) return ret;
+	if ( ret ) return ret;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
 		if ( !(RADEON_READ( RADEON_RBBM_STATUS )
@@ -397,14 +662,14 @@
 			radeon_do_pixcache_flush( dev_priv );
 			return 0;
 		}
-		udelay( 1 );
+		DRM_UDELAY( 1 );
 	}
 
 #if RADEON_FIFO_DEBUG
 	DRM_ERROR( "failed!\n" );
 	radeon_status( dev_priv );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 
@@ -416,16 +681,31 @@
 static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
 {
 	int i;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	radeon_do_wait_for_idle( dev_priv );
 
 	RADEON_WRITE( RADEON_CP_ME_RAM_ADDR, 0 );
-	for ( i = 0 ; i < 256 ; i++ ) {
-		RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
-			      radeon_cp_microcode[i][1] );
-		RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
-			      radeon_cp_microcode[i][0] );
+
+	if (dev_priv->is_r200)
+	{
+		DRM_INFO("Loading R200 Microcode\n");
+		for ( i = 0 ; i < 256 ; i++ ) 
+		{
+			RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
+				      R200_cp_microcode[i][1] );
+			RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
+				      R200_cp_microcode[i][0] );
+		}
+	}
+	else
+	{
+		for ( i = 0 ; i < 256 ; i++ ) {
+			RADEON_WRITE( RADEON_CP_ME_RAM_DATAH,
+				      radeon_cp_microcode[i][1] );
+			RADEON_WRITE( RADEON_CP_ME_RAM_DATAL,
+				      radeon_cp_microcode[i][0] );
+		}
 	}
 }
 
@@ -435,7 +715,7 @@
  */
 static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
 {
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 #if 0
 	u32 tmp;
 
@@ -449,7 +729,7 @@
 int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
 {
 	RING_LOCALS;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	BEGIN_RING( 6 );
 
@@ -458,6 +738,7 @@
 	RADEON_WAIT_UNTIL_IDLE();
 
 	ADVANCE_RING();
+	COMMIT_RING();
 
 	return radeon_do_wait_for_idle( dev_priv );
 }
@@ -467,7 +748,7 @@
 static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
 {
 	RING_LOCALS;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	radeon_do_wait_for_idle( dev_priv );
 
@@ -482,6 +763,7 @@
 	RADEON_WAIT_UNTIL_IDLE();
 
 	ADVANCE_RING();
+	COMMIT_RING();
 }
 
 /* Reset the Command Processor.  This will not flush any pending
@@ -491,7 +773,7 @@
 static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
 {
 	u32 cur_read_ptr;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
 	RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
@@ -505,7 +787,7 @@
  */
 static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
 {
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
 
@@ -518,7 +800,7 @@
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	radeon_do_pixcache_flush( dev_priv );
 
@@ -622,13 +904,63 @@
 
 		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
 			     entry->busaddr[page_ofs]);
-		DRM_DEBUG( "ring rptr: offset=0x%08llx handle=0x%08lx\n",
-			   (u64)entry->busaddr[page_ofs],
+		DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
+			   entry->busaddr[page_ofs],
 			   entry->handle + tmp_ofs );
 	}
 
+	/* Initialize the scratch register pointer.  This will cause
+	 * the scratch register values to be written out to memory
+	 * whenever they are updated.
+	 *
+	 * We simply put this behind the ring read pointer, this works
+	 * with PCI GART as well as (whatever kind of) AGP GART
+	 */
+	RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR )
+					 + RADEON_SCRATCH_REG_OFFSET );
+
+	dev_priv->scratch = ((__volatile__ u32 *)
+			     dev_priv->ring.head +
+			     (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+
+	RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
+
+	/* Writeback doesn't seem to work everywhere, test it first */
+	DRM_WRITE32( &dev_priv->scratch[1], 0 );
+	RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
+
+	for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
+		if ( DRM_READ32( &dev_priv->scratch[1] ) == 0xdeadbeef )
+			break;
+		DRM_UDELAY( 1 );
+	}
+
+	if ( tmp < dev_priv->usec_timeout ) {
+		dev_priv->writeback_works = 1;
+		DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
+	} else {
+		dev_priv->writeback_works = 0;
+		DRM_DEBUG( "writeback test failed\n" );
+	}
+
+	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
+	RADEON_WRITE( RADEON_LAST_FRAME_REG,
+		      dev_priv->sarea_priv->last_frame );
+
+	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
+	RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
+		      dev_priv->sarea_priv->last_dispatch );
+
+	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
+	RADEON_WRITE( RADEON_LAST_CLEAR_REG,
+		      dev_priv->sarea_priv->last_clear );
+
 	/* Set ring buffer size */
+#ifdef __BIG_ENDIAN
+	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT );
+#else
 	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
+#endif
 
 	radeon_do_wait_for_idle( dev_priv );
 
@@ -647,13 +979,12 @@
 static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 {
 	drm_radeon_private_t *dev_priv;
-	struct list_head *list;
 	u32 tmp;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
 	if ( dev_priv == NULL )
-		return -ENOMEM;
+		return DRM_ERR(ENOMEM);
 
 	memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
 
@@ -666,7 +997,7 @@
 		DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 #endif
 
@@ -674,7 +1005,7 @@
 		DRM_ERROR( "PCI GART memory not allocated!\n" );
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	dev_priv->usec_timeout = init->usec_timeout;
@@ -683,15 +1014,13 @@
 		DRM_DEBUG( "TIMEOUT problem!\n" );
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
+	dev_priv->is_r200 = (init->func == RADEON_INIT_R200_CP);
+	dev_priv->do_boxes = 0;
 	dev_priv->cp_mode = init->cp_mode;
 
-	/* Simple idle check.
-	 */
-	atomic_set( &dev_priv->idle_count, 0 );
-
 	/* We don't support anything other than bus-mastering ring mode,
 	 * but the ring can be in either AGP or PCI space for the ring
 	 * read pointer.
@@ -701,7 +1030,7 @@
 		DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	switch ( init->fb_bpp ) {
@@ -743,17 +1072,17 @@
 	 * and screwing with the clear operation.
 	 */
 	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
-					   RADEON_Z_ENABLE |
 					   (dev_priv->color_fmt << 10) |
-					   RADEON_ZBLOCK16);
+					   (1<<15));
 
-	dev_priv->depth_clear.rb3d_zstencilcntl = (dev_priv->depth_fmt |
-						   RADEON_Z_TEST_ALWAYS |
-						   RADEON_STENCIL_TEST_ALWAYS |
-						   RADEON_STENCIL_S_FAIL_KEEP |
-						   RADEON_STENCIL_ZPASS_KEEP |
-						   RADEON_STENCIL_ZFAIL_KEEP |
-						   RADEON_Z_WRITE_ENABLE);
+	dev_priv->depth_clear.rb3d_zstencilcntl = 
+		(dev_priv->depth_fmt |
+		 RADEON_Z_TEST_ALWAYS |
+		 RADEON_STENCIL_TEST_ALWAYS |
+		 RADEON_STENCIL_S_FAIL_REPLACE |
+		 RADEON_STENCIL_ZPASS_REPLACE |
+		 RADEON_STENCIL_ZFAIL_REPLACE |
+		 RADEON_Z_WRITE_ENABLE);
 
 	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
 					 RADEON_BFACE_SOLID |
@@ -767,20 +1096,13 @@
 					 RADEON_ROUND_MODE_TRUNC |
 					 RADEON_ROUND_PREC_8TH_PIX);
 
-	list_for_each(list, &dev->maplist->head) {
-		drm_map_list_t *r_list = (drm_map_list_t *)list;
-		if( r_list->map &&
-		    r_list->map->type == _DRM_SHM &&
-		    r_list->map->flags & _DRM_CONTAINS_LOCK ) {
-			dev_priv->sarea = r_list->map;
- 			break;
- 		}
- 	}
+	DRM_GETSAREA();
+	
 	if(!dev_priv->sarea) {
 		DRM_ERROR("could not find sarea!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
@@ -788,35 +1110,35 @@
 		DRM_ERROR("could not find framebuffer!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
 	if(!dev_priv->cp_ring) {
 		DRM_ERROR("could not find cp ring region!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
 	if(!dev_priv->ring_rptr) {
 		DRM_ERROR("could not find ring read pointer!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
 	if(!dev_priv->buffers) {
 		DRM_ERROR("could not find dma buffer region!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	if ( !dev_priv->is_pci ) {
@@ -826,7 +1148,7 @@
 			DRM_ERROR("could not find agp texture region!\n");
 			dev->dev_private = (void *)dev_priv;
 			radeon_do_cleanup_cp(dev);
-			return -EINVAL;
+			return DRM_ERR(EINVAL);
 		}
 	}
 
@@ -844,7 +1166,7 @@
 			DRM_ERROR("could not find ioremap agp regions!\n");
 			dev->dev_private = (void *)dev_priv;
 			radeon_do_cleanup_cp(dev);
-			return -EINVAL;
+			return DRM_ERR(EINVAL);
 		}
 	} else {
 		dev_priv->cp_ring->handle =
@@ -896,41 +1218,14 @@
 
 	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
 
-#if 0
-	/* Initialize the scratch register pointer.  This will cause
-	 * the scratch register values to be written out to memory
-	 * whenever they are updated.
-	 * FIXME: This doesn't quite work yet, so we're disabling it
-	 * for the release.
-	 */
-	RADEON_WRITE( RADEON_SCRATCH_ADDR, (dev_priv->ring_rptr->offset +
-					    RADEON_SCRATCH_REG_OFFSET) );
-	RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
-#endif
-
-	dev_priv->scratch = ((__volatile__ u32 *)
-			     dev_priv->ring_rptr->handle +
-			     (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
-
-	dev_priv->sarea_priv->last_frame = 0;
-	RADEON_WRITE( RADEON_LAST_FRAME_REG,
-		      dev_priv->sarea_priv->last_frame );
-
-	dev_priv->sarea_priv->last_dispatch = 0;
-	RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
-		      dev_priv->sarea_priv->last_dispatch );
-
-	dev_priv->sarea_priv->last_clear = 0;
-	RADEON_WRITE( RADEON_LAST_CLEAR_REG,
-		      dev_priv->sarea_priv->last_clear );
-
+#if __REALLY_HAVE_SG
 	if ( dev_priv->is_pci ) {
 		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
 					    &dev_priv->bus_pci_gart)) {
 			DRM_ERROR( "failed to init PCI GART!\n" );
 			dev->dev_private = (void *)dev_priv;
 			radeon_do_cleanup_cp(dev);
-			return -ENOMEM;
+			return DRM_ERR(ENOMEM);
 		}
 		/* Turn on PCI GART
 		 */
@@ -953,19 +1248,20 @@
 		RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
 		RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
 	} else {
+#endif /* __REALLY_HAVE_SG */
 		/* Turn off PCI GART
 		 */
 		tmp = RADEON_READ( RADEON_AIC_CNTL )
 		      & ~RADEON_PCIGART_TRANSLATE_EN;
 		RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+#if __REALLY_HAVE_SG
 	}
+#endif /* __REALLY_HAVE_SG */
 
 	radeon_cp_load_microcode( dev_priv );
 	radeon_cp_init_ring_buffer( dev, dev_priv );
 
-#if ROTATE_BUFS
 	dev_priv->last_buf = 0;
-#endif
 
 	dev->dev_private = (void *)dev_priv;
 
@@ -976,7 +1272,7 @@
 
 int radeon_do_cleanup_cp( drm_device_t *dev )
 {
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	if ( dev->dev_private ) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -986,10 +1282,12 @@
 			DRM_IOREMAPFREE( dev_priv->ring_rptr );
 			DRM_IOREMAPFREE( dev_priv->buffers );
 		} else {
+#if __REALLY_HAVE_SG
 			if (!DRM(ati_pcigart_cleanup)( dev,
 						dev_priv->phys_pci_gart,
 						dev_priv->bus_pci_gart ))
 				DRM_ERROR( "failed to cleanup PCI GART!\n" );
+#endif /* __REALLY_HAVE_SG */
 		}
 
 		DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
@@ -1000,33 +1298,29 @@
 	return 0;
 }
 
-int radeon_cp_init( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int radeon_cp_init( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_init_t init;
 
-	if ( copy_from_user( &init, (drm_radeon_init_t *)arg, sizeof(init) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );
 
 	switch ( init.func ) {
 	case RADEON_INIT_CP:
+	case RADEON_INIT_R200_CP:
 		return radeon_do_init_cp( dev, &init );
 	case RADEON_CLEANUP_CP:
 		return radeon_do_cleanup_cp( dev );
 	}
 
-	return -EINVAL;
+	return DRM_ERR(EINVAL);
 }
 
-int radeon_cp_start( struct inode *inode, struct file *filp,
-		     unsigned int cmd, unsigned long arg )
+int radeon_cp_start( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
@@ -1048,20 +1342,17 @@
 /* Stop the CP.  The engine must have been idled before calling this
  * routine.
  */
-int radeon_cp_stop( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int radeon_cp_stop( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_cp_stop_t stop;
 	int ret;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t *)data, sizeof(stop) );
 
 	/* Flush any pending CP commands.  This ensures any outstanding
 	 * commands are exectuted by the engine before we turn it off.
@@ -1075,7 +1366,7 @@
 	 */
 	if ( stop.idle ) {
 		ret = radeon_do_cp_idle( dev_priv );
-		if ( ret < 0 ) return ret;
+		if ( ret ) return ret;
 	}
 
 	/* Finally, we can turn off the CP.  If the engine isn't idle,
@@ -1092,19 +1383,17 @@
 
 /* Just reset the CP ring.  Called as part of an X Server engine reset.
  */
-int radeon_cp_reset( struct inode *inode, struct file *filp,
-		     unsigned int cmd, unsigned long arg )
+int radeon_cp_reset( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( !dev_priv ) {
 		DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	radeon_do_cp_reset( dev_priv );
@@ -1115,25 +1404,24 @@
 	return 0;
 }
 
-int radeon_cp_idle( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int radeon_cp_idle( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
+/* 	if (dev->irq)  */
+/* 		radeon_emit_and_wait_irq( dev ); */
+
 	return radeon_do_cp_idle( dev_priv );
 }
 
-int radeon_engine_reset( struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg )
+int radeon_engine_reset( DRM_IOCTL_ARGS )
 {
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEVICE;
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
@@ -1145,117 +1433,74 @@
  * Fullscreen mode
  */
 
-static int radeon_do_init_pageflip( drm_device_t *dev )
-{
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
-
-	dev_priv->crtc_offset =      RADEON_READ( RADEON_CRTC_OFFSET );
-	dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL );
-
-	RADEON_WRITE( RADEON_CRTC_OFFSET, dev_priv->front_offset );
-	RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL,
-		      dev_priv->crtc_offset_cntl |
-		      RADEON_CRTC_OFFSET_FLIP_CNTL );
-
-	dev_priv->page_flipping = 1;
-	dev_priv->current_page = 0;
-
-	return 0;
-}
-
-int radeon_do_cleanup_pageflip( drm_device_t *dev )
+/* KW: Deprecated to say the least:
+ */
+int radeon_fullscreen( DRM_IOCTL_ARGS )
 {
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
-
-	RADEON_WRITE( RADEON_CRTC_OFFSET,      dev_priv->crtc_offset );
-	RADEON_WRITE( RADEON_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
-
-	dev_priv->page_flipping = 0;
-	dev_priv->current_page = 0;
-
 	return 0;
 }
 
-int radeon_fullscreen( struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg )
-{
-        drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
-	drm_radeon_fullscreen_t fs;
-
-	LOCK_TEST_WITH_RETURN( dev );
-
-	if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg,
-			     sizeof(fs) ) )
-		return -EFAULT;
-
-	switch ( fs.func ) {
-	case RADEON_INIT_FULLSCREEN:
-		return radeon_do_init_pageflip( dev );
-	case RADEON_CLEANUP_FULLSCREEN:
-		return radeon_do_cleanup_pageflip( dev );
-	}
-
-	return -EINVAL;
-}
-
 
 /* ================================================================
  * Freelist management
  */
-#define RADEON_BUFFER_USED	0xffffffff
-#define RADEON_BUFFER_FREE	0
 
-#if 0
-static int radeon_freelist_init( drm_device_t *dev )
+/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
+ *   bufs until freelist code is used.  Note this hides a problem with
+ *   the scratch register * (used to keep track of last buffer
+ *   completed) being written to before * the last buffer has actually
+ *   completed rendering.  
+ *
+ * KW:  It's also a good way to find free buffers quickly.
+ *
+ * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
+ * sleep.  However, bugs in older versions of radeon_accel.c mean that
+ * we essentially have to do this, else old clients will break.
+ * 
+ * However, it does leave open a potential deadlock where all the
+ * buffers are held by other clients, which can't release them because
+ * they can't get the lock.  
+ */
+
+drm_buf_t *radeon_freelist_get( drm_device_t *dev )
 {
 	drm_device_dma_t *dma = dev->dma;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_buf_t *buf;
 	drm_radeon_buf_priv_t *buf_priv;
-	drm_radeon_freelist_t *entry;
-	int i;
-
-	dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t),
-				     DRM_MEM_DRIVER );
-	if ( dev_priv->head == NULL )
-		return -ENOMEM;
-
-	memset( dev_priv->head, 0, sizeof(drm_radeon_freelist_t) );
-	dev_priv->head->age = RADEON_BUFFER_USED;
+	drm_buf_t *buf;
+	int i, t;
+	int start;
 
-	for ( i = 0 ; i < dma->buf_count ; i++ ) {
-		buf = dma->buflist[i];
-		buf_priv = buf->dev_private;
+	if ( ++dev_priv->last_buf >= dma->buf_count )
+		dev_priv->last_buf = 0;
 
-		entry = DRM(alloc)( sizeof(drm_radeon_freelist_t),
-				    DRM_MEM_DRIVER );
-		if ( !entry ) return -ENOMEM;
-
-		entry->age = RADEON_BUFFER_FREE;
-		entry->buf = buf;
-		entry->prev = dev_priv->head;
-		entry->next = dev_priv->head->next;
-		if ( !entry->next )
-			dev_priv->tail = entry;
-
-		buf_priv->discard = 0;
-		buf_priv->dispatched = 0;
-		buf_priv->list_entry = entry;
+	start = dev_priv->last_buf;
 
-		dev_priv->head->next = entry;
+	for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
+		u32 done_age = GET_SCRATCH( 1 );
+		DRM_DEBUG("done_age = %d\n",done_age);
+		for ( i = start ; i < dma->buf_count ; i++ ) {
+			buf = dma->buflist[i];
+			buf_priv = buf->dev_private;
+			if ( buf->pid == 0 || (buf->pending && 
+					       buf_priv->age <= done_age) ) {
+				dev_priv->stats.requested_bufs++;
+				buf->pending = 0;
+				return buf;
+			}
+			start = 0;
+		}
 
-		if ( dev_priv->head->next )
-			dev_priv->head->next->prev = entry;
+		if (t) {
+			DRM_UDELAY( 1 );
+			dev_priv->stats.freelist_loops++;
+		}
 	}
 
-	return 0;
-
+	DRM_DEBUG( "returning NULL!\n" );
+	return NULL;
 }
-#endif
-
+#if 0
 drm_buf_t *radeon_freelist_get( drm_device_t *dev )
 {
 	drm_device_dma_t *dma = dev->dma;
@@ -1263,76 +1508,40 @@
 	drm_radeon_buf_priv_t *buf_priv;
 	drm_buf_t *buf;
 	int i, t;
-#if ROTATE_BUFS
 	int start;
-#endif
+	u32 done_age = DRM_READ32(&dev_priv->scratch[1]);
 
-	/* FIXME: Optimize -- use freelist code */
-
-	for ( i = 0 ; i < dma->buf_count ; i++ ) {
-		buf = dma->buflist[i];
-		buf_priv = buf->dev_private;
-		if ( buf->pid == 0 ) {
-			DRM_DEBUG( "  ret buf=%d last=%d pid=0\n",
-				   buf->idx, dev_priv->last_buf );
-			return buf;
-		}
-		DRM_DEBUG( "    skipping buf=%d pid=%d\n",
-			   buf->idx, buf->pid );
-	}
-
-#if ROTATE_BUFS
 	if ( ++dev_priv->last_buf >= dma->buf_count )
 		dev_priv->last_buf = 0;
+
 	start = dev_priv->last_buf;
-#endif
-	for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) {
-#if 0
-		/* FIXME: Disable this for now */
-		u32 done_age = dev_priv->scratch[RADEON_LAST_DISPATCH];
-#else
-		u32 done_age = RADEON_READ( RADEON_LAST_DISPATCH_REG );
-#endif
-#if ROTATE_BUFS
+	dev_priv->stats.freelist_loops++;
+	
+	for ( t = 0 ; t < 2 ; t++ ) {
 		for ( i = start ; i < dma->buf_count ; i++ ) {
-#else
-		for ( i = 0 ; i < dma->buf_count ; i++ ) {
-#endif
 			buf = dma->buflist[i];
 			buf_priv = buf->dev_private;
-			if ( buf->pending && buf_priv->age <= done_age ) {
-				/* The buffer has been processed, so it
-				 * can now be used.
-				 */
+			if ( buf->pid == 0 || (buf->pending && 
+					       buf_priv->age <= done_age) ) {
+				dev_priv->stats.requested_bufs++;
 				buf->pending = 0;
-				DRM_DEBUG( "  ret buf=%d last=%d age=%d done=%d\n", buf->idx, dev_priv->last_buf, buf_priv->age, done_age );
 				return buf;
 			}
-			DRM_DEBUG( "    skipping buf=%d age=%d done=%d\n",
-				   buf->idx, buf_priv->age,
-				   done_age );
-#if ROTATE_BUFS
-			start = 0;
-#endif
 		}
-		udelay( 1 );
+		start = 0;
 	}
 
-	DRM_ERROR( "returning NULL!\n" );
 	return NULL;
 }
+#endif
 
 void radeon_freelist_reset( drm_device_t *dev )
 {
 	drm_device_dma_t *dma = dev->dma;
-#if ROTATE_BUFS
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-#endif
 	int i;
 
-#if ROTATE_BUFS
 	dev_priv->last_buf = 0;
-#endif
 	for ( i = 0 ; i < dma->buf_count ; i++ ) {
 		drm_buf_t *buf = dma->buflist[i];
 		drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
@@ -1349,12 +1558,24 @@
 {
 	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
 	int i;
+	u32 last_head = GET_RING_HEAD(ring);
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-		radeon_update_ring_snapshot( ring );
+		u32 head = GET_RING_HEAD(ring);
+
+		ring->space = (head - ring->tail) * sizeof(u32);
+		if ( ring->space <= 0 )
+			ring->space += ring->size;
 		if ( ring->space > n )
 			return 0;
-		udelay( 1 );
+		
+		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+		if (head != last_head)
+			i = 0;
+		last_head = head;
+
+		DRM_UDELAY( 1 );
 	}
 
 	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
@@ -1362,7 +1583,7 @@
 	radeon_status( dev_priv );
 	DRM_ERROR( "failed!\n" );
 #endif
-	return -EBUSY;
+	return DRM_ERR(EBUSY);
 }
 
 static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
@@ -1372,50 +1593,47 @@
 
 	for ( i = d->granted_count ; i < d->request_count ; i++ ) {
 		buf = radeon_freelist_get( dev );
-		if ( !buf ) return -EAGAIN;
+		if ( !buf ) return DRM_ERR(EBUSY); /* NOTE: broken client */
 
-		buf->pid = current->pid;
+		buf->pid = DRM_CURRENTPID;
 
-		if ( copy_to_user( &d->request_indices[i], &buf->idx,
+		if ( DRM_COPY_TO_USER( &d->request_indices[i], &buf->idx,
 				   sizeof(buf->idx) ) )
-			return -EFAULT;
-		if ( copy_to_user( &d->request_sizes[i], &buf->total,
+			return DRM_ERR(EFAULT);
+		if ( DRM_COPY_TO_USER( &d->request_sizes[i], &buf->total,
 				   sizeof(buf->total) ) )
-			return -EFAULT;
+			return DRM_ERR(EFAULT);
 
 		d->granted_count++;
 	}
 	return 0;
 }
 
-int radeon_cp_buffers( struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg )
+int radeon_cp_buffers( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_device_dma_t *dma = dev->dma;
 	int ret = 0;
 	drm_dma_t d;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( d, (drm_dma_t *)data, sizeof(d) );
 
 	/* Please don't send us buffers.
 	 */
 	if ( d.send_count != 0 ) {
 		DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n",
-			   current->pid, d.send_count );
-		return -EINVAL;
+			   DRM_CURRENTPID, d.send_count );
+		return DRM_ERR(EINVAL);
 	}
 
 	/* We'll send you buffers.
 	 */
 	if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
 		DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n",
-			   current->pid, d.request_count, dma->buf_count );
-		return -EINVAL;
+			   DRM_CURRENTPID, d.request_count, dma->buf_count );
+		return DRM_ERR(EINVAL);
 	}
 
 	d.granted_count = 0;
@@ -1424,8 +1642,7 @@
 		ret = radeon_cp_get_buffers( dev, &d );
 	}
 
-	if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
-		return -EFAULT;
+	DRM_COPY_TO_USER_IOCTL( (drm_dma_t *)data, d, sizeof(d) );
 
 	return ret;
 }
diff -ruN drivers/char/drm-4.2/radeon_drm.h drivers/char/drm/radeon_drm.h
--- drivers/char/drm-4.2/radeon_drm.h	2001-08-09 01:42:15.000000000 +0900
+++ drivers/char/drm/radeon_drm.h	2003-01-14 07:01:00.000000000 +0900
@@ -2,6 +2,7 @@
  *
  * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -26,6 +27,7 @@
  * Authors:
  *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
  */
 
 #ifndef __RADEON_DRM_H__
@@ -37,7 +39,8 @@
 #ifndef __RADEON_SAREA_DEFINES__
 #define __RADEON_SAREA_DEFINES__
 
-/* What needs to be changed for the current vertex buffer?
+/* Old style state flags, required for sarea interface (1.1 and 1.2
+ * clears) and 1.2 drm_vertex2 ioctl.
  */
 #define RADEON_UPLOAD_CONTEXT		0x00000001
 #define RADEON_UPLOAD_VERTFMT		0x00000002
@@ -56,11 +59,136 @@
 #define RADEON_UPLOAD_TEX2IMAGES	0x00004000
 #define RADEON_UPLOAD_CLIPRECTS		0x00008000 /* handled client-side */
 #define RADEON_REQUIRE_QUIESCENCE	0x00010000
-#define RADEON_UPLOAD_ALL		0x0001ffff
+#define RADEON_UPLOAD_ZBIAS		0x00020000 /* version 1.2 and newer */
+#define RADEON_UPLOAD_ALL		0x003effff
+#define RADEON_UPLOAD_CONTEXT_ALL       0x003e01ff
+
+
+/* New style per-packet identifiers for use in cmd_buffer ioctl with
+ * the RADEON_EMIT_PACKET command.  Comments relate new packets to old
+ * state bits and the packet size:
+ */
+#define RADEON_EMIT_PP_MISC                         0 /* context/7 */
+#define RADEON_EMIT_PP_CNTL                         1 /* context/3 */
+#define RADEON_EMIT_RB3D_COLORPITCH                 2 /* context/1 */
+#define RADEON_EMIT_RE_LINE_PATTERN                 3 /* line/2 */
+#define RADEON_EMIT_SE_LINE_WIDTH                   4 /* line/1 */
+#define RADEON_EMIT_PP_LUM_MATRIX                   5 /* bumpmap/1 */
+#define RADEON_EMIT_PP_ROT_MATRIX_0                 6 /* bumpmap/2 */
+#define RADEON_EMIT_RB3D_STENCILREFMASK             7 /* masks/3 */
+#define RADEON_EMIT_SE_VPORT_XSCALE                 8 /* viewport/6 */
+#define RADEON_EMIT_SE_CNTL                         9 /* setup/2 */
+#define RADEON_EMIT_SE_CNTL_STATUS                  10 /* setup/1 */
+#define RADEON_EMIT_RE_MISC                         11 /* misc/1 */
+#define RADEON_EMIT_PP_TXFILTER_0                   12 /* tex0/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_0               13 /* tex0/1 */
+#define RADEON_EMIT_PP_TXFILTER_1                   14 /* tex1/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_1               15 /* tex1/1 */
+#define RADEON_EMIT_PP_TXFILTER_2                   16 /* tex2/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_2               17 /* tex2/1 */
+#define RADEON_EMIT_SE_ZBIAS_FACTOR                 18 /* zbias/2 */
+#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT           19 /* tcl/11 */
+#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED   20 /* material/17 */
+#define R200_EMIT_PP_TXCBLEND_0                     21 /* tex0/4 */
+#define R200_EMIT_PP_TXCBLEND_1                     22 /* tex1/4 */
+#define R200_EMIT_PP_TXCBLEND_2                     23 /* tex2/4 */
+#define R200_EMIT_PP_TXCBLEND_3                     24 /* tex3/4 */
+#define R200_EMIT_PP_TXCBLEND_4                     25 /* tex4/4 */
+#define R200_EMIT_PP_TXCBLEND_5                     26 /* tex5/4 */
+#define R200_EMIT_PP_TXCBLEND_6                     27 /* /4 */
+#define R200_EMIT_PP_TXCBLEND_7                     28 /* /4 */
+#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0             29 /* tcl/7 */
+#define R200_EMIT_TFACTOR_0                         30 /* tf/7 */
+#define R200_EMIT_VTX_FMT_0                         31 /* vtx/5 */
+#define R200_EMIT_VAP_CTL                           32 /* vap/1 */
+#define R200_EMIT_MATRIX_SELECT_0                   33 /* msl/5 */
+#define R200_EMIT_TEX_PROC_CTL_2                    34 /* tcg/5 */
+#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL            35 /* tcl/1 */
+#define R200_EMIT_PP_TXFILTER_0                     36 /* tex0/6 */
+#define R200_EMIT_PP_TXFILTER_1                     37 /* tex1/6 */
+#define R200_EMIT_PP_TXFILTER_2                     38 /* tex2/6 */
+#define R200_EMIT_PP_TXFILTER_3                     39 /* tex3/6 */
+#define R200_EMIT_PP_TXFILTER_4                     40 /* tex4/6 */
+#define R200_EMIT_PP_TXFILTER_5                     41 /* tex5/6 */
+#define R200_EMIT_PP_TXOFFSET_0                     42 /* tex0/1 */
+#define R200_EMIT_PP_TXOFFSET_1                     43 /* tex1/1 */
+#define R200_EMIT_PP_TXOFFSET_2                     44 /* tex2/1 */
+#define R200_EMIT_PP_TXOFFSET_3                     45 /* tex3/1 */
+#define R200_EMIT_PP_TXOFFSET_4                     46 /* tex4/1 */
+#define R200_EMIT_PP_TXOFFSET_5                     47 /* tex5/1 */
+#define R200_EMIT_VTE_CNTL                          48 /* vte/1 */
+#define R200_EMIT_OUTPUT_VTX_COMP_SEL               49 /* vtx/1 */
+#define R200_EMIT_PP_TAM_DEBUG3                     50 /* tam/1 */
+#define R200_EMIT_PP_CNTL_X                         51 /* cst/1 */
+#define R200_EMIT_RB3D_DEPTHXY_OFFSET               52 /* cst/1 */
+#define R200_EMIT_RE_AUX_SCISSOR_CNTL               53 /* cst/1 */
+#define R200_EMIT_RE_SCISSOR_TL_0                   54 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_1                   55 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_2                   56 /* cst/2 */
+#define R200_EMIT_SE_VAP_CNTL_STATUS                57 /* cst/1 */
+#define R200_EMIT_SE_VTX_STATE_CNTL                 58 /* cst/1 */
+#define R200_EMIT_RE_POINTSIZE                      59 /* cst/1 */
+#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0       60 /* cst/4 */
+#define R200_EMIT_PP_CUBIC_FACES_0                  61
+#define R200_EMIT_PP_CUBIC_OFFSETS_0                62
+#define R200_EMIT_PP_CUBIC_FACES_1                  63
+#define R200_EMIT_PP_CUBIC_OFFSETS_1                64
+#define R200_EMIT_PP_CUBIC_FACES_2                  65
+#define R200_EMIT_PP_CUBIC_OFFSETS_2                66
+#define R200_EMIT_PP_CUBIC_FACES_3                  67
+#define R200_EMIT_PP_CUBIC_OFFSETS_3                68
+#define R200_EMIT_PP_CUBIC_FACES_4                  69
+#define R200_EMIT_PP_CUBIC_OFFSETS_4                70
+#define R200_EMIT_PP_CUBIC_FACES_5                  71
+#define R200_EMIT_PP_CUBIC_OFFSETS_5                72
+#define RADEON_MAX_STATE_PACKETS                    73
+
+
+/* Commands understood by cmd_buffer ioctl.  More can be added but
+ * obviously these can't be removed or changed:
+ */
+#define RADEON_CMD_PACKET      1 /* emit one of the register packets above */
+#define RADEON_CMD_SCALARS     2 /* emit scalar data */
+#define RADEON_CMD_VECTORS     3 /* emit vector data */
+#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
+#define RADEON_CMD_PACKET3     5 /* emit hw packet */
+#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
+#define RADEON_CMD_SCALARS2     7 /* r200 stopgap */
+#define RADEON_CMD_WAIT         8 /* emit hw wait commands -- note:
+				   *  doesn't make the cpu wait, just
+				   *  the graphics hardware */
+
+
+typedef union {
+	int i;
+	struct { 
+		unsigned char cmd_type, pad0, pad1, pad2;
+	} header;
+	struct { 
+		unsigned char cmd_type, packet_id, pad0, pad1;
+	} packet;
+	struct { 
+		unsigned char cmd_type, offset, stride, count; 
+	} scalars;
+	struct { 
+		unsigned char cmd_type, offset, stride, count; 
+	} vectors;
+	struct { 
+		unsigned char cmd_type, buf_idx, pad0, pad1; 
+	} dma;
+	struct { 
+		unsigned char cmd_type, flags, pad0, pad1; 
+	} wait;
+} drm_radeon_cmd_header_t;
+
+#define RADEON_WAIT_2D  0x1
+#define RADEON_WAIT_3D  0x2
+
 
 #define RADEON_FRONT			0x1
 #define RADEON_BACK			0x2
 #define RADEON_DEPTH			0x4
+#define RADEON_STENCIL                  0x8
 
 /* Primitive types
  */
@@ -78,12 +206,9 @@
 /* Byte offsets for indirect buffer data
  */
 #define RADEON_INDEX_PRIM_OFFSET	20
-#define RADEON_HOSTDATA_BLIT_OFFSET	32
 
 #define RADEON_SCRATCH_REG_OFFSET	32
 
-/* Keep these small for testing
- */
 #define RADEON_NR_SAREA_CLIPRECTS	12
 
 /* There are 2 heaps (local/AGP).  Each region within a heap is a
@@ -95,7 +220,7 @@
 #define RADEON_NR_TEX_REGIONS		64
 #define RADEON_LOG_TEX_GRANULARITY	16
 
-#define RADEON_MAX_TEXTURE_LEVELS	11
+#define RADEON_MAX_TEXTURE_LEVELS	12
 #define RADEON_MAX_TEXTURE_UNITS	3
 
 #endif /* __RADEON_SAREA_DEFINES__ */
@@ -155,28 +280,18 @@
 	/* Setup state */
 	unsigned int se_cntl_status;			/* 0x2140 */
 
-#ifdef TCL_ENABLE
-	/* TCL state */
-	radeon_color_regs_t se_tcl_material_emmissive;	/* 0x2210 */
-	radeon_color_regs_t se_tcl_material_ambient;
-	radeon_color_regs_t se_tcl_material_diffuse;
-	radeon_color_regs_t se_tcl_material_specular;
-	unsigned int se_tcl_shininess;
-	unsigned int se_tcl_output_vtx_fmt;
-	unsigned int se_tcl_output_vtx_sel;
-	unsigned int se_tcl_matrix_select_0;
-	unsigned int se_tcl_matrix_select_1;
-	unsigned int se_tcl_ucp_vert_blend_ctl;
-	unsigned int se_tcl_texture_proc_ctl;
-	unsigned int se_tcl_light_model_ctl;
-	unsigned int se_tcl_per_light_ctl[4];
-#endif
-
 	/* Misc state */
 	unsigned int re_top_left;			/* 0x26c0 */
 	unsigned int re_misc;
 } drm_radeon_context_regs_t;
 
+typedef struct {
+	/* Zbias state */
+	unsigned int se_zbias_factor;			/* 0x1dac */
+	unsigned int se_zbias_constant;
+} drm_radeon_context2_regs_t;
+
+
 /* Setup registers for each texture unit
  */
 typedef struct {
@@ -186,24 +301,37 @@
 	unsigned int pp_txcblend;
 	unsigned int pp_txablend;
 	unsigned int pp_tfactor;
-
 	unsigned int pp_border_color;
-
-#ifdef CUBIC_ENABLE
-	unsigned int pp_cubic_faces;
-	unsigned int pp_cubic_offset[5];
-#endif
 } drm_radeon_texture_regs_t;
 
 typedef struct {
+	unsigned int start;
+	unsigned int finish;
+	unsigned int prim:8;
+	unsigned int stateidx:8;
+	unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
+        unsigned int vc_format;   /* vertex format */
+} drm_radeon_prim_t;
+
+
+typedef struct {
+	drm_radeon_context_regs_t context;
+	drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS];
+	drm_radeon_context2_regs_t context2;
+	unsigned int dirty;
+} drm_radeon_state_t;
+
+
+typedef struct {
 	unsigned char next, prev;
 	unsigned char in_use;
 	int age;
 } drm_radeon_tex_region_t;
 
 typedef struct {
-	/* The channel for communication of state information to the kernel
-	 * on firing a vertex buffer.
+	/* The channel for communication of state information to the
+	 * kernel on firing a vertex buffer with either of the
+	 * obsoleted vertex/index ioctls.
 	 */
 	drm_radeon_context_regs_t context_state;
 	drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS];
@@ -225,16 +353,50 @@
 	drm_radeon_tex_region_t tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
 	int tex_age[RADEON_NR_TEX_HEAPS];
 	int ctx_owner;
+        int pfState;                /* number of 3d windows (0,1,2ormore) */
+        int pfCurrentPage;	    /* which buffer is being displayed? */
+	int crtc2_base;		    /* CRTC2 frame offset */
 } drm_radeon_sarea_t;
 
 
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the Xserver file (xf86drmRadeon.h)
+ *
+ * KW: actually it's illegal to change any of this (backwards compatibility).
  */
+
+/* Radeon specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( 0x40, drm_radeon_init_t)
+#define DRM_IOCTL_RADEON_CP_START   DRM_IO(  0x41)
+#define DRM_IOCTL_RADEON_CP_STOP    DRM_IOW( 0x42, drm_radeon_cp_stop_t)
+#define DRM_IOCTL_RADEON_CP_RESET   DRM_IO(  0x43)
+#define DRM_IOCTL_RADEON_CP_IDLE    DRM_IO(  0x44)
+#define DRM_IOCTL_RADEON_RESET      DRM_IO(  0x45)
+#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t)
+#define DRM_IOCTL_RADEON_SWAP       DRM_IO(  0x47)
+#define DRM_IOCTL_RADEON_CLEAR      DRM_IOW( 0x48, drm_radeon_clear_t)
+#define DRM_IOCTL_RADEON_VERTEX     DRM_IOW( 0x49, drm_radeon_vertex_t)
+#define DRM_IOCTL_RADEON_INDICES    DRM_IOW( 0x4a, drm_radeon_indices_t)
+#define DRM_IOCTL_RADEON_STIPPLE    DRM_IOW( 0x4c, drm_radeon_stipple_t)
+#define DRM_IOCTL_RADEON_INDIRECT   DRM_IOWR(0x4d, drm_radeon_indirect_t)
+#define DRM_IOCTL_RADEON_TEXTURE    DRM_IOWR(0x4e, drm_radeon_texture_t)
+#define DRM_IOCTL_RADEON_VERTEX2    DRM_IOW( 0x4f, drm_radeon_vertex_t)
+#define DRM_IOCTL_RADEON_CMDBUF     DRM_IOW( 0x50, drm_radeon_cmd_buffer_t)
+#define DRM_IOCTL_RADEON_GETPARAM   DRM_IOWR(0x51, drm_radeon_getparam_t)
+#define DRM_IOCTL_RADEON_FLIP	    DRM_IO(  0x52)
+#define DRM_IOCTL_RADEON_ALLOC      DRM_IOWR( 0x53, drm_radeon_mem_alloc_t)
+#define DRM_IOCTL_RADEON_FREE       DRM_IOW( 0x54, drm_radeon_mem_free_t)
+#define DRM_IOCTL_RADEON_INIT_HEAP  DRM_IOW( 0x55, drm_radeon_mem_init_heap_t)
+#define DRM_IOCTL_RADEON_IRQ_EMIT   DRM_IOWR( 0x56, drm_radeon_irq_emit_t)
+#define DRM_IOCTL_RADEON_IRQ_WAIT   DRM_IOW( 0x57, drm_radeon_irq_wait_t)
+
 typedef struct drm_radeon_init {
 	enum {
 		RADEON_INIT_CP    = 0x01,
-		RADEON_CLEANUP_CP = 0x02
+		RADEON_CLEANUP_CP = 0x02,
+		RADEON_INIT_R200_CP = 0x03,	
 	} func;
 	unsigned long sarea_priv_offset;
 	int is_pci;
@@ -285,7 +447,7 @@
 	unsigned int clear_color;
 	unsigned int clear_depth;
 	unsigned int color_mask;
-	unsigned int depth_mask;
+	unsigned int depth_mask;   /* misnamed field:  should be stencil */
 	drm_radeon_clear_rect_t *depth_boxes;
 } drm_radeon_clear_t;
 
@@ -304,6 +466,36 @@
 	int discard;			/* Client finished with buffer? */
 } drm_radeon_indices_t;
 
+/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices
+ *      - allows multiple primitives and state changes in a single ioctl
+ *      - supports driver change to emit native primitives
+ */
+typedef struct drm_radeon_vertex2 {
+	int idx;			/* Index of vertex buffer */
+	int discard;			/* Client finished with buffer? */
+	int nr_states;
+	drm_radeon_state_t *state;
+	int nr_prims;
+	drm_radeon_prim_t *prim;
+} drm_radeon_vertex2_t;
+
+/* v1.3 - obsoletes drm_radeon_vertex2
+ *      - allows arbitarily large cliprect list 
+ *      - allows updating of tcl packet, vector and scalar state
+ *      - allows memory-efficient description of state updates
+ *      - allows state to be emitted without a primitive 
+ *           (for clears, ctx switches)
+ *      - allows more than one dma buffer to be referenced per ioctl
+ *      - supports tcl driver
+ *      - may be extended in future versions with new cmd types, packets
+ */
+typedef struct drm_radeon_cmd_buffer {
+	int bufsz;
+	char *buf;
+	int nbox;
+	drm_clip_rect_t *boxes;
+} drm_radeon_cmd_buffer_t;
+
 typedef struct drm_radeon_tex_image {
 	unsigned int x, y;		/* Blit coordinates */
 	unsigned int width, height;
@@ -330,4 +522,55 @@
 	int discard;
 } drm_radeon_indirect_t;
 
+
+/* 1.3: An ioctl to get parameters that aren't available to the 3d
+ * client any other way.  
+ */
+#define RADEON_PARAM_AGP_BUFFER_OFFSET     1 /* card offset of 1st agp buffer */
+#define RADEON_PARAM_LAST_FRAME            2
+#define RADEON_PARAM_LAST_DISPATCH         3
+#define RADEON_PARAM_LAST_CLEAR            4
+#define RADEON_PARAM_IRQ_NR                5
+#define RADEON_PARAM_AGP_BASE              6 /* card offset of agp base */
+
+typedef struct drm_radeon_getparam {
+	int param;
+	int *value;
+} drm_radeon_getparam_t;
+
+/* 1.6: Set up a memory manager for regions of shared memory:
+ */
+#define RADEON_MEM_REGION_AGP 1
+#define RADEON_MEM_REGION_FB  2
+
+typedef struct drm_radeon_mem_alloc {
+	int region;
+	int alignment;
+	int size;
+	int *region_offset;	/* offset from start of fb or agp */
+} drm_radeon_mem_alloc_t;
+
+typedef struct drm_radeon_mem_free {
+	int region;
+	int region_offset;
+} drm_radeon_mem_free_t;
+
+typedef struct drm_radeon_mem_init_heap {
+	int region;
+	int size;
+	int start;	
+} drm_radeon_mem_init_heap_t;
+
+
+/* 1.6: Userspace can request & wait on irq's:
+ */
+typedef struct drm_radeon_irq_emit {
+	int *irq_seq;
+} drm_radeon_irq_emit_t;
+
+typedef struct drm_radeon_irq_wait {
+	int irq_seq;
+} drm_radeon_irq_wait_t;
+
+
 #endif
diff -ruN drivers/char/drm-4.2/radeon_drv.c drivers/char/drm/radeon_drv.c
--- drivers/char/drm-4.2/radeon_drv.c	2001-08-09 01:42:15.000000000 +0900
+++ drivers/char/drm/radeon_drv.c	2003-01-14 07:00:59.000000000 +0900
@@ -30,47 +30,11 @@
 #include <linux/config.h>
 #include "radeon.h"
 #include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
 #include "radeon_drv.h"
 #include "ati_pcigart.h"
 
-#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
-
-#define DRIVER_NAME		"radeon"
-#define DRIVER_DESC		"ATI Radeon"
-#define DRIVER_DATE		"20010405"
-
-#define DRIVER_MAJOR		1
-#define DRIVER_MINOR		1
-#define DRIVER_PATCHLEVEL	1
-
-#define DRIVER_IOCTLS							     \
- [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_INIT)]    = { radeon_cp_init,     1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_START)]   = { radeon_cp_start,    1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)]    = { radeon_cp_stop,     1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)]   = { radeon_cp_reset,    1, 1 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)]    = { radeon_cp_idle,     1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)]    = { radeon_engine_reset,  1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen,  1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)]       = { radeon_cp_swap,     1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)]      = { radeon_cp_clear,    1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)]     = { radeon_cp_vertex,   1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)]    = { radeon_cp_indices,  1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_TEXTURE)]    = { radeon_cp_texture,  1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)]    = { radeon_cp_stipple,  1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)]   = { radeon_cp_indirect, 1, 1 },
-
-
-#if 0
-/* GH: Count data sent to card via ring or vertex/indirect buffers.
- */
-#define __HAVE_COUNTERS         3
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-#endif
-
-
 #include "drm_agpsupport.h"
 #include "drm_auth.h"
 #include "drm_bufs.h"
@@ -78,26 +42,6 @@
 #include "drm_dma.h"
 #include "drm_drawable.h"
 #include "drm_drv.h"
-
-#ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO).  It calls the insmod option
- * routine, drm_parse_drm.
- */
-
-/* JH- We have to hand expand the string ourselves because of the cpp.  If
- * anyone can think of a way that we can fit into the __setup macro without
- * changing it, then please send the solution my way.
- */
-static int __init radeon_options( char *str )
-{
-	DRM(parse_options)( str );
-	return 1;
-}
-
-__setup( DRIVER_NAME "=", radeon_options );
-#endif
-
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
diff -ruN drivers/char/drm-4.2/radeon_drv.h drivers/char/drm/radeon_drv.h
--- drivers/char/drm-4.2/radeon_drv.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/radeon_drv.h	2003-01-14 07:01:00.000000000 +0900
@@ -31,6 +31,9 @@
 #ifndef __RADEON_DRV_H__
 #define __RADEON_DRV_H__
 
+#define GET_RING_HEAD(ring)		DRM_READ32(  (volatile u32 *) (ring)->head )
+#define SET_RING_HEAD(ring,val)		DRM_WRITE32( (volatile u32 *) (ring)->head , (val))
+
 typedef struct drm_radeon_freelist {
    	unsigned int age;
    	drm_buf_t *buf;
@@ -58,6 +61,15 @@
 	u32 se_cntl;
 } drm_radeon_depth_clear_t;
 
+
+struct mem_block {
+	struct mem_block *next;
+	struct mem_block *prev;
+	int start;
+	int size;
+	int pid;		/* 0: free, -1: heap, other: real pids */
+};
+
 typedef struct drm_radeon_private {
 	drm_radeon_ring_buffer_t ring;
 	drm_radeon_sarea_t *sarea_priv;
@@ -71,27 +83,32 @@
 
    	drm_radeon_freelist_t *head;
    	drm_radeon_freelist_t *tail;
-/* FIXME: ROTATE_BUFS is a hask to cycle through bufs until freelist
-   code is used.  Note this hides a problem with the scratch register
-   (used to keep track of last buffer completed) being written to before
-   the last buffer has actually completed rendering. */
-#define ROTATE_BUFS 1
-#if ROTATE_BUFS
 	int last_buf;
-#endif
 	volatile u32 *scratch;
+	int writeback_works;
 
 	int usec_timeout;
+
+	int is_r200;
+
 	int is_pci;
 	unsigned long phys_pci_gart;
 	dma_addr_t bus_pci_gart;
 
-	atomic_t idle_count;
+	struct {
+		u32 boxes;
+		int freelist_timeouts;
+		int freelist_loops;
+		int requested_bufs;
+		int last_frame_reads;
+		int last_clear_reads;
+		int clears;
+		int texture_uploads;
+	} stats;
 
+	int do_boxes;
 	int page_flipping;
 	int current_page;
-	u32 crtc_offset;
-	u32 crtc_offset_cntl;
 
 	u32 color_fmt;
 	unsigned int front_offset;
@@ -116,66 +133,75 @@
 	drm_map_t *ring_rptr;
 	drm_map_t *buffers;
 	drm_map_t *agp_textures;
+
+	struct mem_block *agp_heap;
+	struct mem_block *fb_heap;
+
+	/* SW interrupt */
+   	wait_queue_head_t swi_queue;
+   	atomic_t swi_emitted;
+
 } drm_radeon_private_t;
 
 typedef struct drm_radeon_buf_priv {
 	u32 age;
-	int prim;
-	int discard;
-	int dispatched;
-   	drm_radeon_freelist_t *list_entry;
 } drm_radeon_buf_priv_t;
 
 				/* radeon_cp.c */
-extern int radeon_cp_init( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int radeon_cp_start( struct inode *inode, struct file *filp,
-			    unsigned int cmd, unsigned long arg );
-extern int radeon_cp_stop( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int radeon_cp_reset( struct inode *inode, struct file *filp,
-			    unsigned int cmd, unsigned long arg );
-extern int radeon_cp_idle( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int radeon_engine_reset( struct inode *inode, struct file *filp,
-				unsigned int cmd, unsigned long arg );
-extern int radeon_fullscreen( struct inode *inode, struct file *filp,
-			      unsigned int cmd, unsigned long arg );
-extern int radeon_cp_buffers( struct inode *inode, struct file *filp,
-			      unsigned int cmd, unsigned long arg );
+extern int radeon_cp_init( DRM_IOCTL_ARGS );
+extern int radeon_cp_start( DRM_IOCTL_ARGS );
+extern int radeon_cp_stop( DRM_IOCTL_ARGS );
+extern int radeon_cp_reset( DRM_IOCTL_ARGS );
+extern int radeon_cp_idle( DRM_IOCTL_ARGS );
+extern int radeon_engine_reset( DRM_IOCTL_ARGS );
+extern int radeon_fullscreen( DRM_IOCTL_ARGS );
+extern int radeon_cp_buffers( DRM_IOCTL_ARGS );
 
 extern void radeon_freelist_reset( drm_device_t *dev );
 extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
 
 extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
 
-static inline void
-radeon_update_ring_snapshot( drm_radeon_ring_buffer_t *ring )
-{
-	ring->space = (*(volatile int *)ring->head - ring->tail) * sizeof(u32);
-	if ( ring->space <= 0 )
-		ring->space += ring->size;
-}
-
 extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
 extern int radeon_do_cleanup_cp( drm_device_t *dev );
 extern int radeon_do_cleanup_pageflip( drm_device_t *dev );
 
 				/* radeon_state.c */
-extern int radeon_cp_clear( struct inode *inode, struct file *filp,
-			    unsigned int cmd, unsigned long arg );
-extern int radeon_cp_swap( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-extern int radeon_cp_vertex( struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg );
-extern int radeon_cp_indices( struct inode *inode, struct file *filp,
-			      unsigned int cmd, unsigned long arg );
-extern int radeon_cp_texture( struct inode *inode, struct file *filp,
-			      unsigned int cmd, unsigned long arg );
-extern int radeon_cp_stipple( struct inode *inode, struct file *filp,
-			      unsigned int cmd, unsigned long arg );
-extern int radeon_cp_indirect( struct inode *inode, struct file *filp,
-			       unsigned int cmd, unsigned long arg );
+extern int radeon_cp_clear( DRM_IOCTL_ARGS );
+extern int radeon_cp_swap( DRM_IOCTL_ARGS );
+extern int radeon_cp_vertex( DRM_IOCTL_ARGS );
+extern int radeon_cp_indices( DRM_IOCTL_ARGS );
+extern int radeon_cp_texture( DRM_IOCTL_ARGS );
+extern int radeon_cp_stipple( DRM_IOCTL_ARGS );
+extern int radeon_cp_indirect( DRM_IOCTL_ARGS );
+extern int radeon_cp_vertex2( DRM_IOCTL_ARGS );
+extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS );
+extern int radeon_cp_getparam( DRM_IOCTL_ARGS );
+extern int radeon_cp_flip( DRM_IOCTL_ARGS );
+
+extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
+extern int radeon_mem_free( DRM_IOCTL_ARGS );
+extern int radeon_mem_init_heap( DRM_IOCTL_ARGS );
+extern void radeon_mem_takedown( struct mem_block **heap );
+extern void radeon_mem_release( struct mem_block *heap );
+
+				/* radeon_irq.c */
+extern int radeon_irq_emit( DRM_IOCTL_ARGS );
+extern int radeon_irq_wait( DRM_IOCTL_ARGS );
+
+extern int radeon_emit_and_wait_irq(drm_device_t *dev);
+extern int radeon_wait_irq(drm_device_t *dev, int swi_nr);
+extern int radeon_emit_irq(drm_device_t *dev);
+
+
+/* Flags for stats.boxes
+ */
+#define RADEON_BOX_DMA_IDLE      0x1
+#define RADEON_BOX_RING_FULL     0x2
+#define RADEON_BOX_FLIP          0x4
+#define RADEON_BOX_WAIT_IDLE     0x8
+#define RADEON_BOX_TEXTURE_LOAD  0x10
+
 
 
 /* Register definitions, register access macros and drmAddMap constants
@@ -202,10 +228,10 @@
 #define RADEON_CRTC_OFFSET_CNTL		0x0228
 #	define RADEON_CRTC_TILE_EN		(1 << 15)
 #	define RADEON_CRTC_OFFSET_FLIP_CNTL	(1 << 16)
+#define RADEON_CRTC2_OFFSET		0x0324
+#define RADEON_CRTC2_OFFSET_CNTL	0x0328
 
 #define RADEON_RB3D_COLORPITCH		0x1c48
-#define RADEON_RB3D_DEPTHCLEARVALUE	0x1c30
-#define RADEON_RB3D_DEPTHXY_OFFSET	0x1c60
 
 #define RADEON_DP_GUI_MASTER_CNTL	0x146c
 #	define RADEON_GMC_SRC_PITCH_OFFSET_CNTL	(1 << 0)
@@ -240,6 +266,24 @@
 #define RADEON_SCRATCH_UMSK		0x0770
 #define RADEON_SCRATCH_ADDR		0x0774
 
+#define GET_SCRATCH( x )	(dev_priv->writeback_works			\
+				? DRM_READ32( &dev_priv->scratch[(x)] )		\
+				: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+
+
+#define RADEON_GEN_INT_CNTL		0x0040
+#	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
+#	define RADEON_GUI_IDLE_INT_ENABLE	(1 << 19)
+#	define RADEON_SW_INT_ENABLE		(1 << 25)
+
+#define RADEON_GEN_INT_STATUS		0x0044
+#	define RADEON_CRTC_VBLANK_STAT		(1 << 0)
+#	define RADEON_CRTC_VBLANK_STAT_ACK   	(1 << 0)
+#	define RADEON_GUI_IDLE_INT_TEST_ACK     (1 << 19)
+#	define RADEON_SW_INT_TEST		(1 << 25)
+#	define RADEON_SW_INT_TEST_ACK   	(1 << 25)
+#	define RADEON_SW_INT_FIRE		(1 << 26)
+
 #define RADEON_HOST_PATH_CNTL		0x0130
 #	define RADEON_HDP_SOFT_RESET		(1 << 26)
 #	define RADEON_HDP_WC_TIMEOUT_MASK	(7 << 28)
@@ -253,6 +297,12 @@
 #	define RADEON_ISYNC_WAIT_IDLEGUI	(1 << 4)
 #	define RADEON_ISYNC_CPSCRATCH_IDLEGUI	(1 << 5)
 
+#define RADEON_RBBM_GUICNTL		0x172c
+#	define RADEON_HOST_DATA_SWAP_NONE	(0 << 0)
+#	define RADEON_HOST_DATA_SWAP_16BIT	(1 << 0)
+#	define RADEON_HOST_DATA_SWAP_32BIT	(2 << 0)
+#	define RADEON_HOST_DATA_SWAP_HDW	(3 << 0)
+
 #define RADEON_MC_AGP_LOCATION		0x014c
 #define RADEON_MC_FB_LOCATION		0x0148
 #define RADEON_MCLK_CNTL		0x0012
@@ -290,10 +340,8 @@
 #	define RADEON_ROP_ENABLE		(1 << 6)
 #	define RADEON_STENCIL_ENABLE		(1 << 7)
 #	define RADEON_Z_ENABLE			(1 << 8)
-#	define RADEON_DEPTH_XZ_OFFEST_ENABLE	(1 << 9)
-#	define RADEON_ZBLOCK8			(0 << 15)
-#	define RADEON_ZBLOCK16			(1 << 15)
 #define RADEON_RB3D_DEPTHOFFSET		0x1c24
+#define RADEON_RB3D_DEPTHPITCH		0x1c28
 #define RADEON_RB3D_PLANEMASK		0x1d84
 #define RADEON_RB3D_STENCILREFMASK	0x1d7c
 #define RADEON_RB3D_ZCACHE_MODE		0x3250
@@ -306,9 +354,9 @@
 #	define RADEON_Z_TEST_MASK		(7 << 4)
 #	define RADEON_Z_TEST_ALWAYS		(7 << 4)
 #	define RADEON_STENCIL_TEST_ALWAYS	(7 << 12)
-#	define RADEON_STENCIL_S_FAIL_KEEP	(0 << 16)
-#	define RADEON_STENCIL_ZPASS_KEEP	(0 << 20)
-#	define RADEON_STENCIL_ZFAIL_KEEP	(0 << 20)
+#	define RADEON_STENCIL_S_FAIL_REPLACE	(2 << 16)
+#	define RADEON_STENCIL_ZPASS_REPLACE	(2 << 20)
+#	define RADEON_STENCIL_ZFAIL_REPLACE	(2 << 24)
 #	define RADEON_Z_WRITE_ENABLE		(1 << 30)
 #define RADEON_RBBM_SOFT_RESET		0x00f0
 #	define RADEON_SOFT_RESET_CP		(1 <<  0)
@@ -357,6 +405,16 @@
 #define RADEON_SE_CNTL_STATUS		0x2140
 #define RADEON_SE_LINE_WIDTH		0x1db8
 #define RADEON_SE_VPORT_XSCALE		0x1d98
+#define RADEON_SE_ZBIAS_FACTOR		0x1db0
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210
+#define RADEON_SE_TCL_OUTPUT_VTX_FMT         0x2254
+#define RADEON_SE_TCL_VECTOR_INDX_REG        0x2200
+#       define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT  16
+#       define RADEON_VEC_INDX_DWORD_COUNT_SHIFT     28
+#define RADEON_SE_TCL_VECTOR_DATA_REG       0x2204
+#define RADEON_SE_TCL_SCALAR_INDX_REG       0x2208
+#       define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT  16
+#define RADEON_SE_TCL_SCALAR_DATA_REG       0x220C
 #define RADEON_SURFACE_ACCESS_FLAGS	0x0bf8
 #define RADEON_SURFACE_ACCESS_CLR	0x0bfc
 #define RADEON_SURFACE_CNTL		0x0b00
@@ -421,6 +479,7 @@
 
 #define RADEON_CP_RB_BASE		0x0700
 #define RADEON_CP_RB_CNTL		0x0704
+#	define RADEON_BUF_SWAP_32BIT		(2 << 16)
 #define RADEON_CP_RB_RPTR_ADDR		0x070c
 #define RADEON_CP_RB_RPTR		0x0710
 #define RADEON_CP_RB_WPTR		0x0714
@@ -457,11 +516,14 @@
 #define RADEON_CP_PACKET3		0xC0000000
 #	define RADEON_3D_RNDR_GEN_INDX_PRIM	0x00002300
 #	define RADEON_WAIT_FOR_IDLE		0x00002600
+#	define RADEON_3D_DRAW_VBUF		0x00002800
 #	define RADEON_3D_DRAW_IMMD		0x00002900
-#	define RADEON_3D_CLEAR_ZMASK		0x00003200
+#	define RADEON_3D_DRAW_INDX		0x00002A00
+#	define RADEON_3D_LOAD_VBPNTR		0x00002F00
 #	define RADEON_CNTL_HOSTDATA_BLT		0x00009400
 #	define RADEON_CNTL_PAINT_MULTI		0x00009A00
 #	define RADEON_CNTL_BITBLT_MULTI		0x00009B00
+#	define RADEON_CNTL_SET_SCISSORS		0xC0001E00
 
 #define RADEON_CP_PACKET_MASK		0xC0000000
 #define RADEON_CP_PACKET_COUNT_MASK	0x3fff0000
@@ -470,6 +532,7 @@
 #define RADEON_CP_PACKET1_REG1_MASK	0x003ff800
 
 #define RADEON_VTX_Z_PRESENT			(1 << 31)
+#define RADEON_VTX_PKCOLOR_PRESENT		(1 << 3)
 
 #define RADEON_PRIM_TYPE_NONE			(0 << 0)
 #define RADEON_PRIM_TYPE_POINT			(1 << 0)
@@ -482,6 +545,7 @@
 #define RADEON_PRIM_TYPE_RECT_LIST		(8 << 0)
 #define RADEON_PRIM_TYPE_3VRT_POINT_LIST	(9 << 0)
 #define RADEON_PRIM_TYPE_3VRT_LINE_LIST		(10 << 0)
+#define RADEON_PRIM_TYPE_MASK                   0xf
 #define RADEON_PRIM_WALK_IND			(1 << 4)
 #define RADEON_PRIM_WALK_LIST			(2 << 4)
 #define RADEON_PRIM_WALK_RING			(3 << 4)
@@ -508,6 +572,105 @@
 #define RADEON_TXFORMAT_ARGB4444	5
 #define RADEON_TXFORMAT_ARGB8888	6
 #define RADEON_TXFORMAT_RGBA8888	7
+#define RADEON_TXFORMAT_VYUY422         10
+#define RADEON_TXFORMAT_YVYU422         11
+#define RADEON_TXFORMAT_DXT1            12
+#define RADEON_TXFORMAT_DXT23           14
+#define RADEON_TXFORMAT_DXT45           15
+
+#define R200_PP_TXCBLEND_0                0x2f00
+#define R200_PP_TXCBLEND_1                0x2f10
+#define R200_PP_TXCBLEND_2                0x2f20
+#define R200_PP_TXCBLEND_3                0x2f30
+#define R200_PP_TXCBLEND_4                0x2f40
+#define R200_PP_TXCBLEND_5                0x2f50
+#define R200_PP_TXCBLEND_6                0x2f60
+#define R200_PP_TXCBLEND_7                0x2f70
+#define R200_SE_TCL_LIGHT_MODEL_CTL_0     0x2268 
+#define R200_PP_TFACTOR_0                 0x2ee0
+#define R200_SE_VTX_FMT_0                 0x2088
+#define R200_SE_VAP_CNTL                  0x2080
+#define R200_SE_TCL_MATRIX_SEL_0          0x2230
+#define R200_SE_TCL_TEX_PROC_CTL_2        0x22a8 
+#define R200_SE_TCL_UCP_VERT_BLEND_CTL    0x22c0 
+#define R200_PP_TXFILTER_5                0x2ca0 
+#define R200_PP_TXFILTER_4                0x2c80 
+#define R200_PP_TXFILTER_3                0x2c60 
+#define R200_PP_TXFILTER_2                0x2c40 
+#define R200_PP_TXFILTER_1                0x2c20 
+#define R200_PP_TXFILTER_0                0x2c00 
+#define R200_PP_TXOFFSET_5                0x2d78
+#define R200_PP_TXOFFSET_4                0x2d60
+#define R200_PP_TXOFFSET_3                0x2d48
+#define R200_PP_TXOFFSET_2                0x2d30
+#define R200_PP_TXOFFSET_1                0x2d18
+#define R200_PP_TXOFFSET_0                0x2d00
+
+#define R200_PP_CUBIC_FACES_0             0x2c18
+#define R200_PP_CUBIC_FACES_1             0x2c38
+#define R200_PP_CUBIC_FACES_2             0x2c58
+#define R200_PP_CUBIC_FACES_3             0x2c78
+#define R200_PP_CUBIC_FACES_4             0x2c98
+#define R200_PP_CUBIC_FACES_5             0x2cb8
+#define R200_PP_CUBIC_OFFSET_F1_0         0x2d04
+#define R200_PP_CUBIC_OFFSET_F2_0         0x2d08
+#define R200_PP_CUBIC_OFFSET_F3_0         0x2d0c
+#define R200_PP_CUBIC_OFFSET_F4_0         0x2d10
+#define R200_PP_CUBIC_OFFSET_F5_0         0x2d14
+#define R200_PP_CUBIC_OFFSET_F1_1         0x2d1c
+#define R200_PP_CUBIC_OFFSET_F2_1         0x2d20
+#define R200_PP_CUBIC_OFFSET_F3_1         0x2d24
+#define R200_PP_CUBIC_OFFSET_F4_1         0x2d28
+#define R200_PP_CUBIC_OFFSET_F5_1         0x2d2c
+#define R200_PP_CUBIC_OFFSET_F1_2         0x2d34
+#define R200_PP_CUBIC_OFFSET_F2_2         0x2d38
+#define R200_PP_CUBIC_OFFSET_F3_2         0x2d3c
+#define R200_PP_CUBIC_OFFSET_F4_2         0x2d40
+#define R200_PP_CUBIC_OFFSET_F5_2         0x2d44
+#define R200_PP_CUBIC_OFFSET_F1_3         0x2d4c
+#define R200_PP_CUBIC_OFFSET_F2_3         0x2d50
+#define R200_PP_CUBIC_OFFSET_F3_3         0x2d54
+#define R200_PP_CUBIC_OFFSET_F4_3         0x2d58
+#define R200_PP_CUBIC_OFFSET_F5_3         0x2d5c
+#define R200_PP_CUBIC_OFFSET_F1_4         0x2d64
+#define R200_PP_CUBIC_OFFSET_F2_4         0x2d68
+#define R200_PP_CUBIC_OFFSET_F3_4         0x2d6c
+#define R200_PP_CUBIC_OFFSET_F4_4         0x2d70
+#define R200_PP_CUBIC_OFFSET_F5_4         0x2d74
+#define R200_PP_CUBIC_OFFSET_F1_5         0x2d7c
+#define R200_PP_CUBIC_OFFSET_F2_5         0x2d80
+#define R200_PP_CUBIC_OFFSET_F3_5         0x2d84
+#define R200_PP_CUBIC_OFFSET_F4_5         0x2d88
+#define R200_PP_CUBIC_OFFSET_F5_5         0x2d8c
+
+#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
+#define R200_SE_VTE_CNTL                  0x20b0
+#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL   0x2250
+#define R200_PP_TAM_DEBUG3                0x2d9c
+#define R200_PP_CNTL_X                    0x2cc4
+#define R200_SE_VAP_CNTL_STATUS           0x2140
+#define R200_RE_SCISSOR_TL_0              0x1cd8
+#define R200_RE_SCISSOR_TL_1              0x1ce0
+#define R200_RE_SCISSOR_TL_2              0x1ce8
+#define R200_RB3D_DEPTHXY_OFFSET          0x1d60 
+#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
+#define R200_SE_VTX_STATE_CNTL            0x2180
+#define R200_RE_POINTSIZE                 0x2648
+#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
+
+
+#define SE_VAP_CNTL__TCL_ENA_MASK                          0x00000001
+#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK                   0x00010000
+#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT                 0x00000012
+#define SE_VTE_CNTL__VTX_XY_FMT_MASK                       0x00000100
+#define SE_VTE_CNTL__VTX_Z_FMT_MASK                        0x00000200
+#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK                  0x00000001
+#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK                  0x00000002
+#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT               0x0000000b
+#define R200_3D_DRAW_IMMD_2      0xC0003500
+#define R200_SE_VTX_FMT_1                 0x208c
+#define R200_RE_CNTL                      0x1c50 
+
 
 /* Constants */
 #define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
@@ -515,6 +678,7 @@
 #define RADEON_LAST_FRAME_REG		RADEON_SCRATCH_REG0
 #define RADEON_LAST_DISPATCH_REG	RADEON_SCRATCH_REG1
 #define RADEON_LAST_CLEAR_REG		RADEON_SCRATCH_REG2
+#define RADEON_LAST_SWI_REG		RADEON_SCRATCH_REG3
 #define RADEON_LAST_DISPATCH		1
 
 #define RADEON_MAX_VB_AGE		0x7fffffff
@@ -526,41 +690,11 @@
 #define RADEON_BASE(reg)	((unsigned long)(dev_priv->mmio->handle))
 #define RADEON_ADDR(reg)	(RADEON_BASE( reg ) + reg)
 
-#define RADEON_DEREF(reg)	*(volatile u32 *)RADEON_ADDR( reg )
-#ifdef __alpha__
-#define RADEON_READ(reg)	(_RADEON_READ((u32 *)RADEON_ADDR( reg )))
-static inline u32 _RADEON_READ(u32 *addr)
-{
-	mb();
-	return *(volatile u32 *)addr;
-}
-#define RADEON_WRITE(reg,val)						\
-do {									\
-	wmb();								\
-	RADEON_DEREF(reg) = val;					\
-} while (0)
-#else
-#define RADEON_READ(reg)	RADEON_DEREF( reg )
-#define RADEON_WRITE(reg, val)	do { RADEON_DEREF( reg ) = val; } while (0)
-#endif
+#define RADEON_READ(reg)	DRM_READ32(  (volatile u32 *) RADEON_ADDR(reg) )
+#define RADEON_WRITE(reg,val)	DRM_WRITE32( (volatile u32 *) RADEON_ADDR(reg), (val) )
 
-#define RADEON_DEREF8(reg)	*(volatile u8 *)RADEON_ADDR( reg )
-#ifdef __alpha__
-#define RADEON_READ8(reg)	_RADEON_READ8((u8 *)RADEON_ADDR( reg ))
-static inline u8 _RADEON_READ8(u8 *addr)
-{
-	mb();
-	return *(volatile u8 *)addr;
-}
-#define RADEON_WRITE8(reg,val)						\
-do {									\
-	wmb();								\
-	RADEON_DEREF8( reg ) = val;					\
-} while (0)
-#else
-#define RADEON_READ8(reg)	RADEON_DEREF8( reg )
-#define RADEON_WRITE8(reg, val)	do { RADEON_DEREF8( reg ) = val; } while (0)
-#endif
+#define RADEON_READ8(reg)	DRM_READ8(  (volatile u8 *) RADEON_ADDR(reg) )
+#define RADEON_WRITE8(reg,val)	DRM_WRITE8( (volatile u8 *) RADEON_ADDR(reg), (val) )
 
 #define RADEON_WRITE_PLL( addr, val )					\
 do {									\
@@ -640,27 +774,22 @@
 #define LOCK_TEST_WITH_RETURN( dev )					\
 do {									\
 	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||		\
-	     dev->lock.pid != current->pid ) {				\
-		DRM_ERROR( "%s called without lock held\n",		\
-			   __FUNCTION__ );				\
-		return -EINVAL;						\
+	     dev->lock.pid != DRM_CURRENTPID ) {			\
+		DRM_ERROR( "%s called without lock held\n", __FUNCTION__ );	\
+		return DRM_ERR(EINVAL);				\
 	}								\
 } while (0)
 
+
+/* Perfbox functionality only.  
+ */
 #define RING_SPACE_TEST_WITH_RETURN( dev_priv )				\
 do {									\
-	drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i;	\
-	if ( ring->space < ring->high_mark ) {				\
-		for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {	\
-			radeon_update_ring_snapshot( ring );		\
-			if ( ring->space >= ring->high_mark )		\
-				goto __ring_space_done;			\
-			udelay( 1 );					\
-		}							\
-		DRM_ERROR( "ring space check failed!\n" );		\
-		return -EBUSY;						\
+	if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) {		\
+		u32 head = GET_RING_HEAD(&dev_priv->ring);		\
+		if (head == dev_priv->ring.tail)			\
+			dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE;	\
 	}								\
- __ring_space_done: ;							\
 } while (0)
 
 #define VB_AGE_TEST_WITH_RETURN( dev_priv )				\
@@ -668,7 +797,7 @@
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;		\
 	if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {		\
 		int __ret = radeon_do_cp_idle( dev_priv );		\
-		if ( __ret < 0 ) return __ret;				\
+		if ( __ret ) return __ret;				\
 		sarea_priv->last_dispatch = 0;				\
 		radeon_freelist_reset( dev );				\
 	}								\
@@ -694,12 +823,16 @@
  * Ring control
  */
 
-#define radeon_flush_write_combine()	mb()
+#if defined(__powerpc__)
+#define radeon_flush_write_combine()	(void) GET_RING_HEAD( &dev_priv->ring )
+#else
+#define radeon_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
+#endif
 
 
 #define RADEON_VERBOSE	0
 
-#define RING_LOCALS	int write; unsigned int mask; volatile u32 *ring;
+#define RING_LOCALS	int write, _nr; unsigned int mask; u32 *ring;
 
 #define BEGIN_RING( n ) do {						\
 	if ( RADEON_VERBOSE ) {						\
@@ -707,9 +840,10 @@
 			   n, __FUNCTION__ );				\
 	}								\
 	if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {		\
+                COMMIT_RING();						\
 		radeon_wait_ring( dev_priv, (n) * sizeof(u32) );	\
 	}								\
-	dev_priv->ring.space -= (n) * sizeof(u32);			\
+	_nr = n; dev_priv->ring.space -= (n) * sizeof(u32);		\
 	ring = dev_priv->ring.start;					\
 	write = dev_priv->ring.tail;					\
 	mask = dev_priv->ring.tail_mask;				\
@@ -720,9 +854,17 @@
 		DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",	\
 			  write, dev_priv->ring.tail );			\
 	}								\
-	radeon_flush_write_combine();					\
-	dev_priv->ring.tail = write;					\
-	RADEON_WRITE( RADEON_CP_RB_WPTR, write );			\
+	if (((dev_priv->ring.tail + _nr) & mask) != write) {		\
+		DRM_ERROR( 						\
+			"ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",	\
+			((dev_priv->ring.tail + _nr) & mask),		\
+			write, __LINE__);						\
+	} else								\
+		dev_priv->ring.tail = write;				\
+} while (0)
+
+#define COMMIT_RING() do {					    \
+	RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail );		    \
 } while (0)
 
 #define OUT_RING( x ) do {						\
@@ -734,6 +876,33 @@
 	write &= mask;							\
 } while (0)
 
-#define RADEON_PERFORMANCE_BOXES	0
+#define OUT_RING_REG( reg, val ) do {					\
+	OUT_RING( CP_PACKET0( reg, 0 ) );				\
+	OUT_RING( val );						\
+} while (0)
+
+
+#define OUT_RING_USER_TABLE( tab, sz ) do {			\
+	int _size = (sz);					\
+	int *_tab = (tab);					\
+								\
+	if (write + _size > mask) {				\
+		int i = (mask+1) - write;			\
+		if (DRM_COPY_FROM_USER_UNCHECKED( (int *)(ring+write),	\
+				      _tab, i*4 ))		\
+			return DRM_ERR(EFAULT);		\
+		write = 0;					\
+		_size -= i;					\
+		_tab += i;					\
+	}							\
+								\
+	if (_size && DRM_COPY_FROM_USER_UNCHECKED( (int *)(ring+write),	\
+			               _tab, _size*4 ))		\
+		return DRM_ERR(EFAULT);			\
+								\
+	write += _size;						\
+	write &= mask;						\
+} while (0)
+
 
 #endif /* __RADEON_DRV_H__ */
diff -ruN drivers/char/drm-4.2/radeon_irq.c drivers/char/drm/radeon_irq.c
--- drivers/char/drm-4.2/radeon_irq.c	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/radeon_irq.c	2003-01-14 07:00:59.000000000 +0900
@@ -0,0 +1,253 @@
+/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ * 
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Michel Dänzer <michel@daenzer.net>
+ */
+
+#include "radeon.h"
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+/* Interrupts - Used for device synchronization and flushing in the
+ * following circumstances:
+ *
+ * - Exclusive FB access with hw idle:
+ *    - Wait for GUI Idle (?) interrupt, then do normal flush.
+ *
+ * - Frame throttling, NV_fence:
+ *    - Drop marker irq's into command stream ahead of time.
+ *    - Wait on irq's with lock *not held*
+ *    - Check each for termination condition
+ *
+ * - Internally in cp_getbuffer, etc:
+ *    - as above, but wait with lock held???
+ *
+ * NOTE: These functions are misleadingly named -- the irq's aren't
+ * tied to dma at all, this is just a hangover from dri prehistory.
+ */
+
+void DRM(dma_service)( DRM_IRQ_ARGS )
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_radeon_private_t *dev_priv = 
+	   (drm_radeon_private_t *)dev->dev_private;
+   	u32 stat;
+
+	stat = RADEON_READ(RADEON_GEN_INT_STATUS);
+	if (!stat)
+		return;
+
+	/* SW interrupt */
+	if (stat & RADEON_SW_INT_TEST) {
+		DRM_WAKEUP( &dev_priv->swi_queue );
+	}
+
+	/* VBLANK interrupt */
+	if (stat & RADEON_CRTC_VBLANK_STAT) {
+		atomic_inc(&dev->vbl_received);
+		DRM_WAKEUP(&dev->vbl_queue);
+		DRM(vbl_send_signals)( dev );
+	}
+
+	/* Acknowledge all the bits in GEN_INT_STATUS -- seem to get
+	 * more than we asked for...
+	 */
+	RADEON_WRITE(RADEON_GEN_INT_STATUS, stat);
+}
+
+static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv)
+{
+	u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS );
+	if (tmp)
+		RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );
+}
+
+int radeon_emit_irq(drm_device_t *dev)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	unsigned int ret;
+	RING_LOCALS;
+
+	atomic_inc(&dev_priv->swi_emitted);
+	ret = atomic_read(&dev_priv->swi_emitted);
+
+	BEGIN_RING( 4 );
+	OUT_RING_REG( RADEON_LAST_SWI_REG, ret );
+	OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE );
+	ADVANCE_RING(); 
+ 	COMMIT_RING();
+
+	return ret;
+}
+
+
+int radeon_wait_irq(drm_device_t *dev, int swi_nr)
+{
+  	drm_radeon_private_t *dev_priv = 
+	   (drm_radeon_private_t *)dev->dev_private;
+	int ret = 0;
+
+ 	if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr)  
+ 		return 0; 
+
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+	/* This is a hack to work around mysterious freezes on certain
+	 * systems:
+	 */ 
+	radeon_acknowledge_irqs( dev_priv );
+
+	DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ, 
+		     RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
+
+	return ret;
+}
+
+int radeon_emit_and_wait_irq(drm_device_t *dev)
+{
+	return radeon_wait_irq( dev, radeon_emit_irq(dev) );
+}
+
+
+int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+{
+  	drm_radeon_private_t *dev_priv = 
+	   (drm_radeon_private_t *)dev->dev_private;
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	radeon_acknowledge_irqs( dev_priv );
+
+	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+	/* Assume that the user has missed the current sequence number
+	 * by about a day rather than she wants to wait for years
+	 * using vertical blanks... 
+	 */
+	DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, 
+		     ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) )
+			 - *sequence ) <= (1<<23) ) );
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
+
+/* Needs the lock as it touches the ring.
+ */
+int radeon_irq_emit( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_irq_emit_t emit;
+	int result;
+
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( emit, (drm_radeon_irq_emit_t *)data,
+				  sizeof(emit) );
+
+	result = radeon_emit_irq( dev );
+
+	if ( DRM_COPY_TO_USER( emit.irq_seq, &result, sizeof(int) ) ) {
+		DRM_ERROR( "copy_to_user\n" );
+		return DRM_ERR(EFAULT);
+	}
+
+	return 0;
+}
+
+
+/* Doesn't need the hardware lock.
+ */
+int radeon_irq_wait( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_irq_wait_t irqwait;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( irqwait, (drm_radeon_irq_wait_t *)data,
+				  sizeof(irqwait) );
+
+	return radeon_wait_irq( dev, irqwait.irq_seq );
+}
+
+
+/* drm_dma.h hooks
+*/
+void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
+	drm_radeon_private_t *dev_priv =
+		(drm_radeon_private_t *)dev->dev_private;
+
+ 	/* Disable *all* interrupts */
+      	RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
+
+	/* Clear bits if they're already high */
+	radeon_acknowledge_irqs( dev_priv );
+}
+
+void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
+	drm_radeon_private_t *dev_priv =
+		(drm_radeon_private_t *)dev->dev_private;
+
+   	atomic_set(&dev_priv->swi_emitted, 0);
+	DRM_INIT_WAITQUEUE( &dev_priv->swi_queue );
+
+	/* Turn on SW and VBL ints */
+   	RADEON_WRITE( RADEON_GEN_INT_CNTL,
+		      RADEON_CRTC_VBLANK_MASK |	
+		      RADEON_SW_INT_ENABLE );
+}
+
+void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+	drm_radeon_private_t *dev_priv =
+		(drm_radeon_private_t *)dev->dev_private;
+	if ( dev_priv ) {
+		/* Disable *all* interrupts */
+		RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
+	}
+}
diff -ruN drivers/char/drm-4.2/radeon_mem.c drivers/char/drm/radeon_mem.c
--- drivers/char/drm-4.2/radeon_mem.c	1970-01-01 09:00:00.000000000 +0900
+++ drivers/char/drm/radeon_mem.c	2003-01-14 07:00:59.000000000 +0900
@@ -0,0 +1,334 @@
+/* radeon_mem.c -- Simple agp/fb memory manager for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ * 
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "radeon.h"
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+/* Very simple allocator for agp memory, working on a static range
+ * already mapped into each client's address space.  
+ */
+
+static struct mem_block *split_block(struct mem_block *p, int start, int size,
+				     int pid )
+{
+	/* Maybe cut off the start of an existing block */
+	if (start > p->start) {
+		struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock));
+		if (!newblock) 
+			goto out;
+		newblock->start = start;
+		newblock->size = p->size - (start - p->start);
+		newblock->pid = 0;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size -= newblock->size;
+		p = newblock;
+	}
+   
+	/* Maybe cut off the end of an existing block */
+	if (size < p->size) {
+		struct mem_block *newblock = DRM_MALLOC(sizeof(*newblock));
+		if (!newblock)
+			goto out;
+		newblock->start = start + size;
+		newblock->size = p->size - size;
+		newblock->pid = 0;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size = size;
+	}
+
+ out:
+	/* Our block is in the middle */
+	p->pid = pid;
+	return p;
+}
+
+static struct mem_block *alloc_block( struct mem_block *heap, int size, 
+				      int align2, int pid )
+{
+	struct mem_block *p;
+	int mask = (1 << align2)-1;
+
+	for (p = heap->next ; p != heap ; p = p->next) {
+		int start = (p->start + mask) & ~mask;
+		if (p->pid == 0 && start + size <= p->start + p->size)
+			return split_block( p, start, size, pid );
+	}
+
+	return NULL;
+}
+
+static struct mem_block *find_block( struct mem_block *heap, int start )
+{
+	struct mem_block *p;
+
+	for (p = heap->next ; p != heap ; p = p->next) 
+		if (p->start == start)
+			return p;
+
+	return NULL;
+}
+
+
+static void free_block( struct mem_block *p )
+{
+	p->pid = 0;
+
+	/* Assumes a single contiguous range.  Needs a special pid in
+	 * 'heap' to stop it being subsumed.
+	 */
+	if (p->next->pid == 0) {
+		struct mem_block *q = p->next;
+		p->size += q->size;
+		p->next = q->next;
+		p->next->prev = p;
+		DRM_FREE(q);
+	}
+
+	if (p->prev->pid == 0) {
+		struct mem_block *q = p->prev;
+		q->size += p->size;
+		q->next = p->next;
+		q->next->prev = q;
+		DRM_FREE(p);
+	}
+}
+
+static void print_heap( struct mem_block *heap )
+{
+	struct mem_block *p;
+
+	for (p = heap->next ; p != heap ; p = p->next) 
+		DRM_DEBUG("0x%x..0x%x (0x%x) -- owner %d\n",
+			  p->start, p->start + p->size,
+			  p->size, p->pid);
+}
+
+/* Initialize.  How to check for an uninitialized heap?
+ */
+static int init_heap(struct mem_block **heap, int start, int size)
+{
+	struct mem_block *blocks = DRM_MALLOC(sizeof(*blocks));
+
+	if (!blocks) 
+		return -ENOMEM;
+	
+	*heap = DRM_MALLOC(sizeof(**heap));
+	if (!*heap) {
+		DRM_FREE( blocks );
+		return -ENOMEM;
+	}
+
+	blocks->start = start;
+	blocks->size = size;
+	blocks->pid = 0;
+	blocks->next = blocks->prev = *heap;
+
+	memset( *heap, 0, sizeof(**heap) );
+	(*heap)->pid = -1;
+	(*heap)->next = (*heap)->prev = blocks;
+	return 0;
+}
+
+
+/* Free all blocks associated with the releasing pid.
+ */
+void radeon_mem_release( struct mem_block *heap )
+{
+	int pid = DRM_CURRENTPID;
+	struct mem_block *p;
+
+	if (!heap || !heap->next)
+		return;
+
+	for (p = heap->next ; p != heap ; p = p->next) {
+		if (p->pid == pid) 
+			p->pid = 0;
+	}
+
+	/* Assumes a single contiguous range.  Needs a special pid in
+	 * 'heap' to stop it being subsumed.
+	 */
+	for (p = heap->next ; p != heap ; p = p->next) {
+		while (p->pid == 0 && p->next->pid == 0) {
+			struct mem_block *q = p->next;
+			p->size += q->size;
+			p->next = q->next;
+			p->next->prev = p;
+			DRM_FREE(q);
+		}
+	}
+}
+
+/* Shutdown.
+ */
+void radeon_mem_takedown( struct mem_block **heap )
+{
+	struct mem_block *p;
+	
+	if (!*heap)
+		return;
+
+	for (p = (*heap)->next ; p != *heap ; ) {
+		struct mem_block *q = p;
+		p = p->next;
+		DRM_FREE(q);
+	}
+
+	DRM_FREE( *heap );
+	*heap = 0;
+}
+
+
+
+/* IOCTL HANDLERS */
+
+static struct mem_block **get_heap( drm_radeon_private_t *dev_priv,
+				   int region )
+{
+	switch( region ) {
+	case RADEON_MEM_REGION_AGP:
+ 		return &dev_priv->agp_heap; 
+	case RADEON_MEM_REGION_FB:
+		return &dev_priv->fb_heap;
+	default:
+		return 0;
+	}
+}
+
+int radeon_mem_alloc( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_mem_alloc_t alloc;
+	struct mem_block *block, **heap;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( alloc, (drm_radeon_mem_alloc_t *)data,
+				  sizeof(alloc) );
+
+	heap = get_heap( dev_priv, alloc.region );
+	if (!heap || !*heap)
+		return DRM_ERR(EFAULT);
+	
+	/* Make things easier on ourselves: all allocations at least
+	 * 4k aligned.
+	 */
+	if (alloc.alignment < 12)
+		alloc.alignment = 12;
+
+	block = alloc_block( *heap, alloc.size, alloc.alignment,
+			     DRM_CURRENTPID );
+
+	if (!block) 
+		return DRM_ERR(ENOMEM);
+
+	if ( DRM_COPY_TO_USER( alloc.region_offset, &block->start, 
+			       sizeof(int) ) ) {
+		DRM_ERROR( "copy_to_user\n" );
+		return DRM_ERR(EFAULT);
+	}
+	
+	return 0;
+}
+
+
+
+int radeon_mem_free( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_mem_free_t memfree;
+	struct mem_block *block, **heap;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( memfree, (drm_radeon_mem_free_t *)data,
+				  sizeof(memfree) );
+
+	heap = get_heap( dev_priv, memfree.region );
+	if (!heap || !*heap)
+		return DRM_ERR(EFAULT);
+	
+	block = find_block( *heap, memfree.region_offset );
+	if (!block)
+		return DRM_ERR(EFAULT);
+
+	if (block->pid != DRM_CURRENTPID)
+		return DRM_ERR(EPERM);
+
+	free_block( block );	
+	return 0;
+}
+
+int radeon_mem_init_heap( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_mem_init_heap_t initheap;
+	struct mem_block **heap;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( initheap, (drm_radeon_mem_init_heap_t *)data,
+				  sizeof(initheap) );
+
+	heap = get_heap( dev_priv, initheap.region );
+	if (!heap) 
+		return DRM_ERR(EFAULT);
+	
+	if (*heap) {
+		DRM_ERROR("heap already initialized?");
+		return DRM_ERR(EFAULT);
+	}
+		
+	return init_heap( heap, initheap.start, initheap.size );
+}
+
+
diff -ruN drivers/char/drm-4.2/radeon_state.c drivers/char/drm/radeon_state.c
--- drivers/char/drm-4.2/radeon_state.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/radeon_state.c	2003-01-14 07:00:59.000000000 +0900
@@ -29,16 +29,17 @@
 
 #include "radeon.h"
 #include "drmP.h"
-#include "radeon_drv.h"
 #include "drm.h"
-#include <linux/delay.h>
+#include "drm_sarea.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
 
 
 /* ================================================================
  * CP hardware state programming functions
  */
 
-static inline void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
+static __inline__ void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
 					  drm_clip_rect_t *box )
 {
 	RING_LOCALS;
@@ -47,360 +48,254 @@
 		   box->x1, box->y1, box->x2, box->y2 );
 
 	BEGIN_RING( 4 );
-
 	OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
 	OUT_RING( (box->y1 << 16) | box->x1 );
-
 	OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
 	OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_context( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 14 );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
-	OUT_RING( ctx->pp_misc );
-	OUT_RING( ctx->pp_fog_color );
-	OUT_RING( ctx->re_solid_color );
-	OUT_RING( ctx->rb3d_blendcntl );
-	OUT_RING( ctx->rb3d_depthoffset );
-	OUT_RING( ctx->rb3d_depthpitch );
-	OUT_RING( ctx->rb3d_zstencilcntl );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
-	OUT_RING( ctx->pp_cntl );
-	OUT_RING( ctx->rb3d_cntl );
-	OUT_RING( ctx->rb3d_coloroffset );
-
-	OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
-	OUT_RING( ctx->rb3d_colorpitch );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_vertfmt( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 2 );
-
-	OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
-	OUT_RING( ctx->se_coord_fmt );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_line( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 5 );
-
-	OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
-	OUT_RING( ctx->re_line_pattern );
-	OUT_RING( ctx->re_line_state );
-
-	OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
-	OUT_RING( ctx->se_line_width );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_bumpmap( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 5 );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
-	OUT_RING( ctx->pp_lum_matrix );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
-	OUT_RING( ctx->pp_rot_matrix_0 );
-	OUT_RING( ctx->pp_rot_matrix_1 );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_masks( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 4 );
-
-	OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
-	OUT_RING( ctx->rb3d_stencilrefmask );
-	OUT_RING( ctx->rb3d_ropcntl );
-	OUT_RING( ctx->rb3d_planemask );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_viewport( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 7 );
-
-	OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
-	OUT_RING( ctx->se_vport_xscale );
-	OUT_RING( ctx->se_vport_xoffset );
-	OUT_RING( ctx->se_vport_yscale );
-	OUT_RING( ctx->se_vport_yoffset );
-	OUT_RING( ctx->se_vport_zscale );
-	OUT_RING( ctx->se_vport_zoffset );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_setup( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 4 );
-
-	OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
-	OUT_RING( ctx->se_cntl );
-	OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
-	OUT_RING( ctx->se_cntl_status );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_tcl( drm_radeon_private_t *dev_priv )
-{
-#ifdef TCL_ENABLE
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 29 );
-
-	OUT_RING( CP_PACKET0( RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 27 ) );
-	OUT_RING( ctx->se_tcl_material_emmissive.red );
-	OUT_RING( ctx->se_tcl_material_emmissive.green );
-	OUT_RING( ctx->se_tcl_material_emmissive.blue );
-	OUT_RING( ctx->se_tcl_material_emmissive.alpha );
-	OUT_RING( ctx->se_tcl_material_ambient.red );
-	OUT_RING( ctx->se_tcl_material_ambient.green );
-	OUT_RING( ctx->se_tcl_material_ambient.blue );
-	OUT_RING( ctx->se_tcl_material_ambient.alpha );
-	OUT_RING( ctx->se_tcl_material_diffuse.red );
-	OUT_RING( ctx->se_tcl_material_diffuse.green );
-	OUT_RING( ctx->se_tcl_material_diffuse.blue );
-	OUT_RING( ctx->se_tcl_material_diffuse.alpha );
-	OUT_RING( ctx->se_tcl_material_specular.red );
-	OUT_RING( ctx->se_tcl_material_specular.green );
-	OUT_RING( ctx->se_tcl_material_specular.blue );
-	OUT_RING( ctx->se_tcl_material_specular.alpha );
-	OUT_RING( ctx->se_tcl_shininess );
-	OUT_RING( ctx->se_tcl_output_vtx_fmt );
-	OUT_RING( ctx->se_tcl_output_vtx_sel );
-	OUT_RING( ctx->se_tcl_matrix_select_0 );
-	OUT_RING( ctx->se_tcl_matrix_select_1 );
-	OUT_RING( ctx->se_tcl_ucp_vert_blend_ctl );
-	OUT_RING( ctx->se_tcl_texture_proc_ctl );
-	OUT_RING( ctx->se_tcl_light_model_ctl );
-	for ( i = 0 ; i < 4 ; i++ ) {
-		OUT_RING( ctx->se_tcl_per_light_ctl[i] );
-	}
-
-	ADVANCE_RING();
-#else
-	DRM_ERROR( "TCL not enabled!\n" );
-#endif
-}
-
-static inline void radeon_emit_misc( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
-	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 2 );
-
-	OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
-	OUT_RING( ctx->re_misc );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_tex0( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[0];
-	RING_LOCALS;
-	DRM_DEBUG( "    %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
-
-	BEGIN_RING( 9 );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
-	OUT_RING( tex->pp_txfilter );
-	OUT_RING( tex->pp_txformat );
-	OUT_RING( tex->pp_txoffset );
-	OUT_RING( tex->pp_txcblend );
-	OUT_RING( tex->pp_txablend );
-	OUT_RING( tex->pp_tfactor );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
-	OUT_RING( tex->pp_border_color );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_tex1( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[1];
-	RING_LOCALS;
-	DRM_DEBUG( "    %s: offset=0x%x\n", __FUNCTION__, tex->pp_txoffset );
-
-	BEGIN_RING( 9 );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
-	OUT_RING( tex->pp_txfilter );
-	OUT_RING( tex->pp_txformat );
-	OUT_RING( tex->pp_txoffset );
-	OUT_RING( tex->pp_txcblend );
-	OUT_RING( tex->pp_txablend );
-	OUT_RING( tex->pp_tfactor );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
-	OUT_RING( tex->pp_border_color );
-
 	ADVANCE_RING();
 }
 
-static inline void radeon_emit_tex2( drm_radeon_private_t *dev_priv )
+/* Emit 1.1 state
+ */
+static void radeon_emit_state( drm_radeon_private_t *dev_priv,
+			       drm_radeon_context_regs_t *ctx,
+			       drm_radeon_texture_regs_t *tex,
+			       unsigned int dirty )
 {
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[2];
 	RING_LOCALS;
-	DRM_DEBUG( "    %s\n", __FUNCTION__ );
-
-	BEGIN_RING( 9 );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
-	OUT_RING( tex->pp_txfilter );
-	OUT_RING( tex->pp_txformat );
-	OUT_RING( tex->pp_txoffset );
-	OUT_RING( tex->pp_txcblend );
-	OUT_RING( tex->pp_txablend );
-	OUT_RING( tex->pp_tfactor );
-
-	OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
-	OUT_RING( tex->pp_border_color );
-
-	ADVANCE_RING();
-}
-
-static inline void radeon_emit_state( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	unsigned int dirty = sarea_priv->dirty;
-
-	DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
+	DRM_DEBUG( "dirty=0x%08x\n", dirty );
 
 	if ( dirty & RADEON_UPLOAD_CONTEXT ) {
-		radeon_emit_context( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_CONTEXT;
+		BEGIN_RING( 14 );
+		OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
+		OUT_RING( ctx->pp_misc );
+		OUT_RING( ctx->pp_fog_color );
+		OUT_RING( ctx->re_solid_color );
+		OUT_RING( ctx->rb3d_blendcntl );
+		OUT_RING( ctx->rb3d_depthoffset );
+		OUT_RING( ctx->rb3d_depthpitch );
+		OUT_RING( ctx->rb3d_zstencilcntl );
+		OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
+		OUT_RING( ctx->pp_cntl );
+		OUT_RING( ctx->rb3d_cntl );
+		OUT_RING( ctx->rb3d_coloroffset );
+		OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
+		OUT_RING( ctx->rb3d_colorpitch );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_VERTFMT ) {
-		radeon_emit_vertfmt( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_VERTFMT;
+		BEGIN_RING( 2 );
+		OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
+		OUT_RING( ctx->se_coord_fmt );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_LINE ) {
-		radeon_emit_line( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_LINE;
+		BEGIN_RING( 5 );
+		OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
+		OUT_RING( ctx->re_line_pattern );
+		OUT_RING( ctx->re_line_state );
+		OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
+		OUT_RING( ctx->se_line_width );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
-		radeon_emit_bumpmap( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_BUMPMAP;
+		BEGIN_RING( 5 );
+		OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
+		OUT_RING( ctx->pp_lum_matrix );
+		OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
+		OUT_RING( ctx->pp_rot_matrix_0 );
+		OUT_RING( ctx->pp_rot_matrix_1 );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_MASKS ) {
-		radeon_emit_masks( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_MASKS;
+		BEGIN_RING( 4 );
+		OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
+		OUT_RING( ctx->rb3d_stencilrefmask );
+		OUT_RING( ctx->rb3d_ropcntl );
+		OUT_RING( ctx->rb3d_planemask );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
-		radeon_emit_viewport( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_VIEWPORT;
+		BEGIN_RING( 7 );
+		OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
+		OUT_RING( ctx->se_vport_xscale );
+		OUT_RING( ctx->se_vport_xoffset );
+		OUT_RING( ctx->se_vport_yscale );
+		OUT_RING( ctx->se_vport_yoffset );
+		OUT_RING( ctx->se_vport_zscale );
+		OUT_RING( ctx->se_vport_zoffset );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_SETUP ) {
-		radeon_emit_setup( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_SETUP;
-	}
-
-	if ( dirty & RADEON_UPLOAD_TCL ) {
-#ifdef TCL_ENABLE
-		radeon_emit_tcl( dev_priv );
-#endif
-		sarea_priv->dirty &= ~RADEON_UPLOAD_TCL;
+		BEGIN_RING( 4 );
+		OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
+		OUT_RING( ctx->se_cntl );
+		OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
+		OUT_RING( ctx->se_cntl_status );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_MISC ) {
-		radeon_emit_misc( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_MISC;
+		BEGIN_RING( 2 );
+		OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
+		OUT_RING( ctx->re_misc );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_TEX0 ) {
-		radeon_emit_tex0( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_TEX0;
+		BEGIN_RING( 9 );
+		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
+		OUT_RING( tex[0].pp_txfilter );
+		OUT_RING( tex[0].pp_txformat );
+		OUT_RING( tex[0].pp_txoffset );
+		OUT_RING( tex[0].pp_txcblend );
+		OUT_RING( tex[0].pp_txablend );
+		OUT_RING( tex[0].pp_tfactor );
+		OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
+		OUT_RING( tex[0].pp_border_color );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_TEX1 ) {
-		radeon_emit_tex1( dev_priv );
-		sarea_priv->dirty &= ~RADEON_UPLOAD_TEX1;
+		BEGIN_RING( 9 );
+		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
+		OUT_RING( tex[1].pp_txfilter );
+		OUT_RING( tex[1].pp_txformat );
+		OUT_RING( tex[1].pp_txoffset );
+		OUT_RING( tex[1].pp_txcblend );
+		OUT_RING( tex[1].pp_txablend );
+		OUT_RING( tex[1].pp_tfactor );
+		OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
+		OUT_RING( tex[1].pp_border_color );
+		ADVANCE_RING();
 	}
 
 	if ( dirty & RADEON_UPLOAD_TEX2 ) {
-#if 0
-		radeon_emit_tex2( dev_priv );
-#endif
-		sarea_priv->dirty &= ~RADEON_UPLOAD_TEX2;
+		BEGIN_RING( 9 );
+		OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
+		OUT_RING( tex[2].pp_txfilter );
+		OUT_RING( tex[2].pp_txformat );
+		OUT_RING( tex[2].pp_txoffset );
+		OUT_RING( tex[2].pp_txcblend );
+		OUT_RING( tex[2].pp_txablend );
+		OUT_RING( tex[2].pp_tfactor );
+		OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
+		OUT_RING( tex[2].pp_border_color );
+		ADVANCE_RING();
 	}
+}
+
+/* Emit 1.2 state
+ */
+static void radeon_emit_state2( drm_radeon_private_t *dev_priv,
+				drm_radeon_state_t *state )
+{
+	RING_LOCALS;
 
-	sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
-			       RADEON_UPLOAD_TEX1IMAGES |
-			       RADEON_UPLOAD_TEX2IMAGES |
-			       RADEON_REQUIRE_QUIESCENCE);
+	if (state->dirty & RADEON_UPLOAD_ZBIAS) {
+		BEGIN_RING( 3 );
+		OUT_RING( CP_PACKET0( RADEON_SE_ZBIAS_FACTOR, 1 ) );
+		OUT_RING( state->context2.se_zbias_factor ); 
+		OUT_RING( state->context2.se_zbias_constant ); 
+		ADVANCE_RING();
+	}
+
+	radeon_emit_state( dev_priv, &state->context, 
+			   state->tex, state->dirty );
 }
 
+/* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
+ * 1.3 cmdbuffers allow all previous state to be updated as well as
+ * the tcl scalar and vector areas.  
+ */
+static struct { 
+	int start; 
+	int len; 
+	const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+	{ RADEON_PP_MISC,7,"RADEON_PP_MISC" },
+	{ RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
+	{ RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
+	{ RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
+	{ RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
+	{ RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
+	{ RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
+	{ RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
+	{ RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
+	{ RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
+	{ RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
+	{ RADEON_RE_MISC,1,"RADEON_RE_MISC" },
+	{ RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
+	{ RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
+	{ RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
+	{ RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
+	{ RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
+	{ RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
+	{ RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
+	{ RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
+	{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
+	{ R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0" },
+	{ R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1" },
+	{ R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2" },
+	{ R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3" },
+	{ R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4" },
+	{ R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5" },
+	{ R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6" },
+	{ R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7" },
+	{ R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" },
+	{ R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0" },
+	{ R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0" },
+	{ R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL" },
+	{ R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0" },
+	{ R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2" },
+	{ R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" },
+	{ R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0" },
+	{ R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1" },
+	{ R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2" },
+	{ R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3" },
+	{ R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4" },
+	{ R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5" },
+	{ R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0" },
+	{ R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1" },
+	{ R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2" },
+	{ R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3" },
+	{ R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4" },
+	{ R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5" },
+	{ R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL" },
+	{ R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" },
+	{ R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3" },
+	{ R200_PP_CNTL_X, 1, "R200_PP_CNTL_X" }, 
+	{ R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET" }, 
+	{ R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL" }, 
+	{ R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0" }, 
+	{ R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1" }, 
+	{ R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2" }, 
+	{ R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS" }, 
+	{ R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" }, 
+	{ R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" }, 
+	{ R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
+	{ R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
+	{ R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
+	{ R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" },
+	{ R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
+	{ R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" },
+	{ R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
+	{ R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" },
+	{ R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
+	{ R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" },
+	{ R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
+	{ R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
+	{ R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
+};
+
+
 
-#if RADEON_PERFORMANCE_BOXES
 /* ================================================================
  * Performance monitoring functions
  */
@@ -409,10 +304,12 @@
 			      int x, int y, int w, int h,
 			      int r, int g, int b )
 {
-	u32 pitch, offset;
 	u32 color;
 	RING_LOCALS;
 
+	x += dev_priv->sarea_priv->boxes[0].x1;
+	y += dev_priv->sarea_priv->boxes[0].y1;
+
 	switch ( dev_priv->color_fmt ) {
 	case RADEON_COLOR_FORMAT_RGB565:
 		color = (((r & 0xf8) << 8) |
@@ -425,8 +322,11 @@
 		break;
 	}
 
-	offset = dev_priv->back_offset;
-	pitch = dev_priv->back_pitch >> 3;
+	BEGIN_RING( 4 );
+	RADEON_WAIT_UNTIL_3D_IDLE();		
+	OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
+	OUT_RING( 0xffffffff );
+	ADVANCE_RING();
 
 	BEGIN_RING( 6 );
 
@@ -438,7 +338,12 @@
 		  RADEON_ROP3_P |
 		  RADEON_GMC_CLR_CMP_CNTL_DIS );
 
-	OUT_RING( (pitch << 22) | (offset >> 5) );
+ 	if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) { 
+		OUT_RING( dev_priv->front_pitch_offset );
+ 	} else {	 
+		OUT_RING( dev_priv->back_pitch_offset );
+ 	} 
+
 	OUT_RING( color );
 
 	OUT_RING( (x << 16) | y );
@@ -449,53 +354,77 @@
 
 static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
 {
-	if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
-		radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
-	} else {
-		atomic_set( &dev_priv->idle_count, 0 );
+	/* Collapse various things into a wait flag -- trying to
+	 * guess if userspase slept -- better just to have them tell us.
+	 */
+	if (dev_priv->stats.last_frame_reads > 1 ||
+	    dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
+		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 	}
-}
 
-#endif
+	if (dev_priv->stats.freelist_loops) {
+		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+	}
+
+	/* Purple box for page flipping
+	 */
+	if ( dev_priv->stats.boxes & RADEON_BOX_FLIP ) 
+		radeon_clear_box( dev_priv, 4, 4, 8, 8, 255, 0, 255 );
+
+	/* Red box if we have to wait for idle at any point
+	 */
+	if ( dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE ) 
+		radeon_clear_box( dev_priv, 16, 4, 8, 8, 255, 0, 0 );
+
+	/* Blue box: lost context?
+	 */
+
+	/* Yellow box for texture swaps
+	 */
+	if ( dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD ) 
+		radeon_clear_box( dev_priv, 40, 4, 8, 8, 255, 255, 0 );
+
+	/* Green box if hardware never idles (as far as we can tell)
+	 */
+	if ( !(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE) ) 
+		radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
+
+
+	/* Draw bars indicating number of buffers allocated 
+	 * (not a great measure, easily confused)
+	 */
+	if (dev_priv->stats.requested_bufs) {
+		if (dev_priv->stats.requested_bufs > 100)
+			dev_priv->stats.requested_bufs = 100;
+
+		radeon_clear_box( dev_priv, 4, 16,  
+				  dev_priv->stats.requested_bufs, 4,
+				  196, 128, 128 );
+	}
 
+	memset( &dev_priv->stats, 0, sizeof(dev_priv->stats) );
 
+}
 /* ================================================================
  * CP command dispatch functions
  */
 
-static void radeon_print_dirty( const char *msg, unsigned int flags )
-{
-	DRM_DEBUG( "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
-		   msg,
-		   flags,
-		   (flags & RADEON_UPLOAD_CONTEXT)     ? "context, " : "",
-		   (flags & RADEON_UPLOAD_VERTFMT)     ? "vertfmt, " : "",
-		   (flags & RADEON_UPLOAD_LINE)        ? "line, " : "",
-		   (flags & RADEON_UPLOAD_BUMPMAP)     ? "bumpmap, " : "",
-		   (flags & RADEON_UPLOAD_MASKS)       ? "masks, " : "",
-		   (flags & RADEON_UPLOAD_VIEWPORT)    ? "viewport, " : "",
-		   (flags & RADEON_UPLOAD_SETUP)       ? "setup, " : "",
-		   (flags & RADEON_UPLOAD_TCL)         ? "tcl, " : "",
-		   (flags & RADEON_UPLOAD_MISC)        ? "misc, " : "",
-		   (flags & RADEON_UPLOAD_TEX0)        ? "tex0, " : "",
-		   (flags & RADEON_UPLOAD_TEX1)        ? "tex1, " : "",
-		   (flags & RADEON_UPLOAD_TEX2)        ? "tex2, " : "",
-		   (flags & RADEON_UPLOAD_CLIPRECTS)   ? "cliprects, " : "",
-		   (flags & RADEON_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
-}
-
 static void radeon_cp_dispatch_clear( drm_device_t *dev,
 				      drm_radeon_clear_t *clear,
 				      drm_radeon_clear_rect_t *depth_boxes )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
 	int nbox = sarea_priv->nbox;
 	drm_clip_rect_t *pbox = sarea_priv->boxes;
 	unsigned int flags = clear->flags;
+	u32 rb3d_cntl = 0, rb3d_stencilrefmask= 0;
 	int i;
 	RING_LOCALS;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "flags = 0x%x\n", flags );
+
+	dev_priv->stats.clears++;
 
 	if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
 		unsigned int tmp = flags;
@@ -505,127 +434,277 @@
 		if ( tmp & RADEON_BACK )  flags |= RADEON_FRONT;
 	}
 
-	for ( i = 0 ; i < nbox ; i++ ) {
-		int x = pbox[i].x1;
-		int y = pbox[i].y1;
-		int w = pbox[i].x2 - x;
-		int h = pbox[i].y2 - y;
+	if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
 
-		DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
-			   x, y, w, h, flags );
+		BEGIN_RING( 4 );
 
-		if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
-			BEGIN_RING( 4 );
+		/* Ensure the 3D stream is idle before doing a
+		 * 2D fill to clear the front or back buffer.
+		 */
+		RADEON_WAIT_UNTIL_3D_IDLE();
+		
+		OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
+		OUT_RING( clear->color_mask );
 
-			/* Ensure the 3D stream is idle before doing a
-			 * 2D fill to clear the front or back buffer.
-			 */
-			RADEON_WAIT_UNTIL_3D_IDLE();
+		ADVANCE_RING();
 
-			OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
-			OUT_RING( clear->color_mask );
+		/* Make sure we restore the 3D state next time.
+		 */
+		dev_priv->sarea_priv->ctx_owner = 0;
 
-			ADVANCE_RING();
+		for ( i = 0 ; i < nbox ; i++ ) {
+			int x = pbox[i].x1;
+			int y = pbox[i].y1;
+			int w = pbox[i].x2 - x;
+			int h = pbox[i].y2 - y;
+
+			DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
+				   x, y, w, h, flags );
+
+			if ( flags & RADEON_FRONT ) {
+				BEGIN_RING( 6 );
+				
+				OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+				OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+					  RADEON_GMC_BRUSH_SOLID_COLOR |
+					  (dev_priv->color_fmt << 8) |
+					  RADEON_GMC_SRC_DATATYPE_COLOR |
+					  RADEON_ROP3_P |
+					  RADEON_GMC_CLR_CMP_CNTL_DIS );
+
+				OUT_RING( dev_priv->front_pitch_offset );
+				OUT_RING( clear->clear_color );
+				
+				OUT_RING( (x << 16) | y );
+				OUT_RING( (w << 16) | h );
+				
+				ADVANCE_RING();
+			}
+			
+			if ( flags & RADEON_BACK ) {
+				BEGIN_RING( 6 );
+				
+				OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
+				OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+					  RADEON_GMC_BRUSH_SOLID_COLOR |
+					  (dev_priv->color_fmt << 8) |
+					  RADEON_GMC_SRC_DATATYPE_COLOR |
+					  RADEON_ROP3_P |
+					  RADEON_GMC_CLR_CMP_CNTL_DIS );
+				
+				OUT_RING( dev_priv->back_pitch_offset );
+				OUT_RING( clear->clear_color );
 
-			/* Make sure we restore the 3D state next time.
-			 */
-			dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
-							RADEON_UPLOAD_MASKS);
+				OUT_RING( (x << 16) | y );
+				OUT_RING( (w << 16) | h );
+
+				ADVANCE_RING();
+			}
 		}
+	}
 
-		if ( flags & RADEON_FRONT ) {
-			BEGIN_RING( 6 );
+	/* We have to clear the depth and/or stencil buffers by
+	 * rendering a quad into just those buffers.  Thus, we have to
+	 * make sure the 3D engine is configured correctly.
+	 */
+	if ( dev_priv->is_r200 &&
+	     (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) {
 
-			OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
-			OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-				  RADEON_GMC_BRUSH_SOLID_COLOR |
-				  (dev_priv->color_fmt << 8) |
-				  RADEON_GMC_SRC_DATATYPE_COLOR |
-				  RADEON_ROP3_P |
-				  RADEON_GMC_CLR_CMP_CNTL_DIS );
+		int tempPP_CNTL;
+		int tempRE_CNTL;
+		int tempRB3D_CNTL;
+		int tempRB3D_ZSTENCILCNTL;
+		int tempRB3D_STENCILREFMASK;
+		int tempRB3D_PLANEMASK;
+		int tempSE_CNTL;
+		int tempSE_VTE_CNTL;
+		int tempSE_VTX_FMT_0;
+		int tempSE_VTX_FMT_1;
+		int tempSE_VAP_CNTL;
+		int tempRE_AUX_SCISSOR_CNTL;
 
-			OUT_RING( dev_priv->front_pitch_offset );
-			OUT_RING( clear->clear_color );
+		tempPP_CNTL = 0;
+		tempRE_CNTL = 0;
 
-			OUT_RING( (x << 16) | y );
-			OUT_RING( (w << 16) | h );
+		tempRB3D_CNTL = depth_clear->rb3d_cntl;
+		tempRB3D_CNTL &= ~(1<<15); /* unset radeon magic flag */
 
-			ADVANCE_RING();
+		tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
+		tempRB3D_STENCILREFMASK = 0x0;
+
+		tempSE_CNTL = depth_clear->se_cntl;
+
+
+
+		/* Disable TCL */
+
+		tempSE_VAP_CNTL = (/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK |  */
+				   (0x9 << SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
+
+		tempRB3D_PLANEMASK = 0x0;
+
+		tempRE_AUX_SCISSOR_CNTL = 0x0;
+
+		tempSE_VTE_CNTL =
+			SE_VTE_CNTL__VTX_XY_FMT_MASK |
+			SE_VTE_CNTL__VTX_Z_FMT_MASK;
+
+		/* Vertex format (X, Y, Z, W)*/
+		tempSE_VTX_FMT_0 =
+			SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
+			SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
+		tempSE_VTX_FMT_1 = 0x0;
+
+
+		/* 
+		 * Depth buffer specific enables 
+		 */
+		if (flags & RADEON_DEPTH) {
+			/* Enable depth buffer */
+			tempRB3D_CNTL |= RADEON_Z_ENABLE;
+		} else {
+			/* Disable depth buffer */
+			tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
 		}
 
-		if ( flags & RADEON_BACK ) {
-			BEGIN_RING( 6 );
+		/* 
+		 * Stencil buffer specific enables
+		 */
+		if ( flags & RADEON_STENCIL ) {
+			tempRB3D_CNTL |=  RADEON_STENCIL_ENABLE;
+			tempRB3D_STENCILREFMASK = clear->depth_mask; 
+		} else {
+			tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
+			tempRB3D_STENCILREFMASK = 0x00000000;
+		}
 
-			OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
-			OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-				  RADEON_GMC_BRUSH_SOLID_COLOR |
-				  (dev_priv->color_fmt << 8) |
-				  RADEON_GMC_SRC_DATATYPE_COLOR |
-				  RADEON_ROP3_P |
-				  RADEON_GMC_CLR_CMP_CNTL_DIS );
+		BEGIN_RING( 26 );
+		RADEON_WAIT_UNTIL_2D_IDLE();
 
-			OUT_RING( dev_priv->back_pitch_offset );
-			OUT_RING( clear->clear_color );
+		OUT_RING_REG( RADEON_PP_CNTL, tempPP_CNTL );
+		OUT_RING_REG( R200_RE_CNTL, tempRE_CNTL );
+		OUT_RING_REG( RADEON_RB3D_CNTL, tempRB3D_CNTL );
+		OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
+			      tempRB3D_ZSTENCILCNTL );
+		OUT_RING_REG( RADEON_RB3D_STENCILREFMASK, 
+			      tempRB3D_STENCILREFMASK );
+		OUT_RING_REG( RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK );
+		OUT_RING_REG( RADEON_SE_CNTL, tempSE_CNTL );
+		OUT_RING_REG( R200_SE_VTE_CNTL, tempSE_VTE_CNTL );
+		OUT_RING_REG( R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0 );
+		OUT_RING_REG( R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1 );
+		OUT_RING_REG( R200_SE_VAP_CNTL, tempSE_VAP_CNTL );
+		OUT_RING_REG( R200_RE_AUX_SCISSOR_CNTL, 
+			      tempRE_AUX_SCISSOR_CNTL );
+		ADVANCE_RING();
 
-			OUT_RING( (x << 16) | y );
-			OUT_RING( (w << 16) | h );
+		/* Make sure we restore the 3D state next time.
+		 */
+		dev_priv->sarea_priv->ctx_owner = 0;
 
-			ADVANCE_RING();
+		for ( i = 0 ; i < nbox ; i++ ) {
+			
+			/* Funny that this should be required -- 
+			 *  sets top-left?
+			 */
+			radeon_emit_clip_rect( dev_priv,
+					       &sarea_priv->boxes[i] );
 
+			BEGIN_RING( 14 );
+			OUT_RING( CP_PACKET3( R200_3D_DRAW_IMMD_2, 12 ) );
+			OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
+				   RADEON_PRIM_WALK_RING |
+				   (3 << RADEON_NUM_VERTICES_SHIFT)) );
+			OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+			OUT_RING( 0x3f800000 );
+			OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+			OUT_RING( 0x3f800000 );
+			OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+			OUT_RING( 0x3f800000 );
+			ADVANCE_RING();
 		}
+	} 
+	else if ( (flags & (RADEON_DEPTH | RADEON_STENCIL)) ) {
+
+		rb3d_cntl = depth_clear->rb3d_cntl;
 
 		if ( flags & RADEON_DEPTH ) {
-			drm_radeon_depth_clear_t *depth_clear =
-			   &dev_priv->depth_clear;
+			rb3d_cntl |=  RADEON_Z_ENABLE;
+		} else {
+			rb3d_cntl &= ~RADEON_Z_ENABLE;
+		}
 
-			if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-				radeon_emit_state( dev_priv );
-			}
+		if ( flags & RADEON_STENCIL ) {
+			rb3d_cntl |=  RADEON_STENCIL_ENABLE;
+			rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */
+		} else {
+			rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
+			rb3d_stencilrefmask = 0x00000000;
+		}
 
-			/* FIXME: Render a rectangle to clear the depth
-			 * buffer.  So much for those "fast Z clears"...
-			 */
-			BEGIN_RING( 23 );
+		BEGIN_RING( 13 );
+		RADEON_WAIT_UNTIL_2D_IDLE();
+
+		OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
+		OUT_RING( 0x00000000 );
+		OUT_RING( rb3d_cntl );
+		
+		OUT_RING_REG( RADEON_RB3D_ZSTENCILCNTL,
+			      depth_clear->rb3d_zstencilcntl );
+		OUT_RING_REG( RADEON_RB3D_STENCILREFMASK,
+			      rb3d_stencilrefmask );
+		OUT_RING_REG( RADEON_RB3D_PLANEMASK,
+			      0x00000000 );
+		OUT_RING_REG( RADEON_SE_CNTL,
+			      depth_clear->se_cntl );
+		ADVANCE_RING();
 
-			RADEON_WAIT_UNTIL_2D_IDLE();
+		/* Make sure we restore the 3D state next time.
+		 */
+		dev_priv->sarea_priv->ctx_owner = 0;
 
-			OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
-			OUT_RING( 0x00000000 );
-			OUT_RING( depth_clear->rb3d_cntl );
-			OUT_RING( CP_PACKET0( RADEON_RB3D_ZSTENCILCNTL, 0 ) );
-			OUT_RING( depth_clear->rb3d_zstencilcntl );
-			OUT_RING( CP_PACKET0( RADEON_RB3D_PLANEMASK, 0 ) );
-			OUT_RING( 0x00000000 );
-			OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
-			OUT_RING( depth_clear->se_cntl );
+		for ( i = 0 ; i < nbox ; i++ ) {
+			
+			/* Funny that this should be required -- 
+			 *  sets top-left?
+			 */
+			radeon_emit_clip_rect( dev_priv,
+					       &sarea_priv->boxes[i] );
 
-			OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 10 ) );
-			OUT_RING( RADEON_VTX_Z_PRESENT );
+			BEGIN_RING( 15 );
+
+			OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 13 ) );
+			OUT_RING( RADEON_VTX_Z_PRESENT |
+				  RADEON_VTX_PKCOLOR_PRESENT);
 			OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
 				   RADEON_PRIM_WALK_RING |
 				   RADEON_MAOS_ENABLE |
 				   RADEON_VTX_FMT_RADEON_MODE |
 				   (3 << RADEON_NUM_VERTICES_SHIFT)) );
 
+
 			OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
 			OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
 			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+			OUT_RING( 0x0 );
 
 			OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
 			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
 			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+			OUT_RING( 0x0 );
 
 			OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
 			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
 			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+			OUT_RING( 0x0 );
 
 			ADVANCE_RING();
-
-			/* Make sure we restore the 3D state next time.
-			 */
-			dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
-							RADEON_UPLOAD_SETUP |
-							RADEON_UPLOAD_MASKS);
 		}
 	}
 
@@ -651,13 +730,13 @@
 	drm_clip_rect_t *pbox = sarea_priv->boxes;
 	int i;
 	RING_LOCALS;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
-#if RADEON_PERFORMANCE_BOXES
 	/* Do some trivial performance monitoring...
 	 */
-	radeon_cp_performance_boxes( dev_priv );
-#endif
+	if (dev_priv->do_boxes)
+		radeon_cp_performance_boxes( dev_priv );
+
 
 	/* Wait for the 3D stream to idle before dispatching the bitblt.
 	 * This will prevent data corruption between the two streams.
@@ -689,9 +768,17 @@
 			  RADEON_DP_SRC_SOURCE_MEMORY |
 			  RADEON_GMC_CLR_CMP_CNTL_DIS |
 			  RADEON_GMC_WR_MSK_DIS );
-
-		OUT_RING( dev_priv->back_pitch_offset );
-		OUT_RING( dev_priv->front_pitch_offset );
+		
+		/* Make this work even if front & back are flipped:
+		 */
+		if (dev_priv->current_page == 0) {
+			OUT_RING( dev_priv->back_pitch_offset );
+			OUT_RING( dev_priv->front_pitch_offset );
+		} 
+		else {
+			OUT_RING( dev_priv->front_pitch_offset );
+			OUT_RING( dev_priv->back_pitch_offset );
+		}
 
 		OUT_RING( (x << 16) | y );
 		OUT_RING( (x << 16) | y );
@@ -717,29 +804,33 @@
 static void radeon_cp_dispatch_flip( drm_device_t *dev )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-	DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
+	drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle;
+	int offset = (dev_priv->current_page == 1)
+		   ? dev_priv->front_offset : dev_priv->back_offset;
+	RING_LOCALS;
+	DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", 
+		__FUNCTION__, 
+		dev_priv->current_page,
+		dev_priv->sarea_priv->pfCurrentPage);
 
-#if RADEON_PERFORMANCE_BOXES
 	/* Do some trivial performance monitoring...
 	 */
-	radeon_cp_performance_boxes( dev_priv );
-#endif
+	if (dev_priv->do_boxes) {
+		dev_priv->stats.boxes |= RADEON_BOX_FLIP;
+		radeon_cp_performance_boxes( dev_priv );
+	}
 
+	/* Update the frame offsets for both CRTCs
+	 */
 	BEGIN_RING( 6 );
 
 	RADEON_WAIT_UNTIL_3D_IDLE();
-	RADEON_WAIT_UNTIL_PAGE_FLIPPED();
-
-	OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) );
-
-	if ( dev_priv->current_page == 0 ) {
-		OUT_RING( dev_priv->back_offset );
-		dev_priv->current_page = 1;
-	} else {
-		OUT_RING( dev_priv->front_offset );
-		dev_priv->current_page = 0;
-	}
+	OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch
+					      + sarea->frame.x 
+					      * ( dev_priv->color_fmt - 2 ) ) & ~7 )
+					  + offset );
+	OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
+					   + offset );
 
 	ADVANCE_RING();
 
@@ -748,6 +839,8 @@
 	 * performing the swapbuffer ioctl.
 	 */
 	dev_priv->sarea_priv->last_frame++;
+	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
+					      1 - dev_priv->current_page;
 
 	BEGIN_RING( 2 );
 
@@ -756,82 +849,118 @@
 	ADVANCE_RING();
 }
 
+static int bad_prim_vertex_nr( int primitive, int nr )
+{
+	switch (primitive & RADEON_PRIM_TYPE_MASK) {
+	case RADEON_PRIM_TYPE_NONE:
+	case RADEON_PRIM_TYPE_POINT:
+		return nr < 1;
+	case RADEON_PRIM_TYPE_LINE:
+		return (nr & 1) || nr == 0;
+	case RADEON_PRIM_TYPE_LINE_STRIP:
+		return nr < 2;
+	case RADEON_PRIM_TYPE_TRI_LIST:
+	case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
+	case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
+	case RADEON_PRIM_TYPE_RECT_LIST:
+		return nr % 3 || nr == 0;
+	case RADEON_PRIM_TYPE_TRI_FAN:
+	case RADEON_PRIM_TYPE_TRI_STRIP:
+		return nr < 3;
+	default:
+		return 1;
+	}	
+}
+
+
+
+typedef struct {
+	unsigned int start;
+	unsigned int finish;
+	unsigned int prim;
+	unsigned int numverts;
+	unsigned int offset;   
+        unsigned int vc_format;
+} drm_radeon_tcl_prim_t;
+
 static void radeon_cp_dispatch_vertex( drm_device_t *dev,
-				       drm_buf_t *buf )
+				       drm_buf_t *buf,
+				       drm_radeon_tcl_prim_t *prim,
+				       drm_clip_rect_t *boxes,
+				       int nbox )
+
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	int format = sarea_priv->vc_format;
-	int offset = dev_priv->agp_buffers_offset + buf->offset;
-	int size = buf->used;
-	int prim = buf_priv->prim;
+	drm_clip_rect_t box;
+	int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start;
+	int numverts = (int)prim->numverts;
 	int i = 0;
 	RING_LOCALS;
-	DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox );
-
-	if ( 0 )
-		radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
 
-	if ( buf->used ) {
-		buf_priv->dispatched = 1;
+	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
+		  prim->prim,
+		  prim->vc_format,
+		  prim->start,
+		  prim->finish,
+		  prim->numverts);
+
+	if (bad_prim_vertex_nr( prim->prim, prim->numverts )) {
+		DRM_ERROR( "bad prim %x numverts %d\n", 
+			   prim->prim, prim->numverts );
+		return;
+	}
+
+	do {
+		/* Emit the next cliprect */
+		if ( i < nbox ) {
+			if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
+				return;
 
-		if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-			radeon_emit_state( dev_priv );
+			radeon_emit_clip_rect( dev_priv, &box );
 		}
 
-		do {
-			/* Emit the next set of up to three cliprects */
-			if ( i < sarea_priv->nbox ) {
-				radeon_emit_clip_rect( dev_priv,
-						       &sarea_priv->boxes[i] );
-			}
+		/* Emit the vertex buffer rendering commands */
+		BEGIN_RING( 5 );
 
-			/* Emit the vertex buffer rendering commands */
-			BEGIN_RING( 5 );
+		OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
+		OUT_RING( offset );
+		OUT_RING( numverts );
+		OUT_RING( prim->vc_format );
+		OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST |
+			  RADEON_COLOR_ORDER_RGBA |
+			  RADEON_VTX_FMT_RADEON_MODE |
+			  (numverts << RADEON_NUM_VERTICES_SHIFT) );
 
-			OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
-			OUT_RING( offset );
-			OUT_RING( size );
-			OUT_RING( format );
-			OUT_RING( prim | RADEON_PRIM_WALK_LIST |
-				  RADEON_COLOR_ORDER_RGBA |
-				  RADEON_VTX_FMT_RADEON_MODE |
-				  (size << RADEON_NUM_VERTICES_SHIFT) );
+		ADVANCE_RING();
 
-			ADVANCE_RING();
+		i++;
+	} while ( i < nbox );
+}
 
-			i++;
-		} while ( i < sarea_priv->nbox );
-	}
 
-	if ( buf_priv->discard ) {
-		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
 
-		/* Emit the vertex buffer age */
-		BEGIN_RING( 2 );
-		RADEON_DISPATCH_AGE( buf_priv->age );
-		ADVANCE_RING();
+static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+	RING_LOCALS;
 
-		buf->pending = 1;
-		buf->used = 0;
-		/* FIXME: Check dispatched field */
-		buf_priv->dispatched = 0;
-	}
+	buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
 
-	dev_priv->sarea_priv->last_dispatch++;
+	/* Emit the vertex buffer age */
+	BEGIN_RING( 2 );
+	RADEON_DISPATCH_AGE( buf_priv->age );
+	ADVANCE_RING();
 
-	sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
-	sarea_priv->nbox = 0;
+	buf->pending = 1;
+	buf->used = 0;
 }
 
-
 static void radeon_cp_dispatch_indirect( drm_device_t *dev,
 					 drm_buf_t *buf,
 					 int start, int end )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
 	RING_LOCALS;
 	DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
 		   buf->idx, start, end );
@@ -852,8 +981,6 @@
 			data[dwords++] = RADEON_CP_PACKET2;
 		}
 
-		buf_priv->dispatched = 1;
-
 		/* Fire off the indirect buffer */
 		BEGIN_RING( 3 );
 
@@ -863,100 +990,75 @@
 
 		ADVANCE_RING();
 	}
-
-	if ( buf_priv->discard ) {
-		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
-
-		/* Emit the indirect buffer age */
-		BEGIN_RING( 2 );
-		RADEON_DISPATCH_AGE( buf_priv->age );
-		ADVANCE_RING();
-
-		buf->pending = 1;
-		buf->used = 0;
-		/* FIXME: Check dispatched field */
-		buf_priv->dispatched = 0;
-	}
-
-	dev_priv->sarea_priv->last_dispatch++;
 }
 
+
 static void radeon_cp_dispatch_indices( drm_device_t *dev,
-					drm_buf_t *buf,
-					int start, int end,
-					int count )
+					drm_buf_t *elt_buf,
+					drm_radeon_tcl_prim_t *prim, 
+					drm_clip_rect_t *boxes,
+					int nbox )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	int format = sarea_priv->vc_format;
-	int offset = dev_priv->agp_buffers_offset;
-	int prim = buf_priv->prim;
+	drm_clip_rect_t box;
+	int offset = dev_priv->agp_buffers_offset + prim->offset;
 	u32 *data;
 	int dwords;
 	int i = 0;
-	RING_LOCALS;
-	DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
+	int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
+	int count = (prim->finish - start) / sizeof(u16);
 
-	if ( 0 )
-		radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
-
-	if ( start != end ) {
-		buf_priv->dispatched = 1;
-
-		if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
-			radeon_emit_state( dev_priv );
-		}
-
-		dwords = (end - start + 3) / sizeof(u32);
-
-		data = (u32 *)((char *)dev_priv->buffers->handle
-			       + buf->offset + start);
-
-		data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
-
-		data[1] = offset;
-		data[2] = RADEON_MAX_VB_VERTS;
-		data[3] = format;
-		data[4] = (prim | RADEON_PRIM_WALK_IND |
-			   RADEON_COLOR_ORDER_RGBA |
-			   RADEON_VTX_FMT_RADEON_MODE |
-			   (count << RADEON_NUM_VERTICES_SHIFT) );
-
-		if ( count & 0x1 ) {
-			data[dwords-1] &= 0x0000ffff;
-		}
-
-		do {
-			/* Emit the next set of up to three cliprects */
-			if ( i < sarea_priv->nbox ) {
-				radeon_emit_clip_rect( dev_priv,
-						       &sarea_priv->boxes[i] );
-			}
-
-			radeon_cp_dispatch_indirect( dev, buf, start, end );
-
-			i++;
-		} while ( i < sarea_priv->nbox );
+	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
+		  prim->prim,
+		  prim->vc_format,
+		  prim->start,
+		  prim->finish,
+		  prim->offset,
+		  prim->numverts);
+
+	if (bad_prim_vertex_nr( prim->prim, count )) {
+		DRM_ERROR( "bad prim %x count %d\n", 
+			   prim->prim, count );
+		return;
 	}
 
-	if ( buf_priv->discard ) {
-		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
 
-		/* Emit the vertex buffer age */
-		BEGIN_RING( 2 );
-		RADEON_DISPATCH_AGE( buf_priv->age );
-		ADVANCE_RING();
+	if ( start >= prim->finish ||
+	     (prim->start & 0x7) ) {
+		DRM_ERROR( "buffer prim %d\n", prim->prim );
+		return;
+	}
+
+	dwords = (prim->finish - prim->start + 3) / sizeof(u32);
+
+	data = (u32 *)((char *)dev_priv->buffers->handle +
+		       elt_buf->offset + prim->start);
+
+	data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
+	data[1] = offset;
+	data[2] = prim->numverts;
+	data[3] = prim->vc_format;
+	data[4] = (prim->prim |
+		   RADEON_PRIM_WALK_IND |
+		   RADEON_COLOR_ORDER_RGBA |
+		   RADEON_VTX_FMT_RADEON_MODE |
+		   (count << RADEON_NUM_VERTICES_SHIFT) );
+
+	do {
+		if ( i < nbox ) {
+			if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
+				return;
+			
+			radeon_emit_clip_rect( dev_priv, &box );
+		}
 
-		buf->pending = 1;
-		/* FIXME: Check dispatched field */
-		buf_priv->dispatched = 0;
-	}
+		radeon_cp_dispatch_indirect( dev, elt_buf,
+					     prim->start,
+					     prim->finish );
 
-	dev_priv->sarea_priv->last_dispatch++;
+		i++;
+	} while ( i < nbox );
 
-	sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
-	sarea_priv->nbox = 0;
 }
 
 #define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
@@ -967,25 +1069,35 @@
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_buf_t *buf;
-	drm_radeon_buf_priv_t *buf_priv;
 	u32 format;
 	u32 *buffer;
-	u8 *data;
+	const u8 *data;
 	int size, dwords, tex_width, blit_width;
 	u32 y, height;
-	int ret = 0, i;
+	int i;
 	RING_LOCALS;
 
-	/* FIXME: Be smarter about this...
+	dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
+
+	/* Flush the pixel cache.  This ensures no pixel data gets mixed
+	 * up with the texture data from the host data blit, otherwise
+	 * part of the texture image may be corrupted.
 	 */
-	buf = radeon_freelist_get( dev );
-	if ( !buf ) return -EAGAIN;
+	BEGIN_RING( 4 );
+	RADEON_FLUSH_CACHE();
+	RADEON_WAIT_UNTIL_IDLE();
+	ADVANCE_RING();
 
-	DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
-		   tex->offset >> 10, tex->pitch, tex->format,
-		   image->x, image->y, image->width, image->height );
+#ifdef __BIG_ENDIAN
+	/* The Mesa texture functions provide the data in little endian as the
+	 * chip wants it, but we need to compensate for the fact that the CP
+	 * ring gets byte-swapped
+	 */
+	BEGIN_RING( 2 );
+	OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT );
+	ADVANCE_RING();
+#endif
 
-	buf_priv = buf->dev_private;
 
 	/* The compiler won't optimize away a division by a variable,
 	 * even if the only legal values are powers of two.  Thus, we'll
@@ -1002,6 +1114,8 @@
 	case RADEON_TXFORMAT_ARGB1555:
 	case RADEON_TXFORMAT_RGB565:
 	case RADEON_TXFORMAT_ARGB4444:
+	case RADEON_TXFORMAT_VYUY422:
+	case RADEON_TXFORMAT_YVYU422:
 		format = RADEON_COLOR_FORMAT_RGB565;
 		tex_width = tex->width * 2;
 		blit_width = image->width * 2;
@@ -1014,128 +1128,125 @@
 		break;
 	default:
 		DRM_ERROR( "invalid texture format %d\n", tex->format );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
-	DRM_DEBUG( "   tex=%dx%d  blit=%d\n",
-		   tex_width, tex->height, blit_width );
+	DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width );
 
-	/* Flush the pixel cache.  This ensures no pixel data gets mixed
-	 * up with the texture data from the host data blit, otherwise
-	 * part of the texture image may be corrupted.
-	 */
-	BEGIN_RING( 4 );
-
-	RADEON_FLUSH_CACHE();
-	RADEON_WAIT_UNTIL_IDLE();
-
-	ADVANCE_RING();
-
-	/* Make a copy of the parameters in case we have to update them
-	 * for a multi-pass texture blit.
-	 */
-	y = image->y;
-	height = image->height;
-	data = (u8 *)image->data;
-
-	size = height * blit_width;
+	do {
+		DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
+			   tex->offset >> 10, tex->pitch, tex->format,
+			   image->x, image->y, image->width, image->height );
 
-	if ( size > RADEON_MAX_TEXTURE_SIZE ) {
-		/* Texture image is too large, do a multipass upload */
-		ret = -EAGAIN;
-
-		/* Adjust the blit size to fit the indirect buffer */
-		height = RADEON_MAX_TEXTURE_SIZE / blit_width;
+		/* Make a copy of the parameters in case we have to
+		 * update them for a multi-pass texture blit.
+		 */
+		y = image->y;
+		height = image->height;
+		data = (const u8 *)image->data;
+		
 		size = height * blit_width;
 
+		if ( size > RADEON_MAX_TEXTURE_SIZE ) {
+			height = RADEON_MAX_TEXTURE_SIZE / blit_width;
+			size = height * blit_width;
+		} else if ( size < 4 && size > 0 ) {
+			size = 4;
+		} else if ( size == 0 ) {
+			return 0;
+		}
+
 		/* Update the input parameters for next time */
 		image->y += height;
 		image->height -= height;
-		image->data = (char *)image->data + size;
-
-		if ( copy_to_user( tex->image, image, sizeof(*image) ) ) {
-			DRM_ERROR( "EFAULT on tex->image\n" );
-			return -EFAULT;
-		}
-	} else if ( size < 4 && size > 0 ) {
-		size = 4;
-	}
-
-	dwords = size / 4;
-
-	/* Dispatch the indirect buffer.
-	 */
-	buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
-
-	buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
-	buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-		     RADEON_GMC_BRUSH_NONE |
-		     (format << 8) |
-		     RADEON_GMC_SRC_DATATYPE_COLOR |
-		     RADEON_ROP3_S |
-		     RADEON_DP_SRC_SOURCE_HOST_DATA |
-		     RADEON_GMC_CLR_CMP_CNTL_DIS |
-		     RADEON_GMC_WR_MSK_DIS);
+		image->data += size;
 
-	buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
-	buffer[3] = 0xffffffff;
-	buffer[4] = 0xffffffff;
-	buffer[5] = (y << 16) | image->x;
-	buffer[6] = (height << 16) | image->width;
-	buffer[7] = dwords;
+		buf = radeon_freelist_get( dev );
+		if ( 0 && !buf ) {
+			radeon_do_cp_idle( dev_priv );
+			buf = radeon_freelist_get( dev );
+		}
+		if ( !buf ) {
+			DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");
+			DRM_COPY_TO_USER( tex->image, image, sizeof(*image) );
+			return DRM_ERR(EAGAIN);
+		}
 
-	buffer += 8;
 
-	if ( tex_width >= 32 ) {
-		/* Texture image width is larger than the minimum, so we
-		 * can upload it directly.
+		/* Dispatch the indirect buffer.
 		 */
-		if ( copy_from_user( buffer, data, dwords * sizeof(u32) ) ) {
-			DRM_ERROR( "EFAULT on data, %d dwords\n", dwords );
-			return -EFAULT;
-		}
-	} else {
-		/* Texture image width is less than the minimum, so we
-		 * need to pad out each image scanline to the minimum
-		 * width.
-		 */
-		for ( i = 0 ; i < tex->height ; i++ ) {
-			if ( copy_from_user( buffer, data, tex_width ) ) {
-				DRM_ERROR( "EFAULT on pad, %d bytes\n",
-					   tex_width );
-				return -EFAULT;
+		buffer = (u32*)((char*)dev_priv->buffers->handle + buf->offset);
+		dwords = size / 4;
+		buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
+		buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+			     RADEON_GMC_BRUSH_NONE |
+			     (format << 8) |
+			     RADEON_GMC_SRC_DATATYPE_COLOR |
+			     RADEON_ROP3_S |
+			     RADEON_DP_SRC_SOURCE_HOST_DATA |
+			     RADEON_GMC_CLR_CMP_CNTL_DIS |
+			     RADEON_GMC_WR_MSK_DIS);
+		
+		buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
+		buffer[3] = 0xffffffff;
+		buffer[4] = 0xffffffff;
+		buffer[5] = (y << 16) | image->x;
+		buffer[6] = (height << 16) | image->width;
+		buffer[7] = dwords;
+		buffer += 8;
+
+		if ( tex_width >= 32 ) {
+			/* Texture image width is larger than the minimum, so we
+			 * can upload it directly.
+			 */
+			if ( DRM_COPY_FROM_USER( buffer, data, 
+						 dwords * sizeof(u32) ) ) {
+				DRM_ERROR( "EFAULT on data, %d dwords\n", 
+					   dwords );
+				return DRM_ERR(EFAULT);
+			}
+		} else {
+			/* Texture image width is less than the minimum, so we
+			 * need to pad out each image scanline to the minimum
+			 * width.
+			 */
+			for ( i = 0 ; i < tex->height ; i++ ) {
+				if ( DRM_COPY_FROM_USER( buffer, data, 
+							 tex_width ) ) {
+					DRM_ERROR( "EFAULT on pad, %d bytes\n",
+						   tex_width );
+					return DRM_ERR(EFAULT);
+				}
+				buffer += 8;
+				data += tex_width;
 			}
-			buffer += 8;
-			data += tex_width;
 		}
-	}
 
-	buf->pid = current->pid;
-	buf->used = (dwords + 8) * sizeof(u32);
-	buf_priv->discard = 1;
+		buf->pid = DRM_CURRENTPID;
+		buf->used = (dwords + 8) * sizeof(u32);
+		radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
+		radeon_cp_discard_buffer( dev, buf );
 
-	radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
+	} while (image->height > 0);
 
 	/* Flush the pixel cache after the blit completes.  This ensures
 	 * the texture data is written out to memory before rendering
 	 * continues.
 	 */
 	BEGIN_RING( 4 );
-
 	RADEON_FLUSH_CACHE();
 	RADEON_WAIT_UNTIL_2D_IDLE();
-
 	ADVANCE_RING();
-
-	return ret;
+	return 0;
 }
 
+
 static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	int i;
 	RING_LOCALS;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	BEGIN_RING( 35 );
 
@@ -1155,45 +1266,103 @@
  * IOCTL functions
  */
 
-int radeon_cp_clear( struct inode *inode, struct file *filp,
-		     unsigned int cmd, unsigned long arg )
+int radeon_cp_clear( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_radeon_clear_t clear;
 	drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg,
-			     sizeof(clear) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( clear, (drm_radeon_clear_t *)data,
+			     sizeof(clear) );
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
 	if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
 
-	if ( copy_from_user( &depth_boxes, clear.depth_boxes,
+	if ( DRM_COPY_FROM_USER( &depth_boxes, clear.depth_boxes,
 			     sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
-		return -EFAULT;
+		return DRM_ERR(EFAULT);
 
 	radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
 
+	COMMIT_RING();
+	return 0;
+}
+
+
+/* Not sure why this isn't set all the time:
+ */ 
+static int radeon_do_init_pageflip( drm_device_t *dev )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	DRM_DEBUG( "\n" );
+
+	BEGIN_RING( 6 );
+	RADEON_WAIT_UNTIL_3D_IDLE();
+	OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) );
+	OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
+	OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) );
+	OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL );
+	ADVANCE_RING();
+
+	dev_priv->page_flipping = 1;
+	dev_priv->current_page = 0;
+	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
+
+	return 0;
+}
+
+/* Called whenever a client dies, from DRM(release).
+ * NOTE:  Lock isn't necessarily held when this is called!
+ */
+int radeon_do_cleanup_pageflip( drm_device_t *dev )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG( "\n" );
+
+	if (dev_priv->current_page != 0)
+		radeon_cp_dispatch_flip( dev );
+
+	dev_priv->page_flipping = 0;
+	return 0;
+}
+
+/* Swapping and flipping are different operations, need different ioctls.
+ * They can & should be intermixed to support multiple 3d windows.  
+ */
+int radeon_cp_flip( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG( "\n" );
+
+	LOCK_TEST_WITH_RETURN( dev );
+
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
+	if (!dev_priv->page_flipping) 
+		radeon_do_init_pageflip( dev );
+		
+	radeon_cp_dispatch_flip( dev );
+
+	COMMIT_RING();
 	return 0;
 }
 
-int radeon_cp_swap( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int radeon_cp_swap( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG( "\n" );
 
 	LOCK_TEST_WITH_RETURN( dev );
 
@@ -1202,131 +1371,148 @@
 	if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
 
-	if ( !dev_priv->page_flipping ) {
-		radeon_cp_dispatch_swap( dev );
-		dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
-						RADEON_UPLOAD_MASKS);
-	} else {
-		radeon_cp_dispatch_flip( dev );
-	}
+	radeon_cp_dispatch_swap( dev );
+	dev_priv->sarea_priv->ctx_owner = 0;
 
+	COMMIT_RING();
 	return 0;
 }
 
-int radeon_cp_vertex( struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg )
+int radeon_cp_vertex( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
-	drm_radeon_buf_priv_t *buf_priv;
 	drm_radeon_vertex_t vertex;
+	drm_radeon_tcl_prim_t prim;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( !dev_priv ) {
 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
-	if ( copy_from_user( &vertex, (drm_radeon_vertex_t *)arg,
-			     sizeof(vertex) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t *)data,
+			     sizeof(vertex) );
 
-	DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n",
-		   __FUNCTION__, current->pid,
+	DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
+		   DRM_CURRENTPID,
 		   vertex.idx, vertex.count, vertex.discard );
 
 	if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
 		DRM_ERROR( "buffer index %d (of %d max)\n",
 			   vertex.idx, dma->buf_count - 1 );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	if ( vertex.prim < 0 ||
 	     vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
 		DRM_ERROR( "buffer prim %d\n", vertex.prim );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 	VB_AGE_TEST_WITH_RETURN( dev_priv );
 
 	buf = dma->buflist[vertex.idx];
-	buf_priv = buf->dev_private;
 
-	if ( buf->pid != current->pid ) {
+	if ( buf->pid != DRM_CURRENTPID ) {
 		DRM_ERROR( "process %d using buffer owned by %d\n",
-			   current->pid, buf->pid );
-		return -EINVAL;
+			   DRM_CURRENTPID, buf->pid );
+		return DRM_ERR(EINVAL);
 	}
 	if ( buf->pending ) {
 		DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
-	buf->used = vertex.count;
-	buf_priv->prim = vertex.prim;
-	buf_priv->discard = vertex.discard;
+	/* Build up a prim_t record:
+	 */
+	if (vertex.count) {
+		buf->used = vertex.count; /* not used? */
+
+		if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+			radeon_emit_state( dev_priv,
+					   &sarea_priv->context_state,
+					   sarea_priv->tex_state,
+					   sarea_priv->dirty );
+			
+			sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+					       RADEON_UPLOAD_TEX1IMAGES |
+					       RADEON_UPLOAD_TEX2IMAGES |
+					       RADEON_REQUIRE_QUIESCENCE);
+		}
+
+		prim.start = 0;
+		prim.finish = vertex.count; /* unused */
+		prim.prim = vertex.prim;
+		prim.numverts = vertex.count;
+		prim.vc_format = dev_priv->sarea_priv->vc_format;
+		
+		radeon_cp_dispatch_vertex( dev, buf, &prim,
+					   dev_priv->sarea_priv->boxes,
+					   dev_priv->sarea_priv->nbox );
+	}
 
-	radeon_cp_dispatch_vertex( dev, buf );
+	if (vertex.discard) {
+		radeon_cp_discard_buffer( dev, buf );
+	}
 
+	COMMIT_RING();
 	return 0;
 }
 
-int radeon_cp_indices( struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg )
+int radeon_cp_indices( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
-	drm_radeon_buf_priv_t *buf_priv;
 	drm_radeon_indices_t elts;
+	drm_radeon_tcl_prim_t prim;
 	int count;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( !dev_priv ) {
 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
-	if ( copy_from_user( &elts, (drm_radeon_indices_t *)arg,
-			     sizeof(elts) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( elts, (drm_radeon_indices_t *)data,
+			     sizeof(elts) );
 
-	DRM_DEBUG( "%s: pid=%d index=%d start=%d end=%d discard=%d\n",
-		   __FUNCTION__, current->pid,
+	DRM_DEBUG( "pid=%d index=%d start=%d end=%d discard=%d\n",
+		   DRM_CURRENTPID,
 		   elts.idx, elts.start, elts.end, elts.discard );
 
 	if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
 		DRM_ERROR( "buffer index %d (of %d max)\n",
 			   elts.idx, dma->buf_count - 1 );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	if ( elts.prim < 0 ||
 	     elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
 		DRM_ERROR( "buffer prim %d\n", elts.prim );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 	VB_AGE_TEST_WITH_RETURN( dev_priv );
 
 	buf = dma->buflist[elts.idx];
-	buf_priv = buf->dev_private;
 
-	if ( buf->pid != current->pid ) {
+	if ( buf->pid != DRM_CURRENTPID ) {
 		DRM_ERROR( "process %d using buffer owned by %d\n",
-			   current->pid, buf->pid );
-		return -EINVAL;
+			   DRM_CURRENTPID, buf->pid );
+		return DRM_ERR(EINVAL);
 	}
 	if ( buf->pending ) {
 		DRM_ERROR( "sending pending buffer %d\n", elts.idx );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	count = (elts.end - elts.start) / sizeof(u16);
@@ -1334,86 +1520,108 @@
 
 	if ( elts.start & 0x7 ) {
 		DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 	if ( elts.start < buf->used ) {
 		DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	buf->used = elts.end;
-	buf_priv->prim = elts.prim;
-	buf_priv->discard = elts.discard;
 
-	radeon_cp_dispatch_indices( dev, buf, elts.start, elts.end, count );
+	if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
+		radeon_emit_state( dev_priv,
+				   &sarea_priv->context_state,
+				   sarea_priv->tex_state,
+				   sarea_priv->dirty );
+
+		sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+				       RADEON_UPLOAD_TEX1IMAGES |
+				       RADEON_UPLOAD_TEX2IMAGES |
+				       RADEON_REQUIRE_QUIESCENCE);
+	}
+
+
+	/* Build up a prim_t record:
+	 */
+	prim.start = elts.start;
+	prim.finish = elts.end; 
+	prim.prim = elts.prim;
+	prim.offset = 0;	/* offset from start of dma buffers */
+	prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
+	prim.vc_format = dev_priv->sarea_priv->vc_format;
+	
+	radeon_cp_dispatch_indices( dev, buf, &prim,
+				   dev_priv->sarea_priv->boxes,
+				   dev_priv->sarea_priv->nbox );
+	if (elts.discard) {
+		radeon_cp_discard_buffer( dev, buf );
+	}
 
+	COMMIT_RING();
 	return 0;
 }
 
-int radeon_cp_texture( struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg )
+int radeon_cp_texture( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_texture_t tex;
 	drm_radeon_tex_image_t image;
+	int ret;
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &tex, (drm_radeon_texture_t *)arg, sizeof(tex) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( tex, (drm_radeon_texture_t *)data, sizeof(tex) );
 
 	if ( tex.image == NULL ) {
 		DRM_ERROR( "null texture image!\n" );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
-	if ( copy_from_user( &image,
+	if ( DRM_COPY_FROM_USER( &image,
 			     (drm_radeon_tex_image_t *)tex.image,
 			     sizeof(image) ) )
-		return -EFAULT;
+		return DRM_ERR(EFAULT);
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 	VB_AGE_TEST_WITH_RETURN( dev_priv );
 
-	return radeon_cp_dispatch_texture( dev, &tex, &image );
+	ret = radeon_cp_dispatch_texture( dev, &tex, &image );
+
+	COMMIT_RING();
+	return ret;
 }
 
-int radeon_cp_stipple( struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg )
+int radeon_cp_stipple( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_stipple_t stipple;
 	u32 mask[32];
 
 	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg,
-			     sizeof(stipple) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( stipple, (drm_radeon_stipple_t *)data,
+			     sizeof(stipple) );
 
-	if ( copy_from_user( &mask, stipple.mask, 32 * sizeof(u32) ) )
-		return -EFAULT;
+	if ( DRM_COPY_FROM_USER( &mask, stipple.mask, 32 * sizeof(u32) ) )
+		return DRM_ERR(EFAULT);
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
 	radeon_cp_dispatch_stipple( dev, mask );
 
+	COMMIT_RING();
 	return 0;
 }
 
-int radeon_cp_indirect( struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg )
+int radeon_cp_indirect( DRM_IOCTL_ARGS )
 {
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
-	drm_radeon_buf_priv_t *buf_priv;
 	drm_radeon_indirect_t indirect;
 	RING_LOCALS;
 
@@ -1421,12 +1629,11 @@
 
 	if ( !dev_priv ) {
 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
-	if ( copy_from_user( &indirect, (drm_radeon_indirect_t *)arg,
-			     sizeof(indirect) ) )
-		return -EFAULT;
+	DRM_COPY_FROM_USER_IOCTL( indirect, (drm_radeon_indirect_t *)data,
+			     sizeof(indirect) );
 
 	DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
 		   indirect.idx, indirect.start,
@@ -1435,33 +1642,31 @@
 	if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
 		DRM_ERROR( "buffer index %d (of %d max)\n",
 			   indirect.idx, dma->buf_count - 1 );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	buf = dma->buflist[indirect.idx];
-	buf_priv = buf->dev_private;
 
-	if ( buf->pid != current->pid ) {
+	if ( buf->pid != DRM_CURRENTPID ) {
 		DRM_ERROR( "process %d using buffer owned by %d\n",
-			   current->pid, buf->pid );
-		return -EINVAL;
+			   DRM_CURRENTPID, buf->pid );
+		return DRM_ERR(EINVAL);
 	}
 	if ( buf->pending ) {
 		DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	if ( indirect.start < buf->used ) {
 		DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
 			   indirect.start, buf->used );
-		return -EINVAL;
+		return DRM_ERR(EINVAL);
 	}
 
 	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 	VB_AGE_TEST_WITH_RETURN( dev_priv );
 
 	buf->used = indirect.end;
-	buf_priv->discard = indirect.discard;
 
 	/* Wait for the 3D stream to idle before the indirect buffer
 	 * containing 2D acceleration commands is processed.
@@ -1477,6 +1682,523 @@
 	 * privileged clients.
 	 */
 	radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
+	if (indirect.discard) {
+		radeon_cp_discard_buffer( dev, buf );
+	}
+
+
+	COMMIT_RING();
+	return 0;
+}
+
+int radeon_cp_vertex2( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_radeon_vertex2_t vertex;
+	int i;
+	unsigned char laststate;
+
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex2_t *)data,
+			     sizeof(vertex) );
+
+	DRM_DEBUG( "pid=%d index=%d discard=%d\n",
+		   DRM_CURRENTPID,
+		   vertex.idx, vertex.discard );
+
+	if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
+		DRM_ERROR( "buffer index %d (of %d max)\n",
+			   vertex.idx, dma->buf_count - 1 );
+		return DRM_ERR(EINVAL);
+	}
+
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+	VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+	buf = dma->buflist[vertex.idx];
+
+	if ( buf->pid != DRM_CURRENTPID ) {
+		DRM_ERROR( "process %d using buffer owned by %d\n",
+			   DRM_CURRENTPID, buf->pid );
+		return DRM_ERR(EINVAL);
+	}
+
+	if ( buf->pending ) {
+		DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
+		return DRM_ERR(EINVAL);
+	}
+	
+	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+		return DRM_ERR(EINVAL);
+
+	for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) {
+		drm_radeon_prim_t prim;
+		drm_radeon_tcl_prim_t tclprim;
+		
+		if ( DRM_COPY_FROM_USER( &prim, &vertex.prim[i], sizeof(prim) ) )
+			return DRM_ERR(EFAULT);
+		
+		if ( prim.stateidx != laststate ) {
+			drm_radeon_state_t state;			       
+				
+			if ( DRM_COPY_FROM_USER( &state, 
+					     &vertex.state[prim.stateidx], 
+					     sizeof(state) ) )
+				return DRM_ERR(EFAULT);
+
+			radeon_emit_state2( dev_priv, &state );
+
+			laststate = prim.stateidx;
+		}
+
+		tclprim.start = prim.start;
+		tclprim.finish = prim.finish;
+		tclprim.prim = prim.prim;
+		tclprim.vc_format = prim.vc_format;
+
+		if ( prim.prim & RADEON_PRIM_WALK_IND ) {
+			tclprim.offset = prim.numverts * 64;
+			tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
+
+			radeon_cp_dispatch_indices( dev, buf, &tclprim,
+						    sarea_priv->boxes,
+						    sarea_priv->nbox);
+		} else {
+			tclprim.numverts = prim.numverts;
+			tclprim.offset = 0; /* not used */
+
+			radeon_cp_dispatch_vertex( dev, buf, &tclprim,
+						   sarea_priv->boxes,
+						   sarea_priv->nbox);
+		}
+		
+		if (sarea_priv->nbox == 1)
+			sarea_priv->nbox = 0;
+	}
+
+	if ( vertex.discard ) {
+		radeon_cp_discard_buffer( dev, buf );
+	}
+
+	COMMIT_RING();
+	return 0;
+}
+
+
+static int radeon_emit_packets( 
+	drm_radeon_private_t *dev_priv,
+	drm_radeon_cmd_header_t header,
+	drm_radeon_cmd_buffer_t *cmdbuf )
+{
+	int id = (int)header.packet.packet_id;
+	int sz, reg;
+	int *data = (int *)cmdbuf->buf;
+	RING_LOCALS;
+   
+	if (id >= RADEON_MAX_STATE_PACKETS)
+		return DRM_ERR(EINVAL);
+
+	sz = packet[id].len;
+	reg = packet[id].start;
+
+	if (sz * sizeof(int) > cmdbuf->bufsz) 
+		return DRM_ERR(EINVAL);
+
+	BEGIN_RING(sz+1);
+	OUT_RING( CP_PACKET0( reg, (sz-1) ) );
+	OUT_RING_USER_TABLE( data, sz );
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
+static __inline__ int radeon_emit_scalars( 
+	drm_radeon_private_t *dev_priv,
+	drm_radeon_cmd_header_t header,
+	drm_radeon_cmd_buffer_t *cmdbuf )
+{
+	int sz = header.scalars.count;
+	int *data = (int *)cmdbuf->buf;
+	int start = header.scalars.offset;
+	int stride = header.scalars.stride;
+	RING_LOCALS;
+
+	BEGIN_RING( 3+sz );
+	OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
+	OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+	OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
+	OUT_RING_USER_TABLE( data, sz );
+	ADVANCE_RING();
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
+/* God this is ugly
+ */
+static __inline__ int radeon_emit_scalars2( 
+	drm_radeon_private_t *dev_priv,
+	drm_radeon_cmd_header_t header,
+	drm_radeon_cmd_buffer_t *cmdbuf )
+{
+	int sz = header.scalars.count;
+	int *data = (int *)cmdbuf->buf;
+	int start = ((unsigned int)header.scalars.offset) + 0x100;
+	int stride = header.scalars.stride;
+	RING_LOCALS;
+
+	BEGIN_RING( 3+sz );
+	OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
+	OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+	OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
+	OUT_RING_USER_TABLE( data, sz );
+	ADVANCE_RING();
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
+static __inline__ int radeon_emit_vectors( 
+	drm_radeon_private_t *dev_priv,
+	drm_radeon_cmd_header_t header,
+	drm_radeon_cmd_buffer_t *cmdbuf )
+{
+	int sz = header.vectors.count;
+	int *data = (int *)cmdbuf->buf;
+	int start = header.vectors.offset;
+	int stride = header.vectors.stride;
+	RING_LOCALS;
+
+	BEGIN_RING( 3+sz );
+	OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
+	OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+	OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
+	OUT_RING_USER_TABLE( data, sz );
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
+
+static int radeon_emit_packet3( drm_device_t *dev,
+				drm_radeon_cmd_buffer_t *cmdbuf )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	int cmdsz, tmp;
+	int *cmd = (int *)cmdbuf->buf;
+	RING_LOCALS;
+
+
+	DRM_DEBUG("\n");
+
+	if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
+		return DRM_ERR(EFAULT);
+
+	cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+
+	if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
+	    cmdsz * 4 > cmdbuf->bufsz)
+		return DRM_ERR(EINVAL);
+
+	BEGIN_RING( cmdsz );
+	OUT_RING_USER_TABLE( cmd, cmdsz );
+	ADVANCE_RING();
+
+	cmdbuf->buf += cmdsz * 4;
+	cmdbuf->bufsz -= cmdsz * 4;
+	return 0;
+}
+
+
+static int radeon_emit_packet3_cliprect( drm_device_t *dev,
+					 drm_radeon_cmd_buffer_t *cmdbuf,
+					 int orig_nbox )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_clip_rect_t box;
+	int cmdsz, tmp;
+	int *cmd = (int *)cmdbuf->buf;
+	drm_clip_rect_t *boxes = cmdbuf->boxes;
+	int i = 0;
+	RING_LOCALS;
+
+	DRM_DEBUG("\n");
+
+	if (DRM_GET_USER_UNCHECKED( tmp, &cmd[0]))
+		return DRM_ERR(EFAULT);
+
+	cmdsz = 2 + ((tmp & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+
+	if ((tmp & 0xc0000000) != RADEON_CP_PACKET3 ||
+	    cmdsz * 4 > cmdbuf->bufsz)
+		return DRM_ERR(EINVAL);
+
+	if (!orig_nbox)
+		goto out;
+
+	do {
+		if ( i < cmdbuf->nbox ) {
+			if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
+				return DRM_ERR(EFAULT);
+			/* FIXME The second and subsequent times round
+			 * this loop, send a WAIT_UNTIL_3D_IDLE before
+			 * calling emit_clip_rect(). This fixes a
+			 * lockup on fast machines when sending
+			 * several cliprects with a cmdbuf, as when
+			 * waving a 2D window over a 3D
+			 * window. Something in the commands from user
+			 * space seems to hang the card when they're
+			 * sent several times in a row. That would be
+			 * the correct place to fix it but this works
+			 * around it until I can figure that out - Tim
+			 * Smith */
+			if ( i ) {
+				BEGIN_RING( 2 );
+				RADEON_WAIT_UNTIL_3D_IDLE();
+				ADVANCE_RING();
+			}
+			radeon_emit_clip_rect( dev_priv, &box );
+		}
+		
+		BEGIN_RING( cmdsz );
+		OUT_RING_USER_TABLE( cmd, cmdsz );
+		ADVANCE_RING();
+
+	} while ( ++i < cmdbuf->nbox );
+ 	if (cmdbuf->nbox == 1)
+		cmdbuf->nbox = 0;
+
+ out:
+	cmdbuf->buf += cmdsz * 4;
+	cmdbuf->bufsz -= cmdsz * 4;
+	return 0;
+}
+
+
+static int radeon_emit_wait( drm_device_t *dev, int flags )
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+
+	DRM_DEBUG("%s: %x\n", __FUNCTION__, flags);
+	switch (flags) {
+	case RADEON_WAIT_2D:
+		BEGIN_RING( 2 );
+		RADEON_WAIT_UNTIL_2D_IDLE(); 
+		ADVANCE_RING();
+		break;
+	case RADEON_WAIT_3D:
+		BEGIN_RING( 2 );
+		RADEON_WAIT_UNTIL_3D_IDLE(); 
+		ADVANCE_RING();
+		break;
+	case RADEON_WAIT_2D|RADEON_WAIT_3D:
+		BEGIN_RING( 2 );
+		RADEON_WAIT_UNTIL_IDLE(); 
+		ADVANCE_RING();
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	return 0;
+}
+
+int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf = 0;
+	int idx;
+	drm_radeon_cmd_buffer_t cmdbuf;
+	drm_radeon_cmd_header_t header;
+	int orig_nbox;
+
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( cmdbuf, (drm_radeon_cmd_buffer_t *)data,
+			     sizeof(cmdbuf) );
+
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+	VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+
+	if (DRM_VERIFYAREA_READ( cmdbuf.buf, cmdbuf.bufsz ))
+		return DRM_ERR(EFAULT);
+
+	if (cmdbuf.nbox &&
+	    DRM_VERIFYAREA_READ(cmdbuf.boxes, 
+			 cmdbuf.nbox * sizeof(drm_clip_rect_t)))
+		return DRM_ERR(EFAULT);
+
+	orig_nbox = cmdbuf.nbox;
+
+	while ( cmdbuf.bufsz >= sizeof(header) ) {
+		
+		if (DRM_GET_USER_UNCHECKED( header.i, (int *)cmdbuf.buf )) {
+			DRM_ERROR("__get_user %p\n", cmdbuf.buf);
+			return DRM_ERR(EFAULT);
+		}
+
+		cmdbuf.buf += sizeof(header);
+		cmdbuf.bufsz -= sizeof(header);
+
+		switch (header.header.cmd_type) {
+		case RADEON_CMD_PACKET: 
+			DRM_DEBUG("RADEON_CMD_PACKET\n");
+			if (radeon_emit_packets( dev_priv, header, &cmdbuf )) {
+				DRM_ERROR("radeon_emit_packets failed\n");
+				return DRM_ERR(EINVAL);
+			}
+			break;
+
+		case RADEON_CMD_SCALARS:
+			DRM_DEBUG("RADEON_CMD_SCALARS\n");
+			if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) {
+				DRM_ERROR("radeon_emit_scalars failed\n");
+				return DRM_ERR(EINVAL);
+			}
+			break;
+
+		case RADEON_CMD_VECTORS:
+			DRM_DEBUG("RADEON_CMD_VECTORS\n");
+			if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) {
+				DRM_ERROR("radeon_emit_vectors failed\n");
+				return DRM_ERR(EINVAL);
+			}
+			break;
+
+		case RADEON_CMD_DMA_DISCARD:
+			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+			idx = header.dma.buf_idx;
+			if ( idx < 0 || idx >= dma->buf_count ) {
+				DRM_ERROR( "buffer index %d (of %d max)\n",
+					   idx, dma->buf_count - 1 );
+				return DRM_ERR(EINVAL);
+			}
+
+			buf = dma->buflist[idx];
+			if ( buf->pid != DRM_CURRENTPID || buf->pending ) {
+				DRM_ERROR( "bad buffer\n" );
+				return DRM_ERR(EINVAL);
+			}
+
+			radeon_cp_discard_buffer( dev, buf );
+			break;
+
+		case RADEON_CMD_PACKET3:
+			DRM_DEBUG("RADEON_CMD_PACKET3\n");
+			if (radeon_emit_packet3( dev, &cmdbuf )) {
+				DRM_ERROR("radeon_emit_packet3 failed\n");
+				return DRM_ERR(EINVAL);
+			}
+			break;
+
+		case RADEON_CMD_PACKET3_CLIP:
+			DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
+			if (radeon_emit_packet3_cliprect( dev, &cmdbuf, orig_nbox )) {
+				DRM_ERROR("radeon_emit_packet3_clip failed\n");
+				return DRM_ERR(EINVAL);
+			}
+			break;
+
+		case RADEON_CMD_SCALARS2:
+			DRM_DEBUG("RADEON_CMD_SCALARS2\n");
+			if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) {
+				DRM_ERROR("radeon_emit_scalars2 failed\n");
+				return DRM_ERR(EINVAL);
+			}
+			break;
+
+		case RADEON_CMD_WAIT:
+			DRM_DEBUG("RADEON_CMD_WAIT\n");
+			if (radeon_emit_wait( dev, header.wait.flags )) {
+				DRM_ERROR("radeon_emit_wait failed\n");
+				return DRM_ERR(EINVAL);
+			}
+			break;
+		default:
+			DRM_ERROR("bad cmd_type %d at %p\n", 
+				  header.header.cmd_type,
+				  cmdbuf.buf - sizeof(header));
+			return DRM_ERR(EINVAL);
+		}
+	}
+
+
+	DRM_DEBUG("DONE\n");
+	COMMIT_RING();
+	return 0;
+}
+
+
+
+int radeon_cp_getparam( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_getparam_t param;
+	int value;
 
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( param, (drm_radeon_getparam_t *)data,
+			     sizeof(param) );
+
+	DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
+
+	switch( param.param ) {
+	case RADEON_PARAM_AGP_BUFFER_OFFSET:
+		value = dev_priv->agp_buffers_offset;
+		break;
+	case RADEON_PARAM_LAST_FRAME:
+		dev_priv->stats.last_frame_reads++;
+		value = GET_SCRATCH( 0 );
+		break;
+	case RADEON_PARAM_LAST_DISPATCH:
+		value = GET_SCRATCH( 1 );
+		break;
+	case RADEON_PARAM_LAST_CLEAR:
+		dev_priv->stats.last_clear_reads++;
+		value = GET_SCRATCH( 2 );
+		break;
+	case RADEON_PARAM_IRQ_NR:
+		value = dev->irq;
+		break;
+	case RADEON_PARAM_AGP_BASE:
+		value = dev_priv->agp_vm_start;
+		break;
+	default:
+		return DRM_ERR(EINVAL);
+	}
+
+	if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
+		DRM_ERROR( "copy_to_user\n" );
+		return DRM_ERR(EFAULT);
+	}
+	
 	return 0;
 }
diff -ruN drivers/char/drm-4.2/sis.h drivers/char/drm/sis.h
--- drivers/char/drm-4.2/sis.h	2001-12-22 02:41:53.000000000 +0900
+++ drivers/char/drm/sis.h	2003-01-14 07:01:00.000000000 +0900
@@ -24,7 +24,7 @@
  * DEALINGS IN THE SOFTWARE.
  * 
  */
-/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.1 2001/05/19 18:29:22 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.3 2002/10/30 12:52:38 alanh Exp $ */
 
 #ifndef __SIS_H__
 #define __SIS_H__
@@ -42,6 +42,31 @@
 #define __HAVE_MTRR		1
 #define __HAVE_CTX_BITMAP	1
 
+#define DRIVER_AUTHOR	 "SIS"
+#define DRIVER_NAME	 "sis"
+#define DRIVER_DESC	 "SIS 300/630/540"
+#define DRIVER_DATE	 "20010503"
+#define DRIVER_MAJOR	 1
+#define DRIVER_MINOR	 0
+#define DRIVER_PATCHLEVEL  0
+
+#define DRIVER_IOCTLS \
+        [DRM_IOCTL_NR(SIS_IOCTL_FB_ALLOC)]   = { sis_fb_alloc,	  1, 0 }, \
+        [DRM_IOCTL_NR(SIS_IOCTL_FB_FREE)]    = { sis_fb_free,	  1, 0 }, \
+        /* AGP Memory Management */					  \
+        [DRM_IOCTL_NR(SIS_IOCTL_AGP_INIT)]   = { sisp_agp_init,	  1, 0 }, \
+        [DRM_IOCTL_NR(SIS_IOCTL_AGP_ALLOC)]  = { sisp_agp_alloc,  1, 0 }, \
+        [DRM_IOCTL_NR(SIS_IOCTL_AGP_FREE)]   = { sisp_agp_free,	  1, 0 }
+#if 0 /* these don't appear to be defined */
+	/* SIS Stereo */						 
+	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]    = { sis_control,	  1, 1 }, 
+        [DRM_IOCTL_NR(SIS_IOCTL_FLIP)]       = { sis_flip,	  1, 1 }, 
+        [DRM_IOCTL_NR(SIS_IOCTL_FLIP_INIT)]  = { sis_flip_init,	  1, 1 }, 
+        [DRM_IOCTL_NR(SIS_IOCTL_FLIP_FINAL)] = { sis_flip_final,  1, 1 }
+#endif
+
+#define __HAVE_COUNTERS		5
+
 /* Buffer customization:
  */
 #define DRIVER_AGP_BUFFERS_MAP( dev )					\
diff -ruN drivers/char/drm-4.2/sis_drm.h drivers/char/drm/sis_drm.h
--- drivers/char/drm-4.2/sis_drm.h	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/sis_drm.h	2003-01-14 07:01:00.000000000 +0900
@@ -2,11 +2,21 @@
 #ifndef _sis_drm_public_h_
 #define _sis_drm_public_h_
 
+/* SiS specific ioctls */
+#define SIS_IOCTL_FB_ALLOC		DRM_IOWR(0x44, drm_sis_mem_t)
+#define SIS_IOCTL_FB_FREE		DRM_IOW( 0x45, drm_sis_mem_t)
+#define SIS_IOCTL_AGP_INIT		DRM_IOWR(0x53, drm_sis_agp_t)
+#define SIS_IOCTL_AGP_ALLOC		DRM_IOWR(0x54, drm_sis_mem_t)
+#define SIS_IOCTL_AGP_FREE		DRM_IOW( 0x55, drm_sis_mem_t)
+#define SIS_IOCTL_FLIP			DRM_IOW( 0x48, drm_sis_flip_t)
+#define SIS_IOCTL_FLIP_INIT		DRM_IO(  0x49)
+#define SIS_IOCTL_FLIP_FINAL		DRM_IO(  0x50)
+
 typedef struct {
   int context;
   unsigned int offset;
   unsigned int size;
-  unsigned long free;
+  unsigned int free;
 } drm_sis_mem_t;
 
 typedef struct {
diff -ruN drivers/char/drm-4.2/sis_drv.c drivers/char/drm/sis_drv.c
--- drivers/char/drm-4.2/sis_drv.c	2002-02-26 04:37:57.000000000 +0900
+++ drivers/char/drm/sis_drv.c	2003-01-14 07:00:59.000000000 +0900
@@ -31,31 +31,6 @@
 #include "sis_drm.h"
 #include "sis_drv.h"
 
-#define DRIVER_AUTHOR	 "SIS"
-#define DRIVER_NAME	 "sis"
-#define DRIVER_DESC	 "SIS 300/630/540"
-#define DRIVER_DATE	 "20010503"
-#define DRIVER_MAJOR	 1
-#define DRIVER_MINOR	 0
-#define DRIVER_PATCHLEVEL  0
-
-#define DRIVER_IOCTLS \
-        [DRM_IOCTL_NR(SIS_IOCTL_FB_ALLOC)]   = { sis_fb_alloc,	  1, 0 }, \
-        [DRM_IOCTL_NR(SIS_IOCTL_FB_FREE)]    = { sis_fb_free,	  1, 0 }, \
-        /* AGP Memory Management */					  \
-        [DRM_IOCTL_NR(SIS_IOCTL_AGP_INIT)]   = { sisp_agp_init,	  1, 0 }, \
-        [DRM_IOCTL_NR(SIS_IOCTL_AGP_ALLOC)]  = { sisp_agp_alloc,  1, 0 }, \
-        [DRM_IOCTL_NR(SIS_IOCTL_AGP_FREE)]   = { sisp_agp_free,	  1, 0 }
-#if 0 /* these don't appear to be defined */
-	/* SIS Stereo */						 
-	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]    = { sis_control,	  1, 1 }, 
-        [DRM_IOCTL_NR(SIS_IOCTL_FLIP)]       = { sis_flip,	  1, 1 }, 
-        [DRM_IOCTL_NR(SIS_IOCTL_FLIP_INIT)]  = { sis_flip_init,	  1, 1 }, 
-        [DRM_IOCTL_NR(SIS_IOCTL_FLIP_FINAL)] = { sis_flip_final,  1, 1 }
-#endif
-
-#define __HAVE_COUNTERS		5
-
 #include "drm_auth.h"
 #include "drm_agpsupport.h"
 #include "drm_bufs.h"
diff -ruN drivers/char/drm-4.2/sis_ds.c drivers/char/drm/sis_ds.c
--- drivers/char/drm-4.2/sis_ds.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/sis_ds.c	2003-01-14 07:00:59.000000000 +0900
@@ -28,6 +28,7 @@
  * 
  */
 
+#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -58,7 +59,7 @@
     set->free = 0;
     set->alloc = -1;
     set->trace = -1;
-  }
+  }  
   return set;
 }
 
diff -ruN drivers/char/drm-4.2/sis_mm.c drivers/char/drm/sis_mm.c
--- drivers/char/drm-4.2/sis_mm.c	2002-11-29 08:53:12.000000000 +0900
+++ drivers/char/drm/sis_mm.c	2003-01-14 07:00:59.000000000 +0900
@@ -28,6 +28,7 @@
  * 
  */
 
+#define __NO_VERSION__
 #include "sis.h"
 #include <linux/sisfb.h>
 #include "drmP.h"
@@ -124,7 +125,7 @@
   if(!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
     retval = -1;
 
-  DRM_DEBUG("free fb, offset = %ld\n", fb.free);
+  DRM_DEBUG("free fb, offset = %d\n", fb.free);
   
   return retval;
 }
@@ -185,7 +186,7 @@
     agp.free = (unsigned long)block;
     if(!add_alloc_set(agp.context, AGP_TYPE, agp.free)){
       DRM_DEBUG("adding to allocation set fails\n");
-      mmFreeMem((PMemBlock)agp.free);
+      mmFreeMem((PMemBlock)(unsigned long)agp.free);
       retval = -1;
     }
   }
@@ -218,11 +219,11 @@
     return -1;
   }
 
-  mmFreeMem((PMemBlock)agp.free);
+  mmFreeMem((PMemBlock)(unsigned long)agp.free);
   if(!del_alloc_set(agp.context, AGP_TYPE, agp.free))
     retval = -1;
 
-  DRM_DEBUG("free agp, free = %ld\n", agp.free);
+  DRM_DEBUG("free agp, free = %d\n", agp.free);
   
   return retval;
 }
@@ -288,7 +289,7 @@
 	  retval = setFirst(set, &item);
 	  while(retval){
    	    DRM_DEBUG("free agp memory 0x%x\n", item);
-	    mmFreeMem((PMemBlock)item);
+	    mmFreeMem((PMemBlock)(unsigned long)item);
 	    retval = setNext(set, &item);
 	  }
 	  setDestroy(set);
diff -ruN drivers/char/drm-4.2/tdfx_drv.c drivers/char/drm/tdfx_drv.c
--- drivers/char/drm-4.2/tdfx_drv.c	2001-08-27 23:40:33.000000000 +0900
+++ drivers/char/drm/tdfx_drv.c	2003-01-14 07:00:59.000000000 +0900
@@ -82,25 +82,6 @@
 #include "drm_drawable.h"
 #include "drm_drv.h"
 
-#ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO).  It calls the insmod option
- * routine, drm_parse_drm.
- */
-
-/* JH- We have to hand expand the string ourselves because of the cpp.  If
- * anyone can think of a way that we can fit into the __setup macro without
- * changing it, then please send the solution my way.
- */
-static int __init tdfx_options( char *str )
-{
-	DRM(parse_options)( str );
-	return 1;
-}
-
-__setup( DRIVER_NAME "=", tdfx_options );
-#endif
-
 #include "drm_fops.h"
 #include "drm_init.h"
 #include "drm_ioctl.h"
