## Automatically generated incremental diff
## From:   linux-2.4.8-pre6
## To:     linux-2.4.8-pre7
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.8-pre6/Makefile linux/Makefile
--- linux-2.4.8-pre6/Makefile	Mon Dec  3 22:59:36 2001
+++ linux/Makefile	Mon Dec  3 22:59:45 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 8
-EXTRAVERSION =-pre5
+EXTRAVERSION =-pre7
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.8-pre6/drivers/char/drm/Config.in linux/drivers/char/drm/Config.in
--- linux-2.4.8-pre6/drivers/char/drm/Config.in	Fri Jan 19 13:34:28 2001
+++ linux/drivers/char/drm/Config.in	Mon Dec  3 22:59:45 2001
@@ -2,14 +2,14 @@
 # drm device configuration
 #
 # This driver provides support for the
-# Direct Rendering Infrastructure (DRI) in XFree86 4.x.
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 #
 
-bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
+bool 'Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)' CONFIG_DRM
 if [ "$CONFIG_DRM" != "n" ]; then
     tristate '  3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX
     tristate '  3dlabs GMX 2000' CONFIG_DRM_GAMMA
-    dep_tristate '  ATI Rage 128' CONFIG_DRM_R128 $CONFIG_AGP
+    tristate '  ATI Rage 128' CONFIG_DRM_R128
     dep_tristate '  ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
     dep_tristate '  Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
     dep_tristate '  Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP
diff -urN linux-2.4.8-pre6/drivers/char/drm/Makefile linux/drivers/char/drm/Makefile
--- linux-2.4.8-pre6/drivers/char/drm/Makefile	Mon Mar 26 15:36:30 2001
+++ linux/drivers/char/drm/Makefile	Mon Dec  3 22:59:45 2001
@@ -1,86 +1,29 @@
 #
-# Makefile for the drm device driver.  This driver provides support for
-# the Direct Rendering Infrastructure (DRI) in XFree86 4.x.
-#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 O_TARGET	:= drm.o
-
-export-objs     := gamma_drv.o tdfx_drv.o r128_drv.o ffb_drv.o mga_drv.o \
-		   i810_drv.o
-
-# lib-objs are included in every module so that radical changes to the
-# architecture of the DRM support library can be made at a later time.
-#
-# The downside is that each module is larger, and a system that uses
-# more than one module (i.e., a dual-head system) will use more memory
-# (but a system that uses exactly one module will use the same amount of
-# memory).
-#
-# The upside is that if the DRM support library ever becomes insufficient
-# for new families of cards, a new library can be implemented for those new
-# cards without impacting the drivers for the old cards.  This is significant,
-# because testing architectural changes to old cards may be impossible, and
-# may delay the implementation of a better architecture.  We've traded slight
-# memory waste (in the dual-head case) for greatly improved long-term
-# maintainability.
-#
-# NOTE: lib-objs will be eliminated in future versions, thereby
-# eliminating the need to compile the .o files into every module, but
-# for now we still need them.
-#
-
-lib-objs   := init.o memory.o proc.o auth.o context.o drawable.o bufs.o
-lib-objs   += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o
-
-ifeq ($(CONFIG_AGP),y)
- lib-objs  += agpsupport.o
-else
- ifeq ($(CONFIG_AGP),m)
-  lib-objs  += agpsupport.o
- endif
-endif
-
-list-multi  := gamma.o tdfx.o r128.o ffb.o mga.o i810.o
-gamma-objs  := gamma_drv.o  gamma_dma.o
-tdfx-objs   := tdfx_drv.o                 tdfx_context.o
-r128-objs   := r128_drv.o   r128_cce.o    r128_context.o r128_bufs.o r128_state.o
-ffb-objs    := ffb_drv.o                  ffb_context.o
-mga-objs    := mga_drv.o    mga_dma.o     mga_context.o  mga_bufs.o  mga_state.o
-i810-objs   := i810_drv.o   i810_dma.o    i810_context.o i810_bufs.o
-radeon-objs := radeon_drv.o radeon_cp.o   radeon_context.o radeon_bufs.o radeon_state.o
+export-objs	:= gamma_drv.o tdfx_drv.o r128_drv.o mga_drv.o i810_drv.o \
+		   ffb_drv.o
+list-multi	:= gamma.o tdfx.o r128.o mga.o i810.o ffb.o
+
+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
+i810-objs   := i810_drv.o i810_dma.o
+radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o
+ffb-objs    := ffb_drv.o ffb_context.o
 
 obj-$(CONFIG_DRM_GAMMA) += gamma.o
-obj-$(CONFIG_DRM_TDFX)  += tdfx.o
-obj-$(CONFIG_DRM_R128)  += r128.o
+obj-$(CONFIG_DRM_TDFX)	+= tdfx.o
+obj-$(CONFIG_DRM_R128)	+= r128.o
 obj-$(CONFIG_DRM_RADEON)+= radeon.o
+obj-$(CONFIG_DRM_MGA)	+= mga.o
+obj-$(CONFIG_DRM_I810)	+= i810.o
 obj-$(CONFIG_DRM_FFB)   += ffb.o
-obj-$(CONFIG_DRM_MGA)   += mga.o
-obj-$(CONFIG_DRM_I810)  += i810.o
-
-
-# When linking into the kernel, link the library just once. 
-# If making modules, we include the library into each module
-
-lib-objs-mod := $(patsubst %.o,%-mod.o,$(lib-objs))
-
-ifdef MAKING_MODULES
-  lib = drmlib-mod.a
-else
-  obj-y += drmlib.a
-endif
 
 include $(TOPDIR)/Rules.make
-
-$(patsubst %.o,%.c,$(lib-objs-mod)): 
-	@ln -sf $(subst -mod,,$@) $@
-
-drmlib-mod.a: $(lib-objs-mod)
-	rm -f $@
-	$(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-objs-mod)
-
-drmlib.a: $(lib-objs)
-	rm -f $@
-	$(AR) $(EXTRA_ARFLAGS) rcs $@ $(lib-objs)
 
 gamma.o: $(gamma-objs) $(lib)
 	$(LD) -r -o $@ $(gamma-objs) $(lib)
diff -urN linux-2.4.8-pre6/drivers/char/drm/agpsupport.c linux/drivers/char/drm/agpsupport.c
--- linux-2.4.8-pre6/drivers/char/drm/agpsupport.c	Mon Dec  3 22:59:36 2001
+++ linux/drivers/char/drm/agpsupport.c	Wed Dec 31 16:00:00 1969
@@ -1,339 +0,0 @@
-/* agpsupport.c -- DRM support for AGP/GART backend -*- linux-c -*-
- * Created: Mon Dec 13 09:56:45 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.
- * 
- * Author: Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include <linux/module.h>
-#if LINUX_VERSION_CODE < 0x020400
-#include "agpsupport-pre24.h"
-#else
-#define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp")
-#define DRM_AGP_PUT inter_module_put("drm_agp")
-#endif
-
-static const drm_agp_t *drm_agp = NULL;
-
-int drm_agp_info(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;
-	agp_kern_info    *kern;
-	drm_agp_info_t   info;
-
-	if (!dev->agp->acquired || !drm_agp->copy_info) return -EINVAL;
-
-	kern                   = &dev->agp->agp_info;
-	info.agp_version_major = kern->version.major;
-	info.agp_version_minor = kern->version.minor;
-	info.mode              = kern->mode;
-	info.aperture_base     = kern->aper_base;
-	info.aperture_size     = kern->aper_size * 1024 * 1024;
-	info.memory_allowed    = kern->max_memory << PAGE_SHIFT;
-	info.memory_used       = kern->current_memory << PAGE_SHIFT;
-	info.id_vendor         = kern->device->vendor;
-	info.id_device         = kern->device->device;
-
-	if (copy_to_user((drm_agp_info_t *)arg, &info, sizeof(info)))
-		return -EFAULT;
-	return 0;
-}
-
-int drm_agp_acquire(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;
-	int              retcode;
-
-	if (dev->agp->acquired || !drm_agp->acquire) return -EINVAL;
-	if ((retcode = drm_agp->acquire())) return retcode;
-	dev->agp->acquired = 1;
-	return 0;
-}
-
-int drm_agp_release(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;
-
-	if (!dev->agp->acquired || !drm_agp->release) return -EINVAL;
-	drm_agp->release();
-	dev->agp->acquired = 0;
-	return 0;
-	
-}
-
-void _drm_agp_release(void)
-{
-	if (drm_agp->release) drm_agp->release();
-}
-
-int drm_agp_enable(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_agp_mode_t   mode;
-
-	if (!dev->agp->acquired || !drm_agp->enable) return -EINVAL;
-
-	if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
-		return -EFAULT;
-	
-	dev->agp->mode    = mode.mode;
-	drm_agp->enable(mode.mode);
-	dev->agp->base    = dev->agp->agp_info.aper_base;
-	dev->agp->enabled = 1;
-	return 0;
-}
-
-int drm_agp_alloc(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_agp_buffer_t request;
-	drm_agp_mem_t    *entry;
-	agp_memory       *memory;
-	unsigned long    pages;
-	u32 		 type;
-	if (!dev->agp->acquired) return -EINVAL;
-	if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
-		return -EFAULT;
-	if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
-		return -ENOMEM;
-   
-   	memset(entry, 0, sizeof(*entry));
-
-	pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
-	type = (u32) request.type;
-
-	if (!(memory = drm_alloc_agp(pages, type))) {
-		drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-		return -ENOMEM;
-	}
-	
-	entry->handle    = (unsigned long)memory->memory;
-	entry->memory    = memory;
-	entry->bound     = 0;
-	entry->pages     = pages;
-	entry->prev      = NULL;
-	entry->next      = dev->agp->memory;
-	if (dev->agp->memory) dev->agp->memory->prev = entry;
-	dev->agp->memory = entry;
-
-	request.handle   = entry->handle;
-        request.physical = memory->physical;
-
-	if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) {
-		dev->agp->memory       = entry->next;
-		dev->agp->memory->prev = NULL;
-		drm_free_agp(memory, pages);
-		drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-		return -EFAULT;
-	}
-	return 0;
-}
-
-static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t *dev,
-					   unsigned long handle)
-{
-	drm_agp_mem_t *entry;
-
-	for (entry = dev->agp->memory; entry; entry = entry->next) {
-		if (entry->handle == handle) return entry;
-	}
-	return NULL;
-}
-
-int drm_agp_unbind(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_agp_binding_t request;
-	drm_agp_mem_t     *entry;
-
-	if (!dev->agp->acquired) return -EINVAL;
-	if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
-		return -EFAULT;
-	if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
-		return -EINVAL;
-	if (!entry->bound) return -EINVAL;
-	return drm_unbind_agp(entry->memory);
-}
-
-int drm_agp_bind(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_agp_binding_t request;
-	drm_agp_mem_t     *entry;
-	int               retcode;
-	int               page;
-	
-	if (!dev->agp->acquired || !drm_agp->bind_memory) return -EINVAL;
-	if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
-		return -EFAULT;
-	if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
-		return -EINVAL;
-	if (entry->bound) return -EINVAL;
-	page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
-	if ((retcode = drm_bind_agp(entry->memory, page))) return retcode;
-	entry->bound = dev->agp->base + (page << PAGE_SHIFT);
-	DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", 
-		  dev->agp->base, entry->bound);
-	return 0;
-}
-
-int drm_agp_free(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_agp_buffer_t request;
-	drm_agp_mem_t    *entry;
-	
-	if (!dev->agp->acquired) return -EINVAL;
-	if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
-		return -EFAULT;
-	if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
-		return -EINVAL;
-	if (entry->bound) drm_unbind_agp(entry->memory);
-   
-	if (entry->prev) entry->prev->next = entry->next;
-	else             dev->agp->memory  = entry->next;
-	if (entry->next) entry->next->prev = entry->prev;
-	drm_free_agp(entry->memory, entry->pages);
-	drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-	return 0;
-}
-
-drm_agp_head_t *drm_agp_init(void)
-{
-	drm_agp_head_t *head         = NULL;
-
-	drm_agp = DRM_AGP_GET;
-	if (drm_agp) {
-		if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
-			return NULL;
-		memset((void *)head, 0, sizeof(*head));
-		drm_agp->copy_info(&head->agp_info);
-		if (head->agp_info.chipset == NOT_SUPPORTED) {
-			drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
-			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;
-
-#if LINUX_VERSION_CODE >= 0x020400
-		case INTEL_I840:	head->chipset = "Intel i840";    break;
-#endif
-
-		case VIA_GENERIC:	head->chipset = "VIA";           break;
-		case VIA_VP3:		head->chipset = "VIA VP3";       break;
-		case VIA_MVP3:		head->chipset = "VIA MVP3";      break;
-
-#if LINUX_VERSION_CODE >= 0x020400
-		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;
-#endif
-
-		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 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_M1647: 	head->chipset = "ALi M1647";	 break;
-		case ALI_M1651: 	head->chipset = "ALi M1651";	 break;
-		case SVWRKS_GENERIC:	head->chipset = "Serverworks Generic";
-			break;
-		case SVWRKS_HE: 	head->chipset = "Serverworks HE"; break;
-		case SVWRKS_LE: 	head->chipset = "Serverworks LE"; break;
-
-		default:		head->chipset = "Unknown";       break;
-		}
-		DRM_INFO("AGP %d.%d on %s @ 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);
-	}
-	return head;
-}
-
-void drm_agp_uninit(void)
-{
-	DRM_AGP_PUT;
-	drm_agp = NULL;
-}
-
-agp_memory *drm_agp_allocate_memory(size_t pages, u32 type)
-{
-	if (!drm_agp->allocate_memory) return NULL;
-	return drm_agp->allocate_memory(pages, type);
-}
-
-int drm_agp_free_memory(agp_memory *handle)
-{
-	if (!handle || !drm_agp->free_memory) return 0;
-	drm_agp->free_memory(handle);
-	return 1;
-}
-
-int drm_agp_bind_memory(agp_memory *handle, off_t start)
-{
-	if (!handle || !drm_agp->bind_memory) return -EINVAL;
-	return drm_agp->bind_memory(handle, start);
-}
-
-int drm_agp_unbind_memory(agp_memory *handle)
-{
-	if (!handle || !drm_agp->unbind_memory) return -EINVAL;
-	return drm_agp->unbind_memory(handle);
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/ati_pcigart.h linux/drivers/char/drm/ati_pcigart.h
--- linux-2.4.8-pre6/drivers/char/drm/ati_pcigart.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/ati_pcigart.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,138 @@
+/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
+ * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+#if PAGE_SIZE == 8192
+# define ATI_PCIGART_TABLE_ORDER 	2
+# define ATI_PCIGART_TABLE_PAGES 	(1 << 2)
+#elif PAGE_SIZE == 4096
+# define ATI_PCIGART_TABLE_ORDER 	3
+# define ATI_PCIGART_TABLE_PAGES 	(1 << 3)
+#elif
+# error - PAGE_SIZE not 8K or 4K
+#endif
+
+# define ATI_MAX_PCIGART_PAGES		8192	/* 32 MB aperture, 4K pages */
+# define ATI_PCIGART_PAGE_SIZE		4096	/* PCI GART page size */
+
+static unsigned long DRM(ati_alloc_pcigart_table)( void )
+{
+	unsigned long address;
+	struct page *page;
+	int i;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	address = __get_free_pages( GFP_KERNEL, ATI_PCIGART_TABLE_ORDER );
+	if ( address == 0UL ) {
+		return 0;
+	}
+
+	page = virt_to_page( address );
+
+	for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+		atomic_inc( &page->count );
+		SetPageReserved( page );
+	}
+
+	DRM_DEBUG( "%s: returning 0x%08lx\n", __FUNCTION__, address );
+	return address;
+}
+
+static void DRM(ati_free_pcigart_table)( unsigned long address )
+{
+	struct page *page;
+	int i;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( !address ) return;
+
+	page = virt_to_page( address );
+
+	for ( i = 0 ; i <= ATI_PCIGART_TABLE_PAGES ; i++, page++ ) {
+		atomic_dec( &page->count );
+		ClearPageReserved( page );
+	}
+
+	free_pages( address, ATI_PCIGART_TABLE_ORDER );
+}
+
+unsigned long DRM(ati_pcigart_init)( drm_device_t *dev )
+{
+	drm_sg_mem_t *entry = dev->sg;
+	unsigned long address;
+	unsigned long pages;
+	u32 *pci_gart, page_base;
+	int i, j;
+
+	if ( !entry ) {
+		DRM_ERROR( "no scatter/gather memory!\n" );
+		return 0;
+	}
+
+	address = DRM(ati_alloc_pcigart_table)();
+	if ( !address ) {
+		DRM_ERROR( "cannot allocate PCI GART page!\n" );
+		return 0;
+	}
+
+	pci_gart = (u32 *)address;
+
+	pages = ( entry->pages <= ATI_MAX_PCIGART_PAGES )
+		? entry->pages : ATI_MAX_PCIGART_PAGES;
+
+	memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );
+
+	for ( i = 0 ; i < pages ; i++ ) {
+		page_base = virt_to_bus( entry->pagelist[i]->virtual );
+		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
+			*pci_gart++ = cpu_to_le32( page_base );
+			page_base += ATI_PCIGART_PAGE_SIZE;
+		}
+	}
+
+#if __i386__
+	asm volatile ( "wbinvd" ::: "memory" );
+#else
+	mb();
+#endif
+
+	return address;
+}
+
+int DRM(ati_pcigart_cleanup)( unsigned long address )
+{
+
+	if ( address ) {
+		DRM(ati_free_pcigart_table)( address );
+	}
+
+	return 0;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/auth.c linux/drivers/char/drm/auth.c
--- linux-2.4.8-pre6/drivers/char/drm/auth.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/char/drm/auth.c	Wed Dec 31 16:00:00 1969
@@ -1,162 +0,0 @@
-/* auth.c -- IOCTLs for authentication -*- linux-c -*-
- * Created: Tue Feb  2 08:37:54 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>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-static int drm_hash_magic(drm_magic_t magic)
-{
-	return magic & (DRM_HASH_SIZE-1);
-}
-
-static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
-{
-	drm_file_t	  *retval = NULL;
-	drm_magic_entry_t *pt;
-	int		  hash	  = drm_hash_magic(magic);
-
-	down(&dev->struct_sem);
-	for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
-		if (pt->magic == magic) {
-			retval = pt->priv;
-			break;
-		}
-	}
-	up(&dev->struct_sem);
-	return retval;
-}
-
-int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
-{
-	int		  hash;
-	drm_magic_entry_t *entry;
-	
-	DRM_DEBUG("%d\n", magic);
-	
-	hash	     = drm_hash_magic(magic);
-	entry	     = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
-	if (!entry) return -ENOMEM;
-	entry->magic = magic;
-	entry->priv  = priv;
-	entry->next  = NULL;
-
-	down(&dev->struct_sem);
-	if (dev->magiclist[hash].tail) {
-		dev->magiclist[hash].tail->next = entry;
-		dev->magiclist[hash].tail	= entry;
-	} else {
-		dev->magiclist[hash].head	= entry;
-		dev->magiclist[hash].tail	= entry;
-	}
-	up(&dev->struct_sem);
-	
-	return 0;
-}
-
-int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
-{
-	drm_magic_entry_t *prev = NULL;
-	drm_magic_entry_t *pt;
-	int		  hash;
-	
-	DRM_DEBUG("%d\n", magic);
-	hash = drm_hash_magic(magic);
-	
-	down(&dev->struct_sem);
-	for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
-		if (pt->magic == magic) {
-			if (dev->magiclist[hash].head == pt) {
-				dev->magiclist[hash].head = pt->next;
-			}
-			if (dev->magiclist[hash].tail == pt) {
-				dev->magiclist[hash].tail = prev;
-			}
-			if (prev) {
-				prev->next = pt->next;
-			}
-			up(&dev->struct_sem);
-			return 0;
-		}
-	}
-	up(&dev->struct_sem);
-
-	drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-	
-	return -EINVAL;
-}
-
-int drm_getmagic(struct inode *inode, struct file *filp, unsigned int cmd,
-		 unsigned long arg)
-{
-	static drm_magic_t sequence = 0;
-	static spinlock_t  lock	    = SPIN_LOCK_UNLOCKED;
-	drm_file_t	   *priv    = filp->private_data;
-	drm_device_t	   *dev	    = priv->dev;
-	drm_auth_t	   auth;
-
-				/* Find unique magic */
-	if (priv->magic) {
-		auth.magic = priv->magic;
-	} else {
-		do {
-			spin_lock(&lock);
-			if (!sequence) ++sequence; /* reserve 0 */
-			auth.magic = sequence++;
-			spin_unlock(&lock);
-		} while (drm_find_file(dev, auth.magic));
-		priv->magic = auth.magic;
-		drm_add_magic(dev, priv, auth.magic);
-	}
-	
-	DRM_DEBUG("%u\n", auth.magic);
-	if (copy_to_user((drm_auth_t *)arg, &auth, sizeof(auth)))
-		return -EFAULT;
-	return 0;
-}
-
-int drm_authmagic(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_auth_t	   auth;
-	drm_file_t	   *file;
-
-	if (copy_from_user(&auth, (drm_auth_t *)arg, sizeof(auth)))
-		return -EFAULT;
-	DRM_DEBUG("%u\n", auth.magic);
-	if ((file = drm_find_file(dev, auth.magic))) {
-		file->authenticated = 1;
-		drm_remove_magic(dev, auth.magic);
-		return 0;
-	}
-	return -EINVAL;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/bufs.c linux/drivers/char/drm/bufs.c
--- linux-2.4.8-pre6/drivers/char/drm/bufs.c	Mon Jul 16 15:13:32 2001
+++ linux/drivers/char/drm/bufs.c	Wed Dec 31 16:00:00 1969
@@ -1,543 +0,0 @@
-/* bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
- * Created: Tue Feb  2 08:37:54 1999 by faith@precisioninsight.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * 
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include <linux/config.h>
-#include "drmP.h"
-#include "linux/un.h"
-
-				/* Compute order.  Can be made faster. */
-int drm_order(unsigned long size)
-{
-	int	      order;
-	unsigned long tmp;
-
-	for (order = 0, tmp = size; tmp >>= 1; ++order);
-	if (size & ~(1 << order)) ++order;
-	return order;
-}
-
-int drm_addmap(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_map_t	*map;
-	
-	if (!(filp->f_mode & 3)) return -EACCES; /* Require read/write */
-
-	map	     = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
-	if (!map) return -ENOMEM;
-	if (copy_from_user(map, (drm_map_t *)arg, sizeof(*map))) {
-		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		return -EFAULT;
-	}
-
-	DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n",
-		  map->offset, map->size, map->type);
-	if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
-		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		return -EINVAL;
-	}
-	map->mtrr   = -1;
-	map->handle = 0;
-
-	switch (map->type) {
-	case _DRM_REGISTERS:
-	case _DRM_FRAME_BUFFER:
-#ifndef __sparc__
-		if (map->offset + map->size < map->offset
-		    || map->offset < virt_to_phys(high_memory)) {
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-			return -EINVAL;
-		}
-#endif
-#ifdef CONFIG_MTRR
-		if (map->type == _DRM_FRAME_BUFFER
-		    || (map->flags & _DRM_WRITE_COMBINING)) {
-			map->mtrr = mtrr_add(map->offset, map->size,
-					     MTRR_TYPE_WRCOMB, 1);
-		}
-#endif
-		map->handle = drm_ioremap(map->offset, map->size);
-		break;
-			
-
-	case _DRM_SHM:
-		map->handle = (void *)drm_alloc_pages(drm_order(map->size)
-						      - PAGE_SHIFT,
-						      DRM_MEM_SAREA);
-		DRM_DEBUG("%ld %d %p\n", map->size, drm_order(map->size),
-			  map->handle);
-		if (!map->handle) {
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-			return -ENOMEM;
-		}
-		map->offset = (unsigned long)map->handle;
-		if (map->flags & _DRM_CONTAINS_LOCK) {
-			dev->lock.hw_lock = map->handle; /* Pointer to lock */
-		}
-		break;
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	case _DRM_AGP:
-		map->offset = map->offset + dev->agp->base;
-		break;
-#endif
-	default:
-		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		return -EINVAL;
-	}
-
-	down(&dev->struct_sem);
-	if (dev->maplist) {
-		++dev->map_count;
-		dev->maplist = drm_realloc(dev->maplist,
-					   (dev->map_count-1)
-					   * sizeof(*dev->maplist),
-					   dev->map_count
-					   * sizeof(*dev->maplist),
-					   DRM_MEM_MAPS);
-	} else {
-		dev->map_count = 1;
-		dev->maplist = drm_alloc(dev->map_count*sizeof(*dev->maplist),
-					 DRM_MEM_MAPS);
-	}
-	dev->maplist[dev->map_count-1] = map;
-	up(&dev->struct_sem);
-
-	if (copy_to_user((drm_map_t *)arg, map, sizeof(*map)))
-		return -EFAULT;
-	if (map->type != _DRM_SHM) {
-		if (copy_to_user(&((drm_map_t *)arg)->handle,
-				 &map->offset,
-				 sizeof(map->offset)))
-			return -EFAULT;
-	}		
-	return 0;
-}
-
-int drm_addbufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_desc_t	 request;
-	int		 count;
-	int		 order;
-	int		 size;
-	int		 total;
-	int		 page_order;
-	drm_buf_entry_t	 *entry;
-	unsigned long	 page;
-	drm_buf_t	 *buf;
-	int		 alignment;
-	unsigned long	 offset;
-	int		 i;
-	int		 byte_count;
-	int		 page_count;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	count	   = request.count;
-	order	   = drm_order(request.size);
-	size	   = 1 << order;
-	
-	DRM_DEBUG("count = %d, size = %d (%d), order = %d, queue_count = %d\n",
-		  request.count, request.size, size, order, dev->queue_count);
-
-	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-	if (dev->queue_count) return -EBUSY; /* Not while in use */
-
-	alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
-	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-	total	   = PAGE_SIZE << page_order;
-
-	spin_lock(&dev->count_lock);
-	if (dev->buf_use) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	atomic_inc(&dev->buf_alloc);
-	spin_unlock(&dev->count_lock);
-	
-	down(&dev->struct_sem);
-	entry = &dma->bufs[order];
-	if (entry->buf_count) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;	/* May only call once for each order */
-	}
-	
-	if(count < 0 || count > 4096)
-	{
-		up(&dev->struct_sem);
-		return -EINVAL;
-	}
-	
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
-	if (!entry->buflist) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;
-	}
-	memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
-	entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
-				   DRM_MEM_SEGS);
-	if (!entry->seglist) {
-		drm_free(entry->buflist,
-			 count * sizeof(*entry->buflist),
-			 DRM_MEM_BUFS);
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;
-	}
-	memset(entry->seglist, 0, count * sizeof(*entry->seglist));
-
-	dma->pagelist = drm_realloc(dma->pagelist,
-				    dma->page_count * sizeof(*dma->pagelist),
-				    (dma->page_count + (count << page_order))
-				    * sizeof(*dma->pagelist),
-				    DRM_MEM_PAGES);
-	DRM_DEBUG("pagelist: %d entries\n",
-		  dma->page_count + (count << page_order));
-
-
-	entry->buf_size	  = size;
-	entry->page_order = page_order;
-	byte_count	  = 0;
-	page_count	  = 0;
-	while (entry->buf_count < count) {
-		if (!(page = drm_alloc_pages(page_order, DRM_MEM_DMA))) break;
-		entry->seglist[entry->seg_count++] = page;
-		for (i = 0; i < (1 << page_order); i++) {
-			DRM_DEBUG("page %d @ 0x%08lx\n",
-				  dma->page_count + page_count,
-				  page + PAGE_SIZE * i);
-			dma->pagelist[dma->page_count + page_count++]
-				= page + PAGE_SIZE * i;
-		}
-		for (offset = 0;
-		     offset + size <= total && entry->buf_count < count;
-		     offset += alignment, ++entry->buf_count) {
-			buf	     = &entry->buflist[entry->buf_count];
-			buf->idx     = dma->buf_count + entry->buf_count;
-			buf->total   = alignment;
-			buf->order   = order;
-			buf->used    = 0;
-			buf->offset  = (dma->byte_count + byte_count + offset);
-			buf->address = (void *)(page + offset);
-			buf->next    = NULL;
-			buf->waiting = 0;
-			buf->pending = 0;
-			init_waitqueue_head(&buf->dma_wait);
-			buf->pid     = 0;
-#if DRM_DMA_HISTOGRAM
-			buf->time_queued     = 0;
-			buf->time_dispatched = 0;
-			buf->time_completed  = 0;
-			buf->time_freed	     = 0;
-#endif
-			DRM_DEBUG("buffer %d @ %p\n",
-				  entry->buf_count, buf->address);
-		}
-		byte_count += PAGE_SIZE << page_order;
-	}
-
-	dma->buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist),
-				   DRM_MEM_BUFS);
-	for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
-		dma->buflist[i] = &entry->buflist[i - dma->buf_count];
-
-	dma->buf_count	+= entry->buf_count;
-	dma->seg_count	+= entry->seg_count;
-	dma->page_count += entry->seg_count << page_order;
-	dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
-	
-	drm_freelist_create(&entry->freelist, entry->buf_count);
-	for (i = 0; i < entry->buf_count; i++) {
-		drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
-	}
-	
-	up(&dev->struct_sem);
-
-	request.count = entry->buf_count;
-	request.size  = size;
-
-	if (copy_to_user((drm_buf_desc_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-	
-	atomic_dec(&dev->buf_alloc);
-	return 0;
-}
-
-int drm_infobufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_info_t	 request;
-	int		 i;
-	int		 count;
-
-	if (!dma) return -EINVAL;
-
-	spin_lock(&dev->count_lock);
-	if (atomic_read(&dev->buf_alloc)) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	++dev->buf_use;		/* Can't allocate more after this call */
-	spin_unlock(&dev->count_lock);
-
-	if (copy_from_user(&request,
-			   (drm_buf_info_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
-		if (dma->bufs[i].buf_count) ++count;
-	}
-	
-	DRM_DEBUG("count = %d\n", count);
-	
-	if (request.count >= count) {
-		for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
-			if (dma->bufs[i].buf_count) {
-				if (copy_to_user(&request.list[count].count,
-						 &dma->bufs[i].buf_count,
-						 sizeof(dma->bufs[0]
-							.buf_count)) ||
-				    copy_to_user(&request.list[count].size,
-						 &dma->bufs[i].buf_size,
-						 sizeof(dma->bufs[0].buf_size)) ||
-				    copy_to_user(&request.list[count].low_mark,
-						 &dma->bufs[i]
-						 .freelist.low_mark,
-						 sizeof(dma->bufs[0]
-							.freelist.low_mark)) ||
-				    copy_to_user(&request.list[count]
-						 .high_mark,
-						 &dma->bufs[i]
-						 .freelist.high_mark,
-						 sizeof(dma->bufs[0]
-							.freelist.high_mark)))
-					return -EFAULT;
-
-				DRM_DEBUG("%d %d %d %d %d\n",
-					  i,
-					  dma->bufs[i].buf_count,
-					  dma->bufs[i].buf_size,
-					  dma->bufs[i].freelist.low_mark,
-					  dma->bufs[i].freelist.high_mark);
-				++count;
-			}
-		}
-	}
-	request.count = count;
-
-	if (copy_to_user((drm_buf_info_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-	
-	return 0;
-}
-
-int drm_markbufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_desc_t	 request;
-	int		 order;
-	drm_buf_entry_t	 *entry;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	DRM_DEBUG("%d, %d, %d\n",
-		  request.size, request.low_mark, request.high_mark);
-	order = drm_order(request.size);
-	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-	entry = &dma->bufs[order];
-
-	if (request.low_mark < 0 || request.low_mark > entry->buf_count)
-		return -EINVAL;
-	if (request.high_mark < 0 || request.high_mark > entry->buf_count)
-		return -EINVAL;
-
-	entry->freelist.low_mark  = request.low_mark;
-	entry->freelist.high_mark = request.high_mark;
-	
-	return 0;
-}
-
-int drm_freebufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_free_t	 request;
-	int		 i;
-	int		 idx;
-	drm_buf_t	 *buf;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_free_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	DRM_DEBUG("%d\n", request.count);
-	for (i = 0; i < request.count; i++) {
-		if (copy_from_user(&idx,
-				   &request.list[i],
-				   sizeof(idx)))
-			return -EFAULT;
-		if (idx < 0 || idx >= dma->buf_count) {
-			DRM_ERROR("Index %d (of %d max)\n",
-				  idx, dma->buf_count - 1);
-			return -EINVAL;
-		}
-		buf = dma->buflist[idx];
-		if (buf->pid != current->pid) {
-			DRM_ERROR("Process %d freeing buffer owned by %d\n",
-				  current->pid, buf->pid);
-			return -EINVAL;
-		}
-		drm_free_buffer(dev, buf);
-	}
-	
-	return 0;
-}
-
-int drm_mapbufs(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_device_dma_t *dma	 = dev->dma;
-	int		 retcode = 0;
-	const int	 zero	 = 0;
-	unsigned long	 virtual;
-	unsigned long	 address;
-	drm_buf_map_t	 request;
-	int		 i;
-
-	if (!dma) return -EINVAL;
-	
-	DRM_DEBUG("\n");
-
-	spin_lock(&dev->count_lock);
-	if (atomic_read(&dev->buf_alloc)) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	++dev->buf_use;		/* Can't allocate more after this call */
-	spin_unlock(&dev->count_lock);
-
-	if (copy_from_user(&request,
-			   (drm_buf_map_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	if (request.count >= dma->buf_count) {
-		down_write(&current->mm->mmap_sem);
-		virtual = do_mmap(filp, 0, dma->byte_count,
-				  PROT_READ|PROT_WRITE, MAP_SHARED, 0);
-		up_write(&current->mm->mmap_sem);
-		if (virtual > -1024UL) {
-				/* Real error */
-			retcode = (signed long)virtual;
-			goto done;
-		}
-		request.virtual = (void *)virtual;
-
-		for (i = 0; i < dma->buf_count; i++) {
-			if (copy_to_user(&request.list[i].idx,
-					 &dma->buflist[i]->idx,
-					 sizeof(request.list[0].idx))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			if (copy_to_user(&request.list[i].total,
-					 &dma->buflist[i]->total,
-					 sizeof(request.list[0].total))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			if (copy_to_user(&request.list[i].used,
-					 &zero,
-					 sizeof(zero))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			address = virtual + dma->buflist[i]->offset;
-			if (copy_to_user(&request.list[i].address,
-					 &address,
-					 sizeof(address))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-		}
-	}
-done:
-	request.count = dma->buf_count;
-	DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
-
-	if (copy_to_user((drm_buf_map_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-
-	return retcode;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/context.c linux/drivers/char/drm/context.c
--- linux-2.4.8-pre6/drivers/char/drm/context.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/char/drm/context.c	Wed Dec 31 16:00:00 1969
@@ -1,321 +0,0 @@
-/* context.c -- IOCTLs for contexts and DMA queues -*- linux-c -*-
- * Created: Tue Feb  2 08:37:54 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>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-static int drm_init_queue(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx)
-{
-	DRM_DEBUG("\n");
-	
-	if (atomic_read(&q->use_count) != 1
-	    || atomic_read(&q->finalization)
-	    || atomic_read(&q->block_count)) {
-		DRM_ERROR("New queue is already in use: u%d f%d b%d\n",
-			  atomic_read(&q->use_count),
-			  atomic_read(&q->finalization),
-			  atomic_read(&q->block_count));
-	}
-		  
-	atomic_set(&q->finalization,  0);
-	atomic_set(&q->block_count,   0);
-	atomic_set(&q->block_read,    0);
-	atomic_set(&q->block_write,   0);
-	atomic_set(&q->total_queued,  0);
-	atomic_set(&q->total_flushed, 0);
-	atomic_set(&q->total_locks,   0);
-
-	init_waitqueue_head(&q->write_queue);
-	init_waitqueue_head(&q->read_queue);
-	init_waitqueue_head(&q->flush_queue);
-
-	q->flags = ctx->flags;
-
-	drm_waitlist_create(&q->waitlist, dev->dma->buf_count);
-
-	return 0;
-}
-
-
-/* drm_alloc_queue:
-PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not
-	disappear (so all deallocation must be done after IOCTLs are off)
-     2) dev->queue_count < dev->queue_slots
-     3) dev->queuelist[i].use_count == 0 and
-	dev->queuelist[i].finalization == 0 if i not in use 
-POST: 1) dev->queuelist[i].use_count == 1
-      2) dev->queue_count < dev->queue_slots */
-		
-static int drm_alloc_queue(drm_device_t *dev)
-{
-	int	    i;
-	drm_queue_t *queue;
-	int	    oldslots;
-	int	    newslots;
-				/* Check for a free queue */
-	for (i = 0; i < dev->queue_count; i++) {
-		atomic_inc(&dev->queuelist[i]->use_count);
-		if (atomic_read(&dev->queuelist[i]->use_count) == 1
-		    && !atomic_read(&dev->queuelist[i]->finalization)) {
-			DRM_DEBUG("%d (free)\n", i);
-			return i;
-		}
-		atomic_dec(&dev->queuelist[i]->use_count);
-	}
-				/* Allocate a new queue */
-	
-	queue = drm_alloc(sizeof(*queue), DRM_MEM_QUEUES);
-	if(queue == NULL)
-		return -ENOMEM;	
-
-	memset(queue, 0, sizeof(*queue));
-	down(&dev->struct_sem);
-	atomic_set(&queue->use_count, 1);
-	
-	++dev->queue_count;
-	if (dev->queue_count >= dev->queue_slots) {
-		oldslots = dev->queue_slots * sizeof(*dev->queuelist);
-		if (!dev->queue_slots) dev->queue_slots = 1;
-		dev->queue_slots *= 2;
-		newslots = dev->queue_slots * sizeof(*dev->queuelist);
-
-		dev->queuelist = drm_realloc(dev->queuelist,
-					     oldslots,
-					     newslots,
-					     DRM_MEM_QUEUES);
-		if (!dev->queuelist) {
-			up(&dev->struct_sem);
-			DRM_DEBUG("out of memory\n");
-			return -ENOMEM;
-		}
-	}
-	dev->queuelist[dev->queue_count-1] = queue;
-	
-	up(&dev->struct_sem);
-	DRM_DEBUG("%d (new)\n", dev->queue_count - 1);
-	return dev->queue_count - 1;
-}
-
-int drm_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
-{
-	drm_ctx_res_t	res;
-	drm_ctx_t	ctx;
-	int		i;
-
-	DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
-	if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
-		return -EFAULT;
-	if (res.count >= DRM_RESERVED_CONTEXTS) {
-		memset(&ctx, 0, sizeof(ctx));
-		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-			ctx.handle = i;
-			if (copy_to_user(&res.contexts[i],
-					 &i,
-					 sizeof(i)))
-				return -EFAULT;
-		}
-	}
-	res.count = DRM_RESERVED_CONTEXTS;
-	if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
-		return -EFAULT;
-	return 0;
-}
-
-
-int drm_addctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	if ((ctx.handle = drm_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
-				/* Init kernel's context and get a new one. */
-		drm_init_queue(dev, dev->queuelist[ctx.handle], &ctx);
-		ctx.handle = drm_alloc_queue(dev);
-	}
-	drm_init_queue(dev, dev->queuelist[ctx.handle], &ctx);
-	DRM_DEBUG("%d\n", ctx.handle);
-	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int drm_modctx(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_t	ctx;
-	drm_queue_t	*q;
-		
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	
-	DRM_DEBUG("%d\n", ctx.handle);
-	
-	if (ctx.handle < 0 || ctx.handle >= dev->queue_count) return -EINVAL;
-	q = dev->queuelist[ctx.handle];
-	
-	atomic_inc(&q->use_count);
-	if (atomic_read(&q->use_count) == 1) {
-				/* No longer in use */
-		atomic_dec(&q->use_count);
-		return -EINVAL;
-	}
-
-	if (DRM_BUFCOUNT(&q->waitlist)) {
-		atomic_dec(&q->use_count);
-		return -EBUSY;
-	}
-	
-	q->flags = ctx.flags;
-	
-	atomic_dec(&q->use_count);
-	return 0;
-}
-
-int drm_getctx(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_t	ctx;
-	drm_queue_t	*q;
-		
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	
-	DRM_DEBUG("%d\n", ctx.handle);
-	
-	if (ctx.handle >= dev->queue_count) return -EINVAL;
-	q = dev->queuelist[ctx.handle];
-	
-	atomic_inc(&q->use_count);
-	if (atomic_read(&q->use_count) == 1) {
-				/* No longer in use */
-		atomic_dec(&q->use_count);
-		return -EINVAL;
-	}
-	
-	ctx.flags = q->flags;
-	atomic_dec(&q->use_count);
-	
-	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	
-	return 0;
-}
-
-int drm_switchctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	return drm_context_switch(dev, dev->last_context, ctx.handle);
-}
-
-int drm_newctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	drm_context_switch_complete(dev, ctx.handle);
-
-	return 0;
-}
-
-int drm_rmctx(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_t	ctx;
-	drm_queue_t	*q;
-	drm_buf_t	*buf;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	
-	if (ctx.handle >= dev->queue_count) return -EINVAL;
-	q = dev->queuelist[ctx.handle];
-	
-	atomic_inc(&q->use_count);
-	if (atomic_read(&q->use_count) == 1) {
-				/* No longer in use */
-		atomic_dec(&q->use_count);
-		return -EINVAL;
-	}
-	
-	atomic_inc(&q->finalization); /* Mark queue in finalization state */
-	atomic_sub(2, &q->use_count); /* Mark queue as unused (pending
-					 finalization) */
-
-	while (test_and_set_bit(0, &dev->interrupt_flag)) {
-		schedule();
-		if (signal_pending(current)) {
-			clear_bit(0, &dev->interrupt_flag);
-			return -EINTR;
-		}
-	}
-				/* Remove queued buffers */
-	while ((buf = drm_waitlist_get(&q->waitlist))) {
-		drm_free_buffer(dev, buf);
-	}
-	clear_bit(0, &dev->interrupt_flag);
-	
-				/* Wakeup blocked processes */
-	wake_up_interruptible(&q->read_queue);
-	wake_up_interruptible(&q->write_queue);
-	wake_up_interruptible(&q->flush_queue);
-	
-				/* Finalization over.  Queue is made
-				   available when both use_count and
-				   finalization become 0, which won't
-				   happen until all the waiting processes
-				   stop waiting. */
-	atomic_dec(&q->finalization);
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/ctxbitmap.c linux/drivers/char/drm/ctxbitmap.c
--- linux-2.4.8-pre6/drivers/char/drm/ctxbitmap.c	Fri Jul 21 12:56:44 2000
+++ linux/drivers/char/drm/ctxbitmap.c	Wed Dec 31 16:00:00 1969
@@ -1,85 +0,0 @@
-/* ctxbitmap.c -- Context bitmap management -*- linux-c -*-
- * Created: Thu Jan 6 03:56:42 2000 by jhartmann@precisioninsight.com
- * 
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle)
-{
-	if (ctx_handle < 0) goto failed;
-
-	if (ctx_handle < DRM_MAX_CTXBITMAP) {
-		clear_bit(ctx_handle, dev->ctx_bitmap);
-		return;
-	}
-failed:
-       	DRM_ERROR("Attempt to free invalid context handle: %d\n",
-		  ctx_handle);
-       	return;
-}
-
-int drm_ctxbitmap_next(drm_device_t *dev)
-{
-	int bit;
-
-	bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
-	if (bit < DRM_MAX_CTXBITMAP) {
-		set_bit(bit, dev->ctx_bitmap);
-	   	DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
-		return bit;
-	}
-	return -1;
-}
-
-int drm_ctxbitmap_init(drm_device_t *dev)
-{
-	int i;
-   	int temp;
-
-	dev->ctx_bitmap = (unsigned long *) drm_alloc(PAGE_SIZE, 
-						      DRM_MEM_CTXBITMAP);
-	if(dev->ctx_bitmap == NULL) {
-		return -ENOMEM;
-	}
-	memset((void *) dev->ctx_bitmap, 0, PAGE_SIZE);
-	for(i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-		temp = drm_ctxbitmap_next(dev);
-	   	DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
-	}
-
-	return 0;
-}
-
-void drm_ctxbitmap_cleanup(drm_device_t *dev)
-{
-	drm_free((void *)dev->ctx_bitmap, PAGE_SIZE,
-		 DRM_MEM_CTXBITMAP);
-}
-
diff -urN linux-2.4.8-pre6/drivers/char/drm/dma.c linux/drivers/char/drm/dma.c
--- linux-2.4.8-pre6/drivers/char/drm/dma.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/char/drm/dma.c	Wed Dec 31 16:00:00 1969
@@ -1,546 +0,0 @@
-/* dma.c -- DMA IOCTL and function support -*- linux-c -*-
- * Created: Fri Mar 19 14:30:16 1999 by faith@precisioninsight.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * 
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinuxa.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-#include <linux/interrupt.h>	/* For task queue support */
-
-void drm_dma_setup(drm_device_t *dev)
-{
-	int i;
-	
-	if (!(dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER))) {
-                printk(KERN_ERR "drm_dma_setup: can't drm_alloc dev->dma");
-                return;
-        }       
-	memset(dev->dma, 0, sizeof(*dev->dma));
-	for (i = 0; i <= DRM_MAX_ORDER; i++)
-		memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
-}
-
-void drm_dma_takedown(drm_device_t *dev)
-{
-	drm_device_dma_t  *dma = dev->dma;
-	int		  i, j;
-
-	if (!dma) return;
-	
-				/* Clear dma buffers */
-	for (i = 0; i <= DRM_MAX_ORDER; i++) {
-		if (dma->bufs[i].seg_count) {
-			DRM_DEBUG("order %d: buf_count = %d,"
-				  " seg_count = %d\n",
-				  i,
-				  dma->bufs[i].buf_count,
-				  dma->bufs[i].seg_count);
-			for (j = 0; j < dma->bufs[i].seg_count; j++) {
-				drm_free_pages(dma->bufs[i].seglist[j],
-					       dma->bufs[i].page_order,
-					       DRM_MEM_DMA);
-			}
-			drm_free(dma->bufs[i].seglist,
-				 dma->bufs[i].seg_count
-				 * sizeof(*dma->bufs[0].seglist),
-				 DRM_MEM_SEGS);
-		}
-	   	if(dma->bufs[i].buf_count) {
-		   	for(j = 0; j < dma->bufs[i].buf_count; j++) {
-			   if(dma->bufs[i].buflist[j].dev_private) {
-			      drm_free(dma->bufs[i].buflist[j].dev_private,
-				       dma->bufs[i].buflist[j].dev_priv_size,
-				       DRM_MEM_BUFS);
-			   }
-			}
-		   	drm_free(dma->bufs[i].buflist,
-				 dma->bufs[i].buf_count *
-				 sizeof(*dma->bufs[0].buflist),
-				 DRM_MEM_BUFS);
-		   	drm_freelist_destroy(&dma->bufs[i].freelist);
-		}
-	}
-	
-	if (dma->buflist) {
-		drm_free(dma->buflist,
-			 dma->buf_count * sizeof(*dma->buflist),
-			 DRM_MEM_BUFS);
-	}
-
-	if (dma->pagelist) {
-		drm_free(dma->pagelist,
-			 dma->page_count * sizeof(*dma->pagelist),
-			 DRM_MEM_PAGES);
-	}
-	drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
-	dev->dma = NULL;
-}
-
-#if DRM_DMA_HISTOGRAM
-/* This is slow, but is useful for debugging. */
-int drm_histogram_slot(unsigned long count)
-{
-	int value = DRM_DMA_HISTOGRAM_INITIAL;
-	int slot;
-
-	for (slot = 0;
-	     slot < DRM_DMA_HISTOGRAM_SLOTS;
-	     ++slot, value = DRM_DMA_HISTOGRAM_NEXT(value)) {
-		if (count < value) return slot;
-	}
-	return DRM_DMA_HISTOGRAM_SLOTS - 1;
-}
-
-void drm_histogram_compute(drm_device_t *dev, drm_buf_t *buf)
-{
-	cycles_t queued_to_dispatched;
-	cycles_t dispatched_to_completed;
-	cycles_t completed_to_freed;
-	int	 q2d, d2c, c2f, q2c, q2f;
-	
-	if (buf->time_queued) {
-		queued_to_dispatched	= (buf->time_dispatched
-					   - buf->time_queued);
-		dispatched_to_completed = (buf->time_completed
-					   - buf->time_dispatched);
-		completed_to_freed	= (buf->time_freed
-					   - buf->time_completed);
-
-		q2d = drm_histogram_slot(queued_to_dispatched);
-		d2c = drm_histogram_slot(dispatched_to_completed);
-		c2f = drm_histogram_slot(completed_to_freed);
-
-		q2c = drm_histogram_slot(queued_to_dispatched
-					 + dispatched_to_completed);
-		q2f = drm_histogram_slot(queued_to_dispatched
-					 + dispatched_to_completed
-					 + completed_to_freed);
-		
-		atomic_inc(&dev->histo.total);
-		atomic_inc(&dev->histo.queued_to_dispatched[q2d]);
-		atomic_inc(&dev->histo.dispatched_to_completed[d2c]);
-		atomic_inc(&dev->histo.completed_to_freed[c2f]);
-		
-		atomic_inc(&dev->histo.queued_to_completed[q2c]);
-		atomic_inc(&dev->histo.queued_to_freed[q2f]);
-
-	}
-	buf->time_queued     = 0;
-	buf->time_dispatched = 0;
-	buf->time_completed  = 0;
-	buf->time_freed	     = 0;
-}
-#endif
-
-void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
-{
-	drm_device_dma_t *dma = dev->dma;
-
-	if (!buf) return;
-	
-	buf->waiting  = 0;
-	buf->pending  = 0;
-	buf->pid      = 0;
-	buf->used     = 0;
-#if DRM_DMA_HISTOGRAM
-	buf->time_completed = get_cycles();
-#endif
-	if (waitqueue_active(&buf->dma_wait)) {
-		wake_up_interruptible(&buf->dma_wait);
-	} else {
-				/* If processes are waiting, the last one
-				   to wake will put the buffer on the free
-				   list.  If no processes are waiting, we
-				   put the buffer on the freelist here. */
-		drm_freelist_put(dev, &dma->bufs[buf->order].freelist, buf);
-	}
-}
-
-void drm_reclaim_buffers(drm_device_t *dev, pid_t pid)
-{
-	drm_device_dma_t *dma = dev->dma;
-	int		 i;
-
-	if (!dma) return;
-	for (i = 0; i < dma->buf_count; i++) {
-		if (dma->buflist[i]->pid == pid) {
-			switch (dma->buflist[i]->list) {
-			case DRM_LIST_NONE:
-				drm_free_buffer(dev, dma->buflist[i]);
-				break;
-			case DRM_LIST_WAIT:
-				dma->buflist[i]->list = DRM_LIST_RECLAIM;
-				break;
-			default:
-				/* Buffer already on hardware. */
-				break;
-			}
-		}
-	}
-}
-
-int drm_context_switch(drm_device_t *dev, int old, int new)
-{
-	char	    buf[64];
-	drm_queue_t *q;
-
-	atomic_inc(&dev->total_ctx);
-
-	if (test_and_set_bit(0, &dev->context_flag)) {
-		DRM_ERROR("Reentering -- FIXME\n");
-		return -EBUSY;
-	}
-
-#if DRM_DMA_HISTOGRAM
-	dev->ctx_start = get_cycles();
-#endif
-	
-	DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
-	if (new >= dev->queue_count) {
-		clear_bit(0, &dev->context_flag);
-		return -EINVAL;
-	}
-
-	if (new == dev->last_context) {
-		clear_bit(0, &dev->context_flag);
-		return 0;
-	}
-	
-	q = dev->queuelist[new];
-	atomic_inc(&q->use_count);
-	if (atomic_read(&q->use_count) == 1) {
-		atomic_dec(&q->use_count);
-		clear_bit(0, &dev->context_flag);
-		return -EINVAL;
-	}
-
-	if (drm_flags & DRM_FLAG_NOCTX) {
-		drm_context_switch_complete(dev, new);
-	} else {
-		sprintf(buf, "C %d %d\n", old, new);
-		drm_write_string(dev, buf);
-	}
-	
-	atomic_dec(&q->use_count);
-	
-	return 0;
-}
-
-int drm_context_switch_complete(drm_device_t *dev, int new)
-{
-	drm_device_dma_t *dma = dev->dma;
-	
-	dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
-	dev->last_switch  = jiffies;
-	
-	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("Lock isn't held after context switch\n");
-	}
-
-	if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
-				  DRM_KERNEL_CONTEXT)) {
-			DRM_ERROR("Cannot free lock\n");
-		}
-	}
-	
-#if DRM_DMA_HISTOGRAM
-	atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
-						      - dev->ctx_start)]);
-		   
-#endif
-	clear_bit(0, &dev->context_flag);
-	wake_up_interruptible(&dev->context_wait);
-	
-	return 0;
-}
-
-void drm_clear_next_buffer(drm_device_t *dev)
-{
-	drm_device_dma_t *dma = dev->dma;
-	
-	dma->next_buffer = NULL;
-	if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
-		wake_up_interruptible(&dma->next_queue->flush_queue);
-	}
-	dma->next_queue	 = NULL;
-}
-
-
-int drm_select_queue(drm_device_t *dev, void (*wrapper)(unsigned long))
-{
-	int	   i;
-	int	   candidate = -1;
-	int	   j	     = jiffies;
-
-	if (!dev) {
-		DRM_ERROR("No device\n");
-		return -1;
-	}
-	if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
-				/* This only happens between the time the
-				   interrupt is initialized and the time
-				   the queues are initialized. */
-		return -1;
-	}
-
-				/* Doing "while locked" DMA? */
-	if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
-		return DRM_KERNEL_CONTEXT;
-	}
-
-				/* If there are buffers on the last_context
-				   queue, and we have not been executing
-				   this context very long, continue to
-				   execute this context. */
-	if (dev->last_switch <= j
-	    && dev->last_switch + DRM_TIME_SLICE > j
-	    && DRM_WAITCOUNT(dev, dev->last_context)) {
-		return dev->last_context;
-	}
-
-				/* Otherwise, find a candidate */
-	for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
-		if (DRM_WAITCOUNT(dev, i)) {
-			candidate = dev->last_checked = i;
-			break;
-		}
-	}
-
-	if (candidate < 0) {
-		for (i = 0; i < dev->queue_count; i++) {
-			if (DRM_WAITCOUNT(dev, i)) {
-				candidate = dev->last_checked = i;
-				break;
-			}
-		}
-	}
-
-	if (wrapper
-	    && candidate >= 0
-	    && candidate != dev->last_context
-	    && dev->last_switch <= j
-	    && dev->last_switch + DRM_TIME_SLICE > j) {
-		if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
-			del_timer(&dev->timer);
-			dev->timer.function = wrapper;
-			dev->timer.data	    = (unsigned long)dev;
-			dev->timer.expires  = dev->last_switch+DRM_TIME_SLICE;
-			add_timer(&dev->timer);
-		}
-		return -1;
-	}
-
-	return candidate;
-}
-
-
-int drm_dma_enqueue(drm_device_t *dev, drm_dma_t *d)
-{
-	int		  i;
-	drm_queue_t	  *q;
-	drm_buf_t	  *buf;
-	int		  idx;
-	int		  while_locked = 0;
-	drm_device_dma_t  *dma = dev->dma;
-	DECLARE_WAITQUEUE(entry, current);
-
-	DRM_DEBUG("%d\n", d->send_count);
-
-	if (d->flags & _DRM_DMA_WHILE_LOCKED) {
-		int context = dev->lock.hw_lock->lock;
-		
-		if (!_DRM_LOCK_IS_HELD(context)) {
-			DRM_ERROR("No lock held during \"while locked\""
-				  " request\n");
-			return -EINVAL;
-		}
-		if (d->context != _DRM_LOCKING_CONTEXT(context)
-		    && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
-			DRM_ERROR("Lock held by %d while %d makes"
-				  " \"while locked\" request\n",
-				  _DRM_LOCKING_CONTEXT(context),
-				  d->context);
-			return -EINVAL;
-		}
-		q = dev->queuelist[DRM_KERNEL_CONTEXT];
-		while_locked = 1;
-	} else {
-		q = dev->queuelist[d->context];
-	}
-
-
-	atomic_inc(&q->use_count);
-	if (atomic_read(&q->block_write)) {
-		add_wait_queue(&q->write_queue, &entry);
-		atomic_inc(&q->block_count);
-		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-			if (!atomic_read(&q->block_write)) break;
-			schedule();
-			if (signal_pending(current)) {
-				atomic_dec(&q->use_count);
-				remove_wait_queue(&q->write_queue, &entry);
-				return -EINTR;
-			}
-		}
-		atomic_dec(&q->block_count);
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&q->write_queue, &entry);
-	}
-	
-	for (i = 0; i < d->send_count; i++) {
-		idx = d->send_indices[i];
-		if (idx < 0 || idx >= dma->buf_count) {
-			atomic_dec(&q->use_count);
-			DRM_ERROR("Index %d (of %d max)\n",
-				  d->send_indices[i], dma->buf_count - 1);
-			return -EINVAL;
-		}
-		buf = dma->buflist[ idx ];
-		if (buf->pid != current->pid) {
-			atomic_dec(&q->use_count);
-			DRM_ERROR("Process %d using buffer owned by %d\n",
-				  current->pid, buf->pid);
-			return -EINVAL;
-		}
-		if (buf->list != DRM_LIST_NONE) {
-			atomic_dec(&q->use_count);
-			DRM_ERROR("Process %d using buffer %d on list %d\n",
-				  current->pid, buf->idx, buf->list);
-		}
-		buf->used	  = d->send_sizes[i];
-		buf->while_locked = while_locked;
-		buf->context	  = d->context;
-		if (!buf->used) {
-			DRM_ERROR("Queueing 0 length buffer\n");
-		}
-		if (buf->pending) {
-			atomic_dec(&q->use_count);
-			DRM_ERROR("Queueing pending buffer:"
-				  " buffer %d, offset %d\n",
-				  d->send_indices[i], i);
-			return -EINVAL;
-		}
-		if (buf->waiting) {
-			atomic_dec(&q->use_count);
-			DRM_ERROR("Queueing waiting buffer:"
-				  " buffer %d, offset %d\n",
-				  d->send_indices[i], i);
-			return -EINVAL;
-		}
-		buf->waiting = 1;
-		if (atomic_read(&q->use_count) == 1
-		    || atomic_read(&q->finalization)) {
-			drm_free_buffer(dev, buf);
-		} else {
-			drm_waitlist_put(&q->waitlist, buf);
-			atomic_inc(&q->total_queued);
-		}
-	}
-	atomic_dec(&q->use_count);
-	
-	return 0;
-}
-
-static int drm_dma_get_buffers_of_order(drm_device_t *dev, drm_dma_t *d,
-					int order)
-{
-	int		  i;
-	drm_buf_t	  *buf;
-	drm_device_dma_t  *dma = dev->dma;
-	
-	for (i = d->granted_count; i < d->request_count; i++) {
-		buf = drm_freelist_get(&dma->bufs[order].freelist,
-				       d->flags & _DRM_DMA_WAIT);
-		if (!buf) break;
-		if (buf->pending || buf->waiting) {
-			DRM_ERROR("Free buffer %d in use by %d (w%d, p%d)\n",
-				  buf->idx,
-				  buf->pid,
-				  buf->waiting,
-				  buf->pending);
-		}
-		buf->pid     = current->pid;
-		if (copy_to_user(&d->request_indices[i],
-				 &buf->idx,
-				 sizeof(buf->idx)))
-			return -EFAULT;
-
-		if (copy_to_user(&d->request_sizes[i],
-				 &buf->total,
-				 sizeof(buf->total)))
-			return -EFAULT;
-
-		++d->granted_count;
-	}
-	return 0;
-}
-
-
-int drm_dma_get_buffers(drm_device_t *dev, drm_dma_t *dma)
-{
-	int		  order;
-	int		  retcode = 0;
-	int		  tmp_order;
-	
-	order = drm_order(dma->request_size);
-
-	dma->granted_count = 0;
-	retcode		   = drm_dma_get_buffers_of_order(dev, dma, order);
-
-	if (dma->granted_count < dma->request_count
-	    && (dma->flags & _DRM_DMA_SMALLER_OK)) {
-		for (tmp_order = order - 1;
-		     !retcode
-			     && dma->granted_count < dma->request_count
-			     && tmp_order >= DRM_MIN_ORDER;
-		     --tmp_order) {
-			
-			retcode = drm_dma_get_buffers_of_order(dev, dma,
-							       tmp_order);
-		}
-	}
-
-	if (dma->granted_count < dma->request_count
-	    && (dma->flags & _DRM_DMA_LARGER_OK)) {
-		for (tmp_order = order + 1;
-		     !retcode
-			     && dma->granted_count < dma->request_count
-			     && tmp_order <= DRM_MAX_ORDER;
-		     ++tmp_order) {
-			
-			retcode = drm_dma_get_buffers_of_order(dev, dma,
-							       tmp_order);
-		}
-	}
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drawable.c linux/drivers/char/drm/drawable.c
--- linux-2.4.8-pre6/drivers/char/drm/drawable.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/char/drm/drawable.c	Wed Dec 31 16:00:00 1969
@@ -1,51 +0,0 @@
-/* drawable.c -- IOCTLs for drawables -*- linux-c -*-
- * Created: Tue Feb  2 08:37:54 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>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-int drm_adddraw(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
-{
-	drm_draw_t draw;
-
-	draw.handle = 0;	/* NOOP */
-	DRM_DEBUG("%d\n", draw.handle);
-	if (copy_to_user((drm_draw_t *)arg, &draw, sizeof(draw)))
-		return -EFAULT;
-	return 0;
-}
-
-int drm_rmdraw(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
-{
-	return 0;		/* NOOP */
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm.h linux/drivers/char/drm/drm.h
--- linux-2.4.8-pre6/drivers/char/drm/drm.h	Fri Jan 19 21:38:59 2001
+++ linux/drivers/char/drm/drm.h	Mon Dec  3 22:59:45 2001
@@ -19,10 +19,10 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * 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>
@@ -35,8 +35,8 @@
 #ifndef _DRM_H_
 #define _DRM_H_
 
-#include <linux/config.h>
 #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__)
@@ -44,6 +44,14 @@
 #define DRM_IOCTL_NR(n)	     ((n) & 0xff)
 #endif
 
+#define XFREE86_VERSION(major,minor,patch,snap) \
+		((major << 16) | (minor << 8) | patch)
+
+#ifndef CONFIG_XFREE86_VERSION
+#define CONFIG_XFREE86_VERSION XFREE86_VERSION(4,1,0,0)
+#endif
+
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
 #define DRM_PROC_DEVICES "/proc/devices"
 #define DRM_PROC_MISC	 "/proc/misc"
 #define DRM_PROC_DRM	 "/proc/drm"
@@ -51,8 +59,12 @@
 #define DRM_DEV_MODE	 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
 #define DRM_DEV_UID	 0
 #define DRM_DEV_GID	 0
+#endif
 
-
+#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
+#define DRM_MAJOR       226
+#define DRM_MAX_MINOR   15
+#endif
 #define DRM_NAME	"drm"	  /* Name in kernel, /dev, and /proc	    */
 #define DRM_MIN_ORDER	5	  /* At least 2^5 bytes = 32 bytes	    */
 #define DRM_MAX_ORDER	22	  /* Up to 2^22 bytes = 4MB		    */
@@ -73,12 +85,20 @@
  * XF86DRIClipRectRec in the server as well */
 
 typedef struct drm_clip_rect {
-           unsigned short x1;
-           unsigned short y1;
-           unsigned short x2;
-           unsigned short y2;
+	unsigned short	x1;
+	unsigned short	y1;
+	unsigned short	x2;
+	unsigned short	y2;
 } drm_clip_rect_t;
 
+typedef struct drm_tex_region {
+	unsigned char	next;
+	unsigned char	prev;
+	unsigned char	in_use;
+	unsigned char	padding;
+	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"
@@ -125,10 +145,11 @@
 } drm_control_t;
 
 typedef enum drm_map_type {
-	_DRM_FRAME_BUFFER = 0,	  /* WC (no caching), no core dump	    */
-	_DRM_REGISTERS	  = 1,	  /* no caching, no core dump		    */
-	_DRM_SHM	  = 2,	  /* shared, cached			    */
-	_DRM_AGP          = 3	  /* AGP/GART                               */
+	_DRM_FRAME_BUFFER   = 0,  /* WC (no caching), no core dump	    */
+	_DRM_REGISTERS	    = 1,  /* no caching, no core dump		    */
+	_DRM_SHM	    = 2,  /* shared, cached			    */
+	_DRM_AGP            = 3,  /* AGP/GART                               */
+	_DRM_SCATTER_GATHER = 4	  /* Scatter/gather memory for PCI DMA      */
 } drm_map_type_t;
 
 typedef enum drm_map_flags {
@@ -137,9 +158,15 @@
 	_DRM_LOCKED	     = 0x04, /* shared, cached, locked		    */
 	_DRM_KERNEL	     = 0x08, /* kernel requires access		    */
 	_DRM_WRITE_COMBINING = 0x10, /* use write-combining if available    */
-	_DRM_CONTAINS_LOCK   = 0x20  /* SHM page that contains lock	    */
+	_DRM_CONTAINS_LOCK   = 0x20, /* SHM page that contains lock	    */
+	_DRM_REMOVABLE	     = 0x40  /* Removable mapping		    */
 } drm_map_flags_t;
 
+typedef struct drm_ctx_priv_map {
+	unsigned int	ctx_id;  /* Context requesting private mapping */
+	void		*handle; /* Handle of map */
+} drm_ctx_priv_map_t;
+
 typedef struct drm_map {
 	unsigned long	offset;	 /* Requested physical address (0 for SAREA)*/
 	unsigned long	size;	 /* Requested physical size (bytes)	    */
@@ -151,6 +178,44 @@
 				 /* Private data			    */
 } drm_map_t;
 
+typedef struct drm_client {
+	int		idx;	/* Which client desired?                    */
+	int		auth;	/* Is client authenticated?                 */
+	unsigned long	pid;	/* Process id                               */
+	unsigned long	uid;	/* User id                                  */
+	unsigned long	magic;	/* Magic                                    */
+	unsigned long	iocs;	/* Ioctl count                              */
+} drm_client_t;
+
+typedef enum {
+	_DRM_STAT_LOCK,
+	_DRM_STAT_OPENS,
+	_DRM_STAT_CLOSES,
+	_DRM_STAT_IOCTLS,
+	_DRM_STAT_LOCKS,
+	_DRM_STAT_UNLOCKS,
+	_DRM_STAT_VALUE,	/* Generic value                      */
+	_DRM_STAT_BYTE,		/* Generic byte counter (1024bytes/K) */
+	_DRM_STAT_COUNT,	/* Generic non-byte counter (1000/k)  */
+
+	_DRM_STAT_IRQ,		/* IRQ */
+	_DRM_STAT_PRIMARY,	/* Primary DMA bytes */
+	_DRM_STAT_SECONDARY,	/* Secondary DMA bytes */
+	_DRM_STAT_DMA,		/* DMA */
+	_DRM_STAT_SPECIAL,	/* Special DMA (e.g., priority or polled) */
+	_DRM_STAT_MISSED	/* Missed DMA opportunity */
+
+				/* Add to the *END* of the list */
+} drm_stat_type_t;
+
+typedef struct drm_stats {
+	unsigned long count;
+	struct {
+		unsigned long   value;
+		drm_stat_type_t type;
+	} data[15];
+} drm_stats_t;
+
 typedef enum drm_lock_flags {
 	_DRM_LOCK_READY	     = 0x01, /* Wait until hardware is ready for DMA */
 	_DRM_LOCK_QUIESCENT  = 0x02, /* Wait until hardware quiescent	     */
@@ -193,7 +258,8 @@
 	int	      high_mark; /* High water mark			     */
 	enum {
 		_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA  */
-		_DRM_AGP_BUFFER = 0x02  /* Buffer is in agp space            */
+		_DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space            */
+		_DRM_SG_BUFFER  = 0x04  /* Scatter/gather memory buffer      */
 	}	      flags;
 	unsigned long agp_start; /* Start address of where the agp buffers
 				  * are in the agp aperture */
@@ -299,6 +365,11 @@
 	unsigned short id_device;
 } drm_agp_info_t;
 
+typedef struct drm_scatter_gather {
+	unsigned long size;	/* In bytes -- will round to page boundary */
+	unsigned long handle;	/* Used for mapping / unmapping */
+} drm_scatter_gather_t;
+
 #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)
@@ -310,6 +381,9 @@
 #define DRM_IOCTL_GET_UNIQUE		DRM_IOWR(0x01, drm_unique_t)
 #define DRM_IOCTL_GET_MAGIC		DRM_IOR( 0x02, drm_auth_t)
 #define DRM_IOCTL_IRQ_BUSID		DRM_IOWR(0x03, drm_irq_busid_t)
+#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, drm_map_t)
+#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, drm_client_t)
+#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, drm_stats_t)
 
 #define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, drm_unique_t)
 #define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, drm_auth_t)
@@ -323,6 +397,11 @@
 #define DRM_IOCTL_MAP_BUFS		DRM_IOWR(0x19, drm_buf_map_t)
 #define DRM_IOCTL_FREE_BUFS		DRM_IOW( 0x1a, drm_buf_free_t)
 
+#define DRM_IOCTL_RM_MAP		DRM_IOW( 0x1b, drm_map_t)
+
+#define DRM_IOCTL_SET_SAREA_CTX		DRM_IOW( 0x1c, drm_ctx_priv_map_t)
+#define DRM_IOCTL_GET_SAREA_CTX 	DRM_IOWR(0x1d, drm_ctx_priv_map_t)
+
 #define DRM_IOCTL_ADD_CTX		DRM_IOWR(0x20, drm_ctx_t)
 #define DRM_IOCTL_RM_CTX		DRM_IOWR(0x21, drm_ctx_t)
 #define DRM_IOCTL_MOD_CTX		DRM_IOW( 0x22, drm_ctx_t)
@@ -346,17 +425,21 @@
 #define DRM_IOCTL_AGP_BIND		DRM_IOW( 0x36, drm_agp_binding_t)
 #define DRM_IOCTL_AGP_UNBIND		DRM_IOW( 0x37, drm_agp_binding_t)
 
-/* Mga specific ioctls */
+#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_SWAP		DRM_IOW( 0x41, drm_mga_swap_t)
-#define DRM_IOCTL_MGA_CLEAR		DRM_IOW( 0x42, drm_mga_clear_t)
-#define DRM_IOCTL_MGA_ILOAD		DRM_IOW( 0x43, drm_mga_iload_t)
-#define DRM_IOCTL_MGA_VERTEX		DRM_IOW( 0x44, drm_mga_vertex_t)
-#define DRM_IOCTL_MGA_FLUSH		DRM_IOW( 0x45, drm_lock_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_BLIT		DRM_IOW( 0x47, drm_mga_blit_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 */
+/* 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)
@@ -381,7 +464,8 @@
 #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_PACKET		DRM_IOWR(0x4e, drm_r128_packet_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)
@@ -395,9 +479,9 @@
 #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_BLIT		DRM_IOW( 0x4b, drm_radeon_blit_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)
 
 #ifdef CONFIG_DRM_SIS
 /* SiS specific ioctls */
diff -urN linux-2.4.8-pre6/drivers/char/drm/drmP.h linux/drivers/char/drm/drmP.h
--- linux-2.4.8-pre6/drivers/char/drm/drmP.h	Fri Jul 20 12:52:47 2001
+++ linux/drivers/char/drm/drmP.h	Mon Dec  3 22:59:45 2001
@@ -11,22 +11,22 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the next
  * paragraph) shall be included in all copies or substantial portions of the
  * Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * 
+ * 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>
- * 
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #ifndef _DRM_P_H_
@@ -43,7 +43,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/miscdevice.h>
-#include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
@@ -54,7 +53,7 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>	/* For (un)lock_kernel */
 #include <linux/mm.h>
-#ifdef __alpha__
+#if defined(__alpha__) || defined(__powerpc__)
 #include <asm/pgtable.h> /* For pte_wrprotect */
 #endif
 #include <asm/io.h>
@@ -74,11 +73,46 @@
 #if LINUX_VERSION_CODE < 0x020400
 #include "compat-pre24.h"
 #endif
+#include <asm/pgalloc.h>
 #include "drm.h"
 
+/* DRM template customization defaults
+ */
+#ifndef __HAVE_AGP
+#define __HAVE_AGP		0
+#endif
+#ifndef __HAVE_MTRR
+#define __HAVE_MTRR		0
+#endif
+#ifndef __HAVE_CTX_BITMAP
+#define __HAVE_CTX_BITMAP	0
+#endif
+#ifndef __HAVE_DMA
+#define __HAVE_DMA		0
+#endif
+#ifndef __HAVE_DMA_IRQ
+#define __HAVE_DMA_IRQ		0
+#endif
+#ifndef __HAVE_DMA_WAITLIST
+#define __HAVE_DMA_WAITLIST	0
+#endif
+#ifndef __HAVE_DMA_FREELIST
+#define __HAVE_DMA_FREELIST	0
+#endif
+#ifndef __HAVE_DMA_HISTOGRAM
+#define __HAVE_DMA_HISTOGRAM	0
+#endif
+
+#define __REALLY_HAVE_AGP	(__HAVE_AGP && (defined(CONFIG_AGP) || \
+						defined(CONFIG_AGP_MODULE)))
+#define __REALLY_HAVE_MTRR	(__HAVE_MTRR && defined(CONFIG_MTRR))
+
+
+/* Begin the DRM...
+ */
+
 #define DRM_DEBUG_CODE 2	  /* Include debugging code (if > 1, then
 				     also include looping detection. */
-#define DRM_DMA_HISTOGRAM 1	  /* Make histogram of DMA latency. */
 
 #define DRM_HASH_SIZE	      16 /* Size of key hash table		  */
 #define DRM_KERNEL_CONTEXT    0	 /* Change drm_resctx if changed	  */
@@ -110,6 +144,8 @@
 #define DRM_MEM_TOTALAGP  16
 #define DRM_MEM_BOUNDAGP  17
 #define DRM_MEM_CTXBITMAP 18
+#define DRM_MEM_STUB      19
+#define DRM_MEM_SGLISTS   20
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
 
@@ -164,7 +200,7 @@
 	unsigned long prev, cmp;
 
 	__asm__ __volatile__(
-	"1:	ldl_l %0,%2\n"
+	"1:	ldl_l %0,%5\n"
 	"	cmpeq %0,%3,%1\n"
 	"	beq %1,2f\n"
 	"	mov %4,%1\n"
@@ -175,7 +211,8 @@
 	"3:	br 1b\n"
 	".previous"
 	: "=&r"(prev), "=&r"(cmp), "=m"(*m)
-	: "r"((long) old), "r"(new), "m"(*m));
+	: "r"((long) old), "r"(new), "m"(*m)
+	: "memory" );
 
 	return prev;
 }
@@ -186,7 +223,7 @@
 	unsigned long prev, cmp;
 
 	__asm__ __volatile__(
-	"1:	ldq_l %0,%2\n"
+	"1:	ldq_l %0,%5\n"
 	"	cmpeq %0,%3,%1\n"
 	"	beq %1,2f\n"
 	"	mov %4,%1\n"
@@ -197,7 +234,8 @@
 	"3:	br 1b\n"
 	".previous"
 	: "=&r"(prev), "=&r"(cmp), "=m"(*m)
-	: "r"((long) old), "r"(new), "m"(*m));
+	: "r"((long) old), "r"(new), "m"(*m)
+	: "memory" );
 
 	return prev;
 }
@@ -249,27 +287,58 @@
 	return old;
 }
 
+#elif defined(__powerpc__)
+extern void __cmpxchg_called_with_bad_pointer(void);
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                      unsigned long new, int size)
+{
+	unsigned long prev;
+
+	switch (size) {
+	case 4:
+		__asm__ __volatile__(
+			"sync;"
+			"0:    lwarx %0,0,%1 ;"
+			"      cmpl 0,%0,%3;"
+			"      bne 1f;"
+			"      stwcx. %2,0,%1;"
+			"      bne- 0b;"
+			"1:    "
+			"sync;"
+			: "=&r"(prev)
+			: "r"(ptr), "r"(new), "r"(old)
+			: "cr0", "memory");
+		return prev;
+	}
+	__cmpxchg_called_with_bad_pointer();
+	return old;
+}
+
+#endif /* i386, powerpc & alpha */
+
+#ifndef __alpha__
 #define cmpxchg(ptr,o,n)						\
   ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),		\
 				 (unsigned long)(n),sizeof(*(ptr))))
-#endif /* i386 & alpha */
 #endif
 
+#endif /* !__HAVE_ARCH_CMPXCHG */
+
 				/* Macros to make printk easier */
 #define DRM_ERROR(fmt, arg...) \
 	printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ "] *ERROR* " fmt , ##arg)
 #define DRM_MEM_ERROR(area, fmt, arg...) \
 	printk(KERN_ERR "[" DRM_NAME ":" __FUNCTION__ ":%s] *ERROR* " fmt , \
-	       drm_mem_stats[area].name , ##arg)
+	       DRM(mem_stats)[area].name , ##arg)
 #define DRM_INFO(fmt, arg...)  printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
 
 #if DRM_DEBUG_CODE
-#define DRM_DEBUG(fmt, arg...)						  \
-	do {								  \
-		if (drm_flags&DRM_FLAG_DEBUG)				  \
-			printk(KERN_DEBUG				  \
-			       "[" DRM_NAME ":" __FUNCTION__ "] " fmt ,	  \
-			       ##arg);					  \
+#define DRM_DEBUG(fmt, arg...)						\
+	do {								\
+		if ( DRM(flags) & DRM_FLAG_DEBUG )			\
+			printk(KERN_DEBUG				\
+			       "[" DRM_NAME ":" __FUNCTION__ "] " fmt ,	\
+			       ##arg);					\
 	} while (0)
 #else
 #define DRM_DEBUG(fmt, arg...)		 do { } while (0)
@@ -277,13 +346,36 @@
 
 #define DRM_PROC_LIMIT (PAGE_SIZE-80)
 
-#define DRM_PROC_PRINT(fmt, arg...)	   \
-   len += sprintf(&buf[len], fmt , ##arg); \
-   if (len > DRM_PROC_LIMIT) return len;
-
-#define DRM_PROC_PRINT_RET(ret, fmt, arg...)	    \
-   len += sprintf(&buf[len], fmt , ##arg);	    \
-   if (len > DRM_PROC_LIMIT) { ret; return len; }
+#define DRM_PROC_PRINT(fmt, arg...)					\
+   len += sprintf(&buf[len], fmt , ##arg);				\
+   if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; }
+
+#define DRM_PROC_PRINT_RET(ret, fmt, arg...)				\
+   len += sprintf(&buf[len], fmt , ##arg);				\
+   if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
+
+				/* Mapping helper macros */
+#define DRM_IOREMAP(map)						\
+	(map)->handle = DRM(ioremap)( (map)->offset, (map)->size )
+
+#define DRM_IOREMAPFREE(map)						\
+	do {								\
+		if ( (map)->handle && (map)->size )			\
+			DRM(ioremapfree)( (map)->handle, (map)->size );	\
+	} while (0)
+
+#define DRM_FIND_MAP(_map, _o)						\
+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->offset == (_o) ) {			\
+			(_map) = _entry->map;				\
+			break;						\
+ 		}							\
+	}								\
+} while(0)
 
 				/* Internal types and structures */
 #define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
@@ -294,8 +386,17 @@
 #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
 #define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
 
-typedef int drm_ioctl_t(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
+#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do {	\
+	(_map) = (_dev)->context_sareas[_ctx];		\
+} while(0)
+
+typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
+			 unsigned int cmd, unsigned long arg );
+
+typedef struct drm_pci_list {
+	u16 vendor;
+	u16 device;
+} drm_pci_list_t;
 
 typedef struct drm_ioctl_desc {
 	drm_ioctl_t	     *func;
@@ -305,7 +406,7 @@
 
 typedef struct drm_devstate {
 	pid_t		  owner;	/* X server pid holding x_lock */
-	
+
 } drm_devstate_t;
 
 typedef struct drm_magic_entry {
@@ -366,14 +467,14 @@
 #define DRM_DMA_HISTOGRAM_NEXT(current)	 ((current)*10)
 typedef struct drm_histogram {
 	atomic_t	  total;
-	
+
 	atomic_t	  queued_to_dispatched[DRM_DMA_HISTOGRAM_SLOTS];
 	atomic_t	  dispatched_to_completed[DRM_DMA_HISTOGRAM_SLOTS];
 	atomic_t	  completed_to_freed[DRM_DMA_HISTOGRAM_SLOTS];
-	
+
 	atomic_t	  queued_to_completed[DRM_DMA_HISTOGRAM_SLOTS];
 	atomic_t	  queued_to_freed[DRM_DMA_HISTOGRAM_SLOTS];
-	
+
 	atomic_t	  dma[DRM_DMA_HISTOGRAM_SLOTS];
 	atomic_t	  schedule[DRM_DMA_HISTOGRAM_SLOTS];
 	atomic_t	  ctx[DRM_DMA_HISTOGRAM_SLOTS];
@@ -397,7 +498,7 @@
 	int		  initialized; /* Freelist in use		   */
 	atomic_t	  count;       /* Number of free buffers	   */
 	drm_buf_t	  *next;       /* End pointer			   */
-	
+
 	wait_queue_head_t waiting;     /* Processes waiting on free bufs   */
 	int		  low_mark;    /* Low water mark		   */
 	int		  high_mark;   /* High water mark		   */
@@ -443,9 +544,11 @@
 	wait_queue_head_t read_queue;	/* Processes waiting on block_read  */
 	atomic_t	  block_write;	/* Queue blocked for writes	    */
 	wait_queue_head_t write_queue;	/* Processes waiting on block_write */
+#if 1
 	atomic_t	  total_queued;	/* Total queued statistic	    */
 	atomic_t	  total_flushed;/* Total flushes statistic	    */
 	atomic_t	  total_locks;	/* Total locks statistics	    */
+#endif
 	drm_ctx_flags_t	  flags;	/* Context preserving and 2D-only   */
 	drm_waitlist_t	  waitlist;	/* Pending buffers		    */
 	wait_queue_head_t flush_queue;	/* Processes waiting until flush    */
@@ -459,11 +562,12 @@
 } drm_lock_data_t;
 
 typedef struct drm_device_dma {
+#if 0
 				/* Performance Counters */
 	atomic_t	  total_prio;	/* Total DRM_DMA_PRIORITY	   */
 	atomic_t	  total_bytes;	/* Total bytes DMA'd		   */
 	atomic_t	  total_dmas;	/* Total DMA buffers dispatched	   */
-	
+
 	atomic_t	  total_missed_dma;  /* Missed drm_do_dma	    */
 	atomic_t	  total_missed_lock; /* Missed lock in drm_do_dma   */
 	atomic_t	  total_missed_free; /* Missed drm_free_this_buffer */
@@ -472,16 +576,18 @@
 	atomic_t	  total_tried;	/* Tried next_buffer		    */
 	atomic_t	  total_hit;	/* Sent next_buffer		    */
 	atomic_t	  total_lost;	/* Lost interrupt		    */
+#endif
 
 	drm_buf_entry_t	  bufs[DRM_MAX_ORDER+1];
 	int		  buf_count;
 	drm_buf_t	  **buflist;	/* Vector of pointers info bufs	   */
-	int		  seg_count; 
+	int		  seg_count;
 	int		  page_count;
 	unsigned long	  *pagelist;
 	unsigned long	  byte_count;
 	enum {
-	   _DRM_DMA_USE_AGP = 0x01
+		_DRM_DMA_USE_AGP = 0x01,
+		_DRM_DMA_USE_SG  = 0x02
 	} flags;
 
 				/* DMA support */
@@ -491,7 +597,7 @@
 	wait_queue_head_t waiting;	/* Processes waiting on free bufs  */
 } drm_device_dma_t;
 
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+#if __REALLY_HAVE_AGP
 typedef struct drm_agp_mem {
 	unsigned long      handle;
 	agp_memory         *memory;
@@ -513,18 +619,30 @@
 } drm_agp_head_t;
 #endif
 
+typedef struct drm_sg_mem {
+	unsigned long   handle;
+	void            *virtual;
+	int             pages;
+	struct page     **pagelist;
+} drm_sg_mem_t;
+
 typedef struct drm_sigdata {
 	int           context;
 	drm_hw_lock_t *lock;
 } drm_sigdata_t;
 
+typedef struct drm_map_list {
+	struct list_head	head;
+	drm_map_t		*map;
+} drm_map_list_t;
+
 typedef struct drm_device {
 	const char	  *name;	/* Simple driver name		   */
 	char		  *unique;	/* Unique identifier: e.g., busid  */
 	int		  unique_len;	/* Length of unique field	   */
 	dev_t		  device;	/* Device number for mknod	   */
 	char		  *devname;	/* For /proc/interrupts		   */
-	
+
 	int		  blocked;	/* Blocked due to VC switch?	   */
 	struct proc_dir_entry *root;	/* Root for this device's entries  */
 
@@ -539,17 +657,10 @@
 	int		  buf_use;	/* Buffers in use -- cannot alloc  */
 	atomic_t	  buf_alloc;	/* Buffer allocation in progress   */
 
-				/* Performance Counters */
-	atomic_t	  total_open;
-	atomic_t	  total_close;
-	atomic_t	  total_ioctl;
-	atomic_t	  total_irq;	/* Total interruptions		   */
-	atomic_t	  total_ctx;	/* Total context switches	   */
-	
-	atomic_t	  total_locks;
-	atomic_t	  total_unlocks;
-	atomic_t	  total_contends;
-	atomic_t	  total_sleeps;
+				/* Performance counters */
+	unsigned long     counters;
+	drm_stat_type_t   types[15];
+	atomic_t          counts[15];
 
 				/* Authentication */
 	drm_file_t	  *file_first;
@@ -557,9 +668,12 @@
 	drm_magic_head_t  magiclist[DRM_HASH_SIZE];
 
 				/* Memory management */
-	drm_map_t	  **maplist;	/* Vector of pointers to regions   */
+	drm_map_list_t	  *maplist;	/* Linked list of regions	   */
 	int		  map_count;	/* Number of mappable regions	   */
 
+	drm_map_t	  **context_sareas;
+	int		  max_context;
+
 	drm_vma_entry_t	  *vmalist;	/* List of vmas (for debugging)	   */
 	drm_lock_data_t	  lock;		/* Information on hardware lock	   */
 
@@ -583,10 +697,10 @@
 	struct tq_struct  tq;
 	cycles_t	  ctx_start;
 	cycles_t	  lck_start;
-#if DRM_DMA_HISTOGRAM
+#if __HAVE_DMA_HISTOGRAM
 	drm_histogram_t	  histo;
 #endif
-	
+
 				/* Callback to X server for context switch
 				   and for heavy-handed reset. */
 	char		  buf[DRM_BSZ]; /* Output buffer		   */
@@ -596,10 +710,18 @@
 	struct fasync_struct *buf_async;/* Processes waiting for SIGIO	   */
 	wait_queue_head_t buf_readers;	/* Processes waiting to read	   */
 	wait_queue_head_t buf_writers;	/* Processes waiting to ctx switch */
-	
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+
+#if __REALLY_HAVE_AGP
 	drm_agp_head_t    *agp;
 #endif
+#ifdef __alpha__
+#if LINUX_VERSION_CODE < 0x020403
+	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;
 	drm_sigdata_t     sigdata; /* For block_all_signals */
@@ -607,230 +729,297 @@
 } drm_device_t;
 
 
-				/* Internal function definitions */
+/* ================================================================
+ * Internal function definitions
+ */
 
-				/* Misc. support (init.c) */
-extern int	     drm_flags;
-extern void	     drm_parse_options(char *s);
-extern int           drm_cpu_valid(void);
-
-
-				/* Device support (fops.c) */
-extern int	     drm_open_helper(struct inode *inode, struct file *filp,
-				     drm_device_t *dev);
-extern int	     drm_flush(struct file *filp);
-extern int	     drm_release(struct inode *inode, struct file *filp);
-extern int	     drm_fasync(int fd, struct file *filp, int on);
-extern ssize_t	     drm_read(struct file *filp, char *buf, size_t count,
-			      loff_t *off);
-extern int	     drm_write_string(drm_device_t *dev, const char *s);
-extern unsigned int  drm_poll(struct file *filp, struct poll_table_struct *wait);
+				/* Misc. support (drm_init.h) */
+extern int	     DRM(flags);
+extern void	     DRM(parse_options)( char *s );
+extern int           DRM(cpu_valid)( void );
 
-				/* Mapping support (vm.c) */
+				/* Driver support (drm_drv.h) */
+extern int           DRM(version)(struct inode *inode, struct file *filp,
+				  unsigned int cmd, unsigned long arg);
+extern int           DRM(open)(struct inode *inode, struct file *filp);
+extern int           DRM(release)(struct inode *inode, struct file *filp);
+extern int           DRM(ioctl)(struct inode *inode, struct file *filp,
+				unsigned int cmd, unsigned long arg);
+extern int           DRM(lock)(struct inode *inode, struct file *filp,
+			       unsigned int cmd, unsigned long arg);
+extern int           DRM(unlock)(struct inode *inode, struct file *filp,
+				 unsigned int cmd, unsigned long arg);
+
+				/* Device support (drm_fops.h) */
+extern int	     DRM(open_helper)(struct inode *inode, struct file *filp,
+				      drm_device_t *dev);
+extern int	     DRM(flush)(struct file *filp);
+extern int	     DRM(release_fuck)(struct inode *inode, struct file *filp);
+extern int	     DRM(fasync)(int fd, struct file *filp, int on);
+extern ssize_t	     DRM(read)(struct file *filp, char *buf, size_t count,
+			       loff_t *off);
+extern int	     DRM(write_string)(drm_device_t *dev, const char *s);
+extern unsigned int  DRM(poll)(struct file *filp,
+			       struct poll_table_struct *wait);
+
+				/* Mapping support (drm_vm.h) */
 #if LINUX_VERSION_CODE < 0x020317
-extern unsigned long drm_vm_nopage(struct vm_area_struct *vma,
+extern unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
+				    unsigned long address,
+				    int write_access);
+extern unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
+					unsigned long address,
+					int write_access);
+extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
+					unsigned long address,
+					int write_access);
+extern unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+				       unsigned long address,
+				       int write_access);
+#else
+				/* Return type changed in 2.3.23 */
+extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
 				   unsigned long address,
 				   int write_access);
-extern unsigned long drm_vm_shm_nopage(struct vm_area_struct *vma,
+extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
 				       unsigned long address,
 				       int write_access);
-extern unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
-					    unsigned long address,
-					    int write_access);
-extern unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma,
+extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
 				       unsigned long address,
 				       int write_access);
-#else
-				/* Return type changed in 2.3.23 */
-extern struct page *drm_vm_nopage(struct vm_area_struct *vma,
-				  unsigned long address,
-				  int write_access);
-extern struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
-				      unsigned long address,
-				      int write_access);
-extern struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
-					   unsigned long address,
-					   int write_access);
-extern struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
+extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
 				      unsigned long address,
 				      int write_access);
 #endif
-extern void	     drm_vm_open(struct vm_area_struct *vma);
-extern void	     drm_vm_close(struct vm_area_struct *vma);
-extern int	     drm_mmap_dma(struct file *filp,
-				  struct vm_area_struct *vma);
-extern int	     drm_mmap(struct file *filp, struct vm_area_struct *vma);
-
-
-				/* Proc support (proc.c) */
-extern int	     drm_proc_init(drm_device_t *dev);
-extern int	     drm_proc_cleanup(void);
-
-				/* Memory management support (memory.c) */
-extern void	     drm_mem_init(void);
-extern int	     drm_mem_info(char *buf, char **start, off_t offset,
-				  int len, int *eof, void *data);
-extern void	     *drm_alloc(size_t size, int area);
-extern void	     *drm_realloc(void *oldpt, size_t oldsize, size_t size,
-				  int area);
-extern char	     *drm_strdup(const char *s, int area);
-extern void	     drm_strfree(const char *s, int area);
-extern void	     drm_free(void *pt, size_t size, int area);
-extern unsigned long drm_alloc_pages(int order, int area);
-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_ioremapfree(void *pt, unsigned long size);
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-extern agp_memory    *drm_alloc_agp(int pages, u32 type);
-extern int           drm_free_agp(agp_memory *handle, int pages);
-extern int           drm_bind_agp(agp_memory *handle, unsigned int start);
-extern int           drm_unbind_agp(agp_memory *handle);
+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);
+extern int	     DRM(mmap_dma)(struct file *filp,
+				   struct vm_area_struct *vma);
+extern int	     DRM(mmap)(struct file *filp, struct vm_area_struct *vma);
+
+				/* Memory management support (drm_memory.h) */
+extern void	     DRM(mem_init)(void);
+extern int	     DRM(mem_info)(char *buf, char **start, off_t offset,
+				   int request, int *eof, void *data);
+extern void	     *DRM(alloc)(size_t size, int area);
+extern void	     *DRM(realloc)(void *oldpt, size_t oldsize, size_t size,
+				   int area);
+extern char	     *DRM(strdup)(const char *s, int area);
+extern void	     DRM(strfree)(const char *s, int area);
+extern void	     DRM(free)(void *pt, size_t size, int area);
+extern unsigned long DRM(alloc_pages)(int order, int area);
+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(ioremapfree)(void *pt, unsigned long size);
+
+#if __REALLY_HAVE_AGP
+extern agp_memory    *DRM(alloc_agp)(int pages, u32 type);
+extern int           DRM(free_agp)(agp_memory *handle, int pages);
+extern int           DRM(bind_agp)(agp_memory *handle, unsigned int start);
+extern int           DRM(unbind_agp)(agp_memory *handle);
 #endif
 
-
-				/* Buffer management support (bufs.c) */
-extern int	     drm_order(unsigned long size);
-extern int	     drm_addmap(struct inode *inode, struct file *filp,
-				unsigned int cmd, unsigned long arg);
-extern int	     drm_addbufs(struct inode *inode, struct file *filp,
-				 unsigned int cmd, unsigned long arg);
-extern int	     drm_infobufs(struct inode *inode, struct file *filp,
-				  unsigned int cmd, unsigned long arg);
-extern int	     drm_markbufs(struct inode *inode, struct file *filp,
-				  unsigned int cmd, unsigned long arg);
-extern int	     drm_freebufs(struct inode *inode, struct file *filp,
-				  unsigned int cmd, unsigned long arg);
-extern int	     drm_mapbufs(struct inode *inode, struct file *filp,
+				/* Misc. IOCTL support (drm_ioctl.h) */
+extern int	     DRM(irq_busid)(struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg);
+extern int	     DRM(getunique)(struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg);
+extern int	     DRM(setunique)(struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg);
+extern int	     DRM(getmap)(struct inode *inode, struct file *filp,
 				 unsigned int cmd, unsigned long arg);
-
-
-				/* Buffer list management support (lists.c) */
-extern int	     drm_waitlist_create(drm_waitlist_t *bl, int count);
-extern int	     drm_waitlist_destroy(drm_waitlist_t *bl);
-extern int	     drm_waitlist_put(drm_waitlist_t *bl, drm_buf_t *buf);
-extern drm_buf_t     *drm_waitlist_get(drm_waitlist_t *bl);
-
-extern int	     drm_freelist_create(drm_freelist_t *bl, int count);
-extern int	     drm_freelist_destroy(drm_freelist_t *bl);
-extern int	     drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl,
-				      drm_buf_t *buf);
-extern drm_buf_t     *drm_freelist_get(drm_freelist_t *bl, int block);
-
-				/* DMA support (gen_dma.c) */
-extern void	     drm_dma_setup(drm_device_t *dev);
-extern void	     drm_dma_takedown(drm_device_t *dev);
-extern void	     drm_free_buffer(drm_device_t *dev, drm_buf_t *buf);
-extern void	     drm_reclaim_buffers(drm_device_t *dev, pid_t pid);
-extern int	     drm_context_switch(drm_device_t *dev, int old, int new);
-extern int	     drm_context_switch_complete(drm_device_t *dev, int new);
-extern void	     drm_clear_next_buffer(drm_device_t *dev);
-extern int	     drm_select_queue(drm_device_t *dev,
-				      void (*wrapper)(unsigned long));
-extern int	     drm_dma_enqueue(drm_device_t *dev, drm_dma_t *dma);
-extern int	     drm_dma_get_buffers(drm_device_t *dev, drm_dma_t *dma);
-#if DRM_DMA_HISTOGRAM
-extern int	     drm_histogram_slot(unsigned long count);
-extern void	     drm_histogram_compute(drm_device_t *dev, drm_buf_t *buf);
-#endif
-
-
-				/* Misc. IOCTL support (ioctl.c) */
-extern int	     drm_irq_busid(struct inode *inode, struct file *filp,
-				   unsigned int cmd, unsigned long arg);
-extern int	     drm_getunique(struct inode *inode, struct file *filp,
-				   unsigned int cmd, unsigned long arg);
-extern int	     drm_setunique(struct inode *inode, struct file *filp,
-				   unsigned int cmd, unsigned long arg);
-
-
-				/* Context IOCTL support (context.c) */
-extern int	     drm_resctx(struct inode *inode, struct file *filp,
-				unsigned int cmd, unsigned long arg);
-extern int	     drm_addctx(struct inode *inode, struct file *filp,
-				unsigned int cmd, unsigned long arg);
-extern int	     drm_modctx(struct inode *inode, struct file *filp,
-				unsigned int cmd, unsigned long arg);
-extern int	     drm_getctx(struct inode *inode, struct file *filp,
-				unsigned int cmd, unsigned long arg);
-extern int	     drm_switchctx(struct inode *inode, struct file *filp,
+extern int	     DRM(getclient)(struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg);
+extern int	     DRM(getstats)(struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg);
-extern int	     drm_newctx(struct inode *inode, struct file *filp,
-				unsigned int cmd, unsigned long arg);
-extern int	     drm_rmctx(struct inode *inode, struct file *filp,
-			       unsigned int cmd, unsigned long arg);
 
+				/* Context IOCTL support (drm_context.h) */
+extern int	     DRM(resctx)( struct inode *inode, struct file *filp,
+				  unsigned int cmd, unsigned long arg );
+extern int	     DRM(addctx)( struct inode *inode, struct file *filp,
+				  unsigned int cmd, unsigned long arg );
+extern int	     DRM(modctx)( struct inode *inode, struct file *filp,
+				  unsigned int cmd, unsigned long arg );
+extern int	     DRM(getctx)( struct inode *inode, struct file *filp,
+				  unsigned int cmd, unsigned long arg );
+extern int	     DRM(switchctx)( struct inode *inode, struct file *filp,
+				     unsigned int cmd, unsigned long arg );
+extern int	     DRM(newctx)( struct inode *inode, struct file *filp,
+				  unsigned int cmd, unsigned long arg );
+extern int	     DRM(rmctx)( struct inode *inode, struct file *filp,
+				 unsigned int cmd, unsigned long arg );
+
+extern int	     DRM(context_switch)(drm_device_t *dev, int old, int new);
+extern int	     DRM(context_switch_complete)(drm_device_t *dev, int new);
+
+#if __HAVE_CTX_BITMAP
+extern int	     DRM(ctxbitmap_init)( drm_device_t *dev );
+extern void	     DRM(ctxbitmap_cleanup)( drm_device_t *dev );
+#endif
+
+extern int	     DRM(setsareactx)( struct inode *inode, struct file *filp,
+				       unsigned int cmd, unsigned long arg );
+extern int	     DRM(getsareactx)( struct inode *inode, struct file *filp,
+				       unsigned int cmd, unsigned long arg );
 
-				/* Drawable IOCTL support (drawable.c) */
-extern int	     drm_adddraw(struct inode *inode, struct file *filp,
+				/* Drawable IOCTL support (drm_drawable.h) */
+extern int	     DRM(adddraw)(struct inode *inode, struct file *filp,
+				  unsigned int cmd, unsigned long arg);
+extern int	     DRM(rmdraw)(struct inode *inode, struct file *filp,
 				 unsigned int cmd, unsigned long arg);
-extern int	     drm_rmdraw(struct inode *inode, struct file *filp,
-				unsigned int cmd, unsigned long arg);
 
 
-				/* Authentication IOCTL support (auth.c) */
-extern int	     drm_add_magic(drm_device_t *dev, drm_file_t *priv,
-				   drm_magic_t magic);
-extern int	     drm_remove_magic(drm_device_t *dev, drm_magic_t magic);
-extern int	     drm_getmagic(struct inode *inode, struct file *filp,
-				  unsigned int cmd, unsigned long arg);
-extern int	     drm_authmagic(struct inode *inode, struct file *filp,
+				/* Authentication IOCTL support (drm_auth.h) */
+extern int	     DRM(add_magic)(drm_device_t *dev, drm_file_t *priv,
+				    drm_magic_t magic);
+extern int	     DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic);
+extern int	     DRM(getmagic)(struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg);
+extern int	     DRM(authmagic)(struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg);
 
 
-				/* Locking IOCTL support (lock.c) */
-extern int	     drm_block(struct inode *inode, struct file *filp,
-			       unsigned int cmd, unsigned long arg);
-extern int	     drm_unblock(struct inode *inode, struct file *filp,
-				 unsigned int cmd, unsigned long arg);
-extern int	     drm_lock_take(__volatile__ unsigned int *lock,
-				   unsigned int context);
-extern int	     drm_lock_transfer(drm_device_t *dev,
-				       __volatile__ unsigned int *lock,
-				       unsigned int context);
-extern int	     drm_lock_free(drm_device_t *dev,
-				   __volatile__ unsigned int *lock,
-				   unsigned int context);
-extern int	     drm_finish(struct inode *inode, struct file *filp,
+				/* Locking IOCTL support (drm_lock.h) */
+extern int	     DRM(block)(struct inode *inode, struct file *filp,
 				unsigned int cmd, unsigned long arg);
-extern int	     drm_flush_unblock(drm_device_t *dev, int context,
-				       drm_lock_flags_t flags);
-extern int	     drm_flush_block_and_flush(drm_device_t *dev, int context,
-					       drm_lock_flags_t flags);
-extern int           drm_notifier(void *priv);
-
-				/* Context Bitmap support (ctxbitmap.c) */
-extern int	     drm_ctxbitmap_init(drm_device_t *dev);
-extern void	     drm_ctxbitmap_cleanup(drm_device_t *dev);
-extern int	     drm_ctxbitmap_next(drm_device_t *dev);
-extern void	     drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle);
+extern int	     DRM(unblock)(struct inode *inode, struct file *filp,
+				  unsigned int cmd, unsigned long arg);
+extern int	     DRM(lock_take)(__volatile__ unsigned int *lock,
+				    unsigned int context);
+extern int	     DRM(lock_transfer)(drm_device_t *dev,
+					__volatile__ unsigned int *lock,
+					unsigned int context);
+extern int	     DRM(lock_free)(drm_device_t *dev,
+				    __volatile__ unsigned int *lock,
+				    unsigned int context);
+extern int	     DRM(finish)(struct inode *inode, struct file *filp,
+				 unsigned int cmd, unsigned long arg);
+extern int	     DRM(flush_unblock)(drm_device_t *dev, int context,
+					drm_lock_flags_t flags);
+extern int	     DRM(flush_block_and_flush)(drm_device_t *dev, int context,
+						drm_lock_flags_t flags);
+extern int           DRM(notifier)(void *priv);
+
+				/* Buffer management support (drm_bufs.h) */
+extern int	     DRM(order)( unsigned long size );
+extern int	     DRM(addmap)( struct inode *inode, struct file *filp,
+				  unsigned int cmd, unsigned long arg );
+extern int	     DRM(rmmap)( struct inode *inode, struct file *filp,
+				 unsigned int cmd, unsigned long arg );
+#if __HAVE_DMA
+extern int	     DRM(addbufs)( struct inode *inode, struct file *filp,
+				   unsigned int cmd, unsigned long arg );
+extern int	     DRM(infobufs)( struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg );
+extern int	     DRM(markbufs)( struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg );
+extern int	     DRM(freebufs)( struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg );
+extern int	     DRM(mapbufs)( struct inode *inode, struct file *filp,
+				   unsigned int cmd, unsigned long arg );
+
+				/* DMA support (drm_dma.h) */
+extern int	     DRM(dma_setup)(drm_device_t *dev);
+extern void	     DRM(dma_takedown)(drm_device_t *dev);
+extern void	     DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf);
+extern void	     DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid);
+#if __HAVE_OLD_DMA
+/* GH: This is a dirty hack for now...
+ */
+extern void	     DRM(clear_next_buffer)(drm_device_t *dev);
+extern int	     DRM(select_queue)(drm_device_t *dev,
+				       void (*wrapper)(unsigned long));
+extern int	     DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *dma);
+extern int	     DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma);
+#endif
+#if __HAVE_DMA_IRQ
+extern int           DRM(control)( struct inode *inode, struct file *filp,
+				   unsigned int cmd, unsigned long arg );
+extern int           DRM(irq_install)( drm_device_t *dev, int irq );
+extern int           DRM(irq_uninstall)( drm_device_t *dev );
+extern void          DRM(dma_service)( int irq, void *device,
+				       struct pt_regs *regs );
+#if __HAVE_DMA_IRQ_BH
+extern void          DRM(dma_immediate_bh)( void *dev );
+#endif
+#endif
+#if DRM_DMA_HISTOGRAM
+extern int	     DRM(histogram_slot)(unsigned long count);
+extern void	     DRM(histogram_compute)(drm_device_t *dev, drm_buf_t *buf);
+#endif
 
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-				/* AGP/GART support (agpsupport.c) */
-extern drm_agp_head_t *drm_agp_init(void);
-extern void           drm_agp_uninit(void);
-extern int            drm_agp_acquire(struct inode *inode, struct file *filp,
+				/* Buffer list support (drm_lists.h) */
+#if __HAVE_DMA_WAITLIST
+extern int	     DRM(waitlist_create)(drm_waitlist_t *bl, int count);
+extern int	     DRM(waitlist_destroy)(drm_waitlist_t *bl);
+extern int	     DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf);
+extern drm_buf_t     *DRM(waitlist_get)(drm_waitlist_t *bl);
+#endif
+#if __HAVE_DMA_FREELIST
+extern int	     DRM(freelist_create)(drm_freelist_t *bl, int count);
+extern int	     DRM(freelist_destroy)(drm_freelist_t *bl);
+extern int	     DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
+				       drm_buf_t *buf);
+extern drm_buf_t     *DRM(freelist_get)(drm_freelist_t *bl, int block);
+#endif
+#endif /* __HAVE_DMA */
+
+#if __REALLY_HAVE_AGP
+				/* AGP/GART support (drm_agpsupport.h) */
+extern drm_agp_head_t *DRM(agp_init)(void);
+extern void           DRM(agp_uninit)(void);
+extern int            DRM(agp_acquire)(struct inode *inode, struct file *filp,
+				       unsigned int cmd, unsigned long arg);
+extern void           DRM(agp_do_release)(void);
+extern int            DRM(agp_release)(struct inode *inode, struct file *filp,
+				       unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_enable)(struct inode *inode, struct file *filp,
 				      unsigned int cmd, unsigned long arg);
-extern void           _drm_agp_release(void);
-extern int            drm_agp_release(struct inode *inode, struct file *filp,
-				      unsigned int cmd, unsigned long arg);
-extern int            drm_agp_enable(struct inode *inode, struct file *filp,
-				     unsigned int cmd, unsigned long arg);
-extern int            drm_agp_info(struct inode *inode, struct file *filp,
-				   unsigned int cmd, unsigned long arg);
-extern int            drm_agp_alloc(struct inode *inode, struct file *filp,
+extern int            DRM(agp_info)(struct inode *inode, struct file *filp,
 				    unsigned int cmd, unsigned long arg);
-extern int            drm_agp_free(struct inode *inode, struct file *filp,
-				   unsigned int cmd, unsigned long arg);
-extern int            drm_agp_unbind(struct inode *inode, struct file *filp,
+extern int            DRM(agp_alloc)(struct inode *inode, struct file *filp,
 				     unsigned int cmd, unsigned long arg);
-extern int            drm_agp_bind(struct inode *inode, struct file *filp,
+extern int            DRM(agp_free)(struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_unbind)(struct inode *inode, struct file *filp,
+				      unsigned int cmd, unsigned long arg);
+extern int            DRM(agp_bind)(struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg);
+extern agp_memory     *DRM(agp_allocate_memory)(size_t pages, u32 type);
+extern int            DRM(agp_free_memory)(agp_memory *handle);
+extern int            DRM(agp_bind_memory)(agp_memory *handle, off_t start);
+extern int            DRM(agp_unbind_memory)(agp_memory *handle);
+#endif
+
+				/* Stub support (drm_stub.h) */
+int                   DRM(stub_register)(const char *name,
+					 struct file_operations *fops,
+					 drm_device_t *dev);
+int                   DRM(stub_unregister)(int minor);
+
+				/* Proc support (drm_proc.h) */
+extern struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev,
+					     int minor,
+					     struct proc_dir_entry *root,
+					     struct proc_dir_entry **dev_root);
+extern int            DRM(proc_cleanup)(int minor,
+					struct proc_dir_entry *root,
+					struct proc_dir_entry *dev_root);
+
+#if __HAVE_SG
+				/* Scatter Gather Support (drm_scatter.h) */
+extern void           DRM(sg_cleanup)(drm_sg_mem_t *entry);
+extern int            DRM(sg_alloc)(struct inode *inode, struct file *filp,
+				    unsigned int cmd, unsigned long arg);
+extern int            DRM(sg_free)(struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg);
-extern agp_memory     *drm_agp_allocate_memory(size_t pages, u32 type);
-extern int            drm_agp_free_memory(agp_memory *handle);
-extern int            drm_agp_bind_memory(agp_memory *handle, off_t start);
-extern int            drm_agp_unbind_memory(agp_memory *handle);
-#endif
 #endif
+
+                               /* ATI PCIGART support (ati_pcigart.h) */
+extern unsigned long  DRM(ati_pcigart_init)(drm_device_t *dev);
+extern int            DRM(ati_pcigart_cleanup)(unsigned long address);
+
+#endif /* __KERNEL__ */
 #endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_agpsupport.h linux/drivers/char/drm/drm_agpsupport.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_agpsupport.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_agpsupport.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,360 @@
+/* drm_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*-
+ * Created: Mon Dec 13 09:56:45 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include <linux/module.h>
+
+#if __REALLY_HAVE_AGP
+
+#if LINUX_VERSION_CODE < 0x020400
+#include "agpsupport-pre24.h"
+#else
+#define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp")
+#define DRM_AGP_PUT inter_module_put("drm_agp")
+#endif
+
+static const drm_agp_t *drm_agp = NULL;
+
+int DRM(agp_info)(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;
+	agp_kern_info    *kern;
+	drm_agp_info_t   info;
+
+	if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info)
+		return -EINVAL;
+
+	kern                   = &dev->agp->agp_info;
+	info.agp_version_major = kern->version.major;
+	info.agp_version_minor = kern->version.minor;
+	info.mode              = kern->mode;
+	info.aperture_base     = kern->aper_base;
+	info.aperture_size     = kern->aper_size * 1024 * 1024;
+	info.memory_allowed    = kern->max_memory << PAGE_SHIFT;
+	info.memory_used       = kern->current_memory << PAGE_SHIFT;
+	info.id_vendor         = kern->device->vendor;
+	info.id_device         = kern->device->device;
+
+	if (copy_to_user((drm_agp_info_t *)arg, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(agp_acquire)(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;
+	int              retcode;
+
+	if (!dev->agp || dev->agp->acquired || !drm_agp->acquire)
+		return -EINVAL;
+	if ((retcode = drm_agp->acquire())) return retcode;
+	dev->agp->acquired = 1;
+	return 0;
+}
+
+int DRM(agp_release)(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;
+
+	if (!dev->agp || !dev->agp->acquired || !drm_agp->release)
+		return -EINVAL;
+	drm_agp->release();
+	dev->agp->acquired = 0;
+	return 0;
+
+}
+
+void DRM(agp_do_release)(void)
+{
+	if (drm_agp->release) drm_agp->release();
+}
+
+int DRM(agp_enable)(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_agp_mode_t   mode;
+
+	if (!dev->agp || !dev->agp->acquired || !drm_agp->enable)
+		return -EINVAL;
+
+	if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
+		return -EFAULT;
+
+	dev->agp->mode    = mode.mode;
+	drm_agp->enable(mode.mode);
+	dev->agp->base    = dev->agp->agp_info.aper_base;
+	dev->agp->enabled = 1;
+	return 0;
+}
+
+int DRM(agp_alloc)(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_agp_buffer_t request;
+	drm_agp_mem_t    *entry;
+	agp_memory       *memory;
+	unsigned long    pages;
+	u32 		 type;
+
+	if (!dev->agp || !dev->agp->acquired) return -EINVAL;
+	if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
+		return -EFAULT;
+	if (!(entry = DRM(alloc)(sizeof(*entry), DRM_MEM_AGPLISTS)))
+		return -ENOMEM;
+
+   	memset(entry, 0, sizeof(*entry));
+
+	pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
+	type = (u32) request.type;
+
+	if (!(memory = DRM(alloc_agp)(pages, type))) {
+		DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+		return -ENOMEM;
+	}
+
+	entry->handle    = (unsigned long)memory->memory;
+	entry->memory    = memory;
+	entry->bound     = 0;
+	entry->pages     = pages;
+	entry->prev      = NULL;
+	entry->next      = dev->agp->memory;
+	if (dev->agp->memory) dev->agp->memory->prev = entry;
+	dev->agp->memory = entry;
+
+	request.handle   = entry->handle;
+        request.physical = memory->physical;
+
+	if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) {
+		dev->agp->memory       = entry->next;
+		dev->agp->memory->prev = NULL;
+		DRM(free_agp)(memory, pages);
+		DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev,
+					    unsigned long handle)
+{
+	drm_agp_mem_t *entry;
+
+	for (entry = dev->agp->memory; entry; entry = entry->next) {
+		if (entry->handle == handle) return entry;
+	}
+	return NULL;
+}
+
+int DRM(agp_unbind)(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_agp_binding_t request;
+	drm_agp_mem_t     *entry;
+
+	if (!dev->agp || !dev->agp->acquired) return -EINVAL;
+	if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
+		return -EFAULT;
+	if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
+		return -EINVAL;
+	if (!entry->bound) return -EINVAL;
+	return DRM(unbind_agp)(entry->memory);
+}
+
+int DRM(agp_bind)(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_agp_binding_t request;
+	drm_agp_mem_t     *entry;
+	int               retcode;
+	int               page;
+
+	if (!dev->agp || !dev->agp->acquired || !drm_agp->bind_memory)
+		return -EINVAL;
+	if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
+		return -EFAULT;
+	if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
+		return -EINVAL;
+	if (entry->bound) return -EINVAL;
+	page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
+	if ((retcode = DRM(bind_agp)(entry->memory, page))) return retcode;
+	entry->bound = dev->agp->base + (page << PAGE_SHIFT);
+	DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
+		  dev->agp->base, entry->bound);
+	return 0;
+}
+
+int DRM(agp_free)(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_agp_buffer_t request;
+	drm_agp_mem_t    *entry;
+
+	if (!dev->agp || !dev->agp->acquired) return -EINVAL;
+	if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
+		return -EFAULT;
+	if (!(entry = DRM(agp_lookup_entry)(dev, request.handle)))
+		return -EINVAL;
+	if (entry->bound) DRM(unbind_agp)(entry->memory);
+
+	if (entry->prev) entry->prev->next = entry->next;
+	else             dev->agp->memory  = entry->next;
+	if (entry->next) entry->next->prev = entry->prev;
+	DRM(free_agp)(entry->memory, entry->pages);
+	DRM(free)(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+	return 0;
+}
+
+drm_agp_head_t *DRM(agp_init)(void)
+{
+	drm_agp_head_t *head         = NULL;
+
+	drm_agp = DRM_AGP_GET;
+	if (drm_agp) {
+		if (!(head = DRM(alloc)(sizeof(*head), DRM_MEM_AGPLISTS)))
+			return NULL;
+		memset((void *)head, 0, sizeof(*head));
+		drm_agp->copy_info(&head->agp_info);
+		if (head->agp_info.chipset == NOT_SUPPORTED) {
+			DRM(free)(head, sizeof(*head), DRM_MEM_AGPLISTS);
+			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;
+
+#if LINUX_VERSION_CODE >= 0x020400
+		case INTEL_I815:	head->chipset = "Intel i815";	 break;
+		case INTEL_I840:	head->chipset = "Intel i840";    break;
+		case INTEL_I850:	head->chipset = "Intel i850";	 break;
+#endif
+
+		case VIA_GENERIC:	head->chipset = "VIA";           break;
+		case VIA_VP3:		head->chipset = "VIA VP3";       break;
+		case VIA_MVP3:		head->chipset = "VIA MVP3";      break;
+#if LINUX_VERSION_CODE >= 0x020400
+		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;
+#endif
+
+		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 ALI_GENERIC:	head->chipset = "ALi";           break;
+		case ALI_M1541: 	head->chipset = "ALi M1541";     break;
+
+#if LINUX_VERSION_CODE >= 0x020402
+		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_M1647: 	head->chipset = "ALi M1647";	 break;
+		case ALI_M1651: 	head->chipset = "ALi M1651";	 break;
+#endif
+
+#if LINUX_VERSION_CODE >= 0x020406
+		case SVWRKS_HE: 	head->chipset = "Serverworks HE";
+			break;
+		case SVWRKS_LE: 	head->chipset = "Serverworks LE";
+			break;
+		case SVWRKS_GENERIC: 	head->chipset = "Serverworks Generic";
+			break;
+#endif
+
+		default:		head->chipset = "Unknown";       break;
+		}
+		DRM_INFO("AGP %d.%d on %s @ 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);
+	}
+	return head;
+}
+
+void DRM(agp_uninit)(void)
+{
+	DRM_AGP_PUT;
+	drm_agp = NULL;
+}
+
+agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type)
+{
+	if (!drm_agp->allocate_memory) return NULL;
+	return drm_agp->allocate_memory(pages, type);
+}
+
+int DRM(agp_free_memory)(agp_memory *handle)
+{
+	if (!handle || !drm_agp->free_memory) return 0;
+	drm_agp->free_memory(handle);
+	return 1;
+}
+
+int DRM(agp_bind_memory)(agp_memory *handle, off_t start)
+{
+	if (!handle || !drm_agp->bind_memory) return -EINVAL;
+	return drm_agp->bind_memory(handle, start);
+}
+
+int DRM(agp_unbind_memory)(agp_memory *handle)
+{
+	if (!handle || !drm_agp->unbind_memory) return -EINVAL;
+	return drm_agp->unbind_memory(handle);
+}
+
+#endif /* __REALLY_HAVE_AGP */
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_auth.h linux/drivers/char/drm/drm_auth.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_auth.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_auth.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,162 @@
+/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
+ * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+static int DRM(hash_magic)(drm_magic_t magic)
+{
+	return magic & (DRM_HASH_SIZE-1);
+}
+
+static drm_file_t *DRM(find_file)(drm_device_t *dev, drm_magic_t magic)
+{
+	drm_file_t	  *retval = NULL;
+	drm_magic_entry_t *pt;
+	int		  hash	  = DRM(hash_magic)(magic);
+
+	down(&dev->struct_sem);
+	for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
+		if (pt->magic == magic) {
+			retval = pt->priv;
+			break;
+		}
+	}
+	up(&dev->struct_sem);
+	return retval;
+}
+
+int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
+{
+	int		  hash;
+	drm_magic_entry_t *entry;
+
+	DRM_DEBUG("%d\n", magic);
+
+	hash	     = DRM(hash_magic)(magic);
+	entry	     = DRM(alloc)(sizeof(*entry), DRM_MEM_MAGIC);
+	if (!entry) return -ENOMEM;
+	entry->magic = magic;
+	entry->priv  = priv;
+	entry->next  = NULL;
+
+	down(&dev->struct_sem);
+	if (dev->magiclist[hash].tail) {
+		dev->magiclist[hash].tail->next = entry;
+		dev->magiclist[hash].tail	= entry;
+	} else {
+		dev->magiclist[hash].head	= entry;
+		dev->magiclist[hash].tail	= entry;
+	}
+	up(&dev->struct_sem);
+
+	return 0;
+}
+
+int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
+{
+	drm_magic_entry_t *prev = NULL;
+	drm_magic_entry_t *pt;
+	int		  hash;
+
+	DRM_DEBUG("%d\n", magic);
+	hash = DRM(hash_magic)(magic);
+
+	down(&dev->struct_sem);
+	for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
+		if (pt->magic == magic) {
+			if (dev->magiclist[hash].head == pt) {
+				dev->magiclist[hash].head = pt->next;
+			}
+			if (dev->magiclist[hash].tail == pt) {
+				dev->magiclist[hash].tail = prev;
+			}
+			if (prev) {
+				prev->next = pt->next;
+			}
+			up(&dev->struct_sem);
+			return 0;
+		}
+	}
+	up(&dev->struct_sem);
+
+	DRM(free)(pt, sizeof(*pt), DRM_MEM_MAGIC);
+
+	return -EINVAL;
+}
+
+int DRM(getmagic)(struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg)
+{
+	static drm_magic_t sequence = 0;
+	static spinlock_t  lock	    = SPIN_LOCK_UNLOCKED;
+	drm_file_t	   *priv    = filp->private_data;
+	drm_device_t	   *dev	    = priv->dev;
+	drm_auth_t	   auth;
+
+				/* Find unique magic */
+	if (priv->magic) {
+		auth.magic = priv->magic;
+	} else {
+		do {
+			spin_lock(&lock);
+			if (!sequence) ++sequence; /* reserve 0 */
+			auth.magic = sequence++;
+			spin_unlock(&lock);
+		} while (DRM(find_file)(dev, auth.magic));
+		priv->magic = auth.magic;
+		DRM(add_magic)(dev, priv, auth.magic);
+	}
+
+	DRM_DEBUG("%u\n", auth.magic);
+	if (copy_to_user((drm_auth_t *)arg, &auth, sizeof(auth)))
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(authmagic)(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_auth_t	   auth;
+	drm_file_t	   *file;
+
+	if (copy_from_user(&auth, (drm_auth_t *)arg, sizeof(auth)))
+		return -EFAULT;
+	DRM_DEBUG("%u\n", auth.magic);
+	if ((file = DRM(find_file)(dev, auth.magic))) {
+		file->authenticated = 1;
+		DRM(remove_magic)(dev, auth.magic);
+		return 0;
+	}
+	return -EINVAL;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_bufs.h linux/drivers/char/drm/drm_bufs.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_bufs.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_bufs.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,1140 @@
+/* drm_bufs.h -- Generic buffer template -*- linux-c -*-
+ * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include <linux/vmalloc.h>
+#include "drmP.h"
+
+#ifndef __HAVE_PCI_DMA
+#define __HAVE_PCI_DMA		0
+#endif
+
+#ifndef __HAVE_SG
+#define __HAVE_SG		0
+#endif
+
+#ifndef DRIVER_BUF_PRIV_T
+#define DRIVER_BUF_PRIV_T		u32
+#endif
+#ifndef DRIVER_AGP_BUFFERS_MAP
+#if __HAVE_AGP && __HAVE_DMA
+#error "You must define DRIVER_AGP_BUFFERS_MAP()"
+#else
+#define DRIVER_AGP_BUFFERS_MAP( dev )	NULL
+#endif
+#endif
+
+/*
+ * Compute order.  Can be made faster.
+ */
+int DRM(order)( unsigned long size )
+{
+	int order;
+	unsigned long tmp;
+
+	for ( order = 0, tmp = size ; tmp >>= 1 ; ++order );
+
+	if ( size & ~(1 << order) )
+		++order;
+
+	return order;
+}
+
+int DRM(addmap)( 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_map_t *map;
+	drm_map_list_t *list;
+
+	if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */
+
+	map = DRM(alloc)( sizeof(*map), DRM_MEM_MAPS );
+	if ( !map )
+		return -ENOMEM;
+
+	if ( copy_from_user( map, (drm_map_t *)arg, sizeof(*map) ) ) {
+		DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+		return -EFAULT;
+	}
+
+	/* Only allow shared memory to be removable since we only keep enough
+	 * book keeping information about shared memory to allow for removal
+	 * when processes fork.
+	 */
+	if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) {
+		DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+		return -EINVAL;
+	}
+	DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+		   map->offset, map->size, map->type );
+	if ( (map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK)) ) {
+		DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+		return -EINVAL;
+	}
+	map->mtrr   = -1;
+	map->handle = 0;
+
+	switch ( map->type ) {
+	case _DRM_REGISTERS:
+	case _DRM_FRAME_BUFFER:
+#if !defined(__sparc__) && !defined(__alpha__)
+		if ( map->offset + map->size < map->offset ||
+		     map->offset < virt_to_phys(high_memory) ) {
+			DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+			return -EINVAL;
+		}
+#endif
+#ifdef __alpha__
+		map->offset += dev->hose->mem_space->start;
+#endif
+#if __REALLY_HAVE_MTRR
+		if ( map->type == _DRM_FRAME_BUFFER ||
+		     (map->flags & _DRM_WRITE_COMBINING) ) {
+			map->mtrr = mtrr_add( map->offset, map->size,
+					      MTRR_TYPE_WRCOMB, 1 );
+		}
+#endif
+		map->handle = DRM(ioremap)( map->offset, map->size );
+		break;
+
+	case _DRM_SHM:
+		map->handle = vmalloc_32(map->size);
+		DRM_DEBUG( "%ld %d %p\n",
+			   map->size, DRM(order)( map->size ), map->handle );
+		if ( !map->handle ) {
+			DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+			return -ENOMEM;
+		}
+		map->offset = (unsigned long)map->handle;
+		if ( map->flags & _DRM_CONTAINS_LOCK ) {
+			dev->lock.hw_lock = map->handle; /* Pointer to lock */
+		}
+		break;
+#if __REALLY_HAVE_AGP
+	case _DRM_AGP:
+#ifdef __alpha__
+		map->offset += dev->hose->mem_space->start;
+#endif
+		map->offset = map->offset + dev->agp->base;
+		map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
+		break;
+#endif
+	case _DRM_SCATTER_GATHER:
+		if (!dev->sg) {
+			DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+			return -EINVAL;
+		}
+		map->offset = map->offset + dev->sg->handle;
+		break;
+
+	default:
+		DRM(free)( map, sizeof(*map), DRM_MEM_MAPS );
+		return -EINVAL;
+	}
+
+	list = DRM(alloc)(sizeof(*list), DRM_MEM_MAPS);
+	if(!list) {
+		DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+		return -EINVAL;
+	}
+	memset(list, 0, sizeof(*list));
+	list->map = map;
+
+	down(&dev->struct_sem);
+	list_add(&list->head, &dev->maplist->head);
+ 	up(&dev->struct_sem);
+
+	if ( copy_to_user( (drm_map_t *)arg, map, sizeof(*map) ) )
+		return -EFAULT;
+	if ( map->type != _DRM_SHM ) {
+		if ( copy_to_user( &((drm_map_t *)arg)->handle,
+				   &map->offset,
+				   sizeof(map->offset) ) )
+			return -EFAULT;
+	}
+	return 0;
+}
+
+
+/* Remove a map private from list and deallocate resources if the mapping
+ * isn't in use.
+ */
+
+int DRM(rmmap)(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;
+	struct list_head *list;
+	drm_map_list_t *r_list = NULL;
+	drm_vma_entry_t *pt, *prev;
+	drm_map_t *map;
+	drm_map_t request;
+	int found_maps = 0;
+
+	if (copy_from_user(&request, (drm_map_t *)arg,
+			   sizeof(request))) {
+		return -EFAULT;
+	}
+
+	down(&dev->struct_sem);
+	list = &dev->maplist->head;
+	list_for_each(list, &dev->maplist->head) {
+		r_list = (drm_map_list_t *) list;
+
+		if(r_list->map &&
+		   r_list->map->handle == request.handle &&
+		   r_list->map->flags & _DRM_REMOVABLE) break;
+	}
+
+	/* List has wrapped around to the head pointer, or its empty we didn't
+	 * find anything.
+	 */
+	if(list == (&dev->maplist->head)) {
+		up(&dev->struct_sem);
+		return -EINVAL;
+	}
+	map = r_list->map;
+	list_del(list);
+	DRM(free)(list, sizeof(*list), DRM_MEM_MAPS);
+
+	for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+#if LINUX_VERSION_CODE >= 0x020300
+		if (pt->vma->vm_private_data == map) found_maps++;
+#else
+		if (pt->vma->vm_pte == map) found_maps++;
+#endif
+	}
+
+	if(!found_maps) {
+		switch (map->type) {
+		case _DRM_REGISTERS:
+		case _DRM_FRAME_BUFFER:
+#if __REALLY_HAVE_MTRR
+			if (map->mtrr >= 0) {
+				int retcode;
+				retcode = mtrr_del(map->mtrr,
+						   map->offset,
+						   map->size);
+				DRM_DEBUG("mtrr_del = %d\n", retcode);
+			}
+#endif
+			DRM(ioremapfree)(map->handle, map->size);
+			break;
+		case _DRM_SHM:
+			vfree(map->handle);
+			break;
+		case _DRM_AGP:
+		case _DRM_SCATTER_GATHER:
+			break;
+		}
+		DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+	}
+	up(&dev->struct_sem);
+	return 0;
+}
+
+#if __HAVE_DMA
+
+
+static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
+{
+	int i;
+
+	if (entry->seg_count) {
+		for (i = 0; i < entry->seg_count; i++) {
+			DRM(free_pages)(entry->seglist[i],
+					entry->page_order,
+					DRM_MEM_DMA);
+		}
+		DRM(free)(entry->seglist,
+			  entry->seg_count *
+			  sizeof(*entry->seglist),
+			  DRM_MEM_SEGS);
+
+		entry->seg_count = 0;
+	}
+
+   	if(entry->buf_count) {
+	   	for(i = 0; i < entry->buf_count; i++) {
+			if(entry->buflist[i].dev_private) {
+				DRM(free)(entry->buflist[i].dev_private,
+					  entry->buflist[i].dev_priv_size,
+					  DRM_MEM_BUFS);
+			}
+		}
+		DRM(free)(entry->buflist,
+			  entry->buf_count *
+			  sizeof(*entry->buflist),
+			  DRM_MEM_BUFS);
+
+#if __HAVE_DMA_FREELIST
+	   	DRM(freelist_destroy)(&entry->freelist);
+#endif
+
+		entry->buf_count = 0;
+	}
+}
+
+#if __REALLY_HAVE_AGP
+int DRM(addbufs_agp)( 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_device_dma_t *dma = dev->dma;
+	drm_buf_desc_t request;
+	drm_buf_entry_t *entry;
+	drm_buf_t *buf;
+	unsigned long offset;
+	unsigned long agp_offset;
+	int count;
+	int order;
+	int size;
+	int alignment;
+	int page_order;
+	int total;
+	int byte_count;
+	int i;
+	drm_buf_t **temp_buflist;
+
+	if ( !dma ) return -EINVAL;
+
+	if ( copy_from_user( &request, (drm_buf_desc_t *)arg,
+			     sizeof(request) ) )
+		return -EFAULT;
+
+	count = request.count;
+	order = DRM(order)( request.size );
+	size = 1 << order;
+
+	alignment  = (request.flags & _DRM_PAGE_ALIGN)
+		? PAGE_ALIGN(size) : size;
+	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+	total = PAGE_SIZE << page_order;
+
+	byte_count = 0;
+	agp_offset = dev->agp->base + request.agp_start;
+
+	DRM_DEBUG( "count:      %d\n",  count );
+	DRM_DEBUG( "order:      %d\n",  order );
+	DRM_DEBUG( "size:       %d\n",  size );
+	DRM_DEBUG( "agp_offset: %ld\n", agp_offset );
+	DRM_DEBUG( "alignment:  %d\n",  alignment );
+	DRM_DEBUG( "page_order: %d\n",  page_order );
+	DRM_DEBUG( "total:      %d\n",  total );
+
+	if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+	if ( dev->queue_count ) return -EBUSY; /* Not while in use */
+
+	spin_lock( &dev->count_lock );
+	if ( dev->buf_use ) {
+		spin_unlock( &dev->count_lock );
+		return -EBUSY;
+	}
+	atomic_inc( &dev->buf_alloc );
+	spin_unlock( &dev->count_lock );
+
+	down( &dev->struct_sem );
+	entry = &dma->bufs[order];
+	if ( entry->buf_count ) {
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM; /* May only call once for each order */
+	}
+
+	if (count < 0 || count > 4096) {
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -EINVAL;
+	}
+
+	entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
+				    DRM_MEM_BUFS );
+	if ( !entry->buflist ) {
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM;
+	}
+	memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+
+	entry->buf_size = size;
+	entry->page_order = page_order;
+
+	offset = 0;
+
+	while ( entry->buf_count < count ) {
+		buf          = &entry->buflist[entry->buf_count];
+		buf->idx     = dma->buf_count + entry->buf_count;
+		buf->total   = alignment;
+		buf->order   = order;
+		buf->used    = 0;
+
+		buf->offset  = (dma->byte_count + offset);
+		buf->bus_address = agp_offset + offset;
+		buf->address = (void *)(agp_offset + offset);
+		buf->next    = NULL;
+		buf->waiting = 0;
+		buf->pending = 0;
+		init_waitqueue_head( &buf->dma_wait );
+		buf->pid     = 0;
+
+		buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
+		buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+					       DRM_MEM_BUFS );
+		if(!buf->dev_private) {
+			/* Set count correctly so we free the proper amount. */
+			entry->buf_count = count;
+			DRM(cleanup_buf_error)(entry);
+		}
+		memset( buf->dev_private, 0, buf->dev_priv_size );
+
+#if __HAVE_DMA_HISTOGRAM
+		buf->time_queued = 0;
+		buf->time_dispatched = 0;
+		buf->time_completed = 0;
+		buf->time_freed = 0;
+#endif
+		DRM_DEBUG( "buffer %d @ %p\n",
+			   entry->buf_count, buf->address );
+
+		offset += alignment;
+		entry->buf_count++;
+		byte_count += PAGE_SIZE << page_order;
+	}
+
+	DRM_DEBUG( "byte_count: %d\n", byte_count );
+
+	temp_buflist = DRM(realloc)( dma->buflist,
+				     dma->buf_count * sizeof(*dma->buflist),
+				     (dma->buf_count + entry->buf_count)
+				     * sizeof(*dma->buflist),
+				     DRM_MEM_BUFS );
+	if(!temp_buflist) {
+		/* Free the entry because it isn't valid */
+		DRM(cleanup_buf_error)(entry);
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM;
+	}
+	dma->buflist = temp_buflist;
+
+	for ( i = 0 ; i < entry->buf_count ; i++ ) {
+		dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+	}
+
+	dma->buf_count += entry->buf_count;
+	dma->byte_count += byte_count;
+
+	DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+	DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
+
+#if __HAVE_DMA_FREELIST
+	DRM(freelist_create)( &entry->freelist, entry->buf_count );
+	for ( i = 0 ; i < entry->buf_count ; i++ ) {
+		DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
+	}
+#endif
+	up( &dev->struct_sem );
+
+	request.count = entry->buf_count;
+	request.size = size;
+
+	if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
+		return -EFAULT;
+
+	dma->flags = _DRM_DMA_USE_AGP;
+
+	atomic_dec( &dev->buf_alloc );
+	return 0;
+}
+#endif /* __REALLY_HAVE_AGP */
+
+#if __HAVE_PCI_DMA
+int DRM(addbufs_pci)( 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_device_dma_t *dma = dev->dma;
+	drm_buf_desc_t request;
+	int count;
+	int order;
+	int size;
+	int total;
+	int page_order;
+	drm_buf_entry_t *entry;
+	unsigned long page;
+	drm_buf_t *buf;
+	int alignment;
+	unsigned long offset;
+	int i;
+	int byte_count;
+	int page_count;
+	unsigned long *temp_pagelist;
+	drm_buf_t **temp_buflist;
+
+	if ( !dma ) return -EINVAL;
+
+	if ( copy_from_user( &request, (drm_buf_desc_t *)arg,
+			     sizeof(request) ) )
+		return -EFAULT;
+
+	count = request.count;
+	order = DRM(order)( request.size );
+	size = 1 << order;
+
+	DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n",
+		   request.count, request.size, size,
+		   order, dev->queue_count );
+
+	if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+	if ( dev->queue_count ) return -EBUSY; /* Not while in use */
+
+	alignment = (request.flags & _DRM_PAGE_ALIGN)
+		? PAGE_ALIGN(size) : size;
+	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+	total = PAGE_SIZE << page_order;
+
+	spin_lock( &dev->count_lock );
+	if ( dev->buf_use ) {
+		spin_unlock( &dev->count_lock );
+		return -EBUSY;
+	}
+	atomic_inc( &dev->buf_alloc );
+	spin_unlock( &dev->count_lock );
+
+	down( &dev->struct_sem );
+	entry = &dma->bufs[order];
+	if ( entry->buf_count ) {
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM;	/* May only call once for each order */
+	}
+
+	if (count < 0 || count > 4096) {
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -EINVAL;
+	}
+
+	entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
+				    DRM_MEM_BUFS );
+	if ( !entry->buflist ) {
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM;
+	}
+	memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+
+	entry->seglist = DRM(alloc)( count * sizeof(*entry->seglist),
+				    DRM_MEM_SEGS );
+	if ( !entry->seglist ) {
+		DRM(free)( entry->buflist,
+			  count * sizeof(*entry->buflist),
+			  DRM_MEM_BUFS );
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM;
+	}
+	memset( entry->seglist, 0, count * sizeof(*entry->seglist) );
+
+	temp_pagelist = DRM(realloc)( dma->pagelist,
+				      dma->page_count * sizeof(*dma->pagelist),
+				      (dma->page_count + (count << page_order))
+				      * sizeof(*dma->pagelist),
+				      DRM_MEM_PAGES );
+	if(!temp_pagelist) {
+		DRM(free)( entry->buflist,
+			   count * sizeof(*entry->buflist),
+			   DRM_MEM_BUFS );
+		DRM(free)( entry->seglist,
+			   count * sizeof(*entry->seglist),
+			   DRM_MEM_SEGS );
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM;
+	}
+
+	dma->pagelist = temp_pagelist;
+	DRM_DEBUG( "pagelist: %d entries\n",
+		   dma->page_count + (count << page_order) );
+
+	entry->buf_size	= size;
+	entry->page_order = page_order;
+	byte_count = 0;
+	page_count = 0;
+
+	while ( entry->buf_count < count ) {
+		page = DRM(alloc_pages)( page_order, DRM_MEM_DMA );
+		if ( !page ) break;
+		entry->seglist[entry->seg_count++] = page;
+		for ( i = 0 ; i < (1 << page_order) ; i++ ) {
+			DRM_DEBUG( "page %d @ 0x%08lx\n",
+				   dma->page_count + page_count,
+				   page + PAGE_SIZE * i );
+			dma->pagelist[dma->page_count + page_count++]
+				= page + PAGE_SIZE * i;
+		}
+		for ( offset = 0 ;
+		      offset + size <= total && entry->buf_count < count ;
+		      offset += alignment, ++entry->buf_count ) {
+			buf	     = &entry->buflist[entry->buf_count];
+			buf->idx     = dma->buf_count + entry->buf_count;
+			buf->total   = alignment;
+			buf->order   = order;
+			buf->used    = 0;
+			buf->offset  = (dma->byte_count + byte_count + offset);
+			buf->address = (void *)(page + offset);
+			buf->next    = NULL;
+			buf->waiting = 0;
+			buf->pending = 0;
+			init_waitqueue_head( &buf->dma_wait );
+			buf->pid     = 0;
+#if __HAVE_DMA_HISTOGRAM
+			buf->time_queued     = 0;
+			buf->time_dispatched = 0;
+			buf->time_completed  = 0;
+			buf->time_freed      = 0;
+#endif
+			DRM_DEBUG( "buffer %d @ %p\n",
+				   entry->buf_count, buf->address );
+		}
+		byte_count += PAGE_SIZE << page_order;
+	}
+
+	temp_buflist = DRM(realloc)( dma->buflist,
+				     dma->buf_count * sizeof(*dma->buflist),
+				     (dma->buf_count + entry->buf_count)
+				     * sizeof(*dma->buflist),
+				     DRM_MEM_BUFS );
+	if(!temp_buflist) {
+		/* Free the entry because it isn't valid */
+		DRM(cleanup_buf_error)(entry);
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM;
+	}
+	dma->buflist = temp_buflist;
+
+	for ( i = 0 ; i < entry->buf_count ; i++ ) {
+		dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+	}
+
+	dma->buf_count += entry->buf_count;
+	dma->seg_count += entry->seg_count;
+	dma->page_count += entry->seg_count << page_order;
+	dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
+
+#if __HAVE_DMA_FREELIST
+	DRM(freelist_create)( &entry->freelist, entry->buf_count );
+	for ( i = 0 ; i < entry->buf_count ; i++ ) {
+		DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
+	}
+#endif
+	up( &dev->struct_sem );
+
+	request.count = entry->buf_count;
+	request.size = size;
+
+	if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
+		return -EFAULT;
+
+	atomic_dec( &dev->buf_alloc );
+	return 0;
+
+}
+#endif /* __HAVE_PCI_DMA */
+
+#ifdef __HAVE_SG
+int DRM(addbufs_sg)( 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_device_dma_t *dma = dev->dma;
+	drm_buf_desc_t request;
+	drm_buf_entry_t *entry;
+	drm_buf_t *buf;
+	unsigned long offset;
+	unsigned long agp_offset;
+	int count;
+	int order;
+	int size;
+	int alignment;
+	int page_order;
+	int total;
+	int byte_count;
+	int i;
+	drm_buf_t **temp_buflist;
+
+	if ( !dma ) return -EINVAL;
+
+	if ( copy_from_user( &request, (drm_buf_desc_t *)arg,
+                             sizeof(request) ) )
+		return -EFAULT;
+
+	count = request.count;
+	order = DRM(order)( request.size );
+	size = 1 << order;
+
+	alignment  = (request.flags & _DRM_PAGE_ALIGN)
+			? PAGE_ALIGN(size) : size;
+	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+	total = PAGE_SIZE << page_order;
+
+	byte_count = 0;
+	agp_offset = request.agp_start;
+
+	DRM_DEBUG( "count:      %d\n",  count );
+	DRM_DEBUG( "order:      %d\n",  order );
+	DRM_DEBUG( "size:       %d\n",  size );
+	DRM_DEBUG( "agp_offset: %ld\n", agp_offset );
+	DRM_DEBUG( "alignment:  %d\n",  alignment );
+	DRM_DEBUG( "page_order: %d\n",  page_order );
+	DRM_DEBUG( "total:      %d\n",  total );
+
+	if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+	if ( dev->queue_count ) return -EBUSY; /* Not while in use */
+
+	spin_lock( &dev->count_lock );
+	if ( dev->buf_use ) {
+		spin_unlock( &dev->count_lock );
+		return -EBUSY;
+	}
+	atomic_inc( &dev->buf_alloc );
+	spin_unlock( &dev->count_lock );
+
+	down( &dev->struct_sem );
+	entry = &dma->bufs[order];
+	if ( entry->buf_count ) {
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM; /* May only call once for each order */
+	}
+
+	if (count < 0 || count > 4096) {
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -EINVAL;
+	}
+
+	entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist),
+				     DRM_MEM_BUFS );
+	if ( !entry->buflist ) {
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM;
+	}
+	memset( entry->buflist, 0, count * sizeof(*entry->buflist) );
+
+	entry->buf_size = size;
+	entry->page_order = page_order;
+
+	offset = 0;
+
+	while ( entry->buf_count < count ) {
+		buf          = &entry->buflist[entry->buf_count];
+		buf->idx     = dma->buf_count + entry->buf_count;
+		buf->total   = alignment;
+		buf->order   = order;
+		buf->used    = 0;
+
+		buf->offset  = (dma->byte_count + offset);
+		buf->bus_address = agp_offset + offset;
+		buf->address = (void *)(agp_offset + offset + dev->sg->handle);
+		buf->next    = NULL;
+		buf->waiting = 0;
+		buf->pending = 0;
+		init_waitqueue_head( &buf->dma_wait );
+		buf->pid     = 0;
+
+		buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
+		buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+					       DRM_MEM_BUFS );
+		if(!buf->dev_private) {
+			/* Set count correctly so we free the proper amount. */
+			entry->buf_count = count;
+			DRM(cleanup_buf_error)(entry);
+			up( &dev->struct_sem );
+			atomic_dec( &dev->buf_alloc );
+			return -ENOMEM;
+		}
+
+		memset( buf->dev_private, 0, buf->dev_priv_size );
+
+# if __HAVE_DMA_HISTOGRAM
+		buf->time_queued = 0;
+		buf->time_dispatched = 0;
+		buf->time_completed = 0;
+		buf->time_freed = 0;
+# endif
+		DRM_DEBUG( "buffer %d @ %p\n",
+			   entry->buf_count, buf->address );
+
+		offset += alignment;
+		entry->buf_count++;
+		byte_count += PAGE_SIZE << page_order;
+	}
+
+	DRM_DEBUG( "byte_count: %d\n", byte_count );
+
+	temp_buflist = DRM(realloc)( dma->buflist,
+				     dma->buf_count * sizeof(*dma->buflist),
+				     (dma->buf_count + entry->buf_count)
+				     * sizeof(*dma->buflist),
+				     DRM_MEM_BUFS );
+	if(!temp_buflist) {
+		/* Free the entry because it isn't valid */
+		DRM(cleanup_buf_error)(entry);
+		up( &dev->struct_sem );
+		atomic_dec( &dev->buf_alloc );
+		return -ENOMEM;
+	}
+	dma->buflist = temp_buflist;
+
+	for ( i = 0 ; i < entry->buf_count ; i++ ) {
+		dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+	}
+
+	dma->buf_count += entry->buf_count;
+	dma->byte_count += byte_count;
+
+	DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
+	DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
+
+#if __HAVE_DMA_FREELIST
+	DRM(freelist_create)( &entry->freelist, entry->buf_count );
+	for ( i = 0 ; i < entry->buf_count ; i++ ) {
+		DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
+	}
+#endif
+	up( &dev->struct_sem );
+
+	request.count = entry->buf_count;
+	request.size = size;
+
+	if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) )
+		return -EFAULT;
+
+	dma->flags = _DRM_DMA_USE_SG;
+
+	atomic_dec( &dev->buf_alloc );
+	return 0;
+}
+#endif /* __HAVE_SG */
+
+int DRM(addbufs)( struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg )
+{
+	drm_buf_desc_t request;
+
+	if ( copy_from_user( &request, (drm_buf_desc_t *)arg,
+			     sizeof(request) ) )
+		return -EFAULT;
+
+#if __REALLY_HAVE_AGP
+	if ( request.flags & _DRM_AGP_BUFFER )
+		return DRM(addbufs_agp)( inode, filp, cmd, arg );
+	else
+#endif
+#if __HAVE_SG
+	if ( request.flags & _DRM_SG_BUFFER )
+		return DRM(addbufs_sg)( inode, filp, cmd, arg );
+	else
+#endif
+#if __HAVE_PCI_DMA
+		return DRM(addbufs_pci)( inode, filp, cmd, arg );
+#else
+		return -EINVAL;
+#endif
+}
+
+int DRM(infobufs)( 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_device_dma_t *dma = dev->dma;
+	drm_buf_info_t request;
+	int i;
+	int count;
+
+	if ( !dma ) return -EINVAL;
+
+	spin_lock( &dev->count_lock );
+	if ( atomic_read( &dev->buf_alloc ) ) {
+		spin_unlock( &dev->count_lock );
+		return -EBUSY;
+	}
+	++dev->buf_use;		/* Can't allocate more after this call */
+	spin_unlock( &dev->count_lock );
+
+	if ( copy_from_user( &request,
+			     (drm_buf_info_t *)arg,
+			     sizeof(request) ) )
+		return -EFAULT;
+
+	for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
+		if ( dma->bufs[i].buf_count ) ++count;
+	}
+
+	DRM_DEBUG( "count = %d\n", count );
+
+	if ( request.count >= count ) {
+		for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
+			if ( dma->bufs[i].buf_count ) {
+				drm_buf_desc_t *to = &request.list[count];
+				drm_buf_entry_t *from = &dma->bufs[i];
+				drm_freelist_t *list = &dma->bufs[i].freelist;
+				if ( copy_to_user( &to->count,
+						   &from->buf_count,
+						   sizeof(from->buf_count) ) ||
+				     copy_to_user( &to->size,
+						   &from->buf_size,
+						   sizeof(from->buf_size) ) ||
+				     copy_to_user( &to->low_mark,
+						   &list->low_mark,
+						   sizeof(list->low_mark) ) ||
+				     copy_to_user( &to->high_mark,
+						   &list->high_mark,
+						   sizeof(list->high_mark) ) )
+					return -EFAULT;
+
+				DRM_DEBUG( "%d %d %d %d %d\n",
+					   i,
+					   dma->bufs[i].buf_count,
+					   dma->bufs[i].buf_size,
+					   dma->bufs[i].freelist.low_mark,
+					   dma->bufs[i].freelist.high_mark );
+				++count;
+			}
+		}
+	}
+	request.count = count;
+
+	if ( copy_to_user( (drm_buf_info_t *)arg,
+			   &request,
+			   sizeof(request) ) )
+		return -EFAULT;
+
+	return 0;
+}
+
+int DRM(markbufs)( 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_device_dma_t *dma = dev->dma;
+	drm_buf_desc_t request;
+	int order;
+	drm_buf_entry_t *entry;
+
+	if ( !dma ) return -EINVAL;
+
+	if ( copy_from_user( &request,
+			     (drm_buf_desc_t *)arg,
+			     sizeof(request) ) )
+		return -EFAULT;
+
+	DRM_DEBUG( "%d, %d, %d\n",
+		   request.size, request.low_mark, request.high_mark );
+	order = DRM(order)( request.size );
+	if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL;
+	entry = &dma->bufs[order];
+
+	if ( request.low_mark < 0 || request.low_mark > entry->buf_count )
+		return -EINVAL;
+	if ( request.high_mark < 0 || request.high_mark > entry->buf_count )
+		return -EINVAL;
+
+	entry->freelist.low_mark  = request.low_mark;
+	entry->freelist.high_mark = request.high_mark;
+
+	return 0;
+}
+
+int DRM(freebufs)( 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_device_dma_t *dma = dev->dma;
+	drm_buf_free_t request;
+	int i;
+	int idx;
+	drm_buf_t *buf;
+
+	if ( !dma ) return -EINVAL;
+
+	if ( copy_from_user( &request,
+			     (drm_buf_free_t *)arg,
+			     sizeof(request) ) )
+		return -EFAULT;
+
+	DRM_DEBUG( "%d\n", request.count );
+	for ( i = 0 ; i < request.count ; i++ ) {
+		if ( copy_from_user( &idx,
+				     &request.list[i],
+				     sizeof(idx) ) )
+			return -EFAULT;
+		if ( idx < 0 || idx >= dma->buf_count ) {
+			DRM_ERROR( "Index %d (of %d max)\n",
+				   idx, dma->buf_count - 1 );
+			return -EINVAL;
+		}
+		buf = dma->buflist[idx];
+		if ( buf->pid != current->pid ) {
+			DRM_ERROR( "Process %d freeing buffer owned by %d\n",
+				   current->pid, buf->pid );
+			return -EINVAL;
+		}
+		DRM(free_buffer)( dev, buf );
+	}
+
+	return 0;
+}
+
+int DRM(mapbufs)( 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_device_dma_t *dma = dev->dma;
+	int retcode = 0;
+	const int zero = 0;
+	unsigned long virtual;
+	unsigned long address;
+	drm_buf_map_t request;
+	int i;
+
+	if ( !dma ) return -EINVAL;
+
+	spin_lock( &dev->count_lock );
+	if ( atomic_read( &dev->buf_alloc ) ) {
+		spin_unlock( &dev->count_lock );
+		return -EBUSY;
+	}
+	dev->buf_use++;		/* Can't allocate more after this call */
+	spin_unlock( &dev->count_lock );
+
+	if ( copy_from_user( &request, (drm_buf_map_t *)arg,
+			     sizeof(request) ) )
+		return -EFAULT;
+
+	if ( request.count >= dma->buf_count ) {
+		if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) ||
+		     (__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) {
+			drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
+
+			if ( !map ) {
+				retcode = -EINVAL;
+				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 */
+			retcode = (signed long)virtual;
+			goto done;
+		}
+		request.virtual = (void *)virtual;
+
+		for ( i = 0 ; i < dma->buf_count ; i++ ) {
+			if ( copy_to_user( &request.list[i].idx,
+					   &dma->buflist[i]->idx,
+					   sizeof(request.list[0].idx) ) ) {
+				retcode = -EFAULT;
+				goto done;
+			}
+			if ( copy_to_user( &request.list[i].total,
+					   &dma->buflist[i]->total,
+					   sizeof(request.list[0].total) ) ) {
+				retcode = -EFAULT;
+				goto done;
+			}
+			if ( copy_to_user( &request.list[i].used,
+					   &zero,
+					   sizeof(zero) ) ) {
+				retcode = -EFAULT;
+				goto done;
+			}
+			address = virtual + dma->buflist[i]->offset; /* *** */
+			if ( copy_to_user( &request.list[i].address,
+					   &address,
+					   sizeof(address) ) ) {
+				retcode = -EFAULT;
+				goto done;
+			}
+		}
+	}
+ done:
+	request.count = dma->buf_count;
+	DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode );
+
+	if ( copy_to_user( (drm_buf_map_t *)arg, &request, sizeof(request) ) )
+		return -EFAULT;
+
+	return retcode;
+}
+
+#endif /* __HAVE_DMA */
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_context.h linux/drivers/char/drm/drm_context.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_context.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_context.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,772 @@
+/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
+ * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+#if __HAVE_CTX_BITMAP
+
+/* ================================================================
+ * Context bitmap support
+ */
+
+void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle )
+{
+	if ( ctx_handle < 0 ) goto failed;
+	if ( !dev->ctx_bitmap ) goto failed;
+
+	if ( ctx_handle < DRM_MAX_CTXBITMAP ) {
+		down(&dev->struct_sem);
+		clear_bit( ctx_handle, dev->ctx_bitmap );
+		dev->context_sareas[ctx_handle] = NULL;
+		up(&dev->struct_sem);
+		return;
+	}
+failed:
+       	DRM_ERROR( "Attempt to free invalid context handle: %d\n",
+		   ctx_handle );
+       	return;
+}
+
+int DRM(ctxbitmap_next)( drm_device_t *dev )
+{
+	int bit;
+
+	if(!dev->ctx_bitmap) return -1;
+
+	down(&dev->struct_sem);
+	bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
+	if ( bit < DRM_MAX_CTXBITMAP ) {
+		set_bit( bit, dev->ctx_bitmap );
+	   	DRM_DEBUG( "drm_ctxbitmap_next bit : %d\n", bit );
+		if((bit+1) > dev->max_context) {
+			dev->max_context = (bit+1);
+			if(dev->context_sareas) {
+				drm_map_t **ctx_sareas;
+
+				ctx_sareas = DRM(realloc)(dev->context_sareas,
+						(dev->max_context - 1) * 
+						sizeof(*dev->context_sareas),
+						dev->max_context * 
+						sizeof(*dev->context_sareas),
+						DRM_MEM_MAPS);
+				if(!ctx_sareas) {
+					clear_bit(bit, dev->ctx_bitmap);
+					up(&dev->struct_sem);
+					return -1;
+				}
+				dev->context_sareas = ctx_sareas;
+				dev->context_sareas[bit] = NULL;
+			} else {
+				/* max_context == 1 at this point */
+				dev->context_sareas = DRM(alloc)(
+						dev->max_context * 
+						sizeof(*dev->context_sareas),
+						DRM_MEM_MAPS);
+				if(!dev->context_sareas) {
+					clear_bit(bit, dev->ctx_bitmap);
+					up(&dev->struct_sem);
+					return -1;
+				}
+				dev->context_sareas[bit] = NULL;
+			}
+		}
+		up(&dev->struct_sem);
+		return bit;
+	}
+	up(&dev->struct_sem);
+	return -1;
+}
+
+int DRM(ctxbitmap_init)( drm_device_t *dev )
+{
+	int i;
+   	int temp;
+
+	down(&dev->struct_sem);
+	dev->ctx_bitmap = (unsigned long *) DRM(alloc)( PAGE_SIZE,
+							DRM_MEM_CTXBITMAP );
+	if ( dev->ctx_bitmap == NULL ) {
+		up(&dev->struct_sem);
+		return -ENOMEM;
+	}
+	memset( (void *)dev->ctx_bitmap, 0, PAGE_SIZE );
+	dev->context_sareas = NULL;
+	dev->max_context = -1;
+	up(&dev->struct_sem);
+
+	for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
+		temp = DRM(ctxbitmap_next)( dev );
+	   	DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp );
+	}
+
+	return 0;
+}
+
+void DRM(ctxbitmap_cleanup)( drm_device_t *dev )
+{
+	down(&dev->struct_sem);
+	if( dev->context_sareas ) DRM(free)( dev->context_sareas,
+					     sizeof(*dev->context_sareas) * 
+					     dev->max_context,
+					     DRM_MEM_MAPS );
+	DRM(free)( (void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP );
+	up(&dev->struct_sem);
+}
+
+/* ================================================================
+ * Per Context SAREA Support
+ */
+
+int DRM(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 DRM(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);
+	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;
+}
+
+/* ================================================================
+ * The actual DRM context handling routines
+ */
+
+int DRM(context_switch)( drm_device_t *dev, int old, int new )
+{
+        char buf[64];
+
+        if ( test_and_set_bit( 0, &dev->context_flag ) ) {
+                DRM_ERROR( "Reentering -- FIXME\n" );
+                return -EBUSY;
+        }
+
+#if __HAVE_DMA_HISTOGRAM
+        dev->ctx_start = get_cycles();
+#endif
+
+        DRM_DEBUG( "Context switch from %d to %d\n", old, new );
+
+        if ( new == dev->last_context ) {
+                clear_bit( 0, &dev->context_flag );
+                return 0;
+        }
+
+        if ( DRM(flags) & DRM_FLAG_NOCTX ) {
+                DRM(context_switch_complete)( dev, new );
+        } else {
+                sprintf( buf, "C %d %d\n", old, new );
+                DRM(write_string)( dev, buf );
+        }
+
+        return 0;
+}
+
+int DRM(context_switch_complete)( drm_device_t *dev, int new )
+{
+        dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
+        dev->last_switch  = jiffies;
+
+        if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
+                DRM_ERROR( "Lock isn't held after context switch\n" );
+        }
+
+				/* If a context switch is ever initiated
+                                   when the kernel holds the lock, release
+                                   that lock here. */
+#if __HAVE_DMA_HISTOGRAM
+        atomic_inc( &dev->histo.ctx[DRM(histogram_slot)(get_cycles()
+							- dev->ctx_start)] );
+
+#endif
+        clear_bit( 0, &dev->context_flag );
+        wake_up( &dev->context_wait );
+
+        return 0;
+}
+
+int DRM(resctx)( struct inode *inode, struct file *filp,
+		 unsigned int cmd, unsigned long arg )
+{
+	drm_ctx_res_t res;
+	drm_ctx_t ctx;
+	int i;
+
+	if ( copy_from_user( &res, (drm_ctx_res_t *)arg, sizeof(res) ) )
+		return -EFAULT;
+
+	if ( res.count >= DRM_RESERVED_CONTEXTS ) {
+		memset( &ctx, 0, sizeof(ctx) );
+		for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
+			ctx.handle = i;
+			if ( copy_to_user( &res.contexts[i],
+					   &i, sizeof(i) ) )
+				return -EFAULT;
+		}
+	}
+	res.count = DRM_RESERVED_CONTEXTS;
+
+	if ( copy_to_user( (drm_ctx_res_t *)arg, &res, sizeof(res) ) )
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(addctx)( 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_t ctx;
+
+	if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
+		return -EFAULT;
+
+	ctx.handle = DRM(ctxbitmap_next)( dev );
+	if ( ctx.handle == DRM_KERNEL_CONTEXT ) {
+				/* Skip kernel's context and get a new one. */
+		ctx.handle = DRM(ctxbitmap_next)( dev );
+	}
+	DRM_DEBUG( "%d\n", ctx.handle );
+	if ( ctx.handle == -1 ) {
+		DRM_DEBUG( "Not enough free contexts.\n" );
+				/* Should this return -EBUSY instead? */
+		return -ENOMEM;
+	}
+
+	if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) )
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(modctx)( struct inode *inode, struct file *filp,
+		 unsigned int cmd, unsigned long arg )
+{
+	/* This does nothing */
+	return 0;
+}
+
+int DRM(getctx)( struct inode *inode, struct file *filp,
+		 unsigned int cmd, unsigned long arg )
+{
+	drm_ctx_t ctx;
+
+	if ( copy_from_user( &ctx, (drm_ctx_t*)arg, sizeof(ctx) ) )
+		return -EFAULT;
+
+	/* This is 0, because we don't handle any context flags */
+	ctx.flags = 0;
+
+	if ( copy_to_user( (drm_ctx_t*)arg, &ctx, sizeof(ctx) ) )
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(switchctx)( 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_t ctx;
+
+	if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
+		return -EFAULT;
+
+	DRM_DEBUG( "%d\n", ctx.handle );
+	return DRM(context_switch)( dev, dev->last_context, ctx.handle );
+}
+
+int DRM(newctx)( 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_t ctx;
+
+	if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
+		return -EFAULT;
+
+	DRM_DEBUG( "%d\n", ctx.handle );
+	DRM(context_switch_complete)( dev, ctx.handle );
+
+	return 0;
+}
+
+int DRM(rmctx)( 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_t ctx;
+
+	if ( copy_from_user( &ctx, (drm_ctx_t *)arg, sizeof(ctx) ) )
+		return -EFAULT;
+
+	DRM_DEBUG( "%d\n", ctx.handle );
+	if ( ctx.handle == DRM_KERNEL_CONTEXT + 1 ) {
+		priv->remove_auth_on_close = 1;
+	}
+	if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
+		DRM(ctxbitmap_free)( dev, ctx.handle );
+	}
+
+	return 0;
+}
+
+
+#else /* __HAVE_CTX_BITMAP */
+
+/* ================================================================
+ * Old-style context support
+ */
+
+
+int DRM(context_switch)(drm_device_t *dev, int old, int new)
+{
+	char	    buf[64];
+	drm_queue_t *q;
+
+#if 0
+	atomic_inc(&dev->total_ctx);
+#endif
+
+	if (test_and_set_bit(0, &dev->context_flag)) {
+		DRM_ERROR("Reentering -- FIXME\n");
+		return -EBUSY;
+	}
+
+#if __HAVE_DMA_HISTOGRAM
+	dev->ctx_start = get_cycles();
+#endif
+
+	DRM_DEBUG("Context switch from %d to %d\n", old, new);
+
+	if (new >= dev->queue_count) {
+		clear_bit(0, &dev->context_flag);
+		return -EINVAL;
+	}
+
+	if (new == dev->last_context) {
+		clear_bit(0, &dev->context_flag);
+		return 0;
+	}
+
+	q = dev->queuelist[new];
+	atomic_inc(&q->use_count);
+	if (atomic_read(&q->use_count) == 1) {
+		atomic_dec(&q->use_count);
+		clear_bit(0, &dev->context_flag);
+		return -EINVAL;
+	}
+
+	if (DRM(flags) & DRM_FLAG_NOCTX) {
+		DRM(context_switch_complete)(dev, new);
+	} else {
+		sprintf(buf, "C %d %d\n", old, new);
+		DRM(write_string)(dev, buf);
+	}
+
+	atomic_dec(&q->use_count);
+
+	return 0;
+}
+
+int DRM(context_switch_complete)(drm_device_t *dev, int new)
+{
+	drm_device_dma_t *dma = dev->dma;
+
+	dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
+	dev->last_switch  = jiffies;
+
+	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+		DRM_ERROR("Lock isn't held after context switch\n");
+	}
+
+	if (!dma || !(dma->next_buffer && dma->next_buffer->while_locked)) {
+		if (DRM(lock_free)(dev, &dev->lock.hw_lock->lock,
+				  DRM_KERNEL_CONTEXT)) {
+			DRM_ERROR("Cannot free lock\n");
+		}
+	}
+
+#if __HAVE_DMA_HISTOGRAM
+	atomic_inc(&dev->histo.ctx[DRM(histogram_slot)(get_cycles()
+						      - dev->ctx_start)]);
+
+#endif
+	clear_bit(0, &dev->context_flag);
+	wake_up_interruptible(&dev->context_wait);
+
+	return 0;
+}
+
+static int DRM(init_queue)(drm_device_t *dev, drm_queue_t *q, drm_ctx_t *ctx)
+{
+	DRM_DEBUG("\n");
+
+	if (atomic_read(&q->use_count) != 1
+	    || atomic_read(&q->finalization)
+	    || atomic_read(&q->block_count)) {
+		DRM_ERROR("New queue is already in use: u%d f%d b%d\n",
+			  atomic_read(&q->use_count),
+			  atomic_read(&q->finalization),
+			  atomic_read(&q->block_count));
+	}
+
+	atomic_set(&q->finalization,  0);
+	atomic_set(&q->block_count,   0);
+	atomic_set(&q->block_read,    0);
+	atomic_set(&q->block_write,   0);
+	atomic_set(&q->total_queued,  0);
+	atomic_set(&q->total_flushed, 0);
+	atomic_set(&q->total_locks,   0);
+
+	init_waitqueue_head(&q->write_queue);
+	init_waitqueue_head(&q->read_queue);
+	init_waitqueue_head(&q->flush_queue);
+
+	q->flags = ctx->flags;
+
+	DRM(waitlist_create)(&q->waitlist, dev->dma->buf_count);
+
+	return 0;
+}
+
+
+/* drm_alloc_queue:
+PRE: 1) dev->queuelist[0..dev->queue_count] is allocated and will not
+	disappear (so all deallocation must be done after IOCTLs are off)
+     2) dev->queue_count < dev->queue_slots
+     3) dev->queuelist[i].use_count == 0 and
+	dev->queuelist[i].finalization == 0 if i not in use
+POST: 1) dev->queuelist[i].use_count == 1
+      2) dev->queue_count < dev->queue_slots */
+
+static int DRM(alloc_queue)(drm_device_t *dev)
+{
+	int	    i;
+	drm_queue_t *queue;
+	int	    oldslots;
+	int	    newslots;
+				/* Check for a free queue */
+	for (i = 0; i < dev->queue_count; i++) {
+		atomic_inc(&dev->queuelist[i]->use_count);
+		if (atomic_read(&dev->queuelist[i]->use_count) == 1
+		    && !atomic_read(&dev->queuelist[i]->finalization)) {
+			DRM_DEBUG("%d (free)\n", i);
+			return i;
+		}
+		atomic_dec(&dev->queuelist[i]->use_count);
+	}
+				/* Allocate a new queue */
+	down(&dev->struct_sem);
+
+	queue = gamma_alloc(sizeof(*queue), DRM_MEM_QUEUES);
+	memset(queue, 0, sizeof(*queue));
+	atomic_set(&queue->use_count, 1);
+
+	++dev->queue_count;
+	if (dev->queue_count >= dev->queue_slots) {
+		oldslots = dev->queue_slots * sizeof(*dev->queuelist);
+		if (!dev->queue_slots) dev->queue_slots = 1;
+		dev->queue_slots *= 2;
+		newslots = dev->queue_slots * sizeof(*dev->queuelist);
+
+		dev->queuelist = DRM(realloc)(dev->queuelist,
+					      oldslots,
+					      newslots,
+					      DRM_MEM_QUEUES);
+		if (!dev->queuelist) {
+			up(&dev->struct_sem);
+			DRM_DEBUG("out of memory\n");
+			return -ENOMEM;
+		}
+	}
+	dev->queuelist[dev->queue_count-1] = queue;
+
+	up(&dev->struct_sem);
+	DRM_DEBUG("%d (new)\n", dev->queue_count - 1);
+	return dev->queue_count - 1;
+}
+
+int DRM(resctx)(struct inode *inode, struct file *filp,
+		unsigned int cmd, unsigned long arg)
+{
+	drm_ctx_res_t	res;
+	drm_ctx_t	ctx;
+	int		i;
+
+	DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
+	if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
+		return -EFAULT;
+	if (res.count >= DRM_RESERVED_CONTEXTS) {
+		memset(&ctx, 0, sizeof(ctx));
+		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
+			ctx.handle = i;
+			if (copy_to_user(&res.contexts[i],
+					 &i,
+					 sizeof(i)))
+				return -EFAULT;
+		}
+	}
+	res.count = DRM_RESERVED_CONTEXTS;
+	if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(addctx)(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_t	ctx;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+	if ((ctx.handle = DRM(alloc_queue)(dev)) == DRM_KERNEL_CONTEXT) {
+				/* Init kernel's context and get a new one. */
+		DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
+		ctx.handle = DRM(alloc_queue)(dev);
+	}
+	DRM(init_queue)(dev, dev->queuelist[ctx.handle], &ctx);
+	DRM_DEBUG("%d\n", ctx.handle);
+	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(modctx)(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_t	ctx;
+	drm_queue_t	*q;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+
+	DRM_DEBUG("%d\n", ctx.handle);
+
+	if (ctx.handle < 0 || ctx.handle >= dev->queue_count) return -EINVAL;
+	q = dev->queuelist[ctx.handle];
+
+	atomic_inc(&q->use_count);
+	if (atomic_read(&q->use_count) == 1) {
+				/* No longer in use */
+		atomic_dec(&q->use_count);
+		return -EINVAL;
+	}
+
+	if (DRM_BUFCOUNT(&q->waitlist)) {
+		atomic_dec(&q->use_count);
+		return -EBUSY;
+	}
+
+	q->flags = ctx.flags;
+
+	atomic_dec(&q->use_count);
+	return 0;
+}
+
+int DRM(getctx)(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_t	ctx;
+	drm_queue_t	*q;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+
+	DRM_DEBUG("%d\n", ctx.handle);
+
+	if (ctx.handle >= dev->queue_count) return -EINVAL;
+	q = dev->queuelist[ctx.handle];
+
+	atomic_inc(&q->use_count);
+	if (atomic_read(&q->use_count) == 1) {
+				/* No longer in use */
+		atomic_dec(&q->use_count);
+		return -EINVAL;
+	}
+
+	ctx.flags = q->flags;
+	atomic_dec(&q->use_count);
+
+	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
+		return -EFAULT;
+
+	return 0;
+}
+
+int DRM(switchctx)(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_t	ctx;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+	DRM_DEBUG("%d\n", ctx.handle);
+	return DRM(context_switch)(dev, dev->last_context, ctx.handle);
+}
+
+int DRM(newctx)(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_t	ctx;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+	DRM_DEBUG("%d\n", ctx.handle);
+	DRM(context_switch_complete)(dev, ctx.handle);
+
+	return 0;
+}
+
+int DRM(rmctx)(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_t	ctx;
+	drm_queue_t	*q;
+	drm_buf_t	*buf;
+
+	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
+		return -EFAULT;
+	DRM_DEBUG("%d\n", ctx.handle);
+
+	if (ctx.handle >= dev->queue_count) return -EINVAL;
+	q = dev->queuelist[ctx.handle];
+
+	atomic_inc(&q->use_count);
+	if (atomic_read(&q->use_count) == 1) {
+				/* No longer in use */
+		atomic_dec(&q->use_count);
+		return -EINVAL;
+	}
+
+	atomic_inc(&q->finalization); /* Mark queue in finalization state */
+	atomic_sub(2, &q->use_count); /* Mark queue as unused (pending
+					 finalization) */
+
+	while (test_and_set_bit(0, &dev->interrupt_flag)) {
+		schedule();
+		if (signal_pending(current)) {
+			clear_bit(0, &dev->interrupt_flag);
+			return -EINTR;
+		}
+	}
+				/* Remove queued buffers */
+	while ((buf = DRM(waitlist_get)(&q->waitlist))) {
+		DRM(free_buffer)(dev, buf);
+	}
+	clear_bit(0, &dev->interrupt_flag);
+
+				/* Wakeup blocked processes */
+	wake_up_interruptible(&q->read_queue);
+	wake_up_interruptible(&q->write_queue);
+	wake_up_interruptible(&q->flush_queue);
+
+				/* Finalization over.  Queue is made
+				   available when both use_count and
+				   finalization become 0, which won't
+				   happen until all the waiting processes
+				   stop waiting. */
+	atomic_dec(&q->finalization);
+	return 0;
+}
+
+#endif /* __HAVE_CTX_BITMAP */
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_dma.h linux/drivers/char/drm/drm_dma.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_dma.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_dma.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,603 @@
+/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
+ * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+#include <linux/interrupt.h>	/* For task queue support */
+
+#ifndef __HAVE_DMA_WAITQUEUE
+#define __HAVE_DMA_WAITQUEUE	0
+#endif
+#ifndef __HAVE_DMA_RECLAIM
+#define __HAVE_DMA_RECLAIM	0
+#endif
+#ifndef __HAVE_SHARED_IRQ
+#define __HAVE_SHARED_IRQ	0
+#endif
+
+#if __HAVE_SHARED_IRQ
+#define DRM_IRQ_TYPE		SA_SHIRQ
+#else
+#define DRM_IRQ_TYPE		0
+#endif
+
+#if __HAVE_DMA
+
+int DRM(dma_setup)( drm_device_t *dev )
+{
+	int i;
+
+	dev->dma = DRM(alloc)( sizeof(*dev->dma), DRM_MEM_DRIVER );
+	if ( !dev->dma )
+		return -ENOMEM;
+
+	memset( dev->dma, 0, sizeof(*dev->dma) );
+
+	for ( i = 0 ; i <= DRM_MAX_ORDER ; i++ )
+		memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
+
+	return 0;
+}
+
+void DRM(dma_takedown)(drm_device_t *dev)
+{
+	drm_device_dma_t  *dma = dev->dma;
+	int		  i, j;
+
+	if (!dma) return;
+
+				/* Clear dma buffers */
+	for (i = 0; i <= DRM_MAX_ORDER; i++) {
+		if (dma->bufs[i].seg_count) {
+			DRM_DEBUG("order %d: buf_count = %d,"
+				  " seg_count = %d\n",
+				  i,
+				  dma->bufs[i].buf_count,
+				  dma->bufs[i].seg_count);
+			for (j = 0; j < dma->bufs[i].seg_count; j++) {
+				DRM(free_pages)(dma->bufs[i].seglist[j],
+						dma->bufs[i].page_order,
+						DRM_MEM_DMA);
+			}
+			DRM(free)(dma->bufs[i].seglist,
+				  dma->bufs[i].seg_count
+				  * sizeof(*dma->bufs[0].seglist),
+				  DRM_MEM_SEGS);
+		}
+	   	if(dma->bufs[i].buf_count) {
+		   	for(j = 0; j < dma->bufs[i].buf_count; j++) {
+			   if(dma->bufs[i].buflist[j].dev_private) {
+			      DRM(free)(dma->bufs[i].buflist[j].dev_private,
+					dma->bufs[i].buflist[j].dev_priv_size,
+					DRM_MEM_BUFS);
+			   }
+			}
+		   	DRM(free)(dma->bufs[i].buflist,
+				  dma->bufs[i].buf_count *
+				  sizeof(*dma->bufs[0].buflist),
+				  DRM_MEM_BUFS);
+#if __HAVE_DMA_FREELIST
+		   	DRM(freelist_destroy)(&dma->bufs[i].freelist);
+#endif
+		}
+	}
+
+	if (dma->buflist) {
+		DRM(free)(dma->buflist,
+			  dma->buf_count * sizeof(*dma->buflist),
+			  DRM_MEM_BUFS);
+	}
+
+	if (dma->pagelist) {
+		DRM(free)(dma->pagelist,
+			  dma->page_count * sizeof(*dma->pagelist),
+			  DRM_MEM_PAGES);
+	}
+	DRM(free)(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
+	dev->dma = NULL;
+}
+
+
+#if __HAVE_DMA_HISTOGRAM
+/* This is slow, but is useful for debugging. */
+int DRM(histogram_slot)(unsigned long count)
+{
+	int value = DRM_DMA_HISTOGRAM_INITIAL;
+	int slot;
+
+	for (slot = 0;
+	     slot < DRM_DMA_HISTOGRAM_SLOTS;
+	     ++slot, value = DRM_DMA_HISTOGRAM_NEXT(value)) {
+		if (count < value) return slot;
+	}
+	return DRM_DMA_HISTOGRAM_SLOTS - 1;
+}
+
+void DRM(histogram_compute)(drm_device_t *dev, drm_buf_t *buf)
+{
+	cycles_t queued_to_dispatched;
+	cycles_t dispatched_to_completed;
+	cycles_t completed_to_freed;
+	int	 q2d, d2c, c2f, q2c, q2f;
+
+	if (buf->time_queued) {
+		queued_to_dispatched	= (buf->time_dispatched
+					   - buf->time_queued);
+		dispatched_to_completed = (buf->time_completed
+					   - buf->time_dispatched);
+		completed_to_freed	= (buf->time_freed
+					   - buf->time_completed);
+
+		q2d = DRM(histogram_slot)(queued_to_dispatched);
+		d2c = DRM(histogram_slot)(dispatched_to_completed);
+		c2f = DRM(histogram_slot)(completed_to_freed);
+
+		q2c = DRM(histogram_slot)(queued_to_dispatched
+					  + dispatched_to_completed);
+		q2f = DRM(histogram_slot)(queued_to_dispatched
+					  + dispatched_to_completed
+					  + completed_to_freed);
+
+		atomic_inc(&dev->histo.total);
+		atomic_inc(&dev->histo.queued_to_dispatched[q2d]);
+		atomic_inc(&dev->histo.dispatched_to_completed[d2c]);
+		atomic_inc(&dev->histo.completed_to_freed[c2f]);
+
+		atomic_inc(&dev->histo.queued_to_completed[q2c]);
+		atomic_inc(&dev->histo.queued_to_freed[q2f]);
+
+	}
+	buf->time_queued     = 0;
+	buf->time_dispatched = 0;
+	buf->time_completed  = 0;
+	buf->time_freed	     = 0;
+}
+#endif
+
+void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
+{
+	if (!buf) return;
+
+	buf->waiting  = 0;
+	buf->pending  = 0;
+	buf->pid      = 0;
+	buf->used     = 0;
+#if __HAVE_DMA_HISTOGRAM
+	buf->time_completed = get_cycles();
+#endif
+
+	if ( __HAVE_DMA_WAITQUEUE && waitqueue_active(&buf->dma_wait)) {
+		wake_up_interruptible(&buf->dma_wait);
+	}
+#if __HAVE_DMA_FREELIST
+	else {
+		drm_device_dma_t *dma = dev->dma;
+				/* If processes are waiting, the last one
+				   to wake will put the buffer on the free
+				   list.  If no processes are waiting, we
+				   put the buffer on the freelist here. */
+		DRM(freelist_put)(dev, &dma->bufs[buf->order].freelist, buf);
+	}
+#endif
+}
+
+#if !__HAVE_DMA_RECLAIM
+void DRM(reclaim_buffers)(drm_device_t *dev, pid_t pid)
+{
+	drm_device_dma_t *dma = dev->dma;
+	int		 i;
+
+	if (!dma) return;
+	for (i = 0; i < dma->buf_count; i++) {
+		if (dma->buflist[i]->pid == pid) {
+			switch (dma->buflist[i]->list) {
+			case DRM_LIST_NONE:
+				DRM(free_buffer)(dev, dma->buflist[i]);
+				break;
+			case DRM_LIST_WAIT:
+				dma->buflist[i]->list = DRM_LIST_RECLAIM;
+				break;
+			default:
+				/* Buffer already on hardware. */
+				break;
+			}
+		}
+	}
+}
+#endif
+
+
+/* GH: This is a big hack for now...
+ */
+#if __HAVE_OLD_DMA
+
+void DRM(clear_next_buffer)(drm_device_t *dev)
+{
+	drm_device_dma_t *dma = dev->dma;
+
+	dma->next_buffer = NULL;
+	if (dma->next_queue && !DRM_BUFCOUNT(&dma->next_queue->waitlist)) {
+		wake_up_interruptible(&dma->next_queue->flush_queue);
+	}
+	dma->next_queue	 = NULL;
+}
+
+int DRM(select_queue)(drm_device_t *dev, void (*wrapper)(unsigned long))
+{
+	int	   i;
+	int	   candidate = -1;
+	int	   j	     = jiffies;
+
+	if (!dev) {
+		DRM_ERROR("No device\n");
+		return -1;
+	}
+	if (!dev->queuelist || !dev->queuelist[DRM_KERNEL_CONTEXT]) {
+				/* This only happens between the time the
+				   interrupt is initialized and the time
+				   the queues are initialized. */
+		return -1;
+	}
+
+				/* Doing "while locked" DMA? */
+	if (DRM_WAITCOUNT(dev, DRM_KERNEL_CONTEXT)) {
+		return DRM_KERNEL_CONTEXT;
+	}
+
+				/* If there are buffers on the last_context
+				   queue, and we have not been executing
+				   this context very long, continue to
+				   execute this context. */
+	if (dev->last_switch <= j
+	    && dev->last_switch + DRM_TIME_SLICE > j
+	    && DRM_WAITCOUNT(dev, dev->last_context)) {
+		return dev->last_context;
+	}
+
+				/* Otherwise, find a candidate */
+	for (i = dev->last_checked + 1; i < dev->queue_count; i++) {
+		if (DRM_WAITCOUNT(dev, i)) {
+			candidate = dev->last_checked = i;
+			break;
+		}
+	}
+
+	if (candidate < 0) {
+		for (i = 0; i < dev->queue_count; i++) {
+			if (DRM_WAITCOUNT(dev, i)) {
+				candidate = dev->last_checked = i;
+				break;
+			}
+		}
+	}
+
+	if (wrapper
+	    && candidate >= 0
+	    && candidate != dev->last_context
+	    && dev->last_switch <= j
+	    && dev->last_switch + DRM_TIME_SLICE > j) {
+		if (dev->timer.expires != dev->last_switch + DRM_TIME_SLICE) {
+			del_timer(&dev->timer);
+			dev->timer.function = wrapper;
+			dev->timer.data	    = (unsigned long)dev;
+			dev->timer.expires  = dev->last_switch+DRM_TIME_SLICE;
+			add_timer(&dev->timer);
+		}
+		return -1;
+	}
+
+	return candidate;
+}
+
+
+int DRM(dma_enqueue)(drm_device_t *dev, drm_dma_t *d)
+{
+	int		  i;
+	drm_queue_t	  *q;
+	drm_buf_t	  *buf;
+	int		  idx;
+	int		  while_locked = 0;
+	drm_device_dma_t  *dma = dev->dma;
+	DECLARE_WAITQUEUE(entry, current);
+
+	DRM_DEBUG("%d\n", d->send_count);
+
+	if (d->flags & _DRM_DMA_WHILE_LOCKED) {
+		int context = dev->lock.hw_lock->lock;
+
+		if (!_DRM_LOCK_IS_HELD(context)) {
+			DRM_ERROR("No lock held during \"while locked\""
+				  " request\n");
+			return -EINVAL;
+		}
+		if (d->context != _DRM_LOCKING_CONTEXT(context)
+		    && _DRM_LOCKING_CONTEXT(context) != DRM_KERNEL_CONTEXT) {
+			DRM_ERROR("Lock held by %d while %d makes"
+				  " \"while locked\" request\n",
+				  _DRM_LOCKING_CONTEXT(context),
+				  d->context);
+			return -EINVAL;
+		}
+		q = dev->queuelist[DRM_KERNEL_CONTEXT];
+		while_locked = 1;
+	} else {
+		q = dev->queuelist[d->context];
+	}
+
+
+	atomic_inc(&q->use_count);
+	if (atomic_read(&q->block_write)) {
+		add_wait_queue(&q->write_queue, &entry);
+		atomic_inc(&q->block_count);
+		for (;;) {
+			current->state = TASK_INTERRUPTIBLE;
+			if (!atomic_read(&q->block_write)) break;
+			schedule();
+			if (signal_pending(current)) {
+				atomic_dec(&q->use_count);
+				remove_wait_queue(&q->write_queue, &entry);
+				return -EINTR;
+			}
+		}
+		atomic_dec(&q->block_count);
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&q->write_queue, &entry);
+	}
+
+	for (i = 0; i < d->send_count; i++) {
+		idx = d->send_indices[i];
+		if (idx < 0 || idx >= dma->buf_count) {
+			atomic_dec(&q->use_count);
+			DRM_ERROR("Index %d (of %d max)\n",
+				  d->send_indices[i], dma->buf_count - 1);
+			return -EINVAL;
+		}
+		buf = dma->buflist[ idx ];
+		if (buf->pid != current->pid) {
+			atomic_dec(&q->use_count);
+			DRM_ERROR("Process %d using buffer owned by %d\n",
+				  current->pid, buf->pid);
+			return -EINVAL;
+		}
+		if (buf->list != DRM_LIST_NONE) {
+			atomic_dec(&q->use_count);
+			DRM_ERROR("Process %d using buffer %d on list %d\n",
+				  current->pid, buf->idx, buf->list);
+		}
+		buf->used	  = d->send_sizes[i];
+		buf->while_locked = while_locked;
+		buf->context	  = d->context;
+		if (!buf->used) {
+			DRM_ERROR("Queueing 0 length buffer\n");
+		}
+		if (buf->pending) {
+			atomic_dec(&q->use_count);
+			DRM_ERROR("Queueing pending buffer:"
+				  " buffer %d, offset %d\n",
+				  d->send_indices[i], i);
+			return -EINVAL;
+		}
+		if (buf->waiting) {
+			atomic_dec(&q->use_count);
+			DRM_ERROR("Queueing waiting buffer:"
+				  " buffer %d, offset %d\n",
+				  d->send_indices[i], i);
+			return -EINVAL;
+		}
+		buf->waiting = 1;
+		if (atomic_read(&q->use_count) == 1
+		    || atomic_read(&q->finalization)) {
+			DRM(free_buffer)(dev, buf);
+		} else {
+			DRM(waitlist_put)(&q->waitlist, buf);
+			atomic_inc(&q->total_queued);
+		}
+	}
+	atomic_dec(&q->use_count);
+
+	return 0;
+}
+
+static int DRM(dma_get_buffers_of_order)(drm_device_t *dev, drm_dma_t *d,
+					 int order)
+{
+	int		  i;
+	drm_buf_t	  *buf;
+	drm_device_dma_t  *dma = dev->dma;
+
+	for (i = d->granted_count; i < d->request_count; i++) {
+		buf = DRM(freelist_get)(&dma->bufs[order].freelist,
+					d->flags & _DRM_DMA_WAIT);
+		if (!buf) break;
+		if (buf->pending || buf->waiting) {
+			DRM_ERROR("Free buffer %d in use by %d (w%d, p%d)\n",
+				  buf->idx,
+				  buf->pid,
+				  buf->waiting,
+				  buf->pending);
+		}
+		buf->pid     = current->pid;
+		if (copy_to_user(&d->request_indices[i],
+				 &buf->idx,
+				 sizeof(buf->idx)))
+			return -EFAULT;
+
+		if (copy_to_user(&d->request_sizes[i],
+				 &buf->total,
+				 sizeof(buf->total)))
+			return -EFAULT;
+
+		++d->granted_count;
+	}
+	return 0;
+}
+
+
+int DRM(dma_get_buffers)(drm_device_t *dev, drm_dma_t *dma)
+{
+	int		  order;
+	int		  retcode = 0;
+	int		  tmp_order;
+
+	order = DRM(order)(dma->request_size);
+
+	dma->granted_count = 0;
+	retcode		   = DRM(dma_get_buffers_of_order)(dev, dma, order);
+
+	if (dma->granted_count < dma->request_count
+	    && (dma->flags & _DRM_DMA_SMALLER_OK)) {
+		for (tmp_order = order - 1;
+		     !retcode
+			     && dma->granted_count < dma->request_count
+			     && tmp_order >= DRM_MIN_ORDER;
+		     --tmp_order) {
+
+			retcode = DRM(dma_get_buffers_of_order)(dev, dma,
+								tmp_order);
+		}
+	}
+
+	if (dma->granted_count < dma->request_count
+	    && (dma->flags & _DRM_DMA_LARGER_OK)) {
+		for (tmp_order = order + 1;
+		     !retcode
+			     && dma->granted_count < dma->request_count
+			     && tmp_order <= DRM_MAX_ORDER;
+		     ++tmp_order) {
+
+			retcode = DRM(dma_get_buffers_of_order)(dev, dma,
+								tmp_order);
+		}
+	}
+	return 0;
+}
+
+#endif /* __HAVE_OLD_DMA */
+
+
+#if __HAVE_DMA_IRQ
+
+int DRM(irq_install)( drm_device_t *dev, int irq )
+{
+	int ret;
+
+	if ( !irq )
+		return -EINVAL;
+
+	down( &dev->struct_sem );
+	if ( dev->irq ) {
+		up( &dev->struct_sem );
+		return -EBUSY;
+	}
+	dev->irq = irq;
+	up( &dev->struct_sem );
+
+	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
+
+	dev->context_flag = 0;
+	dev->interrupt_flag = 0;
+	dev->dma_flag = 0;
+
+	dev->dma->next_buffer = NULL;
+	dev->dma->next_queue = NULL;
+	dev->dma->this_buffer = NULL;
+
+#if __HAVE_DMA_IRQ_BH
+	INIT_LIST_HEAD( &dev->tq.list );
+	dev->tq.sync = 0;
+	dev->tq.routine = DRM(dma_immediate_bh);
+	dev->tq.data = dev;
+#endif
+
+				/* Before installing handler */
+	DRIVER_PREINSTALL();
+
+				/* Install handler */
+	ret = request_irq( dev->irq, DRM(dma_service),
+			   DRM_IRQ_TYPE, dev->devname, dev );
+	if ( ret < 0 ) {
+		down( &dev->struct_sem );
+		dev->irq = 0;
+		up( &dev->struct_sem );
+		return ret;
+	}
+
+				/* After installing handler */
+	DRIVER_POSTINSTALL();
+
+	return 0;
+}
+
+int DRM(irq_uninstall)( drm_device_t *dev )
+{
+	int irq;
+
+	down( &dev->struct_sem );
+	irq = dev->irq;
+	dev->irq = 0;
+	up( &dev->struct_sem );
+
+	if ( !irq )
+		return -EINVAL;
+
+	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
+
+	DRIVER_UNINSTALL();
+
+	free_irq( irq, dev );
+
+	return 0;
+}
+
+int DRM(control)( 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_control_t ctl;
+
+	if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
+		return -EFAULT;
+
+	switch ( ctl.func ) {
+	case DRM_INST_HANDLER:
+		return DRM(irq_install)( dev, ctl.irq );
+	case DRM_UNINST_HANDLER:
+		return DRM(irq_uninstall)( dev );
+	default:
+		return -EINVAL;
+	}
+}
+
+#endif /* __HAVE_DMA_IRQ */
+
+#endif /* __HAVE_DMA */
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_drawable.h linux/drivers/char/drm/drm_drawable.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_drawable.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_drawable.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,51 @@
+/* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*-
+ * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+int DRM(adddraw)(struct inode *inode, struct file *filp,
+		 unsigned int cmd, unsigned long arg)
+{
+	drm_draw_t draw;
+
+	draw.handle = 0;	/* NOOP */
+	DRM_DEBUG("%d\n", draw.handle);
+	if (copy_to_user((drm_draw_t *)arg, &draw, sizeof(draw)))
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(rmdraw)(struct inode *inode, struct file *filp,
+		unsigned int cmd, unsigned long arg)
+{
+	return 0;		/* NOOP */
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_drv.h linux/drivers/char/drm/drm_drv.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_drv.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_drv.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,1066 @@
+/* drm_drv.h -- Generic driver template -*- linux-c -*-
+ * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * To use this template, you must at least define the following (samples
+ * given for the MGA driver):
+ *
+ * #define DRIVER_AUTHOR	"VA Linux Systems, Inc."
+ *
+ * #define DRIVER_NAME		"mga"
+ * #define DRIVER_DESC		"Matrox G200/G400"
+ * #define DRIVER_DATE		"20001127"
+ *
+ * #define DRIVER_MAJOR		2
+ * #define DRIVER_MINOR		0
+ * #define DRIVER_PATCHLEVEL	2
+ *
+ * #define DRIVER_IOCTL_COUNT	DRM_ARRAY_SIZE( mga_ioctls )
+ *
+ * #define DRM(x)		mga_##x
+ */
+
+#ifndef __MUST_HAVE_AGP
+#define __MUST_HAVE_AGP			0
+#endif
+#ifndef __HAVE_CTX_BITMAP
+#define __HAVE_CTX_BITMAP		0
+#endif
+#ifndef __HAVE_DMA_IRQ
+#define __HAVE_DMA_IRQ			0
+#endif
+#ifndef __HAVE_DMA_QUEUE
+#define __HAVE_DMA_QUEUE		0
+#endif
+#ifndef __HAVE_MULTIPLE_DMA_QUEUES
+#define __HAVE_MULTIPLE_DMA_QUEUES	0
+#endif
+#ifndef __HAVE_DMA_SCHEDULE
+#define __HAVE_DMA_SCHEDULE		0
+#endif
+#ifndef __HAVE_DMA_FLUSH
+#define __HAVE_DMA_FLUSH		0
+#endif
+#ifndef __HAVE_DMA_READY
+#define __HAVE_DMA_READY		0
+#endif
+#ifndef __HAVE_DMA_QUIESCENT
+#define __HAVE_DMA_QUIESCENT		0
+#endif
+#ifndef __HAVE_RELEASE
+#define __HAVE_RELEASE			0
+#endif
+#ifndef __HAVE_COUNTERS
+#define __HAVE_COUNTERS			0
+#endif
+#ifndef __HAVE_SG
+#define __HAVE_SG			0
+#endif
+#ifndef __HAVE_KERNEL_CTX_SWITCH
+#define __HAVE_KERNEL_CTX_SWITCH	0
+#endif
+
+#ifndef DRIVER_PREINIT
+#define DRIVER_PREINIT()
+#endif
+#ifndef DRIVER_POSTINIT
+#define DRIVER_POSTINIT()
+#endif
+#ifndef DRIVER_PRERELEASE
+#define DRIVER_PRERELEASE()
+#endif
+#ifndef DRIVER_PRETAKEDOWN
+#define DRIVER_PRETAKEDOWN()
+#endif
+#ifndef DRIVER_POSTCLEANUP
+#define DRIVER_POSTCLEANUP()
+#endif
+#ifndef DRIVER_PRESETUP
+#define DRIVER_PRESETUP()
+#endif
+#ifndef DRIVER_POSTSETUP
+#define DRIVER_POSTSETUP()
+#endif
+#ifndef DRIVER_IOCTLS
+#define DRIVER_IOCTLS
+#endif
+#ifndef DRIVER_FOPS
+#if LINUX_VERSION_CODE >= 0x020400
+#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),			\
+}
+#else
+#define DRIVER_FOPS				\
+static struct file_operations	DRM(fops) = {	\
+	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
+#endif
+
+
+/*
+ * The default number of instances (minor numbers) to initialize.
+ */
+#ifndef DRIVER_NUM_CARDS
+#define DRIVER_NUM_CARDS 1
+#endif
+
+static drm_device_t	*DRM(device);
+static int		*DRM(minor);
+static int		DRM(numdevs) = 0;
+
+DRIVER_FOPS;
+
+static drm_ioctl_desc_t		  DRM(ioctls)[] = {
+	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { DRM(version),     0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { DRM(getunique),   0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { DRM(getmagic),    0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { DRM(irq_busid),   0, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)]       = { DRM(getmap),      0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)]    = { DRM(getclient),   0, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)]     = { DRM(getstats),    0, 0 },
+
+	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]    = { DRM(setunique),   1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]         = { DRM(block),       1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]       = { DRM(unblock),     1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]    = { DRM(authmagic),   1, 1 },
+
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { DRM(addmap),      1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { DRM(rmmap),       1, 0 },
+
+#if __HAVE_CTX_BITMAP
+	[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 },
+#endif
+
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]       = { DRM(addctx),      1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]        = { DRM(rmctx),       1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]       = { DRM(modctx),      1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]       = { DRM(getctx),      1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]    = { DRM(switchctx),   1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]       = { DRM(newctx),      1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]       = { DRM(resctx),      1, 0 },
+
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]      = { DRM(adddraw),     1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]       = { DRM(rmdraw),      1, 1 },
+
+	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	        = { DRM(lock),        1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]        = { DRM(unlock),      1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { DRM(finish),      1, 0 },
+
+#if __HAVE_DMA
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]      = { DRM(addbufs),     1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]     = { DRM(markbufs),    1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { DRM(infobufs),    1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { DRM(mapbufs),     1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { DRM(freebufs),    1, 0 },
+
+	/* 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 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { DRM(agp_release), 1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { DRM(agp_enable),  1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { DRM(agp_info),    1, 0 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = { DRM(agp_alloc),   1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = { DRM(agp_free),    1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = { DRM(agp_bind),    1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { DRM(agp_unbind),  1, 1 },
+#endif
+
+#if __HAVE_SG
+	[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)]      = { DRM(sg_alloc),    1, 1 },
+	[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free),     1, 1 },
+#endif
+
+	DRIVER_IOCTLS
+};
+
+#define DRIVER_IOCTL_COUNT	DRM_ARRAY_SIZE( DRM(ioctls) )
+
+#ifdef MODULE
+static char *drm_opts = NULL;
+#endif
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_PARM( drm_opts, "s" );
+
+static int DRM(setup)( drm_device_t *dev )
+{
+	int i;
+
+	DRIVER_PRESETUP();
+	atomic_set( &dev->ioctl_count, 0 );
+	atomic_set( &dev->vma_count, 0 );
+	dev->buf_use = 0;
+	atomic_set( &dev->buf_alloc, 0 );
+
+#if __HAVE_DMA
+	i = DRM(dma_setup)( dev );
+	if ( i < 0 )
+		return i;
+#endif
+
+	dev->counters  = 6 + __HAVE_COUNTERS;
+	dev->types[0]  = _DRM_STAT_LOCK;
+	dev->types[1]  = _DRM_STAT_OPENS;
+	dev->types[2]  = _DRM_STAT_CLOSES;
+	dev->types[3]  = _DRM_STAT_IOCTLS;
+	dev->types[4]  = _DRM_STAT_LOCKS;
+	dev->types[5]  = _DRM_STAT_UNLOCKS;
+#ifdef __HAVE_COUNTER6
+	dev->types[6]  = __HAVE_COUNTER6;
+#endif
+#ifdef __HAVE_COUNTER7
+	dev->types[7]  = __HAVE_COUNTER7;
+#endif
+#ifdef __HAVE_COUNTER8
+	dev->types[8]  = __HAVE_COUNTER8;
+#endif
+#ifdef __HAVE_COUNTER9
+	dev->types[9]  = __HAVE_COUNTER9;
+#endif
+#ifdef __HAVE_COUNTER10
+	dev->types[10] = __HAVE_COUNTER10;
+#endif
+#ifdef __HAVE_COUNTER11
+	dev->types[11] = __HAVE_COUNTER11;
+#endif
+#ifdef __HAVE_COUNTER12
+	dev->types[12] = __HAVE_COUNTER12;
+#endif
+#ifdef __HAVE_COUNTER13
+	dev->types[13] = __HAVE_COUNTER13;
+#endif
+#ifdef __HAVE_COUNTER14
+	dev->types[14] = __HAVE_COUNTER14;
+#endif
+#ifdef __HAVE_COUNTER15
+	dev->types[14] = __HAVE_COUNTER14;
+#endif
+
+	for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
+		atomic_set( &dev->counts[i], 0 );
+
+	for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
+		dev->magiclist[i].head = NULL;
+		dev->magiclist[i].tail = NULL;
+	}
+
+	dev->maplist = DRM(alloc)(sizeof(*dev->maplist),
+				  DRM_MEM_MAPS);
+	if(dev->maplist == NULL) return -ENOMEM;
+	memset(dev->maplist, 0, sizeof(*dev->maplist));
+	INIT_LIST_HEAD(&dev->maplist->head);
+	dev->map_count = 0;
+
+	dev->vmalist = NULL;
+	dev->lock.hw_lock = NULL;
+	init_waitqueue_head( &dev->lock.lock_queue );
+	dev->queue_count = 0;
+	dev->queue_reserved = 0;
+	dev->queue_slots = 0;
+	dev->queuelist = NULL;
+	dev->irq = 0;
+	dev->context_flag = 0;
+	dev->interrupt_flag = 0;
+	dev->dma_flag = 0;
+	dev->last_context = 0;
+	dev->last_switch = 0;
+	dev->last_checked = 0;
+	init_timer( &dev->timer );
+	init_waitqueue_head( &dev->context_wait );
+
+	dev->ctx_start = 0;
+	dev->lck_start = 0;
+
+	dev->buf_rp = dev->buf;
+	dev->buf_wp = dev->buf;
+	dev->buf_end = dev->buf + DRM_BSZ;
+	dev->buf_async = NULL;
+	init_waitqueue_head( &dev->buf_readers );
+	init_waitqueue_head( &dev->buf_writers );
+
+	DRM_DEBUG( "\n" );
+
+	/* The kernel's context could be created here, but is now created
+	 * in drm_dma_enqueue.	This is more resource-efficient for
+	 * hardware that does not do DMA, but may mean that
+	 * drm_select_queue fails between the time the interrupt is
+	 * initialized and the time the queues are initialized.
+	 */
+	DRIVER_POSTSETUP();
+	return 0;
+}
+
+
+static int DRM(takedown)( drm_device_t *dev )
+{
+	drm_magic_entry_t *pt, *next;
+	drm_map_t *map;
+	drm_map_list_t *r_list;
+	struct list_head *list, *list_next;
+	drm_vma_entry_t *vma, *vma_next;
+	int i;
+
+	DRM_DEBUG( "\n" );
+
+	DRIVER_PRETAKEDOWN();
+#if __HAVE_DMA_IRQ
+	if ( dev->irq ) DRM(irq_uninstall)( dev );
+#endif
+
+	down( &dev->struct_sem );
+	del_timer( &dev->timer );
+
+	if ( dev->devname ) {
+		DRM(free)( dev->devname, strlen( dev->devname ) + 1,
+			   DRM_MEM_DRIVER );
+		dev->devname = NULL;
+	}
+
+	if ( dev->unique ) {
+		DRM(free)( dev->unique, strlen( dev->unique ) + 1,
+			   DRM_MEM_DRIVER );
+		dev->unique = NULL;
+		dev->unique_len = 0;
+	}
+				/* Clear pid list */
+	for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
+		for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
+			next = pt->next;
+			DRM(free)( pt, sizeof(*pt), DRM_MEM_MAGIC );
+		}
+		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
+	}
+
+#if __REALLY_HAVE_AGP
+				/* Clear AGP information */
+	if ( dev->agp ) {
+		drm_agp_mem_t *entry;
+		drm_agp_mem_t *nexte;
+
+				/* Remove AGP resources, but leave dev->agp
+                                   intact until drv_cleanup is called. */
+		for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
+			nexte = entry->next;
+			if ( entry->bound ) DRM(unbind_agp)( entry->memory );
+			DRM(free_agp)( entry->memory, entry->pages );
+			DRM(free)( entry, sizeof(*entry), DRM_MEM_AGPLISTS );
+		}
+		dev->agp->memory = NULL;
+
+		if ( dev->agp->acquired ) DRM(agp_do_release)();
+
+		dev->agp->acquired = 0;
+		dev->agp->enabled  = 0;
+	}
+#endif
+
+				/* Clear vma list (only built for debugging) */
+	if ( dev->vmalist ) {
+		for ( vma = dev->vmalist ; vma ; vma = vma_next ) {
+			vma_next = vma->next;
+			DRM(free)( vma, sizeof(*vma), DRM_MEM_VMAS );
+		}
+		dev->vmalist = NULL;
+	}
+
+	if( dev->maplist ) {
+		for(list = dev->maplist->head.next;
+		    list != &dev->maplist->head;
+		    list = list_next) {
+			list_next = list->next;
+			r_list = (drm_map_list_t *)list;
+			map = r_list->map;
+			DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+			if(!map) continue;
+
+			switch ( map->type ) {
+			case _DRM_REGISTERS:
+			case _DRM_FRAME_BUFFER:
+#if __REALLY_HAVE_MTRR
+				if ( map->mtrr >= 0 ) {
+					int retcode;
+					retcode = mtrr_del( map->mtrr,
+							    map->offset,
+							    map->size );
+					DRM_DEBUG( "mtrr_del=%d\n", retcode );
+				}
+#endif
+				DRM(ioremapfree)( map->handle, map->size );
+				break;
+			case _DRM_SHM:
+				vfree(map->handle);
+				break;
+
+			case _DRM_AGP:
+				/* Do nothing here, because this is all
+				 * handled in the AGP/GART driver.
+				 */
+				break;
+                       case _DRM_SCATTER_GATHER:
+				/* Handle it, but do nothing, if HAVE_SG
+				 * isn't defined.
+				 */
+#if __HAVE_SG
+				if(dev->sg) {
+					DRM(sg_cleanup)(dev->sg);
+					dev->sg = NULL;
+				}
+#endif
+				break;
+			}
+ 			DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+ 		}
+		DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+		dev->maplist = NULL;
+ 	}
+
+#if __HAVE_DMA_QUEUE || __HAVE_MULTIPLE_DMA_QUEUES
+	if ( dev->queuelist ) {
+		for ( i = 0 ; i < dev->queue_count ; i++ ) {
+			DRM(waitlist_destroy)( &dev->queuelist[i]->waitlist );
+			if ( dev->queuelist[i] ) {
+				DRM(free)( dev->queuelist[i],
+					  sizeof(*dev->queuelist[0]),
+					  DRM_MEM_QUEUES );
+				dev->queuelist[i] = NULL;
+			}
+		}
+		DRM(free)( dev->queuelist,
+			  dev->queue_slots * sizeof(*dev->queuelist),
+			  DRM_MEM_QUEUES );
+		dev->queuelist = NULL;
+	}
+	dev->queue_count = 0;
+#endif
+
+#if __HAVE_DMA
+	DRM(dma_takedown)( dev );
+#endif
+	if ( dev->lock.hw_lock ) {
+		dev->lock.hw_lock = NULL; /* SHM removed */
+		dev->lock.pid = 0;
+		wake_up_interruptible( &dev->lock.lock_queue );
+	}
+	up( &dev->struct_sem );
+
+	return 0;
+}
+
+/*
+ * Figure out how many instances to initialize.
+ */
+static int drm_count_cards(void)
+{
+	int num = 0;
+#if defined(DRIVER_CARD_LIST)
+	int i;
+	drm_pci_list_t *l;
+	u16 device, vendor;
+	struct pci_dev *pdev = NULL;
+#endif
+
+	DRM_DEBUG( "\n" );
+
+#if defined(DRIVER_COUNT_CARDS)
+	num = DRIVER_COUNT_CARDS();
+#elif defined(DRIVER_CARD_LIST)
+	for (i = 0, l = DRIVER_CARD_LIST; l[i].vendor != 0; i++) {
+		pdev = NULL;
+		vendor = l[i].vendor;
+		device = l[i].device;
+		if(device == 0xffff) device = PCI_ANY_ID;
+		if(vendor == 0xffff) vendor = PCI_ANY_ID;
+		while ((pdev = pci_find_device(vendor, device, pdev))) {
+			num++;
+		}
+	}
+#else
+	num = DRIVER_NUM_CARDS;
+#endif
+	DRM_DEBUG("numdevs = %d\n", num);
+	return num;
+}
+
+/* drm_init is called via init_module at module load time, or via
+ * linux/init/main.c (this is not currently supported).
+ */
+static int __init drm_init( void )
+{
+
+	drm_device_t *dev;
+	int i;
+#if __HAVE_CTX_BITMAP
+	int retcode;
+#endif
+	DRM_DEBUG( "\n" );
+
+#ifdef MODULE
+	DRM(parse_options)( drm_opts );
+#endif
+
+	DRM(numdevs) = drm_count_cards();
+	/* Force at least one instance. */
+	if (DRM(numdevs) <= 0)
+		DRM(numdevs) = 1;
+
+	DRM(device) = kmalloc(sizeof(*DRM(device)) * DRM(numdevs), GFP_KERNEL);
+	if (!DRM(device)) {
+		return -ENOMEM;
+	}
+	DRM(minor) = kmalloc(sizeof(*DRM(minor)) * DRM(numdevs), GFP_KERNEL);
+	if (!DRM(minor)) {
+		kfree(DRM(device));
+		return -ENOMEM;
+	}
+
+	DRIVER_PREINIT();
+
+	DRM(mem_init)();
+
+	for (i = 0; i < DRM(numdevs); i++) {
+		dev = &(DRM(device)[i]);
+		memset( (void *)dev, 0, sizeof(*dev) );
+		dev->count_lock = SPIN_LOCK_UNLOCKED;
+		sema_init( &dev->struct_sem, 1 );
+
+		if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
+			return -EPERM;
+		dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] );
+		dev->name   = DRIVER_NAME;
+
+#if __REALLY_HAVE_AGP
+		dev->agp = DRM(agp_init)();
+#if __MUST_HAVE_AGP
+		if ( dev->agp == NULL ) {
+			DRM_ERROR( "Cannot initialize the agpgart module.\n" );
+			DRM(stub_unregister)(DRM(minor)[i]);
+			DRM(takedown)( dev );
+			return -ENOMEM;
+		}
+#endif
+#if __REALLY_HAVE_MTRR
+		if (dev->agp)
+			dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
+				       dev->agp->agp_info.aper_size*1024*1024,
+				       MTRR_TYPE_WRCOMB,
+				       1 );
+#endif
+#endif
+
+#if __HAVE_CTX_BITMAP
+		retcode = DRM(ctxbitmap_init)( dev );
+		if( retcode ) {
+			DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
+			DRM(stub_unregister)(DRM(minor)[i]);
+			DRM(takedown)( dev );
+			return retcode;
+		}
+#endif
+		DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
+		  	DRIVER_NAME,
+		  	DRIVER_MAJOR,
+		  	DRIVER_MINOR,
+		  	DRIVER_PATCHLEVEL,
+		  	DRIVER_DATE,
+		  	DRM(minor)[i] );
+	}
+
+	DRIVER_POSTINIT();
+
+	return 0;
+}
+
+/* drm_cleanup is called via cleanup_module at module unload time.
+ */
+static void __exit drm_cleanup( void )
+{
+	drm_device_t *dev;
+	int i;
+
+	DRM_DEBUG( "\n" );
+
+	for (i = DRM(numdevs) - 1; i >= 0; i--) {
+		dev = &(DRM(device)[i]);
+		if ( DRM(stub_unregister)(DRM(minor)[i]) ) {
+			DRM_ERROR( "Cannot unload module\n" );
+		} else {
+			DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]);
+			if (i == 0) {
+				DRM_INFO( "Module unloaded\n" );
+			}
+		}
+#if __HAVE_CTX_BITMAP
+		DRM(ctxbitmap_cleanup)( dev );
+#endif
+
+#if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
+		if ( dev->agp && dev->agp->agp_mtrr >= 0) {
+			int retval;
+			retval = mtrr_del( dev->agp->agp_mtrr,
+				   dev->agp->agp_info.aper_base,
+				   dev->agp->agp_info.aper_size*1024*1024 );
+			DRM_DEBUG( "mtrr_del=%d\n", retval );
+		}
+#endif
+
+		DRM(takedown)( dev );
+
+#if __REALLY_HAVE_AGP
+		if ( dev->agp ) {
+			DRM(agp_uninit)();
+			DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
+			dev->agp = NULL;
+		}
+#endif
+	}
+	DRIVER_POSTCLEANUP();
+	kfree(DRM(minor));
+	kfree(DRM(device));
+	DRM(numdevs) = 0;
+}
+
+module_init( drm_init );
+module_exit( drm_cleanup );
+
+
+int DRM(version)( struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg )
+{
+	drm_version_t version;
+	int len;
+
+	if ( copy_from_user( &version,
+			     (drm_version_t *)arg,
+			     sizeof(version) ) )
+		return -EFAULT;
+
+#define DRM_COPY( name, value )						\
+	len = strlen( value );						\
+	if ( len > name##_len ) len = name##_len;			\
+	name##_len = strlen( value );					\
+	if ( len && name ) {						\
+		if ( copy_to_user( name, value, len ) )			\
+			return -EFAULT;					\
+	}
+
+	version.version_major = DRIVER_MAJOR;
+	version.version_minor = DRIVER_MINOR;
+	version.version_patchlevel = DRIVER_PATCHLEVEL;
+
+	DRM_COPY( version.name, DRIVER_NAME );
+	DRM_COPY( version.date, DRIVER_DATE );
+	DRM_COPY( version.desc, DRIVER_DESC );
+
+	if ( copy_to_user( (drm_version_t *)arg,
+			   &version,
+			   sizeof(version) ) )
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(open)( struct inode *inode, struct file *filp )
+{
+	drm_device_t *dev = NULL;
+	int retcode = 0;
+	int i;
+
+	for (i = 0; i < DRM(numdevs); i++) {
+		if (MINOR(inode->i_rdev) == DRM(minor)[i]) {
+			dev = &(DRM(device)[i]);
+			break;
+		}
+	}
+	if (!dev) {
+		return -ENODEV;
+	}
+
+	DRM_DEBUG( "open_count = %d\n", dev->open_count );
+
+	retcode = DRM(open_helper)( inode, filp, dev );
+	if ( !retcode ) {
+#if LINUX_VERSION_CODE < 0x020333
+		MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
+#endif
+		atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
+		spin_lock( &dev->count_lock );
+		if ( !dev->open_count++ ) {
+			spin_unlock( &dev->count_lock );
+			return DRM(setup)( dev );
+		}
+		spin_unlock( &dev->count_lock );
+	}
+
+	return retcode;
+}
+
+int DRM(release)( struct inode *inode, struct file *filp )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev;
+	int retcode = 0;
+
+	lock_kernel();
+	dev = priv->dev;
+
+	DRM_DEBUG( "open_count = %d\n", dev->open_count );
+
+	DRIVER_PRERELEASE();
+
+	/* ========================================================
+	 * Begin inline drm_release
+	 */
+
+	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 dead, 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. */
+	}
+#if __HAVE_RELEASE
+	else if ( dev->lock.hw_lock ) {
+		/* The lock is required to reclaim buffers */
+		DECLARE_WAITQUEUE( entry, current );
+		add_wait_queue( &dev->lock.lock_queue, &entry );
+		for (;;) {
+			current->state = TASK_INTERRUPTIBLE;
+			if ( !dev->lock.hw_lock ) {
+				/* Device has been unregistered */
+				retcode = -EINTR;
+				break;
+			}
+			if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
+					     DRM_KERNEL_CONTEXT ) ) {
+				dev->lock.pid	    = priv->pid;
+				dev->lock.lock_time = jiffies;
+                                atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
+				break;	/* Got lock */
+			}
+				/* Contention */
+#if 0
+			atomic_inc( &dev->total_sleeps );
+#endif
+			schedule();
+			if ( signal_pending( current ) ) {
+				retcode = -ERESTARTSYS;
+				break;
+			}
+		}
+		current->state = TASK_RUNNING;
+		remove_wait_queue( &dev->lock.lock_queue, &entry );
+		if( !retcode ) {
+			DRIVER_RELEASE();
+			DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
+					DRM_KERNEL_CONTEXT );
+		}
+	}
+#elif __HAVE_DMA
+	DRM(reclaim_buffers)( dev, priv->pid );
+#endif
+
+	DRM(fasync)( -1, filp, 0 );
+
+	down( &dev->struct_sem );
+	if ( priv->remove_auth_on_close == 1 ) {
+		drm_file_t *temp = dev->file_first;
+		while ( temp ) {
+			temp->authenticated = 0;
+			temp = temp->next;
+		}
+	}
+	if ( priv->prev ) {
+		priv->prev->next = priv->next;
+	} else {
+		dev->file_first	 = priv->next;
+	}
+	if ( priv->next ) {
+		priv->next->prev = priv->prev;
+	} else {
+		dev->file_last	 = priv->prev;
+	}
+	up( &dev->struct_sem );
+
+	DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
+
+	/* ========================================================
+	 * End inline drm_release
+	 */
+
+#if LINUX_VERSION_CODE < 0x020333
+	MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
+#endif
+	atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
+	spin_lock( &dev->count_lock );
+	if ( !--dev->open_count ) {
+		if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
+			DRM_ERROR( "Device busy: %d %d\n",
+				   atomic_read( &dev->ioctl_count ),
+				   dev->blocked );
+			spin_unlock( &dev->count_lock );
+			unlock_kernel();
+			return -EBUSY;
+		}
+		spin_unlock( &dev->count_lock );
+		unlock_kernel();
+		return DRM(takedown)( dev );
+	}
+	spin_unlock( &dev->count_lock );
+
+	unlock_kernel();
+	return retcode;
+}
+
+/* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.
+ */
+int DRM(ioctl)( 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_ioctl_desc_t *ioctl;
+	drm_ioctl_t *func;
+	int nr = DRM_IOCTL_NR(cmd);
+	int retcode = 0;
+
+	atomic_inc( &dev->ioctl_count );
+	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 );
+
+	if ( nr >= DRIVER_IOCTL_COUNT ) {
+		retcode = -EINVAL;
+	} else {
+		ioctl = &DRM(ioctls)[nr];
+		func = ioctl->func;
+
+		if ( !func ) {
+			DRM_DEBUG( "no function\n" );
+			retcode = -EINVAL;
+		} else if ( ( ioctl->root_only && !capable( CAP_SYS_ADMIN ) )||
+			    ( ioctl->auth_needed && !priv->authenticated ) ) {
+			retcode = -EACCES;
+		} else {
+			retcode = func( inode, filp, cmd, arg );
+		}
+	}
+
+	atomic_dec( &dev->ioctl_count );
+	return retcode;
+}
+
+int DRM(lock)( 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;
+        DECLARE_WAITQUEUE( entry, current );
+        drm_lock_t lock;
+        int ret = 0;
+#if __HAVE_MULTIPLE_DMA_QUEUES
+	drm_queue_t *q;
+#endif
+#if __HAVE_DMA_HISTOGRAM
+        cycles_t start;
+
+        dev->lck_start = start = get_cycles();
+#endif
+
+        if ( copy_from_user( &lock, (drm_lock_t *)arg, sizeof(lock) ) )
+		return -EFAULT;
+
+        if ( lock.context == DRM_KERNEL_CONTEXT ) {
+                DRM_ERROR( "Process %d using kernel context %d\n",
+			   current->pid, lock.context );
+                return -EINVAL;
+        }
+
+        DRM_DEBUG( "%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+		   lock.context, current->pid,
+		   dev->lock.hw_lock->lock, lock.flags );
+
+#if __HAVE_DMA_QUEUE
+        if ( lock.context < 0 )
+                return -EINVAL;
+#elif __HAVE_MULTIPLE_DMA_QUEUES
+        if ( lock.context < 0 || lock.context >= dev->queue_count )
+                return -EINVAL;
+	q = dev->queuelist[lock.context];
+#endif
+
+#if __HAVE_DMA_FLUSH
+	ret = DRM(flush_block_and_flush)( dev, lock.context, lock.flags );
+#endif
+        if ( !ret ) {
+                add_wait_queue( &dev->lock.lock_queue, &entry );
+                for (;;) {
+                        current->state = TASK_INTERRUPTIBLE;
+                        if ( !dev->lock.hw_lock ) {
+                                /* Device has been unregistered */
+                                ret = -EINTR;
+                                break;
+                        }
+                        if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
+					     lock.context ) ) {
+                                dev->lock.pid       = current->pid;
+                                dev->lock.lock_time = jiffies;
+                                atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
+                                break;  /* Got lock */
+                        }
+
+                                /* Contention */
+                        schedule();
+                        if ( signal_pending( current ) ) {
+                                ret = -ERESTARTSYS;
+                                break;
+                        }
+                }
+                current->state = TASK_RUNNING;
+                remove_wait_queue( &dev->lock.lock_queue, &entry );
+        }
+
+#if __HAVE_DMA_FLUSH
+	DRM(flush_unblock)( dev, lock.context, lock.flags ); /* cleanup phase */
+#endif
+
+        if ( !ret ) {
+		sigemptyset( &dev->sigmask );
+		sigaddset( &dev->sigmask, SIGSTOP );
+		sigaddset( &dev->sigmask, SIGTSTP );
+		sigaddset( &dev->sigmask, SIGTTIN );
+		sigaddset( &dev->sigmask, SIGTTOU );
+		dev->sigdata.context = lock.context;
+		dev->sigdata.lock    = dev->lock.hw_lock;
+		block_all_signals( DRM(notifier),
+				   &dev->sigdata, &dev->sigmask );
+
+#if __HAVE_DMA_READY
+                if ( lock.flags & _DRM_LOCK_READY ) {
+			DRIVER_DMA_READY();
+		}
+#endif
+#if __HAVE_DMA_QUIESCENT
+                if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
+			DRIVER_DMA_QUIESCENT();
+		}
+#endif
+#if __HAVE_KERNEL_CTX_SWITCH
+		if ( dev->last_context != lock.context ) {
+			DRM(context_switch)(dev, dev->last_context,
+					    lock.context);
+		}
+#endif
+        }
+
+        DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
+
+#if __HAVE_DMA_HISTOGRAM
+        atomic_inc(&dev->histo.lacq[DRM(histogram_slot)(get_cycles()-start)]);
+#endif
+        return ret;
+}
+
+
+int DRM(unlock)( 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_lock_t lock;
+
+	if ( copy_from_user( &lock, (drm_lock_t *)arg, sizeof(lock) ) )
+		return -EFAULT;
+
+	if ( lock.context == DRM_KERNEL_CONTEXT ) {
+		DRM_ERROR( "Process %d using kernel context %d\n",
+			   current->pid, lock.context );
+		return -EINVAL;
+	}
+
+	atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
+
+	DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
+			    DRM_KERNEL_CONTEXT );
+#if __HAVE_DMA_SCHEDULE
+	DRM(dma_schedule)( dev, 1 );
+#endif
+
+	/* FIXME: Do we ever really need to check this???
+	 */
+	if ( 1 /* !dev->context_flag */ ) {
+		if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
+				     DRM_KERNEL_CONTEXT ) ) {
+			DRM_ERROR( "\n" );
+		}
+	}
+
+	unblock_all_signals();
+	return 0;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_fops.h linux/drivers/char/drm/drm_fops.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_fops.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_fops.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,225 @@
+/* drm_fops.h -- File operations for DRM -*- linux-c -*-
+ * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Daryll Strauss <daryll@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include <linux/poll.h>
+
+/* drm_open is called whenever a process opens /dev/drm. */
+
+int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
+{
+	kdev_t	     minor = MINOR(inode->i_rdev);
+	drm_file_t   *priv;
+
+	if (filp->f_flags & O_EXCL)   return -EBUSY; /* No exclusive opens */
+	if (!DRM(cpu_valid)())        return -EINVAL;
+
+	DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
+
+	priv		    = DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
+	if(!priv) return -ENOMEM;
+
+	memset(priv, 0, sizeof(*priv));
+	filp->private_data  = priv;
+	priv->uid	    = current->euid;
+	priv->pid	    = current->pid;
+	priv->minor	    = minor;
+	priv->dev	    = dev;
+	priv->ioctl_count   = 0;
+	priv->authenticated = capable(CAP_SYS_ADMIN);
+
+	down(&dev->struct_sem);
+	if (!dev->file_last) {
+		priv->next	= NULL;
+		priv->prev	= NULL;
+		dev->file_first = priv;
+		dev->file_last	= priv;
+	} else {
+		priv->next	     = NULL;
+		priv->prev	     = dev->file_last;
+		dev->file_last->next = priv;
+		dev->file_last	     = priv;
+	}
+	up(&dev->struct_sem);
+
+#ifdef __alpha__
+	/*
+	 * Default the hose
+	 */
+	if (!dev->hose) {
+		struct pci_dev *pci_dev;
+		pci_dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
+		if (pci_dev) dev->hose = pci_dev->sysdata;
+		if (!dev->hose) {
+			struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+			if (b) dev->hose = b->sysdata;
+		}
+	}
+#endif
+
+	return 0;
+}
+
+int DRM(flush)(struct file *filp)
+{
+	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);
+	return 0;
+}
+
+int DRM(fasync)(int fd, struct file *filp, int on)
+{
+	drm_file_t    *priv   = filp->private_data;
+	drm_device_t  *dev    = priv->dev;
+	int	      retcode;
+
+	DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device);
+	retcode = fasync_helper(fd, filp, on, &dev->buf_async);
+	if (retcode < 0) return retcode;
+	return 0;
+}
+
+
+/* The drm_read and drm_write_string code (especially that which manages
+   the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
+   DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
+
+ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off)
+{
+	drm_file_t    *priv   = filp->private_data;
+	drm_device_t  *dev    = priv->dev;
+	int	      left;
+	int	      avail;
+	int	      send;
+	int	      cur;
+
+	DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
+
+	while (dev->buf_rp == dev->buf_wp) {
+		DRM_DEBUG("  sleeping\n");
+		if (filp->f_flags & O_NONBLOCK) {
+			return -EAGAIN;
+		}
+		interruptible_sleep_on(&dev->buf_readers);
+		if (signal_pending(current)) {
+			DRM_DEBUG("  interrupted\n");
+			return -ERESTARTSYS;
+		}
+		DRM_DEBUG("  awake\n");
+	}
+
+	left  = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
+	avail = DRM_BSZ - left;
+	send  = DRM_MIN(avail, count);
+
+	while (send) {
+		if (dev->buf_wp > dev->buf_rp) {
+			cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
+		} else {
+			cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
+		}
+		if (copy_to_user(buf, dev->buf_rp, cur))
+			return -EFAULT;
+		dev->buf_rp += cur;
+		if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
+		send -= cur;
+	}
+
+	wake_up_interruptible(&dev->buf_writers);
+	return DRM_MIN(avail, count);;
+}
+
+int DRM(write_string)(drm_device_t *dev, const char *s)
+{
+	int left   = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
+	int send   = strlen(s);
+	int count;
+
+	DRM_DEBUG("%d left, %d to send (%p, %p)\n",
+		  left, send, dev->buf_rp, dev->buf_wp);
+
+	if (left == 1 || dev->buf_wp != dev->buf_rp) {
+		DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
+			  left,
+			  dev->buf_wp,
+			  dev->buf_rp);
+	}
+
+	while (send) {
+		if (dev->buf_wp >= dev->buf_rp) {
+			count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
+			if (count == left) --count; /* Leave a hole */
+		} else {
+			count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
+		}
+		strncpy(dev->buf_wp, s, count);
+		dev->buf_wp += count;
+		if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
+		send -= count;
+	}
+
+#if LINUX_VERSION_CODE < 0x020315 && !defined(KILLFASYNCHASTHREEPARAMETERS)
+	/* The extra parameter to kill_fasync was added in 2.3.21, and is
+           _not_ present in _stock_ 2.2.14 and 2.2.15.  However, some
+           distributions patch 2.2.x kernels to add this parameter.  The
+           Makefile.linux attempts to detect this addition and defines
+           KILLFASYNCHASTHREEPARAMETERS if three parameters are found. */
+	if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO);
+#else
+
+				/* Parameter added in 2.3.21. */
+#if LINUX_VERSION_CODE < 0x020400
+	if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN);
+#else
+				/* Type of first parameter changed in
+                                   Linux 2.4.0-test2... */
+	if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
+#endif
+#endif
+	DRM_DEBUG("waking\n");
+	wake_up_interruptible(&dev->buf_readers);
+	return 0;
+}
+
+unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
+{
+	drm_file_t   *priv = filp->private_data;
+	drm_device_t *dev  = priv->dev;
+
+	poll_wait(filp, &dev->buf_readers, wait);
+	if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
+	return 0;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_init.h linux/drivers/char/drm/drm_init.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_init.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_init.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,116 @@
+/* drm_init.h -- Setup/Cleanup for DRM -*- linux-c -*-
+ * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+#if 0
+int DRM(flags) = DRM_FLAG_DEBUG;
+#else
+int DRM(flags) = 0;
+#endif
+
+/* drm_parse_option parses a single option.  See description for
+ * drm_parse_options for details.
+ */
+static void DRM(parse_option)(char *s)
+{
+	char *c, *r;
+
+	DRM_DEBUG("\"%s\"\n", s);
+	if (!s || !*s) return;
+	for (c = s; *c && *c != ':'; c++); /* find : or \0 */
+	if (*c) r = c + 1; else r = NULL;  /* remember remainder */
+	*c = '\0';			   /* terminate */
+	if (!strcmp(s, "noctx")) {
+		DRM(flags) |= DRM_FLAG_NOCTX;
+		DRM_INFO("Server-mediated context switching OFF\n");
+		return;
+	}
+	if (!strcmp(s, "debug")) {
+		DRM(flags) |= DRM_FLAG_DEBUG;
+		DRM_INFO("Debug messages ON\n");
+		return;
+	}
+	DRM_ERROR("\"%s\" is not a valid option\n", s);
+	return;
+}
+
+/* drm_parse_options parse the insmod "drm_opts=" options, or the command-line
+ * options passed to the kernel via LILO.  The grammar of the format is as
+ * follows:
+ *
+ * drm		::= 'drm_opts=' option_list
+ * option_list	::= option [ ';' option_list ]
+ * option	::= 'device:' major
+ *		|   'debug'
+ *		|   'noctx'
+ * major	::= INTEGER
+ *
+ * Note that 's' contains option_list without the 'drm_opts=' part.
+ *
+ * device=major,minor specifies the device number used for /dev/drm
+ *	  if major == 0 then the misc device is used
+ *	  if major == 0 and minor == 0 then dynamic misc allocation is used
+ * debug=on specifies that debugging messages will be printk'd
+ * debug=trace specifies that each function call will be logged via printk
+ * debug=off turns off all debugging options
+ *
+ */
+
+void DRM(parse_options)(char *s)
+{
+	char *h, *t, *n;
+
+	DRM_DEBUG("\"%s\"\n", s ?: "");
+	if (!s || !*s) return;
+
+	for (h = t = n = s; h && *h; h = n) {
+		for (; *t && *t != ';'; t++);	       /* find ; or \0 */
+		if (*t) n = t + 1; else n = NULL;      /* remember next */
+		*t = '\0';			       /* terminate */
+		DRM(parse_option)(h);		       /* parse */
+	}
+}
+
+/* drm_cpu_valid returns non-zero if the DRI will run on this CPU, and 0
+ * otherwise.
+ */
+int DRM(cpu_valid)(void)
+{
+#if defined(__i386__)
+	if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */
+#endif
+#if defined(__sparc__) && !defined(__sparc_v9__)
+	return 0; /* No cmpxchg before v9 sparc. */
+#endif
+	return 1;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_ioctl.h linux/drivers/char/drm/drm_ioctl.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_ioctl.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_ioctl.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,234 @@
+/* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*-
+ * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    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)
+{
+	drm_irq_busid_t p;
+	struct pci_dev	*dev;
+
+	if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
+		return -EFAULT;
+	dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
+	if (dev) p.irq = dev->irq;
+	else	 p.irq = 0;
+	DRM_DEBUG("%d:%d:%d => IRQ %d\n",
+		  p.busnum, p.devnum, p.funcnum, p.irq);
+	if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(getunique)(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_unique_t	 u;
+
+	if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u)))
+		return -EFAULT;
+	if (u.unique_len >= dev->unique_len) {
+		if (copy_to_user(u.unique, dev->unique, dev->unique_len))
+			return -EFAULT;
+	}
+	u.unique_len = dev->unique_len;
+	if (copy_to_user((drm_unique_t *)arg, &u, sizeof(u)))
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(setunique)(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_unique_t	 u;
+
+	if (dev->unique_len || dev->unique) return -EBUSY;
+
+	if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u))) return -EFAULT;
+
+	if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
+
+	dev->unique_len = u.unique_len;
+	dev->unique	= DRM(alloc)(u.unique_len + 1, DRM_MEM_DRIVER);
+	if(!dev->unique) return -ENOMEM;
+	if (copy_from_user(dev->unique, u.unique, dev->unique_len))
+		return -EFAULT;
+
+	dev->unique[dev->unique_len] = '\0';
+
+	dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
+				  DRM_MEM_DRIVER);
+	if(!dev->devname) {
+		DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
+		return -ENOMEM;
+	}
+	sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
+
+#ifdef __alpha__
+	do {
+		struct pci_dev *pci_dev;
+                int b, d, f;
+                char *p;
+ 
+                for(p = dev->unique; p && *p && *p != ':'; p++);
+                if (!p || !*p) break;
+                b = (int)simple_strtoul(p+1, &p, 10);
+                if (*p != ':') break;
+                d = (int)simple_strtoul(p+1, &p, 10);
+                if (*p != ':') break;
+                f = (int)simple_strtoul(p+1, &p, 10);
+                if (*p) break;
+ 
+                pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
+                if (pci_dev)
+                        dev->hose = pci_dev->sysdata;
+        } while(0);
+#endif
+
+	return 0;
+}
+
+
+int DRM(getmap)( 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_map_t    map;
+	drm_map_list_t *r_list = NULL;
+	struct list_head *list;
+	int          idx;
+	int	     i;
+
+	if (copy_from_user(&map, (drm_map_t *)arg, sizeof(map)))
+		return -EFAULT;
+	idx = map.offset;
+
+	down(&dev->struct_sem);
+	if (idx < 0 || idx >= dev->map_count) {
+		up(&dev->struct_sem);
+		return -EINVAL;
+	}
+
+	i = 0;
+	list_for_each(list, &dev->maplist->head) {
+		if(i == idx) {
+			r_list = (drm_map_list_t *)list;
+			break;
+		}
+		i++;
+	}
+	if(!r_list || !r_list->map) {
+		up(&dev->struct_sem);
+		return -EINVAL;
+	}
+
+	map.offset = r_list->map->offset;
+	map.size   = r_list->map->size;
+	map.type   = r_list->map->type;
+	map.flags  = r_list->map->flags;
+	map.handle = r_list->map->handle;
+	map.mtrr   = r_list->map->mtrr;
+	up(&dev->struct_sem);
+
+	if (copy_to_user((drm_map_t *)arg, &map, sizeof(map))) return -EFAULT;
+	return 0;
+}
+
+int DRM(getclient)( 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_client_t client;
+	drm_file_t   *pt;
+	int          idx;
+	int          i;
+
+	if (copy_from_user(&client, (drm_client_t *)arg, sizeof(client)))
+		return -EFAULT;
+	idx = client.idx;
+	down(&dev->struct_sem);
+	for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next)
+		;
+
+	if (!pt) {
+		up(&dev->struct_sem);
+		return -EINVAL;
+	}
+	client.auth  = pt->authenticated;
+	client.pid   = pt->pid;
+	client.uid   = pt->uid;
+	client.magic = pt->magic;
+	client.iocs  = pt->ioctl_count;
+	up(&dev->struct_sem);
+
+	if (copy_to_user((drm_client_t *)arg, &client, sizeof(client)))
+		return -EFAULT;
+	return 0;
+}
+
+int DRM(getstats)( 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_stats_t  stats;
+	int          i;
+
+	memset(&stats, 0, sizeof(stats));
+	
+	down(&dev->struct_sem);
+
+	for (i = 0; i < dev->counters; i++) {
+		if (dev->types[i] == _DRM_STAT_LOCK)
+			stats.data[i].value
+				= (dev->lock.hw_lock
+				   ? dev->lock.hw_lock->lock : 0);
+		else 
+			stats.data[i].value = atomic_read(&dev->counts[i]);
+		stats.data[i].type  = dev->types[i];
+	}
+	
+	stats.count = dev->counters;
+
+	up(&dev->struct_sem);
+
+	if (copy_to_user((drm_stats_t *)arg, &stats, sizeof(stats)))
+		return -EFAULT;
+	return 0;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_lists.h linux/drivers/char/drm/drm_lists.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_lists.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_lists.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,230 @@
+/* drm_lists.h -- Buffer list handling routines -*- linux-c -*-
+ * Created: Mon Apr 19 20:54:22 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+#if __HAVE_DMA_WAITLIST
+
+int DRM(waitlist_create)(drm_waitlist_t *bl, int count)
+{
+	if (bl->count) return -EINVAL;
+
+	bl->bufs       = DRM(alloc)((bl->count + 2) * sizeof(*bl->bufs),
+				    DRM_MEM_BUFLISTS);
+
+	if(!bl->bufs) return -ENOMEM;
+
+	bl->count      = count;
+	bl->rp	       = bl->bufs;
+	bl->wp	       = bl->bufs;
+	bl->end	       = &bl->bufs[bl->count+1];
+	bl->write_lock = SPIN_LOCK_UNLOCKED;
+	bl->read_lock  = SPIN_LOCK_UNLOCKED;
+	return 0;
+}
+
+int DRM(waitlist_destroy)(drm_waitlist_t *bl)
+{
+	if (bl->rp != bl->wp) return -EINVAL;
+	if (bl->bufs) DRM(free)(bl->bufs,
+				(bl->count + 2) * sizeof(*bl->bufs),
+				DRM_MEM_BUFLISTS);
+	bl->count = 0;
+	bl->bufs  = NULL;
+	bl->rp	  = NULL;
+	bl->wp	  = NULL;
+	bl->end	  = NULL;
+	return 0;
+}
+
+int DRM(waitlist_put)(drm_waitlist_t *bl, drm_buf_t *buf)
+{
+	int	      left;
+	unsigned long flags;
+
+	left = DRM_LEFTCOUNT(bl);
+	if (!left) {
+		DRM_ERROR("Overflow while adding buffer %d from pid %d\n",
+			  buf->idx, buf->pid);
+		return -EINVAL;
+	}
+#if __HAVE_DMA_HISTOGRAM
+	buf->time_queued = get_cycles();
+#endif
+	buf->list	 = DRM_LIST_WAIT;
+
+	spin_lock_irqsave(&bl->write_lock, flags);
+	*bl->wp = buf;
+	if (++bl->wp >= bl->end) bl->wp = bl->bufs;
+	spin_unlock_irqrestore(&bl->write_lock, flags);
+
+	return 0;
+}
+
+drm_buf_t *DRM(waitlist_get)(drm_waitlist_t *bl)
+{
+	drm_buf_t     *buf;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bl->read_lock, flags);
+	buf = *bl->rp;
+	if (bl->rp == bl->wp) {
+		spin_unlock_irqrestore(&bl->read_lock, flags);
+		return NULL;
+	}
+	if (++bl->rp >= bl->end) bl->rp = bl->bufs;
+	spin_unlock_irqrestore(&bl->read_lock, flags);
+
+	return buf;
+}
+
+#endif /* __HAVE_DMA_WAITLIST */
+
+
+#if __HAVE_DMA_FREELIST
+
+int DRM(freelist_create)(drm_freelist_t *bl, int count)
+{
+	atomic_set(&bl->count, 0);
+	bl->next      = NULL;
+	init_waitqueue_head(&bl->waiting);
+	bl->low_mark  = 0;
+	bl->high_mark = 0;
+	atomic_set(&bl->wfh,   0);
+	bl->lock      = SPIN_LOCK_UNLOCKED;
+	++bl->initialized;
+	return 0;
+}
+
+int DRM(freelist_destroy)(drm_freelist_t *bl)
+{
+	atomic_set(&bl->count, 0);
+	bl->next = NULL;
+	return 0;
+}
+
+int DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
+{
+	drm_device_dma_t *dma  = dev->dma;
+
+	if (!dma) {
+		DRM_ERROR("No DMA support\n");
+		return 1;
+	}
+
+	if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) {
+		DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
+			  buf->idx, buf->waiting, buf->pending, buf->list);
+	}
+	if (!bl) return 1;
+#if __HAVE_DMA_HISTOGRAM
+	buf->time_freed = get_cycles();
+	DRM(histogram_compute)(dev, buf);
+#endif
+	buf->list	= DRM_LIST_FREE;
+
+	spin_lock(&bl->lock);
+	buf->next	= bl->next;
+	bl->next	= buf;
+	spin_unlock(&bl->lock);
+
+	atomic_inc(&bl->count);
+	if (atomic_read(&bl->count) > dma->buf_count) {
+		DRM_ERROR("%d of %d buffers free after addition of %d\n",
+			  atomic_read(&bl->count), dma->buf_count, buf->idx);
+		return 1;
+	}
+				/* Check for high water mark */
+	if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) {
+		atomic_set(&bl->wfh, 0);
+		wake_up_interruptible(&bl->waiting);
+	}
+	return 0;
+}
+
+static drm_buf_t *DRM(freelist_try)(drm_freelist_t *bl)
+{
+	drm_buf_t	  *buf;
+
+	if (!bl) return NULL;
+
+				/* Get buffer */
+	spin_lock(&bl->lock);
+	if (!bl->next) {
+		spin_unlock(&bl->lock);
+		return NULL;
+	}
+	buf	  = bl->next;
+	bl->next  = bl->next->next;
+	spin_unlock(&bl->lock);
+
+	atomic_dec(&bl->count);
+	buf->next = NULL;
+	buf->list = DRM_LIST_NONE;
+	if (buf->waiting || buf->pending) {
+		DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
+			  buf->idx, buf->waiting, buf->pending, buf->list);
+	}
+
+	return buf;
+}
+
+drm_buf_t *DRM(freelist_get)(drm_freelist_t *bl, int block)
+{
+	drm_buf_t	  *buf	= NULL;
+	DECLARE_WAITQUEUE(entry, current);
+
+	if (!bl || !bl->initialized) return NULL;
+
+				/* Check for low water mark */
+	if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
+		atomic_set(&bl->wfh, 1);
+	if (atomic_read(&bl->wfh)) {
+		if (block) {
+			add_wait_queue(&bl->waiting, &entry);
+			for (;;) {
+				current->state = TASK_INTERRUPTIBLE;
+				if (!atomic_read(&bl->wfh)
+				    && (buf = DRM(freelist_try)(bl))) break;
+				schedule();
+				if (signal_pending(current)) break;
+			}
+			current->state = TASK_RUNNING;
+			remove_wait_queue(&bl->waiting, &entry);
+		}
+		return buf;
+	}
+
+	return DRM(freelist_try)(bl);
+}
+
+#endif /* __HAVE_DMA_FREELIST */
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_lock.h linux/drivers/char/drm/drm_lock.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_lock.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_lock.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,251 @@
+/* lock.c -- IOCTLs for locking -*- linux-c -*-
+ * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+int DRM(block)(struct inode *inode, struct file *filp, unsigned int cmd,
+	       unsigned long arg)
+{
+	DRM_DEBUG("\n");
+	return 0;
+}
+
+int DRM(unblock)(struct inode *inode, struct file *filp, unsigned int cmd,
+		 unsigned long arg)
+{
+	DRM_DEBUG("\n");
+	return 0;
+}
+
+int DRM(lock_take)(__volatile__ unsigned int *lock, unsigned int context)
+{
+	unsigned int old, new, prev;
+
+	do {
+		old = *lock;
+		if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
+		else			  new = context | _DRM_LOCK_HELD;
+		prev = cmpxchg(lock, old, new);
+	} while (prev != old);
+	if (_DRM_LOCKING_CONTEXT(old) == context) {
+		if (old & _DRM_LOCK_HELD) {
+			if (context != DRM_KERNEL_CONTEXT) {
+				DRM_ERROR("%d holds heavyweight lock\n",
+					  context);
+			}
+			return 0;
+		}
+	}
+	if (new == (context | _DRM_LOCK_HELD)) {
+				/* Have lock */
+		return 1;
+	}
+	return 0;
+}
+
+/* This takes a lock forcibly and hands it to context.	Should ONLY be used
+   inside *_unlock to give lock to kernel before calling *_dma_schedule. */
+int DRM(lock_transfer)(drm_device_t *dev,
+		       __volatile__ unsigned int *lock, unsigned int context)
+{
+	unsigned int old, new, prev;
+
+	dev->lock.pid = 0;
+	do {
+		old  = *lock;
+		new  = context | _DRM_LOCK_HELD;
+		prev = cmpxchg(lock, old, new);
+	} while (prev != old);
+	return 1;
+}
+
+int DRM(lock_free)(drm_device_t *dev,
+		   __volatile__ unsigned int *lock, unsigned int context)
+{
+	unsigned int old, new, prev;
+	pid_t        pid = dev->lock.pid;
+
+	dev->lock.pid = 0;
+	do {
+		old  = *lock;
+		new  = 0;
+		prev = cmpxchg(lock, old, new);
+	} while (prev != old);
+	if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
+		DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n",
+			  context,
+			  _DRM_LOCKING_CONTEXT(old),
+			  pid);
+		return 1;
+	}
+	wake_up_interruptible(&dev->lock.lock_queue);
+	return 0;
+}
+
+static int DRM(flush_queue)(drm_device_t *dev, int context)
+{
+	DECLARE_WAITQUEUE(entry, current);
+	int		  ret	= 0;
+	drm_queue_t	  *q	= dev->queuelist[context];
+
+	DRM_DEBUG("\n");
+
+	atomic_inc(&q->use_count);
+	if (atomic_read(&q->use_count) > 1) {
+		atomic_inc(&q->block_write);
+		add_wait_queue(&q->flush_queue, &entry);
+		atomic_inc(&q->block_count);
+		for (;;) {
+			current->state = TASK_INTERRUPTIBLE;
+			if (!DRM_BUFCOUNT(&q->waitlist)) break;
+			schedule();
+			if (signal_pending(current)) {
+				ret = -EINTR; /* Can't restart */
+				break;
+			}
+		}
+		atomic_dec(&q->block_count);
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&q->flush_queue, &entry);
+	}
+	atomic_dec(&q->use_count);
+
+				/* NOTE: block_write is still incremented!
+				   Use drm_flush_unlock_queue to decrement. */
+	return ret;
+}
+
+static int DRM(flush_unblock_queue)(drm_device_t *dev, int context)
+{
+	drm_queue_t	  *q	= dev->queuelist[context];
+
+	DRM_DEBUG("\n");
+
+	atomic_inc(&q->use_count);
+	if (atomic_read(&q->use_count) > 1) {
+		if (atomic_read(&q->block_write)) {
+			atomic_dec(&q->block_write);
+			wake_up_interruptible(&q->write_queue);
+		}
+	}
+	atomic_dec(&q->use_count);
+	return 0;
+}
+
+int DRM(flush_block_and_flush)(drm_device_t *dev, int context,
+			       drm_lock_flags_t flags)
+{
+	int ret = 0;
+	int i;
+
+	DRM_DEBUG("\n");
+
+	if (flags & _DRM_LOCK_FLUSH) {
+		ret = DRM(flush_queue)(dev, DRM_KERNEL_CONTEXT);
+		if (!ret) ret = DRM(flush_queue)(dev, context);
+	}
+	if (flags & _DRM_LOCK_FLUSH_ALL) {
+		for (i = 0; !ret && i < dev->queue_count; i++) {
+			ret = DRM(flush_queue)(dev, i);
+		}
+	}
+	return ret;
+}
+
+int DRM(flush_unblock)(drm_device_t *dev, int context, drm_lock_flags_t flags)
+{
+	int ret = 0;
+	int i;
+
+	DRM_DEBUG("\n");
+
+	if (flags & _DRM_LOCK_FLUSH) {
+		ret = DRM(flush_unblock_queue)(dev, DRM_KERNEL_CONTEXT);
+		if (!ret) ret = DRM(flush_unblock_queue)(dev, context);
+	}
+	if (flags & _DRM_LOCK_FLUSH_ALL) {
+		for (i = 0; !ret && i < dev->queue_count; i++) {
+			ret = DRM(flush_unblock_queue)(dev, i);
+		}
+	}
+
+	return ret;
+}
+
+int DRM(finish)(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;
+	int		  ret	  = 0;
+	drm_lock_t	  lock;
+
+	DRM_DEBUG("\n");
+
+	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+		return -EFAULT;
+	ret = DRM(flush_block_and_flush)(dev, lock.context, lock.flags);
+	DRM(flush_unblock)(dev, lock.context, lock.flags);
+	return ret;
+}
+
+/* If we get here, it means that the process has called DRM_IOCTL_LOCK
+   without calling DRM_IOCTL_UNLOCK.
+
+   If the lock is not held, then let the signal proceed as usual.
+
+   If the lock is held, then set the contended flag and keep the signal
+   blocked.
+
+
+   Return 1 if the signal should be delivered normally.
+   Return 0 if the signal should be blocked.  */
+
+int DRM(notifier)(void *priv)
+{
+	drm_sigdata_t *s = (drm_sigdata_t *)priv;
+	unsigned int  old, new, prev;
+
+
+				/* Allow signal delivery if lock isn't held */
+	if (!_DRM_LOCK_IS_HELD(s->lock->lock)
+	    || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
+
+				/* Otherwise, set flag to force call to
+                                   drmUnlock */
+	do {
+		old  = s->lock->lock;
+		new  = old | _DRM_LOCK_CONT;
+		prev = cmpxchg(&s->lock->lock, old, new);
+	} while (prev != old);
+	return 0;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_memory.h linux/drivers/char/drm/drm_memory.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_memory.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_memory.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,459 @@
+/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
+ * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include "drmP.h"
+#include <linux/wrapper.h>
+
+typedef struct drm_mem_stats {
+	const char	  *name;
+	int		  succeed_count;
+	int		  free_count;
+	int		  fail_count;
+	unsigned long	  bytes_allocated;
+	unsigned long	  bytes_freed;
+} drm_mem_stats_t;
+
+static spinlock_t	  DRM(mem_lock)	     = SPIN_LOCK_UNLOCKED;
+static unsigned long	  DRM(ram_available) = 0; /* In pages */
+static unsigned long	  DRM(ram_used)      = 0;
+static drm_mem_stats_t	  DRM(mem_stats)[]   = {
+	[DRM_MEM_DMA]	    = { "dmabufs"  },
+	[DRM_MEM_SAREA]	    = { "sareas"   },
+	[DRM_MEM_DRIVER]    = { "driver"   },
+	[DRM_MEM_MAGIC]	    = { "magic"	   },
+	[DRM_MEM_IOCTLS]    = { "ioctltab" },
+	[DRM_MEM_MAPS]	    = { "maplist"  },
+	[DRM_MEM_VMAS]	    = { "vmalist"  },
+	[DRM_MEM_BUFS]	    = { "buflist"  },
+	[DRM_MEM_SEGS]	    = { "seglist"  },
+	[DRM_MEM_PAGES]	    = { "pagelist" },
+	[DRM_MEM_FILES]	    = { "files"	   },
+	[DRM_MEM_QUEUES]    = { "queues"   },
+	[DRM_MEM_CMDS]	    = { "commands" },
+	[DRM_MEM_MAPPINGS]  = { "mappings" },
+	[DRM_MEM_BUFLISTS]  = { "buflists" },
+	[DRM_MEM_AGPLISTS]  = { "agplist"  },
+	[DRM_MEM_SGLISTS]   = { "sglist"   },
+	[DRM_MEM_TOTALAGP]  = { "totalagp" },
+	[DRM_MEM_BOUNDAGP]  = { "boundagp" },
+	[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
+	[DRM_MEM_STUB]      = { "stub"     },
+	{ NULL, 0, }		/* Last entry must be null */
+};
+
+void DRM(mem_init)(void)
+{
+	drm_mem_stats_t *mem;
+	struct sysinfo	si;
+
+	for (mem = DRM(mem_stats); mem->name; ++mem) {
+		mem->succeed_count   = 0;
+		mem->free_count	     = 0;
+		mem->fail_count	     = 0;
+		mem->bytes_allocated = 0;
+		mem->bytes_freed     = 0;
+	}
+
+	si_meminfo(&si);
+#if LINUX_VERSION_CODE < 0x020317
+				/* Changed to page count in 2.3.23 */
+	DRM(ram_available) = si.totalram >> PAGE_SHIFT;
+#else
+	DRM(ram_available) = si.totalram;
+#endif
+	DRM(ram_used)	   = 0;
+}
+
+/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
+
+static int DRM(_mem_info)(char *buf, char **start, off_t offset,
+			  int request, int *eof, void *data)
+{
+	drm_mem_stats_t *pt;
+	int             len = 0;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*eof   = 0;
+	*start = &buf[offset];
+
+	DRM_PROC_PRINT("		  total counts			"
+		       " |    outstanding  \n");
+	DRM_PROC_PRINT("type	   alloc freed fail	bytes	   freed"
+		       " | allocs      bytes\n\n");
+	DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
+		       "system", 0, 0, 0,
+		       DRM(ram_available) << (PAGE_SHIFT - 10));
+	DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
+		       "locked", 0, 0, 0, DRM(ram_used) >> 10);
+	DRM_PROC_PRINT("\n");
+	for (pt = DRM(mem_stats); pt->name; pt++) {
+		DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
+			       pt->name,
+			       pt->succeed_count,
+			       pt->free_count,
+			       pt->fail_count,
+			       pt->bytes_allocated,
+			       pt->bytes_freed,
+			       pt->succeed_count - pt->free_count,
+			       (long)pt->bytes_allocated
+			       - (long)pt->bytes_freed);
+	}
+
+	if (len > request + offset) return request;
+	*eof = 1;
+	return len - offset;
+}
+
+int DRM(mem_info)(char *buf, char **start, off_t offset,
+		  int len, int *eof, void *data)
+{
+	int ret;
+
+	spin_lock(&DRM(mem_lock));
+	ret = DRM(_mem_info)(buf, start, offset, len, eof, data);
+	spin_unlock(&DRM(mem_lock));
+	return ret;
+}
+
+void *DRM(alloc)(size_t size, int area)
+{
+	void *pt;
+
+	if (!size) {
+		DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
+		return NULL;
+	}
+
+	if (!(pt = kmalloc(size, GFP_KERNEL))) {
+		spin_lock(&DRM(mem_lock));
+		++DRM(mem_stats)[area].fail_count;
+		spin_unlock(&DRM(mem_lock));
+		return NULL;
+	}
+	spin_lock(&DRM(mem_lock));
+	++DRM(mem_stats)[area].succeed_count;
+	DRM(mem_stats)[area].bytes_allocated += size;
+	spin_unlock(&DRM(mem_lock));
+	return pt;
+}
+
+void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
+{
+	void *pt;
+
+	if (!(pt = DRM(alloc)(size, area))) return NULL;
+	if (oldpt && oldsize) {
+		memcpy(pt, oldpt, oldsize);
+		DRM(free)(oldpt, oldsize, area);
+	}
+	return pt;
+}
+
+char *DRM(strdup)(const char *s, int area)
+{
+	char *pt;
+	int	 length = s ? strlen(s) : 0;
+
+	if (!(pt = DRM(alloc)(length+1, area))) return NULL;
+	strcpy(pt, s);
+	return pt;
+}
+
+void DRM(strfree)(const char *s, int area)
+{
+	unsigned int size;
+
+	if (!s) return;
+
+	size = 1 + (s ? strlen(s) : 0);
+	DRM(free)((void *)s, size, area);
+}
+
+void DRM(free)(void *pt, size_t size, int area)
+{
+	int alloc_count;
+	int free_count;
+
+	if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
+	else	 kfree(pt);
+	spin_lock(&DRM(mem_lock));
+	DRM(mem_stats)[area].bytes_freed += size;
+	free_count  = ++DRM(mem_stats)[area].free_count;
+	alloc_count =	DRM(mem_stats)[area].succeed_count;
+	spin_unlock(&DRM(mem_lock));
+	if (free_count > alloc_count) {
+		DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
+			      free_count, alloc_count);
+	}
+}
+
+unsigned long DRM(alloc_pages)(int order, int area)
+{
+	unsigned long address;
+	unsigned long bytes	  = PAGE_SIZE << order;
+	unsigned long addr;
+	unsigned int  sz;
+
+	spin_lock(&DRM(mem_lock));
+	if ((DRM(ram_used) >> PAGE_SHIFT)
+	    > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) {
+		spin_unlock(&DRM(mem_lock));
+		return 0;
+	}
+	spin_unlock(&DRM(mem_lock));
+
+	address = __get_free_pages(GFP_KERNEL, order);
+	if (!address) {
+		spin_lock(&DRM(mem_lock));
+		++DRM(mem_stats)[area].fail_count;
+		spin_unlock(&DRM(mem_lock));
+		return 0;
+	}
+	spin_lock(&DRM(mem_lock));
+	++DRM(mem_stats)[area].succeed_count;
+	DRM(mem_stats)[area].bytes_allocated += bytes;
+	DRM(ram_used)		             += bytes;
+	spin_unlock(&DRM(mem_lock));
+
+
+				/* Zero outside the lock */
+	memset((void *)address, 0, bytes);
+
+				/* Reserve */
+	for (addr = address, sz = bytes;
+	     sz > 0;
+	     addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+#if LINUX_VERSION_CODE >= 0x020400
+				/* Argument type changed in 2.4.0-test6/pre8 */
+		mem_map_reserve(virt_to_page(addr));
+#else
+		mem_map_reserve(MAP_NR(addr));
+#endif
+	}
+
+	return address;
+}
+
+void DRM(free_pages)(unsigned long address, int order, int area)
+{
+	unsigned long bytes = PAGE_SIZE << order;
+	int		  alloc_count;
+	int		  free_count;
+	unsigned long addr;
+	unsigned int  sz;
+
+	if (!address) {
+		DRM_MEM_ERROR(area, "Attempt to free address 0\n");
+	} else {
+				/* Unreserve */
+		for (addr = address, sz = bytes;
+		     sz > 0;
+		     addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+#if LINUX_VERSION_CODE >= 0x020400
+				/* Argument type changed in 2.4.0-test6/pre8 */
+			mem_map_unreserve(virt_to_page(addr));
+#else
+			mem_map_unreserve(MAP_NR(addr));
+#endif
+		}
+		free_pages(address, order);
+	}
+
+	spin_lock(&DRM(mem_lock));
+	free_count  = ++DRM(mem_stats)[area].free_count;
+	alloc_count =	DRM(mem_stats)[area].succeed_count;
+	DRM(mem_stats)[area].bytes_freed += bytes;
+	DRM(ram_used)			 -= bytes;
+	spin_unlock(&DRM(mem_lock));
+	if (free_count > alloc_count) {
+		DRM_MEM_ERROR(area,
+			      "Excess frees: %d frees, %d allocs\n",
+			      free_count, alloc_count);
+	}
+}
+
+void *DRM(ioremap)(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(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;
+	int free_count;
+
+	if (!pt)
+		DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+			      "Attempt to free NULL pointer\n");
+	else
+		iounmap(pt);
+
+	spin_lock(&DRM(mem_lock));
+	DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size;
+	free_count  = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
+	alloc_count =	DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
+	spin_unlock(&DRM(mem_lock));
+	if (free_count > alloc_count) {
+		DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
+			      "Excess frees: %d frees, %d allocs\n",
+			      free_count, alloc_count);
+	}
+}
+
+#if __REALLY_HAVE_AGP
+
+agp_memory *DRM(alloc_agp)(int pages, u32 type)
+{
+	agp_memory *handle;
+
+	if (!pages) {
+		DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
+		return NULL;
+	}
+
+	if ((handle = DRM(agp_allocate_memory)(pages, type))) {
+		spin_lock(&DRM(mem_lock));
+		++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
+		DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
+			+= pages << PAGE_SHIFT;
+		spin_unlock(&DRM(mem_lock));
+		return handle;
+	}
+	spin_lock(&DRM(mem_lock));
+	++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count;
+	spin_unlock(&DRM(mem_lock));
+	return NULL;
+}
+
+int DRM(free_agp)(agp_memory *handle, int pages)
+{
+	int           alloc_count;
+	int           free_count;
+	int           retval = -EINVAL;
+
+	if (!handle) {
+		DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+			      "Attempt to free NULL AGP handle\n");
+		return retval;;
+	}
+
+	if (DRM(agp_free_memory)(handle)) {
+		spin_lock(&DRM(mem_lock));
+		free_count  = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
+		alloc_count =   DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
+		DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
+			+= pages << PAGE_SHIFT;
+		spin_unlock(&DRM(mem_lock));
+		if (free_count > alloc_count) {
+			DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+				      "Excess frees: %d frees, %d allocs\n",
+				      free_count, alloc_count);
+		}
+		return 0;
+	}
+	return retval;
+}
+
+int DRM(bind_agp)(agp_memory *handle, unsigned int start)
+{
+	int retcode = -EINVAL;
+
+	if (!handle) {
+		DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+			      "Attempt to bind NULL AGP handle\n");
+		return retcode;
+	}
+
+	if (!(retcode = DRM(agp_bind_memory)(handle, start))) {
+		spin_lock(&DRM(mem_lock));
+		++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
+		DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
+			+= handle->page_count << PAGE_SHIFT;
+		spin_unlock(&DRM(mem_lock));
+		return retcode;
+	}
+	spin_lock(&DRM(mem_lock));
+	++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count;
+	spin_unlock(&DRM(mem_lock));
+	return retcode;
+}
+
+int DRM(unbind_agp)(agp_memory *handle)
+{
+	int alloc_count;
+	int free_count;
+	int retcode = -EINVAL;
+
+	if (!handle) {
+		DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+			      "Attempt to unbind NULL AGP handle\n");
+		return retcode;
+	}
+
+	if ((retcode = DRM(agp_unbind_memory)(handle))) return retcode;
+	spin_lock(&DRM(mem_lock));
+	free_count  = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
+	alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
+	DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
+		+= handle->page_count << PAGE_SHIFT;
+	spin_unlock(&DRM(mem_lock));
+	if (free_count > alloc_count) {
+		DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+			      "Excess frees: %d frees, %d allocs\n",
+			      free_count, alloc_count);
+	}
+	return retcode;
+}
+#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_proc.h linux/drivers/char/drm/drm_proc.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_proc.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_proc.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,630 @@
+/* drm_proc.h -- /proc support for DRM -*- linux-c -*-
+ * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ *
+ * Acknowledgements:
+ *    Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
+ *    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,
+				  int request, int *eof, void *data);
+static int	   DRM(vm_info)(char *buf, char **start, off_t offset,
+				int request, int *eof, void *data);
+static int	   DRM(clients_info)(char *buf, char **start, off_t offset,
+				     int request, int *eof, void *data);
+static int	   DRM(queues_info)(char *buf, char **start, off_t offset,
+				    int request, int *eof, void *data);
+static int	   DRM(bufs_info)(char *buf, char **start, off_t offset,
+				  int request, int *eof, void *data);
+#if DRM_DEBUG_CODE
+static int	   DRM(vma_info)(char *buf, char **start, off_t offset,
+				 int request, int *eof, void *data);
+#endif
+#if __HAVE_DMA_HISTOGRAM
+static int	   DRM(histo_info)(char *buf, char **start, off_t offset,
+				   int request, int *eof, void *data);
+#endif
+
+struct drm_proc_list {
+	const char *name;
+	int	   (*f)(char *, char **, off_t, int, int *, void *);
+} DRM(proc_list)[] = {
+	{ "name",    DRM(name_info)    },
+	{ "mem",     DRM(mem_info)     },
+	{ "vm",	     DRM(vm_info)      },
+	{ "clients", DRM(clients_info) },
+	{ "queues",  DRM(queues_info)  },
+	{ "bufs",    DRM(bufs_info)    },
+#if DRM_DEBUG_CODE
+	{ "vma",     DRM(vma_info)     },
+#endif
+#if __HAVE_DMA_HISTOGRAM
+	{ "histo",   DRM(histo_info)   },
+#endif
+};
+#define DRM_PROC_ENTRIES (sizeof(DRM(proc_list))/sizeof(DRM(proc_list)[0]))
+
+struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev, int minor,
+				      struct proc_dir_entry *root,
+				      struct proc_dir_entry **dev_root)
+{
+	struct proc_dir_entry *ent;
+	int		      i, j;
+	char                  name[64];
+
+	if (!minor) root = create_proc_entry("dri", S_IFDIR, NULL);
+	if (!root) {
+		DRM_ERROR("Cannot create /proc/dri\n");
+		return NULL;
+	}
+
+	sprintf(name, "%d", minor);
+	*dev_root = create_proc_entry(name, S_IFDIR, root);
+	if (!*dev_root) {
+		DRM_ERROR("Cannot create /proc/%s\n", name);
+		return NULL;
+	}
+
+	for (i = 0; i < DRM_PROC_ENTRIES; i++) {
+		ent = create_proc_entry(DRM(proc_list)[i].name,
+					S_IFREG|S_IRUGO, *dev_root);
+		if (!ent) {
+			DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
+				  name, DRM(proc_list)[i].name);
+			for (j = 0; j < i; j++)
+				remove_proc_entry(DRM(proc_list)[i].name,
+						  *dev_root);
+			remove_proc_entry(name, root);
+			if (!minor) remove_proc_entry("dri", NULL);
+			return NULL;
+		}
+		ent->read_proc = DRM(proc_list)[i].f;
+		ent->data      = dev;
+	}
+
+	return root;
+}
+
+
+int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root,
+		      struct proc_dir_entry *dev_root)
+{
+	int  i;
+	char name[64];
+
+	if (!root || !dev_root) return 0;
+
+	for (i = 0; i < DRM_PROC_ENTRIES; i++)
+		remove_proc_entry(DRM(proc_list)[i].name, dev_root);
+	sprintf(name, "%d", minor);
+	remove_proc_entry(name, root);
+	if (!minor) remove_proc_entry("dri", NULL);
+
+	return 0;
+}
+
+static int DRM(name_info)(char *buf, char **start, off_t offset, int request,
+			  int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int          len  = 0;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof   = 0;
+
+	if (dev->unique) {
+		DRM_PROC_PRINT("%s 0x%x %s\n",
+			       dev->name, dev->device, dev->unique);
+	} else {
+		DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device);
+	}
+
+	if (len > request + offset) return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int DRM(_vm_info)(char *buf, char **start, off_t offset, int request,
+			 int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int          len  = 0;
+	drm_map_t    *map;
+	drm_map_list_t *r_list;
+	struct list_head *list;
+
+				/* Hardcoded from _DRM_FRAME_BUFFER,
+                                   _DRM_REGISTERS, _DRM_SHM, and
+                                   _DRM_AGP. */
+	const char   *types[] = { "FB", "REG", "SHM", "AGP" };
+	const char   *type;
+	int	     i;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof   = 0;
+
+	DRM_PROC_PRINT("slot	 offset	      size type flags	 "
+		       "address mtrr\n\n");
+	i = 0;
+	list_for_each(list, &dev->maplist->head) {
+		r_list = (drm_map_list_t *)list;
+		map = r_list->map;
+		if(!map) continue;
+		if (map->type < 0 || map->type > 3) type = "??";
+		else				    type = types[map->type];
+		DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
+			       i,
+			       map->offset,
+			       map->size,
+			       type,
+			       map->flags,
+			       (unsigned long)map->handle);
+		if (map->mtrr < 0) {
+			DRM_PROC_PRINT("none\n");
+		} else {
+			DRM_PROC_PRINT("%4d\n", map->mtrr);
+		}
+		i++;
+	}
+
+	if (len > request + offset) return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int DRM(vm_info)(char *buf, char **start, off_t offset, int request,
+			int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int	     ret;
+
+	down(&dev->struct_sem);
+	ret = DRM(_vm_info)(buf, start, offset, request, eof, data);
+	up(&dev->struct_sem);
+	return ret;
+}
+
+
+static int DRM(_queues_info)(char *buf, char **start, off_t offset,
+			     int request, int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int          len  = 0;
+	int	     i;
+	drm_queue_t  *q;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof   = 0;
+
+	DRM_PROC_PRINT("  ctx/flags   use   fin"
+		       "   blk/rw/rwf  wait    flushed	   queued"
+		       "      locks\n\n");
+	for (i = 0; i < dev->queue_count; i++) {
+		q = dev->queuelist[i];
+		atomic_inc(&q->use_count);
+		DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
+				   "%5d/0x%03x %5d %5d"
+				   " %5d/%c%c/%c%c%c %5Zd\n",
+				   i,
+				   q->flags,
+				   atomic_read(&q->use_count),
+				   atomic_read(&q->finalization),
+				   atomic_read(&q->block_count),
+				   atomic_read(&q->block_read) ? 'r' : '-',
+				   atomic_read(&q->block_write) ? 'w' : '-',
+				   waitqueue_active(&q->read_queue) ? 'r':'-',
+				   waitqueue_active(&q->write_queue) ? 'w':'-',
+				   waitqueue_active(&q->flush_queue) ? 'f':'-',
+				   DRM_BUFCOUNT(&q->waitlist));
+		atomic_dec(&q->use_count);
+	}
+
+	if (len > request + offset) return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int DRM(queues_info)(char *buf, char **start, off_t offset, int request,
+			    int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int	     ret;
+
+	down(&dev->struct_sem);
+	ret = DRM(_queues_info)(buf, start, offset, request, eof, data);
+	up(&dev->struct_sem);
+	return ret;
+}
+
+/* drm_bufs_info is called whenever a process reads
+   /dev/dri/<dev>/bufs. */
+
+static int DRM(_bufs_info)(char *buf, char **start, off_t offset, int request,
+			   int *eof, void *data)
+{
+	drm_device_t	 *dev = (drm_device_t *)data;
+	int              len  = 0;
+	drm_device_dma_t *dma = dev->dma;
+	int		 i;
+
+	if (!dma || offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof   = 0;
+
+	DRM_PROC_PRINT(" o     size count  free	 segs pages    kB\n\n");
+	for (i = 0; i <= DRM_MAX_ORDER; i++) {
+		if (dma->bufs[i].buf_count)
+			DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
+				       i,
+				       dma->bufs[i].buf_size,
+				       dma->bufs[i].buf_count,
+				       atomic_read(&dma->bufs[i]
+						   .freelist.count),
+				       dma->bufs[i].seg_count,
+				       dma->bufs[i].seg_count
+				       *(1 << dma->bufs[i].page_order),
+				       (dma->bufs[i].seg_count
+					* (1 << dma->bufs[i].page_order))
+				       * PAGE_SIZE / 1024);
+	}
+	DRM_PROC_PRINT("\n");
+	for (i = 0; i < dma->buf_count; i++) {
+		if (i && !(i%32)) DRM_PROC_PRINT("\n");
+		DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
+	}
+	DRM_PROC_PRINT("\n");
+
+	if (len > request + offset) return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int DRM(bufs_info)(char *buf, char **start, off_t offset, int request,
+			  int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int	     ret;
+
+	down(&dev->struct_sem);
+	ret = DRM(_bufs_info)(buf, start, offset, request, eof, data);
+	up(&dev->struct_sem);
+	return ret;
+}
+
+
+static int DRM(_clients_info)(char *buf, char **start, off_t offset,
+			      int request, int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int          len  = 0;
+	drm_file_t   *priv;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof   = 0;
+
+	DRM_PROC_PRINT("a dev	pid    uid	magic	  ioctls\n\n");
+	for (priv = dev->file_first; priv; priv = priv->next) {
+		DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
+			       priv->authenticated ? 'y' : 'n',
+			       priv->minor,
+			       priv->pid,
+			       priv->uid,
+			       priv->magic,
+			       priv->ioctl_count);
+	}
+
+	if (len > request + offset) return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int DRM(clients_info)(char *buf, char **start, off_t offset,
+			     int request, int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int	     ret;
+
+	down(&dev->struct_sem);
+	ret = DRM(_clients_info)(buf, start, offset, request, eof, data);
+	up(&dev->struct_sem);
+	return ret;
+}
+
+#if DRM_DEBUG_CODE
+
+#define DRM_VMA_VERBOSE 0
+
+static int DRM(_vma_info)(char *buf, char **start, off_t offset, int request,
+			  int *eof, void *data)
+{
+	drm_device_t	      *dev = (drm_device_t *)data;
+	int                   len  = 0;
+	drm_vma_entry_t	      *pt;
+	struct vm_area_struct *vma;
+#if DRM_VMA_VERBOSE
+	unsigned long	      i;
+	unsigned long	      address;
+	pgd_t		      *pgd;
+	pmd_t		      *pmd;
+	pte_t		      *pte;
+#endif
+#if defined(__i386__)
+	unsigned int	      pgprot;
+#endif
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof   = 0;
+
+	DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
+		       atomic_read(&dev->vma_count),
+		       high_memory, virt_to_phys(high_memory));
+	for (pt = dev->vmalist; pt; pt = pt->next) {
+		if (!(vma = pt->vma)) continue;
+		DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
+			       pt->pid,
+			       vma->vm_start,
+			       vma->vm_end,
+			       vma->vm_flags & VM_READ	   ? 'r' : '-',
+			       vma->vm_flags & VM_WRITE	   ? 'w' : '-',
+			       vma->vm_flags & VM_EXEC	   ? 'x' : '-',
+			       vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
+			       vma->vm_flags & VM_LOCKED   ? 'l' : '-',
+			       vma->vm_flags & VM_IO	   ? 'i' : '-',
+			       VM_OFFSET(vma));
+
+#if defined(__i386__)
+		pgprot = pgprot_val(vma->vm_page_prot);
+		DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
+			       pgprot & _PAGE_PRESENT  ? 'p' : '-',
+			       pgprot & _PAGE_RW       ? 'w' : 'r',
+			       pgprot & _PAGE_USER     ? 'u' : 's',
+			       pgprot & _PAGE_PWT      ? 't' : 'b',
+			       pgprot & _PAGE_PCD      ? 'u' : 'c',
+			       pgprot & _PAGE_ACCESSED ? 'a' : '-',
+			       pgprot & _PAGE_DIRTY    ? 'd' : '-',
+			       pgprot & _PAGE_PSE      ? 'm' : 'k',
+			       pgprot & _PAGE_GLOBAL   ? 'g' : 'l' );
+#endif
+		DRM_PROC_PRINT("\n");
+#if 0
+		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);
+			if (pte_present(*pte)) {
+				address = __pa(pte_page(*pte))
+					+ (i & (PAGE_SIZE-1));
+				DRM_PROC_PRINT("      0x%08lx -> 0x%08lx"
+					       " %c%c%c%c%c\n",
+					       i,
+					       address,
+					       pte_read(*pte)  ? 'r' : '-',
+					       pte_write(*pte) ? 'w' : '-',
+					       pte_exec(*pte)  ? 'x' : '-',
+					       pte_dirty(*pte) ? 'd' : '-',
+					       pte_young(*pte) ? 'a' : '-' );
+			} else {
+				DRM_PROC_PRINT("      0x%08lx\n", i);
+			}
+		}
+#endif
+	}
+
+	if (len > request + offset) return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int DRM(vma_info)(char *buf, char **start, off_t offset, int request,
+			 int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int	     ret;
+
+	down(&dev->struct_sem);
+	ret = DRM(_vma_info)(buf, start, offset, request, eof, data);
+	up(&dev->struct_sem);
+	return ret;
+}
+#endif
+
+
+#if __HAVE_DMA_HISTOGRAM
+static int DRM(_histo_info)(char *buf, char **start, off_t offset, int request,
+			    int *eof, void *data)
+{
+	drm_device_t	 *dev = (drm_device_t *)data;
+	int              len  = 0;
+	drm_device_dma_t *dma = dev->dma;
+	int		 i;
+	unsigned long	 slot_value = DRM_DMA_HISTOGRAM_INITIAL;
+	unsigned long	 prev_value = 0;
+	drm_buf_t	 *buffer;
+
+	if (offset > DRM_PROC_LIMIT) {
+		*eof = 1;
+		return 0;
+	}
+
+	*start = &buf[offset];
+	*eof   = 0;
+
+	DRM_PROC_PRINT("general statistics:\n");
+	DRM_PROC_PRINT("total	 %10u\n", atomic_read(&dev->histo.total));
+	DRM_PROC_PRINT("open	 %10u\n",
+		       atomic_read(&dev->counts[_DRM_STAT_OPENS]));
+	DRM_PROC_PRINT("close	 %10u\n",
+		       atomic_read(&dev->counts[_DRM_STAT_CLOSES]));
+	DRM_PROC_PRINT("ioctl	 %10u\n",
+		       atomic_read(&dev->counts[_DRM_STAT_IOCTLS]));
+
+	DRM_PROC_PRINT("\nlock statistics:\n");
+	DRM_PROC_PRINT("locks	 %10u\n",
+		       atomic_read(&dev->counts[_DRM_STAT_LOCKS]));
+	DRM_PROC_PRINT("unlocks	 %10u\n",
+		       atomic_read(&dev->counts[_DRM_STAT_UNLOCKS]));
+
+	if (dma) {
+#if 0
+		DRM_PROC_PRINT("\ndma statistics:\n");
+		DRM_PROC_PRINT("prio	 %10u\n",
+			       atomic_read(&dma->total_prio));
+		DRM_PROC_PRINT("bytes	 %10u\n",
+			       atomic_read(&dma->total_bytes));
+		DRM_PROC_PRINT("dmas	 %10u\n",
+			       atomic_read(&dma->total_dmas));
+		DRM_PROC_PRINT("missed:\n");
+		DRM_PROC_PRINT("  dma	 %10u\n",
+			       atomic_read(&dma->total_missed_dma));
+		DRM_PROC_PRINT("  lock	 %10u\n",
+			       atomic_read(&dma->total_missed_lock));
+		DRM_PROC_PRINT("  free	 %10u\n",
+			       atomic_read(&dma->total_missed_free));
+		DRM_PROC_PRINT("  sched	 %10u\n",
+			       atomic_read(&dma->total_missed_sched));
+		DRM_PROC_PRINT("tried	 %10u\n",
+			       atomic_read(&dma->total_tried));
+		DRM_PROC_PRINT("hit	 %10u\n",
+			       atomic_read(&dma->total_hit));
+		DRM_PROC_PRINT("lost	 %10u\n",
+			       atomic_read(&dma->total_lost));
+#endif
+
+		buffer = dma->next_buffer;
+		if (buffer) {
+			DRM_PROC_PRINT("next_buffer %7d\n", buffer->idx);
+		} else {
+			DRM_PROC_PRINT("next_buffer    none\n");
+		}
+		buffer = dma->this_buffer;
+		if (buffer) {
+			DRM_PROC_PRINT("this_buffer %7d\n", buffer->idx);
+		} else {
+			DRM_PROC_PRINT("this_buffer    none\n");
+		}
+	}
+
+
+	DRM_PROC_PRINT("\nvalues:\n");
+	if (dev->lock.hw_lock) {
+		DRM_PROC_PRINT("lock	       0x%08x\n",
+			       dev->lock.hw_lock->lock);
+	} else {
+		DRM_PROC_PRINT("lock		     none\n");
+	}
+	DRM_PROC_PRINT("context_flag   0x%08lx\n", dev->context_flag);
+	DRM_PROC_PRINT("interrupt_flag 0x%08lx\n", dev->interrupt_flag);
+	DRM_PROC_PRINT("dma_flag       0x%08lx\n", dev->dma_flag);
+
+	DRM_PROC_PRINT("queue_count    %10d\n",	 dev->queue_count);
+	DRM_PROC_PRINT("last_context   %10d\n",	 dev->last_context);
+	DRM_PROC_PRINT("last_switch    %10lu\n", dev->last_switch);
+	DRM_PROC_PRINT("last_checked   %10d\n",	 dev->last_checked);
+
+
+	DRM_PROC_PRINT("\n		       q2d	  d2c	     c2f"
+		       "	q2c	   q2f	      dma	 sch"
+		       "	ctx	  lacq	     lhld\n\n");
+	for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) {
+		DRM_PROC_PRINT("%s %10lu %10u %10u %10u %10u %10u"
+			       " %10u %10u %10u %10u %10u\n",
+			       i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ",
+			       i == DRM_DMA_HISTOGRAM_SLOTS - 1
+			       ? prev_value : slot_value ,
+
+			       atomic_read(&dev->histo
+					   .queued_to_dispatched[i]),
+			       atomic_read(&dev->histo
+					   .dispatched_to_completed[i]),
+			       atomic_read(&dev->histo
+					   .completed_to_freed[i]),
+
+			       atomic_read(&dev->histo
+					   .queued_to_completed[i]),
+			       atomic_read(&dev->histo
+					   .queued_to_freed[i]),
+			       atomic_read(&dev->histo.dma[i]),
+			       atomic_read(&dev->histo.schedule[i]),
+			       atomic_read(&dev->histo.ctx[i]),
+			       atomic_read(&dev->histo.lacq[i]),
+			       atomic_read(&dev->histo.lhld[i]));
+		prev_value = slot_value;
+		slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value);
+	}
+
+	if (len > request + offset) return request;
+	*eof = 1;
+	return len - offset;
+}
+
+static int DRM(histo_info)(char *buf, char **start, off_t offset, int request,
+			   int *eof, void *data)
+{
+	drm_device_t *dev = (drm_device_t *)data;
+	int	     ret;
+
+	down(&dev->struct_sem);
+	ret = DRM(_histo_info)(buf, start, offset, request, eof, data);
+	up(&dev->struct_sem);
+	return ret;
+}
+#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_scatter.h linux/drivers/char/drm/drm_scatter.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_scatter.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_scatter.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,219 @@
+/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
+ * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/vmalloc.h>
+#include "drmP.h"
+
+#define DEBUG_SCATTER 0
+
+void DRM(sg_cleanup)( drm_sg_mem_t *entry )
+{
+	struct page *page;
+	int i;
+
+	for ( i = 0 ; i < entry->pages ; i++ ) {
+		page = entry->pagelist[i];
+		if ( page )
+			ClearPageReserved( page );
+	}
+
+	vfree( entry->virtual );
+
+	DRM(free)( entry->pagelist,
+		  entry->pages * sizeof(*entry->pagelist),
+		  DRM_MEM_PAGES );
+	DRM(free)( entry,
+		  sizeof(*entry),
+		  DRM_MEM_SGLISTS );
+}
+
+int DRM(sg_alloc)( 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_scatter_gather_t request;
+	drm_sg_mem_t *entry;
+	unsigned long pages, i, j;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	if ( dev->sg )
+		return -EINVAL;
+
+	if ( copy_from_user( &request,
+			     (drm_scatter_gather_t *)arg,
+			     sizeof(request) ) )
+		return -EFAULT;
+
+	entry = DRM(alloc)( sizeof(*entry), DRM_MEM_SGLISTS );
+	if ( !entry )
+		return -ENOMEM;
+
+   	memset( entry, 0, sizeof(*entry) );
+
+	pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
+	DRM_DEBUG( "sg size=%ld pages=%ld\n", request.size, pages );
+
+	entry->pages = pages;
+	entry->pagelist = DRM(alloc)( pages * sizeof(*entry->pagelist),
+				     DRM_MEM_PAGES );
+	if ( !entry->pagelist ) {
+		DRM(free)( entry, sizeof(*entry), DRM_MEM_SGLISTS );
+		return -ENOMEM;
+	}
+	memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
+
+	entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
+	if ( !entry->virtual ) {
+		DRM(free)( entry->pagelist,
+			  entry->pages * sizeof(*entry->pagelist),
+			  DRM_MEM_PAGES );
+		DRM(free)( entry,
+			  sizeof(*entry),
+			  DRM_MEM_SGLISTS );
+		return -ENOMEM;
+	}
+
+	/* This also forces the mapping of COW pages, so our page list
+	 * will be valid.  Please don't remove it...
+	 */
+	memset( entry->virtual, 0, pages << PAGE_SHIFT );
+
+	entry->handle = (unsigned long)entry->virtual;
+
+	DRM_DEBUG( "sg alloc handle  = %08lx\n", entry->handle );
+	DRM_DEBUG( "sg alloc virtual = %p\n", entry->virtual );
+
+	for ( i = entry->handle, j = 0 ; j < pages ; i += PAGE_SIZE, j++ ) {
+		pgd = pgd_offset_k( i );
+		if ( !pgd_present( *pgd ) )
+			goto failed;
+
+		pmd = pmd_offset( pgd, i );
+		if ( !pmd_present( *pmd ) )
+			goto failed;
+
+		pte = pte_offset( pmd, i );
+		if ( !pte_present( *pte ) )
+			goto failed;
+
+		entry->pagelist[j] = pte_page( *pte );
+
+		SetPageReserved( entry->pagelist[j] );
+	}
+
+	request.handle = entry->handle;
+
+	if ( copy_to_user( (drm_scatter_gather_t *)arg,
+			   &request,
+			   sizeof(request) ) ) {
+		DRM(sg_cleanup)( entry );
+		return -EFAULT;
+	}
+
+	dev->sg = entry;
+
+#if DEBUG_SCATTER
+	/* Verify that each page points to its virtual address, and vice
+	 * versa.
+	 */
+	{
+	int error = 0;
+
+	for ( i = 0 ; i < pages ; i++ ) {
+		unsigned long *tmp;
+
+		tmp = (unsigned long *)entry->pagelist[i]->virtual;
+		for ( j = 0 ;
+		      j < PAGE_SIZE / sizeof(unsigned long) ;
+		      j++, tmp++ ) {
+			*tmp = 0xcafebabe;
+		}
+		tmp = (unsigned long *)((u8 *)entry->virtual +
+					(PAGE_SIZE * i));
+		for( j = 0 ;
+		     j < PAGE_SIZE / sizeof(unsigned long) ;
+		     j++, tmp++ ) {
+			if ( *tmp != 0xcafebabe && error == 0 ) {
+				error = 1;
+				DRM_ERROR( "Scatter allocation error, "
+					   "pagelist does not match "
+					   "virtual mapping\n" );
+			}
+		}
+		tmp = (unsigned long *)entry->pagelist[i]->virtual;
+		for(j = 0 ;
+		    j < PAGE_SIZE / sizeof(unsigned long) ;
+		    j++, tmp++) {
+			*tmp = 0;
+		}
+	}
+	if (error == 0)
+		DRM_ERROR( "Scatter allocation matches pagelist\n" );
+	}
+#endif
+
+	return 0;
+
+ failed:
+	DRM(sg_cleanup)( entry );
+	return -ENOMEM;
+}
+
+int DRM(sg_free)( 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_scatter_gather_t request;
+	drm_sg_mem_t *entry;
+
+	if ( copy_from_user( &request,
+			     (drm_scatter_gather_t *)arg,
+			     sizeof(request) ) )
+		return -EFAULT;
+
+	entry = dev->sg;
+	dev->sg = NULL;
+
+	if ( !entry || entry->handle != request.handle )
+		return -EINVAL;
+
+	DRM_DEBUG( "sg free virtual  = %p\n", entry->virtual );
+
+	DRM(sg_cleanup)( entry );
+
+	return 0;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_stub.h linux/drivers/char/drm/drm_stub.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_stub.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_stub.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,157 @@
+/* drm_stub.h -- -*- linux-c -*-
+ * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
+ *
+ * Copyright 2001 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>
+ *
+ */
+
+#define __NO_VERSION__
+#include "drmP.h"
+
+#if LINUX_VERSION_CODE < 0x020400
+#include "stubsupport-pre24.h"
+#endif
+
+#define DRM_STUB_MAXCARDS 16	/* Enough for one machine */
+
+static struct drm_stub_list {
+	const char             *name;
+	struct file_operations *fops;
+	struct proc_dir_entry  *dev_root;
+} *DRM(stub_list);
+
+static struct proc_dir_entry *DRM(stub_root);
+
+static struct drm_stub_info {
+	int (*info_register)(const char *name, struct file_operations *fops,
+			     drm_device_t *dev);
+	int (*info_unregister)(int minor);
+} DRM(stub_info);
+
+static int DRM(stub_open)(struct inode *inode, struct file *filp)
+{
+	int                    minor = MINOR(inode->i_rdev);
+	int                    err   = -ENODEV;
+	struct file_operations *old_fops;
+
+	if (!DRM(stub_list) || !DRM(stub_list)[minor].fops) return -ENODEV;
+	old_fops   = filp->f_op;
+	filp->f_op = fops_get(DRM(stub_list)[minor].fops);
+	if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
+		fops_put(filp->f_op);
+		filp->f_op = fops_get(old_fops);
+	}
+	fops_put(old_fops);
+
+	return err;
+}
+
+static struct file_operations DRM(stub_fops) = {
+#if LINUX_VERSION_CODE >= 0x020400
+	owner:   THIS_MODULE,
+#endif
+	open:	 DRM(stub_open)
+};
+
+static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
+			      drm_device_t *dev)
+{
+	int i;
+
+	if (!DRM(stub_list)) {
+		DRM(stub_list) = DRM(alloc)(sizeof(*DRM(stub_list))
+					    * DRM_STUB_MAXCARDS, DRM_MEM_STUB);
+		if(!DRM(stub_list)) return -1;
+		for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
+			DRM(stub_list)[i].name = NULL;
+			DRM(stub_list)[i].fops = NULL;
+		}
+	}
+	for (i = 0; i < DRM_STUB_MAXCARDS; i++) {
+		if (!DRM(stub_list)[i].fops) {
+			DRM(stub_list)[i].name = name;
+			DRM(stub_list)[i].fops = fops;
+			DRM(stub_root) = DRM(proc_init)(dev, i, DRM(stub_root),
+							&DRM(stub_list)[i]
+							.dev_root);
+			return i;
+		}
+	}
+	return -1;
+}
+
+static int DRM(stub_putminor)(int minor)
+{
+	if (minor < 0 || minor >= DRM_STUB_MAXCARDS) return -1;
+	DRM(stub_list)[minor].name = NULL;
+	DRM(stub_list)[minor].fops = NULL;
+	DRM(proc_cleanup)(minor, DRM(stub_root),
+			  DRM(stub_list)[minor].dev_root);
+	if (minor) {
+		inter_module_put("drm");
+	} else {
+		inter_module_unregister("drm");
+		DRM(free)(DRM(stub_list),
+			  sizeof(*DRM(stub_list)) * DRM_STUB_MAXCARDS,
+			  DRM_MEM_STUB);
+		unregister_chrdev(DRM_MAJOR, "drm");
+	}
+	return 0;
+}
+
+
+int DRM(stub_register)(const char *name, struct file_operations *fops,
+		       drm_device_t *dev)
+{
+	struct drm_stub_info *i = NULL;
+
+	DRM_DEBUG("\n");
+	if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
+		i = (struct drm_stub_info *)inter_module_get("drm");
+
+	if (i) {
+				/* Already registered */
+		DRM(stub_info).info_register   = i->info_register;
+		DRM(stub_info).info_unregister = i->info_unregister;
+		DRM_DEBUG("already registered\n");
+	} else if (DRM(stub_info).info_register != DRM(stub_getminor)) {
+		DRM(stub_info).info_register   = DRM(stub_getminor);
+		DRM(stub_info).info_unregister = DRM(stub_putminor);
+		DRM_DEBUG("calling inter_module_register\n");
+		inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
+	}
+	if (DRM(stub_info).info_register)
+		return DRM(stub_info).info_register(name, fops, dev);
+	return -1;
+}
+
+int DRM(stub_unregister)(int minor)
+{
+	DRM_DEBUG("%d\n", minor);
+	if (DRM(stub_info).info_unregister)
+		return DRM(stub_info).info_unregister(minor);
+	return -1;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/drm_vm.h linux/drivers/char/drm/drm_vm.h
--- linux-2.4.8-pre6/drivers/char/drm/drm_vm.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/drm_vm.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,500 @@
+/* drm_vm.h -- Memory mapping for DRM -*- linux-c -*-
+ * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    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),
+};
+
+struct vm_operations_struct   DRM(vm_shm_ops) = {
+	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),
+};
+
+struct vm_operations_struct   DRM(vm_sg_ops) = {
+	nopage:  DRM(vm_sg_nopage),
+	open:    DRM(vm_open),
+	close:   DRM(vm_close),
+};
+
+#if LINUX_VERSION_CODE < 0x020317
+unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
+			     unsigned long address,
+			     int write_access)
+#else
+				/* Return type changed in 2.3.23 */
+struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
+			    unsigned long address,
+			    int write_access)
+#endif
+{
+	return NOPAGE_SIGBUS;		/* Disallow mremap */
+}
+
+#if LINUX_VERSION_CODE < 0x020317
+unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
+				 unsigned long address,
+				 int write_access)
+#else
+				/* Return type changed in 2.3.23 */
+struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
+				unsigned long address,
+				int write_access)
+#endif
+{
+#if LINUX_VERSION_CODE >= 0x020300
+	drm_map_t	 *map	 = (drm_map_t *)vma->vm_private_data;
+#else
+	drm_map_t	 *map	 = (drm_map_t *)vma->vm_pte;
+#endif
+	unsigned long	 physical;
+	unsigned long	 offset;
+	unsigned long	 i;
+	pgd_t		 *pgd;
+	pmd_t		 *pmd;
+	pte_t		 *pte;
+
+	if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+	if (!map)    		   return NOPAGE_OOM;  /* Nothing allocated */
+
+	offset	 = address - vma->vm_start;
+	i = (unsigned long)map->handle + offset;
+	/* We have to walk page tables here because we need large SAREA's, and
+	 * they need to be virtually contiguous in kernel space.
+	 */
+	pgd = pgd_offset_k( i );
+	if( !pgd_present( *pgd ) ) return NOPAGE_OOM;
+	pmd = pmd_offset( pgd, i );
+	if( !pmd_present( *pmd ) ) return NOPAGE_OOM;
+	pte = pte_offset( pmd, i );
+	if( !pte_present( *pte ) ) return NOPAGE_OOM;
+	physical = (unsigned long)pte_page( *pte )->virtual;
+	atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */
+
+	DRM_DEBUG("0x%08lx => 0x%08lx\n", address, physical);
+#if LINUX_VERSION_CODE < 0x020317
+	return physical;
+#else
+	return virt_to_page(physical);
+#endif
+}
+
+/* Special close routine which deletes map information if we are the last
+ * person to close a mapping and its not in the global maplist.
+ */
+
+void DRM(vm_shm_close)(struct vm_area_struct *vma)
+{
+	drm_file_t	*priv	= vma->vm_file->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_vma_entry_t *pt, *prev, *next;
+	drm_map_t *map;
+	drm_map_list_t *r_list;
+	struct list_head *list;
+	int found_maps = 0;
+
+	DRM_DEBUG("0x%08lx,0x%08lx\n",
+		  vma->vm_start, vma->vm_end - vma->vm_start);
+#if LINUX_VERSION_CODE < 0x020333
+	MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
+#endif
+	atomic_dec(&dev->vma_count);
+
+#if LINUX_VERSION_CODE >= 0x020300
+	map = vma->vm_private_data;
+#else
+	map = vma->vm_pte;
+#endif
+
+	down(&dev->struct_sem);
+	for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
+		next = pt->next;
+#if LINUX_VERSION_CODE >= 0x020300
+		if (pt->vma->vm_private_data == map) found_maps++;
+#else
+		if (pt->vma->vm_pte == map) found_maps++;
+#endif
+		if (pt->vma == vma) {
+			if (prev) {
+				prev->next = pt->next;
+			} else {
+				dev->vmalist = pt->next;
+			}
+			DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS);
+		} else {
+			prev = pt;
+		}
+	}
+	/* We were the only map that was found */
+	if(found_maps == 1 &&
+	   map->flags & _DRM_REMOVABLE) {
+		/* Check to see if we are in the maplist, if we are not, then
+		 * we delete this mappings information.
+		 */
+		found_maps = 0;
+		list = &dev->maplist->head;
+		list_for_each(list, &dev->maplist->head) {
+			r_list = (drm_map_list_t *) list;
+			if (r_list->map == map) found_maps++;
+		}
+
+		if(!found_maps) {
+			switch (map->type) {
+			case _DRM_REGISTERS:
+			case _DRM_FRAME_BUFFER:
+#if __REALLY_HAVE_MTRR
+				if (map->mtrr >= 0) {
+					int retcode;
+					retcode = mtrr_del(map->mtrr,
+							   map->offset,
+							   map->size);
+					DRM_DEBUG("mtrr_del = %d\n", retcode);
+				}
+#endif
+				DRM(ioremapfree)(map->handle, map->size);
+				break;
+			case _DRM_SHM:
+				vfree(map->handle);
+				break;
+			case _DRM_AGP:
+			case _DRM_SCATTER_GATHER:
+				break;
+			}
+			DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
+		}
+	}
+	up(&dev->struct_sem);
+}
+
+#if LINUX_VERSION_CODE < 0x020317
+unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
+				 unsigned long address,
+				 int write_access)
+#else
+				/* Return type changed in 2.3.23 */
+struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
+				unsigned long address,
+				int write_access)
+#endif
+{
+	drm_file_t	 *priv	 = vma->vm_file->private_data;
+	drm_device_t	 *dev	 = priv->dev;
+	drm_device_dma_t *dma	 = dev->dma;
+	unsigned long	 physical;
+	unsigned long	 offset;
+	unsigned long	 page;
+
+	if (!dma)		   return NOPAGE_SIGBUS; /* Error */
+	if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+	if (!dma->pagelist)	   return NOPAGE_OOM ; /* Nothing allocated */
+
+	offset	 = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
+	page	 = offset >> PAGE_SHIFT;
+	physical = dma->pagelist[page] + (offset & (~PAGE_MASK));
+	atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */
+
+	DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", address, page, physical);
+#if LINUX_VERSION_CODE < 0x020317
+	return physical;
+#else
+	return virt_to_page(physical);
+#endif
+}
+
+#if LINUX_VERSION_CODE < 0x020317
+unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+				unsigned long address,
+				int write_access)
+#else
+				/* Return type changed in 2.3.23 */
+struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
+			       unsigned long address,
+			       int write_access)
+#endif
+{
+#if LINUX_VERSION_CODE >= 0x020300
+	drm_map_t        *map    = (drm_map_t *)vma->vm_private_data;
+#else
+	drm_map_t        *map    = (drm_map_t *)vma->vm_pte;
+#endif
+	drm_file_t *priv = vma->vm_file->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_sg_mem_t *entry = dev->sg;
+	unsigned long offset;
+	unsigned long map_offset;
+	unsigned long page_offset;
+	struct page *page;
+
+	if (!entry)                return NOPAGE_SIGBUS; /* Error */
+	if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+	if (!entry->pagelist)      return NOPAGE_OOM ;  /* Nothing allocated */
+
+
+	offset = address - vma->vm_start;
+	map_offset = map->offset - dev->sg->handle;
+	page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
+	page = entry->pagelist[page_offset];
+	atomic_inc(&page->count);                       /* Dec. by kernel */
+
+#if LINUX_VERSION_CODE < 0x020317
+	return (unsigned long)virt_to_phys(page->virtual);
+#else
+	return page;
+#endif
+}
+
+void DRM(vm_open)(struct vm_area_struct *vma)
+{
+	drm_file_t	*priv	= vma->vm_file->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_vma_entry_t *vma_entry;
+
+	DRM_DEBUG("0x%08lx,0x%08lx\n",
+		  vma->vm_start, vma->vm_end - vma->vm_start);
+	atomic_inc(&dev->vma_count);
+#if LINUX_VERSION_CODE < 0x020333
+				/* The map can exist after the fd is closed. */
+	MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
+#endif
+
+	vma_entry = DRM(alloc)(sizeof(*vma_entry), DRM_MEM_VMAS);
+	if (vma_entry) {
+		down(&dev->struct_sem);
+		vma_entry->vma	= vma;
+		vma_entry->next = dev->vmalist;
+		vma_entry->pid	= current->pid;
+		dev->vmalist	= vma_entry;
+		up(&dev->struct_sem);
+	}
+}
+
+void DRM(vm_close)(struct vm_area_struct *vma)
+{
+	drm_file_t	*priv	= vma->vm_file->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_vma_entry_t *pt, *prev;
+
+	DRM_DEBUG("0x%08lx,0x%08lx\n",
+		  vma->vm_start, vma->vm_end - vma->vm_start);
+#if LINUX_VERSION_CODE < 0x020333
+	MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
+#endif
+	atomic_dec(&dev->vma_count);
+
+	down(&dev->struct_sem);
+	for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+		if (pt->vma == vma) {
+			if (prev) {
+				prev->next = pt->next;
+			} else {
+				dev->vmalist = pt->next;
+			}
+			DRM(free)(pt, sizeof(*pt), DRM_MEM_VMAS);
+			break;
+		}
+	}
+	up(&dev->struct_sem);
+}
+
+int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma)
+{
+	drm_file_t	 *priv	 = filp->private_data;
+	drm_device_t	 *dev;
+	drm_device_dma_t *dma;
+	unsigned long	 length	 = vma->vm_end - vma->vm_start;
+
+	lock_kernel();
+	dev	 = priv->dev;
+	dma	 = dev->dma;
+	DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
+		  vma->vm_start, vma->vm_end, VM_OFFSET(vma));
+
+				/* Length must match exact page count */
+	if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
+		unlock_kernel();
+		return -EINVAL;
+	}
+	unlock_kernel();
+
+	vma->vm_ops   = &DRM(vm_dma_ops);
+	vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+
+#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
+				/* In Linux 2.2.3 and above, this is
+				   handled in do_mmap() in mm/mmap.c. */
+	++filp->f_count;
+#endif
+	vma->vm_file  =	 filp;	/* Needed for drm_vm_open() */
+	DRM(vm_open)(vma);
+	return 0;
+}
+
+#ifndef DRIVER_GET_MAP_OFS
+#define DRIVER_GET_MAP_OFS()	(map->offset)
+#endif
+
+#ifndef DRIVER_GET_REG_OFS
+#ifdef __alpha__
+#define DRIVER_GET_REG_OFS()	(dev->hose->dense_mem_base -	\
+				 dev->hose->mem_space->start)
+#else
+#define DRIVER_GET_REG_OFS()	0
+#endif
+#endif
+
+int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
+{
+	drm_file_t	*priv	= filp->private_data;
+	drm_device_t	*dev	= priv->dev;
+	drm_map_t	*map	= NULL;
+	drm_map_list_t  *r_list;
+	unsigned long   offset  = 0;
+	struct list_head *list;
+
+	DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
+		  vma->vm_start, vma->vm_end, VM_OFFSET(vma));
+
+	if ( !priv->authenticated ) return -EACCES;
+
+	if (!VM_OFFSET(vma)) return DRM(mmap_dma)(filp, vma);
+
+				/* A sequential search of a linked list is
+				   fine here because: 1) there will only be
+				   about 5-10 entries in the list and, 2) a
+				   DRI client only has to do this mapping
+				   once, so it doesn't have to be optimized
+				   for performance, even if the list was a
+				   bit longer. */
+	list_for_each(list, &dev->maplist->head) {
+		unsigned long off;
+
+		r_list = (drm_map_list_t *)list;
+		map = r_list->map;
+		if (!map) continue;
+		off = DRIVER_GET_MAP_OFS();
+		if (off == VM_OFFSET(vma)) break;
+	}
+
+	if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
+		return -EPERM;
+
+				/* Check for valid size. */
+	if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
+		vma->vm_flags &= VM_MAYWRITE;
+#if defined(__i386__)
+		pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
+#else
+				/* Ye gads this is ugly.  With more thought
+                                   we could move this up higher and use
+                                   `protection_map' instead.  */
+		vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
+			__pte(pgprot_val(vma->vm_page_prot)))));
+#endif
+	}
+
+	switch (map->type) {
+	case _DRM_FRAME_BUFFER:
+	case _DRM_REGISTERS:
+	case _DRM_AGP:
+		if (VM_OFFSET(vma) >= __pa(high_memory)) {
+#if defined(__i386__)
+			if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
+				pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+				pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
+			}
+#elif defined(__ia64__)
+			if (map->type != _DRM_AGP)
+				vma->vm_page_prot =
+					pgprot_writecombine(vma->vm_page_prot);
+#elif defined(__powerpc__)
+			pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+#endif
+			vma->vm_flags |= VM_IO;	/* not in core dump */
+		}
+		offset = DRIVER_GET_REG_OFS();
+		if (remap_page_range(vma->vm_start,
+				     VM_OFFSET(vma) + offset,
+				     vma->vm_end - vma->vm_start,
+				     vma->vm_page_prot))
+				return -EAGAIN;
+		DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
+			  " offset = 0x%lx\n",
+			  map->type,
+			  vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset);
+		vma->vm_ops = &DRM(vm_ops);
+		break;
+	case _DRM_SHM:
+		vma->vm_ops = &DRM(vm_shm_ops);
+#if LINUX_VERSION_CODE >= 0x020300
+		vma->vm_private_data = (void *)map;
+#else
+		vma->vm_pte = (unsigned long)map;
+#endif
+				/* Don't let this area swap.  Change when
+				   DRM_KERNEL advisory is supported. */
+		vma->vm_flags |= VM_LOCKED;
+		break;
+	case _DRM_SCATTER_GATHER:
+		vma->vm_ops = &DRM(vm_sg_ops);
+#if LINUX_VERSION_CODE >= 0x020300
+		vma->vm_private_data = (void *)map;
+#else
+		vma->vm_pte = (unsigned long)map;
+#endif
+                vma->vm_flags |= VM_LOCKED;
+                break;
+	default:
+		return -EINVAL;	/* This should never happen. */
+	}
+	vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+
+#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
+				/* In Linux 2.2.3 and above, this is
+				   handled in do_mmap() in mm/mmap.c. */
+	++filp->f_count;
+#endif
+	vma->vm_file  =	 filp;	/* Needed for drm_vm_open() */
+	DRM(vm_open)(vma);
+	return 0;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/ffb.h linux/drivers/char/drm/ffb.h
--- linux-2.4.8-pre6/drivers/char/drm/ffb.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/ffb.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,15 @@
+/* ffb.h -- ffb DRM template customization -*- linux-c -*-
+ */
+
+#ifndef __FFB_H__
+#define __FFB_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) ffb_##x
+
+/* General customization:
+ */
+#define __HAVE_KERNEL_CTX_SWITCH	1
+#define __HAVE_RELEASE			1
+#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/ffb_context.c linux/drivers/char/drm/ffb_context.c
--- linux-2.4.8-pre6/drivers/char/drm/ffb_context.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/char/drm/ffb_context.c	Mon Dec  3 22:59:45 2001
@@ -10,13 +10,14 @@
 #include <linux/sched.h>
 #include <asm/upa.h>
 
+#include "ffb.h"
 #include "drmP.h"
 
 #include "ffb_drv.h"
 
-static int ffb_alloc_queue(drm_device_t *dev, int is_2d_only)
+static int DRM(alloc_queue)(drm_device_t *dev, int is_2d_only)
 {
-	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1);
+	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
 	int i;
 
 	for (i = 0; i < FFB_MAX_CTXS; i++) {
@@ -353,9 +354,9 @@
 	} while (--limit);
 }
 
-int ffb_context_switch(drm_device_t *dev, int old, int new)
+int DRM(context_switch)(drm_device_t *dev, int old, int new)
 {
-	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1);
+	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
 
         atomic_inc(&dev->total_ctx);
 
@@ -381,8 +382,8 @@
         return 0;
 }
 
-int ffb_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
+int DRM(resctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+		unsigned long arg)
 {
 	drm_ctx_res_t	res;
 	drm_ctx_t	ctx;
@@ -408,8 +409,8 @@
 }
 
 
-int ffb_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
+int DRM(addctx)(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;
@@ -418,7 +419,7 @@
 
 	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
 		return -EFAULT;
-	idx = ffb_alloc_queue(dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
+	idx = DRM(alloc_queue)(dev, (ctx.flags & _DRM_CONTEXT_2DONLY));
 	if (idx < 0)
 		return -ENFILE;
 
@@ -429,12 +430,12 @@
 	return 0;
 }
 
-int ffb_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
+int DRM(modctx)(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;
-	ffb_dev_priv_t	*fpriv	= (ffb_dev_priv_t *) (dev + 1);
+	ffb_dev_priv_t	*fpriv	= (ffb_dev_priv_t *) dev->dev_private;
 	struct ffb_hw_context *hwctx;
 	drm_ctx_t ctx;
 	int idx;
@@ -458,12 +459,12 @@
 	return 0;
 }
 
-int ffb_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
+int DRM(getctx)(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;
-	ffb_dev_priv_t	*fpriv	= (ffb_dev_priv_t *) (dev + 1);
+	ffb_dev_priv_t	*fpriv	= (ffb_dev_priv_t *) dev->dev_private;
 	struct ffb_hw_context *hwctx;
 	drm_ctx_t ctx;
 	int idx;
@@ -490,8 +491,8 @@
 	return 0;
 }
 
-int ffb_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
+int DRM(switchctx)(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;
@@ -500,11 +501,11 @@
 	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
 		return -EFAULT;
 	DRM_DEBUG("%d\n", ctx.handle);
-	return ffb_context_switch(dev, dev->last_context, ctx.handle);
+	return DRM(context_switch)(dev, dev->last_context, ctx.handle);
 }
 
-int ffb_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
+int DRM(newctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+		unsigned long arg)
 {
 	drm_ctx_t	ctx;
 
@@ -515,13 +516,13 @@
 	return 0;
 }
 
-int ffb_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
+int DRM(rmctx)(struct inode *inode, struct file *filp, unsigned int cmd,
 	       unsigned long arg)
 {
 	drm_ctx_t	ctx;
 	drm_file_t	*priv	= filp->private_data;
 	drm_device_t	*dev	= priv->dev;
-	ffb_dev_priv_t	*fpriv	= (ffb_dev_priv_t *) (dev + 1);
+	ffb_dev_priv_t	*fpriv	= (ffb_dev_priv_t *) dev->dev_private;
 	int idx;
 
 	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
diff -urN linux-2.4.8-pre6/drivers/char/drm/ffb_drv.c linux/drivers/char/drm/ffb_drv.c
--- linux-2.4.8-pre6/drivers/char/drm/ffb_drv.c	Mon Jun 11 19:15:27 2001
+++ linux/drivers/char/drm/ffb_drv.c	Mon Dec  3 22:59:45 2001
@@ -4,195 +4,84 @@
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
  */
 
+#include <linux/config.h>
+#include "ffb.h"
 #include "drmP.h"
 
+#include "ffb_drv.h"
+
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <asm/shmparam.h>
 #include <asm/oplib.h>
 #include <asm/upa.h>
 
-#include "ffb_drv.h"
-
-#define FFB_NAME	"ffb"
-#define FFB_DESC	"Creator/Creator3D"
-#define FFB_DATE	"20000517"
-#define FFB_MAJOR	0
-#define FFB_MINOR	0
-#define FFB_PATCHLEVEL	1
-
-/* Forward declarations. */
-int  ffb_init(void);
-void ffb_cleanup(void);
-static int  ffb_version(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-static int  ffb_open(struct inode *inode, struct file *filp);
-static int  ffb_release(struct inode *inode, struct file *filp);
-static int  ffb_ioctl(struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg);
-static int  ffb_lock(struct inode *inode, struct file *filp,
-		     unsigned int cmd, unsigned long arg);
-static int  ffb_unlock(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-static int ffb_mmap(struct file *filp, struct vm_area_struct *vma);
-static unsigned long ffb_get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
-
-/* From ffb_context.c */
-extern int ffb_resctx(struct inode *, struct file *, unsigned int, unsigned long);
-extern int ffb_addctx(struct inode *, struct file *, unsigned int, unsigned long);
-extern int ffb_modctx(struct inode *, struct file *, unsigned int, unsigned long);
-extern int ffb_getctx(struct inode *, struct file *, unsigned int, unsigned long);
-extern int ffb_switchctx(struct inode *, struct file *, unsigned int, unsigned long);
-extern int ffb_newctx(struct inode *, struct file *, unsigned int, unsigned long);
-extern int ffb_rmctx(struct inode *, struct file *, unsigned int, unsigned long);
-extern int ffb_context_switch(drm_device_t *, int, int);
-
-static struct file_operations ffb_fops = {
-	owner:			THIS_MODULE,
-	open:			ffb_open,
-	flush:			drm_flush,
-	release:		ffb_release,
-	ioctl:			ffb_ioctl,
-	mmap:			ffb_mmap,
-	read:			drm_read,
-	fasync:			drm_fasync,
-	poll:			drm_poll,
-	get_unmapped_area:	ffb_get_unmapped_area,
-};
-
-/* This is just a template, we make a new copy for each FFB
- * we discover at init time so that each one gets a unique
- * misc device minor number.
- */
-static struct miscdevice ffb_misc = {
-	minor:	MISC_DYNAMIC_MINOR,
-	name:	FFB_NAME,
-	fops:	&ffb_fops,
-};
-
-static drm_ioctl_desc_t ffb_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]    = { ffb_version,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]  = { drm_getmagic,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]  = { drm_irq_busid,	  0, 1 }, /* XXX */
-
-	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]	     = { drm_block,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]    = { drm_unblock,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]    = { drm_addmap,	  1, 1 },
-	
-	/* The implementation is currently a nop just like on tdfx.
-	 * Later we can do something more clever. -DaveM
-	 */
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]    = { ffb_addctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]     = { ffb_rmctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]    = { ffb_modctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]    = { ffb_getctx,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { ffb_switchctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]    = { ffb_newctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]    = { ffb_resctx,	  1, 0 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]   = { drm_adddraw,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]    = { drm_rmdraw,	  1, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	     = { ffb_lock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]     = { ffb_unlock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]     = { drm_finish,	  1, 0 },
-};
-#define FFB_IOCTL_COUNT DRM_ARRAY_SIZE(ffb_ioctls)
-
-#ifdef MODULE
-static char *ffb = NULL;
-#endif
-
-MODULE_AUTHOR("David S. Miller (davem@redhat.com)");
-MODULE_DESCRIPTION("Sun Creator/Creator3D DRI");
+#define DRIVER_AUTHOR		"David S. Miller"
 
-static int ffb_takedown(drm_device_t *dev)
-{
-	int		  i;
-	drm_magic_entry_t *pt, *next;
-	drm_map_t	  *map;
-	drm_vma_entry_t	  *vma, *vma_next;
+#define DRIVER_NAME		"ffb"
+#define DRIVER_DESC		"Creator/Creator3D"
+#define DRIVER_DATE		"20000517"
+
+#define DRIVER_MAJOR		0
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	1
+
+#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),			\
+	get_unmapped_area:	ffb_get_unmapped_area,		\
+}
+
+#define DRIVER_COUNT_CARDS()	ffb_count_card_instances()
+/* Allocate private structure and fill it */
+#define DRIVER_PRESETUP()	do {		\
+	int _ret;				\
+	_ret = ffb_presetup(dev);		\
+	if(_ret != 0) return _ret;		\
+} while(0)
+
+/* Free private structure */
+#define DRIVER_PRETAKEDOWN()	do {				\
+	if(dev->dev_private) kfree(dev->dev_private);		\
+} while(0)
+
+#define DRIVER_POSTCLEANUP()	do {				\
+	if(ffb_position != NULL) kfree(ffb_position);		\
+} while(0)
 
-	DRM_DEBUG("\n");
-
-	down(&dev->struct_sem);
-	del_timer(&dev->timer);
-	
-	if (dev->devname) {
-		drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
-		dev->devname = NULL;
-	}
-	
-	if (dev->unique) {
-		drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
-		dev->unique = NULL;
-		dev->unique_len = 0;
-	}
-
-	/* Clear pid list */
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		for (pt = dev->magiclist[i].head; pt; pt = next) {
-			next = pt->next;
-			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-		}
-		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
-	}
-	
-	/* Clear vma list (only built for debugging) */
-	if (dev->vmalist) {
-		for (vma = dev->vmalist; vma; vma = vma_next) {
-			vma_next = vma->next;
-			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
-		}
-		dev->vmalist = NULL;
-	}
-	
-	/* Clear map area information */
-	if (dev->maplist) {
-		for (i = 0; i < dev->map_count; i++) {
-			map = dev->maplist[i];
-			switch (map->type) {
-			case _DRM_REGISTERS:
-			case _DRM_FRAME_BUFFER:
-				drm_ioremapfree(map->handle, map->size);
-				break;
-
-			case _DRM_SHM:
-				drm_free_pages((unsigned long)map->handle,
-					       drm_order(map->size)
-					       - PAGE_SHIFT,
-					       DRM_MEM_SAREA);
-				break;
-
-			default:
-				break;
-			};
-
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		}
-
-		drm_free(dev->maplist,
-			 dev->map_count * sizeof(*dev->maplist),
-			 DRM_MEM_MAPS);
-		dev->maplist   = NULL;
-		dev->map_count = 0;
-	}
-	
-	if (dev->lock.hw_lock) {
-		dev->lock.hw_lock    = NULL; /* SHM removed */
-		dev->lock.pid	     = 0;
-		wake_up_interruptible(&dev->lock.lock_queue);
-	}
-	up(&dev->struct_sem);
-	
-	return 0;
-}
+/* We have to free up the rogue hw context state holding error or 
+ * else we will leak it.
+ */
+#define DRIVER_RELEASE()	do {					\
+	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;	\
+	int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);	\
+	int idx;							\
+									\
+	idx = context - 1;						\
+	if (fpriv && fpriv->hw_state[idx] != NULL) {			\
+		kfree(fpriv->hw_state[idx]);				\
+		fpriv->hw_state[idx] = NULL;				\
+	}								\
+} while(0)
+
+/* For mmap customization */
+#define DRIVER_GET_MAP_OFS	(map->offset & 0xffffffff)
+#define DRIVER_GET_REG_OFS()	ffb_get_reg_offset(dev)
+
+typedef struct _ffb_position_t {
+	int node;
+	int root;
+} ffb_position_t;
 
-drm_device_t **ffb_dev_table;
-static int ffb_dev_table_size;
+static ffb_position_t *ffb_position;
 
 static void get_ffb_type(ffb_dev_priv_t *ffb_priv, int instance)
 {
@@ -247,7 +136,8 @@
 	};
 }
 
-static void __init ffb_apply_upa_parent_ranges(int parent, struct linux_prom64_registers *regs)
+static void ffb_apply_upa_parent_ranges(int parent, 
+					struct linux_prom64_registers *regs)
 {
 	struct linux_prom64_ranges ranges[PROMREG_MAX];
 	char name[128];
@@ -277,26 +167,16 @@
 	return;
 }
 
-static int __init ffb_init_one(int prom_node, int parent_node, int instance)
+static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
+			int instance)
 {
 	struct linux_prom64_registers regs[2*PROMREG_MAX];
-	drm_device_t *dev;
-	ffb_dev_priv_t *ffb_priv;
-	int ret, i;
-
-	dev = kmalloc(sizeof(drm_device_t) + sizeof(ffb_dev_priv_t), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-
-	memset(dev, 0, sizeof(*dev));
-	spin_lock_init(&dev->count_lock);
-	sema_init(&dev->struct_sem, 1);
+	ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
+	int i;
 
-	ffb_priv = (ffb_dev_priv_t *) (dev + 1);
 	ffb_priv->prom_node = prom_node;
 	if (prom_getproperty(ffb_priv->prom_node, "reg",
 			     (void *)regs, sizeof(regs)) <= 0) {
-		kfree(dev);
 		return -EINVAL;
 	}
 	ffb_apply_upa_parent_ranges(parent_node, &regs[0]);
@@ -306,37 +186,39 @@
 	get_ffb_type(ffb_priv, instance);
 	for (i = 0; i < FFB_MAX_CTXS; i++)
 		ffb_priv->hw_state[i] = NULL;
+	
+	return 0;
+}
 
-	ffb_dev_table[instance] = dev;
+static int ffb_presetup(drm_device_t *dev)
+{
+	ffb_dev_priv_t	*ffb_priv;
+	drm_device_t *temp_dev;
+	int ret = 0;
+	int i;
 
-#ifdef MODULE
-	drm_parse_options(ffb);
-#endif
+	/* Check for the case where no device was found. */
+	if(ffb_position == NULL) return -ENODEV;
 
-	memcpy(&ffb_priv->miscdev, &ffb_misc, sizeof(ffb_misc));
-	ret = misc_register(&ffb_priv->miscdev);
-	if (ret) {
-		ffb_dev_table[instance] = NULL;
-		kfree(dev);
-		return ret;
+	/* Find our instance number by finding our device in dev structure */
+	for(i = 0; i < DRM(numdevs); i++) {
+		temp_dev = &(DRM(device)[i]);
+		if(temp_dev == dev) break;
+	}
+	if(i == DRM(numdevs)) {
+		return -ENODEV;
 	}
 
-	dev->device = MKDEV(MISC_MAJOR, ffb_priv->miscdev.minor);
-	dev->name = FFB_NAME;
-
-	drm_mem_init();
-	drm_proc_init(dev);
-
-	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d at %016lx\n",
-		 FFB_NAME,
-		 FFB_MAJOR,
-		 FFB_MINOR,
-		 FFB_PATCHLEVEL,
-		 FFB_DATE,
-		 ffb_priv->miscdev.minor,
-		 ffb_priv->card_phys_base);
-	
-	return 0;
+	ffb_priv = kmalloc(sizeof(ffb_dev_priv_t), GFP_KERNEL);
+	if(!ffb_priv) return -ENOMEM;
+	memset(ffb_priv, 0, sizeof(*ffb_priv));
+	dev->dev_private = ffb_priv;
+
+	ret = ffb_init_one(dev,
+			   ffb_position[i].node,
+			   ffb_position[i].root,
+			   i);
+	return ret;
 }
 
 static int __init ffb_count_siblings(int root)
@@ -351,28 +233,6 @@
 	return count;
 }
 
-static int __init ffb_init_dev_table(void)
-{
-	int root, total;
-
-	total = ffb_count_siblings(prom_root_node);
-	root = prom_getchild(prom_root_node);
-	for (root = prom_searchsiblings(root, "upa"); root;
-	     root = prom_searchsiblings(prom_getsibling(root), "upa"))
-		total += ffb_count_siblings(root);
-
-	if (!total)
-		return -ENODEV;
-
-	ffb_dev_table = kmalloc(sizeof(drm_device_t *) * total, GFP_KERNEL);
-	if (!ffb_dev_table)
-		return -ENOMEM;
-
-	ffb_dev_table_size = total;
-
-	return 0;
-}
-
 static int __init ffb_scan_siblings(int root, int instance)
 {
 	int node, child;
@@ -380,534 +240,70 @@
 	child = prom_getchild(root);
 	for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
 	     node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) {
-		ffb_init_one(node, root, instance);
+		ffb_position[instance].node = node;
+		ffb_position[instance].root = root;
 		instance++;
 	}
 
 	return instance;
 }
 
-int __init ffb_init(void)
+static int __init ffb_count_card_instances(void)
 {
-	int root, instance, ret;
-
-	ret = ffb_init_dev_table();
-	if (ret)
-		return ret;
-
-	instance = ffb_scan_siblings(prom_root_node, 0);
+	int root, total, instance;
 
+	total = ffb_count_siblings(prom_root_node);
 	root = prom_getchild(prom_root_node);
 	for (root = prom_searchsiblings(root, "upa"); root;
 	     root = prom_searchsiblings(prom_getsibling(root), "upa"))
-		instance = ffb_scan_siblings(root, instance);
-
-	return 0;
-}
-
-void __exit ffb_cleanup(void)
-{
-	int instance;
-
-	DRM_DEBUG("\n");
-	
-	drm_proc_cleanup();
-	for (instance = 0; instance < ffb_dev_table_size; instance++) {
-		drm_device_t *dev = ffb_dev_table[instance];
-		ffb_dev_priv_t *ffb_priv;
-
-		if (!dev)
-			continue;
-
-		ffb_priv = (ffb_dev_priv_t *) (dev + 1);
-		if (misc_deregister(&ffb_priv->miscdev)) {
-			DRM_ERROR("Cannot unload module\n");
-		} else {
-			DRM_INFO("Module unloaded\n");
-		}
-		ffb_takedown(dev);
-		kfree(dev);
-		ffb_dev_table[instance] = NULL;
-	}
-	kfree(ffb_dev_table);
-	ffb_dev_table = NULL;
-	ffb_dev_table_size = 0;
-}
-
-static int ffb_version(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	drm_version_t version;
-	int len, ret;
-
-	ret = copy_from_user(&version, (drm_version_t *)arg, sizeof(version));
-	if (ret)
-		return -EFAULT;
-
-	version.version_major		= FFB_MAJOR;
-	version.version_minor		= FFB_MINOR;
-	version.version_patchlevel	= FFB_PATCHLEVEL;
-
-	len = strlen(FFB_NAME);
-	if (len > version.name_len)
-		len = version.name_len;
-	version.name_len = len;
-	if (len && version.name) {
-		ret = copy_to_user(version.name, FFB_NAME, len);
-		if (ret)
-			return -EFAULT;
-	}
-
-	len = strlen(FFB_DATE);
-	if (len > version.date_len)
-		len = version.date_len;
-	version.date_len = len;
-	if (len && version.date) {
-		ret = copy_to_user(version.date, FFB_DATE, len);
-		if (ret)
-			return -EFAULT;
-	}
-
-	len = strlen(FFB_DESC);
-	if (len > version.desc_len)
-		len = version.desc_len;
-	version.desc_len = len;
-	if (len && version.desc) {
-		ret = copy_to_user(version.desc, FFB_DESC, len);
-		if (ret)
-			return -EFAULT;
-	}
-
-	ret = copy_to_user((drm_version_t *) arg, &version, sizeof(version));
-	if (ret)
-		ret = -EFAULT;
-
-	return ret;
-}
-
-static int ffb_setup(drm_device_t *dev)
-{
-	int i;
-
-	atomic_set(&dev->ioctl_count, 0);
-	atomic_set(&dev->vma_count, 0);
-	dev->buf_use = 0;
-	atomic_set(&dev->buf_alloc, 0);
-
-	atomic_set(&dev->total_open, 0);
-	atomic_set(&dev->total_close, 0);
-	atomic_set(&dev->total_ioctl, 0);
-	atomic_set(&dev->total_irq, 0);
-	atomic_set(&dev->total_ctx, 0);
-	atomic_set(&dev->total_locks, 0);
-	atomic_set(&dev->total_unlocks, 0);
-	atomic_set(&dev->total_contends, 0);
-	atomic_set(&dev->total_sleeps, 0);
-
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		dev->magiclist[i].head = NULL;
-		dev->magiclist[i].tail = NULL;
-	}
-
-	dev->maplist	    = NULL;
-	dev->map_count	    = 0;
-	dev->vmalist	    = NULL;
-	dev->lock.hw_lock   = NULL;
-	init_waitqueue_head(&dev->lock.lock_queue);
-	dev->queue_count    = 0;
-	dev->queue_reserved = 0;
-	dev->queue_slots    = 0;
-	dev->queuelist	    = NULL;
-	dev->irq	    = 0;
-	dev->context_flag   = 0;
-	dev->interrupt_flag = 0;
-	dev->dma            = 0;
-	dev->dma_flag	    = 0;
-	dev->last_context   = 0;
-	dev->last_switch    = 0;
-	dev->last_checked   = 0;
-	init_timer(&dev->timer);
-	init_waitqueue_head(&dev->context_wait);
-
-	dev->ctx_start	    = 0;
-	dev->lck_start	    = 0;
-	
-	dev->buf_rp	  = dev->buf;
-	dev->buf_wp	  = dev->buf;
-	dev->buf_end	  = dev->buf + DRM_BSZ;
-	dev->buf_async	  = NULL;
-	init_waitqueue_head(&dev->buf_readers);
-	init_waitqueue_head(&dev->buf_writers);
-
-	return 0;
-}
-
-static int ffb_open(struct inode *inode, struct file *filp)
-{
-	drm_device_t *dev;
-	int minor, i;
-	int ret = 0;
-
-	minor = MINOR(inode->i_rdev);
-	for (i = 0; i < ffb_dev_table_size; i++) {
-		ffb_dev_priv_t *ffb_priv;
-
-		ffb_priv = (ffb_dev_priv_t *) (ffb_dev_table[i] + 1);
-
-		if (ffb_priv->miscdev.minor == minor)
-			break;
-	}
-
-	if (i >= ffb_dev_table_size)
-		return -EINVAL;
-
-	dev = ffb_dev_table[i];
-	if (!dev)
-		return -EINVAL;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	ret = drm_open_helper(inode, filp, dev);
-	if (!ret) {
-		atomic_inc(&dev->total_open);
-		spin_lock(&dev->count_lock);
-		if (!dev->open_count++) {
-			spin_unlock(&dev->count_lock);
-			return ffb_setup(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-
-	return ret;
-}
-
-static int ffb_release(struct inode *inode, struct file *filp)
-{
-	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev;
-	int ret = 0;
-
-	lock_kernel();
-	dev = priv->dev;
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (dev->lock.hw_lock != NULL
-	    && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
-	    && dev->lock.pid == current->pid) {
-		ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) (dev + 1);
-		int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);
-		int idx;
-
-		/* We have to free up the rogue hw context state
-		 * holding error or else we will leak it.
-		 */
-		idx = context - 1;
-		if (fpriv->hw_state[idx] != NULL) {
-			kfree(fpriv->hw_state[idx]);
-			fpriv->hw_state[idx] = NULL;
-		}
-	}
-
-	ret = drm_release(inode, filp);
-
-	if (!ret) {
-		atomic_inc(&dev->total_close);
-		spin_lock(&dev->count_lock);
-		if (!--dev->open_count) {
-			if (atomic_read(&dev->ioctl_count) || dev->blocked) {
-				DRM_ERROR("Device busy: %d %d\n",
-					  atomic_read(&dev->ioctl_count),
-					  dev->blocked);
-				spin_unlock(&dev->count_lock);
-				unlock_kernel();
-				return -EBUSY;
-			}
-			spin_unlock(&dev->count_lock);
-			ret = ffb_takedown(dev);
-			unlock_kernel();
-			return ret;
-		}
-		spin_unlock(&dev->count_lock);
-	}
-
-	unlock_kernel();
-	return ret;
-}
-
-static int ffb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	int		 nr	 = DRM_IOCTL_NR(cmd);
-	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	drm_ioctl_desc_t *ioctl;
-	drm_ioctl_t	 *func;
-	int		 ret;
-
-	atomic_inc(&dev->ioctl_count);
-	atomic_inc(&dev->total_ioctl);
-	++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);
-
-	if (nr >= FFB_IOCTL_COUNT) {
-		ret = -EINVAL;
-	} else {
-		ioctl	  = &ffb_ioctls[nr];
-		func	  = ioctl->func;
-
-		if (!func) {
-			DRM_DEBUG("no function\n");
-			ret = -EINVAL;
-		} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
-			    || (ioctl->auth_needed && !priv->authenticated)) {
-			ret = -EACCES;
-		} else {
-			ret = (func)(inode, filp, cmd, arg);
-		}
-	}
-	
-	atomic_dec(&dev->ioctl_count);
-
-	return ret;
-}
-
-static int ffb_lock(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;
-        DECLARE_WAITQUEUE(entry, current);
-        int               ret	= 0;
-        drm_lock_t        lock;
-
-	ret = copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock));
-	if (ret)
-		return -EFAULT;
-
-        if (lock.context == DRM_KERNEL_CONTEXT) {
-                DRM_ERROR("Process %d using kernel context %d\n",
-                          current->pid, lock.context);
-                return -EINVAL;
-        }
-
-        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-                  lock.context, current->pid, dev->lock.hw_lock->lock,
-                  lock.flags);
-
-	add_wait_queue(&dev->lock.lock_queue, &entry);
-	for (;;) {
-		if (!dev->lock.hw_lock) {
-			/* Device has been unregistered */
-			ret = -EINTR;
-			break;
-		}
-		if (drm_lock_take(&dev->lock.hw_lock->lock,
-				  lock.context)) {
-			dev->lock.pid       = current->pid;
-			dev->lock.lock_time = jiffies;
-			atomic_inc(&dev->total_locks);
-			break;  /* Got lock */
-		}
-                        
-		/* Contention */
-		atomic_inc(&dev->total_sleeps);
-		current->state = TASK_INTERRUPTIBLE;
-		current->policy |= SCHED_YIELD;
-		schedule();
-		if (signal_pending(current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-	}
-	current->state = TASK_RUNNING;
-	remove_wait_queue(&dev->lock.lock_queue, &entry);
-
-        if (!ret) {
-		sigemptyset(&dev->sigmask);
-		sigaddset(&dev->sigmask, SIGSTOP);
-		sigaddset(&dev->sigmask, SIGTSTP);
-		sigaddset(&dev->sigmask, SIGTTIN);
-		sigaddset(&dev->sigmask, SIGTTOU);
-		dev->sigdata.context = lock.context;
-		dev->sigdata.lock = dev->lock.hw_lock;
-		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
-
-		if (dev->last_context != lock.context)
-			ffb_context_switch(dev, dev->last_context, lock.context);
-	}
-
-        DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
-
-        return ret;
-}
-
-int ffb_unlock(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_lock_t	  lock;
-	unsigned int old, new, prev, ctx;
-	int ret;
-
-	ret = copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock));
-	if (ret)
-		return -EFAULT;
-	
-	if ((ctx = lock.context) == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("%d frees lock (%d holds)\n",
-		  lock.context,
-		  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-	atomic_inc(&dev->total_unlocks);
-	if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
-		atomic_inc(&dev->total_contends);
-
-	/* 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;
-
-		do {
-			old  = *plock;
-			new  = ctx;
-			prev = cmpxchg(plock, old, new);
-		} while (prev != old);
-	}
-
-	wake_up_interruptible(&dev->lock.lock_queue);
-	
-	unblock_all_signals();
-	return 0;
-}
-
-extern struct vm_operations_struct drm_vm_ops;
-extern struct vm_operations_struct drm_vm_shm_ops;
-extern struct vm_operations_struct drm_vm_shm_lock_ops;
-
-static int ffb_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	drm_file_t	*priv	= filp->private_data;
-	drm_device_t	*dev	= priv->dev;
-	drm_map_t	*map	= NULL;
-	ffb_dev_priv_t	*ffb_priv;
-	int		i, minor;
-	
-	DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
-		  vma->vm_start, vma->vm_end, VM_OFFSET(vma));
-
-	minor = MINOR(filp->f_dentry->d_inode->i_rdev);
-	ffb_priv = NULL;
-	for (i = 0; i < ffb_dev_table_size; i++) {
-		ffb_priv = (ffb_dev_priv_t *) (ffb_dev_table[i] + 1);
-		if (ffb_priv->miscdev.minor == minor)
-			break;
-	}
-	if (i >= ffb_dev_table_size)
-		return -EINVAL;
-
-	/* We don't support/need dma mappings, so... */
-	if (!VM_OFFSET(vma))
-		return -EINVAL;
-
-	for (i = 0; i < dev->map_count; i++) {
-		unsigned long off;
-
-		map = dev->maplist[i];
-
-		/* Ok, a little hack to make 32-bit apps work. */
-		off = (map->offset & 0xffffffff);
-		if (off == VM_OFFSET(vma))
-			break;
-	}
-
-	if (i >= dev->map_count)
-		return -EINVAL;
-
-	if (!map ||
-	    ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
-		return -EPERM;
+		total += ffb_count_siblings(root);
 
-	if (map->size != (vma->vm_end - vma->vm_start))
-		return -EINVAL;
+	ffb_position = kmalloc(sizeof(ffb_position_t) * total, GFP_KERNEL);
 
-	/* Set read-only attribute before mappings are created
-	 * so it works for fb/reg maps too.
+	/* Actual failure will be caught during ffb_presetup b/c we can't catch
+	 * it easily here.
 	 */
-	if (map->flags & _DRM_READ_ONLY)
-		vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
-			__pte(pgprot_val(vma->vm_page_prot)))));
-
-	switch (map->type) {
-	case _DRM_FRAME_BUFFER:
-		/* FALLTHROUGH */
-
-	case _DRM_REGISTERS:
-		/* In order to handle 32-bit drm apps/xserver we
-		 * play a trick.  The mappings only really specify
-		 * the 32-bit offset from the cards 64-bit base
-		 * address, and we just add in the base here.
-		 */
-		vma->vm_flags |= VM_IO;
-		if (io_remap_page_range(vma->vm_start,
-					ffb_priv->card_phys_base + VM_OFFSET(vma),
-					vma->vm_end - vma->vm_start,
-					vma->vm_page_prot, 0))
-			return -EAGAIN;
+	if(!ffb_position) return -ENOMEM;
 
-		vma->vm_ops = &drm_vm_ops;
-		break;
-	case _DRM_SHM:
-		if (map->flags & _DRM_CONTAINS_LOCK)
-			vma->vm_ops = &drm_vm_shm_lock_ops;
-		else {
-			vma->vm_ops = &drm_vm_shm_ops;
-			vma->vm_private_data = (void *) map;
-		}
-
-		/* Don't let this area swap.  Change when
-		 * DRM_KERNEL advisory is supported.
-		 */
-		vma->vm_flags |= VM_LOCKED;
-		break;
-	default:
-		return -EINVAL;	/* This should never happen. */
-	};
+	instance = ffb_scan_siblings(prom_root_node, 0);
 
-	vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
+	root = prom_getchild(prom_root_node);
+	for (root = prom_searchsiblings(root, "upa"); root;
+	     root = prom_searchsiblings(prom_getsibling(root), "upa"))
+		instance = ffb_scan_siblings(root, instance);
 
-	vma->vm_file = filp; /* Needed for drm_vm_open() */
-	drm_vm_open(vma);
-	return 0;
+	return total;
 }
 
 static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
 {
 	drm_file_t	*priv	= filp->private_data;
 	drm_device_t	*dev;
+	drm_map_list_t  *r_list;
+	struct list_head *list;
 	drm_map_t	*map;
-	int		i;
 
 	if (!priv || (dev = priv->dev) == NULL)
 		return NULL;
 
-	for (i = 0; i < dev->map_count; i++) {
+	list_for_each(list, &dev->maplist->head) {
 		unsigned long uoff;
 
-		map = dev->maplist[i];
-
-		/* Ok, a little hack to make 32-bit apps work. */
+		r_list = (drm_map_list_t *)list;
+		map = r_list->map;
+		if (!map) continue;
 		uoff = (map->offset & 0xffffffff);
-		if (uoff == off)
-			return map;
+		if (uoff == off) return map;
 	}
+
 	return NULL;
 }
 
-static unsigned long ffb_get_unmapped_area(struct file *filp, unsigned long hint, unsigned long len, unsigned long pgoff, unsigned long flags)
+static unsigned long ffb_get_unmapped_area(struct file *filp,
+					   unsigned long hint,
+					   unsigned long len,
+					   unsigned long pgoff,
+					   unsigned long flags)
 {
 	drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT);
 	unsigned long addr = -ENOMEM;
@@ -947,5 +343,46 @@
 	return addr;
 }
 
-module_init(ffb_init);
-module_exit(ffb_cleanup);
+static unsigned long ffb_get_reg_offset(drm_device_t *dev)
+{
+	ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
+
+	if(ffb_priv) {
+		return ffb_priv->card_phys_base;
+	}
+	return 0;
+}
+
+#include "drm_auth.h"
+#include "drm_bufs.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 ffb_options( char *str )
+{
+	DRM(parse_options)( str );
+	return 1;
+}
+
+__setup( DRIVER_NAME "=", ffb_options );
+#endif
+
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff -urN linux-2.4.8-pre6/drivers/char/drm/fops.c linux/drivers/char/drm/fops.c
--- linux-2.4.8-pre6/drivers/char/drm/fops.c	Tue May 22 10:23:16 2001
+++ linux/drivers/char/drm/fops.c	Wed Dec 31 16:00:00 1969
@@ -1,253 +0,0 @@
-/* fops.c -- File operations for DRM -*- linux-c -*-
- * Created: Mon Jan  4 08:58:31 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>
- *    Daryll Strauss <daryll@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include <linux/poll.h>
-
-/* drm_open is called whenever a process opens /dev/drm. */
-
-int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
-{
-	kdev_t	     minor = MINOR(inode->i_rdev);
-	drm_file_t   *priv;
-
-	if (filp->f_flags & O_EXCL)   return -EBUSY; /* No exclusive opens */
-	if (!drm_cpu_valid())         return -EINVAL;
-
-	DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
-
-	priv		    = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
-	if(priv == NULL)
-		return -ENOMEM;
-	memset(priv, 0, sizeof(*priv));
-
-	filp->private_data  = priv;
-	priv->uid	    = current->euid;
-	priv->pid	    = current->pid;
-	priv->minor	    = minor;
-	priv->dev	    = dev;
-	priv->ioctl_count   = 0;
-	priv->authenticated = capable(CAP_SYS_ADMIN);
-
-	down(&dev->struct_sem);
-	if (!dev->file_last) {
-		priv->next	= NULL;
-		priv->prev	= NULL;
-		dev->file_first = priv;
-		dev->file_last	= priv;
-	} else {
-		priv->next	     = NULL;
-		priv->prev	     = dev->file_last;
-		dev->file_last->next = priv;
-		dev->file_last	     = priv;
-	}
-	up(&dev->struct_sem);
-	
-	return 0;
-}
-
-int drm_flush(struct file *filp)
-{
-	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);
-	return 0;
-}
-
-/* drm_release is called whenever a process closes /dev/drm*.  Linux calls
-   this only if any mappings have been closed. */
-
-int drm_release(struct inode *inode, struct file *filp)
-{
-	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_ERROR("Process %d dead, freeing lock for context %d\n",
-			  current->pid,
-			  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-		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_reclaim_buffers(dev, priv->pid);
-
-	drm_fasync(-1, filp, 0);
-
-	down(&dev->struct_sem);
-	if (priv->prev) priv->prev->next = priv->next;
-	else		dev->file_first	 = priv->next;
-	if (priv->next) priv->next->prev = priv->prev;
-	else		dev->file_last	 = priv->prev;
-	up(&dev->struct_sem);
-	
-	drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
-	
-	return 0;
-}
-
-int drm_fasync(int fd, struct file *filp, int on)
-{
-	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev    = priv->dev;
-	int	      retcode;
-	
-	DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device);
-	retcode = fasync_helper(fd, filp, on, &dev->buf_async);
-	if (retcode < 0) return retcode;
-	return 0;
-}
-
-
-/* The drm_read and drm_write_string code (especially that which manages
-   the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
-   DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
-
-ssize_t drm_read(struct file *filp, char *buf, size_t count, loff_t *off)
-{
-	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev    = priv->dev;
-	int	      left;
-	int	      avail;
-	int	      send;
-	int	      cur;
-
-	DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
-	
-	while (dev->buf_rp == dev->buf_wp) {
-		DRM_DEBUG("  sleeping\n");
-		if (filp->f_flags & O_NONBLOCK) {
-			return -EAGAIN;
-		}
-		interruptible_sleep_on(&dev->buf_readers);
-		if (signal_pending(current)) {
-			DRM_DEBUG("  interrupted\n");
-			return -ERESTARTSYS;
-		}
-		DRM_DEBUG("  awake\n");
-	}
-
-	left  = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
-	avail = DRM_BSZ - left;
-	send  = DRM_MIN(avail, count);
-
-	while (send) {
-		if (dev->buf_wp > dev->buf_rp) {
-			cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
-		} else {
-			cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
-		}
-		if (copy_to_user(buf, dev->buf_rp, cur))
-			return -EFAULT;
-		dev->buf_rp += cur;
-		if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
-		send -= cur;
-	}
-	
-	wake_up_interruptible(&dev->buf_writers);
-	return DRM_MIN(avail, count);;
-}
-
-int drm_write_string(drm_device_t *dev, const char *s)
-{
-	int left   = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
-	int send   = strlen(s);
-	int count;
-
-	DRM_DEBUG("%d left, %d to send (%p, %p)\n",
-		  left, send, dev->buf_rp, dev->buf_wp);
-	
-	if (left == 1 || dev->buf_wp != dev->buf_rp) {
-		DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
-			  left,
-			  dev->buf_wp,
-			  dev->buf_rp);
-	}
-
-	while (send) {
-		if (dev->buf_wp >= dev->buf_rp) {
-			count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
-			if (count == left) --count; /* Leave a hole */
-		} else {
-			count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
-		}
-		strncpy(dev->buf_wp, s, count);
-		dev->buf_wp += count;
-		if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
-		send -= count;
-	}
-
-#if LINUX_VERSION_CODE < 0x020315 && !defined(KILLFASYNCHASTHREEPARAMETERS)
-	/* The extra parameter to kill_fasync was added in 2.3.21, and is
-           _not_ present in _stock_ 2.2.14 and 2.2.15.  However, some
-           distributions patch 2.2.x kernels to add this parameter.  The
-           Makefile.linux attempts to detect this addition and defines
-           KILLFASYNCHASTHREEPARAMETERS if three parameters are found. */
-	if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO);
-#else
-
-				/* Parameter added in 2.3.21. */
-#if LINUX_VERSION_CODE < 0x020400
-	if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN);
-#else
-				/* Type of first parameter changed in
-                                   Linux 2.4.0-test2... */
-	if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
-#endif
-#endif
-	DRM_DEBUG("waking\n");
-	wake_up_interruptible(&dev->buf_readers);
-	return 0;
-}
-
-unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
-{
-	drm_file_t   *priv = filp->private_data;
-	drm_device_t *dev  = priv->dev;
-
-	poll_wait(filp, &dev->buf_readers, wait);
-	if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/gamma.h linux/drivers/char/drm/gamma.h
--- linux-2.4.8-pre6/drivers/char/drm/gamma.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/gamma.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,93 @@
+/* gamma.c -- 3dlabs GMX 2000 driver -*- linux-c -*-
+ * Created: Mon Jan  4 08:58:31 1999 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __GAMMA_H__
+#define __GAMMA_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) gamma_##x
+
+/* General customization:
+ */
+#define __HAVE_MTRR			1
+
+/* DMA customization:
+ */
+#define __HAVE_DMA			1
+#define __HAVE_OLD_DMA			1
+#define __HAVE_PCI_DMA			1
+
+#define __HAVE_MULTIPLE_DMA_QUEUES	1
+#define __HAVE_DMA_WAITQUEUE		1
+
+#define __HAVE_DMA_WAITLIST		1
+#define __HAVE_DMA_FREELIST		1
+
+#define __HAVE_DMA_FLUSH		1
+#define __HAVE_DMA_SCHEDULE		1
+
+#define __HAVE_DMA_READY		1
+#define DRIVER_DMA_READY() do {						\
+	gamma_dma_ready(dev);						\
+} while (0)
+
+#define __HAVE_DMA_QUIESCENT		1
+#define DRIVER_DMA_QUIESCENT() do {					\
+	/* FIXME ! */ 							\
+	gamma_dma_quiescent_dual(dev);					\
+	return 0;							\
+} while (0)
+
+#define __HAVE_DMA_IRQ			1
+#define __HAVE_DMA_IRQ_BH		1
+#define DRIVER_PREINSTALL() do {					\
+	drm_gamma_private_t *dev_priv =					\
+				(drm_gamma_private_t *)dev->dev_private;\
+	GAMMA_WRITE( GAMMA_GCOMMANDMODE,	0x00000000 );		\
+	GAMMA_WRITE( GAMMA_GDMACONTROL,		0x00000000 );		\
+} while (0)
+
+#define DRIVER_POSTINSTALL() do {					\
+	drm_gamma_private_t *dev_priv =					\
+				(drm_gamma_private_t *)dev->dev_private;\
+	GAMMA_WRITE( GAMMA_GINTENABLE,		0x00002001 );		\
+	GAMMA_WRITE( GAMMA_COMMANDINTENABLE,	0x00000008 );		\
+	GAMMA_WRITE( GAMMA_GDELAYTIMER,		0x00039090 );		\
+} while (0)
+
+#define DRIVER_UNINSTALL() do {						\
+	drm_gamma_private_t *dev_priv =					\
+				(drm_gamma_private_t *)dev->dev_private;\
+	GAMMA_WRITE( GAMMA_GDELAYTIMER,		0x00000000 );		\
+	GAMMA_WRITE( GAMMA_COMMANDINTENABLE,	0x00000000 );		\
+	GAMMA_WRITE( GAMMA_GINTENABLE,		0x00000000 );		\
+} while (0)
+
+#endif /* __GAMMA_H__ */
diff -urN linux-2.4.8-pre6/drivers/char/drm/gamma_dma.c linux/drivers/char/drm/gamma_dma.c
--- linux-2.4.8-pre6/drivers/char/drm/gamma_dma.c	Mon Dec 11 12:39:44 2000
+++ linux/drivers/char/drm/gamma_dma.c	Mon Dec  3 22:59:45 2001
@@ -11,11 +11,11 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the next
  * paragraph) shall be included in all copies or substantial portions of the
  * Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
@@ -23,73 +23,38 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF 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>
  *
  */
 
 #define __NO_VERSION__
+#include "gamma.h"
 #include "drmP.h"
 #include "gamma_drv.h"
 
 #include <linux/interrupt.h>	/* For task queue support */
+#include <linux/delay.h>
 
 
-/* WARNING!!! MAGIC NUMBER!!!  The number of regions already added to the
-   kernel must be specified here.  Currently, the number is 2.	This must
-   match the order the X server uses for instantiating register regions ,
-   or must be passed in a new ioctl. */
-#define GAMMA_REG(reg)						   \
-	(2							   \
-	 + ((reg < 0x1000)					   \
-	    ? 0							   \
-	    : ((reg < 0x10000) ? 1 : ((reg < 0x11000) ? 2 : 3))))
-
-#define GAMMA_OFF(reg)						   \
-	((reg < 0x1000)						   \
-	 ? reg							   \
-	 : ((reg < 0x10000)					   \
-	    ? (reg - 0x1000)					   \
-	    : ((reg < 0x11000)					   \
-	       ? (reg - 0x10000)				   \
-	       : (reg - 0x11000))))
-
-#define GAMMA_BASE(reg)	 ((unsigned long)dev->maplist[GAMMA_REG(reg)]->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)
-#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0)
-
-#define GAMMA_BROADCASTMASK    0x9378
-#define GAMMA_COMMANDINTENABLE 0x0c48
-#define GAMMA_DMAADDRESS       0x0028
-#define GAMMA_DMACOUNT	       0x0030
-#define GAMMA_FILTERMODE       0x8c00
-#define GAMMA_GCOMMANDINTFLAGS 0x0c50
-#define GAMMA_GCOMMANDMODE     0x0c40
-#define GAMMA_GCOMMANDSTATUS   0x0c60
-#define GAMMA_GDELAYTIMER      0x0c38
-#define GAMMA_GDMACONTROL      0x0060
-#define GAMMA_GINTENABLE       0x0808
-#define GAMMA_GINTFLAGS	       0x0810
-#define GAMMA_INFIFOSPACE      0x0018
-#define GAMMA_OUTFIFOWORDS     0x0020
-#define GAMMA_OUTPUTFIFO       0x2000
-#define GAMMA_SYNC	       0x8c40
-#define GAMMA_SYNC_TAG	       0x0188
-
 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)
 		;
 	GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
 }
 
-static inline void gamma_dma_quiescent_single(drm_device_t *dev)
+void gamma_dma_quiescent_single(drm_device_t *dev)
 {
+	drm_gamma_private_t *dev_priv =
+		(drm_gamma_private_t *)dev->dev_private;
+
 	while (GAMMA_READ(GAMMA_DMACOUNT))
 		;
 	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
@@ -97,15 +62,18 @@
 
 	GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
 	GAMMA_WRITE(GAMMA_SYNC, 0);
-	
+
 	do {
 		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
 			;
 	} while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
 }
 
-static inline void gamma_dma_quiescent_dual(drm_device_t *dev)
+void gamma_dma_quiescent_dual(drm_device_t *dev)
 {
+	drm_gamma_private_t *dev_priv =
+		(drm_gamma_private_t *)dev->dev_private;
+
 	while (GAMMA_READ(GAMMA_DMACOUNT))
 		;
 	while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
@@ -115,13 +83,13 @@
 
 	GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
 	GAMMA_WRITE(GAMMA_SYNC, 0);
-	
+
 				/* Read from first MX */
 	do {
 		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
 			;
 	} while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
-	
+
 				/* Read from second MX */
 	do {
 		while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
@@ -129,34 +97,39 @@
 	} while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
 }
 
-static inline void gamma_dma_ready(drm_device_t *dev)
+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))
 		;
 }
 
 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);
 }
 
-static void gamma_dma_service(int irq, void *device, struct pt_regs *regs)
+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;
-	
-	atomic_inc(&dev->total_irq);
+	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;
+
+	atomic_inc(&dev->counts[6]); /* _DRM_STAT_IRQ */
 	GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
 	GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
 	GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
 	if (gamma_dma_is_ready(dev)) {
 				/* Free previous buffer */
-		if (test_and_set_bit(0, &dev->dma_flag)) {
-			atomic_inc(&dma->total_missed_free);
-			return;
-		}
+		if (test_and_set_bit(0, &dev->dma_flag)) return;
 		if (dma->this_buffer) {
-			drm_free_buffer(dev, dma->this_buffer);
+			gamma_free_buffer(dev, dma->this_buffer);
 			dma->this_buffer = NULL;
 		}
 		clear_bit(0, &dev->dma_flag);
@@ -179,11 +152,8 @@
 	cycles_t	 dma_start, dma_stop;
 #endif
 
-	if (test_and_set_bit(0, &dev->dma_flag)) {
-		atomic_inc(&dma->total_missed_dma);
-		return -EBUSY;
-	}
-	
+	if (test_and_set_bit(0, &dev->dma_flag)) return -EBUSY;
+
 #if DRM_DMA_HISTOGRAM
 	dma_start = get_cycles();
 #endif
@@ -202,20 +172,20 @@
 		  buf->context, buf->idx, length);
 
 	if (buf->list == DRM_LIST_RECLAIM) {
-		drm_clear_next_buffer(dev);
-		drm_free_buffer(dev, buf);
+		gamma_clear_next_buffer(dev);
+		gamma_free_buffer(dev, buf);
 		clear_bit(0, &dev->dma_flag);
 		return -EINVAL;
 	}
 
 	if (!length) {
 		DRM_ERROR("0 length buffer\n");
-		drm_clear_next_buffer(dev);
-		drm_free_buffer(dev, buf);
+		gamma_clear_next_buffer(dev);
+		gamma_free_buffer(dev, buf);
 		clear_bit(0, &dev->dma_flag);
 		return 0;
 	}
-	
+
 	if (!gamma_dma_is_ready(dev)) {
 		clear_bit(0, &dev->dma_flag);
 		return -EBUSY;
@@ -228,9 +198,8 @@
 				  buf->idx, buf->pid);
 		}
 	} else {
-		if (!locked && !drm_lock_take(&dev->lock.hw_lock->lock,
+		if (!locked && !gamma_lock_take(&dev->lock.hw_lock->lock,
 					      DRM_KERNEL_CONTEXT)) {
-			atomic_inc(&dma->total_missed_lock);
 			clear_bit(0, &dev->dma_flag);
 			return -EBUSY;
 		}
@@ -240,13 +209,14 @@
 	    && !(dev->queuelist[buf->context]->flags
 		 & _DRM_CONTEXT_PRESERVED)) {
 				/* PRE: dev->last_context != buf->context */
-		if (drm_context_switch(dev, dev->last_context, buf->context)) {
-			drm_clear_next_buffer(dev);
-			drm_free_buffer(dev, buf);
+		if (DRM(context_switch)(dev, dev->last_context,
+					buf->context)) {
+			DRM(clear_next_buffer)(dev);
+			DRM(free_buffer)(dev, buf);
 		}
 		retcode = -EBUSY;
 		goto cleanup;
-			
+
 				/* POST: we will wait for the context
 				   switch and will dispatch on a later call
 				   when dev->last_context == buf->context.
@@ -254,7 +224,7 @@
 				   TIME! */
 	}
 
-	drm_clear_next_buffer(dev);
+	gamma_clear_next_buffer(dev);
 	buf->pending	 = 1;
 	buf->waiting	 = 0;
 	buf->list	 = DRM_LIST_PEND;
@@ -263,14 +233,14 @@
 #endif
 
 	gamma_dma_dispatch(dev, address, length);
-	drm_free_buffer(dev, dma->this_buffer);
+	gamma_free_buffer(dev, dma->this_buffer);
 	dma->this_buffer = buf;
 
-	atomic_add(length, &dma->total_bytes);
-	atomic_inc(&dma->total_dmas);
+	atomic_inc(&dev->counts[7]); /* _DRM_STAT_DMA */
+	atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
 
 	if (!buf->while_locked && !dev->context_flag && !locked) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
+		if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
 				  DRM_KERNEL_CONTEXT)) {
 			DRM_ERROR("\n");
 		}
@@ -281,18 +251,18 @@
 
 #if DRM_DMA_HISTOGRAM
 	dma_stop = get_cycles();
-	atomic_inc(&dev->histo.dma[drm_histogram_slot(dma_stop - dma_start)]);
+	atomic_inc(&dev->histo.dma[gamma_histogram_slot(dma_stop - dma_start)]);
 #endif
 
 	return retcode;
 }
 
-static void gamma_dma_schedule_timer_wrapper(unsigned long dev)
+static void gamma_dma_timer_bh(unsigned long dev)
 {
 	gamma_dma_schedule((drm_device_t *)dev, 0);
 }
 
-static void gamma_dma_schedule_tq_wrapper(void *dev)
+void gamma_dma_immediate_bh(void *dev)
 {
 	gamma_dma_schedule(dev, 0);
 }
@@ -313,10 +283,10 @@
 
 	if (test_and_set_bit(0, &dev->interrupt_flag)) {
 				/* Not reentrant */
-		atomic_inc(&dma->total_missed_sched);
+		atomic_inc(&dev->counts[10]); /* _DRM_STAT_MISSED */
 		return -EBUSY;
 	}
-	missed = atomic_read(&dma->total_missed_sched);
+	missed = atomic_read(&dev->counts[10]);
 
 #if DRM_DMA_HISTOGRAM
 	schedule_start = get_cycles();
@@ -333,23 +303,18 @@
 				   because the lock could not be obtained
 				   or the DMA engine wasn't ready.  Try
 				   again. */
-		atomic_inc(&dma->total_tried);
-		if (!(retcode = gamma_do_dma(dev, locked))) {
-			atomic_inc(&dma->total_hit);
-			++processed;
-		}
+		if (!(retcode = gamma_do_dma(dev, locked))) ++processed;
 	} else {
 		do {
-			next = drm_select_queue(dev,
-					     gamma_dma_schedule_timer_wrapper);
+			next = gamma_select_queue(dev, gamma_dma_timer_bh);
 			if (next >= 0) {
 				q   = dev->queuelist[next];
-				buf = drm_waitlist_get(&q->waitlist);
+				buf = gamma_waitlist_get(&q->waitlist);
 				dma->next_buffer = buf;
 				dma->next_queue	 = q;
 				if (buf && buf->list == DRM_LIST_RECLAIM) {
-					drm_clear_next_buffer(dev);
-					drm_free_buffer(dev, buf);
+					gamma_clear_next_buffer(dev);
+					gamma_free_buffer(dev, buf);
 				}
 			}
 		} while (next >= 0 && !dma->next_buffer);
@@ -361,21 +326,19 @@
 	}
 
 	if (--expire) {
-		if (missed != atomic_read(&dma->total_missed_sched)) {
-			atomic_inc(&dma->total_lost);
+		if (missed != atomic_read(&dev->counts[10])) {
 			if (gamma_dma_is_ready(dev)) goto again;
 		}
 		if (processed && gamma_dma_is_ready(dev)) {
-			atomic_inc(&dma->total_lost);
 			processed = 0;
 			goto again;
 		}
 	}
-	
+
 	clear_bit(0, &dev->interrupt_flag);
-	
+
 #if DRM_DMA_HISTOGRAM
-	atomic_inc(&dev->histo.schedule[drm_histogram_slot(get_cycles()
+	atomic_inc(&dev->histo.schedule[gamma_histogram_slot(get_cycles()
 							   - schedule_start)]);
 #endif
 	return retcode;
@@ -400,7 +363,7 @@
 		if (signal_pending(current)) return -EINTR;
 	}
 	if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) {
-		while (!drm_lock_take(&dev->lock.hw_lock->lock,
+		while (!gamma_lock_take(&dev->lock.hw_lock->lock,
 				      DRM_KERNEL_CONTEXT)) {
 			schedule();
 			if (signal_pending(current)) {
@@ -410,7 +373,6 @@
 		}
 		++must_free;
 	}
-	atomic_inc(&dma->total_prio);
 
 	for (i = 0; i < d->send_count; i++) {
 		idx = d->send_indices[i];
@@ -461,15 +423,15 @@
 			goto cleanup;
 		}
 		buf->pending = 1;
-		
+
 		if (dev->last_context != buf->context
 		    && !(dev->queuelist[buf->context]->flags
 			 & _DRM_CONTEXT_PRESERVED)) {
 			add_wait_queue(&dev->context_wait, &entry);
 			current->state = TASK_INTERRUPTIBLE;
 				/* PRE: dev->last_context != buf->context */
-			drm_context_switch(dev, dev->last_context,
-					   buf->context);
+			DRM(context_switch)(dev, dev->last_context,
+					    buf->context);
 				/* POST: we will wait for the context
 				   switch and will dispatch on a later call
 				   when dev->last_context == buf->context.
@@ -494,11 +456,11 @@
 		buf->time_dispatched = buf->time_queued;
 #endif
 		gamma_dma_dispatch(dev, address, length);
-		atomic_add(length, &dma->total_bytes);
-		atomic_inc(&dma->total_dmas);
-		
+		atomic_inc(&dev->counts[9]); /* _DRM_STAT_SPECIAL */
+		atomic_add(length, &dev->counts[8]); /* _DRM_STAT_PRIMARY */
+
 		if (last_buf) {
-			drm_free_buffer(dev, last_buf);
+			gamma_free_buffer(dev, last_buf);
 		}
 		last_buf = buf;
 	}
@@ -507,11 +469,11 @@
 cleanup:
 	if (last_buf) {
 		gamma_dma_ready(dev);
-		drm_free_buffer(dev, last_buf);
+		gamma_free_buffer(dev, last_buf);
 	}
-	
+
 	if (must_free && !dev->context_flag) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
+		if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
 				  DRM_KERNEL_CONTEXT)) {
 			DRM_ERROR("\n");
 		}
@@ -531,15 +493,15 @@
 		last_buf = dma->buflist[d->send_indices[d->send_count-1]];
 		add_wait_queue(&last_buf->dma_wait, &entry);
 	}
-	
-	if ((retcode = drm_dma_enqueue(dev, d))) {
+
+	if ((retcode = gamma_dma_enqueue(dev, d))) {
 		if (d->flags & _DRM_DMA_BLOCK)
 			remove_wait_queue(&last_buf->dma_wait, &entry);
 		return retcode;
 	}
-	
+
 	gamma_dma_schedule(dev, 0);
-	
+
 	if (d->flags & _DRM_DMA_BLOCK) {
 		DRM_DEBUG("%d waiting\n", current->pid);
 		for (;;) {
@@ -558,7 +520,7 @@
 		if (!retcode
 		    || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {
 			if (!waitqueue_active(&last_buf->dma_wait)) {
-				drm_free_buffer(dev, last_buf);
+				gamma_free_buffer(dev, last_buf);
 			}
 		}
 		if (retcode) {
@@ -587,19 +549,13 @@
 
 	if (copy_from_user(&d, (drm_dma_t *)arg, sizeof(d)))
 		return -EFAULT;
-	DRM_DEBUG("%d %d: %d send, %d req\n",
-		  current->pid, d.context, d.send_count, d.request_count);
 
-	if (d.context == DRM_KERNEL_CONTEXT || d.context >= dev->queue_slots) {
-		DRM_ERROR("Process %d using context %d\n",
-			  current->pid, d.context);
-		return -EINVAL;
-	}
 	if (d.send_count < 0 || d.send_count > dma->buf_count) {
 		DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n",
 			  current->pid, d.send_count, dma->buf_count);
 		return -EINVAL;
 	}
+
 	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);
@@ -609,14 +565,14 @@
 	if (d.send_count) {
 		if (d.flags & _DRM_DMA_PRIORITY)
 			retcode = gamma_dma_priority(dev, &d);
-		else 
+		else
 			retcode = gamma_dma_send_buffers(dev, &d);
 	}
 
 	d.granted_count = 0;
 
 	if (!retcode && d.request_count) {
-		retcode = drm_dma_get_buffers(dev, &d);
+		retcode = gamma_dma_get_buffers(dev, &d);
 	}
 
 	DRM_DEBUG("%d returning, granted = %d\n",
@@ -625,212 +581,4 @@
 		return -EFAULT;
 
 	return retcode;
-}
-
-int gamma_irq_install(drm_device_t *dev, int irq)
-{
-	int retcode;
-
-	if (!irq)     return -EINVAL;
-	
-	down(&dev->struct_sem);
-	if (dev->irq) {
-		up(&dev->struct_sem);
-		return -EBUSY;
-	}
-	dev->irq = irq;
-	up(&dev->struct_sem);
-	
-	DRM_DEBUG("%d\n", irq);
-
-	dev->context_flag     = 0;
-	dev->interrupt_flag   = 0;
-	dev->dma_flag	      = 0;
-	
-	dev->dma->next_buffer = NULL;
-	dev->dma->next_queue  = NULL;
-	dev->dma->this_buffer = NULL;
-
-	INIT_LIST_HEAD(&dev->tq.list);
-	dev->tq.sync	      = 0;
-	dev->tq.routine	      = gamma_dma_schedule_tq_wrapper;
-	dev->tq.data	      = dev;
-
-
-				/* Before installing handler */
-	GAMMA_WRITE(GAMMA_GCOMMANDMODE, 0);
-	GAMMA_WRITE(GAMMA_GDMACONTROL, 0);
-	
-				/* Install handler */
-	if ((retcode = request_irq(dev->irq,
-				   gamma_dma_service,
-				   0,
-				   dev->devname,
-				   dev))) {
-		down(&dev->struct_sem);
-		dev->irq = 0;
-		up(&dev->struct_sem);
-		return retcode;
-	}
-
-				/* After installing handler */
-	GAMMA_WRITE(GAMMA_GINTENABLE,	    0x2001);
-	GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0x0008);
-	GAMMA_WRITE(GAMMA_GDELAYTIMER,	   0x39090);
-	
-	return 0;
-}
-
-int gamma_irq_uninstall(drm_device_t *dev)
-{
-	int irq;
-
-	down(&dev->struct_sem);
-	irq	 = dev->irq;
-	dev->irq = 0;
-	up(&dev->struct_sem);
-	
-	if (!irq) return -EINVAL;
-	
-	DRM_DEBUG("%d\n", irq);
-	
-	GAMMA_WRITE(GAMMA_GDELAYTIMER,	    0);
-	GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0);
-	GAMMA_WRITE(GAMMA_GINTENABLE,	    0);
-	free_irq(irq, dev);
-
-	return 0;
-}
-
-
-int gamma_control(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_control_t	ctl;
-	int		retcode;
-	
-	if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
-		return -EFAULT;
-	
-	switch (ctl.func) {
-	case DRM_INST_HANDLER:
-		if ((retcode = gamma_irq_install(dev, ctl.irq)))
-			return retcode;
-		break;
-	case DRM_UNINST_HANDLER:
-		if ((retcode = gamma_irq_uninstall(dev)))
-			return retcode;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-int gamma_lock(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;
-	DECLARE_WAITQUEUE(entry, current);
-	int		  ret	= 0;
-	drm_lock_t	  lock;
-	drm_queue_t	  *q;
-#if DRM_DMA_HISTOGRAM
-	cycles_t	  start;
-
-	dev->lck_start = start = get_cycles();
-#endif
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-		  lock.context, current->pid, dev->lock.hw_lock->lock,
-		  lock.flags);
-
-	if (lock.context < 0 || lock.context >= dev->queue_count)
-		return -EINVAL;
-	q = dev->queuelist[lock.context];
-	
-	ret = drm_flush_block_and_flush(dev, lock.context, lock.flags);
-
-	if (!ret) {
-		if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
-		    != lock.context) {
-			long j = jiffies - dev->lock.lock_time;
-
-			if (j > 0 && j <= DRM_LOCK_SLICE) {
-				/* Can't take lock if we just had it and
-				   there is contention. */
-				current->state = TASK_INTERRUPTIBLE;
-				schedule_timeout(j);
-			}
-		}
-		add_wait_queue(&dev->lock.lock_queue, &entry);
-		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-			if (!dev->lock.hw_lock) {
-				/* Device has been unregistered */
-				ret = -EINTR;
-				break;
-			}
-			if (drm_lock_take(&dev->lock.hw_lock->lock,
-					  lock.context)) {
-				dev->lock.pid	    = current->pid;
-				dev->lock.lock_time = jiffies;
-				atomic_inc(&dev->total_locks);
-				atomic_inc(&q->total_locks);
-				break;	/* Got lock */
-			}
-			
-				/* Contention */
-			atomic_inc(&dev->total_sleeps);
-			schedule();
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				break;
-			}
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&dev->lock.lock_queue, &entry);
-	}
-
-	drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */
-	
-	if (!ret) {
-		sigemptyset(&dev->sigmask);
-		sigaddset(&dev->sigmask, SIGSTOP);
-		sigaddset(&dev->sigmask, SIGTSTP);
-		sigaddset(&dev->sigmask, SIGTTIN);
-		sigaddset(&dev->sigmask, SIGTTOU);
-		dev->sigdata.context = lock.context;
-		dev->sigdata.lock    = dev->lock.hw_lock;
-		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
-
-		if (lock.flags & _DRM_LOCK_READY)
-			gamma_dma_ready(dev);
-		if (lock.flags & _DRM_LOCK_QUIESCENT) {
-			if (gamma_found() == 1) {
-				gamma_dma_quiescent_single(dev);
-			} else {
-				gamma_dma_quiescent_dual(dev);
-			}
-		}
-	}
-	DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
-
-#if DRM_DMA_HISTOGRAM
-	atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
-#endif
-	
-	return ret;
 }
diff -urN linux-2.4.8-pre6/drivers/char/drm/gamma_drv.c linux/drivers/char/drm/gamma_drv.c
--- linux-2.4.8-pre6/drivers/char/drm/gamma_drv.c	Sat Nov 11 18:34:38 2000
+++ linux/drivers/char/drm/gamma_drv.c	Mon Dec  3 22:59:45 2001
@@ -26,546 +26,69 @@
  *
  * Authors:
  *    Rickard E. (Rik) Faith <faith@valinux.com>
- *
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include <linux/config.h>
+#include "gamma.h"
 #include "drmP.h"
 #include "gamma_drv.h"
 
-#ifndef PCI_DEVICE_ID_3DLABS_GAMMA
-#define PCI_DEVICE_ID_3DLABS_GAMMA 0x0008
-#endif
-#ifndef PCI_DEVICE_ID_3DLABS_MX
-#define PCI_DEVICE_ID_3DLABS_MX 0x0006
-#endif
+#define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
-#define GAMMA_NAME	 "gamma"
-#define GAMMA_DESC	 "3dlabs GMX 2000"
-#define GAMMA_DATE	 "20000910"
-#define GAMMA_MAJOR	 1
-#define GAMMA_MINOR	 0
-#define GAMMA_PATCHLEVEL 0
-
-static drm_device_t	      gamma_device;
-
-static struct file_operations gamma_fops = {
-#if LINUX_VERSION_CODE >= 0x020400
-				/* This started being used during 2.4.0-test */
-	owner:   THIS_MODULE,
-#endif
-	open:	 gamma_open,
-	flush:	 drm_flush,
-	release: gamma_release,
-	ioctl:	 gamma_ioctl,
-	mmap:	 drm_mmap,
-	read:	 drm_read,
-	fasync:	 drm_fasync,
-	poll:	 drm_poll,
-};
-
-static struct miscdevice      gamma_misc = {
-	minor: MISC_DYNAMIC_MINOR,
-	name:  GAMMA_NAME,
-	fops:  &gamma_fops,
-};
-
-static drm_ioctl_desc_t	      gamma_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]    = { gamma_version,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]  = { drm_getmagic,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]  = { drm_irq_busid,	  0, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]	     = { drm_block,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]    = { drm_unblock,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]    = { gamma_control,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]    = { drm_addmap,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]   = { drm_addbufs,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]  = { drm_markbufs,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]  = { drm_infobufs,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]   = { drm_mapbufs,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]  = { drm_freebufs,	  1, 0 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]    = { drm_addctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]     = { drm_rmctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]    = { drm_modctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]    = { drm_getctx,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { drm_switchctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]    = { drm_newctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]    = { drm_resctx,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]   = { drm_adddraw,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]    = { drm_rmdraw,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	     = { gamma_dma,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	     = { gamma_lock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]     = { gamma_unlock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]     = { drm_finish,	  1, 0 },
-};
-#define GAMMA_IOCTL_COUNT DRM_ARRAY_SIZE(gamma_ioctls)
-
-#ifdef MODULE
-static char		      *gamma = NULL;
-#endif
-static int 		      devices = 0;
+#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_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
 
-MODULE_AUTHOR("VA Linux Systems, Inc.");
-MODULE_DESCRIPTION("3dlabs GMX 2000");
-MODULE_PARM(gamma, "s");
-MODULE_PARM(devices, "i");
-MODULE_PARM_DESC(devices,
-		 "devices=x, where x is the number of MX chips on card\n");
 #ifndef MODULE
-/* gamma_options is called by the kernel to parse command-line options
+/* 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_options.
+ * routine, drm_parse_drm.
  */
 
-
-static int __init gamma_options(char *str)
+/* 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);
+	DRM(parse_options)( str );
 	return 1;
 }
 
-__setup("gamma=", gamma_options);
-#endif
-
-static int gamma_setup(drm_device_t *dev)
-{
-	int i;
-
-	atomic_set(&dev->ioctl_count, 0);
-	atomic_set(&dev->vma_count, 0);
-	dev->buf_use	  = 0;
-	atomic_set(&dev->buf_alloc, 0);
-
-	drm_dma_setup(dev);
-
-	atomic_set(&dev->total_open, 0);
-	atomic_set(&dev->total_close, 0);
-	atomic_set(&dev->total_ioctl, 0);
-	atomic_set(&dev->total_irq, 0);
-	atomic_set(&dev->total_ctx, 0);
-	atomic_set(&dev->total_locks, 0);
-	atomic_set(&dev->total_unlocks, 0);
-	atomic_set(&dev->total_contends, 0);
-	atomic_set(&dev->total_sleeps, 0);
-
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		dev->magiclist[i].head = NULL;
-		dev->magiclist[i].tail = NULL;
-	}
-	dev->maplist	    = NULL;
-	dev->map_count	    = 0;
-	dev->vmalist	    = NULL;
-	dev->lock.hw_lock   = NULL;
-	init_waitqueue_head(&dev->lock.lock_queue);
-	dev->queue_count    = 0;
-	dev->queue_reserved = 0;
-	dev->queue_slots    = 0;
-	dev->queuelist	    = NULL;
-	dev->irq	    = 0;
-	dev->context_flag   = 0;
-	dev->interrupt_flag = 0;
-	dev->dma_flag	    = 0;
-	dev->last_context   = 0;
-	dev->last_switch    = 0;
-	dev->last_checked   = 0;
-	init_timer(&dev->timer);
-	init_waitqueue_head(&dev->context_wait);
-#if DRM_DMA_HISTO
-	memset(&dev->histo, 0, sizeof(dev->histo));
-#endif
-	dev->ctx_start	    = 0;
-	dev->lck_start	    = 0;
-
-	dev->buf_rp	  = dev->buf;
-	dev->buf_wp	  = dev->buf;
-	dev->buf_end	  = dev->buf + DRM_BSZ;
-	dev->buf_async	  = NULL;
-	init_waitqueue_head(&dev->buf_readers);
-	init_waitqueue_head(&dev->buf_writers);
-
-	DRM_DEBUG("\n");
-
-	/* The kernel's context could be created here, but is now created
-	   in drm_dma_enqueue.	This is more resource-efficient for
-	   hardware that does not do DMA, but may mean that
-	   drm_select_queue fails between the time the interrupt is
-	   initialized and the time the queues are initialized. */
-
-	return 0;
-}
-
-
-static int gamma_takedown(drm_device_t *dev)
-{
-	int		  i;
-	drm_magic_entry_t *pt, *next;
-	drm_map_t	  *map;
-	drm_vma_entry_t	  *vma, *vma_next;
-
-	DRM_DEBUG("\n");
-
-	if (dev->irq) gamma_irq_uninstall(dev);
-
-	down(&dev->struct_sem);
-	del_timer(&dev->timer);
-
-	if (dev->devname) {
-		drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
-		dev->devname = NULL;
-	}
-
-	if (dev->unique) {
-		drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
-		dev->unique = NULL;
-		dev->unique_len = 0;
-	}
-				/* Clear pid list */
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		for (pt = dev->magiclist[i].head; pt; pt = next) {
-			next = pt->next;
-			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-		}
-		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
-	}
-
-				/* Clear vma list (only built for debugging) */
-	if (dev->vmalist) {
-		for (vma = dev->vmalist; vma; vma = vma_next) {
-			vma_next = vma->next;
-			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
-		}
-		dev->vmalist = NULL;
-	}
-
-				/* Clear map area and mtrr information */
-	if (dev->maplist) {
-		for (i = 0; i < dev->map_count; i++) {
-			map = dev->maplist[i];
-			switch (map->type) {
-			case _DRM_REGISTERS:
-			case _DRM_FRAME_BUFFER:
-#ifdef CONFIG_MTRR
-				if (map->mtrr >= 0) {
-					int retcode;
-					retcode = mtrr_del(map->mtrr,
-							   map->offset,
-							   map->size);
-					DRM_DEBUG("mtrr_del = %d\n", retcode);
-				}
-#endif
-				drm_ioremapfree(map->handle, map->size);
-				break;
-			case _DRM_SHM:
-				drm_free_pages((unsigned long)map->handle,
-					       drm_order(map->size)
-					       - PAGE_SHIFT,
-					       DRM_MEM_SAREA);
-				break;
-			case _DRM_AGP:
-				/* Do nothing here, because this is all
-                                   handled in the AGP/GART driver. */
-				break;
-			}
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		}
-		drm_free(dev->maplist,
-			 dev->map_count * sizeof(*dev->maplist),
-			 DRM_MEM_MAPS);
-		dev->maplist   = NULL;
-		dev->map_count = 0;
-	}
-
-	if (dev->queuelist) {
-		for (i = 0; i < dev->queue_count; i++) {
-			drm_waitlist_destroy(&dev->queuelist[i]->waitlist);
-			if (dev->queuelist[i]) {
-				drm_free(dev->queuelist[i],
-					 sizeof(*dev->queuelist[0]),
-					 DRM_MEM_QUEUES);
-				dev->queuelist[i] = NULL;
-			}
-		}
-		drm_free(dev->queuelist,
-			 dev->queue_slots * sizeof(*dev->queuelist),
-			 DRM_MEM_QUEUES);
-		dev->queuelist	 = NULL;
-	}
-
-	drm_dma_takedown(dev);
-
-	dev->queue_count     = 0;
-	if (dev->lock.hw_lock) {
-		dev->lock.hw_lock    = NULL; /* SHM removed */
-		dev->lock.pid	     = 0;
-		wake_up_interruptible(&dev->lock.lock_queue);
-	}
-	up(&dev->struct_sem);
-
-	return 0;
-}
-
-int gamma_found(void)
-{
-	return devices;
-}
-
-int gamma_find_devices(void)
-{
-	struct pci_dev *d = NULL, *one = NULL, *two = NULL;
-
-	d = pci_find_device(PCI_VENDOR_ID_3DLABS,PCI_DEVICE_ID_3DLABS_GAMMA,d);
-	if (!d) return 0;
-
-	one = pci_find_device(PCI_VENDOR_ID_3DLABS,PCI_DEVICE_ID_3DLABS_MX,d);
-	if (!one) return 0;
-
-	/* Make sure it's on the same card, if not - no MX's found */
-	if (PCI_SLOT(d->devfn) != PCI_SLOT(one->devfn)) return 0;
-
-	two = pci_find_device(PCI_VENDOR_ID_3DLABS,PCI_DEVICE_ID_3DLABS_MX,one);
-	if (!two) return 1;
-
-	/* Make sure it's on the same card, if not - only 1 MX found */
-	if (PCI_SLOT(d->devfn) != PCI_SLOT(two->devfn)) return 1;
-
-	/* Two MX's found - we don't currently support more than 2 */
-	return 2;
-}
-
-/* gamma_init is called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported). */
-
-static int __init gamma_init(void)
-{
-	int		      retcode;
-	drm_device_t	      *dev = &gamma_device;
-
-	DRM_DEBUG("\n");
-
-	memset((void *)dev, 0, sizeof(*dev));
-	dev->count_lock	  = SPIN_LOCK_UNLOCKED;
-	sema_init(&dev->struct_sem, 1);
-
-#ifdef MODULE
-	drm_parse_options(gamma);
-#endif
-	devices = gamma_find_devices();
-	if (devices == 0) return -1;
-
-	if ((retcode = misc_register(&gamma_misc))) {
-		DRM_ERROR("Cannot register \"%s\"\n", GAMMA_NAME);
-		return retcode;
-	}
-	dev->device = MKDEV(MISC_MAJOR, gamma_misc.minor);
-	dev->name   = GAMMA_NAME;
-
-	drm_mem_init();
-	drm_proc_init(dev);
-
-	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d with %d MX devices\n",
-		 GAMMA_NAME,
-		 GAMMA_MAJOR,
-		 GAMMA_MINOR,
-		 GAMMA_PATCHLEVEL,
-		 GAMMA_DATE,
-		 gamma_misc.minor,
-		 devices);
-
-	return 0;
-}
-
-/* gamma_cleanup is called via cleanup_module at module unload time. */
-
-static void __exit gamma_cleanup(void)
-{
-	drm_device_t	      *dev = &gamma_device;
-
-	DRM_DEBUG("\n");
-
-	drm_proc_cleanup();
-	if (misc_deregister(&gamma_misc)) {
-		DRM_ERROR("Cannot unload module\n");
-	} else {
-		DRM_INFO("Module unloaded\n");
-	}
-	gamma_takedown(dev);
-}
-
-module_init(gamma_init);
-module_exit(gamma_cleanup);
-
-
-int gamma_version(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
-{
-	drm_version_t version;
-	int	      len;
-
-	if (copy_from_user(&version,
-			   (drm_version_t *)arg,
-			   sizeof(version)))
-		return -EFAULT;
-
-#define DRM_COPY(name,value)				     \
-	len = strlen(value);				     \
-	if (len > name##_len) len = name##_len;		     \
-	name##_len = strlen(value);			     \
-	if (len && name) {				     \
-		if (copy_to_user(name, value, len))	     \
-			return -EFAULT;			     \
-	}
-
-	version.version_major	   = GAMMA_MAJOR;
-	version.version_minor	   = GAMMA_MINOR;
-	version.version_patchlevel = GAMMA_PATCHLEVEL;
-
-	DRM_COPY(version.name, GAMMA_NAME);
-	DRM_COPY(version.date, GAMMA_DATE);
-	DRM_COPY(version.desc, GAMMA_DESC);
-
-	if (copy_to_user((drm_version_t *)arg,
-			 &version,
-			 sizeof(version)))
-		return -EFAULT;
-	return 0;
-}
-
-int gamma_open(struct inode *inode, struct file *filp)
-{
-	drm_device_t  *dev    = &gamma_device;
-	int	      retcode = 0;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (!(retcode = drm_open_helper(inode, filp, dev))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
+__setup( DRIVER_NAME "=", gamma_options );
 #endif
-		atomic_inc(&dev->total_open);
-		spin_lock(&dev->count_lock);
-		if (!dev->open_count++) {
-			spin_unlock(&dev->count_lock);
-			return gamma_setup(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-	return retcode;
-}
-
-int gamma_release(struct inode *inode, struct file *filp)
-{
-	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev;
-	int	      retcode = 0;
-
-	lock_kernel();
-	dev = priv->dev;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (!(retcode = drm_release(inode, filp))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-		atomic_inc(&dev->total_close);
-		spin_lock(&dev->count_lock);
-		if (!--dev->open_count) {
-			if (atomic_read(&dev->ioctl_count) || dev->blocked) {
-				DRM_ERROR("Device busy: %d %d\n",
-					  atomic_read(&dev->ioctl_count),
-					  dev->blocked);
-				spin_unlock(&dev->count_lock);
-				unlock_kernel();
-				return -EBUSY;
-			}
-			spin_unlock(&dev->count_lock);
-			unlock_kernel();
-			return gamma_takedown(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-	unlock_kernel();
-	return retcode;
-}
 
-/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */
 
-int gamma_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
-{
-	int		 nr	 = DRM_IOCTL_NR(cmd);
-	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	int		 retcode = 0;
-	drm_ioctl_desc_t *ioctl;
-	drm_ioctl_t	 *func;
-
-	atomic_inc(&dev->ioctl_count);
-	atomic_inc(&dev->total_ioctl);
-	++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);
-
-	if (nr >= GAMMA_IOCTL_COUNT) {
-		retcode = -EINVAL;
-	} else {
-		ioctl	  = &gamma_ioctls[nr];
-		func	  = ioctl->func;
-
-		if (!func) {
-			DRM_DEBUG("no function\n");
-			retcode = -EINVAL;
-		} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
-			    || (ioctl->auth_needed && !priv->authenticated)) {
-			retcode = -EACCES;
-		} else {
-			retcode = (func)(inode, filp, cmd, arg);
-		}
-	}
-
-	atomic_dec(&dev->ioctl_count);
-	return retcode;
-}
-
-
-int gamma_unlock(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_lock_t	  lock;
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("%d frees lock (%d holds)\n",
-		  lock.context,
-		  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-	atomic_inc(&dev->total_unlocks);
-	if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
-		atomic_inc(&dev->total_contends);
-	drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
-	gamma_dma_schedule(dev, 1);
-	if (!dev->context_flag) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
-				  DRM_KERNEL_CONTEXT)) {
-			DRM_ERROR("\n");
-		}
-	}
-#if DRM_DMA_HISTOGRAM
-	atomic_inc(&dev->histo.lhld[drm_histogram_slot(get_cycles()
-						       - dev->lck_start)]);
-#endif
-
-	unblock_all_signals();
-	return 0;
-}
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lists.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff -urN linux-2.4.8-pre6/drivers/char/drm/gamma_drv.h linux/drivers/char/drm/gamma_drv.h
--- linux-2.4.8-pre6/drivers/char/drm/gamma_drv.h	Thu Jul 27 15:05:40 2000
+++ linux/drivers/char/drm/gamma_drv.h	Mon Dec  3 22:59:45 2001
@@ -11,11 +11,11 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the next
  * paragraph) shall be included in all copies or substantial portions of the
  * Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
@@ -23,36 +23,83 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF 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>
- * 
+ *
  */
 
 #ifndef _GAMMA_DRV_H_
 #define _GAMMA_DRV_H_
 
-				/* gamma_drv.c */
-extern int  gamma_version(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  gamma_open(struct inode *inode, struct file *filp);
-extern int  gamma_release(struct inode *inode, struct file *filp);
-extern int  gamma_ioctl(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  gamma_lock(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  gamma_unlock(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
+
+typedef struct drm_gamma_private {
+	drm_map_t *buffers;
+	drm_map_t *mmio0;
+	drm_map_t *mmio1;
+	drm_map_t *mmio2;
+	drm_map_t *mmio3;
+} drm_gamma_private_t;
+
+#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;						\
+	}								\
+} while (0)
+
+
+extern void gamma_dma_ready(drm_device_t *dev);
+extern void gamma_dma_quiescent_single(drm_device_t *dev);
+extern void gamma_dma_quiescent_dual(drm_device_t *dev);
 
 				/* gamma_dma.c */
 extern int  gamma_dma_schedule(drm_device_t *dev, int locked);
 extern int  gamma_dma(struct inode *inode, struct file *filp,
 		      unsigned int cmd, unsigned long arg);
-extern int  gamma_irq_install(drm_device_t *dev, int irq);
-extern int  gamma_irq_uninstall(drm_device_t *dev);
-extern int  gamma_control(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
 extern int  gamma_find_devices(void);
 extern int  gamma_found(void);
+
+
+#define GAMMA_OFF(reg)						   \
+	((reg < 0x1000)						   \
+	 ? reg							   \
+	 : ((reg < 0x10000)					   \
+	    ? (reg - 0x1000)					   \
+	    : ((reg < 0x11000)					   \
+	       ? (reg - 0x10000)				   \
+	       : (reg - 0x11000))))
+
+#define GAMMA_BASE(reg)	 ((unsigned long)				     \
+			  ((reg < 0x1000)    ? dev_priv->mmio0->handle :     \
+			   ((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)
+#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0)
+
+#define GAMMA_BROADCASTMASK    0x9378
+#define GAMMA_COMMANDINTENABLE 0x0c48
+#define GAMMA_DMAADDRESS       0x0028
+#define GAMMA_DMACOUNT	       0x0030
+#define GAMMA_FILTERMODE       0x8c00
+#define GAMMA_GCOMMANDINTFLAGS 0x0c50
+#define GAMMA_GCOMMANDMODE     0x0c40
+#define GAMMA_GCOMMANDSTATUS   0x0c60
+#define GAMMA_GDELAYTIMER      0x0c38
+#define GAMMA_GDMACONTROL      0x0060
+#define GAMMA_GINTENABLE       0x0808
+#define GAMMA_GINTFLAGS	       0x0810
+#define GAMMA_INFIFOSPACE      0x0018
+#define GAMMA_OUTFIFOWORDS     0x0020
+#define GAMMA_OUTPUTFIFO       0x2000
+#define GAMMA_SYNC	       0x8c40
+#define GAMMA_SYNC_TAG	       0x0188
 
 #endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/i810.h linux/drivers/char/drm/i810.h
--- linux-2.4.8-pre6/drivers/char/drm/i810.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/i810.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,116 @@
+/* i810.h -- Intel i810/i815 DRM template customization -*- linux-c -*-
+ * Created: Thu Feb 15 00:01:12 2001 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __I810_H__
+#define __I810_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) i810_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP		1
+#define __MUST_HAVE_AGP		1
+#define __HAVE_MTRR		1
+#define __HAVE_CTX_BITMAP	1
+
+/* Driver customization:
+ */
+#define __HAVE_RELEASE		1
+#define DRIVER_RELEASE() do {						\
+	i810_reclaim_buffers( dev, priv->pid );				\
+} while (0)
+
+/* DMA customization:
+ */
+#define __HAVE_DMA		1
+#define __HAVE_DMA_QUEUE	1
+#define __HAVE_DMA_WAITLIST	1
+#define __HAVE_DMA_RECLAIM	1
+
+#define __HAVE_DMA_QUIESCENT	1
+#define DRIVER_DMA_QUIESCENT() do {					\
+	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)
+
+/* Buffer customization:
+ */
+
+#define DRIVER_BUF_PRIV_T	drm_i810_buf_priv_t
+
+#define DRIVER_AGP_BUFFERS_MAP( dev )					\
+	((drm_i810_private_t *)((dev)->dev_private))->buffer_map
+
+#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/i810_bufs.c linux/drivers/char/drm/i810_bufs.c
--- linux-2.4.8-pre6/drivers/char/drm/i810_bufs.c	Mon Jul 16 15:13:32 2001
+++ linux/drivers/char/drm/i810_bufs.c	Wed Dec 31 16:00:00 1969
@@ -1,339 +0,0 @@
-/* i810_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
- * Created: Thu Jan 6 01:47:26 2000 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * 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>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- * 
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include "i810_drv.h"
-#include "linux/un.h"
-
-int i810_addbufs_agp(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_device_dma_t *dma = dev->dma;
-	drm_buf_desc_t request;
-	drm_buf_entry_t *entry;
-	drm_buf_t *buf;
-	unsigned long offset;
-	unsigned long agp_offset;
-	int count;
-	int order;
-	int size;
-	int alignment;
-	int page_order;
-	int total;
-	int byte_count;
-	int i;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	count = request.count;
-	order = drm_order(request.size);
-	size	= 1 << order;
-	agp_offset = request.agp_start;
-	alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
-	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-	total = PAGE_SIZE << page_order;
-	byte_count = 0;
-   
-	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-	if (dev->queue_count) return -EBUSY; /* Not while in use */
-	spin_lock(&dev->count_lock);
-	if (dev->buf_use) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	atomic_inc(&dev->buf_alloc);
-	spin_unlock(&dev->count_lock);
-   
-	down(&dev->struct_sem);
-	entry = &dma->bufs[order];
-	if (entry->buf_count) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM; /* May only call once for each order */
-	}
-
-	if(count < 0 || count > 4096)
-	{
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -EINVAL;
-	}
-	   
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
-	if (!entry->buflist) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;
-	}
-	memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-   
-	entry->buf_size   = size;
-	entry->page_order = page_order;
-	offset = 0;
-   
-	while(entry->buf_count < count) {
-		buf = &entry->buflist[entry->buf_count];
-		buf->idx = dma->buf_count + entry->buf_count;
-		buf->total = alignment;
-		buf->order = order;
-		buf->used = 0;
-		buf->offset = offset;
-		buf->bus_address = dev->agp->base + agp_offset + offset;
-		buf->address = (void *)(agp_offset + offset + dev->agp->base);
-		buf->next = NULL;
-		buf->waiting = 0;
-		buf->pending = 0;
-		init_waitqueue_head(&buf->dma_wait);
-		buf->pid = 0;
-
-		buf->dev_private = drm_alloc(sizeof(drm_i810_buf_priv_t), 
-					     DRM_MEM_BUFS);
-		buf->dev_priv_size = sizeof(drm_i810_buf_priv_t);
-	   	memset(buf->dev_private, 0, sizeof(drm_i810_buf_priv_t));
-
-#if DRM_DMA_HISTOGRAM
-		buf->time_queued = 0;
-		buf->time_dispatched = 0;
-		buf->time_completed = 0;
-		buf->time_freed = 0;
-#endif
-		offset = offset + alignment;
-		entry->buf_count++;
-		byte_count += PAGE_SIZE << page_order;
-      
-		DRM_DEBUG("buffer %d @ %p\n",
-			  entry->buf_count, buf->address);
-	}
-   
-	dma->buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist),
-				   DRM_MEM_BUFS);
-	for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
-		dma->buflist[i] = &entry->buflist[i - dma->buf_count];
-   
-	dma->buf_count  += entry->buf_count;
-	dma->byte_count += byte_count;
-	drm_freelist_create(&entry->freelist, entry->buf_count);
-	for (i = 0; i < entry->buf_count; i++) {
-		drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
-	}
-   
-	up(&dev->struct_sem);
-   
-	request.count = entry->buf_count;
-	request.size  = size;
-   
-	if (copy_to_user((drm_buf_desc_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-   
-	atomic_dec(&dev->buf_alloc);
-	dma->flags = _DRM_DMA_USE_AGP;
-	return 0;
-}
-
-int i810_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
-{
-	drm_buf_desc_t	 request;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	if(request.flags & _DRM_AGP_BUFFER)
-		return i810_addbufs_agp(inode, filp, cmd, arg);
-	else
-		return -EINVAL;
-}
-
-int i810_infobufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_info_t	 request;
-	int		 i;
-	int		 count;
-
-	if (!dma) return -EINVAL;
-
-	spin_lock(&dev->count_lock);
-	if (atomic_read(&dev->buf_alloc)) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	++dev->buf_use;		/* Can't allocate more after this call */
-	spin_unlock(&dev->count_lock);
-
-	if (copy_from_user(&request,
-			   (drm_buf_info_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
-		if (dma->bufs[i].buf_count) ++count;
-	}
-	
-	DRM_DEBUG("count = %d\n", count);
-	
-	if (request.count >= count) {
-		for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
-			if (dma->bufs[i].buf_count) {
-				if (copy_to_user(&request.list[count].count,
-						 &dma->bufs[i].buf_count,
-						 sizeof(dma->bufs[0]
-							.buf_count)) ||
-				    copy_to_user(&request.list[count].size,
-						 &dma->bufs[i].buf_size,
-						 sizeof(dma->bufs[0].buf_size)) ||
-				    copy_to_user(&request.list[count].low_mark,
-						 &dma->bufs[i]
-						 .freelist.low_mark,
-						 sizeof(dma->bufs[0]
-							.freelist.low_mark)) ||
-				    copy_to_user(&request.list[count]
-						 .high_mark,
-						 &dma->bufs[i]
-						 .freelist.high_mark,
-						 sizeof(dma->bufs[0]
-							.freelist.high_mark)))
-					return -EFAULT;
-
-				DRM_DEBUG("%d %d %d %d %d\n",
-					  i,
-					  dma->bufs[i].buf_count,
-					  dma->bufs[i].buf_size,
-					  dma->bufs[i].freelist.low_mark,
-					  dma->bufs[i].freelist.high_mark);
-				++count;
-			}
-		}
-	}
-	request.count = count;
-
-	if (copy_to_user((drm_buf_info_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-	
-	return 0;
-}
-
-int i810_markbufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_desc_t	 request;
-	int		 order;
-	drm_buf_entry_t	 *entry;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	DRM_DEBUG("%d, %d, %d\n",
-		  request.size, request.low_mark, request.high_mark);
-	order = drm_order(request.size);
-	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-	entry = &dma->bufs[order];
-
-	if (request.low_mark < 0 || request.low_mark > entry->buf_count)
-		return -EINVAL;
-	if (request.high_mark < 0 || request.high_mark > entry->buf_count)
-		return -EINVAL;
-
-	entry->freelist.low_mark  = request.low_mark;
-	entry->freelist.high_mark = request.high_mark;
-	
-	return 0;
-}
-
-int i810_freebufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_free_t	 request;
-	int		 i;
-	int		 idx;
-	drm_buf_t	 *buf;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_free_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	DRM_DEBUG("%d\n", request.count);
-	for (i = 0; i < request.count; i++) {
-		if (copy_from_user(&idx,
-				   &request.list[i],
-				   sizeof(idx)))
-			return -EFAULT;
-		if (idx < 0 || idx >= dma->buf_count) {
-			DRM_ERROR("Index %d (of %d max)\n",
-				  idx, dma->buf_count - 1);
-			return -EINVAL;
-		}
-		buf = dma->buflist[idx];
-		if (buf->pid != current->pid) {
-			DRM_ERROR("Process %d freeing buffer owned by %d\n",
-				  current->pid, buf->pid);
-			return -EINVAL;
-		}
-		drm_free_buffer(dev, buf);
-	}
-	
-	return 0;
-}
-
diff -urN linux-2.4.8-pre6/drivers/char/drm/i810_context.c linux/drivers/char/drm/i810_context.c
--- linux-2.4.8-pre6/drivers/char/drm/i810_context.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/char/drm/i810_context.c	Wed Dec 31 16:00:00 1969
@@ -1,212 +0,0 @@
-/* i810_context.c -- IOCTLs for i810 contexts -*- linux-c -*-
- * Created: Mon Dec 13 09:51:35 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>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include "i810_drv.h"
-
-static int i810_alloc_queue(drm_device_t *dev)
-{
-   	int temp = drm_ctxbitmap_next(dev);
-   	DRM_DEBUG("i810_alloc_queue: %d\n", temp);
-	return temp;
-}
-
-int i810_context_switch(drm_device_t *dev, int old, int new)
-{
-        char        buf[64];
-
-        atomic_inc(&dev->total_ctx);
-
-        if (test_and_set_bit(0, &dev->context_flag)) {
-                DRM_ERROR("Reentering -- FIXME\n");
-                return -EBUSY;
-        }
-
-#if DRM_DMA_HISTOGRAM
-        dev->ctx_start = get_cycles();
-#endif
-        
-        DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
-        if (new == dev->last_context) {
-                clear_bit(0, &dev->context_flag);
-                return 0;
-        }
-        
-        if (drm_flags & DRM_FLAG_NOCTX) {
-                i810_context_switch_complete(dev, new);
-        } else {
-                sprintf(buf, "C %d %d\n", old, new);
-                drm_write_string(dev, buf);
-        }
-        
-        return 0;
-}
-
-int i810_context_switch_complete(drm_device_t *dev, int new)
-{
-        dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
-        dev->last_switch  = jiffies;
-        
-        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-                DRM_ERROR("Lock isn't held after context switch\n");
-        }
-
-				/* If a context switch is ever initiated
-                                   when the kernel holds the lock, release
-                                   that lock here. */
-#if DRM_DMA_HISTOGRAM
-        atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
-                                                      - dev->ctx_start)]);
-                   
-#endif
-        clear_bit(0, &dev->context_flag);
-        wake_up(&dev->context_wait);
-        
-        return 0;
-}
-
-int i810_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
-{
-	drm_ctx_res_t	res;
-	drm_ctx_t	ctx;
-	int		i;
-
-	DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
-	if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
-		return -EFAULT;
-	if (res.count >= DRM_RESERVED_CONTEXTS) {
-		memset(&ctx, 0, sizeof(ctx));
-		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-			ctx.handle = i;
-			if (copy_to_user(&res.contexts[i],
-					 &i,
-					 sizeof(i)))
-				return -EFAULT;
-		}
-	}
-	res.count = DRM_RESERVED_CONTEXTS;
-	if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
-		return -EFAULT;
-	return 0;
-}
-
-int i810_addctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	if ((ctx.handle = i810_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
-				/* Skip kernel's context and get a new one. */
-		ctx.handle = i810_alloc_queue(dev);
-	}
-        if (ctx.handle == -1) {
-		DRM_DEBUG("Not enough free contexts.\n");
-				/* Should this return -EBUSY instead? */
-		return -ENOMEM;
-	}
-	DRM_DEBUG("%d\n", ctx.handle);
-	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int i810_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	unsigned long arg)
-{
-   	/* This does nothing for the i810 */
-	return 0;
-}
-
-int i810_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	unsigned long arg)
-{
-	drm_ctx_t ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
-		return -EFAULT;
-	/* This is 0, because we don't hanlde any context flags */
-	ctx.flags = 0;
-	if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int i810_switchctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	return i810_context_switch(dev, dev->last_context, ctx.handle);
-}
-
-int i810_newctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	i810_context_switch_complete(dev, ctx.handle);
-
-	return 0;
-}
-
-int i810_rmctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-   	if(ctx.handle != DRM_KERNEL_CONTEXT) {
-	   	drm_ctxbitmap_free(dev, ctx.handle);
-	}
-	
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/i810_dma.c linux/drivers/char/drm/i810_dma.c
--- linux-2.4.8-pre6/drivers/char/drm/i810_dma.c	Mon Jul 16 15:13:32 2001
+++ linux/drivers/char/drm/i810_dma.c	Mon Dec  3 22:59:45 2001
@@ -11,11 +11,11 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the next
  * paragraph) shall be included in all copies or substantial portions of the
  * Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
@@ -31,6 +31,7 @@
  */
 
 #define __NO_VERSION__
+#include "i810.h"
 #include "drmP.h"
 #include "i810_drv.h"
 #include <linux/interrupt.h>	/* For task queue support */
@@ -47,17 +48,6 @@
 #define I810_BUF_UNMAPPED 0
 #define I810_BUF_MAPPED   1
 
-#define I810_REG(reg)		2
-#define I810_BASE(reg)		((unsigned long) \
-				dev->maplist[I810_REG(reg)]->handle)
-#define I810_ADDR(reg)		(I810_BASE(reg) + reg)
-#define I810_DEREF(reg)		*(__volatile__ int *)I810_ADDR(reg)
-#define I810_READ(reg)		I810_DEREF(reg)
-#define I810_WRITE(reg,val) 	do { I810_DEREF(reg) = val; } while (0)
-#define I810_DEREF16(reg)	*(__volatile__ u16 *)I810_ADDR(reg)
-#define I810_READ16(reg)	I810_DEREF16(reg)
-#define I810_WRITE16(reg,val)	do { I810_DEREF16(reg) = val; } while (0)
-
 #define RING_LOCALS	unsigned int outring, ringmask; volatile char *virt;
 
 #define BEGIN_LP_RING(n) do {				\
@@ -107,14 +97,14 @@
    	drm_device_dma_t *dma = dev->dma;
 	int		 i;
    	int 		 used;
-   
+
 	/* Linear search might not be the best solution */
 
    	for (i = 0; i < dma->buf_count; i++) {
 	   	drm_buf_t *buf = dma->buflist[ i ];
 	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 		/* In use is already a pointer */
-	   	used = cmpxchg(buf_priv->in_use, I810_BUF_FREE, 
+	   	used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
 			       I810_BUF_CLIENT);
 	   	if(used == I810_BUF_FREE) {
 			return buf;
@@ -131,26 +121,26 @@
 {
    	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
    	int used;
-   
+
    	/* In use is already a pointer */
    	used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
    	if(used != I810_BUF_CLIENT) {
 	   	DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
 	   	return -EINVAL;
 	}
-   
+
    	return 0;
 }
 
 static struct file_operations i810_buffer_fops = {
-	open:	 i810_open,
-	flush:	 drm_flush,
-	release: i810_release,
-	ioctl:	 i810_ioctl,
+	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,
+	read:	 DRM(read),
+	fasync:	 DRM(fasync),
+      	poll:	 DRM(poll),
 };
 
 int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
@@ -166,10 +156,10 @@
 	dev_priv = dev->dev_private;
 	buf      = dev_priv->mmap_buffer;
 	buf_priv = buf->dev_private;
-   
+
 	vma->vm_flags |= (VM_IO | VM_DONTCOPY);
 	vma->vm_file = filp;
-   
+
    	buf_priv->currently_mapped = I810_BUF_MAPPED;
 	unlock_kernel();
 
@@ -192,13 +182,17 @@
 	if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
 
 	if(VM_DONTCOPY != 0) {
-		down_write(&current->mm->mmap_sem);
+#if LINUX_VERSION_CODE <= 0x020402
+		down( &current->mm->mmap_sem );
+#else
+		down_write( &current->mm->mmap_sem );
+#endif
 		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, 
+		buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
 						    PROT_READ|PROT_WRITE,
-						    MAP_SHARED, 
+						    MAP_SHARED,
 						    buf->bus_address);
 		dev_priv->mmap_buffer = NULL;
    		filp->f_op = old_fops;
@@ -208,7 +202,11 @@
 			retcode = (signed int)buf_priv->virtual;
 			buf_priv->virtual = 0;
 		}
-   		up_write(&current->mm->mmap_sem);
+#if LINUX_VERSION_CODE <= 0x020402
+		up( &current->mm->mmap_sem );
+#else
+		up_write( &current->mm->mmap_sem );
+#endif
 	} else {
 		buf_priv->virtual = buf_priv->kernel_virtual;
    		buf_priv->currently_mapped = I810_BUF_MAPPED;
@@ -222,18 +220,26 @@
 	int retcode = 0;
 
 	if(VM_DONTCOPY != 0) {
-		if(buf_priv->currently_mapped != I810_BUF_MAPPED) 
+		if(buf_priv->currently_mapped != I810_BUF_MAPPED)
 			return -EINVAL;
-		down_write(&current->mm->mmap_sem);
+#if LINUX_VERSION_CODE <= 0x020402
+		down( &current->mm->mmap_sem );
+#else
+		down_write( &current->mm->mmap_sem );
+#endif
 #if LINUX_VERSION_CODE < 0x020399
-        	retcode = do_munmap((unsigned long)buf_priv->virtual, 
+        	retcode = do_munmap((unsigned long)buf_priv->virtual,
 				    (size_t) buf->total);
 #else
-        	retcode = do_munmap(current->mm, 
-				    (unsigned long)buf_priv->virtual, 
+        	retcode = do_munmap(current->mm,
+				    (unsigned long)buf_priv->virtual,
 				    (size_t) buf->total);
 #endif
-   		up_write(&current->mm->mmap_sem);
+#if LINUX_VERSION_CODE <= 0x020402
+		up( &current->mm->mmap_sem );
+#else
+		up_write( &current->mm->mmap_sem );
+#endif
 	}
    	buf_priv->currently_mapped = I810_BUF_UNMAPPED;
    	buf_priv->virtual = 0;
@@ -241,7 +247,7 @@
 	return retcode;
 }
 
-static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, 
+static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
 			       struct file *filp)
 {
 	drm_file_t	  *priv	  = filp->private_data;
@@ -255,7 +261,7 @@
 	   	DRM_DEBUG("retcode=%d\n", retcode);
 		return retcode;
 	}
-   
+
 	retcode = i810_map_buffer(buf, filp);
 	if(retcode) {
 		i810_freelist_put(dev, buf);
@@ -263,7 +269,7 @@
 		return retcode;
 	}
 	buf->pid     = priv->pid;
-	buf_priv = buf->dev_private;	
+	buf_priv = buf->dev_private;
 	d->granted = 1;
    	d->request_idx = buf->idx;
    	d->request_size = buf->total;
@@ -275,22 +281,22 @@
 static unsigned long i810_alloc_page(drm_device_t *dev)
 {
 	unsigned long address;
-   
+
 	address = __get_free_page(GFP_KERNEL);
-	if(address == 0UL) 
+	if(address == 0UL)
 		return 0;
-	
+
 	atomic_inc(&virt_to_page(address)->count);
 	set_bit(PG_locked, &virt_to_page(address)->flags);
-   
+
 	return address;
 }
 
 static void i810_free_page(drm_device_t *dev, unsigned long page)
 {
-	if(page == 0UL) 
+	if(page == 0UL)
 		return;
-	
+
 	atomic_dec(&virt_to_page(page)->count);
 	clear_bit(PG_locked, &virt_to_page(page)->flags);
 	wake_up(&virt_to_page(page)->wait);
@@ -304,26 +310,26 @@
 
 	if(dev->dev_private) {
 		int i;
-	   	drm_i810_private_t *dev_priv = 
+	   	drm_i810_private_t *dev_priv =
 	     		(drm_i810_private_t *) dev->dev_private;
-	   
+
 	   	if(dev_priv->ring.virtual_start) {
-		   	drm_ioremapfree((void *) dev_priv->ring.virtual_start,
-					dev_priv->ring.Size);
+		   	DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
+					 dev_priv->ring.Size);
 		}
 	   	if(dev_priv->hw_status_page != 0UL) {
 		   	i810_free_page(dev, dev_priv->hw_status_page);
 		   	/* Need to rewrite hardware status page */
 		   	I810_WRITE(0x02080, 0x1ffff000);
 		}
-	   	drm_free(dev->dev_private, sizeof(drm_i810_private_t), 
+	   	DRM(free)(dev->dev_private, sizeof(drm_i810_private_t),
 			 DRM_MEM_DRIVER);
 	   	dev->dev_private = NULL;
 
 		for (i = 0; i < dma->buf_count; i++) {
 			drm_buf_t *buf = dma->buflist[ i ];
 			drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-			drm_ioremapfree(buf_priv->kernel_virtual, buf->total);
+			DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total);
 		}
 	}
    	return 0;
@@ -340,14 +346,14 @@
 	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;
-	   
+
 		if (ring->head != last_head)
 		   end = jiffies + (HZ*3);
-	  
+
 	   	iters++;
 		if((signed)(end - jiffies) <= 0) {
 		   	DRM_ERROR("space: %d wanted %d\n", ring->space, n);
@@ -358,7 +364,7 @@
 	   	for (i = 0 ; i < 2000 ; i++) ;
 	}
 
-out_wait_ring:   
+out_wait_ring:
    	return iters;
 }
 
@@ -366,21 +372,20 @@
 {
       	drm_i810_private_t *dev_priv = dev->dev_private;
    	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
-      
+
    	ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
      	ring->tail = I810_READ(LP_RING + RING_TAIL);
      	ring->space = ring->head - (ring->tail+8);
      	if (ring->space < 0) ring->space += ring->Size;
 }
 
-static int i810_freelist_init(drm_device_t *dev)
+static int i810_freelist_init(drm_device_t *dev, drm_i810_private_t *dev_priv)
 {
       	drm_device_dma_t *dma = dev->dma;
-   	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
    	int my_idx = 24;
    	u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
    	int i;
-   
+
    	if(dma->buf_count > 1019) {
 	   	/* Not enough space in the status page for the freelist */
 	   	return -EINVAL;
@@ -389,62 +394,82 @@
    	for (i = 0; i < dma->buf_count; i++) {
 	   	drm_buf_t *buf = dma->buflist[ i ];
 	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-	   
+
 	   	buf_priv->in_use = hw_status++;
 	   	buf_priv->my_use_idx = my_idx;
 	   	my_idx += 4;
 
 	   	*buf_priv->in_use = I810_BUF_FREE;
 
-		buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, 
-						       buf->total);
+		buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address,
+							buf->total);
 	}
 	return 0;
 }
 
-static int i810_dma_initialize(drm_device_t *dev, 
+static int i810_dma_initialize(drm_device_t *dev,
 			       drm_i810_private_t *dev_priv,
 			       drm_i810_init_t *init)
 {
-	drm_map_t *sarea_map;
+	struct list_head *list;
 
-   	dev->dev_private = (void *) dev_priv;
    	memset(dev_priv, 0, sizeof(drm_i810_private_t));
 
-   	if (init->ring_map_idx >= dev->map_count ||
-	    init->buffer_map_idx >= dev->map_count) {
+	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_map = r_list->map;
+ 			break;
+ 		}
+ 	}
+	if(!dev_priv->sarea_map) {
+		dev->dev_private = (void *)dev_priv;
 	   	i810_dma_cleanup(dev);
-	   	DRM_ERROR("ring_map or buffer_map are invalid\n");
+	   	DRM_ERROR("can not find sarea!\n");
 	   	return -EINVAL;
 	}
-   
-   	dev_priv->ring_map_idx = init->ring_map_idx;
-   	dev_priv->buffer_map_idx = init->buffer_map_idx;
-	sarea_map = dev->maplist[0];
-	dev_priv->sarea_priv = (drm_i810_sarea_t *) 
-		((u8 *)sarea_map->handle + 
+	DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
+	if(!dev_priv->mmio_map) {
+		dev->dev_private = (void *)dev_priv;
+	   	i810_dma_cleanup(dev);
+	   	DRM_ERROR("can not find mmio map!\n");
+	   	return -EINVAL;
+	}
+	DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
+	if(!dev_priv->buffer_map) {
+		dev->dev_private = (void *)dev_priv;
+	   	i810_dma_cleanup(dev);
+	   	DRM_ERROR("can not find dma buffer map!\n");
+	   	return -EINVAL;
+	}
+
+	dev_priv->sarea_priv = (drm_i810_sarea_t *)
+		((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;
 
-   	dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + 
-						   init->ring_start, 
-						   init->ring_size);
+   	dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base +
+						    init->ring_start,
+						    init->ring_size);
 
-   	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-   
    	if (dev_priv->ring.virtual_start == NULL) {
+		dev->dev_private = (void *) dev_priv;
 	   	i810_dma_cleanup(dev);
 	   	DRM_ERROR("can not ioremap virtual address for"
 			  " ring buffer\n");
 	   	return -ENOMEM;
 	}
 
+   	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
 	dev_priv->w = init->w;
 	dev_priv->h = init->h;
 	dev_priv->pitch = init->pitch;
@@ -454,28 +479,31 @@
 	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;
-	
-   
+
    	/* Program Hardware Status Page */
    	dev_priv->hw_status_page = i810_alloc_page(dev);
-   	memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
    	if(dev_priv->hw_status_page == 0UL) {
+		dev->dev_private = (void *)dev_priv;
 		i810_dma_cleanup(dev);
 		DRM_ERROR("Can not allocate hardware status page\n");
 		return -ENOMEM;
 	}
+   	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, virt_to_bus((void *)dev_priv->hw_status_page));
    	DRM_DEBUG("Enabled hardware status page\n");
-   
+
    	/* Now we need to init our freelist */
-   	if(i810_freelist_init(dev) != 0) {
+   	if(i810_freelist_init(dev, dev_priv) != 0) {
+		dev->dev_private = (void *)dev_priv;
 	   	i810_dma_cleanup(dev);
 	   	DRM_ERROR("Not enough space in the status page for"
 			  " the freelist\n");
 	   	return -ENOMEM;
 	}
+	dev->dev_private = (void *)dev_priv;
+
    	return 0;
 }
 
@@ -487,13 +515,13 @@
    	drm_i810_private_t *dev_priv;
    	drm_i810_init_t init;
    	int retcode = 0;
-	
+
   	if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init)))
 		return -EFAULT;
-	
+
    	switch(init.func) {
 	 	case I810_INIT_DMA:
-	   		dev_priv = drm_alloc(sizeof(drm_i810_private_t), 
+	   		dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
 					     DRM_MEM_DRIVER);
 	   		if(dev_priv == NULL) return -ENOMEM;
 	   		retcode = i810_dma_initialize(dev, dev_priv, &init);
@@ -505,7 +533,7 @@
 	   		retcode = -EINVAL;
 	   	break;
 	}
-   
+
    	return retcode;
 }
 
@@ -517,9 +545,9 @@
  * 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 ) 
-{	
+static void i810EmitContextVerified( drm_device_t *dev,
+				     volatile unsigned int *code )
+{
    	drm_i810_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	unsigned int tmp;
@@ -537,22 +565,22 @@
 		tmp = code[i];
 
 		if ((tmp & (7<<29)) == (3<<29) &&
-		    (tmp & (0x1f<<24)) < (0x1d<<24)) 
+		    (tmp & (0x1f<<24)) < (0x1d<<24))
 		{
-			OUT_RING( tmp ); 
+			OUT_RING( tmp );
 			j++;
-		} 
+		}
 	}
 
-	if (j & 1) 
-		OUT_RING( 0 ); 
+	if (j & 1)
+		OUT_RING( 0 );
 
 	ADVANCE_LP_RING();
 }
 
-static void i810EmitTexVerified( drm_device_t *dev, 
-				 volatile unsigned int *code ) 
-{	
+static void i810EmitTexVerified( drm_device_t *dev,
+				 volatile unsigned int *code )
+{
    	drm_i810_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	unsigned int tmp;
@@ -569,15 +597,15 @@
 		tmp = code[i];
 
 		if ((tmp & (7<<29)) == (3<<29) &&
-		    (tmp & (0x1f<<24)) < (0x1d<<24)) 
+		    (tmp & (0x1f<<24)) < (0x1d<<24))
 		{
-			OUT_RING( tmp ); 
+			OUT_RING( tmp );
 			j++;
 		}
-	} 
-		
-	if (j & 1) 
-		OUT_RING( 0 ); 
+	}
+
+	if (j & 1)
+		OUT_RING( 0 );
 
 	ADVANCE_LP_RING();
 }
@@ -585,9 +613,9 @@
 
 /* Need to do some additional checking when setting the dest buffer.
  */
-static void i810EmitDestVerified( drm_device_t *dev, 
-				  volatile unsigned int *code ) 
-{	
+static void i810EmitDestVerified( drm_device_t *dev,
+				  volatile unsigned int *code )
+{
    	drm_i810_private_t *dev_priv = dev->dev_private;
 	unsigned int tmp;
 	RING_LOCALS;
@@ -651,9 +679,9 @@
 
 
 
-/* need to verify 
+/* need to verify
  */
-static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, 
+static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
 				     unsigned int clear_color,
 				     unsigned int clear_zval )
 {
@@ -684,10 +712,10 @@
 		    pbox->y2 > dev_priv->h)
 			continue;
 
-	   	if ( flags & I810_FRONT ) {	    
+	   	if ( flags & I810_FRONT ) {
 		   	DRM_DEBUG("clear front\n");
-			BEGIN_LP_RING( 6 );	    
-			OUT_RING( BR00_BITBLT_CLIENT | 
+			BEGIN_LP_RING( 6 );
+			OUT_RING( BR00_BITBLT_CLIENT |
 				  BR00_OP_COLOR_BLT | 0x3 );
 			OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
 			OUT_RING( (height << 16) | width );
@@ -699,8 +727,8 @@
 
 		if ( flags & I810_BACK ) {
 			DRM_DEBUG("clear back\n");
-			BEGIN_LP_RING( 6 );	    
-			OUT_RING( BR00_BITBLT_CLIENT | 
+			BEGIN_LP_RING( 6 );
+			OUT_RING( BR00_BITBLT_CLIENT |
 				  BR00_OP_COLOR_BLT | 0x3 );
 			OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
 			OUT_RING( (height << 16) | width );
@@ -712,8 +740,8 @@
 
 		if ( flags & I810_DEPTH ) {
 			DRM_DEBUG("clear depth\n");
-			BEGIN_LP_RING( 6 );	    
-			OUT_RING( BR00_BITBLT_CLIENT | 
+			BEGIN_LP_RING( 6 );
+			OUT_RING( BR00_BITBLT_CLIENT |
 				  BR00_OP_COLOR_BLT | 0x3 );
 			OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
 			OUT_RING( (height << 16) | width );
@@ -744,7 +772,7 @@
       	if (nbox > I810_NR_SAREA_CLIPRECTS)
      		nbox = I810_NR_SAREA_CLIPRECTS;
 
-	for (i = 0 ; i < nbox; i++, pbox++) 
+	for (i = 0 ; i < nbox; i++, pbox++)
 	{
 		unsigned int w = pbox->x2 - pbox->x1;
 		unsigned int h = pbox->y2 - pbox->y1;
@@ -756,7 +784,7 @@
 		    pbox->x2 > dev_priv->w ||
 		    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);
@@ -766,14 +794,14 @@
 		OUT_RING( pitch | (0xCC << 16));
 		OUT_RING( (h << 16) | (w * cpp));
 		OUT_RING( dst );
-		OUT_RING( pitch );	
+		OUT_RING( pitch );
 		OUT_RING( start );
 		ADVANCE_LP_RING();
 	}
 }
 
 
-static void i810_dma_dispatch_vertex(drm_device_t *dev, 
+static void i810_dma_dispatch_vertex(drm_device_t *dev,
 				     drm_buf_t *buf,
 				     int discard,
 				     int used)
@@ -784,30 +812,30 @@
    	drm_clip_rect_t *box = sarea_priv->boxes;
    	int nbox = sarea_priv->nbox;
 	unsigned long address = (unsigned long)buf->bus_address;
-	unsigned long start = address - dev->agp->base;     
+	unsigned long start = address - dev->agp->base;
 	int i = 0, u;
    	RING_LOCALS;
 
    	i810_kernel_lost_context(dev);
 
-   	if (nbox > I810_NR_SAREA_CLIPRECTS) 
+   	if (nbox > I810_NR_SAREA_CLIPRECTS)
 		nbox = I810_NR_SAREA_CLIPRECTS;
 
 	if (discard) {
-		u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, 
+		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) 
+	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", 
+  	DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
 		  address, used, nbox);
 
    	dev_priv->counter++;
@@ -821,7 +849,7 @@
 		*(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
 					     sarea_priv->vertex_prim |
 					     ((used/4)-2));
-		
+
 		if (used & 4) {
 			*(u32 *)((u32)buf_priv->virtual + used) = 0;
 			used += 4;
@@ -829,26 +857,26 @@
 
 		i810_unmap_buffer(buf);
 	}
-		   
+
 	if (used) {
 		do {
 			if (i < nbox) {
 				BEGIN_LP_RING(4);
-				OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | 
+				OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
 					  SC_ENABLE );
 				OUT_RING( GFX_OP_SCISSOR_INFO );
 				OUT_RING( box[i].x1 | (box[i].y1<<16) );
 				OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
 				ADVANCE_LP_RING();
 			}
-			
+
 			BEGIN_LP_RING(4);
 			OUT_RING( CMD_OP_BATCH_BUFFER );
 			OUT_RING( start | BB1_PROTECTED );
 			OUT_RING( start + used - 4 );
 			OUT_RING( 0 );
 			ADVANCE_LP_RING();
-			
+
 		} while (++i < nbox);
 	}
 
@@ -872,24 +900,25 @@
 
 
 /* Interrupts are only for flushing */
-static void i810_dma_service(int irq, void *device, struct pt_regs *regs)
+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->total_irq);
+
+	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, 
+   	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);
 }
 
-static void i810_dma_task_queue(void *device)
+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;
@@ -898,129 +927,6 @@
    	wake_up_interruptible(&dev_priv->flush_queue);
 }
 
-int i810_irq_install(drm_device_t *dev, int irq)
-{
-	int retcode;
-	u16 temp;
-   
-	if (!irq)     return -EINVAL;
-	
-	down(&dev->struct_sem);
-	if (dev->irq) {
-		up(&dev->struct_sem);
-		return -EBUSY;
-	}
-	dev->irq = irq;
-	up(&dev->struct_sem);
-	
-   	DRM_DEBUG(  "Interrupt Install : %d\n", irq);
-	DRM_DEBUG("%d\n", irq);
-
-	dev->context_flag     = 0;
-	dev->interrupt_flag   = 0;
-	dev->dma_flag	      = 0;
-	
-	dev->dma->next_buffer = NULL;
-	dev->dma->next_queue  = NULL;
-	dev->dma->this_buffer = NULL;
-
-	INIT_LIST_HEAD(&dev->tq.list);
-	dev->tq.sync	      = 0;
-	dev->tq.routine	      = i810_dma_task_queue;
-	dev->tq.data	      = dev;
-
-				/* Before installing handler */
-   	temp = I810_READ16(I810REG_HWSTAM);
-   	temp = temp & 0x6000;
-   	I810_WRITE16(I810REG_HWSTAM, temp);
-   	
-      	temp = I810_READ16(I810REG_INT_MASK_R);
-   	temp = temp & 0x6000;
-   	I810_WRITE16(I810REG_INT_MASK_R, temp); /* Unmask interrupts */
-   	temp = I810_READ16(I810REG_INT_ENABLE_R);
-   	temp = temp & 0x6000;
-      	I810_WRITE16(I810REG_INT_ENABLE_R, temp); /* Disable all interrupts */
-
-				/* Install handler */
-	if ((retcode = request_irq(dev->irq,
-				   i810_dma_service,
-				   SA_SHIRQ,
-				   dev->devname,
-				   dev))) {
-		down(&dev->struct_sem);
-		dev->irq = 0;
-		up(&dev->struct_sem);
-		return retcode;
-	}
-   	temp = I810_READ16(I810REG_INT_ENABLE_R);
-   	temp = temp & 0x6000;
-   	temp = temp | 0x0003;
-   	I810_WRITE16(I810REG_INT_ENABLE_R, 
-		     temp); /* Enable bp & user interrupts */
-	return 0;
-}
-
-int i810_irq_uninstall(drm_device_t *dev)
-{
-	int irq;
-   	u16 temp;
-
-
-/*  	return 0; */
-
-	down(&dev->struct_sem);
-	irq	 = dev->irq;
-	dev->irq = 0;
-	up(&dev->struct_sem);
-	
-	if (!irq) return -EINVAL;
-
-   	DRM_DEBUG(  "Interrupt UnInstall: %d\n", irq);	
-	DRM_DEBUG("%d\n", irq);
-   
-   	temp = I810_READ16(I810REG_INT_IDENTITY_R);
-   	temp = temp & ~(0x6000);
-   	if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, 
-				   temp); /* Clear all interrupts */
-   
-   	temp = I810_READ16(I810REG_INT_ENABLE_R);
-   	temp = temp & 0x6000;
-   	I810_WRITE16(I810REG_INT_ENABLE_R, 
-		     temp);                     /* Disable all interrupts */
-
-   	free_irq(irq, dev);
-
-	return 0;
-}
-
-int i810_control(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_control_t	ctl;
-	int		retcode;
-   
-   	DRM_DEBUG(  "i810_control\n");
-
-	if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
-		return -EFAULT;
-	
-	switch (ctl.func) {
-	case DRM_INST_HANDLER:
-		if ((retcode = i810_irq_install(dev, ctl.irq)))
-			return retcode;
-		break;
-	case DRM_UNINST_HANDLER:
-		if ((retcode = i810_irq_uninstall(dev)))
-			return retcode;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
 static inline void i810_dma_emit_flush(drm_device_t *dev)
 {
    	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1057,11 +963,11 @@
 /*     	wake_up_interruptible(&dev_priv->flush_queue); */
 }
 
-static void i810_dma_quiescent(drm_device_t *dev)
+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;      
+	unsigned long end;
 
    	if(dev_priv == NULL) {
 	   	return;
@@ -1069,7 +975,7 @@
       	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);
@@ -1077,16 +983,16 @@
 		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;
 }
 
@@ -1096,7 +1002,7 @@
   	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
 	unsigned long end;
-   	int i, ret = 0;      
+   	int i, ret = 0;
 
    	if(dev_priv == NULL) {
 	   	return 0;
@@ -1111,14 +1017,14 @@
 		if((signed)(end - jiffies) <= 0) {
 		   	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);
 
@@ -1126,8 +1032,8 @@
    	for (i = 0; i < dma->buf_count; i++) {
 	   	drm_buf_t *buf = dma->buflist[ i ];
 	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-	   
-		int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE, 
+
+		int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
 				   I810_BUF_FREE);
 
 		if (used == I810_BUF_HARDWARE)
@@ -1154,9 +1060,9 @@
 	for (i = 0; i < dma->buf_count; i++) {
 	   	drm_buf_t *buf = dma->buflist[ i ];
 	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-	   
+
 		if (buf->pid == pid && buf_priv) {
-			int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, 
+			int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
 					   I810_BUF_FREE);
 
 			if (used == I810_BUF_CLIENT)
@@ -1167,91 +1073,12 @@
 	}
 }
 
-int i810_lock(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;
-
-	DECLARE_WAITQUEUE(entry, current);
-	int		  ret	= 0;
-	drm_lock_t	  lock;
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-   
-   	DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-		  lock.context, current->pid, dev->lock.hw_lock->lock,
-		  lock.flags);
-
-	if (lock.context < 0) {
-		return -EINVAL;
-	}
-	/* Only one queue:
-	 */
-
-	if (!ret) {
-		add_wait_queue(&dev->lock.lock_queue, &entry);
-		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-			if (!dev->lock.hw_lock) {
-				/* Device has been unregistered */
-				ret = -EINTR;
-				break;
-			}
-			if (drm_lock_take(&dev->lock.hw_lock->lock,
-					  lock.context)) {
-				dev->lock.pid	    = current->pid;
-				dev->lock.lock_time = jiffies;
-				atomic_inc(&dev->total_locks);
-				break;	/* Got lock */
-			}
-			
-				/* Contention */
-			atomic_inc(&dev->total_sleeps);
-		   	DRM_DEBUG("Calling lock schedule\n");
-			schedule();
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				break;
-			}
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&dev->lock.lock_queue, &entry);
-	}
-	
-	if (!ret) {
-		sigemptyset(&dev->sigmask);
-		sigaddset(&dev->sigmask, SIGSTOP);
-		sigaddset(&dev->sigmask, SIGTSTP);
-		sigaddset(&dev->sigmask, SIGTTIN);
-		sigaddset(&dev->sigmask, SIGTTOU);
-		dev->sigdata.context = lock.context;
-		dev->sigdata.lock    = dev->lock.hw_lock;
-		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
-
-		if (lock.flags & _DRM_LOCK_QUIESCENT) {
-		   DRM_DEBUG("_DRM_LOCK_QUIESCENT\n");
-		   DRM_DEBUG("fred\n");
-		   i810_dma_quiescent(dev);
-		}
-	}
-	DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
-	return ret;
-}
-
-int i810_flush_ioctl(struct inode *inode, struct file *filp, 
+int i810_flush_ioctl(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_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");
@@ -1271,8 +1098,8 @@
 	drm_device_dma_t *dma = dev->dma;
    	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_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+     					dev_priv->sarea_priv;
 	drm_i810_vertex_t vertex;
 
 	if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex)))
@@ -1288,15 +1115,15 @@
 
 	if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
 
-	i810_dma_dispatch_vertex( dev, 
-				  dma->buflist[ vertex.idx ], 
+	i810_dma_dispatch_vertex( dev,
+				  dma->buflist[ vertex.idx ],
 				  vertex.discard, vertex.used );
 
-   	atomic_add(vertex.used, &dma->total_bytes);
-	atomic_inc(&dma->total_dmas);
+   	atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
+	atomic_inc(&dev->counts[_DRM_STAT_DMA]);
 	sarea_priv->last_enqueue = dev_priv->counter-1;
    	sarea_priv->last_dispatch = (int) hw_status[5];
-   
+
 	return 0;
 }
 
@@ -1311,14 +1138,19 @@
 
    	if (copy_from_user(&clear, (drm_i810_clear_t *)arg, sizeof(clear)))
 		return -EFAULT;
-   
+
    	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
 		DRM_ERROR("i810_clear_bufs called without lock held\n");
 		return -EINVAL;
 	}
 
-	i810_dma_dispatch_clear( dev, clear.flags, 
-				 clear.clear_color, 
+ 	/* GH: Someone's doing nasty things... */
+ 	if (!dev->dev_private) {
+ 		return -EINVAL;
+ 	}
+
+	i810_dma_dispatch_clear( dev, clear.flags,
+				 clear.clear_color,
 				 clear.clear_depth );
    	return 0;
 }
@@ -1328,7 +1160,7 @@
 {
 	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)) {
@@ -1347,8 +1179,8 @@
 	drm_device_t	  *dev	    = priv->dev;
    	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_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+     					dev_priv->sarea_priv;
 
       	sarea_priv->last_dispatch = (int) hw_status[5];
 	return 0;
@@ -1363,18 +1195,18 @@
 	drm_i810_dma_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_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;
-   
+
 	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
 		DRM_ERROR("i810_dma called without lock held\n");
 		return -EINVAL;
 	}
-	
+
 	d.granted = 0;
 
 	retcode = i810_dma_get_buffer(dev, &d, filp);
@@ -1397,8 +1229,8 @@
 	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_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;
@@ -1407,20 +1239,17 @@
 		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;
+        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;
 
-	/* Stopping end users copying their data to the entire kernel
-	   is good.. */
-	if (d.used < 0 || d.used > buf->total)
-		return -EINVAL;
-		
+	if(d.used < 0 || d.used > buf->total) return -EINVAL;
+
    	if (copy_from_user(buf_priv->virtual, d.address, d.used))
 		return -EFAULT;
 
diff -urN linux-2.4.8-pre6/drivers/char/drm/i810_drm.h linux/drivers/char/drm/i810_drm.h
--- linux-2.4.8-pre6/drivers/char/drm/i810_drm.h	Fri Jul 21 12:56:44 2000
+++ linux/drivers/char/drm/i810_drm.h	Mon Dec  3 22:59:45 2001
@@ -98,8 +98,13 @@
 		I810_INIT_DMA = 0x01,
 		I810_CLEANUP_DMA = 0x02
 	} func;
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
 	int ring_map_idx;
 	int buffer_map_idx;
+#else
+	unsigned int mmio_offset;
+	unsigned int buffers_offset;
+#endif
 	int sarea_priv_offset;
 	unsigned int ring_start;
 	unsigned int ring_end;
diff -urN linux-2.4.8-pre6/drivers/char/drm/i810_drv.c linux/drivers/char/drm/i810_drv.c
--- linux-2.4.8-pre6/drivers/char/drm/i810_drv.c	Thu Nov 16 14:05:49 2000
+++ linux/drivers/char/drm/i810_drv.c	Mon Dec  3 22:59:45 2001
@@ -19,630 +19,84 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
- *	    Jeff Hartmann <jhartmann@valinux.com>
+ * 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>
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include <linux/config.h>
+#include "i810.h"
 #include "drmP.h"
 #include "i810_drv.h"
 
-#define I810_NAME	 "i810"
-#define I810_DESC	 "Intel I810"
-#define I810_DATE	 "20000928"
-#define I810_MAJOR	 1
-#define I810_MINOR	 1
-#define I810_PATCHLEVEL	 0
-
-static drm_device_t	      i810_device;
-drm_ctx_t		      i810_res_ctx;
-
-static struct file_operations i810_fops = {
-#if LINUX_VERSION_CODE >= 0x020400
-				/* This started being used during 2.4.0-test */
-	owner:   THIS_MODULE,
-#endif
-	open:	 i810_open,
-	flush:	 drm_flush,
-	release: i810_release,
-	ioctl:	 i810_ioctl,
-	mmap:	 drm_mmap,
-	read:	 drm_read,
-	fasync:	 drm_fasync,
-      	poll:	 drm_poll,
-};
-
-static struct miscdevice      i810_misc = {
-	minor: MISC_DYNAMIC_MINOR,
-	name:  I810_NAME,
-	fops:  &i810_fops,
-};
-
-static drm_ioctl_desc_t	      i810_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]     = { i810_version,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]  = { drm_getunique,  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]   = { drm_getmagic,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]   = { drm_irq_busid,  0, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]  = { drm_setunique,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]	      = { drm_block,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]     = { drm_unblock,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]     = { i810_control,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]  = { drm_authmagic,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]     = { drm_addmap,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]    = { i810_addbufs,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]   = { i810_markbufs,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]   = { i810_infobufs,  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]   = { i810_freebufs,  1, 0 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]     = { i810_addctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]      = { i810_rmctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]     = { i810_modctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]     = { i810_getctx,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]  = { i810_switchctx,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]     = { i810_newctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]     = { i810_resctx,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]    = { drm_adddraw,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]     = { drm_rmdraw,	  1, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	      = { i810_lock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]      = { i810_unlock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]      = { drm_finish,	  1, 0 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]  = { drm_agp_enable,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]    = { drm_agp_info,    1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]   = { drm_agp_alloc,   1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]    = { drm_agp_free,    1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]    = { drm_agp_bind,    1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]  = { drm_agp_unbind,  1, 1 },
-
-   	[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 },
-};
-
-#define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls)
-
-#ifdef MODULE
-static char		      *i810 = NULL;
-#endif
+#define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
-MODULE_AUTHOR("VA Linux Systems, Inc.");
-MODULE_DESCRIPTION("Intel I810");
-MODULE_PARM(i810, "s");
+#define DRIVER_NAME		"i810"
+#define DRIVER_DESC		"Intel i810"
+#define DRIVER_DATE		"20010616"
+
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		1
+#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 },
+
+
+#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"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
 
 #ifndef MODULE
-/* i810_options is called by the kernel to parse command-line options
+/* 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.
  */
 
-static int __init i810_options(char *str)
+/* 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);
+	DRM(parse_options)( str );
 	return 1;
 }
 
-__setup("i810=", i810_options);
-#endif
-
-static int i810_setup(drm_device_t *dev)
-{
-	int i;
-
-	atomic_set(&dev->ioctl_count, 0);
-	atomic_set(&dev->vma_count, 0);
-	dev->buf_use	  = 0;
-	atomic_set(&dev->buf_alloc, 0);
-
-	drm_dma_setup(dev);
-
-	atomic_set(&dev->total_open, 0);
-	atomic_set(&dev->total_close, 0);
-	atomic_set(&dev->total_ioctl, 0);
-	atomic_set(&dev->total_irq, 0);
-	atomic_set(&dev->total_ctx, 0);
-	atomic_set(&dev->total_locks, 0);
-	atomic_set(&dev->total_unlocks, 0);
-	atomic_set(&dev->total_contends, 0);
-	atomic_set(&dev->total_sleeps, 0);
-
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		dev->magiclist[i].head = NULL;
-		dev->magiclist[i].tail = NULL;
-	}
-	dev->maplist	    = NULL;
-	dev->map_count	    = 0;
-	dev->vmalist	    = NULL;
-	dev->lock.hw_lock   = NULL;
-	init_waitqueue_head(&dev->lock.lock_queue);
-	dev->queue_count    = 0;
-	dev->queue_reserved = 0;
-	dev->queue_slots    = 0;
-	dev->queuelist	    = NULL;
-	dev->irq	    = 0;
-	dev->context_flag   = 0;
-	dev->interrupt_flag = 0;
-	dev->dma_flag	    = 0;
-	dev->last_context   = 0;
-	dev->last_switch    = 0;
-	dev->last_checked   = 0;
-	init_timer(&dev->timer);
-	init_waitqueue_head(&dev->context_wait);
-#if DRM_DMA_HISTO
-	memset(&dev->histo, 0, sizeof(dev->histo));
-#endif
-	dev->ctx_start	    = 0;
-	dev->lck_start	    = 0;
-
-	dev->buf_rp	  = dev->buf;
-	dev->buf_wp	  = dev->buf;
-	dev->buf_end	  = dev->buf + DRM_BSZ;
-	dev->buf_async	  = NULL;
-	init_waitqueue_head(&dev->buf_readers);
-	init_waitqueue_head(&dev->buf_writers);
-
-	DRM_DEBUG("\n");
-
-	/* The kernel's context could be created here, but is now created
-	   in drm_dma_enqueue.	This is more resource-efficient for
-	   hardware that does not do DMA, but may mean that
-	   drm_select_queue fails between the time the interrupt is
-	   initialized and the time the queues are initialized. */
-
-	return 0;
-}
-
-
-static int i810_takedown(drm_device_t *dev)
-{
-	int		  i;
-	drm_magic_entry_t *pt, *next;
-	drm_map_t	  *map;
-	drm_vma_entry_t	  *vma, *vma_next;
-
-	DRM_DEBUG("\n");
-
-	if (dev->irq) i810_irq_uninstall(dev);
-
-	down(&dev->struct_sem);
-	del_timer(&dev->timer);
-
-	if (dev->devname) {
-		drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
-		dev->devname = NULL;
-	}
-
-	if (dev->unique) {
-		drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
-		dev->unique = NULL;
-		dev->unique_len = 0;
-	}
-				/* Clear pid list */
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		for (pt = dev->magiclist[i].head; pt; pt = next) {
-			next = pt->next;
-			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-		}
-		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
-	}
-   				/* Clear AGP information */
-	if (dev->agp) {
-		drm_agp_mem_t *entry;
-		drm_agp_mem_t *nexte;
-
-				/* Remove AGP resources, but leave dev->agp
-                                   intact until r128_cleanup is called. */
-		for (entry = dev->agp->memory; entry; entry = nexte) {
-			nexte = entry->next;
-			if (entry->bound) drm_unbind_agp(entry->memory);
-			drm_free_agp(entry->memory, entry->pages);
-			drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-		}
-		dev->agp->memory = NULL;
-
-		if (dev->agp->acquired) _drm_agp_release();
-
-		dev->agp->acquired = 0;
-		dev->agp->enabled  = 0;
-	}
-				/* Clear vma list (only built for debugging) */
-	if (dev->vmalist) {
-		for (vma = dev->vmalist; vma; vma = vma_next) {
-			vma_next = vma->next;
-			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
-		}
-		dev->vmalist = NULL;
-	}
-
-				/* Clear map area and mtrr information */
-	if (dev->maplist) {
-		for (i = 0; i < dev->map_count; i++) {
-			map = dev->maplist[i];
-			switch (map->type) {
-			case _DRM_REGISTERS:
-			case _DRM_FRAME_BUFFER:
-#ifdef CONFIG_MTRR
-				if (map->mtrr >= 0) {
-					int retcode;
-					retcode = mtrr_del(map->mtrr,
-							   map->offset,
-							   map->size);
-					DRM_DEBUG("mtrr_del = %d\n", retcode);
-				}
-#endif
-				drm_ioremapfree(map->handle, map->size);
-				break;
-			case _DRM_SHM:
-				drm_free_pages((unsigned long)map->handle,
-					       drm_order(map->size)
-					       - PAGE_SHIFT,
-					       DRM_MEM_SAREA);
-				break;
-			case _DRM_AGP:
-				break;
-			}
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		}
-		drm_free(dev->maplist,
-			 dev->map_count * sizeof(*dev->maplist),
-			 DRM_MEM_MAPS);
-		dev->maplist   = NULL;
-		dev->map_count = 0;
-	}
-
-	if (dev->queuelist) {
-		for (i = 0; i < dev->queue_count; i++) {
-			drm_waitlist_destroy(&dev->queuelist[i]->waitlist);
-			if (dev->queuelist[i]) {
-				drm_free(dev->queuelist[i],
-					 sizeof(*dev->queuelist[0]),
-					 DRM_MEM_QUEUES);
-				dev->queuelist[i] = NULL;
-			}
-		}
-		drm_free(dev->queuelist,
-			 dev->queue_slots * sizeof(*dev->queuelist),
-			 DRM_MEM_QUEUES);
-		dev->queuelist	 = NULL;
-	}
-
-	drm_dma_takedown(dev);
-
-	dev->queue_count     = 0;
-	if (dev->lock.hw_lock) {
-		dev->lock.hw_lock    = NULL; /* SHM removed */
-		dev->lock.pid	     = 0;
-		wake_up_interruptible(&dev->lock.lock_queue);
-	}
-	up(&dev->struct_sem);
-
-	return 0;
-}
-
-/* i810_init is called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported). */
-
-static int __init i810_init(void)
-{
-	int		      retcode;
-	drm_device_t	      *dev = &i810_device;
-
-	DRM_DEBUG("\n");
-
-	memset((void *)dev, 0, sizeof(*dev));
-	dev->count_lock	  = SPIN_LOCK_UNLOCKED;
-	sema_init(&dev->struct_sem, 1);
-
-#ifdef MODULE
-	drm_parse_options(i810);
-#endif
-	DRM_DEBUG("doing misc_register\n");
-	if ((retcode = misc_register(&i810_misc))) {
-		DRM_ERROR("Cannot register \"%s\"\n", I810_NAME);
-		return retcode;
-	}
-	dev->device = MKDEV(MISC_MAJOR, i810_misc.minor);
-	dev->name   = I810_NAME;
-
-   	DRM_DEBUG("doing mem init\n");
-	drm_mem_init();
-	DRM_DEBUG("doing proc init\n");
-	drm_proc_init(dev);
-	DRM_DEBUG("doing agp init\n");
-	dev->agp    = drm_agp_init();
-   	if(dev->agp == NULL) {
-	   	DRM_INFO("The i810 drm module requires the agpgart module"
-			 " to function correctly\nPlease load the agpgart"
-			 " module before you load the i810 module\n");
-	   	drm_proc_cleanup();
-	   	misc_deregister(&i810_misc);
-	   	i810_takedown(dev);
-	   	return -ENOMEM;
-	}
-	DRM_DEBUG("doing ctxbitmap init\n");
-	if((retcode = drm_ctxbitmap_init(dev))) {
-		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
-		drm_proc_cleanup();
-		misc_deregister(&i810_misc);
-		i810_takedown(dev);
-		return retcode;
-	}
-
-	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
-		 I810_NAME,
-		 I810_MAJOR,
-		 I810_MINOR,
-		 I810_PATCHLEVEL,
-		 I810_DATE,
-		 i810_misc.minor);
-
-	return 0;
-}
-
-/* i810_cleanup is called via cleanup_module at module unload time. */
-
-static void __exit i810_cleanup(void)
-{
-	drm_device_t	      *dev = &i810_device;
-
-	DRM_DEBUG("\n");
-
-	drm_proc_cleanup();
-	if (misc_deregister(&i810_misc)) {
-		DRM_ERROR("Cannot unload module\n");
-	} else {
-		DRM_INFO("Module unloaded\n");
-	}
-	drm_ctxbitmap_cleanup(dev);
-	i810_takedown(dev);
-	if (dev->agp) {
-		drm_agp_uninit();
-		drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
-		dev->agp = NULL;
-	}
-}
-
-module_init(i810_init);
-module_exit(i810_cleanup);
-
-
-int i810_version(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
-{
-	drm_version_t version;
-	int	      len;
-
-	if (copy_from_user(&version,
-			   (drm_version_t *)arg,
-			   sizeof(version)))
-		return -EFAULT;
-
-#define DRM_COPY(name,value)				     \
-	len = strlen(value);				     \
-	if (len > name##_len) len = name##_len;		     \
-	name##_len = strlen(value);			     \
-	if (len && name) {				     \
-		if (copy_to_user(name, value, len))          \
-			return -EFAULT;			     \
-	}
-
-	version.version_major	   = I810_MAJOR;
-	version.version_minor	   = I810_MINOR;
-	version.version_patchlevel = I810_PATCHLEVEL;
-
-	DRM_COPY(version.name, I810_NAME);
-	DRM_COPY(version.date, I810_DATE);
-	DRM_COPY(version.desc, I810_DESC);
-
-	if (copy_to_user((drm_version_t *)arg,
-			 &version,
-			 sizeof(version)))
-		return -EFAULT;
-	return 0;
-}
-
-int i810_open(struct inode *inode, struct file *filp)
-{
-	drm_device_t  *dev    = &i810_device;
-	int	      retcode = 0;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (!(retcode = drm_open_helper(inode, filp, dev))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
+__setup( DRIVER_NAME "=", i810_options );
 #endif
-		atomic_inc(&dev->total_open);
-		spin_lock(&dev->count_lock);
-		if (!dev->open_count++) {
-			spin_unlock(&dev->count_lock);
-			return i810_setup(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-	return retcode;
-}
-
-int i810_release(struct inode *inode, struct file *filp)
-{
-	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev;
-	int	      retcode = 0;
-
-	lock_kernel();
-	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) {
-	      	i810_reclaim_buffers(dev, priv->pid);
-		DRM_ERROR("Process %d dead, freeing lock for context %d\n",
-			  current->pid,
-			  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-		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. */
-	} else if (dev->lock.hw_lock) {
-	   	/* The lock is required to reclaim buffers */
-	   	DECLARE_WAITQUEUE(entry, current);
-	   	add_wait_queue(&dev->lock.lock_queue, &entry);
-		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-			if (!dev->lock.hw_lock) {
-				/* Device has been unregistered */
-				retcode = -EINTR;
-				break;
-			}
-			if (drm_lock_take(&dev->lock.hw_lock->lock,
-					  DRM_KERNEL_CONTEXT)) {
-				dev->lock.pid	    = priv->pid;
-				dev->lock.lock_time = jiffies;
-				atomic_inc(&dev->total_locks);
-				break;	/* Got lock */
-			}
-				/* Contention */
-			atomic_inc(&dev->total_sleeps);
-			schedule();
-			if (signal_pending(current)) {
-				retcode = -ERESTARTSYS;
-				break;
-			}
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&dev->lock.lock_queue, &entry);
-	   	if(!retcode) {
-		   	i810_reclaim_buffers(dev, priv->pid);
-		   	drm_lock_free(dev, &dev->lock.hw_lock->lock,
-				      DRM_KERNEL_CONTEXT);
-		}
-	}
-	drm_fasync(-1, filp, 0);
-
-	down(&dev->struct_sem);
-	if (priv->prev) priv->prev->next = priv->next;
-	else		dev->file_first	 = priv->next;
-	if (priv->next) priv->next->prev = priv->prev;
-	else		dev->file_last	 = priv->prev;
-	up(&dev->struct_sem);
-
-	drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
-#if LINUX_VERSION_CODE < 0x020333
-	MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-   	atomic_inc(&dev->total_close);
-   	spin_lock(&dev->count_lock);
-   	if (!--dev->open_count) {
-	   	if (atomic_read(&dev->ioctl_count) || dev->blocked) {
-		   	DRM_ERROR("Device busy: %d %d\n",
-				  atomic_read(&dev->ioctl_count),
-				  dev->blocked);
-		   	spin_unlock(&dev->count_lock);
-			unlock_kernel();
-		   	return -EBUSY;
-		}
-	   	spin_unlock(&dev->count_lock);
-		unlock_kernel();
-		return i810_takedown(dev);
-	}
-	spin_unlock(&dev->count_lock);
-	unlock_kernel();
-	return retcode;
-}
-
-/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */
-
-int i810_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
-{
-	int		 nr	 = DRM_IOCTL_NR(cmd);
-	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	int		 retcode = 0;
-	drm_ioctl_desc_t *ioctl;
-	drm_ioctl_t	 *func;
-
-	atomic_inc(&dev->ioctl_count);
-	atomic_inc(&dev->total_ioctl);
-	++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);
-
-	if (nr >= I810_IOCTL_COUNT) {
-		retcode = -EINVAL;
-	} else {
-		ioctl	  = &i810_ioctls[nr];
-		func	  = ioctl->func;
-
-		if (!func) {
-			DRM_DEBUG("no function\n");
-			retcode = -EINVAL;
-		} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
-			    || (ioctl->auth_needed && !priv->authenticated)) {
-			retcode = -EACCES;
-		} else {
-			retcode = (func)(inode, filp, cmd, arg);
-		}
-	}
-
-	atomic_dec(&dev->ioctl_count);
-	return retcode;
-}
 
-int i810_unlock(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_lock_t	  lock;
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("%d frees lock (%d holds)\n",
-		  lock.context,
-		  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-	atomic_inc(&dev->total_unlocks);
-	if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
-		atomic_inc(&dev->total_contends);
-   	drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
-	if (!dev->context_flag) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
-				  DRM_KERNEL_CONTEXT)) {
-			DRM_ERROR("\n");
-		}
-	}
-#if DRM_DMA_HISTOGRAM
-	atomic_inc(&dev->histo.lhld[drm_histogram_slot(get_cycles()
-						       - dev->lck_start)]);
-#endif
-
-	unblock_all_signals();
-	return 0;
-}
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lock.h"
+#include "drm_lists.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff -urN linux-2.4.8-pre6/drivers/char/drm/i810_drv.h linux/drivers/char/drm/i810_drv.h
--- linux-2.4.8-pre6/drivers/char/drm/i810_drv.h	Thu Jul 27 15:05:40 2000
+++ linux/drivers/char/drm/i810_drv.h	Mon Dec  3 22:59:45 2001
@@ -11,11 +11,11 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the next
  * paragraph) shall be included in all copies or substantial portions of the
  * Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
@@ -54,11 +54,12 @@
 } drm_i810_ring_buffer_t;
 
 typedef struct drm_i810_private {
-   	int ring_map_idx;
-   	int buffer_map_idx;
+	drm_map_t *sarea_map;
+	drm_map_t *buffer_map;
+	drm_map_t *mmio_map;
 
-   	drm_i810_ring_buffer_t ring;
 	drm_i810_sarea_t *sarea_priv;
+   	drm_i810_ring_buffer_t ring;
 
       	unsigned long hw_status_page;
    	unsigned long counter;
@@ -67,78 +68,33 @@
    	wait_queue_head_t flush_queue;	/* Processes waiting until flush    */
 	drm_buf_t *mmap_buffer;
 
-	
+
 	u32 front_di1, back_di1, zi1;
-	
+
 	int back_offset;
 	int depth_offset;
 	int w, h;
 	int pitch;
 } drm_i810_private_t;
 
-				/* i810_drv.c */
-extern int  i810_version(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  i810_open(struct inode *inode, struct file *filp);
-extern int  i810_release(struct inode *inode, struct file *filp);
-extern int  i810_ioctl(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  i810_unlock(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-
 				/* i810_dma.c */
 extern int  i810_dma_schedule(drm_device_t *dev, int locked);
 extern int  i810_getbuf(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg);
-extern int  i810_irq_install(drm_device_t *dev, int irq);
-extern int  i810_irq_uninstall(drm_device_t *dev);
-extern int  i810_control(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  i810_lock(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
 extern int  i810_dma_init(struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg);
 extern int  i810_flush_ioctl(struct inode *inode, struct file *filp,
 			     unsigned int cmd, unsigned long arg);
 extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid);
-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);
-extern int i810_copybuf(struct inode *inode, struct file *filp, 
+extern int  i810_getage(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg);
-extern int i810_docopy(struct inode *inode, struct file *filp, 
-		       unsigned int cmd, unsigned long arg);
-
-				/* i810_bufs.c */
-extern int  i810_addbufs(struct inode *inode, struct file *filp, 
+extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
+extern int i810_copybuf(struct inode *inode, struct file *filp,
 			unsigned int cmd, unsigned long arg);
-extern int  i810_infobufs(struct inode *inode, struct file *filp, 
-			 unsigned int cmd, unsigned long arg);
-extern int  i810_markbufs(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-extern int  i810_freebufs(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-extern int  i810_addmap(struct inode *inode, struct file *filp,
+extern int i810_docopy(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg);
 
-				/* i810_context.c */
-extern int  i810_resctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  i810_addctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  i810_modctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  i810_getctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  i810_switchctx(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  i810_newctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  i810_rmctx(struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg);
-
-extern int  i810_context_switch(drm_device_t *dev, int old, int new);
-extern int  i810_context_switch_complete(drm_device_t *dev, int new);
+extern void i810_dma_quiescent(drm_device_t *dev);
 
 #define I810_VERBOSE 0
 
@@ -152,6 +108,18 @@
 int i810_clear_bufs(struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg);
 
+
+#define I810_BASE(reg)		((unsigned long) \
+				dev_priv->mmio_map->handle)
+#define I810_ADDR(reg)		(I810_BASE(reg) + reg)
+#define I810_DEREF(reg)		*(__volatile__ int *)I810_ADDR(reg)
+#define I810_READ(reg)		I810_DEREF(reg)
+#define I810_WRITE(reg,val) 	do { I810_DEREF(reg) = val; } while (0)
+#define I810_DEREF16(reg)	*(__volatile__ u16 *)I810_ADDR(reg)
+#define I810_READ16(reg)	I810_DEREF16(reg)
+#define I810_WRITE16(reg,val)	do { I810_DEREF16(reg) = val; } while (0)
+
+
 #define GFX_OP_USER_INTERRUPT 		((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
 #define CMD_REPORT_HEAD			(7<<23)
@@ -184,7 +152,7 @@
 #define RING_START     		0x08
 #define START_ADDR          	0x00FFFFF8
 #define RING_LEN       		0x0C
-#define RING_NR_PAGES       	0x000FF000 
+#define RING_NR_PAGES       	0x000FF000
 #define RING_REPORT_MASK    	0x00000006
 #define RING_REPORT_64K     	0x00000002
 #define RING_REPORT_128K    	0x00000004
@@ -222,4 +190,3 @@
 
 
 #endif
-
diff -urN linux-2.4.8-pre6/drivers/char/drm/init.c linux/drivers/char/drm/init.c
--- linux-2.4.8-pre6/drivers/char/drm/init.c	Fri Jul 21 12:56:44 2000
+++ linux/drivers/char/drm/init.c	Wed Dec 31 16:00:00 1969
@@ -1,113 +0,0 @@
-/* init.c -- Setup/Cleanup for DRM -*- linux-c -*-
- * Created: Mon Jan  4 08:58:31 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>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-int			      drm_flags		= 0;
-
-/* drm_parse_option parses a single option.  See description for
-   drm_parse_options for details. */
-
-static void drm_parse_option(char *s)
-{
-	char *c, *r;
-	
-	DRM_DEBUG("\"%s\"\n", s);
-	if (!s || !*s) return;
-	for (c = s; *c && *c != ':'; c++); /* find : or \0 */
-	if (*c) r = c + 1; else r = NULL;  /* remember remainder */
-	*c = '\0';			   /* terminate */
-	if (!strcmp(s, "noctx")) {
-		drm_flags |= DRM_FLAG_NOCTX;
-		DRM_INFO("Server-mediated context switching OFF\n");
-		return;
-	}
-	if (!strcmp(s, "debug")) {
-		drm_flags |= DRM_FLAG_DEBUG;
-		DRM_INFO("Debug messages ON\n");
-		return;
-	}
-	DRM_ERROR("\"%s\" is not a valid option\n", s);
-	return;
-}
-
-/* drm_parse_options parse the insmod "drm=" options, or the command-line
- * options passed to the kernel via LILO.  The grammar of the format is as
- * follows:
- *
- * drm		::= 'drm=' option_list
- * option_list	::= option [ ';' option_list ]
- * option	::= 'device:' major
- *		|   'debug' 
- *		|   'noctx'
- * major	::= INTEGER
- *
- * Note that 's' contains option_list without the 'drm=' part.
- *
- * device=major,minor specifies the device number used for /dev/drm
- *	  if major == 0 then the misc device is used
- *	  if major == 0 and minor == 0 then dynamic misc allocation is used
- * debug=on specifies that debugging messages will be printk'd
- * debug=trace specifies that each function call will be logged via printk
- * debug=off turns off all debugging options
- *
- */
-
-void drm_parse_options(char *s)
-{
-	char *h, *t, *n;
-	
-	DRM_DEBUG("\"%s\"\n", s ?: "");
-	if (!s || !*s) return;
-
-	for (h = t = n = s; h && *h; h = n) {
-		for (; *t && *t != ';'; t++);	       /* find ; or \0 */
-		if (*t) n = t + 1; else n = NULL;      /* remember next */
-		*t = '\0';			       /* terminate */
-		drm_parse_option(h);		       /* parse */
-	}
-}
-
-/* drm_cpu_valid returns non-zero if the DRI will run on this CPU, and 0
- * otherwise. */
-
-int drm_cpu_valid(void)
-{
-#if defined(__i386__)
-	if (boot_cpu_data.x86 == 3) return 0; /* No cmpxchg on a 386 */
-#endif
-#if defined(__sparc__) && !defined(__sparc_v9__)
-	if (1)
-		return 0; /* No cmpxchg before v9 sparc. */
-#endif
-	return 1;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/ioctl.c linux/drivers/char/drm/ioctl.c
--- linux-2.4.8-pre6/drivers/char/drm/ioctl.c	Mon Jul 16 15:13:32 2001
+++ linux/drivers/char/drm/ioctl.c	Wed Dec 31 16:00:00 1969
@@ -1,99 +0,0 @@
-/* ioctl.c -- IOCTL processing for DRM -*- linux-c -*-
- * Created: Fri Jan  8 09:01:26 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>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-int drm_irq_busid(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
-{
-	drm_irq_busid_t p;
-	struct pci_dev	*dev;
-
-	if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
-		return -EFAULT;
-	dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
-	if (dev) p.irq = dev->irq;
-	else	 p.irq = 0;
-	DRM_DEBUG("%d:%d:%d => IRQ %d\n",
-		  p.busnum, p.devnum, p.funcnum, p.irq);
-	if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
-		return -EFAULT;
-	return 0;
-}
-
-int drm_getunique(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_unique_t	 u;
-
-	if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u)))
-		return -EFAULT;
-	if (u.unique_len >= dev->unique_len) {
-		if (copy_to_user(u.unique, dev->unique, dev->unique_len))
-			return -EFAULT;
-	}
-	u.unique_len = dev->unique_len;
-	if (copy_to_user((drm_unique_t *)arg, &u, sizeof(u)))
-		return -EFAULT;
-	return 0;
-}
-
-int drm_setunique(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_unique_t	 u;
-
-	if (dev->unique_len || dev->unique)
-		return -EBUSY;
-
-	if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u)))
-		return -EFAULT;
-
-	if (!u.unique_len || u.unique_len > 1024)
-		return -EINVAL;
-	
-	dev->unique_len = u.unique_len;
-	dev->unique	= drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER);
-	if (copy_from_user(dev->unique, u.unique, dev->unique_len))
-		return -EFAULT;
-	dev->unique[dev->unique_len] = '\0';
-
-	dev->devname = drm_alloc(strlen(dev->name) + strlen(dev->unique) + 2,
-				 DRM_MEM_DRIVER);
-	sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
-
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/lists.c linux/drivers/char/drm/lists.c
--- linux-2.4.8-pre6/drivers/char/drm/lists.c	Sun Oct  1 20:00:00 2000
+++ linux/drivers/char/drm/lists.c	Wed Dec 31 16:00:00 1969
@@ -1,218 +0,0 @@
-/* lists.c -- Buffer list handling routines -*- linux-c -*-
- * Created: Mon Apr 19 20:54:22 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>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-int drm_waitlist_create(drm_waitlist_t *bl, int count)
-{
-	if (bl->count) return -EINVAL;
-	
-	bl->count      = count;
-	bl->bufs       = drm_alloc((bl->count + 2) * sizeof(*bl->bufs),
-				   DRM_MEM_BUFLISTS);
-	bl->rp	       = bl->bufs;
-	bl->wp	       = bl->bufs;
-	bl->end	       = &bl->bufs[bl->count+1];
-	bl->write_lock = SPIN_LOCK_UNLOCKED;
-	bl->read_lock  = SPIN_LOCK_UNLOCKED;
-	return 0;
-}
-
-int drm_waitlist_destroy(drm_waitlist_t *bl)
-{
-	if (bl->rp != bl->wp) return -EINVAL;
-	if (bl->bufs) drm_free(bl->bufs,
-			       (bl->count + 2) * sizeof(*bl->bufs),
-			       DRM_MEM_BUFLISTS);
-	bl->count = 0;
-	bl->bufs  = NULL;
-	bl->rp	  = NULL;
-	bl->wp	  = NULL;
-	bl->end	  = NULL;
-	return 0;
-}
-
-int drm_waitlist_put(drm_waitlist_t *bl, drm_buf_t *buf)
-{							
-	int	      left;
-	unsigned long flags;
-
-	left = DRM_LEFTCOUNT(bl);
-	if (!left) {
-		DRM_ERROR("Overflow while adding buffer %d from pid %d\n",
-			  buf->idx, buf->pid);
-		return -EINVAL;
-	}
-#if DRM_DMA_HISTOGRAM
-	buf->time_queued = get_cycles();
-#endif
-	buf->list	 = DRM_LIST_WAIT;
-	
-	spin_lock_irqsave(&bl->write_lock, flags);
-	*bl->wp = buf;
-	if (++bl->wp >= bl->end) bl->wp = bl->bufs;
-	spin_unlock_irqrestore(&bl->write_lock, flags);
-	
-	return 0;
-}
-
-drm_buf_t *drm_waitlist_get(drm_waitlist_t *bl)
-{
-	drm_buf_t     *buf;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bl->read_lock, flags);
-	buf = *bl->rp;
-	if (bl->rp == bl->wp) {
-		spin_unlock_irqrestore(&bl->read_lock, flags);
-		return NULL;
-	}				     
-	if (++bl->rp >= bl->end) bl->rp = bl->bufs;
-	spin_unlock_irqrestore(&bl->read_lock, flags);
-	
-	return buf;
-}
-
-int drm_freelist_create(drm_freelist_t *bl, int count)
-{
-	atomic_set(&bl->count, 0);
-	bl->next      = NULL;
-	init_waitqueue_head(&bl->waiting);
-	bl->low_mark  = 0;
-	bl->high_mark = 0;
-	atomic_set(&bl->wfh,   0);
-	bl->lock      = SPIN_LOCK_UNLOCKED;
-	++bl->initialized;
-	return 0;
-}
-
-int drm_freelist_destroy(drm_freelist_t *bl)
-{
-	atomic_set(&bl->count, 0);
-	bl->next = NULL;
-	return 0;
-}
-
-int drm_freelist_put(drm_device_t *dev, drm_freelist_t *bl, drm_buf_t *buf)
-{
-	drm_device_dma_t *dma  = dev->dma;
-
-	if (!dma) {
-		DRM_ERROR("No DMA support\n");
-		return 1;
-	}
-
-	if (buf->waiting || buf->pending || buf->list == DRM_LIST_FREE) {
-		DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
-			  buf->idx, buf->waiting, buf->pending, buf->list);
-	}
-	if (!bl) return 1;
-#if DRM_DMA_HISTOGRAM
-	buf->time_freed = get_cycles();
-	drm_histogram_compute(dev, buf);
-#endif
-	buf->list	= DRM_LIST_FREE;
-	
-	spin_lock(&bl->lock);
-	buf->next	= bl->next;
-	bl->next	= buf;
-	spin_unlock(&bl->lock);
-	
-	atomic_inc(&bl->count);
-	if (atomic_read(&bl->count) > dma->buf_count) {
-		DRM_ERROR("%d of %d buffers free after addition of %d\n",
-			  atomic_read(&bl->count), dma->buf_count, buf->idx);
-		return 1;
-	}
-				/* Check for high water mark */
-	if (atomic_read(&bl->wfh) && atomic_read(&bl->count)>=bl->high_mark) {
-		atomic_set(&bl->wfh, 0);
-		wake_up_interruptible(&bl->waiting);
-	}
-	return 0;
-}
-
-static drm_buf_t *drm_freelist_try(drm_freelist_t *bl)
-{
-	drm_buf_t	  *buf;
-
-	if (!bl) return NULL;
-	
-				/* Get buffer */
-	spin_lock(&bl->lock);
-	if (!bl->next) {
-		spin_unlock(&bl->lock);
-		return NULL;
-	}
-	buf	  = bl->next;
-	bl->next  = bl->next->next;
-	spin_unlock(&bl->lock);
-	
-	atomic_dec(&bl->count);
-	buf->next = NULL;
-	buf->list = DRM_LIST_NONE;
-	if (buf->waiting || buf->pending) {
-		DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
-			  buf->idx, buf->waiting, buf->pending, buf->list);
-	}
-	
-	return buf;
-}
-
-drm_buf_t *drm_freelist_get(drm_freelist_t *bl, int block)
-{
-	drm_buf_t	  *buf	= NULL;
-	DECLARE_WAITQUEUE(entry, current);
-
-	if (!bl || !bl->initialized) return NULL;
-	
-				/* Check for low water mark */
-	if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
-		atomic_set(&bl->wfh, 1);
-	if (atomic_read(&bl->wfh)) {
-		if (block) {
-			add_wait_queue(&bl->waiting, &entry);
-			for (;;) {
-				current->state = TASK_INTERRUPTIBLE;
-				if (!atomic_read(&bl->wfh)
-				    && (buf = drm_freelist_try(bl))) break;
-				schedule();
-				if (signal_pending(current)) break;
-			}
-			current->state = TASK_RUNNING;
-			remove_wait_queue(&bl->waiting, &entry);
-		}
-		return buf;
-	}
-		
-	return drm_freelist_try(bl);
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/lock.c linux/drivers/char/drm/lock.c
--- linux-2.4.8-pre6/drivers/char/drm/lock.c	Sun Oct  1 20:00:00 2000
+++ linux/drivers/char/drm/lock.c	Wed Dec 31 16:00:00 1969
@@ -1,252 +0,0 @@
-/* lock.c -- IOCTLs for locking -*- linux-c -*-
- * Created: Tue Feb  2 08:37:54 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>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-int drm_block(struct inode *inode, struct file *filp, unsigned int cmd,
-	      unsigned long arg)
-{
-	DRM_DEBUG("\n");
-	return 0;
-}
-
-int drm_unblock(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
-{
-	DRM_DEBUG("\n");
-	return 0;
-}
-
-int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
-{
-	unsigned int old, new, prev;
-
-	do {
-		old = *lock;
-		if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
-		else			  new = context | _DRM_LOCK_HELD;
-		prev = cmpxchg(lock, old, new);
-	} while (prev != old);
-	if (_DRM_LOCKING_CONTEXT(old) == context) {
-		if (old & _DRM_LOCK_HELD) {
-			if (context != DRM_KERNEL_CONTEXT) {
-				DRM_ERROR("%d holds heavyweight lock\n",
-					  context);
-			}
-			return 0;
-		}
-	}
-	if (new == (context | _DRM_LOCK_HELD)) {
-				/* Have lock */
-		return 1;
-	}
-	return 0;
-}
-
-/* This takes a lock forcibly and hands it to context.	Should ONLY be used
-   inside *_unlock to give lock to kernel before calling *_dma_schedule. */
-int drm_lock_transfer(drm_device_t *dev,
-		      __volatile__ unsigned int *lock, unsigned int context)
-{
-	unsigned int old, new, prev;
-
-	dev->lock.pid = 0;
-	do {
-		old  = *lock;
-		new  = context | _DRM_LOCK_HELD;
-		prev = cmpxchg(lock, old, new);
-	} while (prev != old);
-	return 1;
-}
-
-int drm_lock_free(drm_device_t *dev,
-		  __volatile__ unsigned int *lock, unsigned int context)
-{
-	unsigned int old, new, prev;
-	pid_t        pid = dev->lock.pid;
-
-	dev->lock.pid = 0;
-	do {
-		old  = *lock;
-		new  = 0;
-		prev = cmpxchg(lock, old, new);
-	} while (prev != old);
-	if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
-		DRM_ERROR("%d freed heavyweight lock held by %d (pid %d)\n",
-			  context,
-			  _DRM_LOCKING_CONTEXT(old),
-			  pid);
-		return 1;
-	}
-	wake_up_interruptible(&dev->lock.lock_queue);
-	return 0;
-}
-
-static int drm_flush_queue(drm_device_t *dev, int context)
-{
-	DECLARE_WAITQUEUE(entry, current);
-	int		  ret	= 0;
-	drm_queue_t	  *q	= dev->queuelist[context];
-	
-	DRM_DEBUG("\n");
-	
-	atomic_inc(&q->use_count);
-	if (atomic_read(&q->use_count) > 1) {
-		atomic_inc(&q->block_write);
-		add_wait_queue(&q->flush_queue, &entry);
-		atomic_inc(&q->block_count);
-		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-			if (!DRM_BUFCOUNT(&q->waitlist)) break;
-			schedule();
-			if (signal_pending(current)) {
-				ret = -EINTR; /* Can't restart */
-				break;
-			}
-		}
-		atomic_dec(&q->block_count);
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&q->flush_queue, &entry);
-	}
-	atomic_dec(&q->use_count);
-	atomic_inc(&q->total_flushed);
-		
-				/* NOTE: block_write is still incremented!
-				   Use drm_flush_unlock_queue to decrement. */
-	return ret;
-}
-
-static int drm_flush_unblock_queue(drm_device_t *dev, int context)
-{
-	drm_queue_t	  *q	= dev->queuelist[context];
-	
-	DRM_DEBUG("\n");
-	
-	atomic_inc(&q->use_count);
-	if (atomic_read(&q->use_count) > 1) {
-		if (atomic_read(&q->block_write)) {
-			atomic_dec(&q->block_write);
-			wake_up_interruptible(&q->write_queue);
-		}
-	}
-	atomic_dec(&q->use_count);
-	return 0;
-}
-
-int drm_flush_block_and_flush(drm_device_t *dev, int context,
-			      drm_lock_flags_t flags)
-{
-	int ret = 0;
-	int i;
-	
-	DRM_DEBUG("\n");
-	
-	if (flags & _DRM_LOCK_FLUSH) {
-		ret = drm_flush_queue(dev, DRM_KERNEL_CONTEXT);
-		if (!ret) ret = drm_flush_queue(dev, context);
-	}
-	if (flags & _DRM_LOCK_FLUSH_ALL) {
-		for (i = 0; !ret && i < dev->queue_count; i++) {
-			ret = drm_flush_queue(dev, i);
-		}
-	}
-	return ret;
-}
-
-int drm_flush_unblock(drm_device_t *dev, int context, drm_lock_flags_t flags)
-{
-	int ret = 0;
-	int i;
-	
-	DRM_DEBUG("\n");
-	
-	if (flags & _DRM_LOCK_FLUSH) {
-		ret = drm_flush_unblock_queue(dev, DRM_KERNEL_CONTEXT);
-		if (!ret) ret = drm_flush_unblock_queue(dev, context);
-	}
-	if (flags & _DRM_LOCK_FLUSH_ALL) {
-		for (i = 0; !ret && i < dev->queue_count; i++) {
-			ret = drm_flush_unblock_queue(dev, i);
-		}
-	}
-		
-	return ret;
-}
-
-int drm_finish(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;
-	int		  ret	  = 0;
-	drm_lock_t	  lock;
-
-	DRM_DEBUG("\n");
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-	ret = drm_flush_block_and_flush(dev, lock.context, lock.flags);
-	drm_flush_unblock(dev, lock.context, lock.flags);
-	return ret;
-}
-
-/* If we get here, it means that the process has called DRM_IOCTL_LOCK
-   without calling DRM_IOCTL_UNLOCK.
-   
-   If the lock is not held, then let the signal proceed as usual.
-   
-   If the lock is held, then set the contended flag and keep the signal
-   blocked.
-   
-
-   Return 1 if the signal should be delivered normally.
-   Return 0 if the signal should be blocked.  */
-
-int drm_notifier(void *priv)
-{
-	drm_sigdata_t *s = (drm_sigdata_t *)priv;
-	unsigned int  old, new, prev;
-
-
-				/* Allow signal delivery if lock isn't held */
-	if (!_DRM_LOCK_IS_HELD(s->lock->lock)
-	    || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context) return 1;
-	
-				/* Otherwise, set flag to force call to
-                                   drmUnlock */
-	do {
-		old  = s->lock->lock;
-		new  = old | _DRM_LOCK_CONT;
-		prev = cmpxchg(&s->lock->lock, old, new);
-	} while (prev != old);
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/memory.c linux/drivers/char/drm/memory.c
--- linux-2.4.8-pre6/drivers/char/drm/memory.c	Thu Nov 16 14:05:49 2000
+++ linux/drivers/char/drm/memory.c	Wed Dec 31 16:00:00 1969
@@ -1,448 +0,0 @@
-/* memory.c -- Memory management wrappers for DRM -*- linux-c -*-
- * Created: Thu Feb  4 14:00:34 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>
- *
- */
-
-#define __NO_VERSION__
-#include <linux/config.h>
-#include "drmP.h"
-#include <linux/wrapper.h>
-
-typedef struct drm_mem_stats {
-	const char	  *name;
-	int		  succeed_count;
-	int		  free_count;
-	int		  fail_count;
-	unsigned long	  bytes_allocated;
-	unsigned long	  bytes_freed;
-} drm_mem_stats_t;
-
-static spinlock_t	  drm_mem_lock	    = SPIN_LOCK_UNLOCKED;
-static unsigned long	  drm_ram_available = 0; /* In pages */
-static unsigned long	  drm_ram_used	    = 0;
-static drm_mem_stats_t	  drm_mem_stats[]   = {
-	[DRM_MEM_DMA]	    = { "dmabufs"  },
-	[DRM_MEM_SAREA]	    = { "sareas"   },
-	[DRM_MEM_DRIVER]    = { "driver"   },
-	[DRM_MEM_MAGIC]	    = { "magic"	   },
-	[DRM_MEM_IOCTLS]    = { "ioctltab" },
-	[DRM_MEM_MAPS]	    = { "maplist"  },
-	[DRM_MEM_VMAS]	    = { "vmalist"  },
-	[DRM_MEM_BUFS]	    = { "buflist"  },
-	[DRM_MEM_SEGS]	    = { "seglist"  },
-	[DRM_MEM_PAGES]	    = { "pagelist" },
-	[DRM_MEM_FILES]	    = { "files"	   },
-	[DRM_MEM_QUEUES]    = { "queues"   },
-	[DRM_MEM_CMDS]	    = { "commands" },
-	[DRM_MEM_MAPPINGS]  = { "mappings" },
-	[DRM_MEM_BUFLISTS]  = { "buflists" },
-	[DRM_MEM_AGPLISTS]  = { "agplist"  },
-	[DRM_MEM_TOTALAGP]  = { "totalagp" },
-	[DRM_MEM_BOUNDAGP]  = { "boundagp" },
-	[DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
-	{ NULL, 0, }		/* Last entry must be null */
-};
-
-void drm_mem_init(void)
-{
-	drm_mem_stats_t *mem;
-	struct sysinfo	si;
-	
-	for (mem = drm_mem_stats; mem->name; ++mem) {
-		mem->succeed_count   = 0;
-		mem->free_count	     = 0;
-		mem->fail_count	     = 0;
-		mem->bytes_allocated = 0;
-		mem->bytes_freed     = 0;
-	}
-	
-	si_meminfo(&si);
-#if LINUX_VERSION_CODE < 0x020317
-				/* Changed to page count in 2.3.23 */
-	drm_ram_available = si.totalram >> PAGE_SHIFT;
-#else
-	drm_ram_available = si.totalram;
-#endif
-	drm_ram_used	  = 0;
-}
-
-/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
-
-static int _drm_mem_info(char *buf, char **start, off_t offset, int len,
-			 int *eof, void *data)
-{
-	drm_mem_stats_t *pt;
-
-	if (offset > 0) return 0; /* no partial requests */
-	len  = 0;
-	*eof = 1;
-	DRM_PROC_PRINT("		  total counts			"
-		       " |    outstanding  \n");
-	DRM_PROC_PRINT("type	   alloc freed fail	bytes	   freed"
-		       " | allocs      bytes\n\n");
-	DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
-		       "system", 0, 0, 0,
-		       drm_ram_available << (PAGE_SHIFT - 10));
-	DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
-		       "locked", 0, 0, 0, drm_ram_used >> 10);
-	DRM_PROC_PRINT("\n");
-	for (pt = drm_mem_stats; pt->name; pt++) {
-		DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
-			       pt->name,
-			       pt->succeed_count,
-			       pt->free_count,
-			       pt->fail_count,
-			       pt->bytes_allocated,
-			       pt->bytes_freed,
-			       pt->succeed_count - pt->free_count,
-			       (long)pt->bytes_allocated
-			       - (long)pt->bytes_freed);
-	}
-	
-	return len;
-}
-
-int drm_mem_info(char *buf, char **start, off_t offset, int len,
-		 int *eof, void *data)
-{
-	int ret;
-	
-	spin_lock(&drm_mem_lock);
-	ret = _drm_mem_info(buf, start, offset, len, eof, data);
-	spin_unlock(&drm_mem_lock);
-	return ret;
-}
-
-void *drm_alloc(size_t size, int area)
-{
-	void *pt;
-	
-	if (!size) {
-		DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
-		return NULL;
-	}
-	
-	if (!(pt = kmalloc(size, GFP_KERNEL))) {
-		spin_lock(&drm_mem_lock);
-		++drm_mem_stats[area].fail_count;
-		spin_unlock(&drm_mem_lock);
-		return NULL;
-	}
-	spin_lock(&drm_mem_lock);
-	++drm_mem_stats[area].succeed_count;
-	drm_mem_stats[area].bytes_allocated += size;
-	spin_unlock(&drm_mem_lock);
-	return pt;
-}
-
-void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
-{
-	void *pt;
-	
-	if (!(pt = drm_alloc(size, area))) return NULL;
-	if (oldpt && oldsize) {
-		memcpy(pt, oldpt, oldsize);
-		drm_free(oldpt, oldsize, area);
-	}
-	return pt;
-}
-
-char *drm_strdup(const char *s, int area)
-{
-	char *pt;
-	int	 length = s ? strlen(s) : 0;
-	
-	if (!(pt = drm_alloc(length+1, area))) return NULL;
-	strcpy(pt, s);
-	return pt;
-}
-
-void drm_strfree(const char *s, int area)
-{
-	unsigned int size;
-	
-	if (!s) return;
-	
-	size = 1 + (s ? strlen(s) : 0);
-	drm_free((void *)s, size, area);
-}
-
-void drm_free(void *pt, size_t size, int area)
-{
-	int alloc_count;
-	int free_count;
-	
-	if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
-	else	 kfree(pt);
-	spin_lock(&drm_mem_lock);
-	drm_mem_stats[area].bytes_freed += size;
-	free_count  = ++drm_mem_stats[area].free_count;
-	alloc_count =	drm_mem_stats[area].succeed_count;
-	spin_unlock(&drm_mem_lock);
-	if (free_count > alloc_count) {
-		DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
-			      free_count, alloc_count);
-	}
-}
-
-unsigned long drm_alloc_pages(int order, int area)
-{
-	unsigned long address;
-	unsigned long bytes	  = PAGE_SIZE << order;
-	unsigned long addr;
-	unsigned int  sz;
-	
-	spin_lock(&drm_mem_lock);
-	if ((drm_ram_used >> PAGE_SHIFT)
-	    > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
-		spin_unlock(&drm_mem_lock);
-		return 0;
-	}
-	spin_unlock(&drm_mem_lock);
-	
-	address = __get_free_pages(GFP_KERNEL, order);
-	if (!address) {
-		spin_lock(&drm_mem_lock);
-		++drm_mem_stats[area].fail_count;
-		spin_unlock(&drm_mem_lock);
-		return 0;
-	}
-	spin_lock(&drm_mem_lock);
-	++drm_mem_stats[area].succeed_count;
-	drm_mem_stats[area].bytes_allocated += bytes;
-	drm_ram_used		            += bytes;
-	spin_unlock(&drm_mem_lock);
-	
-	
-				/* Zero outside the lock */
-	memset((void *)address, 0, bytes);
-	
-				/* Reserve */
-	for (addr = address, sz = bytes;
-	     sz > 0;
-	     addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-#if LINUX_VERSION_CODE >= 0x020400
-				/* Argument type changed in 2.4.0-test6/pre8 */
-		mem_map_reserve(virt_to_page(addr));
-#else
-		mem_map_reserve(MAP_NR(addr));
-#endif
-	}
-	
-	return address;
-}
-
-void drm_free_pages(unsigned long address, int order, int area)
-{
-	unsigned long bytes = PAGE_SIZE << order;
-	int		  alloc_count;
-	int		  free_count;
-	unsigned long addr;
-	unsigned int  sz;
-	
-	if (!address) {
-		DRM_MEM_ERROR(area, "Attempt to free address 0\n");
-	} else {
-				/* Unreserve */
-		for (addr = address, sz = bytes;
-		     sz > 0;
-		     addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-#if LINUX_VERSION_CODE >= 0x020400
-				/* Argument type changed in 2.4.0-test6/pre8 */
-			mem_map_unreserve(virt_to_page(addr));
-#else
-			mem_map_unreserve(MAP_NR(addr));
-#endif
-		}
-		free_pages(address, order);
-	}
-	
-	spin_lock(&drm_mem_lock);
-	free_count  = ++drm_mem_stats[area].free_count;
-	alloc_count =	drm_mem_stats[area].succeed_count;
-	drm_mem_stats[area].bytes_freed += bytes;
-	drm_ram_used			-= bytes;
-	spin_unlock(&drm_mem_lock);
-	if (free_count > alloc_count) {
-		DRM_MEM_ERROR(area,
-			      "Excess frees: %d frees, %d allocs\n",
-			      free_count, alloc_count);
-	}
-}
-
-void *drm_ioremap(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(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;
-	int free_count;
-	
-	if (!pt)
-		DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
-			      "Attempt to free NULL pointer\n");
-	else
-		iounmap(pt);
-	
-	spin_lock(&drm_mem_lock);
-	drm_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size;
-	free_count  = ++drm_mem_stats[DRM_MEM_MAPPINGS].free_count;
-	alloc_count =	drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
-	spin_unlock(&drm_mem_lock);
-	if (free_count > alloc_count) {
-		DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
-			      "Excess frees: %d frees, %d allocs\n",
-			      free_count, alloc_count);
-	}
-}
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-agp_memory *drm_alloc_agp(int pages, u32 type)
-{
-	agp_memory *handle;
-
-	if (!pages) {
-		DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
-		return NULL;
-	}
-	
-	if ((handle = drm_agp_allocate_memory(pages, type))) {
-		spin_lock(&drm_mem_lock);
-		++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
-		drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated
-			+= pages << PAGE_SHIFT;
-		spin_unlock(&drm_mem_lock);
-		return handle;
-	}
-	spin_lock(&drm_mem_lock);
-	++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count;
-	spin_unlock(&drm_mem_lock);
-	return NULL;
-}
-
-int drm_free_agp(agp_memory *handle, int pages)
-{
-	int           alloc_count;
-	int           free_count;
-	int           retval = -EINVAL;
-
-	if (!handle) {
-		DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
-			      "Attempt to free NULL AGP handle\n");
-		return retval;;
-	}
-	
-	if (drm_agp_free_memory(handle)) {
-		spin_lock(&drm_mem_lock);
-		free_count  = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count;
-		alloc_count =   drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
-		drm_mem_stats[DRM_MEM_TOTALAGP].bytes_freed
-			+= pages << PAGE_SHIFT;
-		spin_unlock(&drm_mem_lock);
-		if (free_count > alloc_count) {
-			DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
-				      "Excess frees: %d frees, %d allocs\n",
-				      free_count, alloc_count);
-		}
-		return 0;
-	}
-	return retval;
-}
-
-int drm_bind_agp(agp_memory *handle, unsigned int start)
-{
-	int retcode = -EINVAL;
-
-	if (!handle) {
-		DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
-			      "Attempt to bind NULL AGP handle\n");
-		return retcode;
-	}
-
-	if (!(retcode = drm_agp_bind_memory(handle, start))) {
-		spin_lock(&drm_mem_lock);
-		++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
-		drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated
-			+= handle->page_count << PAGE_SHIFT;
-		spin_unlock(&drm_mem_lock);
-		return retcode;
-	}
-	spin_lock(&drm_mem_lock);
-	++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count;
-	spin_unlock(&drm_mem_lock);
-	return retcode;
-}
-
-int drm_unbind_agp(agp_memory *handle)
-{
-	int alloc_count;
-	int free_count;
-	int retcode = -EINVAL;
-	
-	if (!handle) {
-		DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
-			      "Attempt to unbind NULL AGP handle\n");
-		return retcode;
-	}
-
-	if ((retcode = drm_agp_unbind_memory(handle))) return retcode;
-	spin_lock(&drm_mem_lock);
-	free_count  = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count;
-	alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
-	drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed
-		+= handle->page_count << PAGE_SHIFT;
-	spin_unlock(&drm_mem_lock);
-	if (free_count > alloc_count) {
-		DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
-			      "Excess frees: %d frees, %d allocs\n",
-			      free_count, alloc_count);
-	}
-	return retcode;
-}
-#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga.h linux/drivers/char/drm/mga.h
--- linux-2.4.8-pre6/drivers/char/drm/mga.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/mga.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,67 @@
+/* mga.h -- Matrox G200/G400 DRM template customization -*- linux-c -*-
+ * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __MGA_H__
+#define __MGA_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) mga_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP		1
+#define __MUST_HAVE_AGP		1
+#define __HAVE_MTRR		1
+#define __HAVE_CTX_BITMAP	1
+
+/* Driver customization:
+ */
+#define DRIVER_PRETAKEDOWN() do {					\
+	if ( dev->dev_private ) mga_do_cleanup_dma( dev );		\
+} while (0)
+
+/* DMA customization:
+ */
+#define __HAVE_DMA		1
+
+#define __HAVE_DMA_QUIESCENT	1
+#define DRIVER_DMA_QUIESCENT() do {					\
+	drm_mga_private_t *dev_priv = dev->dev_private;			\
+	return mga_do_wait_for_idle( dev_priv );			\
+} while (0)
+
+/* Buffer customization:
+ */
+#define DRIVER_BUF_PRIV_T	drm_mga_buf_priv_t
+
+#define DRIVER_AGP_BUFFERS_MAP( dev )					\
+	((drm_mga_private_t *)((dev)->dev_private))->buffers
+
+#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga_bufs.c linux/drivers/char/drm/mga_bufs.c
--- linux-2.4.8-pre6/drivers/char/drm/mga_bufs.c	Mon Jul 16 15:13:32 2001
+++ linux/drivers/char/drm/mga_bufs.c	Wed Dec 31 16:00:00 1969
@@ -1,629 +0,0 @@
-/* mga_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
- * Created: Thu Jan 6 01:47:26 2000 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * 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>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include "mga_drv.h"
-#include "linux/un.h"
-
-
-int mga_addbufs_agp(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_device_dma_t *dma = dev->dma;
-	drm_buf_desc_t request;
-	drm_buf_entry_t *entry;
-	drm_buf_t *buf;
-	unsigned long offset;
-	unsigned long agp_offset;
-	int count;
-	int order;
-	int size;
-	int alignment;
-	int page_order;
-	int total;
-	int byte_count;
-	int i;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	count = request.count;
-	order = drm_order(request.size);
-	size	= 1 << order;
-	agp_offset = request.agp_start;
-	alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
-	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-	total = PAGE_SIZE << page_order;
-	byte_count = 0;
-
-	DRM_DEBUG("count: %d\n", count);
-	DRM_DEBUG("order: %d\n", order);
-	DRM_DEBUG("size: %d\n", size);
-	DRM_DEBUG("agp_offset: %ld\n", agp_offset);
-	DRM_DEBUG("alignment: %d\n", alignment);
-	DRM_DEBUG("page_order: %d\n", page_order);
-	DRM_DEBUG("total: %d\n", total);
-	DRM_DEBUG("byte_count: %d\n", byte_count);
-
-	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-	if (dev->queue_count) return -EBUSY; /* Not while in use */
-	spin_lock(&dev->count_lock);
-	if (dev->buf_use) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	atomic_inc(&dev->buf_alloc);
-	spin_unlock(&dev->count_lock);
-   
-	down(&dev->struct_sem);
-	entry = &dma->bufs[order];
-	if (entry->buf_count) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM; /* May only call once for each order */
-	}
-
-	/* This isnt neccessarily a good limit, but we have to stop a dumb
-	   32 bit overflow problem below */
-	   
-	if ( count < 0 || count > 4096)
-	{
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -EINVAL;
-	}
-		   
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
-	if (!entry->buflist) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;
-	}
-	memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-   
-	entry->buf_size   = size;
-	entry->page_order = page_order;
-	offset = 0;
-
-   
-	while(entry->buf_count < count) {
-		buf = &entry->buflist[entry->buf_count];
-		buf->idx = dma->buf_count + entry->buf_count;
-		buf->total = alignment;
-		buf->order = order;
-		buf->used = 0;
-
-		buf->offset = offset; /* Hrm */
-		buf->bus_address = dev->agp->base + agp_offset + offset;
-		buf->address = (void *)(agp_offset + offset + dev->agp->base);
-		buf->next = NULL;
-		buf->waiting = 0;
-		buf->pending = 0;
-		init_waitqueue_head(&buf->dma_wait);
-		buf->pid = 0;
-
-		buf->dev_private = drm_alloc(sizeof(drm_mga_buf_priv_t),
-					     DRM_MEM_BUFS);
-		buf->dev_priv_size = sizeof(drm_mga_buf_priv_t);
-
-#if DRM_DMA_HISTOGRAM
-		buf->time_queued = 0;
-		buf->time_dispatched = 0;
-		buf->time_completed = 0;
-		buf->time_freed = 0;
-#endif
-		offset = offset + alignment;
-		entry->buf_count++;
-		byte_count += PAGE_SIZE << page_order;
-	}
-   
-	dma->buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist),
-				   DRM_MEM_BUFS);
-	for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
-		dma->buflist[i] = &entry->buflist[i - dma->buf_count];
-   
-	dma->buf_count  += entry->buf_count;
-
-	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
-
-	dma->byte_count += byte_count;
-
-	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
-
-	drm_freelist_create(&entry->freelist, entry->buf_count);
-	for (i = 0; i < entry->buf_count; i++) {
-		drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
-	}
-   
-	up(&dev->struct_sem);
-   
-	request.count = entry->buf_count;
-	request.size  = size;
-   
-	if (copy_to_user((drm_buf_desc_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-   
-	atomic_dec(&dev->buf_alloc);
-
-	DRM_DEBUG("count: %d\n", count);
-	DRM_DEBUG("order: %d\n", order);
-	DRM_DEBUG("size: %d\n", size);
-	DRM_DEBUG("agp_offset: %ld\n", agp_offset);
-	DRM_DEBUG("alignment: %d\n", alignment);
-	DRM_DEBUG("page_order: %d\n", page_order);
-	DRM_DEBUG("total: %d\n", total);
-	DRM_DEBUG("byte_count: %d\n", byte_count);
-
-	dma->flags = _DRM_DMA_USE_AGP;
-
-	DRM_DEBUG("dma->flags : %x\n", dma->flags);
-
-	return 0;
-}
-
-int mga_addbufs_pci(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_desc_t	 request;
-	int		 count;
-	int		 order;
-	int		 size;
-	int		 total;
-	int		 page_order;
-	drm_buf_entry_t	 *entry;
-	unsigned long	 page;
-	drm_buf_t	 *buf;
-	int		 alignment;
-	unsigned long	 offset;
-	int		 i;
-	int		 byte_count;
-	int		 page_count;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	count	   = request.count;
-	order	   = drm_order(request.size);
-	size	   = 1 << order;
-	
-	DRM_DEBUG("count = %d, size = %d (%d), order = %d, queue_count = %d\n",
-		  request.count, request.size, size, order, dev->queue_count);
-
-	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-	if (dev->queue_count) return -EBUSY; /* Not while in use */
-
-	alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
-	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-	total	   = PAGE_SIZE << page_order;
-
-	spin_lock(&dev->count_lock);
-	if (dev->buf_use) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	atomic_inc(&dev->buf_alloc);
-	spin_unlock(&dev->count_lock);
-	
-	down(&dev->struct_sem);
-	entry = &dma->bufs[order];
-	if (entry->buf_count) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;	/* May only call once for each order */
-	}
-	
-	if(count < 0 || count > 4096)
-	{
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -EINVAL;
-	}
-	
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
-	if (!entry->buflist) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;
-	}
-	memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
-	entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
-				   DRM_MEM_SEGS);
-	if (!entry->seglist) {
-		drm_free(entry->buflist,
-			 count * sizeof(*entry->buflist),
-			 DRM_MEM_BUFS);
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;
-	}
-	memset(entry->seglist, 0, count * sizeof(*entry->seglist));
-
-	dma->pagelist = drm_realloc(dma->pagelist,
-				    dma->page_count * sizeof(*dma->pagelist),
-				    (dma->page_count + (count << page_order))
-				    * sizeof(*dma->pagelist),
-				    DRM_MEM_PAGES);
-	DRM_DEBUG("pagelist: %d entries\n",
-		  dma->page_count + (count << page_order));
-
-
-	entry->buf_size	  = size;
-	entry->page_order = page_order;
-	byte_count	  = 0;
-	page_count	  = 0;
-	while (entry->buf_count < count) {
-		if (!(page = drm_alloc_pages(page_order, DRM_MEM_DMA))) break;
-		entry->seglist[entry->seg_count++] = page;
-		for (i = 0; i < (1 << page_order); i++) {
-			DRM_DEBUG("page %d @ 0x%08lx\n",
-				  dma->page_count + page_count,
-				  page + PAGE_SIZE * i);
-			dma->pagelist[dma->page_count + page_count++]
-				= page + PAGE_SIZE * i;
-		}
-		for (offset = 0;
-		     offset + size <= total && entry->buf_count < count;
-		     offset += alignment, ++entry->buf_count) {
-			buf	     = &entry->buflist[entry->buf_count];
-			buf->idx     = dma->buf_count + entry->buf_count;
-			buf->total   = alignment;
-			buf->order   = order;
-			buf->used    = 0;
-			buf->offset  = (dma->byte_count + byte_count + offset);
-			buf->address = (void *)(page + offset);
-			buf->next    = NULL;
-			buf->waiting = 0;
-			buf->pending = 0;
-			init_waitqueue_head(&buf->dma_wait);
-			buf->pid     = 0;
-#if DRM_DMA_HISTOGRAM
-			buf->time_queued     = 0;
-			buf->time_dispatched = 0;
-			buf->time_completed  = 0;
-			buf->time_freed	     = 0;
-#endif
-			DRM_DEBUG("buffer %d @ %p\n",
-				  entry->buf_count, buf->address);
-		}
-		byte_count += PAGE_SIZE << page_order;
-	}
-
-	dma->buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist),
-				   DRM_MEM_BUFS);
-	for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
-		dma->buflist[i] = &entry->buflist[i - dma->buf_count];
-
-	dma->buf_count	+= entry->buf_count;
-	dma->seg_count	+= entry->seg_count;
-	dma->page_count += entry->seg_count << page_order;
-	dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
-	
-	drm_freelist_create(&entry->freelist, entry->buf_count);
-	for (i = 0; i < entry->buf_count; i++) {
-		drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
-	}
-	
-	up(&dev->struct_sem);
-
-	request.count = entry->buf_count;
-	request.size  = size;
-
-	if (copy_to_user((drm_buf_desc_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-	
-	atomic_dec(&dev->buf_alloc);
-	return 0;
-}
-
-int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
-{
-	drm_buf_desc_t	 request;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	if(request.flags & _DRM_AGP_BUFFER)
-		return mga_addbufs_agp(inode, filp, cmd, arg);
-	else
-		return mga_addbufs_pci(inode, filp, cmd, arg);
-}
-
-int mga_infobufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_info_t	 request;
-	int		 i;
-	int		 count;
-
-	if (!dma) return -EINVAL;
-
-	spin_lock(&dev->count_lock);
-	if (atomic_read(&dev->buf_alloc)) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	++dev->buf_use;		/* Can't allocate more after this call */
-	spin_unlock(&dev->count_lock);
-
-	if (copy_from_user(&request,
-			   (drm_buf_info_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
-		if (dma->bufs[i].buf_count) ++count;
-	}
-	
-	if (request.count >= count) {
-		for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
-			if (dma->bufs[i].buf_count) {
-				if (copy_to_user(&request.list[count].count,
-						 &dma->bufs[i].buf_count,
-						 sizeof(dma->bufs[0]
-							.buf_count)) ||
-				    copy_to_user(&request.list[count].size,
-						 &dma->bufs[i].buf_size,
-						 sizeof(dma->bufs[0].buf_size)) ||
-				    copy_to_user(&request.list[count].low_mark,
-						 &dma->bufs[i]
-						 .freelist.low_mark,
-						 sizeof(dma->bufs[0]
-							.freelist.low_mark)) ||
-				    copy_to_user(&request.list[count]
-						 .high_mark,
-						 &dma->bufs[i]
-						 .freelist.high_mark,
-						 sizeof(dma->bufs[0]
-							.freelist.high_mark)))
-					return -EFAULT;
-				++count;
-			}
-		}
-	}
-	request.count = count;
-
-	if (copy_to_user((drm_buf_info_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-	
-	return 0;
-}
-
-int mga_markbufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_desc_t	 request;
-	int		 order;
-	drm_buf_entry_t	 *entry;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
-		return -EFAULT;
-
-	order = drm_order(request.size);
-	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-	entry = &dma->bufs[order];
-
-	if (request.low_mark < 0 || request.low_mark > entry->buf_count)
-		return -EINVAL;
-	if (request.high_mark < 0 || request.high_mark > entry->buf_count)
-		return -EINVAL;
-
-	entry->freelist.low_mark  = request.low_mark;
-	entry->freelist.high_mark = request.high_mark;
-	
-	return 0;
-}
-
-int mga_freebufs(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_device_dma_t *dma	 = dev->dma;
-	drm_buf_free_t	 request;
-	int		 i;
-	int		 idx;
-	drm_buf_t	 *buf;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_free_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	for (i = 0; i < request.count; i++) {
-		if (copy_from_user(&idx,
-				   &request.list[i],
-				   sizeof(idx)))
-			return -EFAULT;
-		if (idx < 0 || idx >= dma->buf_count) {
-			DRM_ERROR("Index %d (of %d max)\n",
-				  idx, dma->buf_count - 1);
-			return -EINVAL;
-		}
-		buf = dma->buflist[idx];
-		if (buf->pid != current->pid) {
-			DRM_ERROR("Process %d freeing buffer owned by %d\n",
-				  current->pid, buf->pid);
-			return -EINVAL;
-		}
-		drm_free_buffer(dev, buf);
-	}
-	
-	return 0;
-}
-
-int mga_mapbufs(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_device_dma_t *dma	 = dev->dma;
-	int		 retcode = 0;
-	const int	 zero	 = 0;
-	unsigned long	 virtual;
-	unsigned long	 address;
-	drm_buf_map_t	 request;
-	int		 i;
-
-	if (!dma) return -EINVAL;
-	
-	spin_lock(&dev->count_lock);
-	if (atomic_read(&dev->buf_alloc)) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	++dev->buf_use;		/* Can't allocate more after this call */
-	spin_unlock(&dev->count_lock);
-
-	if (copy_from_user(&request,
-			   (drm_buf_map_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	if (request.count >= dma->buf_count) {
-		if(dma->flags & _DRM_DMA_USE_AGP) {
-			drm_mga_private_t *dev_priv = dev->dev_private;
-			drm_map_t *map = NULL;
-	 
-			map = dev->maplist[dev_priv->buffer_map_idx];
-			if (!map) {
-				retcode = -EINVAL;
-				goto done;
-			}
-
-			DRM_DEBUG("map->offset : %lx\n", map->offset);
-			DRM_DEBUG("map->size : %lx\n", map->size);
-			DRM_DEBUG("map->type : %d\n", map->type);
-			DRM_DEBUG("map->flags : %x\n", map->flags);
-			DRM_DEBUG("map->handle : %p\n", map->handle);
-			DRM_DEBUG("map->mtrr : %d\n", map->mtrr);
-			down_write(&current->mm->mmap_sem);
-			virtual = do_mmap(filp, 0, map->size, 
-					  PROT_READ|PROT_WRITE,
-					  MAP_SHARED, 
-					  (unsigned long)map->offset);
-			up_write(&current->mm->mmap_sem);
-		} else {
-			down_write(&current->mm->mmap_sem);
-			virtual = do_mmap(filp, 0, dma->byte_count,
-					  PROT_READ|PROT_WRITE, MAP_SHARED, 0);
-			up_write(&current->mm->mmap_sem);
-		}
-		if (virtual > -1024UL) {
-			/* Real error */
-			DRM_DEBUG("mmap error\n");
-			retcode = (signed long)virtual;
-			goto done;
-		}
-		request.virtual = (void *)virtual;
-      
-		for (i = 0; i < dma->buf_count; i++) {
-			if (copy_to_user(&request.list[i].idx,
-					 &dma->buflist[i]->idx,
-					 sizeof(request.list[0].idx))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			if (copy_to_user(&request.list[i].total,
-					 &dma->buflist[i]->total,
-					 sizeof(request.list[0].total))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			if (copy_to_user(&request.list[i].used,
-					 &zero,
-					 sizeof(zero))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			address = virtual + dma->buflist[i]->offset;
-			if (copy_to_user(&request.list[i].address,
-					 &address,
-					 sizeof(address))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-		}
-	}
- done:
-	request.count = dma->buf_count;
-	DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
-   
-	if (copy_to_user((drm_buf_map_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-
-	DRM_DEBUG("retcode : %d\n", retcode);
-
-	return retcode;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga_context.c linux/drivers/char/drm/mga_context.c
--- linux-2.4.8-pre6/drivers/char/drm/mga_context.c	Sun Oct  1 20:00:00 2000
+++ linux/drivers/char/drm/mga_context.c	Wed Dec 31 16:00:00 1969
@@ -1,209 +0,0 @@
-/* mga_context.c -- IOCTLs for mga contexts -*- linux-c -*-
- * Created: Mon Dec 13 09:51:35 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.
- * 
- * Author: Rickard E. (Rik) Faith <faith@valinux.com>
- *	   Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include "mga_drv.h"
-
-static int mga_alloc_queue(drm_device_t *dev)
-{
-   	return drm_ctxbitmap_next(dev);
-}
-
-int mga_context_switch(drm_device_t *dev, int old, int new)
-{
-        char        buf[64];
-
-        atomic_inc(&dev->total_ctx);
-
-        if (test_and_set_bit(0, &dev->context_flag)) {
-                DRM_ERROR("Reentering -- FIXME\n");
-                return -EBUSY;
-        }
-
-#if DRM_DMA_HISTOGRAM
-        dev->ctx_start = get_cycles();
-#endif
-        
-        DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
-        if (new == dev->last_context) {
-                clear_bit(0, &dev->context_flag);
-                return 0;
-        }
-        
-        if (drm_flags & DRM_FLAG_NOCTX) {
-                mga_context_switch_complete(dev, new);
-        } else {
-                sprintf(buf, "C %d %d\n", old, new);
-                drm_write_string(dev, buf);
-        }
-        
-        return 0;
-}
-
-int mga_context_switch_complete(drm_device_t *dev, int new)
-{
-        dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
-        dev->last_switch  = jiffies;
-        
-        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-                DRM_ERROR("Lock isn't held after context switch\n");
-        }
-
-				/* If a context switch is ever initiated
-                                   when the kernel holds the lock, release
-                                   that lock here. */
-#if DRM_DMA_HISTOGRAM
-        atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
-                                                      - dev->ctx_start)]);
-                   
-#endif
-        clear_bit(0, &dev->context_flag);
-        wake_up(&dev->context_wait);
-        
-        return 0;
-}
-
-int mga_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
-{
-	drm_ctx_res_t	res;
-	drm_ctx_t	ctx;
-	int		i;
-
-	if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
-		return -EFAULT;
-	if (res.count >= DRM_RESERVED_CONTEXTS) {
-		memset(&ctx, 0, sizeof(ctx));
-		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-			ctx.handle = i;
-			if (copy_to_user(&res.contexts[i],
-					 &i,
-					 sizeof(i)))
-				return -EFAULT;
-		}
-	}
-	res.count = DRM_RESERVED_CONTEXTS;
-	if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
-		return -EFAULT;
-	return 0;
-}
-
-int mga_addctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	if ((ctx.handle = mga_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
-				/* Skip kernel's context and get a new one. */
-		ctx.handle = mga_alloc_queue(dev);
-	}
-        if (ctx.handle == -1) {
-		return -ENOMEM;
-	}
-	DRM_DEBUG("%d\n", ctx.handle);
-	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int mga_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	unsigned long arg)
-{
-   	/* This does nothing for the mga */
-	return 0;
-}
-
-int mga_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	unsigned long arg)
-{
-	drm_ctx_t ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
-		return -EFAULT;
-	/* This is 0, because we don't hanlde any context flags */
-	ctx.flags = 0;
-	if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int mga_switchctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	return mga_context_switch(dev, dev->last_context, ctx.handle);
-}
-
-int mga_newctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	mga_context_switch_complete(dev, ctx.handle);
-
-	return 0;
-}
-
-int mga_rmctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	if(ctx.handle == DRM_KERNEL_CONTEXT+1) priv->remove_auth_on_close = 1;
-
-      	if(ctx.handle != DRM_KERNEL_CONTEXT) {
-	   	drm_ctxbitmap_free(dev, ctx.handle);
-	}
-	
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga_dma.c linux/drivers/char/drm/mga_dma.c
--- linux-2.4.8-pre6/drivers/char/drm/mga_dma.c	Mon Dec 11 12:39:44 2000
+++ linux/drivers/char/drm/mga_dma.c	Mon Dec  3 22:59:45 2001
@@ -24,1028 +24,790 @@
  * 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>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *	    Keith Whitwell <keithw@valinux.com>
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Keith Whitwell <keithw@valinux.com>
  *
+ * Rewritten by:
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #define __NO_VERSION__
+#include "mga.h"
 #include "drmP.h"
 #include "mga_drv.h"
 
 #include <linux/interrupt.h>	/* For task queue support */
+#include <linux/delay.h>
 
-#define MGA_REG(reg)		2
-#define MGA_BASE(reg)		((unsigned long) \
-				((drm_device_t *)dev)->maplist[MGA_REG(reg)]->handle)
-#define MGA_ADDR(reg)		(MGA_BASE(reg) + reg)
-#define MGA_DEREF(reg)		*(__volatile__ int *)MGA_ADDR(reg)
-#define MGA_READ(reg)		MGA_DEREF(reg)
-#define MGA_WRITE(reg,val) 	do { MGA_DEREF(reg) = val; } while (0)
+#define MGA_DEFAULT_USEC_TIMEOUT	10000
+#define MGA_FREELIST_DEBUG		0
 
-#define PDEA_pagpxfer_enable 	     0x2
 
-static int mga_flush_queue(drm_device_t *dev);
+/* ================================================================
+ * Engine control
+ */
 
-static unsigned long mga_alloc_page(drm_device_t *dev)
+int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )
 {
-	unsigned long address;
+	u32 status = 0;
+	int i;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	address = __get_free_page(GFP_KERNEL);
-	if(address == 0UL) {
-		return 0;
+	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
+		status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
+		if ( status == MGA_ENDPRDMASTS ) {
+			MGA_WRITE8( MGA_CRTC_INDEX, 0 );
+			return 0;
+		}
+		udelay( 1 );
 	}
-	atomic_inc(&virt_to_page(address)->count);
-	set_bit(PG_reserved, &virt_to_page(address)->flags);
 
-	return address;
+#if MGA_DMA_DEBUG
+	DRM_ERROR( "failed!\n" );
+	DRM_INFO( "   status=0x%08x\n", status );
+#endif
+	return -EBUSY;
 }
 
-static void mga_free_page(drm_device_t *dev, unsigned long page)
+int mga_do_dma_idle( drm_mga_private_t *dev_priv )
 {
-	if(!page) return;
-	atomic_dec(&virt_to_page(page)->count);
-	clear_bit(PG_reserved, &virt_to_page(page)->flags);
-	free_page(page);
-	return;
+	u32 status = 0;
+	int i;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	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 );
+	}
+
+#if MGA_DMA_DEBUG
+	DRM_ERROR( "failed! status=0x%08x\n", status );
+#endif
+	return -EBUSY;
 }
 
-static void mga_delay(void)
+int mga_do_dma_reset( drm_mga_private_t *dev_priv )
 {
-	return;
-}
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 
-/* These are two age tags that will never be sent to
- * the hardware */
-#define MGA_BUF_USED 	0xffffffff
-#define MGA_BUF_FREE	0
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-static int mga_freelist_init(drm_device_t *dev)
-{
-      	drm_device_dma_t *dma = dev->dma;
-   	drm_buf_t *buf;
-   	drm_mga_buf_priv_t *buf_priv;
-      	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-   	drm_mga_freelist_t *item;
-   	int i;
-
-   	dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
-	if(dev_priv->head == NULL) return -ENOMEM;
-   	memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
-   	dev_priv->head->age = MGA_BUF_USED;
+	/* The primary DMA stream should look like new right about now.
+	 */
+	primary->tail = 0;
+	primary->space = primary->size;
+	primary->last_flush = 0;
 
-   	for (i = 0; i < dma->buf_count; i++) {
-	   	buf = dma->buflist[ i ];
-	        buf_priv = buf->dev_private;
-		item = drm_alloc(sizeof(drm_mga_freelist_t),
-				 DRM_MEM_DRIVER);
-	   	if(item == NULL) return -ENOMEM;
-	   	memset(item, 0, sizeof(drm_mga_freelist_t));
-	  	item->age = MGA_BUF_FREE;
-	   	item->prev = dev_priv->head;
-	   	item->next = dev_priv->head->next;
-	   	if(dev_priv->head->next != NULL)
-			dev_priv->head->next->prev = item;
-	   	if(item->next == NULL) dev_priv->tail = item;
-	   	item->buf = buf;
-	   	buf_priv->my_freelist = item;
-		buf_priv->discard = 0;
-		buf_priv->dispatched = 0;
-	   	dev_priv->head->next = item;
-	}
+	sarea_priv->last_wrap = 0;
 
-   	return 0;
-}
+	/* FIXME: Reset counters, buffer ages etc...
+	 */
 
-static void mga_freelist_cleanup(drm_device_t *dev)
-{
-      	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-   	drm_mga_freelist_t *item;
-   	drm_mga_freelist_t *prev;
-
-   	item = dev_priv->head;
-   	while(item) {
-	   	prev = item;
-	   	item = item->next;
-	   	drm_free(prev, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
-	}
+	/* FIXME: What else do we need to reinitialize?  WARP stuff?
+	 */
 
-   	dev_priv->head = dev_priv->tail = NULL;
+	return 0;
 }
 
-/* Frees dispatch lock */
-static inline void mga_dma_quiescent(drm_device_t *dev)
+int mga_do_engine_reset( drm_mga_private_t *dev_priv )
 {
-	drm_device_dma_t  *dma      = dev->dma;
-	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-   	unsigned long end;
-	int i;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	DRM_DEBUG("dispatch_status = 0x%02lx\n", dev_priv->dispatch_status);
-	end = jiffies + (HZ*3);
-    	while(1) {
-		if(!test_and_set_bit(MGA_IN_DISPATCH,
-				     &dev_priv->dispatch_status)) {
-			break;
-		}
-	   	if((signed)(end - jiffies) <= 0) {
-			DRM_ERROR("irqs: %d wanted %d\n",
-				  atomic_read(&dev->total_irq),
-				  atomic_read(&dma->total_lost));
-			DRM_ERROR("lockup: dispatch_status = 0x%02lx,"
-				  " jiffies = %lu, end = %lu\n",
-				  dev_priv->dispatch_status, jiffies, end);
-			return;
-		}
-		for (i = 0 ; i < 2000 ; i++) mga_delay();
-	}
-	end = jiffies + (HZ*3);
-    	DRM_DEBUG("quiescent status : %x\n", MGA_READ(MGAREG_STATUS));
-    	while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) {
-		if((signed)(end - jiffies) <= 0) {
-			DRM_ERROR("irqs: %d wanted %d\n",
-				  atomic_read(&dev->total_irq),
-				  atomic_read(&dma->total_lost));
-			DRM_ERROR("lockup\n");
-			clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
-			return;
-		}
-		for (i = 0 ; i < 2000 ; i++) mga_delay();
-	}
-    	sarea_priv->dirty |= MGA_DMA_FLUSH;
+	/* 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 */
+	MGA_WRITE( MGA_RST, 0 );
+
+	/* Initialize the registers that get clobbered by the soft
+	 * reset.  Many of the core register values survive a reset,
+	 * but the drawing registers are basically all gone.
+	 *
+	 * 3D clients should probably die after calling this.  The X
+	 * server should reset the engine state to known values.
+	 */
+#if 0
+	MGA_WRITE( MGA_PRIMPTR,
+		   virt_to_bus((void *)dev_priv->prim.status_page) |
+		   MGA_PRIMPTREN0 |
+		   MGA_PRIMPTREN1 );
+#endif
 
-    	clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
-	DRM_DEBUG("exit, dispatch_status = 0x%02lx\n",
-		  dev_priv->dispatch_status);
-}
+	MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR );
+	MGA_WRITE( MGA_IEN,    MGA_SOFTRAPIEN );
 
-static void mga_reset_freelist(drm_device_t *dev)
-{
-   	drm_device_dma_t  *dma      = dev->dma;
-   	drm_buf_t *buf;
-   	drm_mga_buf_priv_t *buf_priv;
-	int i;
+	/* The primary DMA stream should look like new right about now.
+	 */
+	mga_do_dma_reset( dev_priv );
 
-   	for (i = 0; i < dma->buf_count; i++) {
-	   	buf = dma->buflist[ i ];
-	        buf_priv = buf->dev_private;
-		buf_priv->my_freelist->age = MGA_BUF_FREE;
-	}
+	/* This bad boy will never fail.
+	 */
+	return 0;
 }
 
-/* Least recently used :
- * These operations are not atomic b/c they are protected by the
- * hardware lock */
 
-drm_buf_t *mga_freelist_get(drm_device_t *dev)
+/* ================================================================
+ * Primary DMA stream
+ */
+
+void mga_do_dma_flush( drm_mga_private_t *dev_priv )
 {
-   	DECLARE_WAITQUEUE(entry, current);
-   	drm_mga_private_t *dev_priv =
-     		(drm_mga_private_t *) dev->dev_private;
-	drm_mga_freelist_t *prev;
-   	drm_mga_freelist_t *next;
-	static int failed = 0;
-	int return_null = 0;
-
-	if(failed >= 1000 && dev_priv->tail->age >= dev_priv->last_prim_age) {
-		DRM_DEBUG("Waiting on freelist,"
-			  " tail->age = %d, last_prim_age= %d\n",
-			  dev_priv->tail->age,
-			  dev_priv->last_prim_age);
-	   	add_wait_queue(&dev_priv->buf_queue, &entry);
-		set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
-	   	for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-		   	mga_dma_schedule(dev, 0);
-			if(dev_priv->tail->age < dev_priv->last_prim_age)
-				break;
-		   	atomic_inc(&dev->total_sleeps);
-		   	schedule();
-		   	if (signal_pending(current)) {
-				++return_null;
-				break;
-			}
-		}
-		clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
-		current->state = TASK_RUNNING;
-	   	remove_wait_queue(&dev_priv->buf_queue, &entry);
-		if (return_null) return NULL;
-	}
+	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+	u32 head, tail;
+	DMA_LOCALS;
+	DRM_DEBUG( "%s:\n", __FUNCTION__ );
 
-   	if(dev_priv->tail->age < dev_priv->last_prim_age) {
-		prev = dev_priv->tail->prev;
-	   	next = dev_priv->tail;
-	   	prev->next = NULL;
-	   	next->prev = next->next = NULL;
-	   	dev_priv->tail = prev;
-	   	next->age = MGA_BUF_USED;
-		failed = 0;
-	   	return next->buf;
+	if ( primary->tail == primary->last_flush ) {
+		DRM_DEBUG( "   bailing out...\n" );
+		return;
 	}
 
-	failed++;
-   	return NULL;
-}
+	tail = primary->tail + dev_priv->primary->offset;
 
-int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf)
-{
-      	drm_mga_private_t *dev_priv =
-     		(drm_mga_private_t *) dev->dev_private;
-   	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
-	drm_mga_freelist_t *prev;
-   	drm_mga_freelist_t *head;
-   	drm_mga_freelist_t *next;
+	/* We need to pad the stream between flushes, as the card
+	 * actually (partially?) reads the first of these commands.
+	 * See page 4-16 in the G400 manual, middle of the page or so.
+	 */
+	BEGIN_DMA( 1 );
 
-   	if(buf_priv->my_freelist->age == MGA_BUF_USED) {
-		/* Discarded buffer, put it on the tail */
-		next = buf_priv->my_freelist;
-		next->age = MGA_BUF_FREE;
-		prev = dev_priv->tail;
-		prev->next = next;
-		next->prev = prev;
-		next->next = NULL;
-		dev_priv->tail = next;
+	DMA_BLOCK( MGA_DMAPAD,  0x00000000,
+		   MGA_DMAPAD,  0x00000000,
+		   MGA_DMAPAD,  0x00000000,
+		   MGA_DMAPAD,	0x00000000 );
+
+	ADVANCE_DMA();
+
+	primary->last_flush = primary->tail;
+
+	head = MGA_READ( MGA_PRIMADDRESS );
+
+	if ( head <= tail ) {
+		primary->space = primary->size - primary->tail;
 	} else {
-		/* Normally aged buffer, put it on the head + 1,
-		 * as the real head is a sentinal element
-		 */
-		next = buf_priv->my_freelist;
-		head = dev_priv->head;
-		prev = head->next;
-		head->next = next;
-		prev->prev = next;
-		next->prev = head;
-		next->next = prev;
+		primary->space = head - tail;
 	}
 
-   	return 0;
+	DRM_DEBUG( "   head = 0x%06lx\n", head - dev_priv->primary->offset );
+	DRM_DEBUG( "   tail = 0x%06lx\n", tail - dev_priv->primary->offset );
+	DRM_DEBUG( "  space = 0x%06x\n", primary->space );
+
+	mga_flush_write_combine();
+	MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+
+	DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
 }
 
-static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init)
+void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
 {
-   	drm_mga_private_t *dev_priv = dev->dev_private;
-	drm_mga_prim_buf_t *prim_buffer;
-   	int i, temp, size_of_buf;
-   	int offset = init->reserved_map_agpstart;
-
-   	dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) /
-				  PAGE_SIZE) * PAGE_SIZE;
-   	size_of_buf = dev_priv->primary_size / MGA_NUM_PRIM_BUFS;
-	dev_priv->warp_ucode_size = init->warp_ucode_size;
-   	dev_priv->prim_bufs = drm_alloc(sizeof(drm_mga_prim_buf_t *) *
-					(MGA_NUM_PRIM_BUFS + 1),
-					DRM_MEM_DRIVER);
-   	if(dev_priv->prim_bufs == NULL) {
-		DRM_ERROR("Unable to allocate memory for prim_buf\n");
-		return -ENOMEM;
-	}
-   	memset(dev_priv->prim_bufs,
-	       0, sizeof(drm_mga_prim_buf_t *) * (MGA_NUM_PRIM_BUFS + 1));
+	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+	u32 head, tail;
+	DMA_LOCALS;
+	DRM_DEBUG( "%s:\n", __FUNCTION__ );
 
-   	temp = init->warp_ucode_size + dev_priv->primary_size;
-	temp = ((temp + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
+	BEGIN_DMA_WRAP();
 
-	dev_priv->ioremap = drm_ioremap(dev->agp->base + offset,
-					temp);
-	if(dev_priv->ioremap == NULL) {
-		DRM_ERROR("Ioremap failed\n");
-		return -ENOMEM;
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000 );
+
+	ADVANCE_DMA();
+
+	tail = primary->tail + dev_priv->primary->offset;
+
+	primary->tail = 0;
+	primary->last_flush = 0;
+	primary->last_wrap++;
+
+	head = MGA_READ( MGA_PRIMADDRESS );
+
+	if ( head == dev_priv->primary->offset ) {
+		primary->space = primary->size;
+	} else {
+		primary->space = head - dev_priv->primary->offset;
 	}
-   	init_waitqueue_head(&dev_priv->wait_queue);
 
-   	for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) {
-	   	prim_buffer = drm_alloc(sizeof(drm_mga_prim_buf_t),
-					DRM_MEM_DRIVER);
-	   	if(prim_buffer == NULL) return -ENOMEM;
-	   	memset(prim_buffer, 0, sizeof(drm_mga_prim_buf_t));
-	   	prim_buffer->phys_head = offset + dev->agp->base;
-	   	prim_buffer->current_dma_ptr =
-			prim_buffer->head =
-			(u32 *) (dev_priv->ioremap +
-				 offset -
-				 init->reserved_map_agpstart);
-	   	prim_buffer->num_dwords = 0;
-	   	prim_buffer->max_dwords = size_of_buf / sizeof(u32);
-	   	prim_buffer->max_dwords -= 5; /* Leave room for the softrap */
-	   	prim_buffer->sec_used = 0;
-	   	prim_buffer->idx = i;
-		prim_buffer->prim_age = i + 1;
-	   	offset = offset + size_of_buf;
-	   	dev_priv->prim_bufs[i] = prim_buffer;
-	}
-	dev_priv->current_prim_idx = 0;
-        dev_priv->next_prim =
-		dev_priv->last_prim =
-		dev_priv->current_prim =
-        	dev_priv->prim_bufs[0];
-	dev_priv->next_prim_age = 2;
-	dev_priv->last_prim_age = 1;
-   	set_bit(MGA_BUF_IN_USE, &dev_priv->current_prim->buffer_status);
-   	return 0;
+	DRM_DEBUG( "   head = 0x%06lx\n",
+		  head - dev_priv->primary->offset );
+	DRM_DEBUG( "   tail = 0x%06x\n", primary->tail );
+	DRM_DEBUG( "   wrap = %d\n", primary->last_wrap );
+	DRM_DEBUG( "  space = 0x%06x\n", primary->space );
+
+	mga_flush_write_combine();
+	MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
+
+	set_bit( 0, &primary->wrapped );
+	DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
 }
 
-void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
+void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
 {
-       	drm_mga_private_t *dev_priv = dev->dev_private;
-      	drm_device_dma_t  *dma	    = dev->dma;
-       	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- 	int use_agp = PDEA_pagpxfer_enable;
-	unsigned long end;
-   	int i;
-   	int next_idx;
-       	PRIMLOCALS;
-
-   	dev_priv->last_prim = prim;
-
- 	/* We never check for overflow, b/c there is always room */
-    	PRIMPTR(prim);
-   	if(num_dwords <= 0) {
-		DRM_ERROR("num_dwords == 0 when dispatched\n");
-		goto out_prim_wait;
-	}
- 	PRIMOUTREG( MGAREG_DMAPAD, 0);
- 	PRIMOUTREG( MGAREG_DMAPAD, 0);
-       	PRIMOUTREG( MGAREG_DMAPAD, 0);
-   	PRIMOUTREG( MGAREG_SOFTRAP, 0);
-    	PRIMFINISH(prim);
-
-	end = jiffies + (HZ*3);
-    	if(sarea_priv->dirty & MGA_DMA_FLUSH) {
-		while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) {
-			if((signed)(end - jiffies) <= 0) {
-				DRM_ERROR("irqs: %d wanted %d\n",
-					  atomic_read(&dev->total_irq),
-					  atomic_read(&dma->total_lost));
-				DRM_ERROR("lockup (flush)\n");
-				goto out_prim_wait;
-			}
+	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__ );
 
-			for (i = 0 ; i < 4096 ; i++) mga_delay();
-		}
-		sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
-	} else {
-		while((MGA_READ(MGAREG_STATUS) & 0x00020001) != 0x00020000) {
-			if((signed)(end - jiffies) <= 0) {
-				DRM_ERROR("irqs: %d wanted %d\n",
-					  atomic_read(&dev->total_irq),
-					  atomic_read(&dma->total_lost));
-				DRM_ERROR("lockup (wait)\n");
-				goto out_prim_wait;
-			}
+	sarea_priv->last_wrap++;
+	DRM_DEBUG( "   wrap = %d\n", sarea_priv->last_wrap );
 
-			for (i = 0 ; i < 4096 ; i++) mga_delay();
-		}
-	}
+	mga_flush_write_combine();
+	MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );
 
-   	mga_flush_write_combine();
-    	atomic_inc(&dev_priv->pending_bufs);
-       	MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
- 	MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
-   	prim->num_dwords = 0;
-	sarea_priv->last_enqueue = prim->prim_age;
-
-   	next_idx = prim->idx + 1;
-    	if(next_idx >= MGA_NUM_PRIM_BUFS)
-		next_idx = 0;
-
-    	dev_priv->next_prim = dev_priv->prim_bufs[next_idx];
-	return;
-
- out_prim_wait:
-	prim->num_dwords = 0;
-	prim->sec_used = 0;
-	clear_bit(MGA_BUF_IN_USE, &prim->buffer_status);
-   	wake_up_interruptible(&dev_priv->wait_queue);
-	clear_bit(MGA_BUF_SWAP_PENDING, &prim->buffer_status);
-	clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
+	clear_bit( 0, &primary->wrapped );
+	DRM_DEBUG( "%s: done.\n", __FUNCTION__ );
 }
 
-int mga_advance_primary(drm_device_t *dev)
+
+/* ================================================================
+ * Freelist management
+ */
+
+#define MGA_BUFFER_USED		~0
+#define MGA_BUFFER_FREE		0
+
+#if MGA_FREELIST_DEBUG
+static void mga_freelist_print( drm_device_t *dev )
 {
-   	DECLARE_WAITQUEUE(entry, current);
-   	drm_mga_private_t *dev_priv = dev->dev_private;
-   	drm_mga_prim_buf_t *prim_buffer;
-   	drm_device_dma_t  *dma      = dev->dma;
-   	int next_prim_idx;
-   	int ret = 0;
-
-   	/* This needs to reset the primary buffer if available,
-	 * we should collect stats on how many times it bites
-	 * it's tail */
-
-   	next_prim_idx = dev_priv->current_prim_idx + 1;
-   	if(next_prim_idx >= MGA_NUM_PRIM_BUFS)
-     		next_prim_idx = 0;
-   	prim_buffer = dev_priv->prim_bufs[next_prim_idx];
-	set_bit(MGA_IN_WAIT, &dev_priv->dispatch_status);
-
-      	/* In use is cleared in interrupt handler */
-
-   	if(test_and_set_bit(MGA_BUF_IN_USE, &prim_buffer->buffer_status)) {
-	   	add_wait_queue(&dev_priv->wait_queue, &entry);
-	   	for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-		   	mga_dma_schedule(dev, 0);
-		   	if(!test_and_set_bit(MGA_BUF_IN_USE,
-					     &prim_buffer->buffer_status))
-				break;
-		   	atomic_inc(&dev->total_sleeps);
-		   	atomic_inc(&dma->total_missed_sched);
-		   	schedule();
-		   	if (signal_pending(current)) {
-			   	ret = -ERESTARTSYS;
-			   	break;
-			}
-		}
-		current->state = TASK_RUNNING;
-	   	remove_wait_queue(&dev_priv->wait_queue, &entry);
-	   	if(ret) return ret;
-	}
-	clear_bit(MGA_IN_WAIT, &dev_priv->dispatch_status);
-
-   	/* This primary buffer is now free to use */
-   	prim_buffer->current_dma_ptr = prim_buffer->head;
-   	prim_buffer->num_dwords = 0;
-   	prim_buffer->sec_used = 0;
-	prim_buffer->prim_age = dev_priv->next_prim_age++;
-	if(prim_buffer->prim_age == 0 || prim_buffer->prim_age == 0xffffffff) {
-		mga_flush_queue(dev);
-		mga_dma_quiescent(dev);
-		mga_reset_freelist(dev);
-		prim_buffer->prim_age = (dev_priv->next_prim_age += 2);
-	}
-
-	/* Reset all buffer status stuff */
-	clear_bit(MGA_BUF_NEEDS_OVERFLOW, &prim_buffer->buffer_status);
-	clear_bit(MGA_BUF_FORCE_FIRE, &prim_buffer->buffer_status);
-	clear_bit(MGA_BUF_SWAP_PENDING, &prim_buffer->buffer_status);
-
-   	dev_priv->current_prim = prim_buffer;
-   	dev_priv->current_prim_idx = next_prim_idx;
-   	return 0;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_freelist_t *entry;
+
+	DRM_INFO( "\n" );
+	DRM_INFO( "current dispatch: last=0x%x done=0x%x\n",
+		  dev_priv->sarea_priv->last_dispatch,
+		  (unsigned int)(MGA_READ( MGA_PRIMADDRESS ) -
+				 dev_priv->primary->offset) );
+	DRM_INFO( "current freelist:\n" );
+
+	for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) {
+		DRM_INFO( "   %p   idx=%2d  age=0x%x 0x%06lx\n",
+			  entry, entry->buf->idx, entry->age.head,
+			  entry->age.head - dev_priv->primary->offset );
+	}
+	DRM_INFO( "\n" );
 }
+#endif
 
-/* More dynamic performance decisions */
-static inline int mga_decide_to_fire(drm_device_t *dev)
+static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
 {
-   	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_mga_buf_priv_t *buf_priv;
+	drm_mga_freelist_t *entry;
+	int i;
+	DRM_DEBUG( "%s: count=%d\n",
+		   __FUNCTION__, dma->buf_count );
 
-   	if(test_bit(MGA_BUF_FORCE_FIRE, &dev_priv->next_prim->buffer_status)) {
-	   	return 1;
-	}
+	dev_priv->head = DRM(alloc)( sizeof(drm_mga_freelist_t),
+				     DRM_MEM_DRIVER );
+	if ( dev_priv->head == NULL )
+		return -ENOMEM;
 
-	if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) &&
-	    dev_priv->next_prim->num_dwords) {
-	   	return 1;
-	}
+	memset( dev_priv->head, 0, sizeof(drm_mga_freelist_t) );
+	SET_AGE( &dev_priv->head->age, MGA_BUFFER_USED, 0 );
 
-	if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
-	    dev_priv->next_prim->num_dwords) {
-	   	return 1;
-	}
+	for ( i = 0 ; i < dma->buf_count ; i++ ) {
+		buf = dma->buflist[i];
+	        buf_priv = buf->dev_private;
 
-   	if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS - 1) {
-		if(test_bit(MGA_BUF_SWAP_PENDING,
-			    &dev_priv->next_prim->buffer_status)) {
-			return 1;
-		}
-	}
+		entry = DRM(alloc)( sizeof(drm_mga_freelist_t),
+				    DRM_MEM_DRIVER );
+		if ( entry == NULL )
+			return -ENOMEM;
+
+		memset( entry, 0, sizeof(drm_mga_freelist_t) );
+
+		entry->next = dev_priv->head->next;
+		entry->prev = dev_priv->head;
+		SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
+		entry->buf = buf;
+
+		if ( dev_priv->head->next != NULL )
+			dev_priv->head->next->prev = entry;
+		if ( entry->next == NULL )
+			dev_priv->tail = entry;
 
-   	if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS / 2) {
-		if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 8) {
-			return 1;
-		}
-	}
+		buf_priv->list_entry = entry;
+		buf_priv->discard = 0;
+		buf_priv->dispatched = 0;
 
-   	if(atomic_read(&dev_priv->pending_bufs) >= MGA_NUM_PRIM_BUFS / 2) {
-		if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 4) {
-			return 1;
-		}
+		dev_priv->head->next = entry;
 	}
 
-   	return 0;
+	return 0;
 }
 
-int mga_dma_schedule(drm_device_t *dev, int locked)
+static void mga_freelist_cleanup( drm_device_t *dev )
 {
-      	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-	int               retval    = 0;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_freelist_t *entry;
+	drm_mga_freelist_t *next;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-   	if (!dev_priv) return -EBUSY;
-	
-	if (test_and_set_bit(0, &dev->dma_flag)) {
-		retval = -EBUSY;
-		goto sch_out_wakeup;
-	}
-
-   	if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) ||
-	   test_bit(MGA_IN_WAIT, &dev_priv->dispatch_status) ||
-	   test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) {
-		locked = 1;
-	}
-
-   	if (!locked &&
-	    !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) {
-	   	clear_bit(0, &dev->dma_flag);
-		retval = -EBUSY;
-		goto sch_out_wakeup;
-	}
-
-   	if(!test_and_set_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status)) {
-	   	/* Fire dma buffer */
-	   	if(mga_decide_to_fire(dev)) {
-			clear_bit(MGA_BUF_FORCE_FIRE,
-				  &dev_priv->next_prim->buffer_status);
-		   	if(dev_priv->current_prim == dev_priv->next_prim) {
-				/* Schedule overflow for a later time */
-				set_bit(MGA_BUF_NEEDS_OVERFLOW,
-					&dev_priv->next_prim->buffer_status);
-			}
-		   	mga_fire_primary(dev, dev_priv->next_prim);
-		} else {
-			clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
-		}
+	entry = dev_priv->head;
+	while ( entry ) {
+		next = entry->next;
+		DRM(free)( entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER );
+		entry = next;
 	}
 
-	if (!locked) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
-				  DRM_KERNEL_CONTEXT)) {
-			DRM_ERROR("\n");
-		}
-	}
+	dev_priv->head = dev_priv->tail = NULL;
+}
 
-	clear_bit(0, &dev->dma_flag);
+#if 0
+/* FIXME: Still needed?
+ */
+static void mga_freelist_reset( drm_device_t *dev )
+{
+	drm_device_dma_t *dma = dev->dma;
+	drm_buf_t *buf;
+	drm_mga_buf_priv_t *buf_priv;
+	int i;
 
-sch_out_wakeup:
-      	if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
-	   atomic_read(&dev_priv->pending_bufs) == 0) {
-		/* Everything has been processed by the hardware */
-		clear_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status);
-		wake_up_interruptible(&dev_priv->flush_queue);
+	for ( i = 0 ; i < dma->buf_count ; i++ ) {
+		buf = dma->buflist[i];
+	        buf_priv = buf->dev_private;
+		SET_AGE( &buf_priv->list_entry->age,
+			 MGA_BUFFER_FREE, 0 );
 	}
-
-	if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)
-	   && dev_priv->tail->age < dev_priv->last_prim_age)
-		wake_up_interruptible(&dev_priv->buf_queue);
-
-	return retval;
 }
+#endif
 
-static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
+static drm_buf_t *mga_freelist_get( drm_device_t *dev )
 {
-    	drm_device_t	 *dev = (drm_device_t *)device;
-    	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-    	drm_mga_prim_buf_t *last_prim_buffer;
-
-    	atomic_inc(&dev->total_irq);
-	if((MGA_READ(MGAREG_STATUS) & 0x00000001) != 0x00000001) return;
-      	MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
-   	last_prim_buffer = dev_priv->last_prim;
-    	last_prim_buffer->num_dwords = 0;
-    	last_prim_buffer->sec_used = 0;
-	dev_priv->sarea_priv->last_dispatch =
-		dev_priv->last_prim_age = last_prim_buffer->prim_age;
-      	clear_bit(MGA_BUF_IN_USE, &last_prim_buffer->buffer_status);
-      	clear_bit(MGA_BUF_SWAP_PENDING, &last_prim_buffer->buffer_status);
-      	clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
-      	atomic_dec(&dev_priv->pending_bufs);
-   	queue_task(&dev->tq, &tq_immediate);
-   	mark_bh(IMMEDIATE_BH);
-   	wake_up_interruptible(&dev_priv->wait_queue);
-}
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_freelist_t *next;
+	drm_mga_freelist_t *prev;
+	drm_mga_freelist_t *tail = dev_priv->tail;
+	u32 head, wrap;
+	DRM_DEBUG( "%s:\n", __FUNCTION__ );
+
+	head = MGA_READ( MGA_PRIMADDRESS );
+	wrap = dev_priv->sarea_priv->last_wrap;
+
+	DRM_DEBUG( "   tail=0x%06lx %d\n",
+		   tail->age.head ?
+		   tail->age.head - dev_priv->primary->offset : 0,
+		   tail->age.wrap );
+	DRM_DEBUG( "   head=0x%06lx %d\n",
+		   head - dev_priv->primary->offset, wrap );
 
-static void mga_dma_task_queue(void *device)
-{
-	mga_dma_schedule((drm_device_t *)device, 0);
+	if ( TEST_AGE( &tail->age, head, wrap ) ) {
+		prev = dev_priv->tail->prev;
+		next = dev_priv->tail;
+		prev->next = NULL;
+		next->prev = next->next = NULL;
+		dev_priv->tail = prev;
+		SET_AGE( &next->age, MGA_BUFFER_USED, 0 );
+		return next->buf;
+	}
+
+	DRM_DEBUG( "returning NULL!\n" );
+	return NULL;
 }
 
-int mga_dma_cleanup(drm_device_t *dev)
+int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
 {
-	if(dev->dev_private) {
-		drm_mga_private_t *dev_priv =
-			(drm_mga_private_t *) dev->dev_private;
-
-		if (dev->irq) mga_flush_queue(dev);
-		mga_dma_quiescent(dev);
-
-		if(dev_priv->ioremap) {
-			int temp = (dev_priv->warp_ucode_size +
-				    dev_priv->primary_size +
-				    PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE;
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+	drm_mga_freelist_t *head, *entry, *prev;
 
-			drm_ioremapfree((void *) dev_priv->ioremap, temp);
-		}
-	   	if(dev_priv->status_page != NULL) {
-		   	iounmap(dev_priv->status_page);
-		}
-	   	if(dev_priv->real_status_page != 0UL) {
-		   	mga_free_page(dev, dev_priv->real_status_page);
-		}
-	   	if(dev_priv->prim_bufs != NULL) {
-		   	int i;
-		   	for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) {
-			   	if(dev_priv->prim_bufs[i] != NULL) {
-			     		drm_free(dev_priv->prim_bufs[i],
-						 sizeof(drm_mga_prim_buf_t),
-						 DRM_MEM_DRIVER);
-				}
-			}
-		   	drm_free(dev_priv->prim_bufs, sizeof(void *) *
-				 (MGA_NUM_PRIM_BUFS + 1),
-				 DRM_MEM_DRIVER);
-		}
-		if(dev_priv->head != NULL) {
-		   	mga_freelist_cleanup(dev);
-		}
+	DRM_DEBUG( "%s: age=0x%06lx wrap=%d\n",
+		   __FUNCTION__,
+		   buf_priv->list_entry->age.head -
+		   dev_priv->primary->offset,
+		   buf_priv->list_entry->age.wrap );
 
+	entry = buf_priv->list_entry;
+	head = dev_priv->head;
 
-		drm_free(dev->dev_private, sizeof(drm_mga_private_t),
-			 DRM_MEM_DRIVER);
-		dev->dev_private = NULL;
+	if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) {
+		SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
+		prev = dev_priv->tail;
+		prev->next = entry;
+		entry->prev = prev;
+		entry->next = NULL;
+	} else {
+		prev = head->next;
+		head->next = entry;
+		prev->prev = entry;
+		entry->prev = head;
+		entry->next = prev;
 	}
 
 	return 0;
 }
 
-static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
+
+/* ================================================================
+ * DMA initialization, cleanup
+ */
+
+static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
+{
 	drm_mga_private_t *dev_priv;
-	drm_map_t *sarea_map = NULL;
+	struct list_head *list;
+	int ret;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
+	if ( !dev_priv )
+		return -ENOMEM;
+
+	memset( dev_priv, 0, sizeof(drm_mga_private_t) );
+
+	dev_priv->chipset = init->chipset;
+
+	dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
 
-	dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
-	if(dev_priv == NULL) return -ENOMEM;
-	dev->dev_private = (void *) dev_priv;
+	if ( init->sgram ) {
+		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
+	} else {
+		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
+	}
+	dev_priv->maccess	= init->maccess;
+
+	dev_priv->fb_cpp	= init->fb_cpp;
+	dev_priv->front_offset	= init->front_offset;
+	dev_priv->front_pitch	= init->front_pitch;
+	dev_priv->back_offset	= init->back_offset;
+	dev_priv->back_pitch	= init->back_pitch;
+
+	dev_priv->depth_cpp	= init->depth_cpp;
+	dev_priv->depth_offset	= init->depth_offset;
+	dev_priv->depth_pitch	= init->depth_pitch;
 
-	memset(dev_priv, 0, sizeof(drm_mga_private_t));
+	/* FIXME: Need to support AGP textures...
+	 */
+	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;
+ 		}
+ 	}
+	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;
+	}
 
-	if((init->reserved_map_idx >= dev->map_count) ||
-	   (init->buffer_map_idx >= dev->map_count)) {
-		mga_dma_cleanup(dev);
+	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+	if(!dev_priv->fb) {
+		DRM_ERROR( "failed to find framebuffer!\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
+		return -EINVAL;
+	}
+	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+	if(!dev_priv->mmio) {
+		DRM_ERROR( "failed to find mmio region!\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
+		return -EINVAL;
+	}
+	DRM_FIND_MAP( dev_priv->status, init->status_offset );
+	if(!dev_priv->status) {
+		DRM_ERROR( "failed to find status page!\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
 		return -EINVAL;
 	}
 
-	dev_priv->reserved_map_idx = init->reserved_map_idx;
-	dev_priv->buffer_map_idx = init->buffer_map_idx;
-	sarea_map = dev->maplist[0];
-	dev_priv->sarea_priv = (drm_mga_sarea_t *)
-		((u8 *)sarea_map->handle +
-		 init->sarea_priv_offset);
+	DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
+	if(!dev_priv->warp) {
+		DRM_ERROR( "failed to find warp microcode region!\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
+		return -EINVAL;
+	}
+	DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
+	if(!dev_priv->primary) {
+		DRM_ERROR( "failed to find primary dma region!\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
+		return -EINVAL;
+	}
+	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+	if(!dev_priv->buffers) {
+		DRM_ERROR( "failed to find dma buffer region!\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
+		return -EINVAL;
+	}
 
-	/* Scale primary size to the next page */
-	dev_priv->chipset = init->chipset;
-	dev_priv->frontOffset = init->frontOffset;
-	dev_priv->backOffset = init->backOffset;
-	dev_priv->depthOffset = init->depthOffset;
-	dev_priv->textureOffset = init->textureOffset;
-	dev_priv->textureSize = init->textureSize;
-	dev_priv->cpp = init->cpp;
-	dev_priv->sgram = init->sgram;
-	dev_priv->stride = init->stride;
-
-	dev_priv->mAccess = init->mAccess;
-   	init_waitqueue_head(&dev_priv->flush_queue);
-	init_waitqueue_head(&dev_priv->buf_queue);
-	dev_priv->WarpPipe = 0xff000000;
-	dev_priv->vertexsize = 0;
-
-   	DRM_DEBUG("chipset=%d ucode_size=%d backOffset=%x depthOffset=%x\n",
-		  dev_priv->chipset, dev_priv->warp_ucode_size,
-		  dev_priv->backOffset, dev_priv->depthOffset);
-   	DRM_DEBUG("cpp: %d sgram: %d stride: %d maccess: %x\n",
-		  dev_priv->cpp, dev_priv->sgram, dev_priv->stride,
-		  dev_priv->mAccess);
-
-	memcpy(&dev_priv->WarpIndex, &init->WarpIndex,
-	       sizeof(drm_mga_warp_index_t) * MGA_MAX_WARP_PIPES);
-
-   	if(mga_init_primary_bufs(dev, init) != 0) {
-		DRM_ERROR("Can not initialize primary buffers\n");
-		mga_dma_cleanup(dev);
+	dev_priv->sarea_priv =
+		(drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
+				    init->sarea_priv_offset);
+
+	DRM_IOREMAP( dev_priv->warp );
+	DRM_IOREMAP( dev_priv->primary );
+	DRM_IOREMAP( dev_priv->buffers );
+
+	if(!dev_priv->warp->handle ||
+	   !dev_priv->primary->handle ||
+	   !dev_priv->buffers->handle ) {
+		DRM_ERROR( "failed to ioremap agp regions!\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
 		return -ENOMEM;
 	}
-   	dev_priv->real_status_page = mga_alloc_page(dev);
-      	if(dev_priv->real_status_page == 0UL) {
-		mga_dma_cleanup(dev);
-		DRM_ERROR("Can not allocate status page\n");
-		return -ENOMEM;
+
+	ret = mga_warp_install_microcode( dev_priv );
+	if ( ret < 0 ) {
+		DRM_ERROR( "failed to install WARP ucode!\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
+		return ret;
 	}
 
-   	dev_priv->status_page =
-		ioremap_nocache(virt_to_bus((void *)dev_priv->real_status_page),
-				PAGE_SIZE);
-
-   	if(dev_priv->status_page == NULL) {
-		mga_dma_cleanup(dev);
-		DRM_ERROR("Can not remap status page\n");
-		return -ENOMEM;
+	ret = mga_warp_init( dev_priv );
+	if ( ret < 0 ) {
+		DRM_ERROR( "failed to init WARP engine!\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
+		return ret;
 	}
 
-   	/* Write status page when secend or softrap occurs */
-   	MGA_WRITE(MGAREG_PRIMPTR,
-		  virt_to_bus((void *)dev_priv->real_status_page) | 0x00000003);
+	dev_priv->prim.status = (u32 *)dev_priv->status->handle;
+
+	mga_do_wait_for_idle( dev_priv );
+
+	/* Init the primary DMA registers.
+	 */
+	MGA_WRITE( MGA_PRIMADDRESS,
+		   dev_priv->primary->offset | MGA_DMA_GENERAL );
+#if 0
+	MGA_WRITE( MGA_PRIMPTR,
+		   virt_to_bus((void *)dev_priv->prim.status) |
+		   MGA_PRIMPTREN0 |	/* Soft trap, SECEND, SETUPEND */
+		   MGA_PRIMPTREN1 );	/* DWGSYNC */
+#endif
+
+	dev_priv->prim.start = (u8 *)dev_priv->primary->handle;
+	dev_priv->prim.end = ((u8 *)dev_priv->primary->handle
+			      + dev_priv->primary->size);
+	dev_priv->prim.size = dev_priv->primary->size;
+
+	dev_priv->prim.tail = 0;
+	dev_priv->prim.space = dev_priv->prim.size;
+	dev_priv->prim.wrapped = 0;
+
+	dev_priv->prim.last_flush = 0;
+	dev_priv->prim.last_wrap = 0;
+
+	dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
+
+	spin_lock_init( &dev_priv->prim.list_lock );
+
+	dev_priv->prim.status[0] = dev_priv->primary->offset;
+	dev_priv->prim.status[1] = 0;
+
+	dev_priv->sarea_priv->last_wrap = 0;
+	dev_priv->sarea_priv->last_frame.head = 0;
+	dev_priv->sarea_priv->last_frame.wrap = 0;
+
+	if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
+		DRM_ERROR( "could not initialize freelist\n" );
+		/* Assign dev_private so we can do cleanup. */
+		dev->dev_private = (void *)dev_priv;
+		mga_do_cleanup_dma( dev );
+		return -ENOMEM;
+	}
 
+	/* Make dev_private visable to others. */
+	dev->dev_private = (void *)dev_priv;
+	return 0;
+}
 
-	/* Private is now filled in, initialize the hardware */
-	{
-		PRIMLOCALS;
-		PRIMGETPTR( dev_priv );
+int mga_do_cleanup_dma( drm_device_t *dev )
+{
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DWGSYNC, 0x0100);
-		PRIMOUTREG(MGAREG_SOFTRAP, 0);
-		/* Poll for the first buffer to insure that
-		 * the status register will be correct
-		 */
+	if ( dev->dev_private ) {
+		drm_mga_private_t *dev_priv = dev->dev_private;
 
-		mga_flush_write_combine();
-	   	MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
+		DRM_IOREMAPFREE( dev_priv->warp );
+		DRM_IOREMAPFREE( dev_priv->primary );
+		DRM_IOREMAPFREE( dev_priv->buffers );
 
-		MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) |
-					   PDEA_pagpxfer_enable));
+		if ( dev_priv->head != NULL ) {
+			mga_freelist_cleanup( dev );
+		}
 
-	   	while(MGA_READ(MGAREG_DWGSYNC) != 0x0100) ;
+		DRM(free)( dev->dev_private, sizeof(drm_mga_private_t),
+			   DRM_MEM_DRIVER );
+		dev->dev_private = NULL;
 	}
 
-	if(mga_freelist_init(dev) != 0) {
-	   	DRM_ERROR("Could not initialize freelist\n");
-	   	mga_dma_cleanup(dev);
-	   	return -ENOMEM;
-	}
 	return 0;
 }
 
-int mga_dma_init(struct inode *inode, struct file *filp,
-		 unsigned int cmd, unsigned long arg)
+int mga_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_mga_init_t init;
 
-	if (copy_from_user(&init, (drm_mga_init_t *)arg, sizeof(init)))
+	if ( copy_from_user( &init, (drm_mga_init_t *)arg, sizeof(init) ) )
 		return -EFAULT;
 
-	switch(init.func) {
+	switch ( init.func ) {
 	case MGA_INIT_DMA:
-		return mga_dma_initialize(dev, &init);
+		return mga_do_init_dma( dev, &init );
 	case MGA_CLEANUP_DMA:
-		return mga_dma_cleanup(dev);
+		return mga_do_cleanup_dma( dev );
 	}
 
 	return -EINVAL;
 }
 
-int mga_irq_install(drm_device_t *dev, int irq)
-{
-	int retcode;
 
-	if (!irq)     return -EINVAL;
-
-	down(&dev->struct_sem);
-	if (dev->irq) {
-		up(&dev->struct_sem);
-		return -EBUSY;
-	}
-	dev->irq = irq;
-	up(&dev->struct_sem);
-
-	DRM_DEBUG("install irq handler %d\n", irq);
-
-	dev->context_flag     = 0;
-	dev->interrupt_flag   = 0;
-	dev->dma_flag	      = 0;
-	dev->dma->next_buffer = NULL;
-	dev->dma->next_queue  = NULL;
-	dev->dma->this_buffer = NULL;
-	INIT_LIST_HEAD(&dev->tq.list);
-	dev->tq.sync	      = 0;
-	dev->tq.routine	      = mga_dma_task_queue;
-	dev->tq.data	      = dev;
-
-				/* Before installing handler */
-	MGA_WRITE(MGAREG_IEN, 0);
-   				/* Install handler */
-	if ((retcode = request_irq(dev->irq,
-				   mga_dma_service,
-				   SA_SHIRQ,
-				   dev->devname,
-				   dev))) {
-		down(&dev->struct_sem);
-		dev->irq = 0;
-		up(&dev->struct_sem);
-		return retcode;
-	}
-				/* After installing handler */
-   	MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
-	MGA_WRITE(MGAREG_IEN, 0x00000001);
-	return 0;
-}
+/* ================================================================
+ * Primary DMA stream management
+ */
 
-int mga_irq_uninstall(drm_device_t *dev)
+int mga_dma_flush( struct inode *inode, struct file *filp,
+		   unsigned int cmd, unsigned long arg )
 {
-	int irq;
-
-	down(&dev->struct_sem);
-	irq	 = dev->irq;
-	dev->irq = 0;
-	up(&dev->struct_sem);
-
-	if (!irq) return -EINVAL;
-   	DRM_DEBUG("remove irq handler %d\n", irq);
-      	MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
-	MGA_WRITE(MGAREG_IEN, 0);
-	free_irq(irq, dev);
-	return 0;
-}
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+	drm_lock_t lock;
 
-int mga_control(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_control_t	ctl;
+	LOCK_TEST_WITH_RETURN( dev );
 
-	if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
+	if ( copy_from_user( &lock, (drm_lock_t *)arg, sizeof(lock) ) )
 		return -EFAULT;
 
-	switch (ctl.func) {
-	case DRM_INST_HANDLER:
-		return mga_irq_install(dev, ctl.irq);
-	case DRM_UNINST_HANDLER:
-		return mga_irq_uninstall(dev);
-	default:
-		return -EINVAL;
+	DRM_DEBUG( "%s: %s%s%s\n",
+		   __FUNCTION__,
+		   (lock.flags & _DRM_LOCK_FLUSH) ?	"flush, " : "",
+		   (lock.flags & _DRM_LOCK_FLUSH_ALL) ?	"flush all, " : "",
+		   (lock.flags & _DRM_LOCK_QUIESCENT) ?	"idle, " : "" );
+
+	WRAP_WAIT_WITH_RETURN( dev_priv );
+
+	if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {
+		mga_do_dma_flush( dev_priv );
+	}
+
+	if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
+#if MGA_DMA_DEBUG
+		int ret = mga_do_wait_for_idle( dev_priv );
+		if ( ret < 0 )
+			DRM_INFO( __FUNCTION__": -EBUSY\n" );
+		return ret;
+#else
+		return mga_do_wait_for_idle( dev_priv );
+#endif
+	} else {
+		return 0;
 	}
 }
 
-static int mga_flush_queue(drm_device_t *dev)
+int mga_dma_reset( struct inode *inode, struct file *filp,
+		   unsigned int cmd, unsigned long arg )
 {
-   	DECLARE_WAITQUEUE(entry, current);
-  	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-   	int ret = 0;
-
-   	if(!dev_priv) return 0;
-
-   	if(dev_priv->next_prim->num_dwords != 0) {
-   		add_wait_queue(&dev_priv->flush_queue, &entry);
-		if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status)) 
-			DRM_ERROR("Incorrect mga_flush_queue logic\n");
-		set_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status);
-		mga_dma_schedule(dev, 0);
-   		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-	   		if (!test_bit(MGA_IN_FLUSH,
-				      &dev_priv->dispatch_status))
-				break;
-		   	atomic_inc(&dev->total_sleeps);
-	      		schedule();
-	      		if (signal_pending(current)) {
-		   		ret = -EINTR; /* Can't restart */
-				clear_bit(MGA_IN_FLUSH,
-					  &dev_priv->dispatch_status);
-		   		break;
-			}
-		}
-		current->state = TASK_RUNNING;
-   		remove_wait_queue(&dev_priv->flush_queue, &entry);
-	}
-   	return ret;
-}
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
 
-/* Must be called with the lock held */
-void mga_reclaim_buffers(drm_device_t *dev, pid_t pid)
-{
-	drm_device_dma_t *dma = dev->dma;
-	int		 i;
+	LOCK_TEST_WITH_RETURN( dev );
 
-	if (!dma) return;
-      	if(dev->dev_private == NULL) return;
-	if(dma->buflist == NULL) return;
-
-	DRM_DEBUG("buf_count=%d\n", dma->buf_count);
-	
-        mga_flush_queue(dev);
-
-	for (i = 0; i < dma->buf_count; i++) {
-	   	drm_buf_t *buf = dma->buflist[ i ];
-	   	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
-
-		/* Only buffers that need to get reclaimed ever
-		 * get set to free
-		 */
-		if (buf->pid == pid  && buf_priv) {
-			if(buf_priv->my_freelist->age == MGA_BUF_USED)
-		     		buf_priv->my_freelist->age = MGA_BUF_FREE;
-		}
-	}
+	return mga_do_dma_reset( dev_priv );
 }
 
-int mga_lock(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;
-	DECLARE_WAITQUEUE(entry, current);
-	int		  ret	= 0;
-	drm_lock_t	  lock;
 
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	if (lock.context < 0) return -EINVAL;
+/* ================================================================
+ * DMA buffer management
+ */
 
-	/* Only one queue:
-	 */
+static int mga_dma_get_buffers( drm_device_t *dev, drm_dma_t *d )
+{
+	drm_buf_t *buf;
+	int i;
 
-	if (!ret) {
-		add_wait_queue(&dev->lock.lock_queue, &entry);
-		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-			if (!dev->lock.hw_lock) {
-				/* Device has been unregistered */
-				ret = -EINTR;
-				break;
-			}
-			if (drm_lock_take(&dev->lock.hw_lock->lock,
-					  lock.context)) {
-				dev->lock.pid	    = current->pid;
-				dev->lock.lock_time = jiffies;
-				atomic_inc(&dev->total_locks);
-				break;	/* Got lock */
-			}
-
-				/* Contention */
-			atomic_inc(&dev->total_sleeps);
-			schedule();
-			if (signal_pending(current)) {
-				ret = -ERESTARTSYS;
-				break;
-			}
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&dev->lock.lock_queue, &entry);
-	}
+	for ( i = d->granted_count ; i < d->request_count ; i++ ) {
+		buf = mga_freelist_get( dev );
+		if ( !buf ) return -EAGAIN;
+
+		buf->pid = current->pid;
+
+		if ( copy_to_user( &d->request_indices[i],
+				   &buf->idx, sizeof(buf->idx) ) )
+			return -EFAULT;
+		if ( copy_to_user( &d->request_sizes[i],
+				   &buf->total, sizeof(buf->total) ) )
+			return -EFAULT;
 
-	if (!ret) {
-		sigemptyset(&dev->sigmask);
-		sigaddset(&dev->sigmask, SIGSTOP);
-		sigaddset(&dev->sigmask, SIGTSTP);
-		sigaddset(&dev->sigmask, SIGTTIN);
-		sigaddset(&dev->sigmask, SIGTTOU);
-		dev->sigdata.context = lock.context;
-		dev->sigdata.lock    = dev->lock.hw_lock;
-		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
-
-		if (lock.flags & _DRM_LOCK_QUIESCENT) {
-		   DRM_DEBUG("_DRM_LOCK_QUIESCENT\n");
-		   mga_flush_queue(dev);
-		   mga_dma_quiescent(dev);
-		}
+		d->granted_count++;
 	}
-
-	if (ret) DRM_DEBUG("%d %s\n", lock.context,
-			   ret ? "interrupted" : "has lock");
-	return ret;
+	return 0;
 }
 
-int mga_flush_ioctl(struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg)
+int mga_dma_buffers( 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_lock_t	  lock;
-      	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_device_dma_t *dma = dev->dma;
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+	drm_dma_t d;
+	int ret = 0;
 
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) )
 		return -EFAULT;
 
-	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("lock not held\n");
+	/* 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;
 	}
 
-   	if(lock.flags & _DRM_LOCK_FLUSH || lock.flags & _DRM_LOCK_FLUSH_ALL) {
-		drm_mga_prim_buf_t *temp_buf;
+	/* 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;
+	}
 
-		temp_buf = dev_priv->current_prim;
+	WRAP_TEST_WITH_RETURN( dev_priv );
 
-		if(temp_buf && temp_buf->num_dwords) {
-			set_bit(MGA_BUF_FORCE_FIRE, &temp_buf->buffer_status);
-			mga_advance_primary(dev);
- 		}
-		mga_dma_schedule(dev, 1);
-	}
-   	if(lock.flags & _DRM_LOCK_QUIESCENT) {
-		mga_flush_queue(dev);
-		mga_dma_quiescent(dev);
+	d.granted_count = 0;
+
+	if ( d.request_count ) {
+		ret = mga_dma_get_buffers( dev, &d );
 	}
 
-    	return 0;
+	if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
+		return -EFAULT;
+
+	return ret;
 }
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga_drm.h linux/drivers/char/drm/mga_drm.h
--- linux-2.4.8-pre6/drivers/char/drm/mga_drm.h	Thu Jan  4 14:06:18 2001
+++ linux/drivers/char/drm/mga_drm.h	Mon Dec  3 22:59:45 2001
@@ -11,197 +11,178 @@
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the next
  * paragraph) shall be included in all copies or substantial portions of the
  * Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  *
- * Authors: Jeff Hartmann <jhartmann@valinux.com>
- *          Keith Whitwell <keithw@valinux.com>
+ * Authors:
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Keith Whitwell <keithw@valinux.com>
  *
+ * Rewritten by:
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
-#ifndef _MGA_DRM_H_
-#define _MGA_DRM_H_
+#ifndef __MGA_DRM_H__
+#define __MGA_DRM_H__
 
 /* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmMga.h)
+ * defines in the Xserver file (mga_sarea.h)
  */
-#ifndef _MGA_DEFINES_
-#define _MGA_DEFINES_
+#ifndef __MGA_SAREA_DEFINES__
+#define __MGA_SAREA_DEFINES__
 
-#define MGA_F  0x1		/* fog */
-#define MGA_A  0x2		/* alpha */
-#define MGA_S  0x4		/* specular */
-#define MGA_T2 0x8		/* multitexture */
-
-#define MGA_WARP_TGZ            0
-#define MGA_WARP_TGZF           (MGA_F)
-#define MGA_WARP_TGZA           (MGA_A)
-#define MGA_WARP_TGZAF          (MGA_F|MGA_A)
-#define MGA_WARP_TGZS           (MGA_S)
-#define MGA_WARP_TGZSF          (MGA_S|MGA_F)
-#define MGA_WARP_TGZSA          (MGA_S|MGA_A)
-#define MGA_WARP_TGZSAF         (MGA_S|MGA_F|MGA_A)
-#define MGA_WARP_T2GZ           (MGA_T2)
-#define MGA_WARP_T2GZF          (MGA_T2|MGA_F)
-#define MGA_WARP_T2GZA          (MGA_T2|MGA_A)
-#define MGA_WARP_T2GZAF         (MGA_T2|MGA_A|MGA_F)
-#define MGA_WARP_T2GZS          (MGA_T2|MGA_S)
-#define MGA_WARP_T2GZSF         (MGA_T2|MGA_S|MGA_F)
-#define MGA_WARP_T2GZSA         (MGA_T2|MGA_S|MGA_A)
-#define MGA_WARP_T2GZSAF        (MGA_T2|MGA_S|MGA_F|MGA_A)
-
-#define MGA_MAX_G400_PIPES 16
-#define MGA_MAX_G200_PIPES  8	/* no multitex */
-#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
-
-#define MGA_CARD_TYPE_G200 1
-#define MGA_CARD_TYPE_G400 2
-
-#define MGA_FRONT   0x1
-#define MGA_BACK    0x2
-#define MGA_DEPTH   0x4
-
-/* 3d state excluding texture units:
- */
-#define MGA_CTXREG_DSTORG     0	/* validated */
-#define MGA_CTXREG_MACCESS    1	
-#define MGA_CTXREG_PLNWT      2 	
-#define MGA_CTXREG_DWGCTL     3	
-#define MGA_CTXREG_ALPHACTRL  4
-#define MGA_CTXREG_FOGCOLOR   5
-#define MGA_CTXREG_WFLAG      6
-#define MGA_CTXREG_TDUAL0     7
-#define MGA_CTXREG_TDUAL1     8
-#define MGA_CTXREG_FCOL       9
-#define MGA_CTXREG_STENCIL    10
-#define MGA_CTXREG_STENCILCTL 11
-#define MGA_CTX_SETUP_SIZE    12
-
-/* 2d state
- */
-#define MGA_2DREG_PITCH 	0
-#define MGA_2D_SETUP_SIZE 	1
-
-/* Each texture unit has a state:
- */
-#define MGA_TEXREG_CTL        0
-#define MGA_TEXREG_CTL2       1
-#define MGA_TEXREG_FILTER     2
-#define MGA_TEXREG_BORDERCOL  3
-#define MGA_TEXREG_ORG        4 /* validated */
-#define MGA_TEXREG_ORG1       5
-#define MGA_TEXREG_ORG2       6
-#define MGA_TEXREG_ORG3       7
-#define MGA_TEXREG_ORG4       8
-#define MGA_TEXREG_WIDTH      9
-#define MGA_TEXREG_HEIGHT     10
-#define MGA_TEX_SETUP_SIZE    11
+/* WARP pipe flags
+ */
+#define MGA_F			0x1		/* fog */
+#define MGA_A			0x2		/* alpha */
+#define MGA_S			0x4		/* specular */
+#define MGA_T2			0x8		/* multitexture */
+
+#define MGA_WARP_TGZ		0
+#define MGA_WARP_TGZF		(MGA_F)
+#define MGA_WARP_TGZA		(MGA_A)
+#define MGA_WARP_TGZAF		(MGA_F|MGA_A)
+#define MGA_WARP_TGZS		(MGA_S)
+#define MGA_WARP_TGZSF		(MGA_S|MGA_F)
+#define MGA_WARP_TGZSA		(MGA_S|MGA_A)
+#define MGA_WARP_TGZSAF		(MGA_S|MGA_F|MGA_A)
+#define MGA_WARP_T2GZ		(MGA_T2)
+#define MGA_WARP_T2GZF		(MGA_T2|MGA_F)
+#define MGA_WARP_T2GZA		(MGA_T2|MGA_A)
+#define MGA_WARP_T2GZAF		(MGA_T2|MGA_A|MGA_F)
+#define MGA_WARP_T2GZS		(MGA_T2|MGA_S)
+#define MGA_WARP_T2GZSF		(MGA_T2|MGA_S|MGA_F)
+#define MGA_WARP_T2GZSA		(MGA_T2|MGA_S|MGA_A)
+#define MGA_WARP_T2GZSAF	(MGA_T2|MGA_S|MGA_F|MGA_A)
+
+#define MGA_MAX_G200_PIPES	8		/* no multitex */
+#define MGA_MAX_G400_PIPES	16
+#define MGA_MAX_WARP_PIPES	MGA_MAX_G400_PIPES
+#define MGA_WARP_UCODE_SIZE	32768		/* in bytes */
+
+#define MGA_CARD_TYPE_G200	1
+#define MGA_CARD_TYPE_G400	2
+
+
+#define MGA_FRONT		0x1
+#define MGA_BACK		0x2
+#define MGA_DEPTH		0x4
 
 /* What needs to be changed for the current vertex dma buffer?
  */
-#define MGA_UPLOAD_CTX        0x1
-#define MGA_UPLOAD_TEX0       0x2
-#define MGA_UPLOAD_TEX1       0x4
-#define MGA_UPLOAD_PIPE       0x8
-#define MGA_UPLOAD_TEX0IMAGE  0x10 /* handled client-side */
-#define MGA_UPLOAD_TEX1IMAGE  0x20 /* handled client-side */
-#define MGA_UPLOAD_2D 	      0x40
-#define MGA_WAIT_AGE          0x80 /* handled client-side */
-#define MGA_UPLOAD_CLIPRECTS  0x100 /* handled client-side */
-#define MGA_DMA_FLUSH	      0x200 /* set when someone gets the lock
-                                       quiescent */
+#define MGA_UPLOAD_CONTEXT	0x1
+#define MGA_UPLOAD_TEX0		0x2
+#define MGA_UPLOAD_TEX1		0x4
+#define MGA_UPLOAD_PIPE		0x8
+#define MGA_UPLOAD_TEX0IMAGE	0x10 /* handled client-side */
+#define MGA_UPLOAD_TEX1IMAGE	0x20 /* handled client-side */
+#define MGA_UPLOAD_2D		0x40
+#define MGA_WAIT_AGE		0x80 /* handled client-side */
+#define MGA_UPLOAD_CLIPRECTS	0x100 /* handled client-side */
+#if 0
+#define MGA_DMA_FLUSH		0x200 /* set when someone gets the lock
+					 quiescent */
+#endif
 
 /* 32 buffers of 64k each, total 2 meg.
  */
-#define MGA_DMA_BUF_ORDER     16
-#define MGA_DMA_BUF_SZ        (1<<MGA_DMA_BUF_ORDER)
-#define MGA_DMA_BUF_NR        31
+#define MGA_BUFFER_SIZE		(1 << 16)
+#define MGA_NUM_BUFFERS		128
 
 /* Keep these small for testing.
  */
-#define MGA_NR_SAREA_CLIPRECTS 8
+#define MGA_NR_SAREA_CLIPRECTS	8
 
 /* 2 heaps (1 for card, 1 for agp), each divided into upto 128
- * regions, subject to a minimum region size of (1<<16) == 64k. 
+ * regions, subject to a minimum region size of (1<<16) == 64k.
  *
  * Clients may subdivide regions internally, but when sharing between
- * clients, the region size is the minimum granularity. 
+ * clients, the region size is the minimum granularity.
  */
 
-#define MGA_CARD_HEAP 0
-#define MGA_AGP_HEAP  1
-#define MGA_NR_TEX_HEAPS 2
-#define MGA_NR_TEX_REGIONS 16
-#define MGA_LOG_MIN_TEX_REGION_SIZE 16
-#endif
+#define MGA_CARD_HEAP			0
+#define MGA_AGP_HEAP			1
+#define MGA_NR_TEX_HEAPS		2
+#define MGA_NR_TEX_REGIONS		16
+#define MGA_LOG_MIN_TEX_REGION_SIZE	16
 
-typedef struct _drm_mga_warp_index {
-   	int installed;
-   	unsigned long phys_addr;
-   	int size;
-} drm_mga_warp_index_t;
+#endif /* __MGA_SAREA_DEFINES__ */
 
-typedef struct drm_mga_init {
-   	enum { 
-	   	MGA_INIT_DMA = 0x01,
-	       	MGA_CLEANUP_DMA = 0x02
-	} func;
-   	int reserved_map_agpstart;
-   	int reserved_map_idx;
-   	int buffer_map_idx;
-   	int sarea_priv_offset;
-   	int primary_size;
-   	int warp_ucode_size;
-   	unsigned int frontOffset;
-   	unsigned int backOffset;
-   	unsigned int depthOffset;
-   	unsigned int textureOffset;
-   	unsigned int textureSize;
-        unsigned int agpTextureOffset;
-        unsigned int agpTextureSize;
-   	unsigned int cpp;
-   	unsigned int stride;
-   	int sgram;
-	int chipset;
-   	drm_mga_warp_index_t WarpIndex[MGA_MAX_WARP_PIPES];
-	unsigned int mAccess;
-} drm_mga_init_t;
 
-/* Warning: if you change the sarea structure, you must change the Xserver
- * structures as well */
+/* Setup registers for 3D context
+ */
+typedef struct {
+	unsigned int dstorg;
+	unsigned int maccess;
+	unsigned int plnwt;
+	unsigned int dwgctl;
+	unsigned int alphactrl;
+	unsigned int fogcolor;
+	unsigned int wflag;
+	unsigned int tdualstage0;
+	unsigned int tdualstage1;
+	unsigned int fcol;
+	unsigned int stencil;
+	unsigned int stencilctl;
+} drm_mga_context_regs_t;
+
+/* Setup registers for 2D, X server
+ */
+typedef struct {
+	unsigned int pitch;
+} drm_mga_server_regs_t;
+
+/* Setup registers for each texture unit
+ */
+typedef struct {
+	unsigned int texctl;
+	unsigned int texctl2;
+	unsigned int texfilter;
+	unsigned int texbordercol;
+	unsigned int texorg;
+	unsigned int texwidth;
+	unsigned int texheight;
+	unsigned int texorg1;
+	unsigned int texorg2;
+	unsigned int texorg3;
+	unsigned int texorg4;
+} drm_mga_texture_regs_t;
 
-typedef struct _drm_mga_tex_region {
-	unsigned char next, prev;	
-	unsigned char in_use;	
-	unsigned int age;			
-} drm_mga_tex_region_t;
+/* General aging mechanism
+ */
+typedef struct {
+	unsigned int head;		/* Position of head pointer          */
+	unsigned int wrap;		/* Primary DMA wrap count            */
+} drm_mga_age_t;
 
 typedef struct _drm_mga_sarea {
 	/* The channel for communication of state information to the kernel
 	 * on firing a vertex dma buffer.
 	 */
-   	unsigned int ContextState[MGA_CTX_SETUP_SIZE];
-   	unsigned int ServerState[MGA_2D_SETUP_SIZE];
-   	unsigned int TexState[2][MGA_TEX_SETUP_SIZE];
-   	unsigned int WarpPipe;
+   	drm_mga_context_regs_t context_state;
+   	drm_mga_server_regs_t server_state;
+   	drm_mga_texture_regs_t tex_state[2];
+   	unsigned int warp_pipe;
    	unsigned int dirty;
+   	unsigned int vertsize;
 
-   	unsigned int nbox;
+	/* The current cliprects, or a subset thereof.
+	 */
    	drm_clip_rect_t boxes[MGA_NR_SAREA_CLIPRECTS];
-
+   	unsigned int nbox;
 
 	/* Information about the most recently used 3d drawable.  The
-	 * client fills in the req_* fields, the server fills in the 
+	 * client fills in the req_* fields, the server fills in the
 	 * exported_ fields and puts the cliprects into boxes, above.
 	 *
 	 * The client clears the exported_drawable field before
@@ -210,65 +191,120 @@
         unsigned int req_drawable;	 /* the X drawable id */
 	unsigned int req_draw_buffer;	 /* MGA_FRONT or MGA_BACK */
 
-        unsigned int exported_drawable;	 
-	unsigned int exported_index; 
-        unsigned int exported_stamp;	
-        unsigned int exported_buffers;	 
+        unsigned int exported_drawable;
+	unsigned int exported_index;
+        unsigned int exported_stamp;
+        unsigned int exported_buffers;
         unsigned int exported_nfront;
         unsigned int exported_nback;
-	int exported_back_x, exported_front_x, exported_w;	
+	int exported_back_x, exported_front_x, exported_w;
 	int exported_back_y, exported_front_y, exported_h;
    	drm_clip_rect_t exported_boxes[MGA_NR_SAREA_CLIPRECTS];
-   
+
 	/* Counters for aging textures and for client-side throttling.
 	 */
+	unsigned int status[4];
+	unsigned int last_wrap;
+
+	drm_mga_age_t last_frame;
         unsigned int last_enqueue;	/* last time a buffer was enqueued */
 	unsigned int last_dispatch;	/* age of the most recently dispatched buffer */
 	unsigned int last_quiescent;     /*  */
 
-
-	/* LRU lists for texture memory in agp space and on the card
+	/* LRU lists for texture memory in agp space and on the card.
 	 */
-	drm_mga_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1];
+	drm_tex_region_t texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS+1];
 	unsigned int texAge[MGA_NR_TEX_HEAPS];
-	
+
 	/* Mechanism to validate card state.
 	 */
    	int ctxOwner;
-   	int vertexsize;
-} drm_mga_sarea_t;	
+} drm_mga_sarea_t;
 
-/* Device specific ioctls:
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmMga.h)
  */
-typedef struct _drm_mga_clear {
+typedef struct _drm_mga_warp_index {
+   	int installed;
+   	unsigned long phys_addr;
+   	int size;
+} drm_mga_warp_index_t;
+
+typedef struct drm_mga_init {
+   	enum {
+	   	MGA_INIT_DMA    = 0x01,
+	       	MGA_CLEANUP_DMA = 0x02
+	} func;
+
+   	unsigned long sarea_priv_offset;
+
+	int chipset;
+   	int sgram;
+
+	unsigned int maccess;
+
+   	unsigned int fb_cpp;
+	unsigned int front_offset, front_pitch;
+   	unsigned int back_offset, back_pitch;
+
+   	unsigned int depth_cpp;
+   	unsigned int depth_offset, depth_pitch;
+
+   	unsigned int texture_offset[MGA_NR_TEX_HEAPS];
+   	unsigned int texture_size[MGA_NR_TEX_HEAPS];
+
+	unsigned long fb_offset;
+	unsigned long mmio_offset;
+	unsigned long status_offset;
+	unsigned long warp_offset;
+	unsigned long primary_offset;
+	unsigned long buffers_offset;
+} drm_mga_init_t;
+
+typedef struct drm_mga_fullscreen {
+	enum {
+		MGA_INIT_FULLSCREEN    = 0x01,
+		MGA_CLEANUP_FULLSCREEN = 0x02
+	} func;
+} drm_mga_fullscreen_t;
+
+typedef struct drm_mga_clear {
+	unsigned int flags;
 	unsigned int clear_color;
 	unsigned int clear_depth;
-	unsigned int flags;
-	unsigned int clear_depth_mask;
-	unsigned int clear_color_mask;
+	unsigned int color_mask;
+	unsigned int depth_mask;
 } drm_mga_clear_t;
 
-typedef struct _drm_mga_swap {
-   	int dummy;
-} drm_mga_swap_t;
+typedef struct drm_mga_vertex {
+   	int idx;			/* buffer to queue */
+	int used;			/* bytes in use */
+	int discard;			/* client finished with buffer?  */
+} drm_mga_vertex_t;
+
+typedef struct drm_mga_indices {
+   	int idx;			/* buffer to queue */
+	unsigned int start;
+	unsigned int end;
+	int discard;			/* client finished with buffer?  */
+} drm_mga_indices_t;
 
-typedef struct _drm_mga_iload {
+typedef struct drm_mga_iload {
 	int idx;
-	int length;
-	unsigned int destOrg;
+	unsigned int dstorg;
+	unsigned int length;
 } drm_mga_iload_t;
 
-typedef struct _drm_mga_vertex {
-   	int idx;		/* buffer to queue */
-	int used;		/* bytes in use */
-	int discard;		/* client finished with buffer?  */
-} drm_mga_vertex_t;
-
-typedef struct _drm_mga_indices {
-   	int idx;		/* buffer to queue */
-	unsigned int start;		
-	unsigned int end;		
-	int discard;		/* client finished with buffer?  */
-} drm_mga_indices_t;
+typedef struct _drm_mga_blit {
+	unsigned int planemask;
+	unsigned int srcorg;
+	unsigned int dstorg;
+	int src_pitch, dst_pitch;
+	int delta_sx, delta_sy;
+	int delta_dx, delta_dy;
+	int height, ydir;		/* flip image vertically */
+	int source_pitch, dest_pitch;
+} drm_mga_blit_t;
 
 #endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga_drv.c linux/drivers/char/drm/mga_drv.c
--- linux-2.4.8-pre6/drivers/char/drm/mga_drv.c	Thu Jan  4 14:06:18 2001
+++ linux/drivers/char/drm/mga_drv.c	Mon Dec  3 22:59:45 2001
@@ -1,4 +1,4 @@
-/* mga_drv.c -- Matrox g200/g400 driver -*- linux-c -*-
+/* mga_drv.c -- Matrox G200/G400 driver -*- linux-c -*-
  * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -19,647 +19,83 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *
+ * 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>
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include <linux/config.h>
+#include "mga.h"
 #include "drmP.h"
 #include "mga_drv.h"
 
-#define MGA_NAME	 "mga"
-#define MGA_DESC	 "Matrox G200/G400"
-#define MGA_DATE	 "20000928"
-#define MGA_MAJOR	 2
-#define MGA_MINOR	 0
-#define MGA_PATCHLEVEL	 1
-
-static drm_device_t	      mga_device;
-drm_ctx_t		      mga_res_ctx;
-
-static struct file_operations mga_fops = {
-#if LINUX_VERSION_CODE >= 0x020400
-				/* This started being used during 2.4.0-test */
-	owner:   THIS_MODULE,
-#endif
-	open:	 mga_open,
-	flush:	 drm_flush,
-	release: mga_release,
-	ioctl:	 mga_ioctl,
-	mmap:	 drm_mmap,
-	read:	 drm_read,
-	fasync:	 drm_fasync,
-   	poll:	 drm_poll,
-};
-
-static struct miscdevice      mga_misc = {
-	minor: MISC_DYNAMIC_MINOR,
-	name:  MGA_NAME,
-	fops:  &mga_fops,
-};
-
-static drm_ioctl_desc_t	      mga_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]     = { mga_version,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]  = { drm_getunique,  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]   = { drm_getmagic,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]   = { drm_irq_busid,  0, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]  = { drm_setunique,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]	      = { drm_block,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]     = { drm_unblock,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]     = { mga_control,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]  = { drm_authmagic,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]     = { drm_addmap,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]    = { mga_addbufs,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]   = { mga_markbufs,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]   = { mga_infobufs,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]    = { mga_mapbufs,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]   = { mga_freebufs,	  1, 0 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]     = { mga_addctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]      = { mga_rmctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]     = { mga_modctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]     = { mga_getctx,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]  = { mga_switchctx,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]     = { mga_newctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]     = { mga_resctx,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]    = { drm_adddraw,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]     = { drm_rmdraw,	  1, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	      = { mga_dma,	  1, 0 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	      = { mga_lock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]      = { mga_unlock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]      = { drm_finish,	  1, 0 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]  = { drm_agp_enable,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]    = { drm_agp_info,    1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]   = { drm_agp_alloc,   1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]    = { drm_agp_free,    1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]    = { drm_agp_bind,    1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]  = { drm_agp_unbind,  1, 1 },
-   	[DRM_IOCTL_NR(DRM_IOCTL_MGA_INIT)]    = { mga_dma_init,    1, 1 },
-   	[DRM_IOCTL_NR(DRM_IOCTL_MGA_SWAP)]    = { mga_swap_bufs,   1, 0 },
-   	[DRM_IOCTL_NR(DRM_IOCTL_MGA_CLEAR)]   = { mga_clear_bufs,  1, 0 },
-   	[DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)]   = { mga_iload,       1, 0 },
-   	[DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)]  = { mga_vertex,      1, 0 },
-   	[DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)]   = { mga_flush_ioctl, 1, 0 },
-   	[DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_indices,     1, 0 },
-};
-
-#define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
+#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
 
-#ifdef MODULE
-static char		      *mga = NULL;
-#endif
-
-MODULE_AUTHOR("VA Linux Systems, Inc.");
-MODULE_DESCRIPTION("Matrox G200/G400");
-MODULE_PARM(mga, "s");
+#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"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
 
 #ifndef MODULE
-/* mga_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.
+/* 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.
  */
 
-static int __init mga_options(char *str)
+/* 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);
+	DRM(parse_options)( str );
 	return 1;
 }
 
-__setup("mga=", mga_options);
-#endif
-
-static int mga_setup(drm_device_t *dev)
-{
-	int i;
-
-	atomic_set(&dev->ioctl_count, 0);
-	atomic_set(&dev->vma_count, 0);
-	dev->buf_use	  = 0;
-	atomic_set(&dev->buf_alloc, 0);
-
-	drm_dma_setup(dev);
-
-	atomic_set(&dev->total_open, 0);
-	atomic_set(&dev->total_close, 0);
-	atomic_set(&dev->total_ioctl, 0);
-	atomic_set(&dev->total_irq, 0);
-	atomic_set(&dev->total_ctx, 0);
-	atomic_set(&dev->total_locks, 0);
-	atomic_set(&dev->total_unlocks, 0);
-	atomic_set(&dev->total_contends, 0);
-	atomic_set(&dev->total_sleeps, 0);
-
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		dev->magiclist[i].head = NULL;
-		dev->magiclist[i].tail = NULL;
-	}
-	dev->maplist	    = NULL;
-	dev->map_count	    = 0;
-	dev->vmalist	    = NULL;
-	dev->lock.hw_lock   = NULL;
-	init_waitqueue_head(&dev->lock.lock_queue);
-	dev->queue_count    = 0;
-	dev->queue_reserved = 0;
-	dev->queue_slots    = 0;
-	dev->queuelist	    = NULL;
-	dev->irq	    = 0;
-	dev->context_flag   = 0;
-	dev->interrupt_flag = 0;
-	dev->dma_flag	    = 0;
-	dev->last_context   = 0;
-	dev->last_switch    = 0;
-	dev->last_checked   = 0;
-	init_timer(&dev->timer);
-	init_waitqueue_head(&dev->context_wait);
-
-	dev->ctx_start	    = 0;
-	dev->lck_start	    = 0;
-
-	dev->buf_rp	  = dev->buf;
-	dev->buf_wp	  = dev->buf;
-	dev->buf_end	  = dev->buf + DRM_BSZ;
-	dev->buf_async	  = NULL;
-	init_waitqueue_head(&dev->buf_readers);
-	init_waitqueue_head(&dev->buf_writers);
-
-	DRM_DEBUG("\n");
-
-	/* The kernel's context could be created here, but is now created
-	   in drm_dma_enqueue.	This is more resource-efficient for
-	   hardware that does not do DMA, but may mean that
-	   drm_select_queue fails between the time the interrupt is
-	   initialized and the time the queues are initialized. */
-
-	return 0;
-}
-
-
-static int mga_takedown(drm_device_t *dev)
-{
-	int		  i;
-	drm_magic_entry_t *pt, *next;
-	drm_map_t	  *map;
-	drm_vma_entry_t	  *vma, *vma_next;
-
-	DRM_DEBUG("\n");
-
-	if (dev->dev_private) mga_dma_cleanup(dev);
-	if (dev->irq) mga_irq_uninstall(dev);
-
-	down(&dev->struct_sem);
-	del_timer(&dev->timer);
-
-	if (dev->devname) {
-		drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
-		dev->devname = NULL;
-	}
-
-	if (dev->unique) {
-		drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
-		dev->unique = NULL;
-		dev->unique_len = 0;
-	}
-				/* Clear pid list */
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		for (pt = dev->magiclist[i].head; pt; pt = next) {
-			next = pt->next;
-			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-		}
-		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
-	}
-   				/* Clear AGP information */
-	if (dev->agp) {
-		drm_agp_mem_t *entry;
-		drm_agp_mem_t *nexte;
-
-				/* Remove AGP resources, but leave dev->agp
-                                   intact until cleanup is called. */
-		for (entry = dev->agp->memory; entry; entry = nexte) {
-			nexte = entry->next;
-			if (entry->bound) drm_unbind_agp(entry->memory);
-			drm_free_agp(entry->memory, entry->pages);
-			drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-		}
-		dev->agp->memory = NULL;
-
-		if (dev->agp->acquired)	_drm_agp_release();
-
-		dev->agp->acquired = 0;
-		dev->agp->enabled  = 0;
-	}
-				/* Clear vma list (only built for debugging) */
-	if (dev->vmalist) {
-		for (vma = dev->vmalist; vma; vma = vma_next) {
-			vma_next = vma->next;
-			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
-		}
-		dev->vmalist = NULL;
-	}
-
-				/* Clear map area and mtrr information */
-	if (dev->maplist) {
-		for (i = 0; i < dev->map_count; i++) {
-			map = dev->maplist[i];
-			switch (map->type) {
-			case _DRM_REGISTERS:
-			case _DRM_FRAME_BUFFER:
-#ifdef CONFIG_MTRR
-				if (map->mtrr >= 0) {
-					int retcode;
-					retcode = mtrr_del(map->mtrr,
-							   map->offset,
-							   map->size);
-					DRM_DEBUG("mtrr_del = %d\n", retcode);
-				}
-#endif
-				drm_ioremapfree(map->handle, map->size);
-				break;
-			case _DRM_SHM:
-				drm_free_pages((unsigned long)map->handle,
-					       drm_order(map->size)
-					       - PAGE_SHIFT,
-					       DRM_MEM_SAREA);
-				break;
-			case _DRM_AGP:
-				break;
-			}
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		}
-		drm_free(dev->maplist,
-			 dev->map_count * sizeof(*dev->maplist),
-			 DRM_MEM_MAPS);
-		dev->maplist   = NULL;
-		dev->map_count = 0;
-	}
-
-	if (dev->queuelist) {
-		for (i = 0; i < dev->queue_count; i++) {
-			drm_waitlist_destroy(&dev->queuelist[i]->waitlist);
-			if (dev->queuelist[i]) {
-				drm_free(dev->queuelist[i],
-					 sizeof(*dev->queuelist[0]),
-					 DRM_MEM_QUEUES);
-				dev->queuelist[i] = NULL;
-			}
-		}
-		drm_free(dev->queuelist,
-			 dev->queue_slots * sizeof(*dev->queuelist),
-			 DRM_MEM_QUEUES);
-		dev->queuelist	 = NULL;
-	}
-
-	drm_dma_takedown(dev);
-
-	dev->queue_count     = 0;
-	if (dev->lock.hw_lock) {
-		dev->lock.hw_lock    = NULL; /* SHM removed */
-		dev->lock.pid	     = 0;
-		wake_up_interruptible(&dev->lock.lock_queue);
-	}
-	up(&dev->struct_sem);
-
-	return 0;
-}
-
-/* mga_init is called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported). */
-
-static int __init mga_init(void)
-{
-	int		      retcode;
-	drm_device_t	      *dev = &mga_device;
-
-	DRM_DEBUG("\n");
-
-	memset((void *)dev, 0, sizeof(*dev));
-	dev->count_lock	  = SPIN_LOCK_UNLOCKED;
-	sema_init(&dev->struct_sem, 1);
-
-#ifdef MODULE
-	drm_parse_options(mga);
-#endif
-	if ((retcode = misc_register(&mga_misc))) {
-		DRM_ERROR("Cannot register \"%s\"\n", MGA_NAME);
-		return retcode;
-	}
-	dev->device = MKDEV(MISC_MAJOR, mga_misc.minor);
-	dev->name   = MGA_NAME;
-
-	drm_mem_init();
-	drm_proc_init(dev);
-	dev->agp    = drm_agp_init();
-      	if(dev->agp == NULL) {
-	   	DRM_INFO("The mga drm module requires the agpgart module"
-		         " to function correctly\nPlease load the agpgart"
-		         " module before you load the mga module\n");
-	   	drm_proc_cleanup();
-	   	misc_deregister(&mga_misc);
-	   	mga_takedown(dev);
-	   	return -ENOMEM;
-	}
-#ifdef CONFIG_MTRR
-   	dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
-				      dev->agp->agp_info.aper_size * 1024 * 1024,
-				      MTRR_TYPE_WRCOMB,
-				      1);
-#endif
-	if((retcode = drm_ctxbitmap_init(dev))) {
-		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
-		drm_proc_cleanup();
-		misc_deregister(&mga_misc);
-		mga_takedown(dev);
-		return retcode;
-	}
-
-	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
-		 MGA_NAME,
-		 MGA_MAJOR,
-		 MGA_MINOR,
-		 MGA_PATCHLEVEL,
-		 MGA_DATE,
-		 mga_misc.minor);
-
-	return 0;
-}
-
-/* mga_cleanup is called via cleanup_module at module unload time. */
-
-static void __exit mga_cleanup(void)
-{
-	drm_device_t	      *dev = &mga_device;
-
-	DRM_DEBUG("\n");
-
-	drm_proc_cleanup();
-	if (misc_deregister(&mga_misc)) {
-		DRM_ERROR("Cannot unload module\n");
-	} else {
-		DRM_INFO("Module unloaded\n");
-	}
-	drm_ctxbitmap_cleanup(dev);
-#ifdef CONFIG_MTRR
-   	if(dev->agp && dev->agp->agp_mtrr) {
-	   	int retval;
-	   	retval = mtrr_del(dev->agp->agp_mtrr,
-				  dev->agp->agp_info.aper_base,
-				  dev->agp->agp_info.aper_size * 1024*1024);
-	   	DRM_DEBUG("mtrr_del = %d\n", retval);
-	}
-#endif
-
-	mga_takedown(dev);
-	if (dev->agp) {
-		drm_agp_uninit();
-		drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
-		dev->agp = NULL;
-	}
-}
-
-module_init(mga_init);
-module_exit(mga_cleanup);
-
-
-int mga_version(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
-{
-	drm_version_t version;
-	int	      len;
-
-	if (copy_from_user(&version,
-			   (drm_version_t *)arg,
-			   sizeof(version)))
-		return -EFAULT;
-
-#define DRM_COPY(name,value)				     \
-	len = strlen(value);				     \
-	if (len > name##_len) len = name##_len;		     \
-	name##_len = strlen(value);			     \
-	if (len && name) {				     \
-		if (copy_to_user(name, value, len))	     \
-			return -EFAULT;			     \
-	}
-
-	version.version_major	   = MGA_MAJOR;
-	version.version_minor	   = MGA_MINOR;
-	version.version_patchlevel = MGA_PATCHLEVEL;
-
-	DRM_COPY(version.name, MGA_NAME);
-	DRM_COPY(version.date, MGA_DATE);
-	DRM_COPY(version.desc, MGA_DESC);
-
-	if (copy_to_user((drm_version_t *)arg,
-			 &version,
-			 sizeof(version)))
-		return -EFAULT;
-	return 0;
-}
-
-int mga_open(struct inode *inode, struct file *filp)
-{
-	drm_device_t  *dev    = &mga_device;
-	int	      retcode = 0;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (!(retcode = drm_open_helper(inode, filp, dev))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-		atomic_inc(&dev->total_open);
-		spin_lock(&dev->count_lock);
-		if (!dev->open_count++) {
-			spin_unlock(&dev->count_lock);
-			return mga_setup(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-	return retcode;
-}
-
-int mga_release(struct inode *inode, struct file *filp)
-{
-	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev;
-	int	      retcode = 0;
-
-	lock_kernel();
-	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) {
-	      	mga_reclaim_buffers(dev, priv->pid);
-		DRM_INFO("Process %d dead (ctx %d, d_s = 0x%02lx)\n",
-			 current->pid,
-			 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock),
-			 dev->dev_private ?
-			 ((drm_mga_private_t *)dev->dev_private)
-			 ->dispatch_status
-			 : 0);
-
-		if (dev->dev_private)
-			((drm_mga_private_t *)dev->dev_private)
-				->dispatch_status &= MGA_IN_DISPATCH;
-		
-		drm_lock_free(dev,
-			      &dev->lock.hw_lock->lock,
-			      _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-	} else if (dev->lock.hw_lock) {
-	   	/* The lock is required to reclaim buffers */
-	   	DECLARE_WAITQUEUE(entry, current);
-	   	add_wait_queue(&dev->lock.lock_queue, &entry);
-		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
-			if (!dev->lock.hw_lock) {
-				/* Device has been unregistered */
-				retcode = -EINTR;
-				break;
-			}
-			if (drm_lock_take(&dev->lock.hw_lock->lock,
-					  DRM_KERNEL_CONTEXT)) {
-				dev->lock.pid	    = priv->pid;
-				dev->lock.lock_time = jiffies;
-				atomic_inc(&dev->total_locks);
-				break;	/* Got lock */
-			}
-				/* Contention */
-			atomic_inc(&dev->total_sleeps);
-			schedule();
-			if (signal_pending(current)) {
-				retcode = -ERESTARTSYS;
-				break;
-			}
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&dev->lock.lock_queue, &entry);
-	   	if(!retcode) {
-		   	mga_reclaim_buffers(dev, priv->pid);
-			if (dev->dev_private)
-				((drm_mga_private_t *)dev->dev_private)
-					->dispatch_status &= MGA_IN_DISPATCH;
-		   	drm_lock_free(dev, &dev->lock.hw_lock->lock,
-				      DRM_KERNEL_CONTEXT);
-		}
-	}
-	drm_fasync(-1, filp, 0);
-
-	down(&dev->struct_sem);
-	if (priv->remove_auth_on_close == 1) {
-		drm_file_t *temp = dev->file_first;
-		while(temp) {
-			temp->authenticated = 0;
-			temp = temp->next;
-		}
-	}
-	if (priv->prev) priv->prev->next = priv->next;
-	else		dev->file_first	 = priv->next;
-	if (priv->next) priv->next->prev = priv->prev;
-	else		dev->file_last	 = priv->prev;
-	up(&dev->struct_sem);
-
-	drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
-#if LINUX_VERSION_CODE < 0x020333
-	MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
+__setup( DRIVER_NAME "=", mga_options );
 #endif
-   	atomic_inc(&dev->total_close);
-   	spin_lock(&dev->count_lock);
-   	if (!--dev->open_count) {
-	   	if (atomic_read(&dev->ioctl_count) || dev->blocked) {
-		   	DRM_ERROR("Device busy: %d %d\n",
-				  atomic_read(&dev->ioctl_count),
-				  dev->blocked);
-		   	spin_unlock(&dev->count_lock);
-			unlock_kernel();
-		   	return -EBUSY;
-		}
-	   	spin_unlock(&dev->count_lock);
-		unlock_kernel();
-	   	return mga_takedown(dev);
-	}
-	spin_unlock(&dev->count_lock);
-	unlock_kernel();
-	return retcode;
-}
 
 
-/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. */
-
-int mga_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
-{
-	int		 nr	 = DRM_IOCTL_NR(cmd);
-	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	int		 retcode = 0;
-	drm_ioctl_desc_t *ioctl;
-	drm_ioctl_t	 *func;
-
-	atomic_inc(&dev->ioctl_count);
-	atomic_inc(&dev->total_ioctl);
-	++priv->ioctl_count;
-
-	if (nr >= MGA_IOCTL_COUNT) {
-		retcode = -EINVAL;
-	} else {
-		ioctl	  = &mga_ioctls[nr];
-		func	  = ioctl->func;
-
-		if (!func) {
-			DRM_DEBUG("no function: pid = %d, cmd = 0x%02x,"
-				  " nr = 0x%02x, dev 0x%x, auth = %d\n",
-				  current->pid, cmd, nr, dev->device,
-				  priv->authenticated);
-			retcode = -EINVAL;
-		} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
-			    || (ioctl->auth_needed && !priv->authenticated)) {
-			retcode = -EACCES;
-		} else {
-			retcode = (func)(inode, filp, cmd, arg);
-		}
-	}
-
-	atomic_dec(&dev->ioctl_count);
-	return retcode;
-}
-
-int mga_unlock(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_lock_t	  lock;
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	atomic_inc(&dev->total_unlocks);
-	if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
-		atomic_inc(&dev->total_contends);
-	drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
-	mga_dma_schedule(dev, 1);
-
-	if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
-			  DRM_KERNEL_CONTEXT)) DRM_ERROR("\n");
-
-	unblock_all_signals();
-	return 0;
-}
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga_drv.h linux/drivers/char/drm/mga_drv.h
--- linux-2.4.8-pre6/drivers/char/drm/mga_drv.h	Thu Jan  4 14:06:18 2001
+++ linux/drivers/char/drm/mga_drv.h	Mon Dec  3 22:59:45 2001
@@ -1,4 +1,4 @@
-/* mga_drv.h -- Private header for the Matrox g200/g400 driver -*- linux-c -*-
+/* mga_drv.h -- Private header for the Matrox G200/G400 driver -*- linux-c -*-
  * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -19,180 +19,140 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
- * 	    Jeff Hartmann <jhartmann@valinux.com>
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
-#ifndef _MGA_DRV_H_
-#define _MGA_DRV_H_
+#ifndef __MGA_DRV_H__
+#define __MGA_DRV_H__
 
-#define MGA_BUF_IN_USE         0
-#define MGA_BUF_SWAP_PENDING   1
-#define MGA_BUF_FORCE_FIRE     2
-#define MGA_BUF_NEEDS_OVERFLOW 3
+typedef struct drm_mga_primary_buffer {
+	u8 *start;
+	u8 *end;
+	int size;
 
-typedef struct {
-	long buffer_status; /* long req'd for set_bit() --RR */
-   	int num_dwords;
-   	int max_dwords;
-   	u32 *current_dma_ptr;
-   	u32 *head;
-   	u32 phys_head;
-	unsigned int prim_age;
-   	int sec_used;
-   	int idx;
-} drm_mga_prim_buf_t;
+	u32 tail;
+	int space;
+	volatile int wrapped;
+
+	volatile u32 *status;
+
+	u32 last_flush;
+	u32 last_wrap;
+
+	u32 high_mark;
+
+	spinlock_t list_lock;
+} drm_mga_primary_buffer_t;
 
-typedef struct _drm_mga_freelist {
-   	__volatile__ unsigned int age;
+typedef struct drm_mga_freelist {
+   	struct drm_mga_freelist *next;
+   	struct drm_mga_freelist *prev;
+	drm_mga_age_t age;
    	drm_buf_t *buf;
-   	struct _drm_mga_freelist *next;
-   	struct _drm_mga_freelist *prev;
 } drm_mga_freelist_t;
 
-#define MGA_IN_DISPATCH   0
-#define MGA_IN_FLUSH      1
-#define MGA_IN_WAIT       2
-#define MGA_IN_GETBUF	  3
-
-typedef struct _drm_mga_private {
-   	long dispatch_status;  /* long req'd for set_bit() --RR */
-	unsigned int next_prim_age;
-	__volatile__ unsigned int last_prim_age;
-   	int reserved_map_idx;
-   	int buffer_map_idx;
-   	drm_mga_sarea_t *sarea_priv;
-   	int primary_size;
-   	int warp_ucode_size;
-   	int chipset;
-   	unsigned int frontOffset;
-   	unsigned int backOffset;
-   	unsigned int depthOffset;
-   	unsigned int textureOffset;
-   	unsigned int textureSize;
-   	int cpp;
-   	unsigned int stride;
-   	int sgram;
-	int use_agp;
-   	drm_mga_warp_index_t WarpIndex[MGA_MAX_G400_PIPES];
-	unsigned int WarpPipe;
-	unsigned int vertexsize;
-   	atomic_t pending_bufs;
-   	void *status_page;
-   	unsigned long real_status_page;
-   	u8 *ioremap;
-   	drm_mga_prim_buf_t **prim_bufs;
-   	drm_mga_prim_buf_t *next_prim;
-   	drm_mga_prim_buf_t *last_prim;
-   	drm_mga_prim_buf_t *current_prim;
-   	int current_prim_idx;
+typedef struct {
+   	drm_mga_freelist_t *list_entry;
+	int discard;
+	int dispatched;
+} drm_mga_buf_priv_t;
+
+typedef struct drm_mga_private {
+	drm_mga_primary_buffer_t prim;
+	drm_mga_sarea_t *sarea_priv;
+
    	drm_mga_freelist_t *head;
    	drm_mga_freelist_t *tail;
-   	wait_queue_head_t flush_queue;	/* Processes waiting until flush    */
-      	wait_queue_head_t wait_queue;	/* Processes waiting until interrupt */
-	wait_queue_head_t buf_queue;    /* Processes waiting for a free buf */
-	/* Some validated register values:
-	 */
-	u32 mAccess;
-} drm_mga_private_t;
 
-				/* mga_drv.c */
-extern int  mga_version(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  mga_open(struct inode *inode, struct file *filp);
-extern int  mga_release(struct inode *inode, struct file *filp);
-extern int  mga_ioctl(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  mga_unlock(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
+	unsigned int warp_pipe;
+	unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES];
+
+	int chipset;
+	int usec_timeout;
+
+	u32 clear_cmd;
+	u32 maccess;
+
+	unsigned int fb_cpp;
+	unsigned int front_offset;
+	unsigned int front_pitch;
+	unsigned int back_offset;
+	unsigned int back_pitch;
+
+	unsigned int depth_cpp;
+	unsigned int depth_offset;
+	unsigned int depth_pitch;
+
+	unsigned int texture_offset;
+	unsigned int texture_size;
+
+	drm_map_t *sarea;
+	drm_map_t *fb;
+	drm_map_t *mmio;
+	drm_map_t *status;
+	drm_map_t *warp;
+	drm_map_t *primary;
+	drm_map_t *buffers;
+	drm_map_t *agp_textures;
+} drm_mga_private_t;
 
 				/* mga_dma.c */
-extern int  mga_dma_schedule(drm_device_t *dev, int locked);
-extern int  mga_dma(struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg);
-extern int  mga_irq_install(drm_device_t *dev, int irq);
-extern int  mga_irq_uninstall(drm_device_t *dev);
-extern int  mga_control(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  mga_lock(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-
-/* mga_dma_init does init and release */
-extern int mga_dma_init(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int mga_dma_cleanup(drm_device_t *dev);
-extern int mga_flush_ioctl(struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg);
-extern unsigned int mga_create_sync_tag(drm_device_t *dev);
-extern drm_buf_t *mga_freelist_get(drm_device_t *dev);
-extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf);
-extern int mga_advance_primary(drm_device_t *dev);
-extern void mga_reclaim_buffers(drm_device_t *dev, pid_t pid);
-
-
-				/* mga_bufs.c */
-extern int  mga_addbufs(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  mga_infobufs(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-extern int  mga_markbufs(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-extern int  mga_freebufs(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-extern int  mga_mapbufs(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  mga_addmap(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-				/* mga_state.c */
-extern int  mga_clear_bufs(struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg);
-extern int  mga_swap_bufs(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  mga_iload(struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg);
-extern int  mga_vertex(struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg);
-extern int  mga_indices(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-				/* mga_context.c */
-extern int  mga_resctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  mga_addctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  mga_modctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  mga_getctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  mga_switchctx(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  mga_newctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  mga_rmctx(struct inode *inode, struct file *filp,
-		      unsigned int cmd, unsigned long arg);
+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_do_wait_for_idle( drm_mga_private_t *dev_priv );
+extern int mga_do_dma_idle( drm_mga_private_t *dev_priv );
+extern int mga_do_dma_reset( drm_mga_private_t *dev_priv );
+extern int mga_do_engine_reset( drm_mga_private_t *dev_priv );
+extern int mga_do_cleanup_dma( drm_device_t *dev );
+
+extern void mga_do_dma_flush( drm_mga_private_t *dev_priv );
+extern void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv );
+extern void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv );
+
+extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf );
 
-extern int  mga_context_switch(drm_device_t *dev, int old, int new);
-extern int  mga_context_switch_complete(drm_device_t *dev, int new);
+				/* 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 );
+
+				/* 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()
 
-typedef enum {
-	TT_GENERAL,
-	TT_BLIT,
-	TT_VECTOR,
-	TT_VERTEX
-} transferType_t;
 
-typedef struct {
-   	drm_mga_freelist_t *my_freelist;
-	int discard;
-	int dispatched;
-} drm_mga_buf_priv_t;
+#define MGA_BASE( reg )		((u32)(dev_priv->mmio->handle))
+#define MGA_ADDR( reg )		(MGA_BASE(reg) + reg)
+
+#define MGA_DEREF( reg )	*(volatile u32 *)MGA_ADDR( reg )
+#define MGA_READ( reg )		MGA_DEREF( reg )
+#define MGA_WRITE( reg, val )	do { MGA_DEREF( reg ) = val; } while (0)
+#define MGA_DEREF8( reg )	*(volatile u8 *)MGA_ADDR( reg )
+#define MGA_WRITE8( reg, val )  do { MGA_DEREF8( reg ) = val; } while (0)
 
 #define DWGREG0 	0x1c00
 #define DWGREG0_END 	0x1dff
@@ -200,321 +160,470 @@
 #define DWGREG1_END	0x2dff
 
 #define ISREG0(r)	(r >= DWGREG0 && r <= DWGREG0_END)
-#define ADRINDEX0(r)	(u8)((r - DWGREG0) >> 2)
-#define ADRINDEX1(r)	(u8)(((r - DWGREG1) >> 2) | 0x80)
-#define ADRINDEX(r)	(ISREG0(r) ? ADRINDEX0(r) : ADRINDEX1(r))
-
-#define MGA_VERBOSE 0
-#define MGA_NUM_PRIM_BUFS 	8
-
-#define PRIMLOCALS	u8 tempIndex[4]; u32 *dma_ptr; u32 phys_head; \
-			int outcount, num_dwords
-
-#define PRIM_OVERFLOW(dev, dev_priv, length) do {			   \
-	drm_mga_prim_buf_t *tmp_buf =					   \
- 		dev_priv->prim_bufs[dev_priv->current_prim_idx];	   \
-	if( test_bit(MGA_BUF_NEEDS_OVERFLOW, &tmp_buf->buffer_status)) {   \
- 		mga_advance_primary(dev);				   \
- 		mga_dma_schedule(dev, 1);				   \
-		tmp_buf = dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
- 	} else if( tmp_buf->max_dwords - tmp_buf->num_dwords < length ||   \
- 	           tmp_buf->sec_used > MGA_DMA_BUF_NR/2) {		   \
-		set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status);	   \
- 		mga_advance_primary(dev);				   \
- 		mga_dma_schedule(dev, 1);				   \
-		tmp_buf = dev_priv->prim_bufs[dev_priv->current_prim_idx]; \
-	}								   \
-	if(MGA_VERBOSE)							   \
-		DRM_DEBUG("PRIMGETPTR in %s\n", __FUNCTION__);		   \
-	dma_ptr = tmp_buf->current_dma_ptr;				   \
-	num_dwords = tmp_buf->num_dwords;				   \
-	phys_head = tmp_buf->phys_head;					   \
-	outcount = 0;							   \
-} while(0)
-
-#define PRIMGETPTR(dev_priv) do {					\
-	drm_mga_prim_buf_t *tmp_buf =					\
-		dev_priv->prim_bufs[dev_priv->current_prim_idx];	\
-	if(MGA_VERBOSE)							\
-		DRM_DEBUG("PRIMGETPTR in %s\n", __FUNCTION__);		\
-	dma_ptr = tmp_buf->current_dma_ptr;				\
-	num_dwords = tmp_buf->num_dwords;				\
-	phys_head = tmp_buf->phys_head;					\
-	outcount = 0;							\
-} while(0)
-
-#define PRIMPTR(prim_buf) do {					\
-	if(MGA_VERBOSE)						\
-		DRM_DEBUG("PRIMPTR in %s\n", __FUNCTION__);	\
-	dma_ptr = prim_buf->current_dma_ptr;			\
-	num_dwords = prim_buf->num_dwords;			\
-	phys_head = prim_buf->phys_head;			\
-	outcount = 0;						\
-} while(0)
-
-#define PRIMFINISH(prim_buf) do {				\
-	if (MGA_VERBOSE) {					\
-		DRM_DEBUG( "PRIMFINISH in %s\n", __FUNCTION__);	\
-                if (outcount & 3)				\
-                      DRM_DEBUG(" --- truncation\n");	        \
-        }							\
-	prim_buf->num_dwords = num_dwords;			\
-	prim_buf->current_dma_ptr = dma_ptr;			\
-} while(0)
-
-#define PRIMADVANCE(dev_priv)	do {				\
-drm_mga_prim_buf_t *tmp_buf = 					\
-	dev_priv->prim_bufs[dev_priv->current_prim_idx];	\
-	if (MGA_VERBOSE) {					\
-		DRM_DEBUG("PRIMADVANCE in %s\n", __FUNCTION__);	\
-                if (outcount & 3)				\
-                      DRM_DEBUG(" --- truncation\n");	\
-        }							\
-	tmp_buf->num_dwords = num_dwords;      			\
-	tmp_buf->current_dma_ptr = dma_ptr;    			\
-} while (0)
-
-#define PRIMUPDATE(dev_priv)	do {					\
-	drm_mga_prim_buf_t *tmp_buf =					\
-		dev_priv->prim_bufs[dev_priv->current_prim_idx];	\
-	tmp_buf->sec_used++;						\
-} while (0)
-
-#define AGEBUF(dev_priv, buf_priv)	do {				\
-	drm_mga_prim_buf_t *tmp_buf =					\
-		dev_priv->prim_bufs[dev_priv->current_prim_idx];	\
-	buf_priv->my_freelist->age = tmp_buf->prim_age;			\
-} while (0)
-
-
-#define PRIMOUTREG(reg, val) do {					\
-	tempIndex[outcount]=ADRINDEX(reg);				\
-	dma_ptr[1+outcount] = val;					\
-	if (MGA_VERBOSE)						\
-		DRM_DEBUG("   PRIMOUT %d: 0x%x -- 0x%x\n",		\
-		       num_dwords + 1 + outcount, ADRINDEX(reg), val);	\
-	if( ++outcount == 4) {						\
-		outcount = 0;						\
-		dma_ptr[0] = *(unsigned long *)tempIndex;		\
-		dma_ptr+=5;						\
-		num_dwords += 5;					\
+#define DMAREG0(r)	(u8)((r - DWGREG0) >> 2)
+#define DMAREG1(r)	(u8)(((r - DWGREG1) >> 2) | 0x80)
+#define DMAREG(r)	(ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
+
+
+
+/* ================================================================
+ * Helper macross...
+ */
+
+#define MGA_EMIT_STATE( dev_priv, dirty )				\
+do {									\
+	if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) {			\
+		if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {	\
+			mga_g400_emit_state( dev_priv );		\
+		} else {						\
+			mga_g200_emit_state( dev_priv );		\
+		}							\
+	}								\
+} while (0)
+
+#define 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;						\
 	}								\
-}while (0)
+} while (0)
+
+#define WRAP_TEST_WITH_RETURN( dev_priv )				\
+do {									\
+	if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {			\
+		if ( mga_is_idle( dev_priv ) ) {			\
+			mga_do_dma_wrap_end( dev_priv );		\
+		} else if ( dev_priv->prim.space <			\
+			    dev_priv->prim.high_mark ) {		\
+			if ( MGA_DMA_DEBUG )				\
+				DRM_INFO( __FUNCTION__": wrap...\n" );	\
+			return -EBUSY;					\
+		}							\
+	}								\
+} while (0)
+
+#define WRAP_WAIT_WITH_RETURN( dev_priv )				\
+do {									\
+	if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {			\
+		if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {		\
+			if ( MGA_DMA_DEBUG )				\
+				DRM_INFO( __FUNCTION__": wrap...\n" );	\
+			return -EBUSY;					\
+		}							\
+		mga_do_dma_wrap_end( dev_priv );			\
+	}								\
+} while (0)
+
+
+/* ================================================================
+ * Primary DMA command stream
+ */
+
+#define MGA_VERBOSE	0
+
+#define DMA_LOCALS	unsigned int write; volatile u8 *prim;
+
+#define DMA_BLOCK_SIZE	(5 * sizeof(u32))
+
+#define BEGIN_DMA( n )							\
+do {									\
+	if ( MGA_VERBOSE ) {						\
+		DRM_INFO( "BEGIN_DMA( %d ) in %s\n",			\
+			  (n), __FUNCTION__ );				\
+		DRM_INFO( "   space=0x%x req=0x%x\n",			\
+			  dev_priv->prim.space, (n) * DMA_BLOCK_SIZE );	\
+	}								\
+	prim = dev_priv->prim.start;					\
+	write = dev_priv->prim.tail;					\
+} while (0)
+
+#define BEGIN_DMA_WRAP()						\
+do {									\
+	if ( MGA_VERBOSE ) {						\
+		DRM_INFO( "BEGIN_DMA() in %s\n", __FUNCTION__ );	\
+		DRM_INFO( "   space=0x%x\n", dev_priv->prim.space );	\
+	}								\
+	prim = dev_priv->prim.start;					\
+	write = dev_priv->prim.tail;					\
+} while (0)
+
+#define ADVANCE_DMA()							\
+do {									\
+	dev_priv->prim.tail = write;					\
+	if ( MGA_VERBOSE ) {						\
+		DRM_INFO( "ADVANCE_DMA() tail=0x%05x sp=0x%x\n",	\
+			  write, dev_priv->prim.space );		\
+	}								\
+} while (0)
+
+#define FLUSH_DMA()							\
+do {									\
+	if ( 0 ) {							\
+		DRM_INFO( __FUNCTION__ ":\n" );				\
+		DRM_INFO( "   tail=0x%06x head=0x%06lx\n",		\
+			  dev_priv->prim.tail,				\
+			  MGA_READ( MGA_PRIMADDRESS ) -			\
+			  dev_priv->primary->offset );			\
+	}								\
+	if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) {		\
+		if ( dev_priv->prim.space <				\
+		     dev_priv->prim.high_mark ) {			\
+			mga_do_dma_wrap_start( dev_priv );		\
+		} else {						\
+			mga_do_dma_flush( dev_priv );			\
+		}							\
+	}								\
+} while (0)
+
+/* Never use this, always use DMA_BLOCK(...) for primary DMA output.
+ */
+#define DMA_WRITE( offset, val )					\
+do {									\
+	if ( MGA_VERBOSE ) {						\
+		DRM_INFO( "   DMA_WRITE( 0x%08x ) at 0x%04x\n",		\
+			  (u32)(val), write + (offset) * sizeof(u32) );	\
+	}								\
+	*(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val;	\
+} while (0)
+
+#define DMA_BLOCK( reg0, val0, reg1, val1, reg2, val2, reg3, val3 )	\
+do {									\
+	DMA_WRITE( 0, ((DMAREG( reg0 ) << 0) |				\
+		       (DMAREG( reg1 ) << 8) |				\
+		       (DMAREG( reg2 ) << 16) |				\
+		       (DMAREG( reg3 ) << 24)) );			\
+	DMA_WRITE( 1, val0 );						\
+	DMA_WRITE( 2, val1 );						\
+	DMA_WRITE( 3, val2 );						\
+	DMA_WRITE( 4, val3 );						\
+	write += DMA_BLOCK_SIZE;					\
+} while (0)
+
+
+/* Buffer aging via primary DMA stream head pointer.
+ */
+
+#define SET_AGE( age, h, w )						\
+do {									\
+	(age)->head = h;						\
+	(age)->wrap = w;						\
+} while (0)
+
+#define TEST_AGE( age, h, w )		( (age)->wrap < w ||		\
+					  ( (age)->wrap == w &&		\
+					    (age)->head < h ) )
+
+#define AGE_BUFFER( buf_priv )						\
+do {									\
+	drm_mga_freelist_t *entry = (buf_priv)->list_entry;		\
+	if ( (buf_priv)->dispatched ) {					\
+		entry->age.head = (dev_priv->prim.tail +		\
+				   dev_priv->primary->offset);		\
+		entry->age.wrap = dev_priv->sarea_priv->last_wrap;	\
+	} else {							\
+		entry->age.head = 0;					\
+		entry->age.wrap = 0;					\
+	}								\
+} while (0)
+
+
+#define MGA_ENGINE_IDLE_MASK		(MGA_SOFTRAPEN |		\
+					 MGA_DWGENGSTS |		\
+					 MGA_ENDPRDMASTS)
+#define MGA_DMA_IDLE_MASK		(MGA_SOFTRAPEN |		\
+					 MGA_ENDPRDMASTS)
+
+#define MGA_DMA_DEBUG			0
+
+
 
 /* A reduced set of the mga registers.
  */
+#define MGA_CRTC_INDEX			0x1fd4
+
+#define MGA_ALPHACTRL 			0x2c7c
+#define MGA_AR0 			0x1c60
+#define MGA_AR1 			0x1c64
+#define MGA_AR2 			0x1c68
+#define MGA_AR3 			0x1c6c
+#define MGA_AR4 			0x1c70
+#define MGA_AR5 			0x1c74
+#define MGA_AR6 			0x1c78
+
+#define MGA_CXBNDRY			0x1c80
+#define MGA_CXLEFT 			0x1ca0
+#define MGA_CXRIGHT			0x1ca4
+
+#define MGA_DMAPAD 			0x1c54
+#define MGA_DSTORG 			0x2cb8
+#define MGA_DWGCTL 			0x1c00
+#	define MGA_OPCOD_MASK			(15 << 0)
+#	define MGA_OPCOD_TRAP			(4 << 0)
+#	define MGA_OPCOD_TEXTURE_TRAP		(6 << 0)
+#	define MGA_OPCOD_BITBLT			(8 << 0)
+#	define MGA_OPCOD_ILOAD			(9 << 0)
+#	define MGA_ATYPE_MASK			(7 << 4)
+#	define MGA_ATYPE_RPL			(0 << 4)
+#	define MGA_ATYPE_RSTR			(1 << 4)
+#	define MGA_ATYPE_ZI			(3 << 4)
+#	define MGA_ATYPE_BLK			(4 << 4)
+#	define MGA_ATYPE_I			(7 << 4)
+#	define MGA_LINEAR			(1 << 7)
+#	define MGA_ZMODE_MASK			(7 << 8)
+#	define MGA_ZMODE_NOZCMP			(0 << 8)
+#	define MGA_ZMODE_ZE			(2 << 8)
+#	define MGA_ZMODE_ZNE			(3 << 8)
+#	define MGA_ZMODE_ZLT			(4 << 8)
+#	define MGA_ZMODE_ZLTE			(5 << 8)
+#	define MGA_ZMODE_ZGT			(6 << 8)
+#	define MGA_ZMODE_ZGTE			(7 << 8)
+#	define MGA_SOLID			(1 << 11)
+#	define MGA_ARZERO			(1 << 12)
+#	define MGA_SGNZERO			(1 << 13)
+#	define MGA_SHIFTZERO			(1 << 14)
+#	define MGA_BOP_MASK			(15 << 16)
+#	define MGA_BOP_ZERO			(0 << 16)
+#	define MGA_BOP_DST			(10 << 16)
+#	define MGA_BOP_SRC			(12 << 16)
+#	define MGA_BOP_ONE			(15 << 16)
+#	define MGA_TRANS_SHIFT			20
+#	define MGA_TRANS_MASK			(15 << 20)
+#	define MGA_BLTMOD_MASK			(15 << 25)
+#	define MGA_BLTMOD_BMONOLEF		(0 << 25)
+#	define MGA_BLTMOD_BMONOWF		(4 << 25)
+#	define MGA_BLTMOD_PLAN			(1 << 25)
+#	define MGA_BLTMOD_BFCOL			(2 << 25)
+#	define MGA_BLTMOD_BU32BGR		(3 << 25)
+#	define MGA_BLTMOD_BU32RGB		(7 << 25)
+#	define MGA_BLTMOD_BU24BGR		(11 << 25)
+#	define MGA_BLTMOD_BU24RGB		(15 << 25)
+#	define MGA_PATTERN			(1 << 29)
+#	define MGA_TRANSC			(1 << 30)
+#	define MGA_CLIPDIS			(1 << 31)
+#define MGA_DWGSYNC			0x2c4c
+
+#define MGA_FCOL 			0x1c24
+#define MGA_FIFOSTATUS 			0x1e10
+#define MGA_FOGCOL 			0x1cf4
+#define MGA_FXBNDRY			0x1c84
+#define MGA_FXLEFT 			0x1ca8
+#define MGA_FXRIGHT			0x1cac
+
+#define MGA_ICLEAR 			0x1e18
+#	define MGA_SOFTRAPICLR			(1 << 0)
+#define MGA_IEN 			0x1e1c
+#	define MGA_SOFTRAPIEN			(1 << 0)
+
+#define MGA_LEN 			0x1c5c
+
+#define MGA_MACCESS			0x1c04
+
+#define MGA_PITCH 			0x1c8c
+#define MGA_PLNWT 			0x1c1c
+#define MGA_PRIMADDRESS 		0x1e58
+#	define MGA_DMA_GENERAL			(0 << 0)
+#	define MGA_DMA_BLIT			(1 << 0)
+#	define MGA_DMA_VECTOR			(2 << 0)
+#	define MGA_DMA_VERTEX			(3 << 0)
+#define MGA_PRIMEND			0x1e5c
+#	define MGA_PRIMNOSTART			(1 << 0)
+#	define MGA_PAGPXFER			(1 << 1)
+#define MGA_PRIMPTR			0x1e50
+#	define MGA_PRIMPTREN0			(1 << 0)
+#	define MGA_PRIMPTREN1			(1 << 1)
+
+#define MGA_RST 			0x1e40
+#	define MGA_SOFTRESET			(1 << 0)
+#	define MGA_SOFTEXTRST			(1 << 1)
+
+#define MGA_SECADDRESS 			0x2c40
+#define MGA_SECEND 			0x2c44
+#define MGA_SETUPADDRESS 		0x2cd0
+#define MGA_SETUPEND 			0x2cd4
+#define MGA_SGN				0x1c58
+#define MGA_SOFTRAP			0x2c48
+#define MGA_SRCORG 			0x2cb4
+#	define MGA_SRMMAP_MASK			(1 << 0)
+#	define MGA_SRCMAP_FB			(0 << 0)
+#	define MGA_SRCMAP_SYSMEM		(1 << 0)
+#	define MGA_SRCACC_MASK			(1 << 1)
+#	define MGA_SRCACC_PCI			(0 << 1)
+#	define MGA_SRCACC_AGP			(1 << 1)
+#define MGA_STATUS 			0x1e14
+#	define MGA_SOFTRAPEN			(1 << 0)
+#	define MGA_DWGENGSTS			(1 << 16)
+#	define MGA_ENDPRDMASTS			(1 << 17)
+#define MGA_STENCIL			0x2cc8
+#define MGA_STENCILCTL 			0x2ccc
+
+#define MGA_TDUALSTAGE0 		0x2cf8
+#define MGA_TDUALSTAGE1 		0x2cfc
+#define MGA_TEXBORDERCOL 		0x2c5c
+#define MGA_TEXCTL 			0x2c30
+#define MGA_TEXCTL2			0x2c3c
+#	define MGA_DUALTEX			(1 << 7)
+#	define MGA_G400_TC2_MAGIC		(1 << 15)
+#	define MGA_MAP1_ENABLE			(1 << 31)
+#define MGA_TEXFILTER 			0x2c58
+#define MGA_TEXHEIGHT 			0x2c2c
+#define MGA_TEXORG 			0x2c24
+#	define MGA_TEXORGMAP_MASK		(1 << 0)
+#	define MGA_TEXORGMAP_FB			(0 << 0)
+#	define MGA_TEXORGMAP_SYSMEM		(1 << 0)
+#	define MGA_TEXORGACC_MASK		(1 << 1)
+#	define MGA_TEXORGACC_PCI		(0 << 1)
+#	define MGA_TEXORGACC_AGP		(1 << 1)
+#define MGA_TEXORG1			0x2ca4
+#define MGA_TEXORG2			0x2ca8
+#define MGA_TEXORG3			0x2cac
+#define MGA_TEXORG4			0x2cb0
+#define MGA_TEXTRANS 			0x2c34
+#define MGA_TEXTRANSHIGH 		0x2c38
+#define MGA_TEXWIDTH 			0x2c28
+
+#define MGA_WACCEPTSEQ 			0x1dd4
+#define MGA_WCODEADDR 			0x1e6c
+#define MGA_WFLAG 			0x1dc4
+#define MGA_WFLAG1 			0x1de0
+#define MGA_WFLAGNB			0x1e64
+#define MGA_WFLAGNB1 			0x1e08
+#define MGA_WGETMSB			0x1dc8
+#define MGA_WIADDR 			0x1dc0
+#define MGA_WIADDR2			0x1dd8
+#	define MGA_WMODE_SUSPEND		(0 << 0)
+#	define MGA_WMODE_RESUME			(1 << 0)
+#	define MGA_WMODE_JUMP			(2 << 0)
+#	define MGA_WMODE_START			(3 << 0)
+#	define MGA_WAGP_ENABLE			(1 << 2)
+#define MGA_WMISC 			0x1e70
+#	define MGA_WUCODECACHE_ENABLE		(1 << 0)
+#	define MGA_WMASTER_ENABLE		(1 << 1)
+#	define MGA_WCACHEFLUSH_ENABLE		(1 << 3)
+#define MGA_WVRTXSZ			0x1dcc
+
+#define MGA_YBOT 			0x1c9c
+#define MGA_YDST 			0x1c90
+#define MGA_YDSTLEN			0x1c88
+#define MGA_YDSTORG			0x1c94
+#define MGA_YTOP 			0x1c98
+
+#define MGA_ZORG 			0x1c0c
+
+/* This finishes the current batch of commands
+ */
+#define MGA_EXEC 			0x0100
 
-#define MGAREG_MGA_EXEC 			0x0100
-#define MGAREG_ALPHACTRL 			0x2c7c
-#define MGAREG_AR0 				0x1c60
-#define MGAREG_AR1 				0x1c64
-#define MGAREG_AR2 				0x1c68
-#define MGAREG_AR3 				0x1c6c
-#define MGAREG_AR4 				0x1c70
-#define MGAREG_AR5 				0x1c74
-#define MGAREG_AR6 				0x1c78
-#define MGAREG_CXBNDRY				0x1c80
-#define MGAREG_CXLEFT 				0x1ca0
-#define MGAREG_CXRIGHT				0x1ca4
-#define MGAREG_DMAPAD 				0x1c54
-#define MGAREG_DSTORG 				0x2cb8
-#define MGAREG_DWGCTL 				0x1c00
-#define MGAREG_DWGSYNC				0x2c4c
-#define MGAREG_FCOL 				0x1c24
-#define MGAREG_FIFOSTATUS 			0x1e10
-#define MGAREG_FOGCOL 				0x1cf4
-#define MGAREG_FXBNDRY				0x1c84
-#define MGAREG_FXLEFT 				0x1ca8
-#define MGAREG_FXRIGHT				0x1cac
-#define MGAREG_ICLEAR 				0x1e18
-#define MGAREG_IEN 				0x1e1c
-#define MGAREG_LEN 				0x1c5c
-#define MGAREG_MACCESS				0x1c04
-#define MGAREG_PITCH 				0x1c8c
-#define MGAREG_PLNWT 				0x1c1c
-#define MGAREG_PRIMADDRESS 			0x1e58
-#define MGAREG_PRIMEND				0x1e5c
-#define MGAREG_PRIMPTR				0x1e50
-#define MGAREG_SECADDRESS 			0x2c40
-#define MGAREG_SECEND 				0x2c44
-#define MGAREG_SETUPADDRESS 			0x2cd0
-#define MGAREG_SETUPEND 			0x2cd4
-#define MGAREG_SOFTRAP				0x2c48
-#define MGAREG_SRCORG 				0x2cb4
-#define MGAREG_STATUS 				0x1e14
-#define MGAREG_STENCIL				0x2cc8
-#define MGAREG_STENCILCTL 			0x2ccc
-#define MGAREG_TDUALSTAGE0 			0x2cf8
-#define MGAREG_TDUALSTAGE1 			0x2cfc
-#define MGAREG_TEXBORDERCOL 			0x2c5c
-#define MGAREG_TEXCTL 				0x2c30
-#define MGAREG_TEXCTL2				0x2c3c
-#define MGAREG_TEXFILTER 			0x2c58
-#define MGAREG_TEXHEIGHT 			0x2c2c
-#define MGAREG_TEXORG 				0x2c24
-#define MGAREG_TEXORG1				0x2ca4
-#define MGAREG_TEXORG2				0x2ca8
-#define MGAREG_TEXORG3				0x2cac
-#define MGAREG_TEXORG4				0x2cb0
-#define MGAREG_TEXTRANS 			0x2c34
-#define MGAREG_TEXTRANSHIGH 			0x2c38
-#define MGAREG_TEXWIDTH 			0x2c28
-#define MGAREG_WACCEPTSEQ 			0x1dd4
-#define MGAREG_WCODEADDR 			0x1e6c
-#define MGAREG_WFLAG 				0x1dc4
-#define MGAREG_WFLAG1 				0x1de0
-#define MGAREG_WFLAGNB				0x1e64
-#define MGAREG_WFLAGNB1 			0x1e08
-#define MGAREG_WGETMSB				0x1dc8
-#define MGAREG_WIADDR 				0x1dc0
-#define MGAREG_WIADDR2				0x1dd8
-#define MGAREG_WMISC 				0x1e70
-#define MGAREG_WVRTXSZ				0x1dcc
-#define MGAREG_YBOT 				0x1c9c
-#define MGAREG_YDST 				0x1c90
-#define MGAREG_YDSTLEN				0x1c88
-#define MGAREG_YDSTORG				0x1c94
-#define MGAREG_YTOP 				0x1c98
-#define MGAREG_ZORG 				0x1c0c
-
-/* Warp registers */
-#define MGAREG_WR0                              0x2d00
-#define MGAREG_WR1                              0x2d04
-#define MGAREG_WR2                              0x2d08
-#define MGAREG_WR3                              0x2d0c
-#define MGAREG_WR4                              0x2d10
-#define MGAREG_WR5                              0x2d14
-#define MGAREG_WR6                              0x2d18
-#define MGAREG_WR7                              0x2d1c
-#define MGAREG_WR8                              0x2d20
-#define MGAREG_WR9                              0x2d24
-#define MGAREG_WR10                             0x2d28
-#define MGAREG_WR11                             0x2d2c
-#define MGAREG_WR12                             0x2d30
-#define MGAREG_WR13                             0x2d34
-#define MGAREG_WR14                             0x2d38
-#define MGAREG_WR15                             0x2d3c
-#define MGAREG_WR16                             0x2d40
-#define MGAREG_WR17                             0x2d44
-#define MGAREG_WR18                             0x2d48
-#define MGAREG_WR19                             0x2d4c
-#define MGAREG_WR20                             0x2d50
-#define MGAREG_WR21                             0x2d54
-#define MGAREG_WR22                             0x2d58
-#define MGAREG_WR23                             0x2d5c
-#define MGAREG_WR24                             0x2d60
-#define MGAREG_WR25                             0x2d64
-#define MGAREG_WR26                             0x2d68
-#define MGAREG_WR27                             0x2d6c
-#define MGAREG_WR28                             0x2d70
-#define MGAREG_WR29                             0x2d74
-#define MGAREG_WR30                             0x2d78
-#define MGAREG_WR31                             0x2d7c
-#define MGAREG_WR32                             0x2d80
-#define MGAREG_WR33                             0x2d84
-#define MGAREG_WR34                             0x2d88
-#define MGAREG_WR35                             0x2d8c
-#define MGAREG_WR36                             0x2d90
-#define MGAREG_WR37                             0x2d94
-#define MGAREG_WR38                             0x2d98
-#define MGAREG_WR39                             0x2d9c
-#define MGAREG_WR40                             0x2da0
-#define MGAREG_WR41                             0x2da4
-#define MGAREG_WR42                             0x2da8
-#define MGAREG_WR43                             0x2dac
-#define MGAREG_WR44                             0x2db0
-#define MGAREG_WR45                             0x2db4
-#define MGAREG_WR46                             0x2db8
-#define MGAREG_WR47                             0x2dbc
-#define MGAREG_WR48                             0x2dc0
-#define MGAREG_WR49                             0x2dc4
-#define MGAREG_WR50                             0x2dc8
-#define MGAREG_WR51                             0x2dcc
-#define MGAREG_WR52                             0x2dd0
-#define MGAREG_WR53                             0x2dd4
-#define MGAREG_WR54                             0x2dd8
-#define MGAREG_WR55                             0x2ddc
-#define MGAREG_WR56                             0x2de0
-#define MGAREG_WR57                             0x2de4
-#define MGAREG_WR58                             0x2de8
-#define MGAREG_WR59                             0x2dec
-#define MGAREG_WR60                             0x2df0
-#define MGAREG_WR61                             0x2df4
-#define MGAREG_WR62                             0x2df8
-#define MGAREG_WR63                             0x2dfc
-
-#define PDEA_pagpxfer_enable			0x2
-
-#define WIA_wmode_suspend			0x0
-#define WIA_wmode_start 			0x3
-#define WIA_wagp_agp				0x4
-
-#define DC_opcod_line_open 			0x0
-#define DC_opcod_autoline_open 			0x1
-#define DC_opcod_line_close 			0x2
-#define DC_opcod_autoline_close 		0x3
-#define DC_opcod_trap 				0x4
-#define DC_opcod_texture_trap 			0x6
-#define DC_opcod_bitblt 			0x8
-#define DC_opcod_iload 				0x9
-#define DC_atype_rpl 				0x0
-#define DC_atype_rstr 				0x10
-#define DC_atype_zi 				0x30
-#define DC_atype_blk 				0x40
-#define DC_atype_i 				0x70
-#define DC_linear_xy 				0x0
-#define DC_linear_linear 			0x80
-#define DC_zmode_nozcmp 			0x0
-#define DC_zmode_ze 				0x200
-#define DC_zmode_zne 				0x300
-#define DC_zmode_zlt 				0x400
-#define DC_zmode_zlte 				0x500
-#define DC_zmode_zgt 				0x600
-#define DC_zmode_zgte 				0x700
-#define DC_solid_disable 			0x0
-#define DC_solid_enable 			0x800
-#define DC_arzero_disable 			0x0
-#define DC_arzero_enable 			0x1000
-#define DC_sgnzero_disable 			0x0
-#define DC_sgnzero_enable 			0x2000
-#define DC_shftzero_disable 			0x0
-#define DC_shftzero_enable 			0x4000
-#define DC_bop_SHIFT 				16
-#define DC_trans_SHIFT 				20
-#define DC_bltmod_bmonolef 			0x0
-#define DC_bltmod_bmonowf 			0x8000000
-#define DC_bltmod_bplan 			0x2000000
-#define DC_bltmod_bfcol 			0x4000000
-#define DC_bltmod_bu32bgr 			0x6000000
-#define DC_bltmod_bu32rgb 			0xe000000
-#define DC_bltmod_bu24bgr 			0x16000000
-#define DC_bltmod_bu24rgb 			0x1e000000
-#define DC_pattern_disable 			0x0
-#define DC_pattern_enable 			0x20000000
-#define DC_transc_disable 			0x0
-#define DC_transc_enable 			0x40000000
-#define DC_clipdis_disable 			0x0
-#define DC_clipdis_enable 			0x80000000
-
-
-#define SETADD_mode_vertlist                   	0x0
-
-
-#define MGA_CLEAR_CMD (DC_opcod_trap | DC_arzero_enable | 		\
-		       DC_sgnzero_enable | DC_shftzero_enable | 	\
-		       (0xC << DC_bop_SHIFT) | DC_clipdis_enable | 	\
-		       DC_solid_enable | DC_transc_enable)
-
-
-#define MGA_COPY_CMD (DC_opcod_bitblt | DC_atype_rpl | DC_linear_xy |	\
-		      DC_solid_disable | DC_arzero_disable | 		\
-		      DC_sgnzero_enable | DC_shftzero_enable | 		\
-		      (0xC << DC_bop_SHIFT) | DC_bltmod_bfcol | 	\
-		      DC_pattern_disable | DC_transc_disable | 		\
-		      DC_clipdis_enable)				\
-
-#define MGA_FLUSH_CMD (DC_opcod_texture_trap | (0xF << DC_trans_SHIFT) |\
-		       DC_arzero_enable | DC_sgnzero_enable |		\
-		       DC_atype_i)
+/* Warp registers
+ */
+#define MGA_WR0				0x2d00
+#define MGA_WR1				0x2d04
+#define MGA_WR2				0x2d08
+#define MGA_WR3				0x2d0c
+#define MGA_WR4				0x2d10
+#define MGA_WR5				0x2d14
+#define MGA_WR6				0x2d18
+#define MGA_WR7				0x2d1c
+#define MGA_WR8				0x2d20
+#define MGA_WR9				0x2d24
+#define MGA_WR10			0x2d28
+#define MGA_WR11			0x2d2c
+#define MGA_WR12			0x2d30
+#define MGA_WR13			0x2d34
+#define MGA_WR14			0x2d38
+#define MGA_WR15			0x2d3c
+#define MGA_WR16			0x2d40
+#define MGA_WR17			0x2d44
+#define MGA_WR18			0x2d48
+#define MGA_WR19			0x2d4c
+#define MGA_WR20			0x2d50
+#define MGA_WR21			0x2d54
+#define MGA_WR22			0x2d58
+#define MGA_WR23			0x2d5c
+#define MGA_WR24			0x2d60
+#define MGA_WR25			0x2d64
+#define MGA_WR26			0x2d68
+#define MGA_WR27			0x2d6c
+#define MGA_WR28			0x2d70
+#define MGA_WR29			0x2d74
+#define MGA_WR30			0x2d78
+#define MGA_WR31			0x2d7c
+#define MGA_WR32			0x2d80
+#define MGA_WR33			0x2d84
+#define MGA_WR34			0x2d88
+#define MGA_WR35			0x2d8c
+#define MGA_WR36			0x2d90
+#define MGA_WR37			0x2d94
+#define MGA_WR38			0x2d98
+#define MGA_WR39			0x2d9c
+#define MGA_WR40			0x2da0
+#define MGA_WR41			0x2da4
+#define MGA_WR42			0x2da8
+#define MGA_WR43			0x2dac
+#define MGA_WR44			0x2db0
+#define MGA_WR45			0x2db4
+#define MGA_WR46			0x2db8
+#define MGA_WR47			0x2dbc
+#define MGA_WR48			0x2dc0
+#define MGA_WR49			0x2dc4
+#define MGA_WR50			0x2dc8
+#define MGA_WR51			0x2dcc
+#define MGA_WR52			0x2dd0
+#define MGA_WR53			0x2dd4
+#define MGA_WR54			0x2dd8
+#define MGA_WR55			0x2ddc
+#define MGA_WR56			0x2de0
+#define MGA_WR57			0x2de4
+#define MGA_WR58			0x2de8
+#define MGA_WR59			0x2dec
+#define MGA_WR60			0x2df0
+#define MGA_WR61			0x2df4
+#define MGA_WR62			0x2df8
+#define MGA_WR63			0x2dfc
+#	define MGA_G400_WR_MAGIC		(1 << 6)
+#	define MGA_G400_WR56_MAGIC		0x46480000	/* 12800.0f */
+
+
+#define MGA_ILOAD_ALIGN		64
+#define MGA_ILOAD_MASK		(MGA_ILOAD_ALIGN - 1)
+
+#define MGA_DWGCTL_FLUSH	(MGA_OPCOD_TEXTURE_TRAP |		\
+				 MGA_ATYPE_I |				\
+				 MGA_ZMODE_NOZCMP |			\
+				 MGA_ARZERO |				\
+				 MGA_SGNZERO |				\
+				 MGA_BOP_SRC |				\
+				 (15 << MGA_TRANS_SHIFT))
+
+#define MGA_DWGCTL_CLEAR	(MGA_OPCOD_TRAP |			\
+				 MGA_ZMODE_NOZCMP |			\
+				 MGA_SOLID |				\
+				 MGA_ARZERO |				\
+				 MGA_SGNZERO |				\
+				 MGA_SHIFTZERO |			\
+				 MGA_BOP_SRC |				\
+				 (0 << MGA_TRANS_SHIFT) |		\
+				 MGA_BLTMOD_BMONOLEF |			\
+				 MGA_TRANSC |				\
+				 MGA_CLIPDIS)
+
+#define MGA_DWGCTL_COPY		(MGA_OPCOD_BITBLT |			\
+				 MGA_ATYPE_RPL |			\
+				 MGA_SGNZERO |				\
+				 MGA_SHIFTZERO |			\
+				 MGA_BOP_SRC |				\
+				 (0 << MGA_TRANS_SHIFT) |		\
+				 MGA_BLTMOD_BFCOL |			\
+				 MGA_CLIPDIS)
+
+/* Simple idle test.
+ */
+static inline int mga_is_idle( drm_mga_private_t *dev_priv )
+{
+	u32 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
+	return ( status == MGA_ENDPRDMASTS );
+}
 
 #endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga_state.c linux/drivers/char/drm/mga_state.c
--- linux-2.4.8-pre6/drivers/char/drm/mga_state.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/char/drm/mga_state.c	Mon Dec  3 22:59:45 2001
@@ -1,4 +1,4 @@
-/* mga_state.c -- State support for mga g200/g400 -*- linux-c -*-
+/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*-
  * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -19,404 +19,400 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  *
- * Authors: Jeff Hartmann <jhartmann@valinux.com>
- * 	    Keith Whitwell <keithw@valinux.com>
+ * Authors:
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Keith Whitwell <keithw@valinux.com>
  *
+ * Rewritten by:
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #define __NO_VERSION__
+#include "mga.h"
 #include "drmP.h"
 #include "mga_drv.h"
 #include "drm.h"
 
-/* If you change the functions to set state, PLEASE
- * change these values
+
+/* ================================================================
+ * DMA hardware state programming functions
  */
 
-#define MGAEMITCLIP_SIZE	10
-#define MGAEMITCTX_SIZE		20
-#define MGAG200EMITTEX_SIZE 	20
-#define MGAG400EMITTEX0_SIZE	30
-#define MGAG400EMITTEX1_SIZE	25
-#define MGAG400EMITPIPE_SIZE	50
-#define MGAG200EMITPIPE_SIZE	15
-
-#define MAX_STATE_SIZE ((MGAEMITCLIP_SIZE * MGA_NR_SAREA_CLIPRECTS) + \
-			MGAEMITCTX_SIZE + MGAG400EMITTEX0_SIZE + \
-			MGAG400EMITTEX1_SIZE + MGAG400EMITPIPE_SIZE)
-
-static void mgaEmitClipRect(drm_mga_private_t * dev_priv,
-			    drm_clip_rect_t * box)
+static void mga_emit_clip_rect( drm_mga_private_t *dev_priv,
+				drm_clip_rect_t *box )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	unsigned int *regs = sarea_priv->ContextState;
-	PRIMLOCALS;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	unsigned int pitch = dev_priv->front_pitch;
+	DMA_LOCALS;
 
-	/* This takes 10 dwords */
-	PRIMGETPTR(dev_priv);
+	BEGIN_DMA( 2 );
 
-	/* Force reset of dwgctl on G400 (eliminates clip disable bit) */
-	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
-#if 0
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DWGSYNC, 0);
-		PRIMOUTREG(MGAREG_DWGSYNC, 0);
-		PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
-#else
-		PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
-		PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
-		PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
-		PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
-#endif
+	/* Force reset of DWGCTL on G400 (eliminates clip disable bit).
+	 */
+	if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
+		DMA_BLOCK( MGA_DWGCTL,		ctx->dwgctl,
+			   MGA_LEN + MGA_EXEC,	0x80000000,
+			   MGA_DWGCTL,		ctx->dwgctl,
+			   MGA_LEN + MGA_EXEC,	0x80000000 );
 	}
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_CXBNDRY, ((box->x2) << 16) | (box->x1));
-	PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / dev_priv->cpp);
-	PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / dev_priv->cpp);
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_CXBNDRY,	(box->x2 << 16) | box->x1,
+		   MGA_YTOP,	box->y1 * pitch,
+		   MGA_YBOT,	box->y2 * pitch );
 
-	PRIMADVANCE(dev_priv);
+	ADVANCE_DMA();
 }
 
-static void mgaEmitContext(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;
-	unsigned int *regs = sarea_priv->ContextState;
-	PRIMLOCALS;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	DMA_LOCALS;
 
-	/* This takes a max of 20 dwords */
-	PRIMGETPTR(dev_priv);
+	BEGIN_DMA( 3 );
 
-	PRIMOUTREG(MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG]);
-	PRIMOUTREG(MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS]);
-	PRIMOUTREG(MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT]);
-	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
+	DMA_BLOCK( MGA_DSTORG,		ctx->dstorg,
+		   MGA_MACCESS,		ctx->maccess,
+		   MGA_PLNWT,		ctx->plnwt,
+		   MGA_DWGCTL,		ctx->dwgctl );
 
-	PRIMOUTREG(MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL]);
-	PRIMOUTREG(MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR]);
-	PRIMOUTREG(MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG]);
-	PRIMOUTREG(MGAREG_ZORG, dev_priv->depthOffset);	/* invarient */
+	DMA_BLOCK( MGA_ALPHACTRL,	ctx->alphactrl,
+		   MGA_FOGCOL,		ctx->fogcolor,
+		   MGA_WFLAG,		ctx->wflag,
+		   MGA_ZORG,		dev_priv->depth_offset );
 
-	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
-		PRIMOUTREG(MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG]);
-		PRIMOUTREG(MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0]);
-		PRIMOUTREG(MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1]);
-		PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);
+	DMA_BLOCK( MGA_FCOL,		ctx->fcol,
+		   MGA_DMAPAD,		0x00000000,
+		   MGA_DMAPAD,		0x00000000,
+		   MGA_DMAPAD,		0x00000000 );
 
-		PRIMOUTREG(MGAREG_STENCIL, regs[MGA_CTXREG_STENCIL]);
-		PRIMOUTREG(MGAREG_STENCILCTL, regs[MGA_CTXREG_STENCILCTL]);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-	} else {
-		PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-	}
-
-	PRIMADVANCE(dev_priv);
+	ADVANCE_DMA();
 }
 
-static void mgaG200EmitTex(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;
-	unsigned int *regs = sarea_priv->TexState[0];
-	PRIMLOCALS;
-
-	PRIMGETPTR(dev_priv);
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	DMA_LOCALS;
 
-	/* This takes 20 dwords */
+	BEGIN_DMA( 4 );
 
-	PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2]);
-	PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
-	PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
-	PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
+	DMA_BLOCK( MGA_DSTORG,		ctx->dstorg,
+		   MGA_MACCESS,		ctx->maccess,
+		   MGA_PLNWT,		ctx->plnwt,
+		   MGA_DWGCTL,		ctx->dwgctl );
 
-	PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
-	PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
-	PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
-	PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
+	DMA_BLOCK( MGA_ALPHACTRL,	ctx->alphactrl,
+		   MGA_FOGCOL,		ctx->fogcolor,
+		   MGA_WFLAG,		ctx->wflag,
+		   MGA_ZORG,		dev_priv->depth_offset );
 
-	PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
-	PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
-	PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
-	PRIMOUTREG(MGAREG_WR24, regs[MGA_TEXREG_WIDTH]);
+	DMA_BLOCK( MGA_WFLAG1,		ctx->wflag,
+		   MGA_TDUALSTAGE0,	ctx->tdualstage0,
+		   MGA_TDUALSTAGE1,	ctx->tdualstage1,
+		   MGA_FCOL,		ctx->fcol );
 
-	PRIMOUTREG(MGAREG_WR34, regs[MGA_TEXREG_HEIGHT]);
-	PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
-	PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
+	DMA_BLOCK( MGA_STENCIL,		ctx->stencil,
+		   MGA_STENCILCTL,	ctx->stencilctl,
+		   MGA_DMAPAD,		0x00000000,
+		   MGA_DMAPAD,		0x00000000 );
 
-	PRIMADVANCE(dev_priv);
+	ADVANCE_DMA();
 }
 
-#define TMC_dualtex_enable 		0x80
-
-static void mgaG400EmitTex0(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;
-	unsigned int *regs = sarea_priv->TexState[0];
-	PRIMLOCALS;
-
-	PRIMGETPTR(dev_priv);
-
-	/* This takes 30 dwords */
-
-	PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
-	PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
-	PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
-	PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
+	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+	DMA_LOCALS;
 
-	PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
-	PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
-	PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
-	PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
+	BEGIN_DMA( 4 );
 
-	PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
-	PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
-	PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
-	PRIMOUTREG(MGAREG_WR49, 0);
+	DMA_BLOCK( MGA_TEXCTL2,		tex->texctl2,
+		   MGA_TEXCTL,		tex->texctl,
+		   MGA_TEXFILTER,	tex->texfilter,
+		   MGA_TEXBORDERCOL,	tex->texbordercol );
 
-	PRIMOUTREG(MGAREG_WR57, 0);
-	PRIMOUTREG(MGAREG_WR53, 0);
-	PRIMOUTREG(MGAREG_WR61, 0);
-	PRIMOUTREG(MGAREG_WR52, 0x40);
+	DMA_BLOCK( MGA_TEXORG,		tex->texorg,
+		   MGA_TEXORG1,		tex->texorg1,
+		   MGA_TEXORG2,		tex->texorg2,
+		   MGA_TEXORG3,		tex->texorg3 );
 
-	PRIMOUTREG(MGAREG_WR60, 0x40);
-	PRIMOUTREG(MGAREG_WR54, regs[MGA_TEXREG_WIDTH] | 0x40);
-	PRIMOUTREG(MGAREG_WR62, regs[MGA_TEXREG_HEIGHT] | 0x40);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
+	DMA_BLOCK( MGA_TEXORG4,		tex->texorg4,
+		   MGA_TEXWIDTH,	tex->texwidth,
+		   MGA_TEXHEIGHT,	tex->texheight,
+		   MGA_WR24,		tex->texwidth );
 
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
-	PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
+	DMA_BLOCK( MGA_WR34,		tex->texheight,
+		   MGA_TEXTRANS,	0x0000ffff,
+		   MGA_TEXTRANSHIGH,	0x0000ffff,
+		   MGA_DMAPAD,		0x00000000 );
 
-	PRIMADVANCE(dev_priv);
+	ADVANCE_DMA();
 }
 
-#define TMC_map1_enable 		0x80000000
-
-static void mgaG400EmitTex1(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;
-	unsigned int *regs = sarea_priv->TexState[1];
-	PRIMLOCALS;
+	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+	DMA_LOCALS;
 
-	PRIMGETPTR(dev_priv);
+	BEGIN_DMA( 6 );
 
-	/* This takes 25 dwords */
+	DMA_BLOCK( MGA_TEXCTL2,		tex->texctl2 | MGA_G400_TC2_MAGIC,
+		   MGA_TEXCTL,		tex->texctl,
+		   MGA_TEXFILTER,	tex->texfilter,
+		   MGA_TEXBORDERCOL,	tex->texbordercol );
 
-	PRIMOUTREG(MGAREG_TEXCTL2,
-		   regs[MGA_TEXREG_CTL2] | TMC_map1_enable | 0x00008000);
-	PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
-	PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
-	PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
+	DMA_BLOCK( MGA_TEXORG,		tex->texorg,
+		   MGA_TEXORG1,		tex->texorg1,
+		   MGA_TEXORG2,		tex->texorg2,
+		   MGA_TEXORG3,		tex->texorg3 );
 
-	PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
-	PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
-	PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
-	PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
+	DMA_BLOCK( MGA_TEXORG4,		tex->texorg4,
+		   MGA_TEXWIDTH,	tex->texwidth,
+		   MGA_TEXHEIGHT,	tex->texheight,
+		   MGA_WR49,		0x00000000 );
 
-	PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
-	PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
-	PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
-	PRIMOUTREG(MGAREG_WR49, 0);
+	DMA_BLOCK( MGA_WR57,		0x00000000,
+		   MGA_WR53,		0x00000000,
+		   MGA_WR61,		0x00000000,
+		   MGA_WR52,		MGA_G400_WR_MAGIC );
 
-	PRIMOUTREG(MGAREG_WR57, 0);
-	PRIMOUTREG(MGAREG_WR53, 0);
-	PRIMOUTREG(MGAREG_WR61, 0);
-	PRIMOUTREG(MGAREG_WR52, regs[MGA_TEXREG_WIDTH] | 0x40);
+	DMA_BLOCK( MGA_WR60,		MGA_G400_WR_MAGIC,
+		   MGA_WR54,		tex->texwidth | MGA_G400_WR_MAGIC,
+		   MGA_WR62,		tex->texheight | MGA_G400_WR_MAGIC,
+		   MGA_DMAPAD,		0x00000000 );
 
-	PRIMOUTREG(MGAREG_WR60, regs[MGA_TEXREG_HEIGHT] | 0x40);
-	PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
-	PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
-	PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
+	DMA_BLOCK( MGA_DMAPAD,		0x00000000,
+		   MGA_DMAPAD,		0x00000000,
+		   MGA_TEXTRANS,	0x0000ffff,
+		   MGA_TEXTRANSHIGH,	0x0000ffff );
 
-	PRIMADVANCE(dev_priv);
+	ADVANCE_DMA();
 }
 
-#define MAGIC_FPARAM_HEX_VALUE 0x46480000
-/* This is the hex value of 12800.0f which is a magic value we must
- * set in wr56.
- */
-
-static void mgaG400EmitPipe(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;
-	unsigned int pipe = sarea_priv->WarpPipe;
-	PRIMLOCALS;
+	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
+	DMA_LOCALS;
 
-	PRIMGETPTR(dev_priv);
+	BEGIN_DMA( 5 );
 
-	/* This takes 50 dwords */
+	DMA_BLOCK( MGA_TEXCTL2,		(tex->texctl2 |
+					 MGA_MAP1_ENABLE |
+					 MGA_G400_TC2_MAGIC),
+		   MGA_TEXCTL,		tex->texctl,
+		   MGA_TEXFILTER,	tex->texfilter,
+		   MGA_TEXBORDERCOL,	tex->texbordercol );
+
+	DMA_BLOCK( MGA_TEXORG,		tex->texorg,
+		   MGA_TEXORG1,		tex->texorg1,
+		   MGA_TEXORG2,		tex->texorg2,
+		   MGA_TEXORG3,		tex->texorg3 );
+
+	DMA_BLOCK( MGA_TEXORG4,		tex->texorg4,
+		   MGA_TEXWIDTH,	tex->texwidth,
+		   MGA_TEXHEIGHT,	tex->texheight,
+		   MGA_WR49,		0x00000000 );
+
+	DMA_BLOCK( MGA_WR57,		0x00000000,
+		   MGA_WR53,		0x00000000,
+		   MGA_WR61,		0x00000000,
+		   MGA_WR52,		tex->texwidth | MGA_G400_WR_MAGIC );
+
+	DMA_BLOCK( MGA_WR60,		tex->texheight | MGA_G400_WR_MAGIC,
+		   MGA_TEXTRANS,	0x0000ffff,
+		   MGA_TEXTRANSHIGH,	0x0000ffff,
+		   MGA_TEXCTL2,		tex->texctl2 | MGA_G400_TC2_MAGIC );
 
-	/* Establish vertex size.  
-	 */
-	PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-
-	if (pipe & MGA_T2) {
-		PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-
-		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
-		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
-		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
-		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
-	} else {
-		if (dev_priv->WarpPipe & MGA_T2) {
-			/* Flush the WARP pipe */
-			PRIMOUTREG(MGAREG_YDST, 0);
-			PRIMOUTREG(MGAREG_FXLEFT, 0);
-			PRIMOUTREG(MGAREG_FXRIGHT, 1);
-			PRIMOUTREG(MGAREG_DWGCTL, MGA_FLUSH_CMD);
-
-			PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 1);
-			PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
-			PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
-			PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
-
-			PRIMOUTREG(MGAREG_TEXCTL2, 0x80 | 0x00008000);
-			PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
-			PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-		}
-
-		PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
-		PRIMOUTREG(MGAREG_DMAPAD, 0);
+	ADVANCE_DMA();
+}
 
-		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
-		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
-		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
-		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
-	}
+static inline void mga_g200_emit_pipe( drm_mga_private_t *dev_priv )
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	unsigned int pipe = sarea_priv->warp_pipe;
+	DMA_LOCALS;
 
-	PRIMOUTREG(MGAREG_WFLAG, 0);
-	PRIMOUTREG(MGAREG_WFLAG1, 0);
-	PRIMOUTREG(MGAREG_WR56, MAGIC_FPARAM_HEX_VALUE);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
+	BEGIN_DMA( 3 );
 
-	PRIMOUTREG(MGAREG_WR49, 0);	/* Tex stage 0 */
-	PRIMOUTREG(MGAREG_WR57, 0);	/* Tex stage 0 */
-	PRIMOUTREG(MGAREG_WR53, 0);	/* Tex stage 1 */
-	PRIMOUTREG(MGAREG_WR61, 0);	/* Tex stage 1 */
+	DMA_BLOCK( MGA_WIADDR,	MGA_WMODE_SUSPEND,
+		   MGA_WVRTXSZ,	0x00000007,
+		   MGA_WFLAG,	0x00000000,
+		   MGA_WR24,	0x00000000 );
+
+	DMA_BLOCK( MGA_WR25,	0x00000100,
+		   MGA_WR34,	0x00000000,
+		   MGA_WR42,	0x0000ffff,
+		   MGA_WR60,	0x0000ffff );
 
-	PRIMOUTREG(MGAREG_WR54, 0x40);	/* Tex stage 0 : w */
-	PRIMOUTREG(MGAREG_WR62, 0x40);	/* Tex stage 0 : h */
-	PRIMOUTREG(MGAREG_WR52, 0x40);	/* Tex stage 1 : w */
-	PRIMOUTREG(MGAREG_WR60, 0x40);	/* Tex stage 1 : h */
+	/* Padding required to to hardware bug.
+	 */
+	DMA_BLOCK( MGA_DMAPAD,	0xffffffff,
+		   MGA_DMAPAD,	0xffffffff,
+		   MGA_DMAPAD,	0xffffffff,
+		   MGA_WIADDR,	(dev_priv->warp_pipe_phys[pipe] |
+				 MGA_WMODE_START |
+				 MGA_WAGP_ENABLE) );
 
-	/* Dma pading required due to hw bug */
-	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
-	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
-	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
-	PRIMOUTREG(MGAREG_WIADDR2,
-		   (u32) (dev_priv->WarpIndex[pipe].
-			  phys_addr | WIA_wmode_start | WIA_wagp_agp));
-	PRIMADVANCE(dev_priv);
+	ADVANCE_DMA();
 }
 
-static void mgaG200EmitPipe(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->WarpPipe;
-	PRIMLOCALS;
-
-	PRIMGETPTR(dev_priv);
-
-	/* This takes 15 dwords */
+	unsigned int pipe = sarea_priv->warp_pipe;
+	DMA_LOCALS;
 
-	PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
-	PRIMOUTREG(MGAREG_WVRTXSZ, 7);
-	PRIMOUTREG(MGAREG_WFLAG, 0);
-	PRIMOUTREG(MGAREG_WR24, 0);	/* tex w/h */
+	BEGIN_DMA( 10 );
 
-	PRIMOUTREG(MGAREG_WR25, 0x100);
-	PRIMOUTREG(MGAREG_WR34, 0);	/* tex w/h */
-	PRIMOUTREG(MGAREG_WR42, 0xFFFF);
-	PRIMOUTREG(MGAREG_WR60, 0xFFFF);
+	DMA_BLOCK( MGA_WIADDR2,	MGA_WMODE_SUSPEND,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000 );
+
+	if ( pipe & MGA_T2 ) {
+		DMA_BLOCK( MGA_WVRTXSZ,		0x00001e09,
+			   MGA_DMAPAD,		0x00000000,
+			   MGA_DMAPAD,		0x00000000,
+			   MGA_DMAPAD,		0x00000000 );
+
+		DMA_BLOCK( MGA_WACCEPTSEQ,	0x00000000,
+			   MGA_WACCEPTSEQ,	0x00000000,
+			   MGA_WACCEPTSEQ,	0x00000000,
+			   MGA_WACCEPTSEQ,	0x1e000000 );
+	} else {
+		if ( dev_priv->warp_pipe & MGA_T2 ) {
+			/* Flush the WARP pipe */
+			DMA_BLOCK( MGA_YDST,		0x00000000,
+				   MGA_FXLEFT,		0x00000000,
+				   MGA_FXRIGHT,		0x00000001,
+				   MGA_DWGCTL,		MGA_DWGCTL_FLUSH );
+
+			DMA_BLOCK( MGA_LEN + MGA_EXEC,	0x00000001,
+				   MGA_DWGSYNC,		0x00007000,
+				   MGA_TEXCTL2,		MGA_G400_TC2_MAGIC,
+				   MGA_LEN + MGA_EXEC,	0x00000000 );
+
+			DMA_BLOCK( MGA_TEXCTL2,		(MGA_DUALTEX |
+							 MGA_G400_TC2_MAGIC),
+				   MGA_LEN + MGA_EXEC,	0x00000000,
+				   MGA_TEXCTL2,		MGA_G400_TC2_MAGIC,
+				   MGA_DMAPAD,		0x00000000 );
+		}
 
-	/* Dma pading required due to hw bug */
-	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
-	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
-	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
-	PRIMOUTREG(MGAREG_WIADDR,
-		   (u32) (dev_priv->WarpIndex[pipe].
-			  phys_addr | WIA_wmode_start | WIA_wagp_agp));
+		DMA_BLOCK( MGA_WVRTXSZ,		0x00001807,
+			   MGA_DMAPAD,		0x00000000,
+			   MGA_DMAPAD,		0x00000000,
+			   MGA_DMAPAD,		0x00000000 );
+
+		DMA_BLOCK( MGA_WACCEPTSEQ,	0x00000000,
+			   MGA_WACCEPTSEQ,	0x00000000,
+			   MGA_WACCEPTSEQ,	0x00000000,
+			   MGA_WACCEPTSEQ,	0x18000000 );
+	}
+
+	DMA_BLOCK( MGA_WFLAG,	0x00000000,
+		   MGA_WFLAG1,	0x00000000,
+		   MGA_WR56,	MGA_G400_WR56_MAGIC,
+		   MGA_DMAPAD,	0x00000000 );
+
+	DMA_BLOCK( MGA_WR49,	0x00000000,		/* tex0              */
+		   MGA_WR57,	0x00000000,		/* tex0              */
+		   MGA_WR53,	0x00000000,		/* tex1              */
+		   MGA_WR61,	0x00000000 );		/* tex1              */
+
+	DMA_BLOCK( MGA_WR54,	MGA_G400_WR_MAGIC,	/* tex0 width        */
+		   MGA_WR62,	MGA_G400_WR_MAGIC,	/* tex0 height       */
+		   MGA_WR52,	MGA_G400_WR_MAGIC,	/* tex1 width        */
+		   MGA_WR60,	MGA_G400_WR_MAGIC );	/* tex1 height       */
+
+	/* Padding required to to hardware bug */
+	DMA_BLOCK( MGA_DMAPAD,	0xffffffff,
+		   MGA_DMAPAD,	0xffffffff,
+		   MGA_DMAPAD,	0xffffffff,
+		   MGA_WIADDR2,	(dev_priv->warp_pipe_phys[pipe] |
+				 MGA_WMODE_START |
+				 MGA_WAGP_ENABLE) );
 
-	PRIMADVANCE( dev_priv );
+	ADVANCE_DMA();
 }
 
-static void mgaEmitState(drm_mga_private_t * dev_priv)
+static void mga_g200_emit_state( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int dirty = sarea_priv->dirty;
 
-	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
-		int multitex = sarea_priv->WarpPipe & MGA_T2;
+	if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
+		mga_g200_emit_pipe( dev_priv );
+		dev_priv->warp_pipe = sarea_priv->warp_pipe;
+	}
 
-		if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
-			mgaG400EmitPipe(dev_priv);
-			dev_priv->WarpPipe = sarea_priv->WarpPipe;
-		}
+	if ( dirty & MGA_UPLOAD_CONTEXT ) {
+		mga_g200_emit_context( dev_priv );
+		sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+	}
 
-		if (dirty & MGA_UPLOAD_CTX) {
-			mgaEmitContext(dev_priv);
-			sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
-		}
+	if ( dirty & MGA_UPLOAD_TEX0 ) {
+		mga_g200_emit_tex0( dev_priv );
+		sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+	}
+}
 
-		if (dirty & MGA_UPLOAD_TEX0) {
-			mgaG400EmitTex0(dev_priv);
-			sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
-		}
+static void mga_g400_emit_state( drm_mga_private_t *dev_priv )
+{
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	unsigned int dirty = sarea_priv->dirty;
+	int multitex = sarea_priv->warp_pipe & MGA_T2;
 
-		if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
-			mgaG400EmitTex1(dev_priv);
-			sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
-		}
-	} else {
-		if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
-			mgaG200EmitPipe(dev_priv);
-			dev_priv->WarpPipe = sarea_priv->WarpPipe;
-		}
+	if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) {
+		mga_g400_emit_pipe( dev_priv );
+		dev_priv->warp_pipe = sarea_priv->warp_pipe;
+	}
 
-		if (dirty & MGA_UPLOAD_CTX) {
-			mgaEmitContext(dev_priv);
-			sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
-		}
+	if ( dirty & MGA_UPLOAD_CONTEXT ) {
+		mga_g400_emit_context( dev_priv );
+		sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+	}
 
-		if (dirty & MGA_UPLOAD_TEX0) {
-			mgaG200EmitTex(dev_priv);
-			sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
-		}
+	if ( dirty & MGA_UPLOAD_TEX0 ) {
+		mga_g400_emit_tex0( dev_priv );
+		sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+	}
+
+	if ( (dirty & MGA_UPLOAD_TEX1) && multitex ) {
+		mga_g400_emit_tex1( dev_priv );
+		sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
 	}
 }
 
+
+/* ================================================================
+ * SAREA state verification
+ */
+
 /* Disallow all write destinations except the front and backbuffer.
  */
-static int mgaVerifyContext(drm_mga_private_t * dev_priv)
+static int mga_verify_context( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	unsigned int *regs = sarea_priv->ContextState;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 
-	if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
-	    regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
-		DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n",
-			  regs[MGA_CTXREG_DSTORG], dev_priv->frontOffset,
-			  dev_priv->backOffset);
-		regs[MGA_CTXREG_DSTORG] = 0;
-		return -1;
+	if ( ctx->dstorg != dev_priv->front_offset &&
+	     ctx->dstorg != dev_priv->back_offset ) {
+		DRM_ERROR( "*** bad DSTORG: %x (front %x, back %x)\n\n",
+			   ctx->dstorg, dev_priv->front_offset,
+			   dev_priv->back_offset );
+		ctx->dstorg = 0;
+		return -EINVAL;
 	}
 
 	return 0;
@@ -424,594 +420,668 @@
 
 /* Disallow texture reads from PCI space.
  */
-static int mgaVerifyTex(drm_mga_private_t * dev_priv, int unit)
+static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
+	unsigned int org;
 
-	if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
-		DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n",
-			  sarea_priv->TexState[unit][MGA_TEXREG_ORG],
-			  unit);
-		sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
-		return -1;
+	org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
+
+	if ( org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI) ) {
+		DRM_ERROR( "*** bad TEXORG: 0x%x, unit %d\n",
+			   tex->texorg, unit );
+		tex->texorg = 0;
+		return -EINVAL;
 	}
 
 	return 0;
 }
 
-static int mgaVerifyState(drm_mga_private_t * dev_priv)
+static int mga_verify_state( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int dirty = sarea_priv->dirty;
-	int rv = 0;
+	int ret = 0;
 
-	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+	if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 
-	if (dirty & MGA_UPLOAD_CTX)
-		rv |= mgaVerifyContext(dev_priv);
+	if ( dirty & MGA_UPLOAD_CONTEXT )
+		ret |= mga_verify_context( dev_priv );
 
-	if (dirty & MGA_UPLOAD_TEX0)
-		rv |= mgaVerifyTex(dev_priv, 0);
+	if ( dirty & MGA_UPLOAD_TEX0 )
+		ret |= mga_verify_tex( dev_priv, 0 );
 
-	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
-		if (dirty & MGA_UPLOAD_TEX1)
-			rv |= mgaVerifyTex(dev_priv, 1);
+	if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) {
+		if ( dirty & MGA_UPLOAD_TEX1 )
+			ret |= mga_verify_tex( dev_priv, 1 );
 
-		if (dirty & MGA_UPLOAD_PIPE)
-			rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES);
+		if ( dirty & MGA_UPLOAD_PIPE )
+			ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES );
 	} else {
-		if (dirty & MGA_UPLOAD_PIPE)
-			rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES);
+		if ( dirty & MGA_UPLOAD_PIPE )
+			ret |= ( sarea_priv->warp_pipe > MGA_MAX_G200_PIPES );
 	}
 
-	return rv == 0;
+	return ( ret == 0 );
 }
 
-static int mgaVerifyIload(drm_mga_private_t * dev_priv,
-			  unsigned long bus_address,
-			  unsigned int dstOrg, int length)
+static int mga_verify_iload( drm_mga_private_t *dev_priv,
+			     unsigned int dstorg, unsigned int length )
 {
-	if (dstOrg < dev_priv->textureOffset ||
-	    dstOrg + length >
-	    (dev_priv->textureOffset + dev_priv->textureSize)) {
+	if ( dstorg < dev_priv->texture_offset ||
+	     dstorg + length > (dev_priv->texture_offset +
+				dev_priv->texture_size) ) {
+		DRM_ERROR( "*** bad iload DSTORG: 0x%x\n", dstorg );
 		return -EINVAL;
 	}
-	if (length % 64) {
+
+	if ( length & MGA_ILOAD_MASK ) {
+		DRM_ERROR( "*** bad iload length: 0x%x\n",
+			   length & MGA_ILOAD_MASK );
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mga_verify_blit( drm_mga_private_t *dev_priv,
+			    unsigned int srcorg, unsigned int dstorg )
+{
+	if ( (srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
+	     (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) {
+		DRM_ERROR( "*** bad blit: src=0x%x dst=0x%x\n",
+			   srcorg, dstorg );
 		return -EINVAL;
 	}
 	return 0;
 }
 
-/* This copies a 64 byte aligned agp region to the frambuffer
- * with a standard blit, the ioctl needs to do checking */
 
-static void mga_dma_dispatch_tex_blit(drm_device_t * dev,
-				      unsigned long bus_address,
-				      int length, unsigned int destOrg)
+/* ================================================================
+ *
+ */
+
+static void mga_dma_dispatch_clear( drm_device_t *dev,
+				    drm_mga_clear_t *clear )
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
-	int use_agp = PDEA_pagpxfer_enable | 0x00000001;
-	u16 y2;
-	PRIMLOCALS;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	int nbox = sarea_priv->nbox;
+	int i;
+	DMA_LOCALS;
+	DRM_DEBUG( __FUNCTION__ ":\n" );
 
-	y2 = length / 64;
+	BEGIN_DMA( 1 );
+
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_DWGSYNC,	0x00007100,
+		   MGA_DWGSYNC,	0x00007000 );
+
+	ADVANCE_DMA();
+
+	for ( i = 0 ; i < nbox ; i++ ) {
+		drm_clip_rect_t *box = &pbox[i];
+		u32 height = box->y2 - box->y1;
+
+		DRM_DEBUG( "   from=%d,%d to=%d,%d\n",
+			   box->x1, box->y1, box->x2, box->y2 );
+
+		if ( clear->flags & MGA_FRONT ) {
+			BEGIN_DMA( 2 );
+
+			DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+				   MGA_PLNWT,	clear->color_mask,
+				   MGA_YDSTLEN, (box->y1 << 16) | height,
+				   MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+
+			DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+				   MGA_FCOL,	clear->clear_color,
+				   MGA_DSTORG,	dev_priv->front_offset,
+				   MGA_DWGCTL + MGA_EXEC,
+						dev_priv->clear_cmd );
+
+			ADVANCE_DMA();
+		}
+
+
+		if ( clear->flags & MGA_BACK ) {
+			BEGIN_DMA( 2 );
+
+			DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+				   MGA_PLNWT,	clear->color_mask,
+				   MGA_YDSTLEN, (box->y1 << 16) | height,
+				   MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+
+			DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+				   MGA_FCOL,	clear->clear_color,
+				   MGA_DSTORG,	dev_priv->back_offset,
+				   MGA_DWGCTL + MGA_EXEC,
+						dev_priv->clear_cmd );
+
+			ADVANCE_DMA();
+		}
+
+		if ( clear->flags & MGA_DEPTH ) {
+			BEGIN_DMA( 2 );
+
+			DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+				   MGA_PLNWT,	clear->depth_mask,
+				   MGA_YDSTLEN, (box->y1 << 16) | height,
+				   MGA_FXBNDRY, (box->x2 << 16) | box->x1 );
+
+			DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+				   MGA_FCOL,	clear->clear_depth,
+				   MGA_DSTORG,	dev_priv->depth_offset,
+				   MGA_DWGCTL + MGA_EXEC,
+						dev_priv->clear_cmd );
+
+			ADVANCE_DMA();
+		}
+
+	}
+
+	BEGIN_DMA( 1 );
+
+	/* Force reset of DWGCTL */
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_PLNWT,	ctx->plnwt,
+		   MGA_DWGCTL,	ctx->dwgctl );
+
+	ADVANCE_DMA();
+
+	FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_swap( drm_device_t *dev )
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+	drm_clip_rect_t *pbox = sarea_priv->boxes;
+	int nbox = sarea_priv->nbox;
+	int i;
+	DMA_LOCALS;
+	DRM_DEBUG( __FUNCTION__ ":\n" );
+
+	sarea_priv->last_frame.head = dev_priv->prim.tail;
+	sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
 
-	PRIM_OVERFLOW(dev, dev_priv, 30);
+	BEGIN_DMA( 4 + nbox );
 
-	PRIMOUTREG(MGAREG_DSTORG, destOrg);
-	PRIMOUTREG(MGAREG_MACCESS, 0x00000000);
-	PRIMOUTREG(MGAREG_SRCORG, (u32) bus_address | use_agp);
-	PRIMOUTREG(MGAREG_AR5, 64);
-
-	PRIMOUTREG(MGAREG_PITCH, 64);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
-
-	PRIMOUTREG(MGAREG_AR0, 63);
-	PRIMOUTREG(MGAREG_AR3, 0);
-	PRIMOUTREG(MGAREG_FXBNDRY, (63 << 16));
-	PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC, y2);
-
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_SRCORG, 0);
-	PRIMOUTREG(MGAREG_PITCH, dev_priv->stride / dev_priv->cpp);
-	PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
-	PRIMADVANCE(dev_priv);
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_DWGSYNC,	0x00007100,
+		   MGA_DWGSYNC,	0x00007000 );
+
+	DMA_BLOCK( MGA_DSTORG,	dev_priv->front_offset,
+		   MGA_MACCESS,	dev_priv->maccess,
+		   MGA_SRCORG,	dev_priv->back_offset,
+		   MGA_AR5,	dev_priv->front_pitch );
+
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_PLNWT,	0xffffffff,
+		   MGA_DWGCTL,	MGA_DWGCTL_COPY );
+
+	for ( i = 0 ; i < nbox ; i++ ) {
+		drm_clip_rect_t *box = &pbox[i];
+		u32 height = box->y2 - box->y1;
+		u32 start = box->y1 * dev_priv->front_pitch;
+
+		DRM_DEBUG( "   from=%d,%d to=%d,%d\n",
+			   box->x1, box->y1, box->x2, box->y2 );
+
+		DMA_BLOCK( MGA_AR0,	start + box->x2 - 1,
+			   MGA_AR3,	start + box->x1,
+			   MGA_FXBNDRY,	((box->x2 - 1) << 16) | box->x1,
+			   MGA_YDSTLEN + MGA_EXEC,
+					(box->y1 << 16) | height );
+	}
+
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_PLNWT,	ctx->plnwt,
+		   MGA_SRCORG,	dev_priv->front_offset,
+		   MGA_DWGCTL,	ctx->dwgctl );
+
+	ADVANCE_DMA();
+
+	FLUSH_DMA();
+
+	DRM_DEBUG( "%s... done.\n", __FUNCTION__ );
 }
 
-static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
+static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf )
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	unsigned long address = (unsigned long) buf->bus_address;
-	int length = buf->used;
-	int use_agp = PDEA_pagpxfer_enable;
+	u32 address = (u32) buf->bus_address;
+	u32 length = (u32) buf->used;
 	int i = 0;
-	PRIMLOCALS;
+	DMA_LOCALS;
+	DRM_DEBUG( "vertex: buf=%d used=%d\n", buf->idx, buf->used );
 
-	if (buf->used) {
-		/* WARNING: if you change any of the state functions verify
-		 * these numbers (Overestimating this doesn't hurt).
-		 */
+	if ( buf->used ) {
 		buf_priv->dispatched = 1;
-		PRIM_OVERFLOW(dev, dev_priv,
-			      (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
-		mgaEmitState(dev_priv);
 
-#if 0
-		length = dev_priv->vertexsize * 3 * 4;
-#endif
+		MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
 
 		do {
-			if (i < sarea_priv->nbox) {
-				mgaEmitClipRect(dev_priv,
-						&sarea_priv->boxes[i]);
+			if ( i < sarea_priv->nbox ) {
+				mga_emit_clip_rect( dev_priv,
+						    &sarea_priv->boxes[i] );
 			}
 
-			PRIMGETPTR(dev_priv);
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_SECADDRESS,
-				   ((u32) address) | TT_VERTEX);
-			PRIMOUTREG(MGAREG_SECEND,
-				   (((u32) (address + length)) | use_agp));
-			PRIMADVANCE(dev_priv);
-		} while (++i < sarea_priv->nbox);
-	}
-	if (buf_priv->discard) {
-		if (buf_priv->dispatched == 1)
-			AGEBUF(dev_priv, buf_priv);
+			BEGIN_DMA( 1 );
+
+			DMA_BLOCK( MGA_DMAPAD,		0x00000000,
+				   MGA_DMAPAD,		0x00000000,
+				   MGA_SECADDRESS,	(address |
+							 MGA_DMA_VERTEX),
+				   MGA_SECEND,		((address + length) |
+							 MGA_PAGPXFER) );
+
+			ADVANCE_DMA();
+		} while ( ++i < sarea_priv->nbox );
+	}
+
+	if ( buf_priv->discard ) {
+		AGE_BUFFER( buf_priv );
+		buf->pending = 0;
+		buf->used = 0;
 		buf_priv->dispatched = 0;
-		mga_freelist_put(dev, buf);
-	}
 
+		mga_freelist_put( dev, buf );
+	}
 
+	FLUSH_DMA();
 }
 
-
-static void mga_dma_dispatch_indices(drm_device_t * dev,
-				     drm_buf_t * buf,
-				     unsigned int start, unsigned int end)
+static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf,
+				      unsigned int start, unsigned int end )
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	unsigned int address = (unsigned int) buf->bus_address;
-	int use_agp = PDEA_pagpxfer_enable;
+	u32 address = (u32) buf->bus_address;
 	int i = 0;
-	PRIMLOCALS;
+	DMA_LOCALS;
+	DRM_DEBUG( "indices: buf=%d start=%d end=%d\n", buf->idx, start, end );
 
-	if (start != end) {
-		/* WARNING: if you change any of the state functions verify
-		 * these numbers (Overestimating this doesn't hurt).
-		 */
+	if ( start != end ) {
 		buf_priv->dispatched = 1;
-		PRIM_OVERFLOW(dev, dev_priv,
-			      (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
-		mgaEmitState(dev_priv);
+
+		MGA_EMIT_STATE( dev_priv, sarea_priv->dirty );
 
 		do {
-			if (i < sarea_priv->nbox) {
-				mgaEmitClipRect(dev_priv,
-						&sarea_priv->boxes[i]);
+			if ( i < sarea_priv->nbox ) {
+				mga_emit_clip_rect( dev_priv,
+						    &sarea_priv->boxes[i] );
 			}
 
-			PRIMGETPTR(dev_priv);
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_SETUPADDRESS,
-				   ((address + start) |
-				    SETADD_mode_vertlist));
-			PRIMOUTREG(MGAREG_SETUPEND,
-				   ((address + end) | use_agp));
-/*  				   ((address + start + 12) | use_agp)); */
-			PRIMADVANCE(dev_priv);
-		} while (++i < sarea_priv->nbox);
-	}
-	if (buf_priv->discard) {
-		if (buf_priv->dispatched == 1)
-			AGEBUF(dev_priv, buf_priv);
+			BEGIN_DMA( 1 );
+
+			DMA_BLOCK( MGA_DMAPAD,		0x00000000,
+				   MGA_DMAPAD,		0x00000000,
+				   MGA_SETUPADDRESS,	address + start,
+				   MGA_SETUPEND,	((address + end) |
+							 MGA_PAGPXFER) );
+
+			ADVANCE_DMA();
+		} while ( ++i < sarea_priv->nbox );
+	}
+
+	if ( buf_priv->discard ) {
+		AGE_BUFFER( buf_priv );
+		buf->pending = 0;
+		buf->used = 0;
 		buf_priv->dispatched = 0;
-		mga_freelist_put(dev, buf);
+
+		mga_freelist_put( dev, buf );
 	}
-}
 
+	FLUSH_DMA();
+}
 
-static void mga_dma_dispatch_clear(drm_device_t * dev, int flags,
-				   unsigned int clear_color,
-				   unsigned int clear_zval,
-				   unsigned int clear_colormask,
-				   unsigned int clear_depthmask)
+/* This copies a 64 byte aligned agp region to the frambuffer with a
+ * standard blit, the ioctl needs to do checking.
+ */
+static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf,
+				    unsigned int dstorg, unsigned int length )
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
-	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	unsigned int *regs = sarea_priv->ContextState;
-	int nbox = sarea_priv->nbox;
-	drm_clip_rect_t *pbox = sarea_priv->boxes;
-	unsigned int cmd;
-	int i;
-	PRIMLOCALS;
+	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+	drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
+	u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM;
+	u32 y2;
+	DMA_LOCALS;
+	DRM_DEBUG( "%s: buf=%d used=%d\n",
+		   __FUNCTION__, buf->idx, buf->used );
 
-	if (dev_priv->sgram)
-		cmd = MGA_CLEAR_CMD | DC_atype_blk;
-	else
-		cmd = MGA_CLEAR_CMD | DC_atype_rstr;
-
-	PRIM_OVERFLOW(dev, dev_priv, 35 * MGA_NR_SAREA_CLIPRECTS);
-
-	for (i = 0; i < nbox; i++) {
-		unsigned int height = pbox[i].y2 - pbox[i].y1;
-
-		if (flags & MGA_FRONT) {
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
-			PRIMOUTREG(MGAREG_YDSTLEN,
-				   (pbox[i].y1 << 16) | height);
-			PRIMOUTREG(MGAREG_FXBNDRY,
-				   (pbox[i].x2 << 16) | pbox[i].x1);
-
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_FCOL, clear_color);
-			PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
-			PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
-		}
+	y2 = length / 64;
 
-		if (flags & MGA_BACK) {
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
-			PRIMOUTREG(MGAREG_YDSTLEN,
-				   (pbox[i].y1 << 16) | height);
-			PRIMOUTREG(MGAREG_FXBNDRY,
-				   (pbox[i].x2 << 16) | pbox[i].x1);
-
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_FCOL, clear_color);
-			PRIMOUTREG(MGAREG_DSTORG, dev_priv->backOffset);
-			PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
-		}
+	BEGIN_DMA( 5 );
 
-		if (flags & MGA_DEPTH) {
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_PLNWT, clear_depthmask);
-			PRIMOUTREG(MGAREG_YDSTLEN,
-				   (pbox[i].y1 << 16) | height);
-			PRIMOUTREG(MGAREG_FXBNDRY,
-				   (pbox[i].x2 << 16) | pbox[i].x1);
-
-			PRIMOUTREG(MGAREG_DMAPAD, 0);
-			PRIMOUTREG(MGAREG_FCOL, clear_zval);
-			PRIMOUTREG(MGAREG_DSTORG, dev_priv->depthOffset);
-			PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
-		}
-	}
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_DWGSYNC,	0x00007100,
+		   MGA_DWGSYNC,	0x00007000 );
 
-	/* Force reset of DWGCTL */
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
-	PRIMADVANCE(dev_priv);
+	DMA_BLOCK( MGA_DSTORG,	dstorg,
+		   MGA_MACCESS,	0x00000000,
+		   MGA_SRCORG,	srcorg,
+		   MGA_AR5,	64 );
+
+	DMA_BLOCK( MGA_PITCH,	64,
+		   MGA_PLNWT,	0xffffffff,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_DWGCTL,	MGA_DWGCTL_COPY );
+
+	DMA_BLOCK( MGA_AR0,	63,
+		   MGA_AR3,	0,
+		   MGA_FXBNDRY,	(63 << 16) | 0,
+		   MGA_YDSTLEN + MGA_EXEC, y2 );
+
+	DMA_BLOCK( MGA_PLNWT,	ctx->plnwt,
+		   MGA_SRCORG,	dev_priv->front_offset,
+		   MGA_PITCH,	dev_priv->front_pitch,
+		   MGA_DWGSYNC,	0x00007000 );
+
+	ADVANCE_DMA();
+
+	AGE_BUFFER( buf_priv );
+
+	buf->pending = 0;
+	buf->used = 0;
+	buf_priv->dispatched = 0;
+
+	mga_freelist_put( dev, buf );
+
+	FLUSH_DMA();
 }
 
-static void mga_dma_dispatch_swap(drm_device_t * dev)
+static void mga_dma_dispatch_blit( drm_device_t *dev,
+				   drm_mga_blit_t *blit )
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	unsigned int *regs = sarea_priv->ContextState;
-	int nbox = sarea_priv->nbox;
+	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 	drm_clip_rect_t *pbox = sarea_priv->boxes;
-	int i;
-	int pixel_stride = dev_priv->stride / dev_priv->cpp;
+	int nbox = sarea_priv->nbox;
+	u32 scandir = 0, i;
+	DMA_LOCALS;
+	DRM_DEBUG( __FUNCTION__ ":\n" );
+
+	BEGIN_DMA( 4 + nbox );
+
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_DMAPAD,	0x00000000,
+		   MGA_DWGSYNC,	0x00007100,
+		   MGA_DWGSYNC,	0x00007000 );
+
+	DMA_BLOCK( MGA_DWGCTL,	MGA_DWGCTL_COPY,
+		   MGA_PLNWT,	blit->planemask,
+		   MGA_SRCORG,	blit->srcorg,
+		   MGA_DSTORG,	blit->dstorg );
+
+	DMA_BLOCK( MGA_SGN,	scandir,
+		   MGA_MACCESS,	dev_priv->maccess,
+		   MGA_AR5,	blit->ydir * blit->src_pitch,
+		   MGA_PITCH,	blit->dst_pitch );
+
+	for ( i = 0 ; i < nbox ; i++ ) {
+		int srcx = pbox[i].x1 + blit->delta_sx;
+		int srcy = pbox[i].y1 + blit->delta_sy;
+		int dstx = pbox[i].x1 + blit->delta_dx;
+		int dsty = pbox[i].y1 + blit->delta_dy;
+		int h = pbox[i].y2 - pbox[i].y1;
+		int w = pbox[i].x2 - pbox[i].x1 - 1;
+		int start;
 
-	PRIMLOCALS;
+		if ( blit->ydir == -1 ) {
+			srcy = blit->height - srcy - 1;
+		}
 
-	PRIM_OVERFLOW(dev, dev_priv, (MGA_NR_SAREA_CLIPRECTS * 5) + 20);
+		start = srcy * blit->src_pitch + srcx;
 
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DWGSYNC, 0x7100);
-	PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
-
-	PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
-	PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
-	PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
-	PRIMOUTREG(MGAREG_AR5, pixel_stride);
-
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
-
-	for (i = 0; i < nbox; i++) {
-		unsigned int h = pbox[i].y2 - pbox[i].y1;
-		unsigned int start = pbox[i].y1 * pixel_stride;
-
-		PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
-		PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1);
-		PRIMOUTREG(MGAREG_FXBNDRY,
-			   pbox[i].x1 | ((pbox[i].x2 - 1) << 16));
-		PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC,
-			   (pbox[i].y1 << 16) | h);
+		DMA_BLOCK( MGA_AR0,	start + w,
+			   MGA_AR3,	start,
+			   MGA_FXBNDRY,	((dstx + w) << 16) | (dstx & 0xffff),
+			   MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h );
 	}
 
+	/* Do something to flush AGP?
+	 */
+
 	/* Force reset of DWGCTL */
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_DMAPAD, 0);
-	PRIMOUTREG(MGAREG_SRCORG, 0);
-	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
+	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
+		   MGA_PLNWT,	ctx->plnwt,
+		   MGA_PITCH,	dev_priv->front_pitch,
+		   MGA_DWGCTL,	ctx->dwgctl );
 
-	PRIMADVANCE(dev_priv);
+	ADVANCE_DMA();
 }
 
-int mga_clear_bufs(struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg)
+
+/* ================================================================
+ *
+ */
+
+int mga_dma_clear( 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_mga_private_t *dev_priv =
-	    (drm_mga_private_t *) dev->dev_private;
+	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_clear_t clear;
 
-	if (copy_from_user(&clear, (drm_mga_clear_t *) arg, sizeof(clear)))
-		return -EFAULT;
+	LOCK_TEST_WITH_RETURN( dev );
 
-	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("mga_clear_bufs called without lock held\n");
-		return -EINVAL;
-	}
+	if ( copy_from_user( &clear, (drm_mga_clear_t *) arg, sizeof(clear) ) )
+		return -EFAULT;
 
-	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+	if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 
+	WRAP_TEST_WITH_RETURN( dev_priv );
+
+	mga_dma_dispatch_clear( dev, &clear );
+
 	/* Make sure we restore the 3D state next time.
 	 */
-	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
-	mga_dma_dispatch_clear(dev, clear.flags,
-			       clear.clear_color,
-			       clear.clear_depth,
-			       clear.clear_color_mask,
-			       clear.clear_depth_mask);
-	PRIMUPDATE(dev_priv);
-	mga_flush_write_combine();
-	mga_dma_schedule(dev, 1);
+	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
 	return 0;
 }
 
-int mga_swap_bufs(struct inode *inode, struct file *filp,
-		  unsigned int cmd, unsigned long arg)
+int mga_dma_swap( 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_mga_private_t *dev_priv =
-	    (drm_mga_private_t *) dev->dev_private;
+	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 
-	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("mga_swap_bufs called without lock held\n");
-		return -EINVAL;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
-	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+	if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 
+	WRAP_TEST_WITH_RETURN( dev_priv );
+
+	mga_dma_dispatch_swap( dev );
+
 	/* Make sure we restore the 3D state next time.
 	 */
-	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
-	mga_dma_dispatch_swap(dev);
-	PRIMUPDATE(dev_priv);
-	set_bit(MGA_BUF_SWAP_PENDING,
-		&dev_priv->current_prim->buffer_status);
-	mga_flush_write_combine();
-	mga_dma_schedule(dev, 1);
+	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
 	return 0;
 }
 
-int mga_iload(struct inode *inode, struct file *filp,
-	      unsigned int cmd, unsigned long arg)
+int mga_dma_vertex( 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_mga_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
-	drm_mga_private_t *dev_priv =
-	    (drm_mga_private_t *) dev->dev_private;
-	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_buf_t *buf;
 	drm_mga_buf_priv_t *buf_priv;
-	drm_mga_iload_t iload;
-	unsigned long bus_address;
+	drm_mga_vertex_t vertex;
 
-	if (copy_from_user(&iload, (drm_mga_iload_t *) arg, sizeof(iload)))
-		return -EFAULT;
+	LOCK_TEST_WITH_RETURN( dev );
 
-	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("mga_iload called without lock held\n");
-		return -EINVAL;
-	}
+	if ( copy_from_user( &vertex,
+			     (drm_mga_vertex_t *)arg,
+			     sizeof(vertex) ) )
+		return -EFAULT;
 
-	if(iload.idx < 0 || iload.idx > dma->buf_count) return -EINVAL;
-	buf = dma->buflist[iload.idx];
+        if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
+	buf = dma->buflist[vertex.idx];
 	buf_priv = buf->dev_private;
-	bus_address = buf->bus_address;
 
-	if (mgaVerifyIload(dev_priv,
-			   bus_address, iload.destOrg, iload.length)) {
-		mga_freelist_put(dev, buf);
+	buf->used = vertex.used;
+	buf_priv->discard = vertex.discard;
+
+	if ( !mga_verify_state( dev_priv ) ) {
+		if ( vertex.discard ) {
+			if ( buf_priv->dispatched == 1 )
+				AGE_BUFFER( buf_priv );
+			buf_priv->dispatched = 0;
+			mga_freelist_put( dev, buf );
+		}
 		return -EINVAL;
 	}
 
-	sarea_priv->dirty |= MGA_UPLOAD_CTX;
+	WRAP_TEST_WITH_RETURN( dev_priv );
+
+	mga_dma_dispatch_vertex( dev, buf );
 
-	mga_dma_dispatch_tex_blit(dev, bus_address, iload.length,
-				  iload.destOrg);
-	AGEBUF(dev_priv, buf_priv);
-	buf_priv->discard = 1;
-	mga_freelist_put(dev, buf);
-	mga_flush_write_combine();
-	mga_dma_schedule(dev, 1);
 	return 0;
 }
 
-int mga_vertex(struct inode *inode, struct file *filp,
-	       unsigned int cmd, unsigned long arg)
+int mga_dma_indices( 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_mga_private_t *dev_priv =
-	    (drm_mga_private_t *) dev->dev_private;
+	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
 	drm_mga_buf_priv_t *buf_priv;
-	drm_mga_vertex_t vertex;
+	drm_mga_indices_t indices;
 
-	if (copy_from_user(&vertex, (drm_mga_vertex_t *) arg, sizeof(vertex)))
-		return -EFAULT;
+	LOCK_TEST_WITH_RETURN( dev );
 
-	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("mga_vertex called without lock held\n");
-		return -EINVAL;
-	}
+	if ( copy_from_user( &indices,
+			     (drm_mga_indices_t *)arg,
+			     sizeof(indices) ) )
+		return -EFAULT;
 
-	if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
+        if(indices.idx < 0 || indices.idx > dma->buf_count) return -EINVAL;
 
-	buf = dma->buflist[vertex.idx];
+	buf = dma->buflist[indices.idx];
 	buf_priv = buf->dev_private;
 
-	buf->used = vertex.used;
-	buf_priv->discard = vertex.discard;
+	buf_priv->discard = indices.discard;
 
-	if (!mgaVerifyState(dev_priv)) {
-		if (vertex.discard) {
-			if (buf_priv->dispatched == 1)
-				AGEBUF(dev_priv, buf_priv);
+	if ( !mga_verify_state( dev_priv ) ) {
+		if ( indices.discard ) {
+			if ( buf_priv->dispatched == 1 )
+				AGE_BUFFER( buf_priv );
 			buf_priv->dispatched = 0;
-			mga_freelist_put(dev, buf);
+			mga_freelist_put( dev, buf );
 		}
 		return -EINVAL;
 	}
 
-	mga_dma_dispatch_vertex(dev, buf);
+	WRAP_TEST_WITH_RETURN( dev_priv );
+
+	mga_dma_dispatch_indices( dev, buf, indices.start, indices.end );
 
-	PRIMUPDATE(dev_priv);
-	mga_flush_write_combine();
-	mga_dma_schedule(dev, 1);
 	return 0;
 }
 
-
-int mga_indices(struct inode *inode, struct file *filp,
-		unsigned int cmd, unsigned long arg)
+int mga_dma_iload( 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_mga_private_t *dev_priv =
-	    (drm_mga_private_t *) dev->dev_private;
 	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_indices_t indices;
+	drm_mga_iload_t iload;
+	DRM_DEBUG( __FUNCTION__ ":\n" );
 
-	if (copy_from_user(&indices,
-			   (drm_mga_indices_t *)arg, sizeof(indices)))
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( copy_from_user( &iload, (drm_mga_iload_t *)arg, sizeof(iload) ) )
 		return -EFAULT;
 
-	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("mga_indices called without lock held\n");
-		return -EINVAL;
+#if 0
+	if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {
+		if ( MGA_DMA_DEBUG )
+			DRM_INFO( __FUNCTION__": -EBUSY\n" );
+		return -EBUSY;
 	}
+#endif
+        if(iload.idx < 0 || iload.idx > dma->buf_count) return -EINVAL;
 
-	if(indices.idx < 0 || indices.idx > dma->buf_count) return -EINVAL;
-	buf = dma->buflist[indices.idx];
+	buf = dma->buflist[iload.idx];
 	buf_priv = buf->dev_private;
 
-	buf_priv->discard = indices.discard;
-
-	if (!mgaVerifyState(dev_priv)) {
-		if (indices.discard) {
-			if (buf_priv->dispatched == 1)
-				AGEBUF(dev_priv, buf_priv);
-			buf_priv->dispatched = 0;
-			mga_freelist_put(dev, buf);
-		}
+	if ( mga_verify_iload( dev_priv, iload.dstorg, iload.length ) ) {
+		mga_freelist_put( dev, buf );
 		return -EINVAL;
 	}
 
-	mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
-
-	PRIMUPDATE(dev_priv);
-	mga_flush_write_combine();
-	mga_dma_schedule(dev, 1);
-	return 0;
-}
+	WRAP_TEST_WITH_RETURN( dev_priv );
 
+	mga_dma_dispatch_iload( dev, buf, iload.dstorg, iload.length );
 
+	/* Make sure we restore the 3D state next time.
+	 */
+	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
 
-static int mga_dma_get_buffers(drm_device_t * dev, drm_dma_t * d)
-{
-	int i;
-	drm_buf_t *buf;
-
-	for (i = d->granted_count; i < d->request_count; i++) {
-		buf = mga_freelist_get(dev);
-		if (!buf)
-			break;
-		buf->pid = current->pid;
-		if (copy_to_user(&d->request_indices[i],
-				 &buf->idx, sizeof(buf->idx)))
-			return -EFAULT;
-		if (copy_to_user(&d->request_sizes[i],
-				 &buf->total, sizeof(buf->total)))
-			return -EFAULT;
-		++d->granted_count;
-	}
 	return 0;
 }
 
-int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
-	    unsigned long arg)
+int mga_dma_blit( 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_device_dma_t *dma = dev->dma;
-	int retcode = 0;
-	drm_dma_t d;
+	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__ );
+
+	LOCK_TEST_WITH_RETURN( dev );
 
-	if (copy_from_user(&d, (drm_dma_t *) arg, sizeof(d)))
+	if ( copy_from_user( &blit, (drm_mga_blit_t *)arg, sizeof(blit) ) )
 		return -EFAULT;
 
-	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-		DRM_ERROR("mga_dma called without lock held\n");
-		return -EINVAL;
-	}
+	if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS )
+		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 
-	/* 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);
+	if ( mga_verify_blit( dev_priv, blit.srcorg, blit.dstorg ) )
 		return -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;
-	}
+	WRAP_TEST_WITH_RETURN( dev_priv );
 
-	d.granted_count = 0;
+	mga_dma_dispatch_blit( dev, &blit );
 
-	if (d.request_count) {
-		retcode = mga_dma_get_buffers(dev, &d);
-	}
+	/* Make sure we restore the 3D state next time.
+	 */
+	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
 
-	if (copy_to_user((drm_dma_t *) arg, &d, sizeof(d)))
-		return -EFAULT;
-	return retcode;
+	return 0;
 }
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga_ucode.h linux/drivers/char/drm/mga_ucode.h
--- linux-2.4.8-pre6/drivers/char/drm/mga_ucode.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/mga_ucode.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,11645 @@
+/* mga_ucode.h -- Matrox G200/G400 WARP engine microcode -*- linux-c -*-
+ * Created: Thu Jan 11 21:20:43 2001 by gareth@valinux.com
+ *
+ * Copyright 1999 Matrox Graphics Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * MATROX GRAPHICS INC., OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Kernel-based WARP engine management:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * WARP pipes are named according to the functions they perform, where:
+ *
+ *   - T stands for computation of texture stage 0
+ *   - T2 stands for computation of both texture stage 0 and texture stage 1
+ *   - G stands for computation of triangle intensity (Gouraud interpolation)
+ *   - Z stands for computation of Z buffer interpolation
+ *   - S stands for computation of specular highlight
+ *   - A stands for computation of the alpha channel
+ *   - F stands for computation of vertex fog interpolation
+ */
+
+static unsigned char warp_g200_tgz[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x72, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x60, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x03, 0x80, 0x0A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x57, 0x39, 0x20, 0xE9,
+0x28, 0x19, 0x60, 0xEC,
+
+0x2B, 0x32, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0xB3, 0x05,
+0x00, 0xE0,
+0x16, 0x28, 0x20, 0xE9,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x2B, 0x20, 0xE9,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x85, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x84, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x82, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x7F, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgza[] = {
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x7D, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x6B, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x44, 0x4C, 0xB6,
+0x25, 0x44, 0x54, 0xB6,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x07, 0xC0, 0x44, 0xC6,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1F, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x3F, 0x3D, 0x5D, 0x9F,
+0x00, 0xE0,
+0x07, 0x20,
+
+0x00, 0x80, 0x00, 0xE8,
+0x28, 0x19, 0x60, 0xEC,
+
+0xB3, 0x05,
+0x00, 0xE0,
+0x00, 0x80, 0x00, 0xE8,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0x26, 0x1F, 0xDF,
+0x9D, 0x1F, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x9E, 0x3F, 0x4F, 0xE9,
+
+0x07, 0x07, 0x1F, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x9C, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x7A, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x79, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x77, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x74, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzaf[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x83, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x6F, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0D, 0x21, 0x1A, 0xB6,
+0x05, 0x21, 0x31, 0xB6,
+
+0x2D, 0x44, 0x4C, 0xB6,
+0x25, 0x44, 0x54, 0xB6,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x2F, 0xC0, 0x21, 0xC6,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x07, 0xC0, 0x44, 0xC6,
+
+0x17, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x2D, 0x20,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x1F, 0x62, 0x57, 0x9F,
+0x00, 0xE0,
+0x07, 0x20,
+
+0x3F, 0x3D, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x28, 0x19, 0x60, 0xEC,
+
+0xB3, 0x05,
+0x00, 0xE0,
+0x17, 0x26, 0x17, 0xDF,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x35, 0x17, 0x4F, 0xE9,
+
+0x1F, 0x26, 0x1F, 0xDF,
+0x9D, 0x1F, 0x4F, 0xE9,
+
+0x9E, 0x3F, 0x4F, 0xE9,
+0x39, 0x37, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x17, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x07, 0x07, 0x1F, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x31, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x9C, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x74, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x73, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x71, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6E, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzf[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x7F, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x6B, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0D, 0x21, 0x1A, 0xB6,
+0x05, 0x21, 0x31, 0xB6,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x2F, 0xC0, 0x21, 0xC6,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x17, 0x50, 0x56, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x00, 0x80, 0x00, 0xE8,
+0x28, 0x19, 0x60, 0xEC,
+
+0xB3, 0x05,
+0x00, 0xE0,
+0x00, 0x80, 0x00, 0xE8,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x17, 0x26, 0x17, 0xDF,
+0x35, 0x17, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x39, 0x37, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x17, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x31, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x78, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x77, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x75, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x72, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzs[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x8B, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x77, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x21, 0x1A, 0xB0,
+0x25, 0x21, 0x31, 0xB0,
+
+0x0D, 0x21, 0x1A, 0xB2,
+0x05, 0x21, 0x31, 0xB2,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x05, 0x20,
+0x0D, 0x20,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x2F, 0xC0, 0x21, 0xC0,
+
+0x16, 0x42, 0x56, 0x9F,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x21, 0x31, 0xB4,
+0x2D, 0x21, 0x1A, 0xB4,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0x05,
+0x00, 0xE0,
+0x28, 0x19, 0x60, 0xEC,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x26, 0x1E, 0xDF,
+
+0xA7, 0x1E, 0x4F, 0xE9,
+0x17, 0x26, 0x16, 0xDF,
+
+0x2D, 0x20,
+0x00, 0xE0,
+0xA8, 0x3F, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x1E, 0xAF,
+0x25, 0x20,
+0x00, 0xE0,
+
+0xA4, 0x16, 0x4F, 0xE9,
+0x0F, 0xC0, 0x21, 0xC2,
+
+0xA6, 0x80, 0x4F, 0xE9,
+0x1F, 0x62, 0x57, 0x9F,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0xE0,
+0x8F, 0x20,
+
+0xA5, 0x37, 0x4F, 0xE9,
+0x0F, 0x17, 0x0F, 0xAF,
+
+0x06, 0xC0, 0x21, 0xC4,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0xA3, 0x80, 0x4F, 0xE9,
+
+0x06, 0x20,
+0x00, 0xE0,
+0x1F, 0x26, 0x1F, 0xDF,
+
+0xA1, 0x1F, 0x4F, 0xE9,
+0xA2, 0x3F, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x06, 0x06, 0x1F, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x6C, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6B, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x69, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsa[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x8F, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x7B, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x21, 0x1A, 0xB0,
+0x25, 0x21, 0x31, 0xB0,
+
+0x0D, 0x21, 0x1A, 0xB2,
+0x05, 0x21, 0x31, 0xB2,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x05, 0x20,
+0x0D, 0x20,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x2F, 0xC0, 0x21, 0xC0,
+
+0x16, 0x42, 0x56, 0x9F,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x21, 0x31, 0xB4,
+0x2D, 0x21, 0x1A, 0xB4,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0x05,
+0x00, 0xE0,
+0x28, 0x19, 0x60, 0xEC,
+
+0x0D, 0x44, 0x4C, 0xB6,
+0x05, 0x44, 0x54, 0xB6,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x26, 0x1E, 0xDF,
+
+0xA7, 0x1E, 0x4F, 0xE9,
+0x17, 0x26, 0x16, 0xDF,
+
+0x2D, 0x20,
+0x00, 0xE0,
+0xA8, 0x3F, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x1E, 0xAF,
+0x25, 0x20,
+0x00, 0xE0,
+
+0xA4, 0x16, 0x4F, 0xE9,
+0x0F, 0xC0, 0x21, 0xC2,
+
+0xA6, 0x80, 0x4F, 0xE9,
+0x1F, 0x62, 0x57, 0x9F,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x00, 0x80, 0x00, 0xE8,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0xE0,
+0x0F, 0x20,
+
+0x17, 0x50, 0x56, 0x9F,
+0xA5, 0x37, 0x4F, 0xE9,
+
+0x06, 0xC0, 0x21, 0xC4,
+0x0F, 0x17, 0x0F, 0xAF,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2F, 0xC0, 0x44, 0xC6,
+0xA3, 0x80, 0x4F, 0xE9,
+
+0x06, 0x20,
+0x00, 0xE0,
+0x1F, 0x26, 0x1F, 0xDF,
+
+0x17, 0x26, 0x17, 0xDF,
+0x9D, 0x17, 0x4F, 0xE9,
+
+0xA1, 0x1F, 0x4F, 0xE9,
+0xA2, 0x3F, 0x4F, 0xE9,
+
+0x06, 0x06, 0x1F, 0xAF,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x9E, 0x37, 0x4F, 0xE9,
+0x2F, 0x17, 0x2F, 0xAF,
+
+0xA0, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x9C, 0x80, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x68, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x67, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x65, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x62, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsaf[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x94, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x80, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x21, 0x1A, 0xB0,
+0x25, 0x21, 0x31, 0xB0,
+
+0x0D, 0x21, 0x1A, 0xB2,
+0x05, 0x21, 0x31, 0xB2,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x05, 0x20,
+0x0D, 0x20,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x2F, 0xC0, 0x21, 0xC0,
+
+0x16, 0x42, 0x56, 0x9F,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x21, 0x31, 0xB4,
+0x2D, 0x21, 0x1A, 0xB4,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0x05,
+0x00, 0xE0,
+0x28, 0x19, 0x60, 0xEC,
+
+0x0D, 0x21, 0x1A, 0xB6,
+0x05, 0x21, 0x31, 0xB6,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x26, 0x1E, 0xDF,
+
+0xA7, 0x1E, 0x4F, 0xE9,
+0x17, 0x26, 0x16, 0xDF,
+
+0x2D, 0x20,
+0x00, 0xE0,
+0xA8, 0x3F, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x1E, 0xAF,
+0x25, 0x20,
+0x00, 0xE0,
+
+0xA4, 0x16, 0x4F, 0xE9,
+0x0F, 0xC0, 0x21, 0xC2,
+
+0xA6, 0x80, 0x4F, 0xE9,
+0x1F, 0x62, 0x57, 0x9F,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x2F, 0xC0, 0x21, 0xC6,
+
+0x2D, 0x44, 0x4C, 0xB6,
+0x25, 0x44, 0x54, 0xB6,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0xE0,
+0x0F, 0x20,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x07, 0xC0, 0x44, 0xC6,
+
+0x17, 0x50, 0x56, 0x9F,
+0xA5, 0x37, 0x4F, 0xE9,
+
+0x06, 0xC0, 0x21, 0xC4,
+0x0F, 0x17, 0x0F, 0xAF,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x3E, 0x3D, 0x5D, 0x9F,
+0x00, 0xE0,
+0x07, 0x20,
+
+0x2F, 0x20,
+0x00, 0xE0,
+0xA3, 0x0F, 0x4F, 0xE9,
+
+0x06, 0x20,
+0x00, 0xE0,
+0x1F, 0x26, 0x1F, 0xDF,
+
+0x17, 0x26, 0x17, 0xDF,
+0xA1, 0x1F, 0x4F, 0xE9,
+
+0x1E, 0x26, 0x1E, 0xDF,
+0x9D, 0x1E, 0x4F, 0xE9,
+
+0x35, 0x17, 0x4F, 0xE9,
+0xA2, 0x3F, 0x4F, 0xE9,
+
+0x06, 0x06, 0x1F, 0xAF,
+0x39, 0x37, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x17, 0xAF,
+0x07, 0x07, 0x1E, 0xAF,
+
+0xA0, 0x80, 0x4F, 0xE9,
+0x9E, 0x3E, 0x4F, 0xE9,
+
+0x31, 0x80, 0x4F, 0xE9,
+0x9C, 0x80, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x63, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x62, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x60, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x5D, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsf[] = {
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x98, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x81, 0x04,
+0x89, 0x04,
+0x01, 0x04,
+0x09, 0x04,
+
+0xC9, 0x41, 0xC0, 0xEC,
+0x11, 0x04,
+0x00, 0xE0,
+
+0x41, 0xCC, 0x41, 0xCD,
+0x49, 0xCC, 0x49, 0xCD,
+
+0xD1, 0x41, 0xC0, 0xEC,
+0x51, 0xCC, 0x51, 0xCD,
+
+0x80, 0x04,
+0x10, 0x04,
+0x08, 0x04,
+0x00, 0xE0,
+
+0x00, 0xCC, 0xC0, 0xCD,
+0xD1, 0x49, 0xC0, 0xEC,
+
+0x8A, 0x1F, 0x20, 0xE9,
+0x8B, 0x3F, 0x20, 0xE9,
+
+0x41, 0x3C, 0x41, 0xAD,
+0x49, 0x3C, 0x49, 0xAD,
+
+0x10, 0xCC, 0x10, 0xCD,
+0x08, 0xCC, 0x08, 0xCD,
+
+0xB9, 0x41, 0x49, 0xBB,
+0x1F, 0xF0, 0x41, 0xCD,
+
+0x51, 0x3C, 0x51, 0xAD,
+0x00, 0x98, 0x80, 0xE9,
+
+0x8F, 0x80, 0x07, 0xEA,
+0x24, 0x1F, 0x20, 0xE9,
+
+0x21, 0x45, 0x80, 0xE8,
+0x1A, 0x4D, 0x80, 0xE8,
+
+0x31, 0x55, 0x80, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0x41, 0x49, 0xBD,
+0x1D, 0x41, 0x51, 0xBD,
+
+0x2E, 0x41, 0x2A, 0xB8,
+0x34, 0x53, 0xA0, 0xE8,
+
+0x15, 0x30,
+0x1D, 0x30,
+0x58, 0xE3,
+0x00, 0xE0,
+
+0xB5, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x24, 0x43, 0xA0, 0xE8,
+0x2C, 0x4B, 0xA0, 0xE8,
+
+0x15, 0x72,
+0x09, 0xE3,
+0x00, 0xE0,
+0x1D, 0x72,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0x97, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x6C, 0x64, 0xC8, 0xEC,
+0x98, 0xE1,
+0xB5, 0x05,
+
+0xBD, 0x05,
+0x2E, 0x30,
+0x32, 0xC0, 0xA0, 0xE8,
+
+0x33, 0xC0, 0xA0, 0xE8,
+0x74, 0x64, 0xC8, 0xEC,
+
+0x40, 0x3C, 0x40, 0xAD,
+0x32, 0x6A,
+0x2A, 0x30,
+
+0x20, 0x73,
+0x33, 0x6A,
+0x00, 0xE0,
+0x28, 0x73,
+
+0x1C, 0x72,
+0x83, 0xE2,
+0x7B, 0x80, 0x15, 0xEA,
+
+0xB8, 0x3D, 0x28, 0xDF,
+0x30, 0x35, 0x20, 0xDF,
+
+0x40, 0x30,
+0x00, 0xE0,
+0xCC, 0xE2,
+0x64, 0x72,
+
+0x25, 0x42, 0x52, 0xBF,
+0x2D, 0x42, 0x4A, 0xBF,
+
+0x30, 0x2E, 0x30, 0xDF,
+0x38, 0x2E, 0x38, 0xDF,
+
+0x18, 0x1D, 0x45, 0xE9,
+0x1E, 0x15, 0x45, 0xE9,
+
+0x2B, 0x49, 0x51, 0xBD,
+0x00, 0xE0,
+0x1F, 0x73,
+
+0x38, 0x38, 0x40, 0xAF,
+0x30, 0x30, 0x40, 0xAF,
+
+0x24, 0x1F, 0x24, 0xDF,
+0x1D, 0x32, 0x20, 0xE9,
+
+0x2C, 0x1F, 0x2C, 0xDF,
+0x1A, 0x33, 0x20, 0xE9,
+
+0xB0, 0x10,
+0x08, 0xE3,
+0x40, 0x10,
+0xB8, 0x10,
+
+0x26, 0xF0, 0x30, 0xCD,
+0x2F, 0xF0, 0x38, 0xCD,
+
+0x2B, 0x80, 0x20, 0xE9,
+0x2A, 0x80, 0x20, 0xE9,
+
+0xA6, 0x20,
+0x88, 0xE2,
+0x00, 0xE0,
+0xAF, 0x20,
+
+0x28, 0x2A, 0x26, 0xAF,
+0x20, 0x2A, 0xC0, 0xAF,
+
+0x34, 0x1F, 0x34, 0xDF,
+0x46, 0x24, 0x46, 0xDF,
+
+0x28, 0x30, 0x80, 0xBF,
+0x20, 0x38, 0x80, 0xBF,
+
+0x47, 0x24, 0x47, 0xDF,
+0x4E, 0x2C, 0x4E, 0xDF,
+
+0x4F, 0x2C, 0x4F, 0xDF,
+0x56, 0x34, 0x56, 0xDF,
+
+0x28, 0x15, 0x28, 0xDF,
+0x20, 0x1D, 0x20, 0xDF,
+
+0x57, 0x34, 0x57, 0xDF,
+0x00, 0xE0,
+0x1D, 0x05,
+
+0x04, 0x80, 0x10, 0xEA,
+0x89, 0xE2,
+0x2B, 0x30,
+
+0x3F, 0xC1, 0x1D, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x68,
+0xBF, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x20, 0xC0, 0x20, 0xAF,
+0x28, 0x05,
+0x97, 0x74,
+
+0x00, 0xE0,
+0x2A, 0x10,
+0x16, 0xC0, 0x20, 0xE9,
+
+0x04, 0x80, 0x10, 0xEA,
+0x8C, 0xE2,
+0x95, 0x05,
+
+0x28, 0xC1, 0x28, 0xAD,
+0x1F, 0xC1, 0x15, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA8, 0x67,
+0x9F, 0x6B,
+0x00, 0x80, 0x00, 0xE8,
+
+0x28, 0xC0, 0x28, 0xAD,
+0x1D, 0x25,
+0x20, 0x05,
+
+0x28, 0x32, 0x80, 0xAD,
+0x40, 0x2A, 0x40, 0xBD,
+
+0x1C, 0x80, 0x20, 0xE9,
+0x20, 0x33, 0x20, 0xAD,
+
+0x20, 0x73,
+0x00, 0xE0,
+0xB6, 0x49, 0x51, 0xBB,
+
+0x26, 0x2F, 0xB0, 0xE8,
+0x19, 0x20, 0x20, 0xE9,
+
+0x35, 0x20, 0x35, 0xDF,
+0x3D, 0x20, 0x3D, 0xDF,
+
+0x15, 0x20, 0x15, 0xDF,
+0x1D, 0x20, 0x1D, 0xDF,
+
+0x26, 0xD0, 0x26, 0xCD,
+0x29, 0x49, 0x2A, 0xB8,
+
+0x26, 0x40, 0x80, 0xBD,
+0x3B, 0x48, 0x50, 0xBD,
+
+0x3E, 0x54, 0x57, 0x9F,
+0x00, 0xE0,
+0x82, 0xE1,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x26, 0x30,
+0x29, 0x30,
+0x48, 0x3C, 0x48, 0xAD,
+
+0x2B, 0x72,
+0xC2, 0xE1,
+0x2C, 0xC0, 0x44, 0xC2,
+
+0x05, 0x24, 0x34, 0xBF,
+0x0D, 0x24, 0x2C, 0xBF,
+
+0x2D, 0x46, 0x4E, 0xBF,
+0x25, 0x46, 0x56, 0xBF,
+
+0x20, 0x1D, 0x6F, 0x8F,
+0x32, 0x3E, 0x5F, 0xE9,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x30,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x33, 0x1E, 0x5F, 0xE9,
+
+0x05, 0x44, 0x54, 0xB2,
+0x0D, 0x44, 0x4C, 0xB2,
+
+0x19, 0xC0, 0xB0, 0xE8,
+0x34, 0xC0, 0x44, 0xC4,
+
+0x33, 0x73,
+0x00, 0xE0,
+0x3E, 0x62, 0x57, 0x9F,
+
+0x1E, 0xAF, 0x59, 0x9F,
+0x00, 0xE0,
+0x0D, 0x20,
+
+0x84, 0x3E, 0x58, 0xE9,
+0x28, 0x1D, 0x6F, 0x8F,
+
+0x05, 0x20,
+0x00, 0xE0,
+0x85, 0x1E, 0x58, 0xE9,
+
+0x9B, 0x3B, 0x33, 0xDF,
+0x20, 0x20, 0x42, 0xAF,
+
+0x30, 0x42, 0x56, 0x9F,
+0x80, 0x3E, 0x57, 0xE9,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x30, 0x80, 0x5F, 0xE9,
+
+0x28, 0x28, 0x24, 0xAF,
+0x81, 0x1E, 0x57, 0xE9,
+
+0x05, 0x47, 0x57, 0xBF,
+0x0D, 0x47, 0x4F, 0xBF,
+
+0x88, 0x80, 0x58, 0xE9,
+0x1B, 0x29, 0x1B, 0xDF,
+
+0x30, 0x1D, 0x6F, 0x8F,
+0x3A, 0x30, 0x4F, 0xE9,
+
+0x1C, 0x30, 0x26, 0xDF,
+0x09, 0xE3,
+0x3B, 0x05,
+
+0x3E, 0x50, 0x56, 0x9F,
+0x3B, 0x3F, 0x4F, 0xE9,
+
+0x1E, 0x8F, 0x51, 0x9F,
+0x00, 0xE0,
+0xAC, 0x20,
+
+0x2D, 0x44, 0x4C, 0xB4,
+0x2C, 0x1C, 0xC0, 0xAF,
+
+0x25, 0x44, 0x54, 0xB4,
+0x00, 0xE0,
+0xC8, 0x30,
+
+0x30, 0x46, 0x30, 0xAF,
+0x1B, 0x1B, 0x48, 0xAF,
+
+0x00, 0xE0,
+0x25, 0x20,
+0x38, 0x2C, 0x4F, 0xE9,
+
+0x86, 0x80, 0x57, 0xE9,
+0x38, 0x1D, 0x6F, 0x8F,
+
+0x28, 0x74,
+0x00, 0xE0,
+0x0D, 0x44, 0x4C, 0xB0,
+
+0x05, 0x44, 0x54, 0xB0,
+0x2D, 0x20,
+0x9B, 0x10,
+
+0x82, 0x3E, 0x57, 0xE9,
+0x32, 0xF0, 0x1B, 0xCD,
+
+0x1E, 0xBD, 0x59, 0x9F,
+0x83, 0x1E, 0x57, 0xE9,
+
+0x38, 0x47, 0x38, 0xAF,
+0x34, 0x20,
+0x2A, 0x30,
+
+0x00, 0xE0,
+0x0D, 0x20,
+0x32, 0x20,
+0x05, 0x20,
+
+0x87, 0x80, 0x57, 0xE9,
+0x1F, 0x54, 0x57, 0x9F,
+
+0x17, 0x42, 0x56, 0x9F,
+0x00, 0xE0,
+0x3B, 0x6A,
+
+0x3F, 0x8F, 0x51, 0x9F,
+0x37, 0x1E, 0x4F, 0xE9,
+
+0x37, 0x32, 0x2A, 0xAF,
+0x00, 0xE0,
+0x32, 0x00,
+
+0x00, 0x80, 0x00, 0xE8,
+0x27, 0xC0, 0x44, 0xC0,
+
+0x36, 0x1F, 0x4F, 0xE9,
+0x1F, 0x1F, 0x26, 0xDF,
+
+0x37, 0x1B, 0x37, 0xBF,
+0x17, 0x26, 0x17, 0xDF,
+
+0x3E, 0x17, 0x4F, 0xE9,
+0x3F, 0x3F, 0x4F, 0xE9,
+
+0x34, 0x1F, 0x34, 0xAF,
+0x2B, 0x05,
+0xA7, 0x20,
+
+0x33, 0x2B, 0x37, 0xDF,
+0x27, 0x17, 0xC0, 0xAF,
+
+0x34, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2D, 0x21, 0x1A, 0xB0,
+0x25, 0x21, 0x31, 0xB0,
+
+0x0D, 0x21, 0x1A, 0xB2,
+0x05, 0x21, 0x31, 0xB2,
+
+0x03, 0x80, 0x2A, 0xEA,
+0x17, 0xC1, 0x2B, 0xBD,
+
+0x2D, 0x20,
+0x25, 0x20,
+0x05, 0x20,
+0x0D, 0x20,
+
+0xB3, 0x68,
+0x97, 0x25,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0xC0, 0x33, 0xAF,
+0x2F, 0xC0, 0x21, 0xC0,
+
+0x16, 0x42, 0x56, 0x9F,
+0x3C, 0x27, 0x4F, 0xE9,
+
+0x1E, 0x62, 0x57, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x21, 0x31, 0xB4,
+0x2D, 0x21, 0x1A, 0xB4,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x33, 0x05,
+0x00, 0xE0,
+0x28, 0x19, 0x60, 0xEC,
+
+0x0D, 0x21, 0x1A, 0xB6,
+0x05, 0x21, 0x31, 0xB6,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0xE0,
+0x2F, 0x20,
+
+0x23, 0x3B, 0x33, 0xAD,
+0x1E, 0x26, 0x1E, 0xDF,
+
+0xA7, 0x1E, 0x4F, 0xE9,
+0x17, 0x26, 0x16, 0xDF,
+
+0x2D, 0x20,
+0x00, 0xE0,
+0xA8, 0x3F, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x1E, 0xAF,
+0x25, 0x20,
+0x00, 0xE0,
+
+0xA4, 0x16, 0x4F, 0xE9,
+0x0F, 0xC0, 0x21, 0xC2,
+
+0xA6, 0x80, 0x4F, 0xE9,
+0x1F, 0x62, 0x57, 0x9F,
+
+0x0D, 0x20,
+0x05, 0x20,
+0x2F, 0xC0, 0x21, 0xC6,
+
+0x3F, 0x2F, 0x5D, 0x9F,
+0x00, 0xE0,
+0x0F, 0x20,
+
+0x17, 0x50, 0x56, 0x9F,
+0xA5, 0x37, 0x4F, 0xE9,
+
+0x06, 0xC0, 0x21, 0xC4,
+0x0F, 0x17, 0x0F, 0xAF,
+
+0x37, 0x0F, 0x5C, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2F, 0x20,
+0x00, 0xE0,
+0xA3, 0x80, 0x4F, 0xE9,
+
+0x06, 0x20,
+0x00, 0xE0,
+0x1F, 0x26, 0x1F, 0xDF,
+
+0x17, 0x26, 0x17, 0xDF,
+0x35, 0x17, 0x4F, 0xE9,
+
+0xA1, 0x1F, 0x4F, 0xE9,
+0xA2, 0x3F, 0x4F, 0xE9,
+
+0x06, 0x06, 0x1F, 0xAF,
+0x39, 0x37, 0x4F, 0xE9,
+
+0x2F, 0x2F, 0x17, 0xAF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xA0, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x31, 0x80, 0x4F, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x57, 0x39, 0x20, 0xE9,
+
+0x16, 0x28, 0x20, 0xE9,
+0x1D, 0x3B, 0x20, 0xE9,
+
+0x1E, 0x2B, 0x20, 0xE9,
+0x2B, 0x32, 0x20, 0xE9,
+
+0x1C, 0x23, 0x20, 0xE9,
+0x57, 0x36, 0x20, 0xE9,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x40, 0x40, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x90, 0xE2,
+0x00, 0xE0,
+
+0x68, 0xFF, 0x20, 0xEA,
+0x19, 0xC8, 0xC1, 0xCD,
+
+0x1F, 0xD7, 0x18, 0xBD,
+0x3F, 0xD7, 0x22, 0xBD,
+
+0x9F, 0x41, 0x49, 0xBD,
+0x00, 0x80, 0x00, 0xE8,
+
+0x25, 0x41, 0x49, 0xBD,
+0x2D, 0x41, 0x51, 0xBD,
+
+0x0D, 0x80, 0x07, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x35, 0x40, 0x48, 0xBD,
+0x3D, 0x40, 0x50, 0xBD,
+
+0x00, 0x80, 0x00, 0xE8,
+0x25, 0x30,
+0x2D, 0x30,
+
+0x35, 0x30,
+0xB5, 0x30,
+0xBD, 0x30,
+0x3D, 0x30,
+
+0x9C, 0xA7, 0x5B, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x67, 0xFF, 0x0A, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC9, 0x41, 0xC8, 0xEC,
+0x42, 0xE1,
+0x00, 0xE0,
+
+0x65, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0xC8, 0x40, 0xC0, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x62, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g400_t2gz[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x78, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x69, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x25, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x9F, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xBE, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x7D, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gza[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x7C, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x6D, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x29, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x74, 0xC6,
+0x3D, 0xCF, 0x74, 0xC2,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x0F, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB4,
+0x02, 0x44, 0x64, 0xB4,
+
+0x2A, 0x44, 0x54, 0xB6,
+0x1A, 0x44, 0x64, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x9B, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xBA, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x79, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzaf[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x81, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x72, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x37, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x2E, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x0F, 0xCF, 0x74, 0xC6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x0F, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB4,
+0x02, 0x44, 0x64, 0xB4,
+
+0x2A, 0x44, 0x54, 0xB6,
+0x1A, 0x44, 0x64, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x3D, 0xCF, 0x75, 0xC6,
+0x00, 0x80, 0x00, 0xE8,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x45, 0x55, 0xB6,
+0x02, 0x45, 0x65, 0xB6,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x3D, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x96, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xB5, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x74, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzf[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x7D, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x6E, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0F, 0xCF, 0x75, 0xC6,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x28, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x31, 0x0F, 0x20, 0xE9,
+
+0x0A, 0x44, 0x54, 0xB4,
+0x02, 0x44, 0x64, 0xB4,
+
+0x2A, 0x45, 0x55, 0xB6,
+0x1A, 0x45, 0x65, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x9A, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xBB, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x78, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzs[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x85, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x76, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x0F, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x31, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x0A, 0x45, 0x55, 0xB0,
+0x02, 0x45, 0x65, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB2,
+0x1A, 0x45, 0x65, 0xB2,
+
+0x0A, 0x45, 0x55, 0xB4,
+0x02, 0x45, 0x65, 0xB4,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x20,
+0x1A, 0x20,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA7, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x92, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xB2, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x70, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsa[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x8A, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x7B, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x0F, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x36, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x0A, 0x45, 0x55, 0xB0,
+0x02, 0x45, 0x65, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB2,
+0x1A, 0x45, 0x65, 0xB2,
+
+0x0A, 0x45, 0x55, 0xB4,
+0x02, 0x45, 0x65, 0xB4,
+
+0x0F, 0xCF, 0x74, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB6,
+0x1A, 0x44, 0x64, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x8D, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xAD, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x6B, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsaf[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x8E, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x7F, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x0F, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x3A, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x0A, 0x45, 0x55, 0xB0,
+0x02, 0x45, 0x65, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB2,
+0x1A, 0x45, 0x65, 0xB2,
+
+0x0A, 0x45, 0x55, 0xB4,
+0x02, 0x45, 0x65, 0xB4,
+
+0x0F, 0xCF, 0x74, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB6,
+0x1A, 0x44, 0x64, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x45, 0x55, 0xB6,
+0x02, 0x45, 0x65, 0xB6,
+
+0x3D, 0xCF, 0x75, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x31, 0x3D, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x89, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xA9, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x67, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsf[] = {
+
+0x00, 0x8A, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x0A, 0x40, 0x50, 0xBF,
+0x2A, 0x40, 0x60, 0xBF,
+
+0x32, 0x41, 0x51, 0xBF,
+0x3A, 0x41, 0x61, 0xBF,
+
+0xC3, 0x6B,
+0xD3, 0x6B,
+0x00, 0x8A, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x53, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x23, 0x9F,
+0x00, 0xE0,
+0x51, 0x04,
+
+0x90, 0xE2,
+0x61, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x51, 0x41, 0xE0, 0xEC,
+0x39, 0x67, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x63, 0xA0, 0xE8,
+
+0x61, 0x41, 0xE0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x8A, 0x80, 0x15, 0xEA,
+0x10, 0x04,
+0x20, 0x04,
+
+0x61, 0x51, 0xE0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x52, 0xBF,
+0x0F, 0x52, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x62, 0xBF,
+0x1E, 0x51, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x0E, 0x61, 0x60, 0xEA,
+
+0x32, 0x40, 0x50, 0xBD,
+0x22, 0x40, 0x60, 0xBD,
+
+0x12, 0x41, 0x51, 0xBD,
+0x3A, 0x41, 0x61, 0xBD,
+
+0xBF, 0x2F, 0x0E, 0xBD,
+0x97, 0xE2,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x35, 0x48, 0xB1, 0xE8,
+0x3D, 0x59, 0xB1, 0xE8,
+
+0x46, 0x31, 0x46, 0xBF,
+0x56, 0x31, 0x56, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x66, 0x31, 0x66, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x57, 0x39, 0x57, 0xBF,
+0x67, 0x39, 0x67, 0xBF,
+
+0x7B, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x35, 0x00,
+0x3D, 0x00,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0x8D, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x75, 0xF8, 0xEC,
+0x35, 0x20,
+0x3D, 0x20,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x53, 0x53, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x0E, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x48, 0x35, 0x48, 0xBF,
+0x58, 0x35, 0x58, 0xBF,
+
+0x68, 0x35, 0x68, 0xBF,
+0x49, 0x3D, 0x49, 0xBF,
+
+0x59, 0x3D, 0x59, 0xBF,
+0x69, 0x3D, 0x69, 0xBF,
+
+0x63, 0x63, 0x2D, 0xDF,
+0x4D, 0x7D, 0xF8, 0xEC,
+
+0x59, 0xE3,
+0x00, 0xE0,
+0xB8, 0x38, 0x33, 0xBF,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x18, 0x3A, 0x41, 0xE9,
+
+0x3F, 0x53, 0xA0, 0xE8,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x63, 0xA0, 0xE8,
+
+0x50, 0x70, 0xF8, 0xEC,
+0x2B, 0x50, 0x3C, 0xE9,
+
+0x1F, 0x0F, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x59, 0x78, 0xF8, 0xEC,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x46, 0x37, 0x46, 0xDF,
+0x56, 0x3F, 0x56, 0xDF,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x66, 0x3D, 0x66, 0xDF,
+
+0x1D, 0x32, 0x41, 0xE9,
+0x67, 0x3D, 0x67, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3F, 0x57, 0xDF,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x59, 0x3F, 0x59, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x69, 0x3D, 0x69, 0xDF,
+
+0x48, 0x37, 0x48, 0xDF,
+0x58, 0x3F, 0x58, 0xDF,
+
+0x68, 0x3D, 0x68, 0xDF,
+0x49, 0x37, 0x49, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x0F, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x54, 0xB0,
+0x02, 0x44, 0x64, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB2,
+0x1A, 0x44, 0x64, 0xB2,
+
+0x36, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0F, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x54, 0xB4,
+0x1A, 0x44, 0x64, 0xB4,
+
+0x0A, 0x45, 0x55, 0xB0,
+0x02, 0x45, 0x65, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB2,
+0x1A, 0x45, 0x65, 0xB2,
+
+0x0A, 0x45, 0x55, 0xB4,
+0x02, 0x45, 0x65, 0xB4,
+
+0x0F, 0xCF, 0x75, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x31, 0x0F, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x55, 0xB6,
+0x1A, 0x45, 0x65, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x56, 0xBF,
+0x1A, 0x46, 0x66, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x57, 0xBF,
+0x02, 0x47, 0x67, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x53, 0xBF,
+0x1A, 0x43, 0x63, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x48, 0x58, 0xBF,
+0x02, 0x48, 0x68, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x2A, 0x49, 0x59, 0xBF,
+0x1A, 0x49, 0x69, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x82, 0x30, 0x57, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x83, 0x38, 0x57, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x84, 0x31, 0x5E, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x85, 0x39, 0x5E, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x87, 0x77, 0x57, 0xE9,
+0x8B, 0x3E, 0xBF, 0xEA,
+
+0x80, 0x30, 0x57, 0xE9,
+0x81, 0x38, 0x57, 0xE9,
+
+0x82, 0x31, 0x57, 0xE9,
+0x86, 0x78, 0x57, 0xE9,
+
+0x83, 0x39, 0x57, 0xE9,
+0x87, 0x79, 0x57, 0xE9,
+
+0x30, 0x1F, 0x5F, 0xE9,
+0x8A, 0x34, 0x20, 0xE9,
+
+0x8B, 0x3C, 0x20, 0xE9,
+0x37, 0x50, 0x60, 0xBD,
+
+0x57, 0x0D, 0x20, 0xE9,
+0x35, 0x51, 0x61, 0xBD,
+
+0x2B, 0x50, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x0E, 0x77,
+
+0x24, 0x51, 0x20, 0xE9,
+0x8D, 0xFF, 0x20, 0xEA,
+
+0x16, 0x0E, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x0B, 0x46, 0xA0, 0xE8,
+0x1B, 0x56, 0xA0, 0xE8,
+
+0x2B, 0x66, 0xA0, 0xE8,
+0x0C, 0x47, 0xA0, 0xE8,
+
+0x1C, 0x57, 0xA0, 0xE8,
+0x2C, 0x67, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x57, 0x80, 0x57, 0xCF,
+
+0x66, 0x33, 0x66, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x67, 0x3B, 0x67, 0xCF,
+
+0x0B, 0x48, 0xA0, 0xE8,
+0x1B, 0x58, 0xA0, 0xE8,
+
+0x2B, 0x68, 0xA0, 0xE8,
+0x0C, 0x49, 0xA0, 0xE8,
+
+0x1C, 0x59, 0xA0, 0xE8,
+0x2C, 0x69, 0xA0, 0xE8,
+
+0x0B, 0x00,
+0x1B, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x0C, 0x00,
+0x1C, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x0B, 0x65,
+0x1B, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x0C, 0x65,
+0x1C, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x0B, 0x1B, 0x60, 0xEC,
+0x34, 0xD7, 0x34, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x0C, 0x1C, 0x60, 0xEC,
+
+0x3C, 0xD7, 0x3C, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x0B, 0x2B, 0xDE, 0xE8,
+0x1B, 0x80, 0xDE, 0xE8,
+
+0x34, 0x80, 0x34, 0xBD,
+0x3C, 0x80, 0x3C, 0xBD,
+
+0x33, 0xD7, 0x0B, 0xBD,
+0x3B, 0xD7, 0x1B, 0xBD,
+
+0x48, 0x80, 0x48, 0xCF,
+0x59, 0x80, 0x59, 0xCF,
+
+0x68, 0x33, 0x68, 0xCF,
+0x49, 0x3B, 0x49, 0xCF,
+
+0xAD, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x58, 0x33, 0x58, 0xCF,
+0x69, 0x3B, 0x69, 0xCF,
+
+0x6B, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgz[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x58, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x4A, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x1D, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xAF, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xD6, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x9D, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgza[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x5C, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x4E, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x27, 0xCF, 0x74, 0xC6,
+0x3D, 0xCF, 0x74, 0xC2,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x20, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x27, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB4,
+0x02, 0x44, 0x54, 0xB4,
+
+0x2A, 0x44, 0x4C, 0xB6,
+0x1A, 0x44, 0x54, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xAB, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xD3, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x99, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzaf[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x61, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x53, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x34, 0x37, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x26, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x27, 0xCF, 0x74, 0xC6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x27, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB4,
+0x02, 0x44, 0x54, 0xB4,
+
+0x2A, 0x44, 0x4C, 0xB6,
+0x1A, 0x44, 0x54, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x3D, 0xCF, 0x75, 0xC6,
+0x00, 0x80, 0x00, 0xE8,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x45, 0x4D, 0xB6,
+0x02, 0x45, 0x55, 0xB6,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x3D, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xA6, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xCD, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x94, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzf[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x5D, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x4F, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x34, 0x80, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x27, 0xCF, 0x75, 0xC6,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x20, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x3D, 0xCF, 0x74, 0xC2,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x31, 0x27, 0x20, 0xE9,
+
+0x0A, 0x44, 0x4C, 0xB4,
+0x02, 0x44, 0x54, 0xB4,
+
+0x2A, 0x45, 0x4D, 0xB6,
+0x1A, 0x45, 0x55, 0xB6,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x38, 0x3D, 0x20, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xAA, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xD3, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x98, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzs[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x65, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x57, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x27, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x29, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x27, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x0A, 0x45, 0x4D, 0xB0,
+0x02, 0x45, 0x55, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB2,
+0x1A, 0x45, 0x55, 0xB2,
+
+0x0A, 0x45, 0x4D, 0xB4,
+0x02, 0x45, 0x55, 0xB4,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x20,
+0x02, 0x20,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA7, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0xA2, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xCA, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x90, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsa[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x6A, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x5C, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x27, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x2E, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x27, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x0A, 0x45, 0x4D, 0xB0,
+0x02, 0x45, 0x55, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB2,
+0x1A, 0x45, 0x55, 0xB2,
+
+0x0A, 0x45, 0x4D, 0xB4,
+0x02, 0x45, 0x55, 0xB4,
+
+0x27, 0xCF, 0x74, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB6,
+0x1A, 0x44, 0x54, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0x9D, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xC5, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x8B, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsaf[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x6E, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x60, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x27, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x32, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x27, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x0A, 0x45, 0x4D, 0xB0,
+0x02, 0x45, 0x55, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB2,
+0x1A, 0x45, 0x55, 0xB2,
+
+0x0A, 0x45, 0x4D, 0xB4,
+0x02, 0x45, 0x55, 0xB4,
+
+0x27, 0xCF, 0x74, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9C, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB6,
+0x1A, 0x44, 0x54, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x45, 0x4D, 0xB6,
+0x02, 0x45, 0x55, 0xB6,
+
+0x3D, 0xCF, 0x75, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x31, 0x3D, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x9D, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x9E, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x30, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x38, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0x99, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xC1, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x87, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsf[] = {
+
+0x00, 0x88, 0x98, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+0xFF, 0x80, 0xC0, 0xE9,
+0x00, 0x80, 0x00, 0xE8,
+
+0x22, 0x40, 0x48, 0xBF,
+0x2A, 0x40, 0x50, 0xBF,
+
+0x32, 0x41, 0x49, 0xBF,
+0x3A, 0x41, 0x51, 0xBF,
+
+0xC3, 0x6B,
+0xCB, 0x6B,
+0x00, 0x88, 0x98, 0xE9,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x96, 0xE2,
+0x41, 0x04,
+
+0x7B, 0x43, 0xA0, 0xE8,
+0x73, 0x4B, 0xA0, 0xE8,
+
+0xAD, 0xEE, 0x29, 0x9F,
+0x00, 0xE0,
+0x49, 0x04,
+
+0x90, 0xE2,
+0x51, 0x04,
+0x31, 0x46, 0xB1, 0xE8,
+
+0x49, 0x41, 0xC0, 0xEC,
+0x39, 0x57, 0xB1, 0xE8,
+
+0x00, 0x04,
+0x46, 0xE2,
+0x73, 0x53, 0xA0, 0xE8,
+
+0x51, 0x41, 0xC0, 0xEC,
+0x31, 0x00,
+0x39, 0x00,
+
+0x6A, 0x80, 0x15, 0xEA,
+0x08, 0x04,
+0x10, 0x04,
+
+0x51, 0x49, 0xC0, 0xEC,
+0x2F, 0x41, 0x60, 0xEA,
+
+0x31, 0x20,
+0x39, 0x20,
+0x1F, 0x42, 0xA0, 0xE8,
+
+0x2A, 0x42, 0x4A, 0xBF,
+0x27, 0x4A, 0xA0, 0xE8,
+
+0x1A, 0x42, 0x52, 0xBF,
+0x1E, 0x49, 0x60, 0xEA,
+
+0x73, 0x7B, 0xC8, 0xEC,
+0x26, 0x51, 0x60, 0xEA,
+
+0x32, 0x40, 0x48, 0xBD,
+0x22, 0x40, 0x50, 0xBD,
+
+0x12, 0x41, 0x49, 0xBD,
+0x3A, 0x41, 0x51, 0xBD,
+
+0xBF, 0x2F, 0x26, 0xBD,
+0x00, 0xE0,
+0x7B, 0x72,
+
+0x32, 0x20,
+0x22, 0x20,
+0x12, 0x20,
+0x3A, 0x20,
+
+0x46, 0x31, 0x46, 0xBF,
+0x4E, 0x31, 0x4E, 0xBF,
+
+0xB3, 0xE2, 0x2D, 0x9F,
+0x00, 0x80, 0x00, 0xE8,
+
+0x56, 0x31, 0x56, 0xBF,
+0x47, 0x39, 0x47, 0xBF,
+
+0x4F, 0x39, 0x4F, 0xBF,
+0x57, 0x39, 0x57, 0xBF,
+
+0x5C, 0x80, 0x07, 0xEA,
+0x24, 0x41, 0x20, 0xE9,
+
+0x42, 0x73, 0xF8, 0xEC,
+0x00, 0xE0,
+0x2D, 0x73,
+
+0x33, 0x72,
+0x0C, 0xE3,
+0xA5, 0x2F, 0x1E, 0xBD,
+
+0x43, 0x43, 0x2D, 0xDF,
+0x4B, 0x4B, 0x2D, 0xDF,
+
+0xAE, 0x1E, 0x26, 0xBD,
+0x58, 0xE3,
+0x33, 0x66,
+
+0x53, 0x53, 0x2D, 0xDF,
+0x00, 0x80, 0x00, 0xE8,
+
+0xB8, 0x38, 0x33, 0xBF,
+0x00, 0xE0,
+0x59, 0xE3,
+
+0x1E, 0x12, 0x41, 0xE9,
+0x1A, 0x22, 0x41, 0xE9,
+
+0x2B, 0x40, 0x3D, 0xE9,
+0x3F, 0x4B, 0xA0, 0xE8,
+
+0x2D, 0x73,
+0x30, 0x76,
+0x05, 0x80, 0x3D, 0xEA,
+
+0x37, 0x43, 0xA0, 0xE8,
+0x3D, 0x53, 0xA0, 0xE8,
+
+0x48, 0x70, 0xF8, 0xEC,
+0x2B, 0x48, 0x3C, 0xE9,
+
+0x1F, 0x27, 0xBC, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x00, 0x80, 0x00, 0xE8,
+0x00, 0x80, 0x00, 0xE8,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x15, 0xC0, 0x20, 0xE9,
+0x15, 0xC0, 0x20, 0xE9,
+
+0x18, 0x3A, 0x41, 0xE9,
+0x1D, 0x32, 0x41, 0xE9,
+
+0x2A, 0x40, 0x20, 0xE9,
+0x56, 0x3D, 0x56, 0xDF,
+
+0x46, 0x37, 0x46, 0xDF,
+0x4E, 0x3F, 0x4E, 0xDF,
+
+0x16, 0x30, 0x20, 0xE9,
+0x4F, 0x3F, 0x4F, 0xDF,
+
+0x47, 0x37, 0x47, 0xDF,
+0x57, 0x3D, 0x57, 0xDF,
+
+0x32, 0x32, 0x2D, 0xDF,
+0x22, 0x22, 0x2D, 0xDF,
+
+0x12, 0x12, 0x2D, 0xDF,
+0x3A, 0x3A, 0x2D, 0xDF,
+
+0x27, 0xCF, 0x74, 0xC2,
+0x37, 0xCF, 0x74, 0xC4,
+
+0x0A, 0x44, 0x4C, 0xB0,
+0x02, 0x44, 0x54, 0xB0,
+
+0x3D, 0xCF, 0x74, 0xC0,
+0x34, 0x37, 0x20, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x38, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3C, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB2,
+0x1A, 0x44, 0x54, 0xB2,
+
+0x2E, 0x80, 0x3A, 0xEA,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x27, 0xCF, 0x75, 0xC0,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x32, 0x31, 0x5F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x33, 0x39, 0x5F, 0xE9,
+
+0x3D, 0xCF, 0x75, 0xC2,
+0x37, 0xCF, 0x75, 0xC4,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA6, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA3, 0x3D, 0x20, 0xE9,
+
+0x2A, 0x44, 0x4C, 0xB4,
+0x1A, 0x44, 0x54, 0xB4,
+
+0x0A, 0x45, 0x4D, 0xB0,
+0x02, 0x45, 0x55, 0xB0,
+
+0x88, 0x73, 0x5E, 0xE9,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA0, 0x37, 0x20, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x3E, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x3F, 0x38, 0x4F, 0xE9,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x3A, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x3B, 0x39, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB2,
+0x1A, 0x45, 0x55, 0xB2,
+
+0x0A, 0x45, 0x4D, 0xB4,
+0x02, 0x45, 0x55, 0xB4,
+
+0x27, 0xCF, 0x75, 0xC6,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0xA7, 0x30, 0x4F, 0xE9,
+0x0A, 0x20,
+0x02, 0x20,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x31, 0x27, 0x20, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA8, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x45, 0x4D, 0xB6,
+0x1A, 0x45, 0x55, 0xB6,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x36, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x37, 0x39, 0x4F, 0xE9,
+
+0x00, 0x80, 0x00, 0xE8,
+0x2A, 0x20,
+0x1A, 0x20,
+
+0x2A, 0x46, 0x4E, 0xBF,
+0x1A, 0x46, 0x56, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA4, 0x31, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA5, 0x39, 0x4F, 0xE9,
+
+0x0A, 0x47, 0x4F, 0xBF,
+0x02, 0x47, 0x57, 0xBF,
+
+0x31, 0x53, 0x2F, 0x9F,
+0xA1, 0x30, 0x4F, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0xA2, 0x38, 0x4F, 0xE9,
+
+0x2A, 0x43, 0x4B, 0xBF,
+0x1A, 0x43, 0x53, 0xBF,
+
+0x30, 0x50, 0x2E, 0x9F,
+0x35, 0x31, 0x4F, 0xE9,
+
+0x38, 0x21, 0x2C, 0x9F,
+0x39, 0x39, 0x4F, 0xE9,
+
+0x31, 0x53, 0x2F, 0x9F,
+0x80, 0x31, 0x57, 0xE9,
+
+0x39, 0xE5, 0x2C, 0x9F,
+0x81, 0x39, 0x57, 0xE9,
+
+0x37, 0x48, 0x50, 0xBD,
+0x8A, 0x36, 0x20, 0xE9,
+
+0x86, 0x76, 0x57, 0xE9,
+0x8B, 0x3E, 0x20, 0xE9,
+
+0x82, 0x30, 0x57, 0xE9,
+0x87, 0x77, 0x57, 0xE9,
+
+0x83, 0x38, 0x57, 0xE9,
+0x35, 0x49, 0x51, 0xBD,
+
+0x84, 0x31, 0x5E, 0xE9,
+0x30, 0x1F, 0x5F, 0xE9,
+
+0x85, 0x39, 0x5E, 0xE9,
+0x57, 0x25, 0x20, 0xE9,
+
+0x2B, 0x48, 0x20, 0xE9,
+0x1D, 0x37, 0xE1, 0xEA,
+
+0x1E, 0x35, 0xE1, 0xEA,
+0x00, 0xE0,
+0x26, 0x77,
+
+0x24, 0x49, 0x20, 0xE9,
+0x9D, 0xFF, 0x20, 0xEA,
+
+0x16, 0x26, 0x20, 0xE9,
+0x57, 0x2E, 0xBF, 0xEA,
+
+0x1C, 0x46, 0xA0, 0xE8,
+0x23, 0x4E, 0xA0, 0xE8,
+
+0x2B, 0x56, 0xA0, 0xE8,
+0x1D, 0x47, 0xA0, 0xE8,
+
+0x24, 0x4F, 0xA0, 0xE8,
+0x2C, 0x57, 0xA0, 0xE8,
+
+0x1C, 0x00,
+0x23, 0x00,
+0x2B, 0x00,
+0x00, 0xE0,
+
+0x1D, 0x00,
+0x24, 0x00,
+0x2C, 0x00,
+0x00, 0xE0,
+
+0x1C, 0x65,
+0x23, 0x65,
+0x2B, 0x65,
+0x00, 0xE0,
+
+0x1D, 0x65,
+0x24, 0x65,
+0x2C, 0x65,
+0x00, 0xE0,
+
+0x1C, 0x23, 0x60, 0xEC,
+0x36, 0xD7, 0x36, 0xAD,
+
+0x2B, 0x80, 0x60, 0xEC,
+0x1D, 0x24, 0x60, 0xEC,
+
+0x3E, 0xD7, 0x3E, 0xAD,
+0x2C, 0x80, 0x60, 0xEC,
+
+0x1C, 0x2B, 0xDE, 0xE8,
+0x23, 0x80, 0xDE, 0xE8,
+
+0x36, 0x80, 0x36, 0xBD,
+0x3E, 0x80, 0x3E, 0xBD,
+
+0x33, 0xD7, 0x1C, 0xBD,
+0x3B, 0xD7, 0x23, 0xBD,
+
+0x46, 0x80, 0x46, 0xCF,
+0x4F, 0x80, 0x4F, 0xCF,
+
+0x56, 0x33, 0x56, 0xCF,
+0x47, 0x3B, 0x47, 0xCF,
+
+0xC5, 0xFF, 0x20, 0xEA,
+0x00, 0x80, 0x00, 0xE8,
+
+0x4E, 0x33, 0x4E, 0xCF,
+0x57, 0x3B, 0x57, 0xCF,
+
+0x8B, 0xFF, 0x20, 0xEA,
+0x57, 0xC0, 0xBF, 0xEA,
+
+0x00, 0x80, 0xA0, 0xE9,
+0x00, 0x00, 0xD8, 0xEC,
+
+};
diff -urN linux-2.4.8-pre6/drivers/char/drm/mga_warp.c linux/drivers/char/drm/mga_warp.c
--- linux-2.4.8-pre6/drivers/char/drm/mga_warp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/mga_warp.c	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,210 @@
+/* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*-
+ * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#define __NO_VERSION__
+#include "mga.h"
+#include "drmP.h"
+#include "mga_drv.h"
+#include "mga_ucode.h"
+
+
+#define MGA_WARP_CODE_ALIGN		256		/* in bytes */
+
+#define WARP_UCODE_SIZE( which )					\
+	((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
+
+#define WARP_UCODE_INSTALL( which, where )				\
+do {									\
+	DRM_DEBUG( " pcbase = 0x%08lx  vcbase = %p\n", pcbase, vcbase );\
+	dev_priv->warp_pipe_phys[where] = pcbase;			\
+	memcpy( vcbase, which, sizeof(which) );				\
+	pcbase += WARP_UCODE_SIZE( which );				\
+	vcbase += WARP_UCODE_SIZE( which );				\
+} while (0)
+
+
+static unsigned int mga_warp_g400_microcode_size( drm_mga_private_t *dev_priv )
+{
+	unsigned int size;
+
+	size = ( WARP_UCODE_SIZE( warp_g400_tgz ) +
+		 WARP_UCODE_SIZE( warp_g400_tgza ) +
+		 WARP_UCODE_SIZE( warp_g400_tgzaf ) +
+		 WARP_UCODE_SIZE( warp_g400_tgzf ) +
+		 WARP_UCODE_SIZE( warp_g400_tgzs ) +
+		 WARP_UCODE_SIZE( warp_g400_tgzsa ) +
+		 WARP_UCODE_SIZE( warp_g400_tgzsaf ) +
+		 WARP_UCODE_SIZE( warp_g400_tgzsf ) +
+		 WARP_UCODE_SIZE( warp_g400_t2gz ) +
+		 WARP_UCODE_SIZE( warp_g400_t2gza ) +
+		 WARP_UCODE_SIZE( warp_g400_t2gzaf ) +
+		 WARP_UCODE_SIZE( warp_g400_t2gzf ) +
+		 WARP_UCODE_SIZE( warp_g400_t2gzs ) +
+		 WARP_UCODE_SIZE( warp_g400_t2gzsa ) +
+		 WARP_UCODE_SIZE( warp_g400_t2gzsaf ) +
+		 WARP_UCODE_SIZE( warp_g400_t2gzsf ) );
+
+	size = PAGE_ALIGN( size );
+
+	DRM_DEBUG( "G400 ucode size = %d bytes\n", size );
+	return size;
+}
+
+static unsigned int mga_warp_g200_microcode_size( drm_mga_private_t *dev_priv )
+{
+	unsigned int size;
+
+	size = ( WARP_UCODE_SIZE( warp_g200_tgz ) +
+		 WARP_UCODE_SIZE( warp_g200_tgza ) +
+		 WARP_UCODE_SIZE( warp_g200_tgzaf ) +
+		 WARP_UCODE_SIZE( warp_g200_tgzf ) +
+		 WARP_UCODE_SIZE( warp_g200_tgzs ) +
+		 WARP_UCODE_SIZE( warp_g200_tgzsa ) +
+		 WARP_UCODE_SIZE( warp_g200_tgzsaf ) +
+		 WARP_UCODE_SIZE( warp_g200_tgzsf ) );
+
+	size = PAGE_ALIGN( size );
+
+	DRM_DEBUG( "G200 ucode size = %d bytes\n", size );
+	return size;
+}
+
+static int mga_warp_install_g400_microcode( drm_mga_private_t *dev_priv )
+{
+	unsigned char *vcbase = dev_priv->warp->handle;
+	unsigned long pcbase = dev_priv->warp->offset;
+	unsigned int size;
+
+	size = mga_warp_g400_microcode_size( dev_priv );
+	if ( size > dev_priv->warp->size ) {
+		DRM_ERROR( "microcode too large! (%u > %lu)\n",
+			   size, dev_priv->warp->size );
+		return -ENOMEM;
+	}
+
+	memset( dev_priv->warp_pipe_phys, 0,
+		sizeof(dev_priv->warp_pipe_phys) );
+
+	WARP_UCODE_INSTALL( warp_g400_tgz,	MGA_WARP_TGZ );
+	WARP_UCODE_INSTALL( warp_g400_tgzf,	MGA_WARP_TGZF );
+	WARP_UCODE_INSTALL( warp_g400_tgza,	MGA_WARP_TGZA );
+	WARP_UCODE_INSTALL( warp_g400_tgzaf,	MGA_WARP_TGZAF );
+	WARP_UCODE_INSTALL( warp_g400_tgzs,	MGA_WARP_TGZS );
+	WARP_UCODE_INSTALL( warp_g400_tgzsf,	MGA_WARP_TGZSF );
+	WARP_UCODE_INSTALL( warp_g400_tgzsa,	MGA_WARP_TGZSA );
+	WARP_UCODE_INSTALL( warp_g400_tgzsaf,	MGA_WARP_TGZSAF );
+
+	WARP_UCODE_INSTALL( warp_g400_t2gz,	MGA_WARP_T2GZ );
+	WARP_UCODE_INSTALL( warp_g400_t2gzf,	MGA_WARP_T2GZF );
+	WARP_UCODE_INSTALL( warp_g400_t2gza,	MGA_WARP_T2GZA );
+	WARP_UCODE_INSTALL( warp_g400_t2gzaf,	MGA_WARP_T2GZAF );
+	WARP_UCODE_INSTALL( warp_g400_t2gzs,	MGA_WARP_T2GZS );
+	WARP_UCODE_INSTALL( warp_g400_t2gzsf,	MGA_WARP_T2GZSF );
+	WARP_UCODE_INSTALL( warp_g400_t2gzsa,	MGA_WARP_T2GZSA );
+	WARP_UCODE_INSTALL( warp_g400_t2gzsaf,	MGA_WARP_T2GZSAF );
+
+	return 0;
+}
+
+static int mga_warp_install_g200_microcode( drm_mga_private_t *dev_priv )
+{
+	unsigned char *vcbase = dev_priv->warp->handle;
+	unsigned long pcbase = dev_priv->warp->offset;
+	unsigned int size;
+
+	size = mga_warp_g200_microcode_size( dev_priv );
+	if ( size > dev_priv->warp->size ) {
+		DRM_ERROR( "microcode too large! (%u > %lu)\n",
+			   size, dev_priv->warp->size );
+		return -ENOMEM;
+	}
+
+	memset( dev_priv->warp_pipe_phys, 0,
+		sizeof(dev_priv->warp_pipe_phys) );
+
+	WARP_UCODE_INSTALL( warp_g200_tgz,	MGA_WARP_TGZ );
+	WARP_UCODE_INSTALL( warp_g200_tgzf,	MGA_WARP_TGZF );
+	WARP_UCODE_INSTALL( warp_g200_tgza,	MGA_WARP_TGZA );
+	WARP_UCODE_INSTALL( warp_g200_tgzaf,	MGA_WARP_TGZAF );
+	WARP_UCODE_INSTALL( warp_g200_tgzs,	MGA_WARP_TGZS );
+	WARP_UCODE_INSTALL( warp_g200_tgzsf,	MGA_WARP_TGZSF );
+	WARP_UCODE_INSTALL( warp_g200_tgzsa,	MGA_WARP_TGZSA );
+	WARP_UCODE_INSTALL( warp_g200_tgzsaf,	MGA_WARP_TGZSAF );
+
+	return 0;
+}
+
+int mga_warp_install_microcode(	drm_mga_private_t *dev_priv )
+{
+	switch ( dev_priv->chipset ) {
+	case MGA_CARD_TYPE_G400:
+		return mga_warp_install_g400_microcode( dev_priv );
+	case MGA_CARD_TYPE_G200:
+		return mga_warp_install_g200_microcode( dev_priv );
+	default:
+		return -EINVAL;
+	}
+}
+
+#define WMISC_EXPECTED		(MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
+
+int mga_warp_init( drm_mga_private_t *dev_priv )
+{
+	u32 wmisc;
+
+	/* FIXME: Get rid of these damned magic numbers...
+	 */
+	switch ( dev_priv->chipset ) {
+	case MGA_CARD_TYPE_G400:
+		MGA_WRITE( MGA_WIADDR2, MGA_WMODE_SUSPEND );
+		MGA_WRITE( MGA_WGETMSB, 0x00000E00 );
+		MGA_WRITE( MGA_WVRTXSZ, 0x00001807 );
+		MGA_WRITE( MGA_WACCEPTSEQ, 0x18000000 );
+		break;
+	case MGA_CARD_TYPE_G200:
+		MGA_WRITE( MGA_WIADDR, MGA_WMODE_SUSPEND );
+		MGA_WRITE( MGA_WGETMSB, 0x1606 );
+		MGA_WRITE( MGA_WVRTXSZ, 7 );
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	MGA_WRITE( MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
+			       MGA_WMASTER_ENABLE |
+			       MGA_WCACHEFLUSH_ENABLE) );
+	wmisc = MGA_READ( MGA_WMISC );
+	if ( wmisc != WMISC_EXPECTED ) {
+		DRM_ERROR( "WARP engine config failed! 0x%x != 0x%x\n",
+			   wmisc, WMISC_EXPECTED );
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff -urN linux-2.4.8-pre6/drivers/char/drm/proc.c linux/drivers/char/drm/proc.c
--- linux-2.4.8-pre6/drivers/char/drm/proc.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/char/drm/proc.c	Wed Dec 31 16:00:00 1969
@@ -1,578 +0,0 @@
-/* proc.c -- /proc support for DRM -*- linux-c -*-
- * Created: Mon Jan 11 09:48:47 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>
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-
-static struct proc_dir_entry *drm_root	   = NULL;
-static struct proc_dir_entry *drm_dev_root = NULL;
-static char		     drm_slot_name[64];
-
-static int	   drm_name_info(char *buf, char **start, off_t offset,
-				 int len, int *eof, void *data);
-static int	   drm_vm_info(char *buf, char **start, off_t offset,
-			       int len, int *eof, void *data);
-static int	   drm_clients_info(char *buf, char **start, off_t offset,
-				    int len, int *eof, void *data);
-static int	   drm_queues_info(char *buf, char **start, off_t offset,
-				   int len, int *eof, void *data);
-static int	   drm_bufs_info(char *buf, char **start, off_t offset,
-				 int len, int *eof, void *data);
-#if DRM_DEBUG_CODE
-static int	   drm_vma_info(char *buf, char **start, off_t offset,
-				int len, int *eof, void *data);
-#endif
-#if DRM_DMA_HISTOGRAM
-static int	   drm_histo_info(char *buf, char **start, off_t offset,
-				  int len, int *eof, void *data);
-#endif
-
-struct drm_proc_list {
-	const char *name;
-	int	   (*f)(char *, char **, off_t, int, int *, void *);
-} drm_proc_list[] = {
-	{ "name",    drm_name_info    },
-	{ "mem",     drm_mem_info     },
-	{ "vm",	     drm_vm_info      },
-	{ "clients", drm_clients_info },
-	{ "queues",  drm_queues_info  },
-	{ "bufs",    drm_bufs_info    },
-#if DRM_DEBUG_CODE
-	{ "vma",     drm_vma_info     },
-#endif
-#if DRM_DMA_HISTOGRAM
-	{ "histo",   drm_histo_info   },
-#endif
-};
-#define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
-
-int drm_proc_init(drm_device_t *dev)
-{
-	struct proc_dir_entry *ent;
-	int		      i, j;
-
-	drm_root = create_proc_entry("dri", S_IFDIR, NULL);
-	if (!drm_root) {
-		DRM_ERROR("Cannot create /proc/dri\n");
-		return -1;
-	}
-
-				/* Instead of doing this search, we should
-				   add some global support for /proc/dri. */
-	for (i = 0; i < 8; i++) {
-		sprintf(drm_slot_name, "dri/%d", i);
-		drm_dev_root = create_proc_entry(drm_slot_name, S_IFDIR, NULL);
-		if (!drm_dev_root) {
-			DRM_ERROR("Cannot create /proc/%s\n", drm_slot_name);
-			remove_proc_entry("dri", NULL);
-			break;
-		}
-		if (drm_dev_root->nlink == 2) break;
-		drm_dev_root = NULL;
-	}
-	if (!drm_dev_root) {
-		DRM_ERROR("Cannot find slot in /proc/dri\n");
-		return -1;
-	}
-
-	for (i = 0; i < DRM_PROC_ENTRIES; i++) {
-		ent = create_proc_entry(drm_proc_list[i].name,
-					S_IFREG|S_IRUGO, drm_dev_root);
-		if (!ent) {
-			DRM_ERROR("Cannot create /proc/%s/%s\n",
-				  drm_slot_name, drm_proc_list[i].name);
-			for (j = 0; j < i; j++)
-				remove_proc_entry(drm_proc_list[i].name,
-						  drm_dev_root);
-			remove_proc_entry(drm_slot_name, NULL);
-			remove_proc_entry("dri", NULL);
-			return -1;
-		}
-		ent->read_proc = drm_proc_list[i].f;
-		ent->data      = dev;
-	}
-
-	return 0;
-}
-
-
-int drm_proc_cleanup(void)
-{
-	int i;
-	
-	if (drm_root) {
-		if (drm_dev_root) {
-			for (i = 0; i < DRM_PROC_ENTRIES; i++) {
-				remove_proc_entry(drm_proc_list[i].name,
-						  drm_dev_root);
-			}
-			remove_proc_entry(drm_slot_name, NULL);
-		}
-		remove_proc_entry("dri", NULL);
-		remove_proc_entry(DRM_NAME, NULL);
-	}
-	drm_root = drm_dev_root = NULL;
-	return 0;
-}
-
-static int drm_name_info(char *buf, char **start, off_t offset, int len,
-			 int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-
-	if (offset > 0) return 0; /* no partial requests */
-	len  = 0;
-	*eof = 1;
-
-	if (dev->unique) {
-		DRM_PROC_PRINT("%s 0x%x %s\n",
-			       dev->name, dev->device, dev->unique);
-	} else {
-		DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device);
-	}
-	return len;
-}
-
-static int _drm_vm_info(char *buf, char **start, off_t offset, int len,
-			int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-	drm_map_t    *map;
-				/* Hardcoded from _DRM_FRAME_BUFFER,
-                                   _DRM_REGISTERS, _DRM_SHM, and
-                                   _DRM_AGP. */
-	const char   *types[] = { "FB", "REG", "SHM", "AGP" };
-	const char   *type;
-	int	     i;
-
-	if (offset > 0) return 0; /* no partial requests */
-	len  = 0;
-	*eof = 1;
-	DRM_PROC_PRINT("slot	 offset	      size type flags	 "
-		       "address mtrr\n\n");
-	for (i = 0; i < dev->map_count; i++) {
-		map = dev->maplist[i];
-		if (map->type < 0 || map->type > 3) type = "??";
-		else				    type = types[map->type];
-		DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
-			       i,
-			       map->offset,
-			       map->size,
-			       type,
-			       map->flags,
-			       (unsigned long)map->handle);
-		if (map->mtrr < 0) {
-			DRM_PROC_PRINT("none\n");
-		} else {
-			DRM_PROC_PRINT("%4d\n", map->mtrr);
-		}
-	}
-
-	return len;
-}
-
-static int drm_vm_info(char *buf, char **start, off_t offset, int len,
-		       int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-	int	     ret;
-
-	down(&dev->struct_sem);
-	ret = _drm_vm_info(buf, start, offset, len, eof, data);
-	up(&dev->struct_sem);
-	return ret;
-}
-
-
-static int _drm_queues_info(char *buf, char **start, off_t offset, int len,
-			    int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-	int	     i;
-	drm_queue_t  *q;
-
-	if (offset > 0) return 0; /* no partial requests */
-	len  = 0;
-	*eof = 1;
-	DRM_PROC_PRINT("  ctx/flags   use   fin"
-		       "   blk/rw/rwf  wait    flushed	   queued"
-		       "      locks\n\n");
-	for (i = 0; i < dev->queue_count; i++) {
-		q = dev->queuelist[i];
-		atomic_inc(&q->use_count);
-		DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
-				   "%5d/0x%03x %5d %5d"
-				   " %5d/%c%c/%c%c%c %5Zd %10d %10d %10d\n",
-				   i,
-				   q->flags,
-				   atomic_read(&q->use_count),
-				   atomic_read(&q->finalization),
-				   atomic_read(&q->block_count),
-				   atomic_read(&q->block_read) ? 'r' : '-',
-				   atomic_read(&q->block_write) ? 'w' : '-',
-				   waitqueue_active(&q->read_queue) ? 'r':'-',
-				   waitqueue_active(&q->write_queue) ? 'w':'-',
-				   waitqueue_active(&q->flush_queue) ? 'f':'-',
-				   DRM_BUFCOUNT(&q->waitlist),
-				   atomic_read(&q->total_flushed),
-				   atomic_read(&q->total_queued),
-				   atomic_read(&q->total_locks));
-		atomic_dec(&q->use_count);
-	}
-	
-	return len;
-}
-
-static int drm_queues_info(char *buf, char **start, off_t offset, int len,
-			   int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-	int	     ret;
-
-	down(&dev->struct_sem);
-	ret = _drm_queues_info(buf, start, offset, len, eof, data);
-	up(&dev->struct_sem);
-	return ret;
-}
-
-/* drm_bufs_info is called whenever a process reads
-   /dev/drm/<dev>/bufs. */
-
-static int _drm_bufs_info(char *buf, char **start, off_t offset, int len,
-			  int *eof, void *data)
-{
-	drm_device_t	 *dev = (drm_device_t *)data;
-	drm_device_dma_t *dma = dev->dma;
-	int		 i;
-
-	if (!dma)	return 0;
-	if (offset > 0) return 0; /* no partial requests */
-	len  = 0;
-	*eof = 1;
-	DRM_PROC_PRINT(" o     size count  free	 segs pages    kB\n\n");
-	for (i = 0; i <= DRM_MAX_ORDER; i++) {
-		if (dma->bufs[i].buf_count)
-			DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
-				       i,
-				       dma->bufs[i].buf_size,
-				       dma->bufs[i].buf_count,
-				       atomic_read(&dma->bufs[i]
-						   .freelist.count),
-				       dma->bufs[i].seg_count,
-				       dma->bufs[i].seg_count
-				       *(1 << dma->bufs[i].page_order),
-				       (dma->bufs[i].seg_count
-					* (1 << dma->bufs[i].page_order))
-				       * PAGE_SIZE / 1024);
-	}
-	DRM_PROC_PRINT("\n");
-	for (i = 0; i < dma->buf_count; i++) {
-		if (i && !(i%32)) DRM_PROC_PRINT("\n");
-		DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
-	}
-	DRM_PROC_PRINT("\n");
-
-	return len;
-}
-
-static int drm_bufs_info(char *buf, char **start, off_t offset, int len,
-			 int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-	int	     ret;
-
-	down(&dev->struct_sem);
-	ret = _drm_bufs_info(buf, start, offset, len, eof, data);
-	up(&dev->struct_sem);
-	return ret;
-}
-
-
-static int _drm_clients_info(char *buf, char **start, off_t offset, int len,
-			     int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-	drm_file_t   *priv;
-
-	if (offset > 0) return 0; /* no partial requests */
-	len  = 0;
-	*eof = 1;
-	DRM_PROC_PRINT("a dev	pid    uid	magic	  ioctls\n\n");
-	for (priv = dev->file_first; priv; priv = priv->next) {
-		DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
-			       priv->authenticated ? 'y' : 'n',
-			       priv->minor,
-			       priv->pid,
-			       priv->uid,
-			       priv->magic,
-			       priv->ioctl_count);
-	}
-
-	return len;
-}
-
-static int drm_clients_info(char *buf, char **start, off_t offset, int len,
-			    int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-	int	     ret;
-
-	down(&dev->struct_sem);
-	ret = _drm_clients_info(buf, start, offset, len, eof, data);
-	up(&dev->struct_sem);
-	return ret;
-}
-
-#if DRM_DEBUG_CODE
-
-#define DRM_VMA_VERBOSE 0
-
-static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
-			 int *eof, void *data)
-{
-	drm_device_t	      *dev = (drm_device_t *)data;
-	drm_vma_entry_t	      *pt;
-	struct vm_area_struct *vma;
-#if DRM_VMA_VERBOSE
-	unsigned long	      i;
-	unsigned long	      address;
-	pgd_t		      *pgd;
-	pmd_t		      *pmd;
-	pte_t		      *pte;
-#endif
-#if defined(__i386__)
-	unsigned int	      pgprot;
-#endif
-
-	if (offset > 0) return 0; /* no partial requests */
-	len  = 0;
-	*eof = 1;
-	DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
-		       atomic_read(&dev->vma_count),
-		       high_memory, virt_to_phys(high_memory));
-	for (pt = dev->vmalist; pt; pt = pt->next) {
-		if (!(vma = pt->vma)) continue;
-		DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
-			       pt->pid,
-			       vma->vm_start,
-			       vma->vm_end,
-			       vma->vm_flags & VM_READ	   ? 'r' : '-',
-			       vma->vm_flags & VM_WRITE	   ? 'w' : '-',
-			       vma->vm_flags & VM_EXEC	   ? 'x' : '-',
-			       vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
-			       vma->vm_flags & VM_LOCKED   ? 'l' : '-',
-			       vma->vm_flags & VM_IO	   ? 'i' : '-',
-			       VM_OFFSET(vma));
-		
-#if defined(__i386__)
-		pgprot = pgprot_val(vma->vm_page_prot);
-		DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
-			       pgprot & _PAGE_PRESENT  ? 'p' : '-',
-			       pgprot & _PAGE_RW       ? 'w' : 'r',
-			       pgprot & _PAGE_USER     ? 'u' : 's',
-			       pgprot & _PAGE_PWT      ? 't' : 'b',
-			       pgprot & _PAGE_PCD      ? 'u' : 'c',
-			       pgprot & _PAGE_ACCESSED ? 'a' : '-',
-			       pgprot & _PAGE_DIRTY    ? 'd' : '-',
-			       pgprot & _PAGE_PSE      ? 'm' : 'k',
-			       pgprot & _PAGE_GLOBAL   ? 'g' : 'l' );
-#endif		
-		DRM_PROC_PRINT("\n");
-#if 0
-		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);
-			if (pte_present(*pte)) {
-				address = __pa(pte_page(*pte))
-					+ (i & (PAGE_SIZE-1));
-				DRM_PROC_PRINT("      0x%08lx -> 0x%08lx"
-					       " %c%c%c%c%c\n",
-					       i,
-					       address,
-					       pte_read(*pte)  ? 'r' : '-',
-					       pte_write(*pte) ? 'w' : '-',
-					       pte_exec(*pte)  ? 'x' : '-',
-					       pte_dirty(*pte) ? 'd' : '-',
-					       pte_young(*pte) ? 'a' : '-' );
-			} else {
-				DRM_PROC_PRINT("      0x%08lx\n", i);
-			}
-		}
-#endif
-	}
-	
-	return len;
-}
-
-static int drm_vma_info(char *buf, char **start, off_t offset, int len,
-			int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-	int	     ret;
-
-	down(&dev->struct_sem);
-	ret = _drm_vma_info(buf, start, offset, len, eof, data);
-	up(&dev->struct_sem);
-	return ret;
-}
-#endif
-
-
-#if DRM_DMA_HISTOGRAM
-static int _drm_histo_info(char *buf, char **start, off_t offset, int len,
-			   int *eof, void *data)
-{
-	drm_device_t	 *dev = (drm_device_t *)data;
-	drm_device_dma_t *dma = dev->dma;
-	int		 i;
-	unsigned long	 slot_value = DRM_DMA_HISTOGRAM_INITIAL;
-	unsigned long	 prev_value = 0;
-	drm_buf_t	 *buffer;
-
-	if (offset > 0) return 0; /* no partial requests */
-	len  = 0;
-	*eof = 1;
-
-	DRM_PROC_PRINT("general statistics:\n");
-	DRM_PROC_PRINT("total	 %10u\n", atomic_read(&dev->histo.total));
-	DRM_PROC_PRINT("open	 %10u\n", atomic_read(&dev->total_open));
-	DRM_PROC_PRINT("close	 %10u\n", atomic_read(&dev->total_close));
-	DRM_PROC_PRINT("ioctl	 %10u\n", atomic_read(&dev->total_ioctl));
-	DRM_PROC_PRINT("irq	 %10u\n", atomic_read(&dev->total_irq));
-	DRM_PROC_PRINT("ctx	 %10u\n", atomic_read(&dev->total_ctx));
-	
-	DRM_PROC_PRINT("\nlock statistics:\n");
-	DRM_PROC_PRINT("locks	 %10u\n", atomic_read(&dev->total_locks));
-	DRM_PROC_PRINT("unlocks	 %10u\n", atomic_read(&dev->total_unlocks));
-	DRM_PROC_PRINT("contends %10u\n", atomic_read(&dev->total_contends));
-	DRM_PROC_PRINT("sleeps	 %10u\n", atomic_read(&dev->total_sleeps));
-
-
-	if (dma) {
-		DRM_PROC_PRINT("\ndma statistics:\n");
-		DRM_PROC_PRINT("prio	 %10u\n",
-			       atomic_read(&dma->total_prio));
-		DRM_PROC_PRINT("bytes	 %10u\n",
-			       atomic_read(&dma->total_bytes));
-		DRM_PROC_PRINT("dmas	 %10u\n",
-			       atomic_read(&dma->total_dmas));
-		DRM_PROC_PRINT("missed:\n");
-		DRM_PROC_PRINT("  dma	 %10u\n",
-			       atomic_read(&dma->total_missed_dma));
-		DRM_PROC_PRINT("  lock	 %10u\n",
-			       atomic_read(&dma->total_missed_lock));
-		DRM_PROC_PRINT("  free	 %10u\n",
-			       atomic_read(&dma->total_missed_free));
-		DRM_PROC_PRINT("  sched	 %10u\n",
-			       atomic_read(&dma->total_missed_sched));
-		DRM_PROC_PRINT("tried	 %10u\n",
-			       atomic_read(&dma->total_tried));
-		DRM_PROC_PRINT("hit	 %10u\n",
-			       atomic_read(&dma->total_hit));
-		DRM_PROC_PRINT("lost	 %10u\n",
-			       atomic_read(&dma->total_lost));
-		
-		buffer = dma->next_buffer;
-		if (buffer) {
-			DRM_PROC_PRINT("next_buffer %7d\n", buffer->idx);
-		} else {
-			DRM_PROC_PRINT("next_buffer    none\n");
-		}
-		buffer = dma->this_buffer;
-		if (buffer) {
-			DRM_PROC_PRINT("this_buffer %7d\n", buffer->idx);
-		} else {
-			DRM_PROC_PRINT("this_buffer    none\n");
-		}
-	}
-	
-
-	DRM_PROC_PRINT("\nvalues:\n");
-	if (dev->lock.hw_lock) {
-		DRM_PROC_PRINT("lock	       0x%08x\n",
-			       dev->lock.hw_lock->lock);
-	} else {
-		DRM_PROC_PRINT("lock		     none\n");
-	}
-	DRM_PROC_PRINT("context_flag   0x%08lx\n", dev->context_flag);
-	DRM_PROC_PRINT("interrupt_flag 0x%08lx\n", dev->interrupt_flag);
-	DRM_PROC_PRINT("dma_flag       0x%08lx\n", dev->dma_flag);
-
-	DRM_PROC_PRINT("queue_count    %10d\n",	 dev->queue_count);
-	DRM_PROC_PRINT("last_context   %10d\n",	 dev->last_context);
-	DRM_PROC_PRINT("last_switch    %10lu\n", dev->last_switch);
-	DRM_PROC_PRINT("last_checked   %10d\n",	 dev->last_checked);
-		
-	
-	DRM_PROC_PRINT("\n		       q2d	  d2c	     c2f"
-		       "	q2c	   q2f	      dma	 sch"
-		       "	ctx	  lacq	     lhld\n\n");
-	for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) {
-		DRM_PROC_PRINT("%s %10lu %10u %10u %10u %10u %10u"
-			       " %10u %10u %10u %10u %10u\n",
-			       i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ",
-			       i == DRM_DMA_HISTOGRAM_SLOTS - 1
-			       ? prev_value : slot_value ,
-			       
-			       atomic_read(&dev->histo
-					   .queued_to_dispatched[i]),
-			       atomic_read(&dev->histo
-					   .dispatched_to_completed[i]),
-			       atomic_read(&dev->histo
-					   .completed_to_freed[i]),
-			       
-			       atomic_read(&dev->histo
-					   .queued_to_completed[i]),
-			       atomic_read(&dev->histo
-					   .queued_to_freed[i]),
-			       atomic_read(&dev->histo.dma[i]),
-			       atomic_read(&dev->histo.schedule[i]),
-			       atomic_read(&dev->histo.ctx[i]),
-			       atomic_read(&dev->histo.lacq[i]),
-			       atomic_read(&dev->histo.lhld[i]));
-		prev_value = slot_value;
-		slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value);
-	}
-	return len;
-}
-
-static int drm_histo_info(char *buf, char **start, off_t offset, int len,
-			  int *eof, void *data)
-{
-	drm_device_t *dev = (drm_device_t *)data;
-	int	     ret;
-
-	down(&dev->struct_sem);
-	ret = _drm_histo_info(buf, start, offset, len, eof, data);
-	up(&dev->struct_sem);
-	return ret;
-}
-#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/r128.h linux/drivers/char/drm/r128.h
--- linux-2.4.8-pre6/drivers/char/drm/r128.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/r128.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,81 @@
+/* r128.h -- ATI Rage 128 DRM template customization -*- linux-c -*-
+ * Created: Wed Feb 14 16:07:10 2001 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __R128_H__
+#define __R128_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) r128_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP		1
+#define __MUST_HAVE_AGP		0
+#define __HAVE_MTRR		1
+#define __HAVE_CTX_BITMAP	1
+#define __HAVE_SG		1
+#define __HAVE_PCI_DMA		1
+
+/* Driver customization:
+ */
+#define DRIVER_PRERELEASE() do {					\
+	if ( dev->dev_private ) {					\
+		drm_r128_private_t *dev_priv = dev->dev_private;	\
+		if ( dev_priv->page_flipping ) {			\
+			r128_do_cleanup_pageflip( dev );		\
+		}							\
+	}								\
+} while (0)
+
+#define DRIVER_PRETAKEDOWN() do {					\
+	if ( dev->dev_private ) r128_do_cleanup_cce( dev );		\
+} while (0)
+
+/* DMA customization:
+ */
+#define __HAVE_DMA		1
+
+#if 0
+/* GH: Remove this for now... */
+#define __HAVE_DMA_QUIESCENT	1
+#define DRIVER_DMA_QUIESCENT() do {					\
+	drm_r128_private_t *dev_priv = dev->dev_private;		\
+	return r128_do_cce_idle( dev_priv );				\
+} while (0)
+#endif
+
+/* Buffer customization:
+ */
+#define DRIVER_BUF_PRIV_T	drm_r128_buf_priv_t
+
+#define DRIVER_AGP_BUFFERS_MAP( dev )					\
+	((drm_r128_private_t *)((dev)->dev_private))->buffers
+
+#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/r128_bufs.c linux/drivers/char/drm/r128_bufs.c
--- linux-2.4.8-pre6/drivers/char/drm/r128_bufs.c	Mon Jul 16 15:13:32 2001
+++ linux/drivers/char/drm/r128_bufs.c	Wed Dec 31 16:00:00 1969
@@ -1,319 +0,0 @@
-/* r128_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
- * Created: Wed Apr 12 16:19:08 2000 by kevin@precisioninsight.com
- *
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Kevin E. Martin <martin@valinux.com>
- *          Rickard E. (Rik) Faith <faith@valinux.com>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include <linux/config.h>
-#include "drmP.h"
-#include "r128_drv.h"
-#include "linux/un.h"
-
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-int r128_addbufs_agp(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_device_dma_t *dma  = dev->dma;
-	drm_buf_desc_t    request;
-	drm_buf_entry_t  *entry;
-	drm_buf_t        *buf;
-	unsigned long     offset;
-	unsigned long     agp_offset;
-	int               count;
-	int               order;
-	int               size;
-	int               alignment;
-	int               page_order;
-	int               total;
-	int               byte_count;
-	int               i;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	count      = request.count;
-	order      = drm_order(request.size);
-	size       = 1 << order;
-
-	alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
-	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-	total      = PAGE_SIZE << page_order;
-
-	byte_count = 0;
-	agp_offset = dev->agp->base + request.agp_start;
-
-	DRM_DEBUG("count:      %d\n",  count);
-	DRM_DEBUG("order:      %d\n",  order);
-	DRM_DEBUG("size:       %d\n",  size);
-	DRM_DEBUG("agp_offset: %ld\n", agp_offset);
-	DRM_DEBUG("alignment:  %d\n",  alignment);
-	DRM_DEBUG("page_order: %d\n",  page_order);
-	DRM_DEBUG("total:      %d\n",  total);
-
-	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-	if (dev->queue_count) return -EBUSY; /* Not while in use */
-
-	spin_lock(&dev->count_lock);
-	if (dev->buf_use) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	atomic_inc(&dev->buf_alloc);
-	spin_unlock(&dev->count_lock);
-
-	down(&dev->struct_sem);
-	entry = &dma->bufs[order];
-	if (entry->buf_count) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM; /* May only call once for each order */
-	}
-
-	/* Might be a poor limit, but take that up with XFree86 
-	   if its a problem */
-	   
-	if(count < 0 || count > 4096)
-	{
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -EINVAL;
-	}
-		
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
-	if (!entry->buflist) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;
-	}
-	memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
-	entry->buf_size   = size;
-	entry->page_order = page_order;
-	offset            = 0;
-
-	for (offset = 0;
-	     entry->buf_count < count;
-	     offset += alignment, ++entry->buf_count) {
-		buf          = &entry->buflist[entry->buf_count];
-		buf->idx     = dma->buf_count + entry->buf_count;
-		buf->total   = alignment;
-		buf->order   = order;
-		buf->used    = 0;
-		buf->offset  = (dma->byte_count + offset);
-		buf->address = (void *)(agp_offset + offset);
-		buf->next    = NULL;
-		buf->waiting = 0;
-		buf->pending = 0;
-		init_waitqueue_head(&buf->dma_wait);
-		buf->pid     = 0;
-
-		buf->dev_priv_size = sizeof(drm_r128_buf_priv_t);
-		buf->dev_private   = drm_alloc(sizeof(drm_r128_buf_priv_t),
-					       DRM_MEM_BUFS);
-		memset(buf->dev_private, 0, buf->dev_priv_size);
-
-#if DRM_DMA_HISTOGRAM
-		buf->time_queued     = 0;
-		buf->time_dispatched = 0;
-		buf->time_completed  = 0;
-		buf->time_freed      = 0;
-#endif
-
-		byte_count += PAGE_SIZE << page_order;
-
-		DRM_DEBUG("buffer %d @ %p\n",
-			  entry->buf_count, buf->address);
-	}
-
-	DRM_DEBUG("byte_count: %d\n", byte_count);
-
-	dma->buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist),
-				   DRM_MEM_BUFS);
-	for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
-		dma->buflist[i] = &entry->buflist[i - dma->buf_count];
-
-	dma->buf_count  += entry->buf_count;
-	dma->byte_count += byte_count;
-
-	drm_freelist_create(&entry->freelist, entry->buf_count);
-	for (i = 0; i < entry->buf_count; i++) {
-		drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
-	}
-
-	up(&dev->struct_sem);
-
-	request.count = entry->buf_count;
-	request.size  = size;
-
-	if (copy_to_user((drm_buf_desc_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-
-	dma->flags = _DRM_DMA_USE_AGP;
-
-	atomic_dec(&dev->buf_alloc);
-	return 0;
-}
-#endif
-
-int r128_addbufs(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_r128_private_t	*dev_priv	= dev->dev_private;
-	drm_buf_desc_t		request;
-
-	if (!dev_priv || dev_priv->is_pci) return -EINVAL;
-
-	if (copy_from_user(&request,
-			   (drm_buf_desc_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	if (request.flags & _DRM_AGP_BUFFER)
-		return r128_addbufs_agp(inode, filp, cmd, arg);
-	else
-#endif
-		return -EINVAL;
-}
-
-int r128_mapbufs(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_r128_private_t	*dev_priv	= dev->dev_private;
-	drm_device_dma_t	*dma		= dev->dma;
-	int			 retcode	= 0;
-	const int		 zero		= 0;
-	unsigned long		 virtual;
-	unsigned long		 address;
-	drm_buf_map_t		 request;
-	int			 i;
-
-	if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL;
-
-	DRM_DEBUG("\n");
-
-	spin_lock(&dev->count_lock);
-	if (atomic_read(&dev->buf_alloc)) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	++dev->buf_use;		/* Can't allocate more after this call */
-	spin_unlock(&dev->count_lock);
-
-	if (copy_from_user(&request,
-			   (drm_buf_map_t *)arg,
-			   sizeof(request)))
-		return -EFAULT;
-
-	if (request.count >= dma->buf_count) {
-		if (dma->flags & _DRM_DMA_USE_AGP) {
-			drm_map_t *map;
-
-			map = dev_priv->buffers;
-			if (!map) {
-				retcode = -EINVAL;
-				goto done;
-			}
-
-			down_write(&current->mm->mmap_sem);
-			virtual = do_mmap(filp, 0, map->size,
-					  PROT_READ|PROT_WRITE,
-					  MAP_SHARED,
-					  (unsigned long)map->offset);
-			up_write(&current->mm->mmap_sem);
-		} else {
-			down_write(&current->mm->mmap_sem);
-			virtual = do_mmap(filp, 0, dma->byte_count,
-					  PROT_READ|PROT_WRITE, MAP_SHARED, 0);
-			up_write(&current->mm->mmap_sem);
-		}
-		if (virtual > -1024UL) {
-			/* Real error */
-			retcode = (signed long)virtual;
-			goto done;
-		}
-		request.virtual = (void *)virtual;
-
-		for (i = 0; i < dma->buf_count; i++) {
-			if (copy_to_user(&request.list[i].idx,
-					 &dma->buflist[i]->idx,
-					 sizeof(request.list[0].idx))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			if (copy_to_user(&request.list[i].total,
-					 &dma->buflist[i]->total,
-					 sizeof(request.list[0].total))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			if (copy_to_user(&request.list[i].used,
-					 &zero,
-					 sizeof(zero))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			address = virtual + dma->buflist[i]->offset;
-			if (copy_to_user(&request.list[i].address,
-					 &address,
-					 sizeof(address))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-		}
-	}
- done:
-	request.count = dma->buf_count;
-	DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
-
-	if (copy_to_user((drm_buf_map_t *)arg,
-			 &request,
-			 sizeof(request)))
-		return -EFAULT;
-
-	return retcode;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/r128_cce.c linux/drivers/char/drm/r128_cce.c
--- linux-2.4.8-pre6/drivers/char/drm/r128_cce.c	Thu Jan  4 13:03:20 2001
+++ linux/drivers/char/drm/r128_cce.c	Mon Dec  3 22:59:45 2001
@@ -25,20 +25,19 @@
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Gareth Hughes <gareth@valinux.com>
- *
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #define __NO_VERSION__
+#include "r128.h"
 #include "drmP.h"
 #include "r128_drv.h"
 
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/delay.h>
 
+#define R128_FIFO_DEBUG		0
 
-/* FIXME: Temporary CCE packet buffer */
-u32 r128_cce_buffer[(1 << 14)] __attribute__ ((aligned (32)));
 
 /* CCE microcode (from ATI) */
 static u32 r128_cce_microcode[] = {
@@ -86,26 +85,6 @@
 };
 
 
-#define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
-
-#define DO_REMAPFREE(_m)                                                    \
-	do {                                                                \
-		if ((_m)->handle && (_m)->size)                             \
-			drm_ioremapfree((_m)->handle, (_m)->size);          \
-	} while (0)
-
-#define DO_FIND_MAP(_m, _o)                                                 \
-	do {                                                                \
-		int _i;                                                     \
-		for (_i = 0; _i < dev->map_count; _i++) {                   \
-			if (dev->maplist[_i]->offset == _o) {               \
-				_m = dev->maplist[_i];                      \
-				break;                                      \
-			}                                                   \
-		}                                                           \
-	} while (0)
-
-
 int R128_READ_PLL(drm_device_t *dev, int addr)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -114,7 +93,7 @@
 	return R128_READ(R128_CLOCK_CNTL_DATA);
 }
 
-#if 0
+#if R128_FIFO_DEBUG
 static void r128_status( drm_r128_private_t *dev_priv )
 {
 	printk( "GUI_STAT           = 0x%08x\n",
@@ -152,7 +131,9 @@
 		udelay( 1 );
 	}
 
+#if R128_FIFO_DEBUG
 	DRM_ERROR( "%s failed!\n", __FUNCTION__ );
+#endif
 	return -EBUSY;
 }
 
@@ -166,16 +147,18 @@
 		udelay( 1 );
 	}
 
+#if R128_FIFO_DEBUG
 	DRM_ERROR( "%s failed!\n", __FUNCTION__ );
+#endif
 	return -EBUSY;
 }
 
-static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
+int r128_do_wait_for_idle( drm_r128_private_t *dev_priv )
 {
 	int i, ret;
 
 	ret = r128_do_wait_for_fifo( dev_priv, 64 );
-	if ( !ret ) return ret;
+	if ( ret < 0 ) return ret;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
 		if ( !(R128_READ( R128_GUI_STAT ) & R128_GUI_ACTIVE) ) {
@@ -185,7 +168,9 @@
 		udelay( 1 );
 	}
 
+#if R128_FIFO_DEBUG
 	DRM_ERROR( "%s failed!\n", __FUNCTION__ );
+#endif
 	return -EBUSY;
 }
 
@@ -199,6 +184,8 @@
 {
 	int i;
 
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
 	r128_do_wait_for_idle( dev_priv );
 
 	R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 );
@@ -224,12 +211,12 @@
 
 /* Wait for the CCE to go idle.
  */
-static int r128_do_cce_idle( drm_r128_private_t *dev_priv )
+int r128_do_cce_idle( drm_r128_private_t *dev_priv )
 {
 	int i;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-		if ( *dev_priv->ring.head == dev_priv->ring.tail ) {
+		if ( GET_RING_HEAD( &dev_priv->ring ) == dev_priv->ring.tail ) {
 			int pm4stat = R128_READ( R128_PM4_STAT );
 			if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >=
 			       dev_priv->cce_fifo_size ) &&
@@ -241,7 +228,7 @@
 		udelay( 1 );
 	}
 
-#if 0
+#if R128_FIFO_DEBUG
 	DRM_ERROR( "failed!\n" );
 	r128_status( dev_priv );
 #endif
@@ -263,19 +250,19 @@
 }
 
 /* Reset the Concurrent Command Engine.  This will not flush any pending
- * commangs, so you must wait for the CCE command stream to complete
+ * commands, so you must wait for the CCE command stream to complete
  * before calling this routine.
  */
 static void r128_do_cce_reset( drm_r128_private_t *dev_priv )
 {
 	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
 	R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
-	*dev_priv->ring.head = 0;
+	SET_RING_HEAD( &dev_priv->ring, 0 );
 	dev_priv->ring.tail = 0;
 }
 
 /* Stop the Concurrent Command Engine.  This will not flush any pending
- * commangs, so you must flush the command stream and wait for the CCE
+ * commands, so you must flush the command stream and wait for the CCE
  * to go idle before calling this routine.
  */
 static void r128_do_cce_stop( drm_r128_private_t *dev_priv )
@@ -327,25 +314,49 @@
 	return 0;
 }
 
-static void r128_cce_init_ring_buffer( drm_device_t *dev )
+static void r128_cce_init_ring_buffer( drm_device_t *dev,
+				       drm_r128_private_t *dev_priv )
 {
-	drm_r128_private_t *dev_priv = dev->dev_private;
 	u32 ring_start;
 	u32 tmp;
 
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
 	/* The manual (p. 2) says this address is in "VM space".  This
 	 * means it's an offset from the start of AGP space.
 	 */
-	ring_start = dev_priv->cce_ring->offset - dev->agp->base;
+#if __REALLY_HAVE_AGP
+	if ( !dev_priv->is_pci )
+		ring_start = dev_priv->cce_ring->offset - dev->agp->base;
+	else
+#endif
+		ring_start = dev_priv->cce_ring->offset - dev->sg->handle;
+
 	R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET );
 
 	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 );
 	R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 );
 
 	/* DL_RPTR_ADDR is a physical address in AGP space. */
-	*dev_priv->ring.head = 0;
-	R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
-		    dev_priv->ring_rptr->offset );
+	SET_RING_HEAD( &dev_priv->ring, 0 );
+
+	if ( !dev_priv->is_pci ) {
+		R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
+			    dev_priv->ring_rptr->offset );
+	} else {
+		drm_sg_mem_t *entry = dev->sg;
+		unsigned long tmp_ofs, page_ofs;
+
+		tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
+		page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+		R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
+			    virt_to_bus(entry->pagelist[page_ofs]->virtual));
+
+		DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
+			   virt_to_bus(entry->pagelist[page_ofs]->virtual),
+			   entry->handle + tmp_ofs );
+	}
 
 	/* Set watermark control */
 	R128_WRITE( R128_PM4_BUFFER_WM_CNTL,
@@ -365,37 +376,35 @@
 static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 {
 	drm_r128_private_t *dev_priv;
-        int i;
+	struct list_head *list;
+
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	dev_priv = drm_alloc( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
+	dev_priv = DRM(alloc)( sizeof(drm_r128_private_t), DRM_MEM_DRIVER );
 	if ( dev_priv == NULL )
 		return -ENOMEM;
-	dev->dev_private = (void *)dev_priv;
 
 	memset( dev_priv, 0, sizeof(drm_r128_private_t) );
 
 	dev_priv->is_pci = init->is_pci;
 
-	/* GH: We don't support PCI cards until PCI GART is implemented.
-	 * Fail here so we can remove all checks for PCI cards around
-	 * the CCE ring code.
-	 */
-	if ( dev_priv->is_pci ) {
-		drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
-		dev->dev_private = NULL;
+	if ( dev_priv->is_pci && !dev->sg ) {
+		DRM_ERROR( "PCI GART memory not allocated!\n" );
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce( dev );
 		return -EINVAL;
 	}
 
 	dev_priv->usec_timeout = init->usec_timeout;
 	if ( dev_priv->usec_timeout < 1 ||
 	     dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) {
-		drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
-		dev->dev_private = NULL;
+		DRM_DEBUG( "TIMEOUT problem!\n" );
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce( dev );
 		return -EINVAL;
 	}
 
 	dev_priv->cce_mode = init->cce_mode;
-	dev_priv->cce_secure = init->cce_secure;
 
 	/* GH: Simple idle check.
 	 */
@@ -409,8 +418,9 @@
 	     ( init->cce_mode != R128_PM4_128BM_64INDBM ) &&
 	     ( init->cce_mode != R128_PM4_64BM_128INDBM ) &&
 	     ( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) {
-		drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
-		dev->dev_private = NULL;
+		DRM_DEBUG( "Bad cce_mode!\n" );
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce( dev );
 		return -EINVAL;
 	}
 
@@ -435,13 +445,30 @@
 		break;
 	}
 
-	dev_priv->fb_bpp	= init->fb_bpp;
+	switch ( init->fb_bpp ) {
+	case 16:
+		dev_priv->color_fmt = R128_DATATYPE_RGB565;
+		break;
+	case 32:
+	default:
+		dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
+		break;
+	}
 	dev_priv->front_offset	= init->front_offset;
 	dev_priv->front_pitch	= init->front_pitch;
 	dev_priv->back_offset	= init->back_offset;
 	dev_priv->back_pitch	= init->back_pitch;
 
-	dev_priv->depth_bpp	= init->depth_bpp;
+	switch ( init->depth_bpp ) {
+	case 16:
+		dev_priv->depth_fmt = R128_DATATYPE_RGB565;
+		break;
+	case 24:
+	case 32:
+	default:
+		dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
+		break;
+	}
 	dev_priv->depth_offset	= init->depth_offset;
 	dev_priv->depth_pitch	= init->depth_pitch;
 	dev_priv->span_offset	= init->span_offset;
@@ -456,39 +483,99 @@
 	dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) |
 					 (dev_priv->span_offset >> 5));
 
-	/* FIXME: We want multiple shared areas, including one shared
-	 * only by the X Server and kernel module.
-	 */
-	for ( i = 0 ; i < dev->map_count ; i++ ) {
-		if ( dev->maplist[i]->type == _DRM_SHM ) {
-			dev_priv->sarea = dev->maplist[i];
-			break;
-		}
+	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;
+ 		}
+ 	}
+	if(!dev_priv->sarea) {
+		DRM_ERROR("could not find sarea!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce( dev );
+		return -EINVAL;
 	}
 
-	DO_FIND_MAP( dev_priv->fb, init->fb_offset );
-	DO_FIND_MAP( dev_priv->mmio, init->mmio_offset );
-	DO_FIND_MAP( dev_priv->cce_ring, init->ring_offset );
-	DO_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
-	DO_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+	if(!dev_priv->fb) {
+		DRM_ERROR("could not find framebuffer!\n");
+		dev->dev_private = (void *)dev_priv;
+		r128_do_cleanup_cce( dev );
+		return -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;
+	}
+	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;
+	}
+	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;
+	}
+	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;
+	}
 
 	if ( !dev_priv->is_pci ) {
-		DO_FIND_MAP( dev_priv->agp_textures,
-			     init->agp_textures_offset );
+		DRM_FIND_MAP( dev_priv->agp_textures,
+			      init->agp_textures_offset );
+		if(!dev_priv->agp_textures) {
+			DRM_ERROR("could not find agp texture region!\n");
+			dev->dev_private = (void *)dev_priv;
+			r128_do_cleanup_cce( dev );
+			return -EINVAL;
+		}
 	}
 
 	dev_priv->sarea_priv =
 		(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				     init->sarea_priv_offset);
 
-	DO_REMAP( dev_priv->cce_ring );
-	DO_REMAP( dev_priv->ring_rptr );
-	DO_REMAP( dev_priv->buffers );
-#if 0
 	if ( !dev_priv->is_pci ) {
-		DO_REMAP( dev_priv->agp_textures );
+		DRM_IOREMAP( dev_priv->cce_ring );
+		DRM_IOREMAP( dev_priv->ring_rptr );
+		DRM_IOREMAP( dev_priv->buffers );
+		if(!dev_priv->cce_ring->handle ||
+		   !dev_priv->ring_rptr->handle ||
+		   !dev_priv->buffers->handle) {
+			DRM_ERROR("Could not ioremap agp regions!\n");
+			dev->dev_private = (void *)dev_priv;
+			r128_do_cleanup_cce( dev );
+			return -ENOMEM;
+		}
+	} else {
+		dev_priv->cce_ring->handle =
+			(void *)dev_priv->cce_ring->offset;
+		dev_priv->ring_rptr->handle =
+			(void *)dev_priv->ring_rptr->offset;
+		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
 	}
+
+#if __REALLY_HAVE_AGP
+	if ( !dev_priv->is_pci )
+		dev_priv->cce_buffers_offset = dev->agp->base;
+	else
 #endif
+		dev_priv->cce_buffers_offset = dev->sg->handle;
 
 	dev_priv->ring.head = ((__volatile__ u32 *)
 			       dev_priv->ring_rptr->handle);
@@ -497,11 +584,13 @@
 	dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle
 			      + init->ring_size / sizeof(u32));
 	dev_priv->ring.size = init->ring_size;
-	dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
+	dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 );
 
 	dev_priv->ring.tail_mask =
 		(dev_priv->ring.size / sizeof(u32)) - 1;
 
+	dev_priv->ring.high_mark = 128;
+
 	dev_priv->sarea_priv->last_frame = 0;
 	R128_WRITE( R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame );
 
@@ -509,29 +598,41 @@
 	R128_WRITE( R128_LAST_DISPATCH_REG,
 		    dev_priv->sarea_priv->last_dispatch );
 
-	r128_cce_init_ring_buffer( dev );
+	if ( dev_priv->is_pci ) {
+		dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev );
+		if ( !dev_priv->phys_pci_gart ) {
+			DRM_ERROR( "failed to init PCI GART!\n" );
+			dev->dev_private = (void *)dev_priv;
+			r128_do_cleanup_cce( dev );
+			return -ENOMEM;
+		}
+		R128_WRITE( R128_PCI_GART_PAGE,
+			    virt_to_bus( (void *)dev_priv->phys_pci_gart ) );
+	}
+
+	r128_cce_init_ring_buffer( dev, dev_priv );
 	r128_cce_load_microcode( dev_priv );
+
+	dev->dev_private = (void *)dev_priv;
+
 	r128_do_engine_reset( dev );
 
 	return 0;
 }
 
-static int r128_do_cleanup_cce( drm_device_t *dev )
+int r128_do_cleanup_cce( drm_device_t *dev )
 {
 	if ( dev->dev_private ) {
 		drm_r128_private_t *dev_priv = dev->dev_private;
 
-		DO_REMAPFREE( dev_priv->cce_ring );
-		DO_REMAPFREE( dev_priv->ring_rptr );
-		DO_REMAPFREE( dev_priv->buffers );
-#if 0
 		if ( !dev_priv->is_pci ) {
-			DO_REMAPFREE( dev_priv->agp_textures );
+			DRM_IOREMAPFREE( dev_priv->cce_ring );
+			DRM_IOREMAPFREE( dev_priv->ring_rptr );
+			DRM_IOREMAPFREE( dev_priv->buffers );
 		}
-#endif
 
-		drm_free( dev->dev_private, sizeof(drm_r128_private_t),
-			  DRM_MEM_DRIVER );
+		DRM(free)( dev->dev_private, sizeof(drm_r128_private_t),
+			   DRM_MEM_DRIVER );
 		dev->dev_private = NULL;
 	}
 
@@ -545,6 +646,8 @@
         drm_device_t *dev = priv->dev;
 	drm_r128_init_t init;
 
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
 	if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) )
 		return -EFAULT;
 
@@ -566,11 +669,8 @@
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
+
 	if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) {
 		DRM_DEBUG( "%s while CCE running\n", __FUNCTION__ );
 		return 0;
@@ -594,11 +694,7 @@
 	int ret;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( copy_from_user( &stop, (drm_r128_init_t *)arg, sizeof(stop) ) )
 		return -EFAULT;
@@ -640,11 +736,8 @@
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
+
 	if ( !dev_priv ) {
 		DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
 		return -EINVAL;
@@ -666,11 +759,7 @@
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( dev_priv->cce_running ) {
 		r128_do_cce_flush( dev_priv );
@@ -686,17 +775,72 @@
         drm_device_t *dev = priv->dev;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	return r128_do_engine_reset( dev );
 }
 
 
 /* ================================================================
+ * Fullscreen mode
+ */
+
+static int r128_do_init_pageflip( drm_device_t *dev )
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	dev_priv->crtc_offset =      R128_READ( R128_CRTC_OFFSET );
+	dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
+
+	R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset );
+	R128_WRITE( R128_CRTC_OFFSET_CNTL,
+		    dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL );
+
+	dev_priv->page_flipping = 1;
+	dev_priv->current_page = 0;
+
+	return 0;
+}
+
+int r128_do_cleanup_pageflip( drm_device_t *dev )
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
+	R128_WRITE( R128_CRTC_OFFSET,      dev_priv->crtc_offset );
+	R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
+
+	dev_priv->page_flipping = 0;
+	dev_priv->current_page = 0;
+
+	return 0;
+}
+
+int r128_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_r128_fullscreen_t fs;
+
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( copy_from_user( &fs, (drm_r128_fullscreen_t *)arg, sizeof(fs) ) )
+		return -EFAULT;
+
+	switch ( fs.func ) {
+	case R128_INIT_FULLSCREEN:
+		return r128_do_init_pageflip( dev );
+	case R128_CLEANUP_FULLSCREEN:
+		return r128_do_cleanup_pageflip( dev );
+	}
+
+	return -EINVAL;
+}
+
+
+/* ================================================================
  * Freelist management
  */
 #define R128_BUFFER_USED	0xffffffff
@@ -712,8 +856,8 @@
 	drm_r128_freelist_t *entry;
 	int i;
 
-	dev_priv->head = drm_alloc( sizeof(drm_r128_freelist_t),
-				    DRM_MEM_DRIVER );
+	dev_priv->head = DRM(alloc)( sizeof(drm_r128_freelist_t),
+				     DRM_MEM_DRIVER );
 	if ( dev_priv->head == NULL )
 		return -ENOMEM;
 
@@ -724,8 +868,8 @@
 		buf = dma->buflist[i];
 		buf_priv = buf->dev_private;
 
-		entry = drm_alloc( sizeof(drm_r128_freelist_t),
-				   DRM_MEM_DRIVER );
+		entry = DRM(alloc)( sizeof(drm_r128_freelist_t),
+				    DRM_MEM_DRIVER );
 		if ( !entry ) return -ENOMEM;
 
 		entry->age = R128_BUFFER_FREE;
@@ -802,7 +946,7 @@
 
 
 /* ================================================================
- * CCE packet submission
+ * CCE command submission
  */
 
 int r128_wait_ring( drm_r128_private_t *dev_priv, int n )
@@ -811,378 +955,17 @@
 	int i;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-		ring->space = *ring->head - ring->tail;
-		if ( ring->space <= 0 )
-			ring->space += ring->size;
-
+		r128_update_ring_snapshot( ring );
 		if ( ring->space >= n )
 			return 0;
-
 		udelay( 1 );
 	}
 
+	/* FIXME: This is being ignored... */
+	DRM_ERROR( "failed!\n" );
 	return -EBUSY;
 }
 
-void r128_update_ring_snapshot( drm_r128_private_t *dev_priv )
-{
-	drm_r128_ring_buffer_t *ring = &dev_priv->ring;
-
-	ring->space = *ring->head - ring->tail;
-#if R128_PERFORMANCE_BOXES
-	if ( ring->space == 0 )
-		atomic_inc( &dev_priv->idle_count );
-#endif
-	if ( ring->space <= 0 )
-		ring->space += ring->size;
-}
-
-#if 0
-static int r128_verify_command( drm_r128_private_t *dev_priv,
-				u32 cmd, int *size )
-{
-	int writing = 1;
-
-	*size = 0;
-
-	switch ( cmd & R128_CCE_PACKET_MASK ) {
-	case R128_CCE_PACKET0:
-		if ( (cmd & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2) &&
-		     (cmd & R128_CCE_PACKET0_REG_MASK) !=
-		     (R128_PM4_VC_FPU_SETUP >> 2) ) {
-			writing = 0;
-		}
-		*size = ((cmd & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
-		break;
-
-	case R128_CCE_PACKET1:
-		if ( (cmd & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2) &&
-		     (cmd & R128_CCE_PACKET1_REG0_MASK) !=
-		     (R128_PM4_VC_FPU_SETUP >> 2) ) {
-			writing = 0;
-		}
-		if ( (cmd & R128_CCE_PACKET1_REG1_MASK) <= (0x1004 << 9) &&
-		     (cmd & R128_CCE_PACKET1_REG1_MASK) !=
-		     (R128_PM4_VC_FPU_SETUP << 9) ) {
-			writing = 0;
-		}
-		*size = 3;
-		break;
-
-	case R128_CCE_PACKET2:
-		break;
-
-	case R128_CCE_PACKET3:
-		*size = ((cmd & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2;
-		break;
-
-	}
-
-	return writing;
-}
-
-static int r128_submit_packet_ring_secure( drm_r128_private_t *dev_priv,
-					   u32 *commands, int *count )
-{
-#if 0
-	int write = dev_priv->sarea_priv->ring_write;
-	int *write_ptr = dev_priv->ring_start + write;
-	int c = *count;
-	u32 tmp = 0;
-	int psize = 0;
-	int writing = 1;
-	int timeout;
-
-	while ( c > 0 ) {
-		tmp = *commands++;
-		if ( !psize ) {
-			writing = r128_verify_command( dev_priv, tmp, &psize );
-		}
-		psize--;
-
-		if ( writing ) {
-			write++;
-			*write_ptr++ = tmp;
-		}
-		if ( write >= dev_priv->ring_entries ) {
-			write = 0;
-			write_ptr = dev_priv->ring_start;
-		}
-		timeout = 0;
-		while ( write == *dev_priv->ring_read_ptr ) {
-			R128_READ( R128_PM4_BUFFER_DL_RPTR );
-			if ( timeout++ >= dev_priv->usec_timeout )
-				return -EBUSY;
-			udelay( 1 );
-		}
-		c--;
-	}
-
-	if ( write < 32 ) {
-		memcpy( dev_priv->ring_end,
-			dev_priv->ring_start,
-			write * sizeof(u32) );
-	}
-
-	/* Make sure WC cache has been flushed */
-	r128_flush_write_combine();
-
-	dev_priv->sarea_priv->ring_write = write;
-	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write );
-
-	*count = 0;
-#endif
-	return 0;
-}
-
-static int r128_submit_packet_ring_insecure( drm_r128_private_t *dev_priv,
-					     u32 *commands, int *count )
-{
-#if 0
-	int write = dev_priv->sarea_priv->ring_write;
-	int *write_ptr = dev_priv->ring_start + write;
-	int c = *count;
-	int timeout;
-
-	while ( c > 0 ) {
-		write++;
-		*write_ptr++ = *commands++;
-		if ( write >= dev_priv->ring_entries ) {
-			write = 0;
-			write_ptr = dev_priv->ring_start;
-		}
-
-		timeout = 0;
-		while ( write == *dev_priv->ring_read_ptr ) {
-			R128_READ( R128_PM4_BUFFER_DL_RPTR );
-			if ( timeout++ >= dev_priv->usec_timeout )
-				return -EBUSY;
-			udelay( 1 );
-		}
-		c--;
-	}
-
-	if ( write < 32 ) {
-		memcpy( dev_priv->ring_end,
-			dev_priv->ring_start,
-			write * sizeof(u32) );
-	}
-
-	/* Make sure WC cache has been flushed */
-	r128_flush_write_combine();
-
-	dev_priv->sarea_priv->ring_write = write;
-	R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write );
-
-	*count = 0;
-#endif
-	return 0;
-}
-#endif
-
-/* Internal packet submission routine.  This uses the insecure versions
- * of the packet submission functions, and thus should only be used for
- * packets generated inside the kernel module.
- */
-int r128_do_submit_packet( drm_r128_private_t *dev_priv,
-			   u32 *buffer, int count )
-{
-	int c = count;
-	int ret = 0;
-
-#if 0
-	int left = 0;
-
-	if ( c >= dev_priv->ring_entries ) {
-		c = dev_priv->ring_entries - 1;
-		left = count - c;
-	}
-
-	/* Since this is only used by the kernel we can use the
-	 * insecure ring buffer submit packet routine.
-	 */
-	ret = r128_submit_packet_ring_insecure( dev_priv, buffer, &c );
-	c += left;
-#endif
-
-	return ( ret < 0 ) ? ret : c;
-}
-
-/* External packet submission routine.  This uses the secure versions
- * by default, and can thus submit packets received from user space.
- */
-int r128_cce_packet( 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_r128_private_t *dev_priv = dev->dev_private;
-	drm_r128_packet_t packet;
-	u32 *buffer;
-	int c;
-	int size;
-	int ret = 0;
-
-#if 0
-	/* GH: Disable packet submission for now.
-	 */
-	return -EINVAL;
-#endif
-
-	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-	     dev->lock.pid != current->pid ) {
-		DRM_ERROR( "r128_submit_packet called without lock held\n" );
-		return -EINVAL;
-	}
-
-	if ( copy_from_user( &packet, (drm_r128_packet_t *)arg,
-			     sizeof(packet) ) )
-		return -EFAULT;
-
-#if 0
-	c = packet.count;
-	size = c * sizeof(*buffer);
-
-	{
-		int left = 0;
-
-		if ( c >= dev_priv->ring_entries ) {
-			c = dev_priv->ring_entries - 1;
-			size = c * sizeof(*buffer);
-			left = packet.count - c;
-		}
-
-		buffer = kmalloc( size, 0 );
-		if ( buffer == NULL)
-			return -ENOMEM;
-		if ( copy_from_user( buffer, packet.buffer, size ) )
-			return -EFAULT;
-
-		if ( dev_priv->cce_secure ) {
-			ret = r128_submit_packet_ring_secure( dev_priv,
-							      buffer, &c );
-		} else {
-			ret = r128_submit_packet_ring_insecure( dev_priv,
-								buffer, &c );
-		}
-		c += left;
-	}
-
-	kfree( buffer );
-#else
-	c = 0;
-#endif
-
-	packet.count = c;
-	if ( copy_to_user( (drm_r128_packet_t *)arg, &packet,
-			   sizeof(packet) ) )
-		return -EFAULT;
-
-	if ( ret ) {
-		return ret;
-	} else if ( c > 0 ) {
-		return -EAGAIN;
-	}
-	return 0;
-}
-
-#if 0
-static int r128_send_vertbufs( drm_device_t *dev, drm_r128_vertex_t *v )
-{
-	drm_device_dma_t    *dma      = dev->dma;
-	drm_r128_private_t  *dev_priv = dev->dev_private;
-	drm_r128_buf_priv_t *buf_priv;
-	drm_buf_t           *buf;
-	int                  i, ret;
-	RING_LOCALS;
-
-	/* Make sure we have valid data */
-	for (i = 0; i < v->send_count; i++) {
-		int idx = v->send_indices[i];
-
-		if (idx < 0 || idx >= dma->buf_count) {
-			DRM_ERROR("Index %d (of %d max)\n",
-				  idx, dma->buf_count - 1);
-			return -EINVAL;
-		}
-		buf = dma->buflist[idx];
-		if (buf->pid != current->pid) {
-			DRM_ERROR("Process %d using buffer owned by %d\n",
-				  current->pid, buf->pid);
-			return -EINVAL;
-		}
-		if (buf->pending) {
-			DRM_ERROR("Sending pending buffer:"
-				  " buffer %d, offset %d\n",
-				  v->send_indices[i], i);
-			return -EINVAL;
-		}
-	}
-
-	/* Wait for idle, if we've wrapped to make sure that all pending
-           buffers have been processed */
-	if (dev_priv->submit_age == R128_MAX_VBUF_AGE) {
-		if ((ret = r128_do_cce_idle(dev)) < 0) return ret;
-		dev_priv->submit_age = 0;
-		r128_freelist_reset(dev);
-	}
-
-	/* Make sure WC cache has been flushed (if in PIO mode) */
-	if (!dev_priv->cce_is_bm_mode) r128_flush_write_combine();
-
-	/* FIXME: Add support for sending vertex buffer to the CCE here
-	   instead of in client code.  The v->prim holds the primitive
-	   type that should be drawn.  Loop over the list buffers in
-	   send_indices[] and submit a packet for each VB.
-
-	   This will require us to loop over the clip rects here as
-	   well, which implies that we extend the kernel driver to allow
-	   cliprects to be stored here.  Note that the cliprects could
-	   possibly come from the X server instead of the client, but
-	   this will require additional changes to the DRI to allow for
-	   this optimization. */
-
-	/* Submit a CCE packet that writes submit_age to R128_VB_AGE_REG */
-#if 0
-	cce_buffer[0] = R128CCE0(R128_CCE_PACKET0, R128_VB_AGE_REG, 0);
-	cce_buffer[1] = dev_priv->submit_age;
-
-	if ((ret = r128_do_submit_packet(dev, cce_buffer, 2)) < 0) {
-		/* Until we add support for sending VBs to the CCE in
-		   this routine, we can recover from this error.  After
-		   we add that support, we won't be able to easily
-		   recover, so we will probably have to implement
-		   another mechanism for handling timeouts from packets
-		   submitted directly by the kernel. */
-		return ret;
-	}
-#else
-	BEGIN_RING( 2 );
-
-	OUT_RING( CCE_PACKET0( R128_VB_AGE_REG, 0 ) );
-	OUT_RING( dev_priv->submit_age );
-
-	ADVANCE_RING();
-#endif
-	/* Now that the submit packet request has succeeded, we can mark
-           the buffers as pending */
-	for (i = 0; i < v->send_count; i++) {
-		buf = dma->buflist[v->send_indices[i]];
-		buf->pending = 1;
-
-		buf_priv      = buf->dev_private;
-		buf_priv->age = dev_priv->submit_age;
-	}
-
-	dev_priv->submit_age++;
-
-	return 0;
-}
-#endif
-
-
-
-
 static int r128_cce_get_buffers( drm_device_t *dev, drm_dma_t *d )
 {
 	int i;
@@ -1215,14 +998,10 @@
 	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;
-
-	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;
-	}
 
 	/* Please don't send us buffers.
 	 */
diff -urN linux-2.4.8-pre6/drivers/char/drm/r128_context.c linux/drivers/char/drm/r128_context.c
--- linux-2.4.8-pre6/drivers/char/drm/r128_context.c	Thu Jan  4 13:03:20 2001
+++ linux/drivers/char/drm/r128_context.c	Wed Dec 31 16:00:00 1969
@@ -1,217 +0,0 @@
-/* r128_context.c -- IOCTLs for r128 contexts -*- linux-c -*-
- * Created: Mon Dec 13 09:51:35 1999 by faith@precisioninsight.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include "r128_drv.h"
-
-extern drm_ctx_t r128_res_ctx;
-
-static int r128_alloc_queue(drm_device_t *dev)
-{
-	return drm_ctxbitmap_next(dev);
-}
-
-int r128_context_switch(drm_device_t *dev, int old, int new)
-{
-        char        buf[64];
-
-        atomic_inc(&dev->total_ctx);
-
-        if (test_and_set_bit(0, &dev->context_flag)) {
-                DRM_ERROR("Reentering -- FIXME\n");
-                return -EBUSY;
-        }
-
-#if DRM_DMA_HISTOGRAM
-        dev->ctx_start = get_cycles();
-#endif
-
-        DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
-        if (new == dev->last_context) {
-                clear_bit(0, &dev->context_flag);
-                return 0;
-        }
-
-        if (drm_flags & DRM_FLAG_NOCTX) {
-                r128_context_switch_complete(dev, new);
-        } else {
-                sprintf(buf, "C %d %d\n", old, new);
-                drm_write_string(dev, buf);
-        }
-
-        return 0;
-}
-
-int r128_context_switch_complete(drm_device_t *dev, int new)
-{
-        dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
-        dev->last_switch  = jiffies;
-
-        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-                DRM_ERROR("Lock isn't held after context switch\n");
-        }
-
-				/* If a context switch is ever initiated
-                                   when the kernel holds the lock, release
-                                   that lock here. */
-#if DRM_DMA_HISTOGRAM
-        atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
-                                                      - dev->ctx_start)]);
-
-#endif
-        clear_bit(0, &dev->context_flag);
-        wake_up(&dev->context_wait);
-
-        return 0;
-}
-
-
-int r128_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
-{
-	drm_ctx_res_t	res;
-	drm_ctx_t	ctx;
-	int		i;
-
-	DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
-	if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
-		return -EFAULT;
-	if (res.count >= DRM_RESERVED_CONTEXTS) {
-		memset(&ctx, 0, sizeof(ctx));
-		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-			ctx.handle = i;
-			if (copy_to_user(&res.contexts[i],
-					 &i,
-					 sizeof(i)))
-				return -EFAULT;
-		}
-	}
-	res.count = DRM_RESERVED_CONTEXTS;
-	if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
-		return -EFAULT;
-	return 0;
-}
-
-
-int r128_addctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	if ((ctx.handle = r128_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
-				/* Skip kernel's context and get a new one. */
-		ctx.handle = r128_alloc_queue(dev);
-	}
-	DRM_DEBUG("%d\n", ctx.handle);
-	if (ctx.handle == -1) {
-		DRM_DEBUG("Not enough free contexts.\n");
-				/* Should this return -EBUSY instead? */
-		return -ENOMEM;
-	}
-
-	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int r128_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	unsigned long arg)
-{
-	drm_ctx_t ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
-		return -EFAULT;
-	if (ctx.flags==_DRM_CONTEXT_PRESERVED)
-		r128_res_ctx.handle=ctx.handle;
-	return 0;
-}
-
-int r128_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	unsigned long arg)
-{
-	drm_ctx_t ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
-		return -EFAULT;
-	/* This is 0, because we don't hanlde any context flags */
-	ctx.flags = 0;
-	if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int r128_switchctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	return r128_context_switch(dev, dev->last_context, ctx.handle);
-}
-
-int r128_newctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	r128_context_switch_complete(dev, ctx.handle);
-
-	return 0;
-}
-
-int r128_rmctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	drm_ctxbitmap_free(dev, ctx.handle);
-
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/r128_drm.h linux/drivers/char/drm/r128_drm.h
--- linux-2.4.8-pre6/drivers/char/drm/r128_drm.h	Thu Jan  4 13:03:20 2001
+++ linux/drivers/char/drm/r128_drm.h	Mon Dec  3 22:59:45 2001
@@ -25,13 +25,12 @@
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
- *
+ *    Kevin E. Martin <martin@valinux.com>
  */
 
-#ifndef _R128_DRM_H_
-#define _R128_DRM_H_
+#ifndef __R128_DRM_H__
+#define __R128_DRM_H__
 
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the X server file (r128_sarea.h)
@@ -69,21 +68,13 @@
 
 /* Vertex/indirect buffer size
  */
-#if 1
 #define R128_BUFFER_SIZE		16384
-#else
-#define R128_BUFFER_SIZE		(128 * 1024)
-#endif
 
 /* Byte offsets for indirect buffer data
  */
 #define R128_INDEX_PRIM_OFFSET		20
 #define R128_HOSTDATA_BLIT_OFFSET	32
 
-/* 2048x2048 @ 32bpp texture requires this many indirect buffers
- */
-#define R128_MAX_BLIT_BUFFERS		((2048 * 2048 * 4) / R128_BUFFER_SIZE)
-
 /* Keep these small for testing.
  */
 #define R128_NR_SAREA_CLIPRECTS		12
@@ -98,7 +89,9 @@
 #define R128_LOG_TEX_GRANULARITY	16
 
 #define R128_NR_CONTEXT_REGS		12
-#define R128_TEX_MAXLEVELS		11
+
+#define R128_MAX_TEXTURE_LEVELS		11
+#define R128_MAX_TEXTURE_UNITS		2
 
 #endif /* __R128_SAREA_DEFINES__ */
 
@@ -137,28 +130,23 @@
 	unsigned int scale_3d_cntl;
 } drm_r128_context_regs_t;
 
-/* Setup registers for each texture unit */
+/* Setup registers for each texture unit
+ */
 typedef struct {
 	unsigned int tex_cntl;
 	unsigned int tex_combine_cntl;
 	unsigned int tex_size_pitch;
-	unsigned int tex_offset[R128_TEX_MAXLEVELS];
+	unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS];
 	unsigned int tex_border_color;
 } drm_r128_texture_regs_t;
 
 
-typedef struct drm_tex_region {
-	unsigned char next, prev;
-	unsigned char in_use;
-	int age;
-} drm_tex_region_t;
-
 typedef struct drm_r128_sarea {
 	/* The channel for communication of state information to the kernel
 	 * on firing a vertex buffer.
 	 */
 	drm_r128_context_regs_t context_state;
-	drm_r128_texture_regs_t tex_state[R128_NR_TEX_HEAPS];
+	drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS];
 	unsigned int dirty;
 	unsigned int vertsize;
 	unsigned int vc_format;
@@ -187,7 +175,11 @@
 		R128_INIT_CCE    = 0x01,
 		R128_CLEANUP_CCE = 0x02
 	} func;
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
 	int sarea_priv_offset;
+#else
+	unsigned long sarea_priv_offset;
+#endif
 	int is_pci;
 	int cce_mode;
 	int cce_secure;
@@ -201,12 +193,21 @@
 	unsigned int depth_offset, depth_pitch;
 	unsigned int span_offset;
 
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
 	unsigned int fb_offset;
 	unsigned int mmio_offset;
 	unsigned int ring_offset;
 	unsigned int ring_rptr_offset;
 	unsigned int buffers_offset;
 	unsigned int agp_textures_offset;
+#else
+	unsigned long fb_offset;
+	unsigned long mmio_offset;
+	unsigned long ring_offset;
+	unsigned long ring_rptr_offset;
+	unsigned long buffers_offset;
+	unsigned long agp_textures_offset;
+#endif
 } drm_r128_init_t;
 
 typedef struct drm_r128_cce_stop {
@@ -216,9 +217,15 @@
 
 typedef struct drm_r128_clear {
 	unsigned int flags;
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
 	int x, y, w, h;
+#endif
 	unsigned int clear_color;
 	unsigned int clear_depth;
+#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
+	unsigned int color_mask;
+	unsigned int depth_mask;
+#endif
 } drm_r128_clear_t;
 
 typedef struct drm_r128_vertex {
@@ -263,10 +270,18 @@
 	unsigned int *mask;
 } drm_r128_stipple_t;
 
-typedef struct drm_r128_packet {
-	unsigned int *buffer;
-	int count;
-	int flags;
-} drm_r128_packet_t;
+typedef struct drm_r128_indirect {
+	int idx;
+	int start;
+	int end;
+	int discard;
+} drm_r128_indirect_t;
+
+typedef struct drm_r128_fullscreen {
+	enum {
+		R128_INIT_FULLSCREEN    = 0x01,
+		R128_CLEANUP_FULLSCREEN = 0x02
+	} func;
+} drm_r128_fullscreen_t;
 
 #endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/r128_drv.c linux/drivers/char/drm/r128_drv.c
--- linux-2.4.8-pre6/drivers/char/drm/r128_drv.c	Thu Jan  4 13:03:20 2001
+++ linux/drivers/char/drm/r128_drv.c	Mon Dec  3 22:59:45 2001
@@ -1,7 +1,7 @@
 /* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
  * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
  *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
@@ -19,681 +19,94 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  *
  * Authors:
  *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
- *
  */
 
 #include <linux/config.h>
+#include "r128.h"
 #include "drmP.h"
 #include "r128_drv.h"
+#include "ati_pcigart.h"
 
-#define R128_NAME		"r128"
-#define R128_DESC		"ATI Rage 128"
-#define R128_DATE		"20001215"
-#define R128_MAJOR		2
-#define R128_MINOR		1
-#define R128_PATCHLEVEL		2
-
-static drm_device_t	r128_device;
-drm_ctx_t		r128_res_ctx;
-
-static struct file_operations r128_fops = {
-#if LINUX_VERSION_CODE >= 0x020400
-				/* This started being used during 2.4.0-test */
-	owner:   THIS_MODULE,
-#endif
-	open:	 r128_open,
-	flush:	 drm_flush,
-	release: r128_release,
-	ioctl:	 r128_ioctl,
-	mmap:	 drm_mmap,
-	read:	 drm_read,
-	fasync:	 drm_fasync,
-	poll:	 drm_poll,
-};
-
-static struct miscdevice      r128_misc = {
-	minor: MISC_DYNAMIC_MINOR,
-	name:  R128_NAME,
-	fops:  &r128_fops,
-};
-
-static drm_ioctl_desc_t	      r128_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]      = { r128_version,      0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]   = { drm_getunique,     0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]    = { drm_getmagic,      0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]    = { drm_irq_busid,     0, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]   = { drm_setunique,     1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]	       = { drm_block,         1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]      = { drm_unblock,       1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]   = { drm_authmagic,     1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]      = { drm_addmap,        1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]     = { r128_addbufs,      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]    = { drm_markbufs,      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]    = { drm_infobufs,      1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]     = { r128_mapbufs,      1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]    = { drm_freebufs,      1, 0 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]      = { r128_addctx,	      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]       = { r128_rmctx,	      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]      = { r128_modctx,	      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]      = { r128_getctx,	      1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]   = { r128_switchctx,    1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]      = { r128_newctx,	      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]      = { r128_resctx,	      1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]     = { drm_adddraw,	      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]      = { drm_rmdraw,	      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	       = { r128_cce_buffers,  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	       = { r128_lock,	      1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]       = { r128_unlock,	      1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]       = { drm_finish,	      1, 0 },
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]  = { drm_agp_acquire,   1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]  = { drm_agp_release,   1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]   = { drm_agp_enable,    1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]     = { drm_agp_info,      1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]    = { drm_agp_alloc,     1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]     = { drm_agp_free,      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]     = { drm_agp_bind,      1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]   = { drm_agp_unbind,    1, 1 },
-#endif
+#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
 
-	[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_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_PACKET)]  = { r128_cce_packet,   1, 0 },
-};
-#define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls)
+#define DRIVER_NAME		"r128"
+#define DRIVER_DESC		"ATI Rage 128"
+#define DRIVER_DATE		"20010405"
+
+#define DRIVER_MAJOR		2
+#define DRIVER_MINOR		1
+#define DRIVER_PATCHLEVEL	6
+
+#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 },
 
-#ifdef MODULE
-static char		      *r128 = NULL;
+
+#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
 
-MODULE_AUTHOR("VA Linux Systems, Inc.");
-MODULE_DESCRIPTION("r128");
-MODULE_PARM(r128, "s");
+
+#include "drm_agpsupport.h"
+#include "drm_auth.h"
+#include "drm_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
 
 #ifndef MODULE
-/* r128_options is called by the kernel to parse command-line options
+/* 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.
  */
 
-static int __init r128_options(char *str)
+/* 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);
+	DRM(parse_options)( str );
 	return 1;
 }
 
-__setup("r128=", r128_options);
-#endif
-
-static int r128_setup(drm_device_t *dev)
-{
-	int i;
-
-	atomic_set(&dev->ioctl_count, 0);
-	atomic_set(&dev->vma_count, 0);
-	dev->buf_use	  = 0;
-	atomic_set(&dev->buf_alloc, 0);
-
-	drm_dma_setup(dev);
-
-	atomic_set(&dev->total_open, 0);
-	atomic_set(&dev->total_close, 0);
-	atomic_set(&dev->total_ioctl, 0);
-	atomic_set(&dev->total_irq, 0);
-	atomic_set(&dev->total_ctx, 0);
-	atomic_set(&dev->total_locks, 0);
-	atomic_set(&dev->total_unlocks, 0);
-	atomic_set(&dev->total_contends, 0);
-	atomic_set(&dev->total_sleeps, 0);
-
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		dev->magiclist[i].head = NULL;
-		dev->magiclist[i].tail = NULL;
-	}
-	dev->maplist	    = NULL;
-	dev->map_count	    = 0;
-	dev->vmalist	    = NULL;
-	dev->lock.hw_lock   = NULL;
-	init_waitqueue_head(&dev->lock.lock_queue);
-	dev->queue_count    = 0;
-	dev->queue_reserved = 0;
-	dev->queue_slots    = 0;
-	dev->queuelist	    = NULL;
-	dev->irq	    = 0;
-	dev->context_flag   = 0;
-	dev->interrupt_flag = 0;
-	dev->dma_flag	    = 0;
-	dev->last_context   = 0;
-	dev->last_switch    = 0;
-	dev->last_checked   = 0;
-	init_timer(&dev->timer);
-	init_waitqueue_head(&dev->context_wait);
-
-	dev->ctx_start	    = 0;
-	dev->lck_start	    = 0;
-
-	dev->buf_rp	  = dev->buf;
-	dev->buf_wp	  = dev->buf;
-	dev->buf_end	  = dev->buf + DRM_BSZ;
-	dev->buf_async	  = NULL;
-	init_waitqueue_head(&dev->buf_readers);
-	init_waitqueue_head(&dev->buf_writers);
-
-	r128_res_ctx.handle=-1;
-
-	DRM_DEBUG("\n");
-
-	/* The kernel's context could be created here, but is now created
-	   in drm_dma_enqueue.	This is more resource-efficient for
-	   hardware that does not do DMA, but may mean that
-	   drm_select_queue fails between the time the interrupt is
-	   initialized and the time the queues are initialized. */
-
-	return 0;
-}
-
-
-static int r128_takedown(drm_device_t *dev)
-{
-	int		  i;
-	drm_magic_entry_t *pt, *next;
-	drm_map_t	  *map;
-	drm_vma_entry_t	  *vma, *vma_next;
-
-	DRM_DEBUG("\n");
-
-	down(&dev->struct_sem);
-	del_timer(&dev->timer);
-
-	if (dev->devname) {
-		drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
-		dev->devname = NULL;
-	}
-
-	if (dev->unique) {
-		drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
-		dev->unique = NULL;
-		dev->unique_len = 0;
-	}
-				/* Clear pid list */
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		for (pt = dev->magiclist[i].head; pt; pt = next) {
-			next = pt->next;
-			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-		}
-		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
-	}
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-				/* Clear AGP information */
-	if (dev->agp) {
-		drm_agp_mem_t *entry;
-		drm_agp_mem_t *nexte;
-
-				/* Remove AGP resources, but leave dev->agp
-                                   intact until r128_cleanup is called. */
-		for (entry = dev->agp->memory; entry; entry = nexte) {
-			nexte = entry->next;
-			if (entry->bound) drm_unbind_agp(entry->memory);
-			drm_free_agp(entry->memory, entry->pages);
-			drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-		}
-		dev->agp->memory = NULL;
-
-		if (dev->agp->acquired)	_drm_agp_release();
-
-		dev->agp->acquired = 0;
-		dev->agp->enabled  = 0;
-	}
-#endif
-
-				/* Clear vma list (only built for debugging) */
-	if (dev->vmalist) {
-		for (vma = dev->vmalist; vma; vma = vma_next) {
-			vma_next = vma->next;
-			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
-		}
-		dev->vmalist = NULL;
-	}
-
-				/* Clear map area and mtrr information */
-	if (dev->maplist) {
-		for (i = 0; i < dev->map_count; i++) {
-			map = dev->maplist[i];
-			switch (map->type) {
-			case _DRM_REGISTERS:
-			case _DRM_FRAME_BUFFER:
-#ifdef CONFIG_MTRR
-				if (map->mtrr >= 0) {
-					int retcode;
-					retcode = mtrr_del(map->mtrr,
-							   map->offset,
-							   map->size);
-					DRM_DEBUG("mtrr_del = %d\n", retcode);
-				}
-#endif
-				drm_ioremapfree(map->handle, map->size);
-				break;
-			case _DRM_SHM:
-				drm_free_pages((unsigned long)map->handle,
-					       drm_order(map->size)
-					       - PAGE_SHIFT,
-					       DRM_MEM_SAREA);
-				break;
-			case _DRM_AGP:
-				/* Do nothing here, because this is all
-                                   handled in the AGP/GART driver. */
-				break;
-			}
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		}
-		drm_free(dev->maplist,
-			 dev->map_count * sizeof(*dev->maplist),
-			 DRM_MEM_MAPS);
-		dev->maplist   = NULL;
-		dev->map_count = 0;
-	}
-
-	drm_dma_takedown(dev);
-
-	dev->queue_count     = 0;
-	if (dev->lock.hw_lock) {
-		dev->lock.hw_lock    = NULL; /* SHM removed */
-		dev->lock.pid	     = 0;
-		wake_up_interruptible(&dev->lock.lock_queue);
-	}
-	up(&dev->struct_sem);
-
-	return 0;
-}
-
-/* r128_init is called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported). */
-
-static int __init r128_init(void)
-{
-	int		      retcode;
-	drm_device_t	      *dev = &r128_device;
-
-	DRM_DEBUG("\n");
-
-	memset((void *)dev, 0, sizeof(*dev));
-	dev->count_lock	  = SPIN_LOCK_UNLOCKED;
-	sema_init(&dev->struct_sem, 1);
-
-#ifdef MODULE
-	drm_parse_options(r128);
-#endif
-
-	if ((retcode = misc_register(&r128_misc))) {
-		DRM_ERROR("Cannot register \"%s\"\n", R128_NAME);
-		return retcode;
-	}
-	dev->device = MKDEV(MISC_MAJOR, r128_misc.minor);
-	dev->name   = R128_NAME;
-
-	drm_mem_init();
-	drm_proc_init(dev);
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	dev->agp    = drm_agp_init();
-	if (dev->agp == NULL) {
-		DRM_ERROR("Cannot initialize agpgart module.\n");
-		drm_proc_cleanup();
-		misc_deregister(&r128_misc);
-		r128_takedown(dev);
-		return -ENOMEM;
-	}
-
-#ifdef CONFIG_MTRR
-	dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
-				      dev->agp->agp_info.aper_size*1024*1024,
-				      MTRR_TYPE_WRCOMB,
-				      1);
+__setup( DRIVER_NAME "=", r128_options );
 #endif
-#endif
-
-	if((retcode = drm_ctxbitmap_init(dev))) {
-		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
-		drm_proc_cleanup();
-		misc_deregister(&r128_misc);
-		r128_takedown(dev);
-		return retcode;
-	}
-
-	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
-		 R128_NAME,
-		 R128_MAJOR,
-		 R128_MINOR,
-		 R128_PATCHLEVEL,
-		 R128_DATE,
-		 r128_misc.minor);
-
-	return 0;
-}
-
-/* r128_cleanup is called via cleanup_module at module unload time. */
-
-static void __exit r128_cleanup(void)
-{
-	drm_device_t	      *dev = &r128_device;
-
-	DRM_DEBUG("\n");
-
-	drm_proc_cleanup();
-	if (misc_deregister(&r128_misc)) {
-		DRM_ERROR("Cannot unload module\n");
-	} else {
-		DRM_INFO("Module unloaded\n");
-	}
-	drm_ctxbitmap_cleanup(dev);
-	r128_takedown(dev);
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	if (dev->agp) {
-		drm_agp_uninit();
-		drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
-		dev->agp = NULL;
-	}
-#endif
-}
-
-module_init(r128_init);
-module_exit(r128_cleanup);
 
-
-int r128_version(struct inode *inode, struct file *filp,
-		 unsigned int cmd, unsigned long arg)
-{
-	drm_version_t version;
-	int	      len;
-
-	if (copy_from_user(&version,
-			   (drm_version_t *)arg,
-			   sizeof(version)))
-		return -EFAULT;
-
-#define DRM_COPY(name,value)					\
-	len = strlen(value);					\
-	if (len > name##_len) len = name##_len;			\
-	name##_len = strlen(value);				\
-	if (len && name) {					\
-		if (copy_to_user(name, value, len))		\
-			return -EFAULT;				\
-	}
-
-	version.version_major	   = R128_MAJOR;
-	version.version_minor	   = R128_MINOR;
-	version.version_patchlevel = R128_PATCHLEVEL;
-
-	DRM_COPY(version.name, R128_NAME);
-	DRM_COPY(version.date, R128_DATE);
-	DRM_COPY(version.desc, R128_DESC);
-
-	if (copy_to_user((drm_version_t *)arg,
-			 &version,
-			 sizeof(version)))
-		return -EFAULT;
-	return 0;
-}
-
-int r128_open(struct inode *inode, struct file *filp)
-{
-	drm_device_t  *dev    = &r128_device;
-	int	      retcode = 0;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (!(retcode = drm_open_helper(inode, filp, dev))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-		atomic_inc(&dev->total_open);
-		spin_lock(&dev->count_lock);
-		if (!dev->open_count++) {
-			spin_unlock(&dev->count_lock);
-			return r128_setup(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-
-	return retcode;
-}
-
-int r128_release(struct inode *inode, struct file *filp)
-{
-	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev;
-	int	      retcode = 0;
-
-	lock_kernel();
-	dev = priv->dev;
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (!(retcode = drm_release(inode, filp))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-		atomic_inc(&dev->total_close);
-		spin_lock(&dev->count_lock);
-		if (!--dev->open_count) {
-			if (atomic_read(&dev->ioctl_count) || dev->blocked) {
-				DRM_ERROR("Device busy: %d %d\n",
-					  atomic_read(&dev->ioctl_count),
-					  dev->blocked);
-				spin_unlock(&dev->count_lock);
-				unlock_kernel();
-				return -EBUSY;
-			}
-			spin_unlock(&dev->count_lock);
-			unlock_kernel();
-			return r128_takedown(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-
-	unlock_kernel();
-	return retcode;
-}
-
-/* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */
-int r128_ioctl(struct inode *inode, struct file *filp,
-	       unsigned int cmd, unsigned long arg)
-{
-	int		 nr	 = DRM_IOCTL_NR(cmd);
-	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	int		 retcode = 0;
-	drm_ioctl_desc_t *ioctl;
-	drm_ioctl_t	 *func;
-
-	atomic_inc(&dev->ioctl_count);
-	atomic_inc(&dev->total_ioctl);
-	++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);
-
-	if (nr >= R128_IOCTL_COUNT) {
-		retcode = -EINVAL;
-	} else {
-		ioctl	  = &r128_ioctls[nr];
-		func	  = ioctl->func;
-
-		if (!func) {
-			DRM_DEBUG("no function\n");
-			retcode = -EINVAL;
-		} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
-			   || (ioctl->auth_needed && !priv->authenticated)) {
-			retcode = -EACCES;
-		} else {
-			retcode = (func)(inode, filp, cmd, arg);
-		}
-	}
-
-#if 0
-	if ( retcode ) {
-		DRM_INFO( "%s 0x%x ret = %d\n", __FUNCTION__, nr, retcode );
-	}
-#endif
-
-	atomic_dec(&dev->ioctl_count);
-	return retcode;
-}
-
-int r128_lock(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;
-        DECLARE_WAITQUEUE(entry, current);
-        int               ret   = 0;
-        drm_lock_t        lock;
-#if DRM_DMA_HISTOGRAM
-        cycles_t          start;
-
-        dev->lck_start = start = get_cycles();
-#endif
-
-        if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-        if (lock.context == DRM_KERNEL_CONTEXT) {
-                DRM_ERROR("Process %d using kernel context %d\n",
-                          current->pid, lock.context);
-                return -EINVAL;
-        }
-
-        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-                  lock.context, current->pid, dev->lock.hw_lock->lock,
-                  lock.flags);
-
-        if (lock.context < 0)
-                return -EINVAL;
-
-        if (!ret) {
-                add_wait_queue(&dev->lock.lock_queue, &entry);
-                for (;;) {
-                        current->state = TASK_INTERRUPTIBLE;
-                        if (!dev->lock.hw_lock) {
-                                /* Device has been unregistered */
-                                ret = -EINTR;
-                                break;
-                        }
-                        if (drm_lock_take(&dev->lock.hw_lock->lock,
-                                          lock.context)) {
-                                dev->lock.pid       = current->pid;
-                                dev->lock.lock_time = jiffies;
-                                atomic_inc(&dev->total_locks);
-                                break;  /* Got lock */
-                        }
-
-                                /* Contention */
-                        atomic_inc(&dev->total_sleeps);
-                        schedule();
-                        if (signal_pending(current)) {
-                                ret = -ERESTARTSYS;
-                                break;
-                        }
-                }
-                current->state = TASK_RUNNING;
-                remove_wait_queue(&dev->lock.lock_queue, &entry);
-        }
-
-        if (!ret) {
-		sigemptyset(&dev->sigmask);
-		sigaddset(&dev->sigmask, SIGSTOP);
-		sigaddset(&dev->sigmask, SIGTSTP);
-		sigaddset(&dev->sigmask, SIGTTIN);
-		sigaddset(&dev->sigmask, SIGTTOU);
-		dev->sigdata.context = lock.context;
-		dev->sigdata.lock    = dev->lock.hw_lock;
-		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
-                if (lock.flags & _DRM_LOCK_READY) {
-				/* Wait for space in DMA/FIFO */
-		}
-                if (lock.flags & _DRM_LOCK_QUIESCENT) {
-				/* Make hardware quiescent */
-			DRM_DEBUG( "not quiescent!\n" );
-#if 0
-                        r128_quiescent(dev);
-#endif
-		}
-        }
-
-#if LINUX_VERSION_CODE < 0x020400
-	if (lock.context != r128_res_ctx.handle) {
-		current->counter = 5;
-		current->priority = DEF_PRIORITY/4;
-	}
-#endif
-        DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
-
-#if DRM_DMA_HISTOGRAM
-        atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
-#endif
-
-        return ret;
-}
-
-
-int r128_unlock(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_lock_t	  lock;
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("%d frees lock (%d holds)\n",
-		  lock.context,
-		  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-	atomic_inc(&dev->total_unlocks);
-	if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
-		atomic_inc(&dev->total_contends);
-	drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
-				/* FIXME: Try to send data to card here */
-	if (!dev->context_flag) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
-				  DRM_KERNEL_CONTEXT)) {
-			DRM_ERROR("\n");
-		}
-	}
-
-#if LINUX_VERSION_CODE < 0x020400
-	if (lock.context != r128_res_ctx.handle) {
-		current->counter = 5;
-		current->priority = DEF_PRIORITY;
-	}
-#endif
-	unblock_all_signals();
-	return 0;
-}
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
+#include "drm_scatter.h"
diff -urN linux-2.4.8-pre6/drivers/char/drm/r128_drv.h linux/drivers/char/drm/r128_drv.h
--- linux-2.4.8-pre6/drivers/char/drm/r128_drv.h	Wed Jun 20 21:00:55 2001
+++ linux/drivers/char/drm/r128_drv.h	Mon Dec  3 22:59:45 2001
@@ -25,15 +25,18 @@
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Rickard E. (Rik) Faith <faith@valinux.com>
- *   Kevin E. Martin <martin@valinux.com>
- *   Gareth Hughes <gareth@valinux.com>
- *
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Michel Dänzer <daenzerm@student.ethz.ch>
  */
 
 #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 )
+
 typedef struct drm_r128_freelist {
    	unsigned int age;
    	drm_buf_t *buf;
@@ -51,6 +54,8 @@
 	u32 tail;
 	u32 tail_mask;
 	int space;
+
+	int high_mark;
 } drm_r128_ring_buffer_t;
 
 typedef struct drm_r128_private {
@@ -59,7 +64,6 @@
 
 	int cce_mode;
 	int cce_fifo_size;
-	int cce_secure;
 	int cce_running;
 
    	drm_r128_freelist_t *head;
@@ -67,16 +71,23 @@
 
 	int usec_timeout;
 	int is_pci;
+	unsigned long phys_pci_gart;
+	unsigned long cce_buffers_offset;
 
 	atomic_t idle_count;
 
-	unsigned int fb_bpp;
+	int page_flipping;
+	int current_page;
+	u32 crtc_offset;
+	u32 crtc_offset_cntl;
+
+	u32 color_fmt;
 	unsigned int front_offset;
 	unsigned int front_pitch;
 	unsigned int back_offset;
 	unsigned int back_pitch;
 
-	unsigned int depth_bpp;
+	u32 depth_fmt;
 	unsigned int depth_offset;
 	unsigned int depth_pitch;
 	unsigned int span_offset;
@@ -103,18 +114,6 @@
    	drm_r128_freelist_t *list_entry;
 } drm_r128_buf_priv_t;
 
-				/* r128_drv.c */
-extern int  r128_version( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int  r128_open( struct inode *inode, struct file *filp );
-extern int  r128_release( struct inode *inode, struct file *filp );
-extern int  r128_ioctl( struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg );
-extern int  r128_lock( struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg );
-extern int  r128_unlock( struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg );
-
 				/* r128_cce.c */
 extern int r128_cce_init( struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg );
@@ -128,7 +127,7 @@
 			  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_cce_packet( struct inode *inode, struct file *filp,
+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 );
@@ -137,7 +136,18 @@
 extern drm_buf_t *r128_freelist_get( drm_device_t *dev );
 
 extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
-extern void r128_update_ring_snapshot( drm_r128_private_t *dev_priv );
+
+static inline void
+r128_update_ring_snapshot( drm_r128_ring_buffer_t *ring )
+{
+	ring->space = (GET_RING_HEAD( ring ) - ring->tail) * sizeof(u32);
+	if ( ring->space <= 0 )
+		ring->space += ring->size;
+}
+
+extern int r128_do_cce_idle( drm_r128_private_t *dev_priv );
+extern int r128_do_cleanup_cce( drm_device_t *dev );
+extern int r128_do_cleanup_pageflip( drm_device_t *dev );
 
 				/* r128_state.c */
 extern int r128_cce_clear( struct inode *inode, struct file *filp,
@@ -154,31 +164,8 @@
 			   unsigned int cmd, unsigned long arg );
 extern int r128_cce_stipple( struct inode *inode, struct file *filp,
 			     unsigned int cmd, unsigned long arg );
-
-				/* r128_bufs.c */
-extern int r128_addbufs(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int r128_mapbufs(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-
-				/* r128_context.c */
-extern int  r128_resctx(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  r128_addctx(struct inode *inode, struct file *filp,
-		        unsigned int cmd, unsigned long arg);
-extern int  r128_modctx(struct inode *inode, struct file *filp,
-		        unsigned int cmd, unsigned long arg);
-extern int  r128_getctx(struct inode *inode, struct file *filp,
-		        unsigned int cmd, unsigned long arg);
-extern int  r128_switchctx(struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg);
-extern int  r128_newctx(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  r128_rmctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-
-extern int  r128_context_switch(drm_device_t *dev, int old, int new);
-extern int  r128_context_switch_complete(drm_device_t *dev, int new);
+extern int r128_cce_indirect( struct inode *inode, struct file *filp,
+			      unsigned int cmd, unsigned long arg );
 
 
 /* Register definitions, register access macros and drmAddMap constants
@@ -215,8 +202,10 @@
 #define R128_CLOCK_CNTL_INDEX		0x0008
 #define R128_CLOCK_CNTL_DATA		0x000c
 #	define R128_PLL_WR_EN			(1 << 7)
-
 #define R128_CONSTANT_COLOR_C		0x1d34
+#define R128_CRTC_OFFSET		0x0224
+#define R128_CRTC_OFFSET_CNTL		0x0228
+#	define R128_CRTC_OFFSET_FLIP_CNTL	(1 << 16)
 
 #define R128_DP_GUI_MASTER_CNTL		0x146c
 #       define R128_GMC_SRC_PITCH_OFFSET_CNTL	(1    <<  0)
@@ -265,6 +254,7 @@
 #	define R128_PC_FLUSH_ALL		0x00ff
 #	define R128_PC_BUSY			(1 << 31)
 
+#define R128_PCI_GART_PAGE		0x017c
 #define R128_PRIM_TEX_CNTL_C		0x1cb0
 
 #define R128_SCALE_3D_CNTL		0x1a00
@@ -276,6 +266,8 @@
 #define R128_TEX_CNTL_C			0x1c9c
 #	define R128_TEX_CACHE_FLUSH		(1 << 23)
 
+#define R128_WAIT_UNTIL			0x1720
+#	define R128_EVENT_CRTC_OFFSET		(1 << 0)
 #define R128_WINDOW_XY_OFFSET		0x1bcc
 
 
@@ -376,38 +368,68 @@
 #define R128_WATERMARK_N		8
 #define R128_WATERMARK_K		128
 
-#define R128_MAX_USEC_TIMEOUT	100000	/* 100 ms */
+#define R128_MAX_USEC_TIMEOUT		100000	/* 100 ms */
 
 #define R128_LAST_FRAME_REG		R128_GUI_SCRATCH_REG0
 #define R128_LAST_DISPATCH_REG		R128_GUI_SCRATCH_REG1
-#define R128_MAX_VB_AGE			0xffffffff
-
+#define R128_MAX_VB_AGE			0x7fffffff
 #define R128_MAX_VB_VERTS		(0xffff)
 
+#define R128_RING_HIGH_MARK		128
 
-#define R128_BASE(reg)		((unsigned long)(dev_priv->mmio->handle))
-#define R128_ADDR(reg)		(R128_BASE(reg) + reg)
+#define R128_PERFORMANCE_BOXES		0
 
-#define R128_READ(reg)		readl(R128_ADDR(reg))
-#define R128_WRITE(reg,val)	writel(val,R128_ADDR(reg))
 
-#define R128_READ8(reg)		readb(R128_ADDR(reg))
-#define R128_WRITE8(reg,val)	writeb(val,R128_ADDR(reg))
+#define R128_BASE(reg)		((unsigned long)(dev_priv->mmio->handle))
+#define R128_ADDR(reg)		(R128_BASE( reg ) + reg)
 
-#define R128_WRITE_PLL(addr,val)                                              \
-do {                                                                          \
-	R128_WRITE8(R128_CLOCK_CNTL_INDEX, ((addr) & 0x1f) | R128_PLL_WR_EN); \
-	R128_WRITE(R128_CLOCK_CNTL_DATA, (val));                              \
+#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
 
-extern int R128_READ_PLL(drm_device_t *dev, int addr);
-
-#define R128CCE0(p,r,n)   ((p) | ((n) << 16) | ((r) >> 2))
-#define R128CCE1(p,r1,r2) ((p) | (((r2) >> 2) << 11) | ((r1) >> 2))
-#define R128CCE2(p)       ((p))
-#define R128CCE3(p,n)     ((p) | ((n) << 16))
-
+#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_WRITE_PLL(addr,val)					\
+do {									\
+	R128_WRITE8(R128_CLOCK_CNTL_INDEX,				\
+		    ((addr) & 0x1f) | R128_PLL_WR_EN);			\
+	R128_WRITE(R128_CLOCK_CNTL_DATA, (val));			\
+} while (0)
 
+extern int R128_READ_PLL(drm_device_t *dev, int addr);
 
 
 #define CCE_PACKET0( reg, n )		(R128_CCE_PACKET0 |		\
@@ -419,33 +441,92 @@
 					 (pkt) | ((n) << 16))
 
 
-#define r128_flush_write_combine()		mb()
+/* ================================================================
+ * Misc helper macros
+ */
+
+#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;						\
+	}								\
+} while (0)
+
+#define RING_SPACE_TEST_WITH_RETURN( dev_priv )				\
+do {									\
+	drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i;		\
+	if ( ring->space < ring->high_mark ) {				\
+		for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {	\
+			r128_update_ring_snapshot( ring );		\
+			if ( ring->space >= ring->high_mark )		\
+				goto __ring_space_done;			\
+			udelay( 1 );					\
+		}							\
+		DRM_ERROR( "ring space check failed!\n" );		\
+		return -EBUSY;						\
+	}								\
+ __ring_space_done:							\
+} while (0)
+
+#define VB_AGE_TEST_WITH_RETURN( dev_priv )				\
+do {									\
+	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;		\
+	if ( sarea_priv->last_dispatch >= R128_MAX_VB_AGE ) {		\
+		int __ret = r128_do_cce_idle( dev_priv );		\
+		if ( __ret < 0 ) return __ret;				\
+		sarea_priv->last_dispatch = 0;				\
+		r128_freelist_reset( dev );				\
+	}								\
+} while (0)
+
+#define R128_WAIT_UNTIL_PAGE_FLIPPED() do {				\
+	OUT_RING( CCE_PACKET0( R128_WAIT_UNTIL, 0 ) );			\
+	OUT_RING( R128_EVENT_CRTC_OFFSET );				\
+} while (0)
+
+
+/* ================================================================
+ * Ring control
+ */
+
+#define r128_flush_write_combine()	mb()
 
 
 #define R128_VERBOSE	0
 
-#define RING_LOCALS	int write; unsigned int tail_mask; volatile u32 *ring;
+#define RING_LOCALS							\
+	int write; unsigned int tail_mask; volatile u32 *ring;
 
 #define BEGIN_RING( n ) do {						\
 	if ( R128_VERBOSE ) {						\
 		DRM_INFO( "BEGIN_RING( %d ) in %s\n",			\
-			   n, __FUNCTION__ );				\
+			   (n), __FUNCTION__ );				\
 	}								\
-	if ( dev_priv->ring.space < n * sizeof(u32) ) {			\
-		r128_wait_ring( dev_priv, n * sizeof(u32) );		\
+	if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {		\
+		r128_wait_ring( dev_priv, (n) * sizeof(u32) );		\
 	}								\
-	dev_priv->ring.space -= n * sizeof(u32);			\
+	dev_priv->ring.space -= (n) * sizeof(u32);			\
 	ring = dev_priv->ring.start;					\
 	write = dev_priv->ring.tail;					\
 	tail_mask = dev_priv->ring.tail_mask;				\
 } while (0)
 
+/* You can set this to zero if you want.  If the card locks up, you'll
+ * need to keep this set.  It works around a bug in early revs of the
+ * Rage 128 chipset, where the CCE would read 32 dwords past the end of
+ * the ring buffer before wrapping around.
+ */
+#define R128_BROKEN_CCE	1
+
 #define ADVANCE_RING() do {						\
 	if ( R128_VERBOSE ) {						\
-		DRM_INFO( "ADVANCE_RING() tail=0x%06x wr=0x%06x\n",	\
+		DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",	\
 			  write, dev_priv->ring.tail );			\
 	}								\
-	if ( write < 32 ) {						\
+	if ( R128_BROKEN_CCE && write < 32 ) {				\
 		memcpy( dev_priv->ring.end,				\
 			dev_priv->ring.start,				\
 			write * sizeof(u32) );				\
@@ -460,10 +541,8 @@
 		DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",		\
 			   (unsigned int)(x), write );			\
 	}								\
-	ring[write++] = x;						\
+	ring[write++] = cpu_to_le32( x );				\
 	write &= tail_mask;						\
 } while (0)
-
-#define R128_PERFORMANCE_BOXES	0
 
 #endif /* __R128_DRV_H__ */
diff -urN linux-2.4.8-pre6/drivers/char/drm/r128_state.c linux/drivers/char/drm/r128_state.c
--- linux-2.4.8-pre6/drivers/char/drm/r128_state.c	Thu Jan  4 13:03:20 2001
+++ linux/drivers/char/drm/r128_state.c	Mon Dec  3 22:59:45 2001
@@ -25,13 +25,14 @@
  *
  * Authors:
  *    Gareth Hughes <gareth@valinux.com>
- *
  */
 
 #define __NO_VERSION__
+#include "r128.h"
 #include "drmP.h"
 #include "r128_drv.h"
 #include "drm.h"
+#include <linux/delay.h>
 
 
 /* ================================================================
@@ -181,14 +182,14 @@
 	RING_LOCALS;
 	DRM_DEBUG( "    %s\n", __FUNCTION__ );
 
-	BEGIN_RING( 7 + R128_TEX_MAXLEVELS );
+	BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS );
 
 	OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
-			       2 + R128_TEX_MAXLEVELS ) );
+			       2 + R128_MAX_TEXTURE_LEVELS ) );
 	OUT_RING( tex->tex_cntl );
 	OUT_RING( tex->tex_combine_cntl );
 	OUT_RING( ctx->tex_size_pitch_c );
-	for ( i = 0 ; i < R128_TEX_MAXLEVELS ; i++ ) {
+	for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
 		OUT_RING( tex->tex_offset[i] );
 	}
 
@@ -207,13 +208,13 @@
 	RING_LOCALS;
 	DRM_DEBUG( "    %s\n", __FUNCTION__ );
 
-	BEGIN_RING( 5 + R128_TEX_MAXLEVELS );
+	BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS );
 
 	OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
-			       1 + R128_TEX_MAXLEVELS ) );
+			       1 + R128_MAX_TEXTURE_LEVELS ) );
 	OUT_RING( tex->tex_cntl );
 	OUT_RING( tex->tex_combine_cntl );
-	for ( i = 0 ; i < R128_TEX_MAXLEVELS ; i++ ) {
+	for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
 		OUT_RING( tex->tex_offset[i] );
 	}
 
@@ -310,13 +311,13 @@
 	BEGIN_RING( 6 );
 
 	OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
-	OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
-		  | R128_GMC_BRUSH_SOLID_COLOR
-		  | fb_bpp
-		  | R128_GMC_SRC_DATATYPE_COLOR
-		  | R128_ROP3_P
-		  | R128_GMC_CLR_CMP_CNTL_DIS
-		  | R128_GMC_AUX_CLIP_DIS );
+	OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+		  R128_GMC_BRUSH_SOLID_COLOR |
+		  fb_bpp |
+		  R128_GMC_SRC_DATATYPE_COLOR |
+		  R128_ROP3_P |
+		  R128_GMC_CLR_CMP_CNTL_DIS |
+		  R128_GMC_AUX_CLIP_DIS );
 
 	OUT_RING( (pitch << 21) | (offset >> 5) );
 	OUT_RING( color );
@@ -360,42 +361,23 @@
 }
 
 static void r128_cce_dispatch_clear( drm_device_t *dev,
-				     unsigned int flags,
-				     int cx, int cy, int cw, int ch,
-				     unsigned int clear_color,
-				     unsigned int clear_depth )
+				     drm_r128_clear_t *clear )
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
 	drm_clip_rect_t *pbox = sarea_priv->boxes;
-	u32 fb_bpp, depth_bpp;
+	unsigned int flags = clear->flags;
 	int i;
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	r128_update_ring_snapshot( dev_priv );
+	if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
+		unsigned int tmp = flags;
 
-	switch ( dev_priv->fb_bpp ) {
-	case 16:
-		fb_bpp = R128_GMC_DST_16BPP;
-		break;
-	case 32:
-		fb_bpp = R128_GMC_DST_32BPP;
-		break;
-	default:
-		return;
-	}
-	switch ( dev_priv->depth_bpp ) {
-	case 16:
-		depth_bpp = R128_GMC_DST_16BPP;
-		break;
-	case 24:
-	case 32:
-		depth_bpp = R128_GMC_DST_32BPP;
-		break;
-	default:
-		return;
+		flags &= ~(R128_FRONT | R128_BACK);
+		if ( tmp & R128_FRONT ) flags |= R128_BACK;
+		if ( tmp & R128_BACK )  flags |= R128_FRONT;
 	}
 
 	for ( i = 0 ; i < nbox ; i++ ) {
@@ -412,7 +394,7 @@
 			BEGIN_RING( 2 );
 
 			OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
-			OUT_RING( sarea_priv->context_state.plane_3d_mask_c );
+			OUT_RING( clear->color_mask );
 
 			ADVANCE_RING();
 		}
@@ -421,16 +403,16 @@
 			BEGIN_RING( 6 );
 
 			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
-			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
-				  | R128_GMC_BRUSH_SOLID_COLOR
-				  | fb_bpp
-				  | R128_GMC_SRC_DATATYPE_COLOR
-				  | R128_ROP3_P
-				  | R128_GMC_CLR_CMP_CNTL_DIS
-				  | R128_GMC_AUX_CLIP_DIS );
+			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+				  R128_GMC_BRUSH_SOLID_COLOR |
+				  (dev_priv->color_fmt << 8) |
+				  R128_GMC_SRC_DATATYPE_COLOR |
+				  R128_ROP3_P |
+				  R128_GMC_CLR_CMP_CNTL_DIS |
+				  R128_GMC_AUX_CLIP_DIS );
 
 			OUT_RING( dev_priv->front_pitch_offset_c );
-			OUT_RING( clear_color );
+			OUT_RING( clear->clear_color );
 
 			OUT_RING( (x << 16) | y );
 			OUT_RING( (w << 16) | h );
@@ -442,16 +424,16 @@
 			BEGIN_RING( 6 );
 
 			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
-			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
-				  | R128_GMC_BRUSH_SOLID_COLOR
-				  | fb_bpp
-				  | R128_GMC_SRC_DATATYPE_COLOR
-				  | R128_ROP3_P
-				  | R128_GMC_CLR_CMP_CNTL_DIS
-				  | R128_GMC_AUX_CLIP_DIS );
+			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+				  R128_GMC_BRUSH_SOLID_COLOR |
+				  (dev_priv->color_fmt << 8) |
+				  R128_GMC_SRC_DATATYPE_COLOR |
+				  R128_ROP3_P |
+				  R128_GMC_CLR_CMP_CNTL_DIS |
+				  R128_GMC_AUX_CLIP_DIS );
 
 			OUT_RING( dev_priv->back_pitch_offset_c );
-			OUT_RING( clear_color );
+			OUT_RING( clear->clear_color );
 
 			OUT_RING( (x << 16) | y );
 			OUT_RING( (w << 16) | h );
@@ -463,17 +445,17 @@
 			BEGIN_RING( 6 );
 
 			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
-			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
-				  | R128_GMC_BRUSH_SOLID_COLOR
-				  | depth_bpp
-				  | R128_GMC_SRC_DATATYPE_COLOR
-				  | R128_ROP3_P
-				  | R128_GMC_CLR_CMP_CNTL_DIS
-				  | R128_GMC_AUX_CLIP_DIS
-				  | R128_GMC_WR_MSK_DIS );
+			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+				  R128_GMC_BRUSH_SOLID_COLOR |
+				  (dev_priv->depth_fmt << 8) |
+				  R128_GMC_SRC_DATATYPE_COLOR |
+				  R128_ROP3_P |
+				  R128_GMC_CLR_CMP_CNTL_DIS |
+				  R128_GMC_AUX_CLIP_DIS |
+				  R128_GMC_WR_MSK_DIS );
 
 			OUT_RING( dev_priv->depth_pitch_offset_c );
-			OUT_RING( clear_depth );
+			OUT_RING( clear->clear_depth );
 
 			OUT_RING( (x << 16) | y );
 			OUT_RING( (w << 16) | h );
@@ -489,29 +471,16 @@
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int nbox = sarea_priv->nbox;
 	drm_clip_rect_t *pbox = sarea_priv->boxes;
-	u32 fb_bpp;
 	int i;
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	r128_update_ring_snapshot( dev_priv );
-
 #if R128_PERFORMANCE_BOXES
 	/* Do some trivial performance monitoring...
 	 */
 	r128_cce_performance_boxes( dev_priv );
 #endif
 
-	switch ( dev_priv->fb_bpp ) {
-	case 16:
-		fb_bpp = R128_GMC_DST_16BPP;
-		break;
-	case 32:
-	default:
-		fb_bpp = R128_GMC_DST_32BPP;
-		break;
-	}
-
 	for ( i = 0 ; i < nbox ; i++ ) {
 		int x = pbox[i].x1;
 		int y = pbox[i].y1;
@@ -521,16 +490,16 @@
 		BEGIN_RING( 7 );
 
 		OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
-		OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL
-			  | R128_GMC_DST_PITCH_OFFSET_CNTL
-			  | R128_GMC_BRUSH_NONE
-			  | fb_bpp
-			  | R128_GMC_SRC_DATATYPE_COLOR
-			  | R128_ROP3_S
-			  | R128_DP_SRC_SOURCE_MEMORY
-			  | R128_GMC_CLR_CMP_CNTL_DIS
-			  | R128_GMC_AUX_CLIP_DIS
-			  | R128_GMC_WR_MSK_DIS );
+		OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
+			  R128_GMC_DST_PITCH_OFFSET_CNTL |
+			  R128_GMC_BRUSH_NONE |
+			  (dev_priv->color_fmt << 8) |
+			  R128_GMC_SRC_DATATYPE_COLOR |
+			  R128_ROP3_S |
+			  R128_DP_SRC_SOURCE_MEMORY |
+			  R128_GMC_CLR_CMP_CNTL_DIS |
+			  R128_GMC_AUX_CLIP_DIS |
+			  R128_GMC_WR_MSK_DIS );
 
 		OUT_RING( dev_priv->back_pitch_offset_c );
 		OUT_RING( dev_priv->front_pitch_offset_c );
@@ -556,6 +525,47 @@
 	ADVANCE_RING();
 }
 
+static void r128_cce_dispatch_flip( drm_device_t *dev )
+{
+	drm_r128_private_t *dev_priv = dev->dev_private;
+	RING_LOCALS;
+	DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
+
+#if R128_PERFORMANCE_BOXES
+	/* Do some trivial performance monitoring...
+	 */
+	r128_cce_performance_boxes( dev_priv );
+#endif
+
+	BEGIN_RING( 4 );
+
+	R128_WAIT_UNTIL_PAGE_FLIPPED();
+	OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) );
+
+	if ( dev_priv->current_page == 0 ) {
+		OUT_RING( dev_priv->back_offset );
+		dev_priv->current_page = 1;
+	} else {
+		OUT_RING( dev_priv->front_offset );
+		dev_priv->current_page = 0;
+	}
+
+	ADVANCE_RING();
+
+	/* Increment the frame counter.  The client-side 3D driver must
+	 * throttle the framerate by waiting for this value before
+	 * performing the swapbuffer ioctl.
+	 */
+	dev_priv->sarea_priv->last_frame++;
+
+	BEGIN_RING( 2 );
+
+	OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
+	OUT_RING( dev_priv->sarea_priv->last_frame );
+
+	ADVANCE_RING();
+}
+
 static void r128_cce_dispatch_vertex( drm_device_t *dev,
 				      drm_buf_t *buf )
 {
@@ -563,7 +573,7 @@
 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int format = sarea_priv->vc_format;
-	int offset = dev_priv->buffers->offset + buf->offset - dev->agp->base;
+	int offset = buf->bus_address;
 	int size = buf->used;
 	int prim = buf_priv->prim;
 	int i = 0;
@@ -571,8 +581,6 @@
 	DRM_DEBUG( "%s: buf=%d nbox=%d\n",
 		   __FUNCTION__, buf->idx, sarea_priv->nbox );
 
-	r128_update_ring_snapshot( dev_priv );
-
 	if ( 0 )
 		r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
 
@@ -626,22 +634,10 @@
 
 	dev_priv->sarea_priv->last_dispatch++;
 
-#if 0
-	if ( dev_priv->submit_age == R128_MAX_VB_AGE ) {
-		ret = r128_do_cce_idle( dev_priv );
-		if ( ret < 0 ) return ret;
-		dev_priv->submit_age = 0;
-		r128_freelist_reset( dev );
-	}
-#endif
-
 	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
 	sarea_priv->nbox = 0;
 }
 
-
-
-
 static void r128_cce_dispatch_indirect( drm_device_t *dev,
 					drm_buf_t *buf,
 					int start, int end )
@@ -652,11 +648,8 @@
 	DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
 		   buf->idx, start, end );
 
-	r128_update_ring_snapshot( dev_priv );
-
 	if ( start != end ) {
-		int offset = (dev_priv->buffers->offset - dev->agp->base
-			      + buf->offset + start);
+		int offset = buf->bus_address + start;
 		int dwords = (end - start + 3) / sizeof(u32);
 
 		/* Indirect buffer data must be an even number of
@@ -667,7 +660,7 @@
 			u32 *data = (u32 *)
 				((char *)dev_priv->buffers->handle
 				 + buf->offset + start);
-			data[dwords++] = R128_CCE_PACKET2;
+			data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
 		}
 
 		buf_priv->dispatched = 1;
@@ -700,15 +693,6 @@
 	}
 
 	dev_priv->sarea_priv->last_dispatch++;
-
-#if 0
-	if ( dev_priv->submit_age == R128_MAX_VB_AGE ) {
-		ret = r128_do_cce_idle( dev_priv );
-		if ( ret < 0 ) return ret;
-		dev_priv->submit_age = 0;
-		r128_freelist_reset( dev );
-	}
-#endif
 }
 
 static void r128_cce_dispatch_indices( drm_device_t *dev,
@@ -720,7 +704,7 @@
 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int format = sarea_priv->vc_format;
-	int offset = dev_priv->buffers->offset - dev->agp->base;
+	int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
 	int prim = buf_priv->prim;
 	u32 *data;
 	int dwords;
@@ -728,8 +712,6 @@
 	RING_LOCALS;
 	DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
 
-	r128_update_ring_snapshot( dev_priv );
-
 	if ( 0 )
 		r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
 
@@ -745,16 +727,21 @@
 		data = (u32 *)((char *)dev_priv->buffers->handle
 			       + buf->offset + start);
 
-		data[0] = CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
+		data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
+						    dwords-2 ) );
 
-		data[1] = offset;
-		data[2] = R128_MAX_VB_VERTS;
-		data[3] = format;
-		data[4] = (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
-			   (count << 16));
+		data[1] = cpu_to_le32( offset );
+		data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
+		data[3] = cpu_to_le32( format );
+		data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
+					(count << 16)) );
 
 		if ( count & 0x1 ) {
+#ifdef __LITTLE_ENDIAN
 			data[dwords-1] &= 0x0000ffff;
+#else
+			data[dwords-1] &= 0xffff0000;
+#endif
 		}
 
 		do {
@@ -789,15 +776,6 @@
 
 	dev_priv->sarea_priv->last_dispatch++;
 
-#if 0
-	if ( dev_priv->submit_age == R128_MAX_VB_AGE ) {
-		ret = r128_do_cce_idle( dev_priv );
-		if ( ret < 0 ) return ret;
-		dev_priv->submit_age = 0;
-		r128_freelist_reset( dev );
-	}
-#endif
-
 	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
 	sarea_priv->nbox = 0;
 }
@@ -814,20 +792,22 @@
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	r128_update_ring_snapshot( dev_priv );
-
 	/* The compiler won't optimize away a division by a variable,
 	 * even if the only legal values are powers of two.  Thus, we'll
 	 * use a shift instead.
 	 */
 	switch ( blit->format ) {
+	case R128_DATATYPE_ARGB8888:
+		dword_shift = 0;
+		break;
 	case R128_DATATYPE_ARGB1555:
 	case R128_DATATYPE_RGB565:
 	case R128_DATATYPE_ARGB4444:
 		dword_shift = 1;
 		break;
-	case R128_DATATYPE_ARGB8888:
-		dword_shift = 0;
+	case R128_DATATYPE_CI8:
+	case R128_DATATYPE_RGB8:
+		dword_shift = 2;
 		break;
 	default:
 		DRM_ERROR( "invalid blit format %d\n", blit->format );
@@ -867,23 +847,23 @@
 
 	data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
 
-	data[0] = CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 );
-	data[1] = ( R128_GMC_DST_PITCH_OFFSET_CNTL
-		    | R128_GMC_BRUSH_NONE
-		    | (blit->format << 8)
-		    | R128_GMC_SRC_DATATYPE_COLOR
-		    | R128_ROP3_S
-		    | R128_DP_SRC_SOURCE_HOST_DATA
-		    | R128_GMC_CLR_CMP_CNTL_DIS
-		    | R128_GMC_AUX_CLIP_DIS
-		    | R128_GMC_WR_MSK_DIS );
-
-	data[2] = (blit->pitch << 21) | (blit->offset >> 5);
-	data[3] = 0xffffffff;
-	data[4] = 0xffffffff;
-	data[5] = (blit->y << 16) | blit->x;
-	data[6] = (blit->height << 16) | blit->width;
-	data[7] = dwords;
+	data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
+	data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
+				R128_GMC_BRUSH_NONE |
+				(blit->format << 8) |
+				R128_GMC_SRC_DATATYPE_COLOR |
+				R128_ROP3_S |
+				R128_DP_SRC_SOURCE_HOST_DATA |
+				R128_GMC_CLR_CMP_CNTL_DIS |
+				R128_GMC_AUX_CLIP_DIS |
+				R128_GMC_WR_MSK_DIS) );
+
+	data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
+	data[3] = cpu_to_le32( 0xffffffff );
+	data[4] = cpu_to_le32( 0xffffffff );
+	data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
+	data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
+	data[7] = cpu_to_le32( dwords );
 
 	buf->used = (dwords + 8) * sizeof(u32);
 
@@ -918,25 +898,10 @@
 	int count, x, y;
 	u32 *buffer;
 	u8 *mask;
-	u32 depth_bpp;
 	int i;
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	r128_update_ring_snapshot( dev_priv );
-
-	switch ( dev_priv->depth_bpp ) {
-	case 16:
-		depth_bpp = R128_GMC_DST_16BPP;
-		break;
-	case 24:
-	case 32:
-		depth_bpp = R128_GMC_DST_32BPP;
-		break;
-	default:
-		return -EINVAL;
-	}
-
 	count = depth->n;
 	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
 		return -EFAULT;
@@ -945,7 +910,7 @@
 		return -EFAULT;
 	}
 
-	buffer = kmalloc( depth->n * sizeof(u32), 0 );
+	buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL );
 	if ( buffer == NULL )
 		return -ENOMEM;
 	if ( copy_from_user( buffer, depth->buffer,
@@ -955,7 +920,7 @@
 	}
 
 	if ( depth->mask ) {
-		mask = kmalloc( depth->n * sizeof(u8), 0 );
+		mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL );
 		if ( mask == NULL ) {
 			kfree( buffer );
 			return -ENOMEM;
@@ -971,15 +936,14 @@
 			if ( mask[i] ) {
 				BEGIN_RING( 6 );
 
-				OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI,
-						       4 ) );
-				OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
-					  | R128_GMC_BRUSH_SOLID_COLOR
-					  | depth_bpp
-					  | R128_GMC_SRC_DATATYPE_COLOR
-					  | R128_ROP3_P
-					  | R128_GMC_CLR_CMP_CNTL_DIS
-					  | R128_GMC_WR_MSK_DIS );
+				OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+				OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+					  R128_GMC_BRUSH_SOLID_COLOR |
+					  (dev_priv->depth_fmt << 8) |
+					  R128_GMC_SRC_DATATYPE_COLOR |
+					  R128_ROP3_P |
+					  R128_GMC_CLR_CMP_CNTL_DIS |
+					  R128_GMC_WR_MSK_DIS );
 
 				OUT_RING( dev_priv->depth_pitch_offset_c );
 				OUT_RING( buffer[i] );
@@ -997,13 +961,13 @@
 			BEGIN_RING( 6 );
 
 			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
-			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
-				  | R128_GMC_BRUSH_SOLID_COLOR
-				  | depth_bpp
-				  | R128_GMC_SRC_DATATYPE_COLOR
-				  | R128_ROP3_P
-				  | R128_GMC_CLR_CMP_CNTL_DIS
-				  | R128_GMC_WR_MSK_DIS );
+			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+				  R128_GMC_BRUSH_SOLID_COLOR |
+				  (dev_priv->depth_fmt << 8) |
+				  R128_GMC_SRC_DATATYPE_COLOR |
+				  R128_ROP3_P |
+				  R128_GMC_CLR_CMP_CNTL_DIS |
+				  R128_GMC_WR_MSK_DIS );
 
 			OUT_RING( dev_priv->depth_pitch_offset_c );
 			OUT_RING( buffer[i] );
@@ -1027,32 +991,17 @@
 	int count, *x, *y;
 	u32 *buffer;
 	u8 *mask;
-	u32 depth_bpp;
 	int i;
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	r128_update_ring_snapshot( dev_priv );
-
-	switch ( dev_priv->depth_bpp ) {
-	case 16:
-		depth_bpp = R128_GMC_DST_16BPP;
-		break;
-	case 24:
-	case 32:
-		depth_bpp = R128_GMC_DST_32BPP;
-		break;
-	default:
-		return -EINVAL;
-	}
-
 	count = depth->n;
 
-	x = kmalloc( count * sizeof(*x), 0 );
+	x = kmalloc( count * sizeof(*x), GFP_KERNEL );
 	if ( x == NULL ) {
 		return -ENOMEM;
 	}
-	y = kmalloc( count * sizeof(*y), 0 );
+	y = kmalloc( count * sizeof(*y), GFP_KERNEL );
 	if ( y == NULL ) {
 		kfree( x );
 		return -ENOMEM;
@@ -1068,7 +1017,7 @@
 		return -EFAULT;
 	}
 
-	buffer = kmalloc( depth->n * sizeof(u32), 0 );
+	buffer = kmalloc( depth->n * sizeof(u32), GFP_KERNEL );
 	if ( buffer == NULL ) {
 		kfree( x );
 		kfree( y );
@@ -1083,7 +1032,7 @@
 	}
 
 	if ( depth->mask ) {
-		mask = kmalloc( depth->n * sizeof(u8), 0 );
+		mask = kmalloc( depth->n * sizeof(u8), GFP_KERNEL );
 		if ( mask == NULL ) {
 			kfree( x );
 			kfree( y );
@@ -1103,15 +1052,14 @@
 			if ( mask[i] ) {
 				BEGIN_RING( 6 );
 
-				OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI,
-						       4 ) );
-				OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
-					  | R128_GMC_BRUSH_SOLID_COLOR
-					  | depth_bpp
-					  | R128_GMC_SRC_DATATYPE_COLOR
-					  | R128_ROP3_P
-					  | R128_GMC_CLR_CMP_CNTL_DIS
-					  | R128_GMC_WR_MSK_DIS );
+				OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
+				OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+					  R128_GMC_BRUSH_SOLID_COLOR |
+					  (dev_priv->depth_fmt << 8) |
+					  R128_GMC_SRC_DATATYPE_COLOR |
+					  R128_ROP3_P |
+					  R128_GMC_CLR_CMP_CNTL_DIS |
+					  R128_GMC_WR_MSK_DIS );
 
 				OUT_RING( dev_priv->depth_pitch_offset_c );
 				OUT_RING( buffer[i] );
@@ -1129,13 +1077,13 @@
 			BEGIN_RING( 6 );
 
 			OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
-			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL
-				  | R128_GMC_BRUSH_SOLID_COLOR
-				  | depth_bpp
-				  | R128_GMC_SRC_DATATYPE_COLOR
-				  | R128_ROP3_P
-				  | R128_GMC_CLR_CMP_CNTL_DIS
-				  | R128_GMC_WR_MSK_DIS );
+			OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
+				  R128_GMC_BRUSH_SOLID_COLOR |
+				  (dev_priv->depth_fmt << 8) |
+				  R128_GMC_SRC_DATATYPE_COLOR |
+				  R128_ROP3_P |
+				  R128_GMC_CLR_CMP_CNTL_DIS |
+				  R128_GMC_WR_MSK_DIS );
 
 			OUT_RING( dev_priv->depth_pitch_offset_c );
 			OUT_RING( buffer[i] );
@@ -1159,24 +1107,9 @@
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	int count, x, y;
-	u32 depth_bpp;
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	r128_update_ring_snapshot( dev_priv );
-
-	switch ( dev_priv->depth_bpp ) {
-	case 16:
-		depth_bpp = R128_GMC_DST_16BPP;
-		break;
-	case 24:
-	case 32:
-		depth_bpp = R128_GMC_DST_32BPP;
-		break;
-	default:
-		return -EINVAL;
-	}
-
 	count = depth->n;
 	if ( copy_from_user( &x, depth->x, sizeof(x) ) ) {
 		return -EFAULT;
@@ -1188,15 +1121,15 @@
 	BEGIN_RING( 7 );
 
 	OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
-	OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL
-		  | R128_GMC_DST_PITCH_OFFSET_CNTL
-		  | R128_GMC_BRUSH_NONE
-		  | depth_bpp
-		  | R128_GMC_SRC_DATATYPE_COLOR
-		  | R128_ROP3_S
-		  | R128_DP_SRC_SOURCE_MEMORY
-		  | R128_GMC_CLR_CMP_CNTL_DIS
-		  | R128_GMC_WR_MSK_DIS );
+	OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
+		  R128_GMC_DST_PITCH_OFFSET_CNTL |
+		  R128_GMC_BRUSH_NONE |
+		  (dev_priv->depth_fmt << 8) |
+		  R128_GMC_SRC_DATATYPE_COLOR |
+		  R128_ROP3_S |
+		  R128_DP_SRC_SOURCE_MEMORY |
+		  R128_GMC_CLR_CMP_CNTL_DIS |
+		  R128_GMC_WR_MSK_DIS );
 
 	OUT_RING( dev_priv->depth_pitch_offset_c );
 	OUT_RING( dev_priv->span_pitch_offset_c );
@@ -1215,35 +1148,20 @@
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 	int count, *x, *y;
-	u32 depth_bpp;
 	int i;
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	r128_update_ring_snapshot( dev_priv );
-
-	switch ( dev_priv->depth_bpp ) {
-	case 16:
-		depth_bpp = R128_GMC_DST_16BPP;
-		break;
-	case 24:
-	case 32:
-		depth_bpp = R128_GMC_DST_32BPP;
-		break;
-	default:
-		return -EINVAL;
-	}
-
 	count = depth->n;
 	if ( count > dev_priv->depth_pitch ) {
 		count = dev_priv->depth_pitch;
 	}
 
-	x = kmalloc( count * sizeof(*x), 0 );
+	x = kmalloc( count * sizeof(*x), GFP_KERNEL );
 	if ( x == NULL ) {
 		return -ENOMEM;
 	}
-	y = kmalloc( count * sizeof(*y), 0 );
+	y = kmalloc( count * sizeof(*y), GFP_KERNEL );
 	if ( y == NULL ) {
 		kfree( x );
 		return -ENOMEM;
@@ -1263,15 +1181,15 @@
 		BEGIN_RING( 7 );
 
 		OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
-		OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL
-			  | R128_GMC_DST_PITCH_OFFSET_CNTL
-			  | R128_GMC_BRUSH_NONE
-			  | depth_bpp
-			  | R128_GMC_SRC_DATATYPE_COLOR
-			  | R128_ROP3_S
-			  | R128_DP_SRC_SOURCE_MEMORY
-			  | R128_GMC_CLR_CMP_CNTL_DIS
-			  | R128_GMC_WR_MSK_DIS );
+		OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
+			  R128_GMC_DST_PITCH_OFFSET_CNTL |
+			  R128_GMC_BRUSH_NONE |
+			  (dev_priv->depth_fmt << 8) |
+			  R128_GMC_SRC_DATATYPE_COLOR |
+			  R128_ROP3_S |
+			  R128_DP_SRC_SOURCE_MEMORY |
+			  R128_GMC_CLR_CMP_CNTL_DIS |
+			  R128_GMC_WR_MSK_DIS );
 
 		OUT_RING( dev_priv->depth_pitch_offset_c );
 		OUT_RING( dev_priv->span_pitch_offset_c );
@@ -1301,11 +1219,9 @@
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	r128_update_ring_snapshot( dev_priv );
-
 	BEGIN_RING( 33 );
 
-	OUT_RING(  CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
+	OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
 	for ( i = 0 ; i < 32 ; i++ ) {
 		OUT_RING( stipple[i] );
 	}
@@ -1328,22 +1244,18 @@
 	drm_r128_clear_t clear;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-	     dev->lock.pid != current->pid ) {
-		DRM_ERROR( "r128_cce_clear called without lock held\n" );
-		return -EINVAL;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( copy_from_user( &clear, (drm_r128_clear_t *) arg,
 			     sizeof(clear) ) )
 		return -EFAULT;
 
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
 	if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
 
-	r128_cce_dispatch_clear( dev, clear.flags,
-				 clear.x, clear.y, clear.w, clear.h,
-				 clear.clear_color, clear.clear_depth );
+	r128_cce_dispatch_clear( dev, &clear );
 
 	/* Make sure we restore the 3D state next time.
 	 */
@@ -1361,20 +1273,20 @@
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||
-	     dev->lock.pid != current->pid ) {
-		DRM_ERROR( "r128_cce_swap called without lock held\n" );
-		return -EINVAL;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
+
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
 	if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
 
-	r128_cce_dispatch_swap( dev );
-
-	/* Make sure we restore the 3D state next time.
-	 */
-	dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+	if ( !dev_priv->page_flipping ) {
+		r128_cce_dispatch_swap( dev );
+		dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
+						R128_UPLOAD_MASKS);
+	} else {
+		r128_cce_dispatch_flip( dev );
+	}
 
 	return 0;
 }
@@ -1390,13 +1302,10 @@
 	drm_r128_buf_priv_t *buf_priv;
 	drm_r128_vertex_t vertex;
 
-	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;
-	}
-	if ( !dev_priv || dev_priv->is_pci ) {
-		DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
 		return -EINVAL;
 	}
 
@@ -1419,6 +1328,9 @@
 		return -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;
 
@@ -1453,13 +1365,10 @@
 	drm_r128_indices_t elts;
 	int count;
 
-	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;
-	}
-	if ( !dev_priv || dev_priv->is_pci ) {
-		DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
 		return -EINVAL;
 	}
 
@@ -1482,6 +1391,9 @@
 		return -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;
 
@@ -1522,13 +1434,10 @@
 	drm_file_t *priv = filp->private_data;
 	drm_device_t *dev = priv->dev;
 	drm_device_dma_t *dma = dev->dma;
+	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_blit_t blit;
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( copy_from_user( &blit, (drm_r128_blit_t *)arg,
 			     sizeof(blit) ) )
@@ -1543,6 +1452,9 @@
 		return -EINVAL;
 	}
 
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+	VB_AGE_TEST_WITH_RETURN( dev_priv );
+
 	return r128_cce_dispatch_blit( dev, &blit );
 }
 
@@ -1551,18 +1463,17 @@
 {
 	drm_file_t *priv = filp->private_data;
 	drm_device_t *dev = priv->dev;
+	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_depth_t depth;
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( copy_from_user( &depth, (drm_r128_depth_t *)arg,
 			     sizeof(depth) ) )
 		return -EFAULT;
 
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
 	switch ( depth.func ) {
 	case R128_WRITE_SPAN:
 		return r128_cce_dispatch_write_span( dev, &depth );
@@ -1582,14 +1493,11 @@
 {
 	drm_file_t *priv = filp->private_data;
 	drm_device_t *dev = priv->dev;
+	drm_r128_private_t *dev_priv = dev->dev_private;
 	drm_r128_stipple_t stipple;
 	u32 mask[32];
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( copy_from_user( &stipple, (drm_r128_stipple_t *)arg,
 			     sizeof(stipple) ) )
@@ -1599,7 +1507,22 @@
 			     32 * sizeof(u32) ) )
 		return -EFAULT;
 
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
 	r128_cce_dispatch_stipple( dev, mask );
 
 	return 0;
+}
+
+int r128_cce_indirect( 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;
+
+	LOCK_TEST_WITH_RETURN( dev );
+
+	/* Indirect buffer firing is not supported at this time.
+	 */
+	return -EINVAL;
 }
diff -urN linux-2.4.8-pre6/drivers/char/drm/radeon.h linux/drivers/char/drm/radeon.h
--- linux-2.4.8-pre6/drivers/char/drm/radeon.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/radeon.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,81 @@
+/* radeon.h -- ATI Radeon DRM template customization -*- linux-c -*-
+ * Created: Wed Feb 14 17:07:34 2001 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_H__
+#define __RADEON_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) radeon_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP		1
+#define __MUST_HAVE_AGP		0
+#define __HAVE_MTRR		1
+#define __HAVE_CTX_BITMAP	1
+#define __HAVE_SG		1
+#define __HAVE_PCI_DMA		1
+
+/* Driver customization:
+ */
+#define DRIVER_PRERELEASE() do {					\
+	if ( dev->dev_private ) {					\
+		drm_radeon_private_t *dev_priv = dev->dev_private;	\
+		if ( dev_priv->page_flipping ) {			\
+			radeon_do_cleanup_pageflip( dev );		\
+		}							\
+	}								\
+} while (0)
+
+#define DRIVER_PRETAKEDOWN() do {					\
+	if ( dev->dev_private ) radeon_do_cleanup_cp( dev );		\
+} while (0)
+
+/* 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 )					\
+	((drm_radeon_private_t *)((dev)->dev_private))->buffers
+
+#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/radeon_bufs.c linux/drivers/char/drm/radeon_bufs.c
--- linux-2.4.8-pre6/drivers/char/drm/radeon_bufs.c	Mon Jul 16 15:13:32 2001
+++ linux/drivers/char/drm/radeon_bufs.c	Wed Dec 31 16:00:00 1969
@@ -1,312 +0,0 @@
-/* radeon_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
- *
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Kevin E. Martin <martin@valinux.com>
- *          Rickard E. (Rik) Faith <faith@valinux.com>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include <linux/config.h>
-#include "drmP.h"
-#include "radeon_drv.h"
-#include "linux/un.h"
-
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-int radeon_addbufs_agp(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_device_dma_t *dma  = dev->dma;
-	drm_buf_desc_t    request;
-	drm_buf_entry_t  *entry;
-	drm_buf_t        *buf;
-	unsigned long     offset;
-	unsigned long     agp_offset;
-	int               count;
-	int               order;
-	int               size;
-	int               alignment;
-	int               page_order;
-	int               total;
-	int               byte_count;
-	int               i;
-
-	if (!dma) return -EINVAL;
-
-	if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
-		return -EFAULT;
-
-	count      = request.count;
-	order      = drm_order(request.size);
-	size       = 1 << order;
-
-	alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
-	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-	total      = PAGE_SIZE << page_order;
-
-	byte_count = 0;
-	agp_offset = dev->agp->base + request.agp_start;
-
-	DRM_DEBUG("count:      %d\n",  count);
-	DRM_DEBUG("order:      %d\n",  order);
-	DRM_DEBUG("size:       %d\n",  size);
-	DRM_DEBUG("agp_offset: %ld\n", agp_offset);
-	DRM_DEBUG("alignment:  %d\n",  alignment);
-	DRM_DEBUG("page_order: %d\n",  page_order);
-	DRM_DEBUG("total:      %d\n",  total);
-
-	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
-	if (dev->queue_count) return -EBUSY; /* Not while in use */
-
-	spin_lock(&dev->count_lock);
-	if (dev->buf_use) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	atomic_inc(&dev->buf_alloc);
-	spin_unlock(&dev->count_lock);
-
-	down(&dev->struct_sem);
-	entry = &dma->bufs[order];
-	if (entry->buf_count) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM; /* May only call once for each order */
-	}
-
-	/* Might be too low a limit. XFree folks need to fix this properly */
-	
-	if(count < 0 || count > 4096)
-	{
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -EINVAL;
-	}
-		
-	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-				   DRM_MEM_BUFS);
-	if (!entry->buflist) {
-		up(&dev->struct_sem);
-		atomic_dec(&dev->buf_alloc);
-		return -ENOMEM;
-	}
-	memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
-	entry->buf_size   = size;
-	entry->page_order = page_order;
-	offset            = 0;
-
-	for (offset = 0;
-	     entry->buf_count < count;
-	     offset += alignment, ++entry->buf_count) {
-		buf          = &entry->buflist[entry->buf_count];
-		buf->idx     = dma->buf_count + entry->buf_count;
-		buf->total   = alignment;
-		buf->order   = order;
-		buf->used    = 0;
-		buf->offset  = (dma->byte_count + offset);
-		buf->address = (void *)(agp_offset + offset);
-		buf->next    = NULL;
-		buf->waiting = 0;
-		buf->pending = 0;
-		init_waitqueue_head(&buf->dma_wait);
-		buf->pid     = 0;
-
-		buf->dev_priv_size = sizeof(drm_radeon_buf_priv_t);
-		buf->dev_private   = drm_alloc(sizeof(drm_radeon_buf_priv_t),
-					       DRM_MEM_BUFS);
-                if (!buf->dev_private) {
-                        up(&dev->struct_sem);
-                        atomic_dec(&dev->buf_alloc);
-                        return -ENOMEM;
-                }
-		memset(buf->dev_private, 0, buf->dev_priv_size);
-
-#if DRM_DMA_HISTOGRAM
-		buf->time_queued     = 0;
-		buf->time_dispatched = 0;
-		buf->time_completed  = 0;
-		buf->time_freed      = 0;
-#endif
-
-		byte_count += PAGE_SIZE << page_order;
-
-		DRM_DEBUG("buffer %d @ %p\n",
-			  entry->buf_count, buf->address);
-	}
-
-	DRM_DEBUG("byte_count: %d\n", byte_count);
-
-	dma->buflist = drm_realloc(dma->buflist,
-				   dma->buf_count * sizeof(*dma->buflist),
-				   (dma->buf_count + entry->buf_count)
-				   * sizeof(*dma->buflist),
-				   DRM_MEM_BUFS);
-	for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
-		dma->buflist[i] = &entry->buflist[i - dma->buf_count];
-
-	dma->buf_count  += entry->buf_count;
-	dma->byte_count += byte_count;
-
-	drm_freelist_create(&entry->freelist, entry->buf_count);
-	for (i = 0; i < entry->buf_count; i++) {
-		drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
-	}
-
-	up(&dev->struct_sem);
-
-	request.count = entry->buf_count;
-	request.size  = size;
-
-	if (copy_to_user((drm_buf_desc_t *)arg, &request, sizeof(request)))
-		return -EFAULT;
-
-	dma->flags = _DRM_DMA_USE_AGP;
-
-	atomic_dec(&dev->buf_alloc);
-	return 0;
-}
-#endif
-
-int radeon_addbufs(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_private_t	*dev_priv	= dev->dev_private;
-	drm_buf_desc_t		request;
-
-	if (!dev_priv || dev_priv->is_pci) return -EINVAL;
-
-	if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
-		return -EFAULT;
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	if (request.flags & _DRM_AGP_BUFFER)
-		return radeon_addbufs_agp(inode, filp, cmd, arg);
-	else
-#endif
-		return -EINVAL;
-}
-
-int radeon_mapbufs(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_private_t	*dev_priv	= dev->dev_private;
-	drm_device_dma_t	*dma		= dev->dma;
-	int			 retcode	= 0;
-	const int		 zero		= 0;
-	unsigned long		 virtual;
-	unsigned long		 address;
-	drm_buf_map_t		 request;
-	int			 i;
-
-	if (!dma || !dev_priv || dev_priv->is_pci) return -EINVAL;
-
-	DRM_DEBUG("\n");
-
-	spin_lock(&dev->count_lock);
-	if (atomic_read(&dev->buf_alloc)) {
-		spin_unlock(&dev->count_lock);
-		return -EBUSY;
-	}
-	++dev->buf_use;		/* Can't allocate more after this call */
-	spin_unlock(&dev->count_lock);
-
-	if (copy_from_user(&request, (drm_buf_map_t *)arg, sizeof(request)))
-		return -EFAULT;
-
-	if (request.count >= dma->buf_count) {
-		if (dma->flags & _DRM_DMA_USE_AGP) {
-			drm_map_t *map;
-
-			map = dev_priv->buffers;
-			if (!map) {
-				retcode = -EINVAL;
-				goto done;
-			}
-
-			down_write(&current->mm->mmap_sem);
-			virtual = do_mmap(filp, 0, map->size,
-					  PROT_READ|PROT_WRITE,
-					  MAP_SHARED,
-					  (unsigned long)map->offset);
-			up_write(&current->mm->mmap_sem);
-		} else {
-			down_write(&current->mm->mmap_sem);
-			virtual = do_mmap(filp, 0, dma->byte_count,
-					  PROT_READ|PROT_WRITE, MAP_SHARED, 0);
-			up_write(&current->mm->mmap_sem);
-		}
-		if (virtual > -1024UL) {
-			/* Real error */
-			retcode = (signed long)virtual;
-			goto done;
-		}
-		request.virtual = (void *)virtual;
-
-		for (i = 0; i < dma->buf_count; i++) {
-			if (copy_to_user(&request.list[i].idx,
-					 &dma->buflist[i]->idx,
-					 sizeof(request.list[0].idx))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			if (copy_to_user(&request.list[i].total,
-					 &dma->buflist[i]->total,
-					 sizeof(request.list[0].total))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			if (copy_to_user(&request.list[i].used,
-					 &zero,
-					 sizeof(zero))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-			address = virtual + dma->buflist[i]->offset;
-			if (copy_to_user(&request.list[i].address,
-					 &address,
-					 sizeof(address))) {
-				retcode = -EFAULT;
-				goto done;
-			}
-		}
-	}
- done:
-	request.count = dma->buf_count;
-	DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
-
-	if (copy_to_user((drm_buf_map_t *)arg, &request, sizeof(request)))
-		return -EFAULT;
-
-	return retcode;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/radeon_context.c linux/drivers/char/drm/radeon_context.c
--- linux-2.4.8-pre6/drivers/char/drm/radeon_context.c	Fri Jan 19 13:34:08 2001
+++ linux/drivers/char/drm/radeon_context.c	Wed Dec 31 16:00:00 1969
@@ -1,215 +0,0 @@
-/* radeon_context.c -- IOCTLs for Radeon contexts -*- linux-c -*-
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Kevin E. Martin <martin@valinux.com>
- *         Rickard E. (Rik) Faith <faith@valinux.com>
- *
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include "radeon_drv.h"
-
-extern drm_ctx_t radeon_res_ctx;
-
-static int radeon_alloc_queue(drm_device_t *dev)
-{
-	return drm_ctxbitmap_next(dev);
-}
-
-int radeon_context_switch(drm_device_t *dev, int old, int new)
-{
-        char        buf[64];
-
-        atomic_inc(&dev->total_ctx);
-
-        if (test_and_set_bit(0, &dev->context_flag)) {
-                DRM_ERROR("Reentering -- FIXME\n");
-                return -EBUSY;
-        }
-
-#if DRM_DMA_HISTOGRAM
-        dev->ctx_start = get_cycles();
-#endif
-
-        DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
-        if (new == dev->last_context) {
-                clear_bit(0, &dev->context_flag);
-                return 0;
-        }
-
-        if (drm_flags & DRM_FLAG_NOCTX) {
-                radeon_context_switch_complete(dev, new);
-        } else {
-                sprintf(buf, "C %d %d\n", old, new);
-                drm_write_string(dev, buf);
-        }
-
-        return 0;
-}
-
-int radeon_context_switch_complete(drm_device_t *dev, int new)
-{
-        dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
-        dev->last_switch  = jiffies;
-
-        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-                DRM_ERROR("Lock isn't held after context switch\n");
-        }
-
-				/* If a context switch is ever initiated
-                                   when the kernel holds the lock, release
-                                   that lock here. */
-#if DRM_DMA_HISTOGRAM
-        atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
-                                                      - dev->ctx_start)]);
-
-#endif
-        clear_bit(0, &dev->context_flag);
-        wake_up(&dev->context_wait);
-
-        return 0;
-}
-
-
-int radeon_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
-{
-	drm_ctx_res_t	res;
-	drm_ctx_t	ctx;
-	int		i;
-
-	DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
-	if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
-		return -EFAULT;
-	if (res.count >= DRM_RESERVED_CONTEXTS) {
-		memset(&ctx, 0, sizeof(ctx));
-		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-			ctx.handle = i;
-			if (copy_to_user(&res.contexts[i], &i, sizeof(i)))
-				return -EFAULT;
-		}
-	}
-	res.count = DRM_RESERVED_CONTEXTS;
-	if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
-		return -EFAULT;
-	return 0;
-}
-
-
-int radeon_addctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	if ((ctx.handle = radeon_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
-				/* Skip kernel's context and get a new one. */
-		ctx.handle = radeon_alloc_queue(dev);
-	}
-	DRM_DEBUG("%d\n", ctx.handle);
-	if (ctx.handle == -1) {
-		DRM_DEBUG("Not enough free contexts.\n");
-				/* Should this return -EBUSY instead? */
-		return -ENOMEM;
-	}
-
-	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int radeon_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
-{
-	drm_ctx_t ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
-		return -EFAULT;
-	if (ctx.flags==_DRM_CONTEXT_PRESERVED)
-		radeon_res_ctx.handle=ctx.handle;
-	return 0;
-}
-
-int radeon_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
-{
-	drm_ctx_t ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
-		return -EFAULT;
-	/* This is 0, because we don't hanlde any context flags */
-	ctx.flags = 0;
-	if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int radeon_switchctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	return radeon_context_switch(dev, dev->last_context, ctx.handle);
-}
-
-int radeon_newctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	radeon_context_switch_complete(dev, ctx.handle);
-
-	return 0;
-}
-
-int radeon_rmctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	drm_ctxbitmap_free(dev, ctx.handle);
-
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/radeon_cp.c linux/drivers/char/drm/radeon_cp.c
--- linux-2.4.8-pre6/drivers/char/drm/radeon_cp.c	Fri Jan 19 13:34:08 2001
+++ linux/drivers/char/drm/radeon_cp.c	Mon Dec  3 22:59:45 2001
@@ -24,12 +24,12 @@
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Kevin E. Martin <martin@valinux.com>
- *   Gareth Hughes <gareth@valinux.com>
- *
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #define __NO_VERSION__
+#include "radeon.h"
 #include "drmP.h"
 #include "radeon_drv.h"
 
@@ -38,6 +38,12 @@
 
 #define RADEON_FIFO_DEBUG	0
 
+#if defined(__alpha__)
+# define PCIGART_ENABLED
+#else
+# undef PCIGART_ENABLED
+#endif
+
 
 /* CP microcode (from ATI) */
 static u32 radeon_cp_microcode[][2] = {
@@ -300,26 +306,6 @@
 };
 
 
-#define DO_IOREMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size)
-
-#define DO_IOREMAPFREE(_m)						\
-	do {								\
-		if ((_m)->handle && (_m)->size)				\
-			drm_ioremapfree((_m)->handle, (_m)->size);	\
-	} while (0)
-
-#define DO_FIND_MAP(_m, _o)						\
-	do {								\
-		int _i;							\
-		for (_i = 0; _i < dev->map_count; _i++) {		\
-			if (dev->maplist[_i]->offset == _o) {		\
-				_m = dev->maplist[_i];			\
-				break;					\
-			}						\
-		}							\
-	} while (0)
-
-
 int RADEON_READ_PLL(drm_device_t *dev, int addr)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -338,6 +324,16 @@
 		(unsigned int)RADEON_READ( RADEON_CP_RB_RPTR ) );
 	printk( "CP_RB_WTPR = 0x%08x\n",
 		(unsigned int)RADEON_READ( RADEON_CP_RB_WPTR ) );
+	printk( "AIC_CNTL = 0x%08x\n",
+		(unsigned int)RADEON_READ( RADEON_AIC_CNTL ) );
+	printk( "AIC_STAT = 0x%08x\n",
+		(unsigned int)RADEON_READ( RADEON_AIC_STAT ) );
+	printk( "AIC_PT_BASE = 0x%08x\n",
+		(unsigned int)RADEON_READ( RADEON_AIC_PT_BASE ) );
+	printk( "TLB_ADDR = 0x%08x\n",
+		(unsigned int)RADEON_READ( RADEON_AIC_TLB_ADDR ) );
+	printk( "TLB_DATA = 0x%08x\n",
+		(unsigned int)RADEON_READ( RADEON_AIC_TLB_DATA ) );
 }
 #endif
 
@@ -421,6 +417,7 @@
 static void radeon_cp_load_microcode( drm_radeon_private_t *dev_priv )
 {
 	int i;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
 	radeon_do_wait_for_idle( dev_priv );
 
@@ -439,6 +436,7 @@
  */
 static void radeon_do_cp_flush( drm_radeon_private_t *dev_priv )
 {
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 #if 0
 	u32 tmp;
 
@@ -452,6 +450,7 @@
 int radeon_do_cp_idle( drm_radeon_private_t *dev_priv )
 {
 	RING_LOCALS;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
 	BEGIN_RING( 6 );
 
@@ -469,6 +468,7 @@
 static void radeon_do_cp_start( drm_radeon_private_t *dev_priv )
 {
 	RING_LOCALS;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
 	radeon_do_wait_for_idle( dev_priv );
 
@@ -492,6 +492,7 @@
 static void radeon_do_cp_reset( drm_radeon_private_t *dev_priv )
 {
 	u32 cur_read_ptr;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
 	cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
 	RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
@@ -505,6 +506,8 @@
  */
 static void radeon_do_cp_stop( drm_radeon_private_t *dev_priv )
 {
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
 	RADEON_WRITE( RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS );
 
 	dev_priv->cp_running = 0;
@@ -523,8 +526,13 @@
 	clock_cntl_index = RADEON_READ( RADEON_CLOCK_CNTL_INDEX );
 	mclk_cntl = RADEON_READ_PLL( dev, RADEON_MCLK_CNTL );
 
-	/* FIXME: remove magic number here and in radeon ddx driver!!! */
-	RADEON_WRITE_PLL( RADEON_MCLK_CNTL, mclk_cntl | 0x003f00000 );
+	RADEON_WRITE_PLL( RADEON_MCLK_CNTL, ( mclk_cntl |
+					      RADEON_FORCEON_MCLKA |
+					      RADEON_FORCEON_MCLKB |
+ 					      RADEON_FORCEON_YCLKA |
+					      RADEON_FORCEON_YCLKB |
+					      RADEON_FORCEON_MC |
+					      RADEON_FORCEON_AIC ) );
 
 	rbbm_soft_reset = RADEON_READ( RADEON_RBBM_SOFT_RESET );
 
@@ -566,23 +574,33 @@
 	return 0;
 }
 
-static void radeon_cp_init_ring_buffer( drm_device_t *dev )
+static void radeon_cp_init_ring_buffer( drm_device_t *dev,
+				        drm_radeon_private_t *dev_priv )
 {
-	drm_radeon_private_t *dev_priv = dev->dev_private;
 	u32 ring_start, cur_read_ptr;
 	u32 tmp;
 
 	/* Initialize the memory controller */
 	RADEON_WRITE( RADEON_MC_FB_LOCATION,
 		      (dev_priv->agp_vm_start - 1) & 0xffff0000 );
-	RADEON_WRITE( RADEON_MC_AGP_LOCATION,
-		      (((dev_priv->agp_vm_start - 1 +
-			 dev_priv->agp_size) & 0xffff0000) |
-		       (dev_priv->agp_vm_start >> 16)) );
-
-	ring_start = (dev_priv->cp_ring->offset
-		      - dev->agp->base
-		      + dev_priv->agp_vm_start);
+
+	if ( !dev_priv->is_pci ) {
+		RADEON_WRITE( RADEON_MC_AGP_LOCATION,
+			      (((dev_priv->agp_vm_start - 1 +
+				 dev_priv->agp_size) & 0xffff0000) |
+			       (dev_priv->agp_vm_start >> 16)) );
+	}
+
+#if __REALLY_HAVE_AGP
+	if ( !dev_priv->is_pci )
+		ring_start = (dev_priv->cp_ring->offset
+			      - dev->agp->base
+			      + dev_priv->agp_vm_start);
+       else
+#endif
+		ring_start = (dev_priv->cp_ring->offset
+			      - dev->sg->handle
+			      + dev_priv->agp_vm_start);
 
 	RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
 
@@ -595,17 +613,29 @@
 	*dev_priv->ring.head = cur_read_ptr;
 	dev_priv->ring.tail = cur_read_ptr;
 
-	RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset );
+	if ( !dev_priv->is_pci ) {
+		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+			      dev_priv->ring_rptr->offset );
+	} else {
+		drm_sg_mem_t *entry = dev->sg;
+		unsigned long tmp_ofs, page_ofs;
+
+		tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
+		page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+			      virt_to_bus(entry->pagelist[page_ofs]->virtual));
+
+		DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
+			   virt_to_bus(entry->pagelist[page_ofs]->virtual),
+			   entry->handle + tmp_ofs );
+	}
 
 	/* Set ring buffer size */
 	RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
 
 	radeon_do_wait_for_idle( dev_priv );
 
-	/* Turn off PCI GART */
-	tmp = RADEON_READ( RADEON_AIC_CNTL ) & ~RADEON_PCIGART_TRANSLATE_EN;
-	RADEON_WRITE( RADEON_AIC_CNTL, tmp );
-
 	/* Turn on bus mastering */
 	tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
 	RADEON_WRITE( RADEON_BUS_CNTL, tmp );
@@ -621,32 +651,42 @@
 static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 {
 	drm_radeon_private_t *dev_priv;
-        int i;
+	struct list_head *list;
+	u32 tmp;
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	dev_priv = drm_alloc( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
+	dev_priv = DRM(alloc)( sizeof(drm_radeon_private_t), DRM_MEM_DRIVER );
 	if ( dev_priv == NULL )
 		return -ENOMEM;
-	dev->dev_private = (void *)dev_priv;
 
 	memset( dev_priv, 0, sizeof(drm_radeon_private_t) );
 
 	dev_priv->is_pci = init->is_pci;
 
-	/* We don't support PCI cards until PCI GART is implemented.
-	 * Fail here so we can remove all checks for PCI cards around
-	 * the CP ring code.
+#if !defined(PCIGART_ENABLED)
+	/* PCI support is not 100% working, so we disable it here.
 	 */
 	if ( dev_priv->is_pci ) {
-		drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
-		dev->dev_private = NULL;
+		DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
+		dev->dev_private = (void *)dev_priv;
+		radeon_do_cleanup_cp(dev);
+		return -EINVAL;
+	}
+#endif
+
+	if ( dev_priv->is_pci && !dev->sg ) {
+		DRM_ERROR( "PCI GART memory not allocated!\n" );
+		dev->dev_private = (void *)dev_priv;
+		radeon_do_cleanup_cp(dev);
 		return -EINVAL;
 	}
 
 	dev_priv->usec_timeout = init->usec_timeout;
 	if ( dev_priv->usec_timeout < 1 ||
 	     dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
-		drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
-		dev->dev_private = NULL;
+		DRM_DEBUG( "TIMEOUT problem!\n" );
+		dev->dev_private = (void *)dev_priv;
+		radeon_do_cleanup_cp(dev);
 		return -EINVAL;
 	}
 
@@ -662,8 +702,9 @@
 	 */
 	if ( ( init->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
 	     ( init->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
-		drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER );
-		dev->dev_private = NULL;
+		DRM_DEBUG( "BAD cp_mode (%x)!\n", init->cp_mode );
+		dev->dev_private = (void *)dev_priv;
+		radeon_do_cleanup_cp(dev);
 		return -EINVAL;
 	}
 
@@ -722,55 +763,128 @@
 					 RADEON_BFACE_SOLID |
 					 RADEON_FFACE_SOLID |
 					 RADEON_FLAT_SHADE_VTX_LAST |
-
 					 RADEON_DIFFUSE_SHADE_FLAT |
 					 RADEON_ALPHA_SHADE_FLAT |
 					 RADEON_SPECULAR_SHADE_FLAT |
 					 RADEON_FOG_SHADE_FLAT |
-
 					 RADEON_VTX_PIX_CENTER_OGL |
 					 RADEON_ROUND_MODE_TRUNC |
 					 RADEON_ROUND_PREC_8TH_PIX);
 
-	/* FIXME: We want multiple shared areas, including one shared
-	 * only by the X Server and kernel module.
-	 */
-	for ( i = 0 ; i < dev->map_count ; i++ ) {
-		if ( dev->maplist[i]->type == _DRM_SHM ) {
-			dev_priv->sarea = dev->maplist[i];
-			break;
-		}
+	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;
+ 		}
+ 	}
+	if(!dev_priv->sarea) {
+		DRM_ERROR("could not find sarea!\n");
+		dev->dev_private = (void *)dev_priv;
+		radeon_do_cleanup_cp(dev);
+		return -EINVAL;
 	}
 
-	DO_FIND_MAP( dev_priv->fb, init->fb_offset );
-	DO_FIND_MAP( dev_priv->mmio, init->mmio_offset );
-	DO_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
-	DO_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
-	DO_FIND_MAP( dev_priv->buffers, init->buffers_offset );
+	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
+	if(!dev_priv->fb) {
+		DRM_ERROR("could not find framebuffer!\n");
+		dev->dev_private = (void *)dev_priv;
+		radeon_do_cleanup_cp(dev);
+		return -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;
+	}
+	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;
+	}
+	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;
+	}
+	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;
+	}
 
 	if ( !dev_priv->is_pci ) {
-		DO_FIND_MAP( dev_priv->agp_textures,
-			     init->agp_textures_offset );
+		DRM_FIND_MAP( dev_priv->agp_textures,
+			      init->agp_textures_offset );
+		if(!dev_priv->agp_textures) {
+			DRM_ERROR("could not find agp texture region!\n");
+			dev->dev_private = (void *)dev_priv;
+			radeon_do_cleanup_cp(dev);
+			return -EINVAL;
+		}
 	}
 
 	dev_priv->sarea_priv =
 		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				       init->sarea_priv_offset);
 
-	DO_IOREMAP( dev_priv->cp_ring );
-	DO_IOREMAP( dev_priv->ring_rptr );
-	DO_IOREMAP( dev_priv->buffers );
-#if 0
 	if ( !dev_priv->is_pci ) {
-		DO_IOREMAP( dev_priv->agp_textures );
+		DRM_IOREMAP( dev_priv->cp_ring );
+		DRM_IOREMAP( dev_priv->ring_rptr );
+		DRM_IOREMAP( dev_priv->buffers );
+		if(!dev_priv->cp_ring->handle ||
+		   !dev_priv->ring_rptr->handle ||
+		   !dev_priv->buffers->handle) {
+			DRM_ERROR("could not find ioremap agp regions!\n");
+			dev->dev_private = (void *)dev_priv;
+			radeon_do_cleanup_cp(dev);
+			return -EINVAL;
+		}
+	} else {
+		dev_priv->cp_ring->handle =
+			(void *)dev_priv->cp_ring->offset;
+		dev_priv->ring_rptr->handle =
+			(void *)dev_priv->ring_rptr->offset;
+		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
+
+		DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
+			   dev_priv->cp_ring->handle );
+		DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
+			   dev_priv->ring_rptr->handle );
+		DRM_DEBUG( "dev_priv->buffers->handle %p\n",
+			   dev_priv->buffers->handle );
 	}
-#endif
+
 
 	dev_priv->agp_size = init->agp_size;
 	dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );
-	dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
-					- dev->agp->base
-					+ dev_priv->agp_vm_start);
+#if __REALLY_HAVE_AGP
+	if ( !dev_priv->is_pci )
+		dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
+						- dev->agp->base
+						+ dev_priv->agp_vm_start);
+	else
+#endif
+		dev_priv->agp_buffers_offset = (dev_priv->buffers->offset
+						- dev->sg->handle
+						+ dev_priv->agp_vm_start);
+
+	DRM_DEBUG( "dev_priv->agp_size %d\n",
+		   dev_priv->agp_size );
+	DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n",
+		   dev_priv->agp_vm_start );
+	DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n",
+		   dev_priv->agp_buffers_offset );
 
 	dev_priv->ring.head = ((__volatile__ u32 *)
 			       dev_priv->ring_rptr->handle);
@@ -779,11 +893,13 @@
 	dev_priv->ring.end = ((u32 *)dev_priv->cp_ring->handle
 			      + init->ring_size / sizeof(u32));
 	dev_priv->ring.size = init->ring_size;
-	dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 );
+	dev_priv->ring.size_l2qw = DRM(order)( init->ring_size / 8 );
 
 	dev_priv->ring.tail_mask =
 		(dev_priv->ring.size / sizeof(u32)) - 1;
 
+	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
+
 #if 0
 	/* Initialize the scratch register pointer.  This will cause
 	 * the scratch register values to be written out to memory
@@ -812,33 +928,72 @@
 	RADEON_WRITE( RADEON_LAST_CLEAR_REG,
 		      dev_priv->sarea_priv->last_clear );
 
+	if ( dev_priv->is_pci ) {
+		dev_priv->phys_pci_gart = DRM(ati_pcigart_init)( dev );
+		if ( !dev_priv->phys_pci_gart ) {
+			DRM_ERROR( "failed to init PCI GART!\n" );
+			dev->dev_private = (void *)dev_priv;
+			radeon_do_cleanup_cp(dev);
+			return -ENOMEM;
+		}
+		/* Turn on PCI GART
+		 */
+		tmp = RADEON_READ( RADEON_AIC_CNTL )
+		      | RADEON_PCIGART_TRANSLATE_EN;
+		RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+
+		/* set PCI GART page-table base address
+		 */
+		RADEON_WRITE( RADEON_AIC_PT_BASE,
+			      virt_to_bus( (void *)dev_priv->phys_pci_gart ) );
+
+		/* set address range for PCI address translate
+		 */
+		RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start );
+		RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start
+						  + dev_priv->agp_size - 1);
+
+		/* Turn off AGP aperture -- is this required for PCIGART?
+		 */
+		RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
+		RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
+	} else {
+		/* Turn off PCI GART
+		 */
+		tmp = RADEON_READ( RADEON_AIC_CNTL )
+		      & ~RADEON_PCIGART_TRANSLATE_EN;
+		RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+	}
+
 	radeon_cp_load_microcode( dev_priv );
-	radeon_cp_init_ring_buffer( dev );
-	radeon_do_engine_reset( dev );
+	radeon_cp_init_ring_buffer( dev, dev_priv );
 
 #if ROTATE_BUFS
 	dev_priv->last_buf = 0;
 #endif
 
+	dev->dev_private = (void *)dev_priv;
+
+	radeon_do_engine_reset( dev );
+
 	return 0;
 }
 
-static int radeon_do_cleanup_cp( drm_device_t *dev )
+int radeon_do_cleanup_cp( drm_device_t *dev )
 {
+	DRM_DEBUG( "%s\n", __FUNCTION__ );
+
 	if ( dev->dev_private ) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
 
-		DO_IOREMAPFREE( dev_priv->cp_ring );
-		DO_IOREMAPFREE( dev_priv->ring_rptr );
-		DO_IOREMAPFREE( dev_priv->buffers );
-#if 0
 		if ( !dev_priv->is_pci ) {
-			DO_IOREMAPFREE( dev_priv->agp_textures );
+			DRM_IOREMAPFREE( dev_priv->cp_ring );
+			DRM_IOREMAPFREE( dev_priv->ring_rptr );
+			DRM_IOREMAPFREE( dev_priv->buffers );
 		}
-#endif
 
-		drm_free( dev->dev_private, sizeof(drm_radeon_private_t),
-			  DRM_MEM_DRIVER );
+		DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
+			   DRM_MEM_DRIVER );
 		dev->dev_private = NULL;
 	}
 
@@ -873,11 +1028,8 @@
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
+
 	if ( dev_priv->cp_running ) {
 		DRM_DEBUG( "%s while CP running\n", __FUNCTION__ );
 		return 0;
@@ -906,11 +1058,7 @@
 	int ret;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) )
 		return -EFAULT;
@@ -952,11 +1100,8 @@
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
+
 	if ( !dev_priv ) {
 		DRM_DEBUG( "%s called before init done\n", __FUNCTION__ );
 		return -EINVAL;
@@ -978,11 +1123,7 @@
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	return radeon_do_cp_idle( dev_priv );
 }
@@ -994,11 +1135,7 @@
         drm_device_t *dev = priv->dev;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	return radeon_do_engine_reset( dev );
 }
@@ -1048,11 +1185,7 @@
         drm_device_t *dev = priv->dev;
 	drm_radeon_fullscreen_t fs;
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg,
 			     sizeof(fs) ) )
@@ -1085,8 +1218,8 @@
 	drm_radeon_freelist_t *entry;
 	int i;
 
-	dev_priv->head = drm_alloc( sizeof(drm_radeon_freelist_t),
-				    DRM_MEM_DRIVER );
+	dev_priv->head = DRM(alloc)( sizeof(drm_radeon_freelist_t),
+				     DRM_MEM_DRIVER );
 	if ( dev_priv->head == NULL )
 		return -ENOMEM;
 
@@ -1097,8 +1230,8 @@
 		buf = dma->buflist[i];
 		buf_priv = buf->dev_private;
 
-		entry = drm_alloc( sizeof(drm_radeon_freelist_t),
-				   DRM_MEM_DRIVER );
+		entry = DRM(alloc)( sizeof(drm_radeon_freelist_t),
+				    DRM_MEM_DRIVER );
 		if ( !entry ) return -ENOMEM;
 
 		entry->age = RADEON_BUFFER_FREE;
@@ -1218,32 +1351,20 @@
 	int i;
 
 	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-		ring->space = *ring->head - ring->tail;
-		if ( ring->space <= 0 )
-			ring->space += ring->size;
-
-		if ( ring->space >= n )
+		radeon_update_ring_snapshot( ring );
+		if ( ring->space > n )
 			return 0;
-
 		udelay( 1 );
 	}
 
 	/* FIXME: This return value is ignored in the BEGIN_RING macro! */
+#if RADEON_FIFO_DEBUG
+	radeon_status( dev_priv );
 	DRM_ERROR( "failed!\n" );
+#endif
 	return -EBUSY;
 }
 
-void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv )
-{
-	drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
-
-	ring->space = *ring->head - ring->tail;
-	if ( ring->space == 0 )
-		atomic_inc( &dev_priv->idle_count );
-	if ( ring->space <= 0 )
-		ring->space += ring->size;
-}
-
 static int radeon_cp_get_buffers( drm_device_t *dev, drm_dma_t *d )
 {
 	int i;
@@ -1276,14 +1397,10 @@
 	int ret = 0;
 	drm_dma_t d;
 
-	if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) )
-		return -EFAULT;
+	LOCK_TEST_WITH_RETURN( dev );
 
-	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;
-	}
+	if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) )
+		return -EFAULT;
 
 	/* Please don't send us buffers.
 	 */
@@ -1307,7 +1424,7 @@
 		ret = radeon_cp_get_buffers( dev, &d );
 	}
 
-	if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) )
+	if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
 		return -EFAULT;
 
 	return ret;
diff -urN linux-2.4.8-pre6/drivers/char/drm/radeon_drm.h linux/drivers/char/drm/radeon_drm.h
--- linux-2.4.8-pre6/drivers/char/drm/radeon_drm.h	Fri Jan 19 13:34:08 2001
+++ linux/drivers/char/drm/radeon_drm.h	Mon Dec  3 22:59:45 2001
@@ -26,7 +26,6 @@
  * Authors:
  *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
- *
  */
 
 #ifndef __RADEON_DRM_H__
@@ -74,7 +73,7 @@
 
 /* Vertex/indirect buffer size
  */
-#define RADEON_BUFFER_SIZE		16384
+#define RADEON_BUFFER_SIZE		65536
 
 /* Byte offsets for indirect buffer data
  */
@@ -237,7 +236,7 @@
 		RADEON_INIT_CP    = 0x01,
 		RADEON_CLEANUP_CP = 0x02
 	} func;
-	int sarea_priv_offset;
+	unsigned long sarea_priv_offset;
 	int is_pci;
 	int cp_mode;
 	int agp_size;
@@ -250,12 +249,12 @@
 	unsigned int depth_bpp;
 	unsigned int depth_offset, depth_pitch;
 
-	unsigned int fb_offset;
-	unsigned int mmio_offset;
-	unsigned int ring_offset;
-	unsigned int ring_rptr_offset;
-	unsigned int buffers_offset;
-	unsigned int agp_textures_offset;
+	unsigned long fb_offset;
+	unsigned long mmio_offset;
+	unsigned long ring_offset;
+	unsigned long ring_rptr_offset;
+	unsigned long buffers_offset;
+	unsigned long agp_textures_offset;
 } drm_radeon_init_t;
 
 typedef struct drm_radeon_cp_stop {
@@ -276,15 +275,18 @@
 #define CLEAR_Y2	3
 #define CLEAR_DEPTH	4
 
+typedef union drm_radeon_clear_rect {
+	float f[5];
+	unsigned int ui[5];
+} drm_radeon_clear_rect_t;
+
 typedef struct drm_radeon_clear {
 	unsigned int flags;
-	int x, y, w, h;
 	unsigned int clear_color;
 	unsigned int clear_depth;
-	union {
-		float f[5];
-		unsigned int ui[5];
-	} rect;
+	unsigned int color_mask;
+	unsigned int depth_mask;
+	drm_radeon_clear_rect_t *depth_boxes;
 } drm_radeon_clear_t;
 
 typedef struct drm_radeon_vertex {
@@ -302,14 +304,20 @@
 	int discard;			/* Client finished with buffer? */
 } drm_radeon_indices_t;
 
-typedef struct drm_radeon_blit {
-	int idx;
-	int pitch;
+typedef struct drm_radeon_tex_image {
+	unsigned int x, y;		/* Blit coordinates */
+	unsigned int width, height;
+	const void *data;
+} drm_radeon_tex_image_t;
+
+typedef struct drm_radeon_texture {
 	int offset;
+	int pitch;
 	int format;
-	unsigned short x, y;
-	unsigned short width, height;
-} drm_radeon_blit_t;
+	int width;			/* Texture image coordinates */
+	int height;
+	drm_radeon_tex_image_t *image;
+} drm_radeon_texture_t;
 
 typedef struct drm_radeon_stipple {
 	unsigned int *mask;
diff -urN linux-2.4.8-pre6/drivers/char/drm/radeon_drv.c linux/drivers/char/drm/radeon_drv.c
--- linux-2.4.8-pre6/drivers/char/drm/radeon_drv.c	Fri Jan 19 13:34:08 2001
+++ linux/drivers/char/drm/radeon_drv.c	Mon Dec  3 22:59:45 2001
@@ -1,7 +1,7 @@
 /* radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
+ * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
  *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,685 +18,92 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Kevin E. Martin <martin@valinux.com>
- *          Rickard E. (Rik) Faith <faith@valinux.com>
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include <linux/config.h>
+#include "radeon.h"
 #include "drmP.h"
 #include "radeon_drv.h"
+#include "ati_pcigart.h"
 
-#define RADEON_NAME		"radeon"
-#define RADEON_DESC		"ATI Radeon"
-#define RADEON_DATE		"20010105"
-#define RADEON_MAJOR		1
-#define RADEON_MINOR		0
-#define RADEON_PATCHLEVEL	0
-
-static drm_device_t	      radeon_device;
-drm_ctx_t	              radeon_res_ctx;
-
-static struct file_operations radeon_fops = {
-#if LINUX_VERSION_CODE >= 0x020400
-				/* This started being used during 2.4.0-test */
-	owner:   THIS_MODULE,
-#endif
-	open:	 radeon_open,
-	flush:	 drm_flush,
-	release: radeon_release,
-	ioctl:	 radeon_ioctl,
-	mmap:	 drm_mmap,
-	read:	 drm_read,
-	fasync:	 drm_fasync,
-	poll:	 drm_poll,
-};
-
-static struct miscdevice      radeon_misc = {
-	minor: MISC_DYNAMIC_MINOR,
-	name:  RADEON_NAME,
-	fops:  &radeon_fops,
-};
-
-static drm_ioctl_desc_t	      radeon_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { radeon_version,	0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { drm_getunique,	0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { drm_getmagic,	0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { drm_irq_busid,	0, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)]    = { drm_setunique,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]	        = { drm_block,		1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]       = { drm_unblock,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)]    = { drm_authmagic,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { drm_addmap,		1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]      = { radeon_addbufs,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]     = { drm_markbufs,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { drm_infobufs,	1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { radeon_mapbufs,	1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { drm_freebufs,	1, 0 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]       = { radeon_addctx,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]        = { radeon_rmctx,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]       = { radeon_modctx,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]       = { radeon_getctx,	1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)]    = { radeon_switchctx,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]       = { radeon_newctx,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]       = { radeon_resctx,	1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]      = { drm_adddraw,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]       = { drm_rmdraw,		1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	        = { radeon_cp_buffers,	1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	        = { radeon_lock,	1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]        = { radeon_unlock,	1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { drm_finish,		1, 0 },
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { drm_agp_acquire,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { drm_agp_release,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { drm_agp_enable,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = { drm_agp_info,	1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = { drm_agp_alloc,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = { drm_agp_free,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = { drm_agp_bind,	1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { drm_agp_unbind,	1, 1 },
-#endif
+#define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
 
-	[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_BLIT)]    = { radeon_cp_blit,    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 },
-};
-#define RADEON_IOCTL_COUNT DRM_ARRAY_SIZE(radeon_ioctls)
+#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 },
 
-#ifdef MODULE
-static char		      *radeon = NULL;
+
+#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
 
-MODULE_AUTHOR("VA Linux Systems, Inc.");
-MODULE_DESCRIPTION("radeon");
-MODULE_PARM(radeon, "s");
+
+#include "drm_agpsupport.h"
+#include "drm_auth.h"
+#include "drm_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
 
 #ifndef MODULE
-/* radeon_options is called by the kernel to parse command-line options
+/* 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.
  */
 
-static int __init radeon_options(char *str)
+/* 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);
+	DRM(parse_options)( str );
 	return 1;
 }
 
-__setup("radeon=", radeon_options);
+__setup( DRIVER_NAME "=", radeon_options );
 #endif
 
-static int radeon_setup(drm_device_t *dev)
-{
-	int i;
-
-	atomic_set(&dev->ioctl_count, 0);
-	atomic_set(&dev->vma_count, 0);
-	dev->buf_use	  = 0;
-	atomic_set(&dev->buf_alloc, 0);
-
-	drm_dma_setup(dev);
-
-	atomic_set(&dev->total_open, 0);
-	atomic_set(&dev->total_close, 0);
-	atomic_set(&dev->total_ioctl, 0);
-	atomic_set(&dev->total_irq, 0);
-	atomic_set(&dev->total_ctx, 0);
-	atomic_set(&dev->total_locks, 0);
-	atomic_set(&dev->total_unlocks, 0);
-	atomic_set(&dev->total_contends, 0);
-	atomic_set(&dev->total_sleeps, 0);
-
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		dev->magiclist[i].head = NULL;
-		dev->magiclist[i].tail = NULL;
-	}
-	dev->maplist	    = NULL;
-	dev->map_count	    = 0;
-	dev->vmalist	    = NULL;
-	dev->lock.hw_lock   = NULL;
-	init_waitqueue_head(&dev->lock.lock_queue);
-	dev->queue_count    = 0;
-	dev->queue_reserved = 0;
-	dev->queue_slots    = 0;
-	dev->queuelist	    = NULL;
-	dev->irq	    = 0;
-	dev->context_flag   = 0;
-	dev->interrupt_flag = 0;
-	dev->dma_flag	    = 0;
-	dev->last_context   = 0;
-	dev->last_switch    = 0;
-	dev->last_checked   = 0;
-	init_timer(&dev->timer);
-	init_waitqueue_head(&dev->context_wait);
-
-	dev->ctx_start	    = 0;
-	dev->lck_start	    = 0;
-
-	dev->buf_rp	    = dev->buf;
-	dev->buf_wp	    = dev->buf;
-	dev->buf_end	    = dev->buf + DRM_BSZ;
-	dev->buf_async	    = NULL;
-	init_waitqueue_head(&dev->buf_readers);
-	init_waitqueue_head(&dev->buf_writers);
-
-	radeon_res_ctx.handle = -1;
-
-	DRM_DEBUG("\n");
-
-	/* The kernel's context could be created here, but is now created
-	   in drm_dma_enqueue.	This is more resource-efficient for
-	   hardware that does not do DMA, but may mean that
-	   drm_select_queue fails between the time the interrupt is
-	   initialized and the time the queues are initialized. */
-
-	return 0;
-}
-
-
-static int radeon_takedown(drm_device_t *dev)
-{
-	int		  i;
-	drm_magic_entry_t *pt, *next;
-	drm_map_t	  *map;
-	drm_vma_entry_t	  *vma, *vma_next;
-
-	DRM_DEBUG("\n");
-
-	down(&dev->struct_sem);
-	del_timer(&dev->timer);
-
-	if (dev->devname) {
-		drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
-		dev->devname = NULL;
-	}
-
-	if (dev->unique) {
-		drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
-		dev->unique = NULL;
-		dev->unique_len = 0;
-	}
-				/* Clear pid list */
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		for (pt = dev->magiclist[i].head; pt; pt = next) {
-			next = pt->next;
-			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-		}
-		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
-	}
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-				/* Clear AGP information */
-	if (dev->agp) {
-		drm_agp_mem_t *entry;
-		drm_agp_mem_t *nexte;
-
-				/* Remove AGP resources, but leave dev->agp
-                                   intact until radeon_cleanup is called. */
-		for (entry = dev->agp->memory; entry; entry = nexte) {
-			nexte = entry->next;
-			if (entry->bound) drm_unbind_agp(entry->memory);
-			drm_free_agp(entry->memory, entry->pages);
-			drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-		}
-		dev->agp->memory = NULL;
-
-		if (dev->agp->acquired)	_drm_agp_release();
-
-		dev->agp->acquired = 0;
-		dev->agp->enabled  = 0;
-	}
-#endif
-
-				/* Clear vma list (only built for debugging) */
-	if (dev->vmalist) {
-		for (vma = dev->vmalist; vma; vma = vma_next) {
-			vma_next = vma->next;
-			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
-		}
-		dev->vmalist = NULL;
-	}
-
-				/* Clear map area and mtrr information */
-	if (dev->maplist) {
-		for (i = 0; i < dev->map_count; i++) {
-			map = dev->maplist[i];
-			switch (map->type) {
-			case _DRM_REGISTERS:
-			case _DRM_FRAME_BUFFER:
-#ifdef CONFIG_MTRR
-				if (map->mtrr >= 0) {
-					int retcode;
-					retcode = mtrr_del(map->mtrr,
-							   map->offset,
-							   map->size);
-					DRM_DEBUG("mtrr_del = %d\n", retcode);
-				}
-#endif
-				drm_ioremapfree(map->handle, map->size);
-				break;
-			case _DRM_SHM:
-				drm_free_pages((unsigned long)map->handle,
-					       drm_order(map->size)
-					       - PAGE_SHIFT,
-					       DRM_MEM_SAREA);
-				break;
-			case _DRM_AGP:
-				/* Do nothing here, because this is all
-                                   handled in the AGP/GART driver. */
-				break;
-			}
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		}
-		drm_free(dev->maplist,
-			 dev->map_count * sizeof(*dev->maplist),
-			 DRM_MEM_MAPS);
-		dev->maplist   = NULL;
-		dev->map_count = 0;
-	}
-
-	drm_dma_takedown(dev);
-
-	dev->queue_count     = 0;
-	if (dev->lock.hw_lock) {
-		dev->lock.hw_lock    = NULL; /* SHM removed */
-		dev->lock.pid	     = 0;
-		wake_up_interruptible(&dev->lock.lock_queue);
-	}
-	up(&dev->struct_sem);
-
-	return 0;
-}
-
-/* radeon_init is called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported). */
-
-static int __init radeon_init(void)
-{
-	int		      retcode;
-	drm_device_t	      *dev = &radeon_device;
-
-	DRM_DEBUG("\n");
-
-	memset((void *)dev, 0, sizeof(*dev));
-	dev->count_lock	  = SPIN_LOCK_UNLOCKED;
-	sema_init(&dev->struct_sem, 1);
-
-#ifdef MODULE
-	drm_parse_options(radeon);
-#endif
-
-	if ((retcode = misc_register(&radeon_misc))) {
-		DRM_ERROR("Cannot register \"%s\"\n", RADEON_NAME);
-		return retcode;
-	}
-	dev->device = MKDEV(MISC_MAJOR, radeon_misc.minor);
-	dev->name   = RADEON_NAME;
-
-	drm_mem_init();
-	drm_proc_init(dev);
-
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	dev->agp    = drm_agp_init();
-      	if (dev->agp == NULL) {
-	   	DRM_ERROR("Cannot initialize agpgart module.\n");
-	   	drm_proc_cleanup();
-	   	misc_deregister(&radeon_misc);
-	   	radeon_takedown(dev);
-	   	return -ENOMEM;
-	}
-
-#ifdef CONFIG_MTRR
-	dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base,
-				      dev->agp->agp_info.aper_size*1024*1024,
-				      MTRR_TYPE_WRCOMB,
-				      1);
-#endif
-#endif
-
-	if((retcode = drm_ctxbitmap_init(dev))) {
-		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
-		drm_proc_cleanup();
-		misc_deregister(&radeon_misc);
-		radeon_takedown(dev);
-		return retcode;
-	}
-
-	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
-		 RADEON_NAME,
-		 RADEON_MAJOR,
-		 RADEON_MINOR,
-		 RADEON_PATCHLEVEL,
-		 RADEON_DATE,
-		 radeon_misc.minor);
-
-	return 0;
-}
-
-/* radeon_cleanup is called via cleanup_module at module unload time. */
-
-static void __exit radeon_cleanup(void)
-{
-	drm_device_t	      *dev = &radeon_device;
-
-	DRM_DEBUG("\n");
-
-	drm_proc_cleanup();
-	if (misc_deregister(&radeon_misc)) {
-		DRM_ERROR("Cannot unload module\n");
-	} else {
-		DRM_INFO("Module unloaded\n");
-	}
-	drm_ctxbitmap_cleanup(dev);
-	radeon_takedown(dev);
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	if (dev->agp) {
-		drm_agp_uninit();
-		drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
-		dev->agp = NULL;
-	}
-#endif
-}
-
-module_init(radeon_init);
-module_exit(radeon_cleanup);
-
-
-int radeon_version(struct inode *inode, struct file *filp, unsigned int cmd,
-		   unsigned long arg)
-{
-	drm_version_t version;
-	int	      len;
-
-	if (copy_from_user(&version,
-			   (drm_version_t *)arg,
-			   sizeof(version)))
-		return -EFAULT;
-
-#define DRM_COPY(name,value)				     \
-	len = strlen(value);				     \
-	if (len > name##_len) len = name##_len;		     \
-	name##_len = strlen(value);			     \
-	if (len && name) {				     \
-		if (copy_to_user(name, value, len))	     \
-			return -EFAULT;			     \
-	}
-
-	version.version_major	   = RADEON_MAJOR;
-	version.version_minor	   = RADEON_MINOR;
-	version.version_patchlevel = RADEON_PATCHLEVEL;
-
-	DRM_COPY(version.name, RADEON_NAME);
-	DRM_COPY(version.date, RADEON_DATE);
-	DRM_COPY(version.desc, RADEON_DESC);
-
-	if (copy_to_user((drm_version_t *)arg,
-			 &version,
-			 sizeof(version)))
-		return -EFAULT;
-	return 0;
-}
-
-int radeon_open(struct inode *inode, struct file *filp)
-{
-	drm_device_t  *dev    = &radeon_device;
-	int	      retcode = 0;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (!(retcode = drm_open_helper(inode, filp, dev))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-		atomic_inc(&dev->total_open);
-		spin_lock(&dev->count_lock);
-		if (!dev->open_count++) {
-			spin_unlock(&dev->count_lock);
-			return radeon_setup(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-
-	return retcode;
-}
-
-int radeon_release(struct inode *inode, struct file *filp)
-{
-	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev;
-	int	      retcode = 0;
-
-	lock_kernel();
-	dev = priv->dev;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-
-	/* Force the cleanup of page flipping when required */
-	if ( dev->dev_private ) {
-		drm_radeon_private_t *dev_priv = dev->dev_private;
-		if ( dev_priv->page_flipping ) {
-			radeon_do_cleanup_pageflip( dev );
-		}
-	}
-
-	if (!(retcode = drm_release(inode, filp))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-		atomic_inc(&dev->total_close);
-		spin_lock(&dev->count_lock);
-		if (!--dev->open_count) {
-			if (atomic_read(&dev->ioctl_count) || dev->blocked) {
-				DRM_ERROR("Device busy: %d %d\n",
-					  atomic_read(&dev->ioctl_count),
-					  dev->blocked);
-				spin_unlock(&dev->count_lock);
-				unlock_kernel();
-				return -EBUSY;
-			}
-			spin_unlock(&dev->count_lock);
-			unlock_kernel();
-			return radeon_takedown(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-
-	unlock_kernel();
-	return retcode;
-}
-
-/* radeon_ioctl is called whenever a process performs an ioctl on /dev/drm. */
-
-int radeon_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-		 unsigned long arg)
-{
-	int		 nr	 = DRM_IOCTL_NR(cmd);
-	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	int		 retcode = 0;
-	drm_ioctl_desc_t *ioctl;
-	drm_ioctl_t	 *func;
-
-	atomic_inc(&dev->ioctl_count);
-	atomic_inc(&dev->total_ioctl);
-	++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);
-
-	if (nr >= RADEON_IOCTL_COUNT) {
-		retcode = -EINVAL;
-	} else {
-		ioctl	  = &radeon_ioctls[nr];
-		func	  = ioctl->func;
-
-		if (!func) {
-			DRM_DEBUG("no function\n");
-			retcode = -EINVAL;
-		} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
-			    || (ioctl->auth_needed && !priv->authenticated)) {
-			retcode = -EACCES;
-		} else {
-			retcode = (func)(inode, filp, cmd, arg);
-		}
-	}
-
-	atomic_dec(&dev->ioctl_count);
-	return retcode;
-}
-
-int radeon_lock(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;
-        DECLARE_WAITQUEUE(entry, current);
-        int               ret   = 0;
-        drm_lock_t        lock;
-#if DRM_DMA_HISTOGRAM
-        cycles_t          start;
-
-        dev->lck_start = start = get_cycles();
-#endif
-
-        if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-        if (lock.context == DRM_KERNEL_CONTEXT) {
-                DRM_ERROR("Process %d using kernel context %d\n",
-                          current->pid, lock.context);
-                return -EINVAL;
-        }
-
-        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-                  lock.context, current->pid, dev->lock.hw_lock->lock,
-                  lock.flags);
-
-        if (lock.context < 0 /* || lock.context >= dev->queue_count */)
-                return -EINVAL;
-
-        if (!ret) {
-                add_wait_queue(&dev->lock.lock_queue, &entry);
-                for (;;) {
-                        current->state = TASK_INTERRUPTIBLE;
-                        if (!dev->lock.hw_lock) {
-                                /* Device has been unregistered */
-                                ret = -EINTR;
-                                break;
-                        }
-                        if (drm_lock_take(&dev->lock.hw_lock->lock,
-                                          lock.context)) {
-                                dev->lock.pid       = current->pid;
-                                dev->lock.lock_time = jiffies;
-                                atomic_inc(&dev->total_locks);
-                                break;  /* Got lock */
-                        }
-
-                                /* Contention */
-                        atomic_inc(&dev->total_sleeps);
-                        schedule();
-                        if (signal_pending(current)) {
-                                ret = -ERESTARTSYS;
-                                break;
-                        }
-                }
-                current->state = TASK_RUNNING;
-                remove_wait_queue(&dev->lock.lock_queue, &entry);
-        }
-
-        if (!ret) {
-		sigemptyset(&dev->sigmask);
-		sigaddset(&dev->sigmask, SIGSTOP);
-		sigaddset(&dev->sigmask, SIGTSTP);
-		sigaddset(&dev->sigmask, SIGTTIN);
-		sigaddset(&dev->sigmask, SIGTTOU);
-		dev->sigdata.context = lock.context;
-		dev->sigdata.lock    = dev->lock.hw_lock;
-		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
-                if (lock.flags & _DRM_LOCK_READY) {
-				/* Wait for space in DMA/FIFO */
-		}
-                if (lock.flags & _DRM_LOCK_QUIESCENT) {
-				/* Make hardware quiescent */
-			DRM_DEBUG("not quiescent!\n");
-#if 0
-                        radeon_quiescent(dev);
-#endif
-		}
-        }
-
-#if LINUX_VERSION_CODE < 0x020400
-	if (lock.context != radeon_res_ctx.handle) {
-		current->counter = 5;
-		current->priority = DEF_PRIORITY/4;
-	}
-#endif
-        DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
-
-#if DRM_DMA_HISTOGRAM
-        atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
-#endif
-
-        return ret;
-}
-
-
-int radeon_unlock(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_lock_t	  lock;
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("%d frees lock (%d holds)\n",
-		  lock.context,
-		  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-	atomic_inc(&dev->total_unlocks);
-	if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
-		atomic_inc(&dev->total_contends);
-	drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
-				/* FIXME: Try to send data to card here */
-	if (!dev->context_flag) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
-				  DRM_KERNEL_CONTEXT)) {
-			DRM_ERROR("\n");
-		}
-	}
-
-#if LINUX_VERSION_CODE < 0x020400
-	if (lock.context != radeon_res_ctx.handle) {
-		current->counter = 5;
-		current->priority = DEF_PRIORITY;
-	}
-#endif
-	unblock_all_signals();
-	return 0;
-}
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
+#include "drm_scatter.h"
diff -urN linux-2.4.8-pre6/drivers/char/drm/radeon_drv.h linux/drivers/char/drm/radeon_drv.h
--- linux-2.4.8-pre6/drivers/char/drm/radeon_drv.h	Fri Jan 19 13:34:09 2001
+++ linux/drivers/char/drm/radeon_drv.h	Mon Dec  3 22:59:45 2001
@@ -24,10 +24,8 @@
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *   Rickard E. (Rik) Faith <faith@valinux.com>
- *   Kevin E. Martin <martin@valinux.com>
- *   Gareth Hughes <gareth@valinux.com>
- *
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #ifndef __RADEON_DRV_H__
@@ -50,6 +48,8 @@
 	u32 tail;
 	u32 tail_mask;
 	int space;
+
+	int high_mark;
 } drm_radeon_ring_buffer_t;
 
 typedef struct drm_radeon_depth_clear_t {
@@ -64,7 +64,7 @@
 
 	int agp_size;
 	u32 agp_vm_start;
-	u32 agp_buffers_offset;
+	unsigned long agp_buffers_offset;
 
 	int cp_mode;
 	int cp_running;
@@ -83,6 +83,7 @@
 
 	int usec_timeout;
 	int is_pci;
+	unsigned long phys_pci_gart;
 
 	atomic_t idle_count;
 
@@ -91,13 +92,13 @@
 	u32 crtc_offset;
 	u32 crtc_offset_cntl;
 
-	unsigned int color_fmt;
+	u32 color_fmt;
 	unsigned int front_offset;
 	unsigned int front_pitch;
 	unsigned int back_offset;
 	unsigned int back_pitch;
 
-	unsigned int depth_fmt;
+	u32 depth_fmt;
 	unsigned int depth_offset;
 	unsigned int depth_pitch;
 
@@ -124,18 +125,6 @@
    	drm_radeon_freelist_t *list_entry;
 } drm_radeon_buf_priv_t;
 
-				/* radeon_drv.c */
-extern int  radeon_version( struct inode *inode, struct file *filp,
-			    unsigned int cmd, unsigned long arg );
-extern int  radeon_open( struct inode *inode, struct file *filp );
-extern int  radeon_release( struct inode *inode, struct file *filp );
-extern int  radeon_ioctl( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-extern int  radeon_lock( struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg );
-extern int  radeon_unlock( struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg );
-
 				/* radeon_cp.c */
 extern int radeon_cp_init( struct inode *inode, struct file *filp,
 			   unsigned int cmd, unsigned long arg );
@@ -158,9 +147,17 @@
 extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
 
 extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
-extern void radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv );
+
+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 */
@@ -172,43 +169,19 @@
 			     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_blit( 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 );
 
-				/* radeon_bufs.c */
-extern int radeon_addbufs(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int radeon_mapbufs(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-
-				/* radeon_context.c */
-extern int  radeon_resctx(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  radeon_addctx(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  radeon_modctx(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  radeon_getctx(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  radeon_switchctx(struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg);
-extern int  radeon_newctx(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  radeon_rmctx(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-
-extern int  radeon_context_switch(drm_device_t *dev, int old, int new);
-extern int  radeon_context_switch_complete(drm_device_t *dev, int new);
-
 
 /* Register definitions, register access macros and drmAddMap constants
  * for Radeon kernel driver.
  */
 
+#define RADEON_AGP_COMMAND		0x0f60
 #define RADEON_AUX_SCISSOR_CNTL		0x26f0
 #	define RADEON_EXCLUSIVE_SCISSOR_0	(1 << 24)
 #	define RADEON_EXCLUSIVE_SCISSOR_1	(1 << 25)
@@ -282,6 +255,12 @@
 #define RADEON_MC_AGP_LOCATION		0x014c
 #define RADEON_MC_FB_LOCATION		0x0148
 #define RADEON_MCLK_CNTL		0x0012
+#	define RADEON_FORCEON_MCLKA		(1 << 16)
+#	define RADEON_FORCEON_MCLKB		(1 << 17)
+#	define RADEON_FORCEON_YCLKA		(1 << 18)
+#	define RADEON_FORCEON_YCLKB		(1 << 19)
+#	define RADEON_FORCEON_MC		(1 << 20)
+#	define RADEON_FORCEON_AIC		(1 << 21)
 
 #define RADEON_PP_BORDER_COLOR_0	0x1d40
 #define RADEON_PP_BORDER_COLOR_1	0x1d44
@@ -462,6 +441,12 @@
 
 #define RADEON_AIC_CNTL			0x01d0
 #	define RADEON_PCIGART_TRANSLATE_EN	(1 << 0)
+#define RADEON_AIC_STAT			0x01d4
+#define RADEON_AIC_PT_BASE		0x01d8
+#define RADEON_AIC_LO_ADDR		0x01dc
+#define RADEON_AIC_HI_ADDR		0x01e0
+#define RADEON_AIC_TLB_ADDR		0x01e4
+#define RADEON_AIC_TLB_DATA		0x01e8
 
 /* CP command packets */
 #define RADEON_CP_PACKET0		0x00000000
@@ -514,14 +499,14 @@
 #define RADEON_COLOR_FORMAT_RGB8	9
 #define RADEON_COLOR_FORMAT_ARGB4444	15
 
-#define RADEON_TXF_8BPP_I		0
-#define RADEON_TXF_16BPP_AI88		1
-#define RADEON_TXF_8BPP_RGB332		2
-#define RADEON_TXF_16BPP_ARGB1555	3
-#define RADEON_TXF_16BPP_RGB565		4
-#define RADEON_TXF_16BPP_ARGB4444	5
-#define RADEON_TXF_32BPP_ARGB8888	6
-#define RADEON_TXF_32BPP_RGBA8888	7
+#define RADEON_TXFORMAT_I8		0
+#define RADEON_TXFORMAT_AI88		1
+#define RADEON_TXFORMAT_RGB332		2
+#define RADEON_TXFORMAT_ARGB1555	3
+#define RADEON_TXFORMAT_RGB565		4
+#define RADEON_TXFORMAT_ARGB4444	5
+#define RADEON_TXFORMAT_ARGB8888	6
+#define RADEON_TXFORMAT_RGBA8888	7
 
 /* Constants */
 #define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
@@ -534,27 +519,56 @@
 #define RADEON_MAX_VB_AGE		0x7fffffff
 #define RADEON_MAX_VB_VERTS		(0xffff)
 
+#define RADEON_RING_HIGH_MARK		128
 
-#define RADEON_BASE(reg)	((u32)(dev_priv->mmio->handle))
-#define RADEON_ADDR(reg)	(RADEON_BASE(reg) + reg)
 
-#define RADEON_DEREF(reg)	*(__volatile__ u32 *)RADEON_ADDR(reg)
-#define RADEON_READ(reg)	RADEON_DEREF(reg)
-#define RADEON_WRITE(reg,val)	do { RADEON_DEREF(reg) = val; } while (0)
+#define RADEON_BASE(reg)	((unsigned long)(dev_priv->mmio->handle))
+#define RADEON_ADDR(reg)	(RADEON_BASE( reg ) + reg)
 
-#define RADEON_DEREF8(reg)	*(__volatile__ u8 *)RADEON_ADDR(reg)
-#define RADEON_READ8(reg)	RADEON_DEREF8(reg)
-#define RADEON_WRITE8(reg,val)	do { RADEON_DEREF8(reg) = val; } while (0)
+#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_WRITE_PLL(addr,val)                                            \
-do {                                                                          \
-	RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX,                                \
-		      ((addr) & 0x1f) | RADEON_PLL_WR_EN);                    \
-	RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val));                          \
-} while (0)
+#define RADEON_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
 
-extern int RADEON_READ_PLL(drm_device_t *dev, int addr);
+#define RADEON_WRITE_PLL( addr, val )					\
+do {									\
+	RADEON_WRITE8( RADEON_CLOCK_CNTL_INDEX,				\
+		       ((addr) & 0x1f) | RADEON_PLL_WR_EN );		\
+	RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) );			\
+} while (0)
 
+extern int RADEON_READ_PLL( drm_device_t *dev, int addr );
 
 
 #define CP_PACKET0( reg, n )						\
@@ -573,54 +587,46 @@
  * Engine control helper macros
  */
 
-#define RADEON_WAIT_UNTIL_2D_IDLE()					\
-do {									\
+#define RADEON_WAIT_UNTIL_2D_IDLE() do {				\
 	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
 	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
 		   RADEON_WAIT_HOST_IDLECLEAN) );			\
 } while (0)
 
-#define RADEON_WAIT_UNTIL_3D_IDLE()					\
-do {									\
+#define RADEON_WAIT_UNTIL_3D_IDLE() do {				\
 	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
 	OUT_RING( (RADEON_WAIT_3D_IDLECLEAN |				\
 		   RADEON_WAIT_HOST_IDLECLEAN) );			\
 } while (0)
 
-#define RADEON_WAIT_UNTIL_IDLE()					\
-do {									\
+#define RADEON_WAIT_UNTIL_IDLE() do {					\
 	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
 	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
 		   RADEON_WAIT_3D_IDLECLEAN |				\
 		   RADEON_WAIT_HOST_IDLECLEAN) );			\
 } while (0)
 
-#define RADEON_WAIT_UNTIL_PAGE_FLIPPED()				\
-do {									\
+#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do {				\
 	OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );			\
 	OUT_RING( RADEON_WAIT_CRTC_PFLIP );				\
 } while (0)
 
-#define RADEON_FLUSH_CACHE()						\
-do {									\
+#define RADEON_FLUSH_CACHE() do {					\
 	OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) );	\
 	OUT_RING( RADEON_RB2D_DC_FLUSH );				\
 } while (0)
 
-#define RADEON_PURGE_CACHE()						\
-do {									\
+#define RADEON_PURGE_CACHE() do {					\
 	OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) );	\
 	OUT_RING( RADEON_RB2D_DC_FLUSH_ALL );				\
 } while (0)
 
-#define RADEON_FLUSH_ZCACHE()						\
-do {									\
+#define RADEON_FLUSH_ZCACHE() do {					\
 	OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );	\
 	OUT_RING( RADEON_RB3D_ZC_FLUSH );				\
 } while (0)
 
-#define RADEON_PURGE_ZCACHE()						\
-do {									\
+#define RADEON_PURGE_ZCACHE() do {					\
 	OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );	\
 	OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL );				\
 } while (0)
@@ -630,7 +636,33 @@
  * Misc helper macros
  */
 
-#define VB_AGE_CHECK_WITH_RET( dev_priv )				\
+#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;						\
+	}								\
+} while (0)
+
+#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;						\
+	}								\
+ __ring_space_done:							\
+} while (0)
+
+#define VB_AGE_TEST_WITH_RETURN( dev_priv )				\
 do {									\
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;		\
 	if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {		\
@@ -641,20 +673,17 @@
 	}								\
 } while (0)
 
-#define RADEON_DISPATCH_AGE( age )					\
-do {									\
+#define RADEON_DISPATCH_AGE( age ) do {					\
 	OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) );		\
 	OUT_RING( age );						\
 } while (0)
 
-#define RADEON_FRAME_AGE( age )						\
-do {									\
+#define RADEON_FRAME_AGE( age ) do {					\
 	OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) );		\
 	OUT_RING( age );						\
 } while (0)
 
-#define RADEON_CLEAR_AGE( age )						\
-do {									\
+#define RADEON_CLEAR_AGE( age ) do {					\
 	OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) );		\
 	OUT_RING( age );						\
 } while (0)
@@ -676,7 +705,7 @@
 		DRM_INFO( "BEGIN_RING( %d ) in %s\n",			\
 			   n, __FUNCTION__ );				\
 	}								\
-	if ( dev_priv->ring.space < (n) * sizeof(u32) ) {		\
+	if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {		\
 		radeon_wait_ring( dev_priv, (n) * sizeof(u32) );	\
 	}								\
 	dev_priv->ring.space -= (n) * sizeof(u32);			\
@@ -687,7 +716,7 @@
 
 #define ADVANCE_RING() do {						\
 	if ( RADEON_VERBOSE ) {						\
-		DRM_INFO( "ADVANCE_RING() tail=0x%06x wr=0x%06x\n",	\
+		DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",	\
 			  write, dev_priv->ring.tail );			\
 	}								\
 	radeon_flush_write_combine();					\
diff -urN linux-2.4.8-pre6/drivers/char/drm/radeon_state.c linux/drivers/char/drm/radeon_state.c
--- linux-2.4.8-pre6/drivers/char/drm/radeon_state.c	Wed Jan 24 09:17:27 2001
+++ linux/drivers/char/drm/radeon_state.c	Mon Dec  3 22:59:45 2001
@@ -23,12 +23,12 @@
  * DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *    Kevin E. Martin <martin@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
- *
+ *    Kevin E. Martin <martin@valinux.com>
  */
 
 #define __NO_VERSION__
+#include "radeon.h"
 #include "drmP.h"
 #include "radeon_drv.h"
 #include "drm.h"
@@ -486,7 +486,8 @@
 }
 
 static void radeon_cp_dispatch_clear( drm_device_t *dev,
-				      drm_radeon_clear_t *clear )
+				      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;
@@ -497,8 +498,6 @@
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	radeon_update_ring_snapshot( dev_priv );
-
 	if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
 		unsigned int tmp = flags;
 
@@ -525,7 +524,7 @@
 			RADEON_WAIT_UNTIL_3D_IDLE();
 
 			OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
-			OUT_RING( sarea_priv->context_state.rb3d_planemask );
+			OUT_RING( clear->color_mask );
 
 			ADVANCE_RING();
 
@@ -609,17 +608,17 @@
 				   RADEON_VTX_FMT_RADEON_MODE |
 				   (3 << RADEON_NUM_VERTICES_SHIFT)) );
 
-			OUT_RING( clear->rect.ui[CLEAR_X1] );
-			OUT_RING( clear->rect.ui[CLEAR_Y1] );
-			OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
-
-			OUT_RING( clear->rect.ui[CLEAR_X1] );
-			OUT_RING( clear->rect.ui[CLEAR_Y2] );
-			OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
-
-			OUT_RING( clear->rect.ui[CLEAR_X2] );
-			OUT_RING( clear->rect.ui[CLEAR_Y2] );
-			OUT_RING( clear->rect.ui[CLEAR_DEPTH] );
+			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( depth_boxes[i].ui[CLEAR_X1] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
+
+			OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
+			OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
 
 			ADVANCE_RING();
 
@@ -655,8 +654,6 @@
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	radeon_update_ring_snapshot( dev_priv );
-
 #if RADEON_PERFORMANCE_BOXES
 	/* Do some trivial performance monitoring...
 	 */
@@ -724,8 +721,6 @@
 	RING_LOCALS;
 	DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page );
 
-	radeon_update_ring_snapshot( dev_priv );
-
 #if RADEON_PERFORMANCE_BOXES
 	/* Do some trivial performance monitoring...
 	 */
@@ -776,8 +771,6 @@
 	RING_LOCALS;
 	DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox );
 
-	radeon_update_ring_snapshot( dev_priv );
-
 	if ( 0 )
 		radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
 
@@ -844,8 +837,6 @@
 	DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
 		   buf->idx, start, end );
 
-	radeon_update_ring_snapshot( dev_priv );
-
 	if ( start != end ) {
 		int offset = (dev_priv->agp_buffers_offset
 			      + buf->offset + start);
@@ -908,8 +899,6 @@
 	RING_LOCALS;
 	DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
 
-	radeon_update_ring_snapshot( dev_priv );
-
 	if ( 0 )
 		radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
 
@@ -971,50 +960,67 @@
 	sarea_priv->nbox = 0;
 }
 
-static int radeon_cp_dispatch_blit( drm_device_t *dev,
-				    drm_radeon_blit_t *blit )
+#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
+
+static int radeon_cp_dispatch_texture( drm_device_t *dev,
+				       drm_radeon_texture_t *tex,
+				       drm_radeon_tex_image_t *image )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
 	drm_buf_t *buf;
 	drm_radeon_buf_priv_t *buf_priv;
 	u32 format;
-	u32 *data;
-	int dword_shift, dwords;
+	u32 *buffer;
+	u8 *data;
+	int size, dwords, tex_width, blit_width;
+	u32 y, height;
+	int ret = 0, i;
 	RING_LOCALS;
-	DRM_DEBUG( "blit: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
-		   blit->offset >> 10, blit->pitch, blit->format,
-		   blit->x, blit->y, blit->width, blit->height );
 
-	radeon_update_ring_snapshot( dev_priv );
+	/* FIXME: Be smarter about this...
+	 */
+	buf = radeon_freelist_get( dev );
+	if ( !buf ) return -EAGAIN;
+
+	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 );
+
+	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
 	 * use a shift instead.
 	 */
-	switch ( blit->format ) {
-	case RADEON_TXF_32BPP_ARGB8888:
-	case RADEON_TXF_32BPP_RGBA8888:
+	switch ( tex->format ) {
+	case RADEON_TXFORMAT_ARGB8888:
+	case RADEON_TXFORMAT_RGBA8888:
 		format = RADEON_COLOR_FORMAT_ARGB8888;
-		dword_shift = 0;
+		tex_width = tex->width * 4;
+		blit_width = image->width * 4;
 		break;
-	case RADEON_TXF_16BPP_AI88:
-	case RADEON_TXF_16BPP_ARGB1555:
-	case RADEON_TXF_16BPP_RGB565:
-	case RADEON_TXF_16BPP_ARGB4444:
+	case RADEON_TXFORMAT_AI88:
+	case RADEON_TXFORMAT_ARGB1555:
+	case RADEON_TXFORMAT_RGB565:
+	case RADEON_TXFORMAT_ARGB4444:
 		format = RADEON_COLOR_FORMAT_RGB565;
-		dword_shift = 1;
+		tex_width = tex->width * 2;
+		blit_width = image->width * 2;
 		break;
-	case RADEON_TXF_8BPP_I:
-	case RADEON_TXF_8BPP_RGB332:
+	case RADEON_TXFORMAT_I8:
+	case RADEON_TXFORMAT_RGB332:
 		format = RADEON_COLOR_FORMAT_CI8;
-		dword_shift = 2;
+		tex_width = tex->width * 1;
+		blit_width = image->width * 1;
 		break;
 	default:
-		DRM_ERROR( "invalid blit format %d\n", blit->format );
+		DRM_ERROR( "invalid texture format %d\n", tex->format );
 		return -EINVAL;
 	}
 
+	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.
@@ -1026,46 +1032,88 @@
 
 	ADVANCE_RING();
 
-	/* Dispatch the indirect buffer.
+	/* Make a copy of the parameters in case we have to update them
+	 * for a multi-pass texture blit.
 	 */
-	buf = dma->buflist[blit->idx];
-	buf_priv = buf->dev_private;
-
-	if ( buf->pid != current->pid ) {
-		DRM_ERROR( "process %d using buffer owned by %d\n",
-			   current->pid, buf->pid );
-		return -EINVAL;
-	}
-	if ( buf->pending ) {
-		DRM_ERROR( "sending pending buffer %d\n", blit->idx );
-		return -EINVAL;
+	y = image->y;
+	height = image->height;
+	data = (u8 *)image->data;
+
+	size = height * blit_width;
+
+	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;
+		size = height * blit_width;
+
+		/* 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 = 4;
 	}
 
-	buf_priv->discard = 1;
-
-	dwords = (blit->width * blit->height) >> dword_shift;
-	if ( !dwords ) dwords = 1;
+	dwords = size / 4;
 
-	data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
+	/* Dispatch the indirect buffer.
+	 */
+	buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
 
-	data[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
-	data[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);
-
-	data[2] = (blit->pitch << 22) | (blit->offset >> 10);
-	data[3] = 0xffffffff;
-	data[4] = 0xffffffff;
-	data[5] = (blit->y << 16) | blit->x;
-	data[6] = (blit->height << 16) | blit->width;
-	data[7] = dwords;
+	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 ( 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 += 8;
+			data += tex_width;
+		}
+	}
 
+	buf->pid = current->pid;
 	buf->used = (dwords + 8) * sizeof(u32);
+	buf_priv->discard = 1;
 
 	radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
 
@@ -1080,7 +1128,7 @@
 
 	ADVANCE_RING();
 
-	return 0;
+	return ret;
 }
 
 static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
@@ -1090,8 +1138,6 @@
 	RING_LOCALS;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	radeon_update_ring_snapshot( dev_priv );
-
 	BEGIN_RING( 35 );
 
 	OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
@@ -1118,22 +1164,25 @@
 	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__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &clear, (drm_radeon_clear_t *) arg,
+	if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg,
 			     sizeof(clear) ) )
 		return -EFAULT;
 
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
 	if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
 
-	radeon_cp_dispatch_clear( dev, &clear );
+	if ( copy_from_user( &depth_boxes, clear.depth_boxes,
+			     sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
+		return -EFAULT;
+
+	radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
 
 	return 0;
 }
@@ -1147,11 +1196,9 @@
 	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
+
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
 
 	if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
 		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
@@ -1178,13 +1225,10 @@
 	drm_radeon_buf_priv_t *buf_priv;
 	drm_radeon_vertex_t vertex;
 
-	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;
-	}
-	if ( !dev_priv || dev_priv->is_pci ) {
-		DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
 		return -EINVAL;
 	}
 
@@ -1207,7 +1251,8 @@
 		return -EINVAL;
 	}
 
-	VB_AGE_CHECK_WITH_RET( dev_priv );
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+	VB_AGE_TEST_WITH_RETURN( dev_priv );
 
 	buf = dma->buflist[vertex.idx];
 	buf_priv = buf->dev_private;
@@ -1243,13 +1288,10 @@
 	drm_radeon_indices_t elts;
 	int count;
 
-	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;
-	}
-	if ( !dev_priv || dev_priv->is_pci ) {
-		DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
 		return -EINVAL;
 	}
 
@@ -1272,7 +1314,8 @@
 		return -EINVAL;
 	}
 
-	VB_AGE_CHECK_WITH_RET( dev_priv );
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+	VB_AGE_TEST_WITH_RETURN( dev_priv );
 
 	buf = dma->buflist[elts.idx];
 	buf_priv = buf->dev_private;
@@ -1308,37 +1351,34 @@
 	return 0;
 }
 
-int radeon_cp_blit( struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg )
+int radeon_cp_texture( 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_private_t *dev_priv = dev->dev_private;
-	drm_device_dma_t *dma = dev->dma;
-	drm_radeon_blit_t blit;
+	drm_radeon_texture_t tex;
+	drm_radeon_tex_image_t image;
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
-	if ( copy_from_user( &blit, (drm_radeon_blit_t *)arg,
-			     sizeof(blit) ) )
+	if ( copy_from_user( &tex, (drm_radeon_texture_t *)arg, sizeof(tex) ) )
 		return -EFAULT;
 
-	DRM_DEBUG( "%s: pid=%d index=%d\n",
-		   __FUNCTION__, current->pid, blit.idx );
-
-	if ( blit.idx < 0 || blit.idx > dma->buf_count ) {
-		DRM_ERROR( "sending %d buffers (of %d max)\n",
-			   blit.idx, dma->buf_count );
+	if ( tex.image == NULL ) {
+		DRM_ERROR( "null texture image!\n" );
 		return -EINVAL;
 	}
 
-	VB_AGE_CHECK_WITH_RET( dev_priv );
+	if ( copy_from_user( &image,
+			     (drm_radeon_tex_image_t *)tex.image,
+			     sizeof(image) ) )
+		return -EFAULT;
 
-	return radeon_cp_dispatch_blit( dev, &blit );
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+	VB_AGE_TEST_WITH_RETURN( dev_priv );
+
+	return radeon_cp_dispatch_texture( dev, &tex, &image );
 }
 
 int radeon_cp_stipple( struct inode *inode, struct file *filp,
@@ -1346,23 +1386,21 @@
 {
 	drm_file_t *priv = filp->private_data;
 	drm_device_t *dev = priv->dev;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_radeon_stipple_t stipple;
 	u32 mask[32];
 
-	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;
-	}
+	LOCK_TEST_WITH_RETURN( dev );
 
 	if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg,
 			     sizeof(stipple) ) )
 		return -EFAULT;
 
-	if ( copy_from_user( &mask, stipple.mask,
-			     32 * sizeof(u32) ) )
+	if ( copy_from_user( &mask, stipple.mask, 32 * sizeof(u32) ) )
 		return -EFAULT;
 
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+
 	radeon_cp_dispatch_stipple( dev, mask );
 
 	return 0;
@@ -1380,13 +1418,10 @@
 	drm_radeon_indirect_t indirect;
 	RING_LOCALS;
 
-	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;
-	}
-	if ( !dev_priv || dev_priv->is_pci ) {
-		DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ );
+	LOCK_TEST_WITH_RETURN( dev );
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
 		return -EINVAL;
 	}
 
@@ -1423,7 +1458,8 @@
 		return -EINVAL;
 	}
 
-	VB_AGE_CHECK_WITH_RET( dev_priv );
+	RING_SPACE_TEST_WITH_RETURN( dev_priv );
+	VB_AGE_TEST_WITH_RETURN( dev_priv );
 
 	buf->used = indirect.end;
 	buf_priv->discard = indirect.discard;
diff -urN linux-2.4.8-pre6/drivers/char/drm/tdfx.h linux/drivers/char/drm/tdfx.h
--- linux-2.4.8-pre6/drivers/char/drm/tdfx.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/tdfx.h	Mon Dec  3 22:59:45 2001
@@ -0,0 +1,42 @@
+/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-
+ * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __TDFX_H__
+#define __TDFX_H__
+
+/* This remains constant for all DRM template files.
+ */
+#define DRM(x) tdfx_##x
+
+/* General customization:
+ */
+#define __HAVE_MTRR		1
+#define __HAVE_CTX_BITMAP	1
+
+#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/tdfx_context.c linux/drivers/char/drm/tdfx_context.c
--- linux-2.4.8-pre6/drivers/char/drm/tdfx_context.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/char/drm/tdfx_context.c	Wed Dec 31 16:00:00 1969
@@ -1,219 +0,0 @@
-/* tdfx_context.c -- IOCTLs for tdfx contexts -*- linux-c -*-
- * Created: Thu Oct  7 10:50:22 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>
- *    Daryll Strauss <daryll@valinux.com>
- * 
- */
-
-#define __NO_VERSION__
-#include "drmP.h"
-#include "tdfx_drv.h"
-
-extern drm_ctx_t tdfx_res_ctx;
-
-static int tdfx_alloc_queue(drm_device_t *dev)
-{
-	return drm_ctxbitmap_next(dev);
-}
-
-int tdfx_context_switch(drm_device_t *dev, int old, int new)
-{
-        char        buf[64];
-
-        atomic_inc(&dev->total_ctx);
-
-        if (test_and_set_bit(0, &dev->context_flag)) {
-                DRM_ERROR("Reentering -- FIXME\n");
-                return -EBUSY;
-        }
-
-#if DRM_DMA_HISTOGRAM
-        dev->ctx_start = get_cycles();
-#endif
-        
-        DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
-        if (new == dev->last_context) {
-                clear_bit(0, &dev->context_flag);
-                return 0;
-        }
-        
-        if (drm_flags & DRM_FLAG_NOCTX) {
-                tdfx_context_switch_complete(dev, new);
-        } else {
-                sprintf(buf, "C %d %d\n", old, new);
-                drm_write_string(dev, buf);
-        }
-        
-        return 0;
-}
-
-int tdfx_context_switch_complete(drm_device_t *dev, int new)
-{
-        dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
-        dev->last_switch  = jiffies;
-        
-        if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-                DRM_ERROR("Lock isn't held after context switch\n");
-        }
-
-				/* If a context switch is ever initiated
-                                   when the kernel holds the lock, release
-                                   that lock here. */
-#if DRM_DMA_HISTOGRAM
-        atomic_inc(&dev->histo.ctx[drm_histogram_slot(get_cycles()
-                                                      - dev->ctx_start)]);
-                   
-#endif
-        clear_bit(0, &dev->context_flag);
-        wake_up(&dev->context_wait);
-        
-        return 0;
-}
-
-
-int tdfx_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	       unsigned long arg)
-{
-	drm_ctx_res_t	res;
-	drm_ctx_t	ctx;
-	int		i;
-
-	DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
-	if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
-		return -EFAULT;
-	if (res.count >= DRM_RESERVED_CONTEXTS) {
-		memset(&ctx, 0, sizeof(ctx));
-		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-			ctx.handle = i;
-			if (copy_to_user(&res.contexts[i],
-					 &i,
-					 sizeof(i)))
-				return -EFAULT;
-		}
-	}
-	res.count = DRM_RESERVED_CONTEXTS;
-	if (copy_to_user((drm_ctx_res_t *)arg, &res, sizeof(res)))
-		return -EFAULT;
-	return 0;
-}
-
-
-int tdfx_addctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	if ((ctx.handle = tdfx_alloc_queue(dev)) == DRM_KERNEL_CONTEXT) {
-				/* Skip kernel's context and get a new one. */
-		ctx.handle = tdfx_alloc_queue(dev);
-	}
-	DRM_DEBUG("%d\n", ctx.handle);
-	if (ctx.handle == -1) {
-		DRM_DEBUG("Not enough free contexts.\n");
-				/* Should this return -EBUSY instead? */
-		return -ENOMEM;
-	}
-   
-	if (copy_to_user((drm_ctx_t *)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int tdfx_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	unsigned long arg)
-{
-	drm_ctx_t ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
-		return -EFAULT;
-	if (ctx.flags==_DRM_CONTEXT_PRESERVED)
-		tdfx_res_ctx.handle=ctx.handle;
-	return 0;
-}
-
-int tdfx_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
-	unsigned long arg)
-{
-	drm_ctx_t ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t*)arg, sizeof(ctx)))
-		return -EFAULT;
-	/* This is 0, because we don't handle any context flags */
-	ctx.flags = 0;
-	if (copy_to_user((drm_ctx_t*)arg, &ctx, sizeof(ctx)))
-		return -EFAULT;
-	return 0;
-}
-
-int tdfx_switchctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	return tdfx_context_switch(dev, dev->last_context, ctx.handle);
-}
-
-int tdfx_newctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	tdfx_context_switch_complete(dev, ctx.handle);
-
-	return 0;
-}
-
-int tdfx_rmctx(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_t	ctx;
-
-	if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
-		return -EFAULT;
-	DRM_DEBUG("%d\n", ctx.handle);
-	drm_ctxbitmap_free(dev, ctx.handle);
-
-	return 0;
-}
diff -urN linux-2.4.8-pre6/drivers/char/drm/tdfx_drv.c linux/drivers/char/drm/tdfx_drv.c
--- linux-2.4.8-pre6/drivers/char/drm/tdfx_drv.c	Thu Nov 16 14:05:49 2000
+++ linux/drivers/char/drm/tdfx_drv.c	Mon Dec  3 22:59:45 2001
@@ -27,670 +27,68 @@
  * Authors:
  *    Rickard E. (Rik) Faith <faith@valinux.com>
  *    Daryll Strauss <daryll@valinux.com>
- *
+ *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include <linux/config.h>
+#include "tdfx.h"
 #include "drmP.h"
-#include "tdfx_drv.h"
 
-#define TDFX_NAME	 "tdfx"
-#define TDFX_DESC	 "3dfx Banshee/Voodoo3+"
-#define TDFX_DATE	 "20000928"
-#define TDFX_MAJOR	 1
-#define TDFX_MINOR	 0
-#define TDFX_PATCHLEVEL  0
-
-static drm_device_t	      tdfx_device;
-drm_ctx_t	              tdfx_res_ctx;
-
-static struct file_operations tdfx_fops = {
-#if LINUX_VERSION_CODE >= 0x020400
-				/* This started being used during 2.4.0-test */
-	owner:   THIS_MODULE,
-#endif
-	open:	 tdfx_open,
-	flush:	 drm_flush,
-	release: tdfx_release,
-	ioctl:	 tdfx_ioctl,
-	mmap:	 drm_mmap,
-	read:	 drm_read,
-	fasync:	 drm_fasync,
-	poll:	 drm_poll,
-};
+#define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
-static struct miscdevice      tdfx_misc = {
-	minor: MISC_DYNAMIC_MINOR,
-	name:  TDFX_NAME,
-	fops:  &tdfx_fops,
-};
+#define DRIVER_NAME		"tdfx"
+#define DRIVER_DESC		"3dfx Banshee/Voodoo3+"
+#define DRIVER_DATE		"20010216"
 
-static drm_ioctl_desc_t	      tdfx_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]    = { tdfx_version,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]  = { drm_getmagic,	  0, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]  = { drm_irq_busid,	  0, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)]	     = { drm_block,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)]    = { drm_unblock,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]    = { drm_addmap,	  1, 1 },
-
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]    = { tdfx_addctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]     = { tdfx_rmctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)]    = { tdfx_modctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)]    = { tdfx_getctx,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { tdfx_switchctx,  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)]    = { tdfx_newctx,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)]    = { tdfx_resctx,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]   = { drm_adddraw,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]    = { drm_rmdraw,	  1, 1 },
-	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	     = { tdfx_lock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]     = { tdfx_unlock,	  1, 0 },
-	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]     = { drm_finish,	  1, 0 },
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = {drm_agp_acquire, 1, 1},
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = {drm_agp_release, 1, 1},
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = {drm_agp_enable,  1, 1},
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)]      = {drm_agp_info,    1, 1},
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)]     = {drm_agp_alloc,   1, 1},
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]      = {drm_agp_free,    1, 1},
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]      = {drm_agp_unbind,  1, 1},
-	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = {drm_agp_bind,    1, 1},
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	0
+
+#ifndef PCI_DEVICE_ID_3DFX_VOODOO5
+#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009
 #endif
+
+static drm_pci_list_t DRM(idlist)[] = {
+	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE },
+	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3 },
+	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5 },
+	{ 0, 0 }
 };
-#define TDFX_IOCTL_COUNT DRM_ARRAY_SIZE(tdfx_ioctls)
 
-#ifdef MODULE
-static char		      *tdfx = NULL;
-#endif
+#define DRIVER_CARD_LIST DRM(idlist)
 
-MODULE_AUTHOR("VA Linux Systems, Inc.");
-MODULE_DESCRIPTION("tdfx");
-MODULE_PARM(tdfx, "s");
+
+#include "drm_auth.h"
+#include "drm_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
 
 #ifndef MODULE
-/* tdfx_options is called by the kernel to parse command-line options
+/* 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.
  */
 
-static int __init tdfx_options(char *str)
+/* 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);
+	DRM(parse_options)( str );
 	return 1;
 }
 
-__setup("tdfx=", tdfx_options);
-#endif
-
-static int tdfx_setup(drm_device_t *dev)
-{
-	int i;
-
-	atomic_set(&dev->ioctl_count, 0);
-	atomic_set(&dev->vma_count, 0);
-	dev->buf_use	  = 0;
-	atomic_set(&dev->buf_alloc, 0);
-
-	atomic_set(&dev->total_open, 0);
-	atomic_set(&dev->total_close, 0);
-	atomic_set(&dev->total_ioctl, 0);
-	atomic_set(&dev->total_irq, 0);
-	atomic_set(&dev->total_ctx, 0);
-	atomic_set(&dev->total_locks, 0);
-	atomic_set(&dev->total_unlocks, 0);
-	atomic_set(&dev->total_contends, 0);
-	atomic_set(&dev->total_sleeps, 0);
-
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		dev->magiclist[i].head = NULL;
-		dev->magiclist[i].tail = NULL;
-	}
-	dev->maplist	    = NULL;
-	dev->map_count	    = 0;
-	dev->vmalist	    = NULL;
-	dev->lock.hw_lock   = NULL;
-	init_waitqueue_head(&dev->lock.lock_queue);
-	dev->queue_count    = 0;
-	dev->queue_reserved = 0;
-	dev->queue_slots    = 0;
-	dev->queuelist	    = NULL;
-	dev->irq	    = 0;
-	dev->context_flag   = 0;
-	dev->interrupt_flag = 0;
-	dev->dma            = 0;
-	dev->dma_flag	    = 0;
-	dev->last_context   = 0;
-	dev->last_switch    = 0;
-	dev->last_checked   = 0;
-	init_timer(&dev->timer);
-	init_waitqueue_head(&dev->context_wait);
-
-	dev->ctx_start	    = 0;
-	dev->lck_start	    = 0;
-
-	dev->buf_rp	  = dev->buf;
-	dev->buf_wp	  = dev->buf;
-	dev->buf_end	  = dev->buf + DRM_BSZ;
-	dev->buf_async	  = NULL;
-	init_waitqueue_head(&dev->buf_readers);
-	init_waitqueue_head(&dev->buf_writers);
-
-	tdfx_res_ctx.handle=-1;
-
-	DRM_DEBUG("\n");
-
-	/* The kernel's context could be created here, but is now created
-	   in drm_dma_enqueue.	This is more resource-efficient for
-	   hardware that does not do DMA, but may mean that
-	   drm_select_queue fails between the time the interrupt is
-	   initialized and the time the queues are initialized. */
-
-	return 0;
-}
-
-
-static int tdfx_takedown(drm_device_t *dev)
-{
-	int		  i;
-	drm_magic_entry_t *pt, *next;
-	drm_map_t	  *map;
-	drm_vma_entry_t	  *vma, *vma_next;
-
-	DRM_DEBUG("\n");
-
-	down(&dev->struct_sem);
-	del_timer(&dev->timer);
-
-	if (dev->devname) {
-		drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER);
-		dev->devname = NULL;
-	}
-
-	if (dev->unique) {
-		drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER);
-		dev->unique = NULL;
-		dev->unique_len = 0;
-	}
-				/* Clear pid list */
-	for (i = 0; i < DRM_HASH_SIZE; i++) {
-		for (pt = dev->magiclist[i].head; pt; pt = next) {
-			next = pt->next;
-			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-		}
-		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
-	}
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-				/* Clear AGP information */
-	if (dev->agp) {
-		drm_agp_mem_t *temp;
-		drm_agp_mem_t *temp_next;
-
-		temp = dev->agp->memory;
-		while(temp != NULL) {
-			temp_next = temp->next;
-			drm_free_agp(temp->memory, temp->pages);
-			drm_free(temp, sizeof(*temp), DRM_MEM_AGPLISTS);
-			temp = temp_next;
-		}
-		if (dev->agp->acquired) _drm_agp_release();
-	}
-#endif
-				/* Clear vma list (only built for debugging) */
-	if (dev->vmalist) {
-		for (vma = dev->vmalist; vma; vma = vma_next) {
-			vma_next = vma->next;
-			drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
-		}
-		dev->vmalist = NULL;
-	}
-
-				/* Clear map area and mtrr information */
-	if (dev->maplist) {
-		for (i = 0; i < dev->map_count; i++) {
-			map = dev->maplist[i];
-			switch (map->type) {
-			case _DRM_REGISTERS:
-			case _DRM_FRAME_BUFFER:
-#ifdef CONFIG_MTRR
-				if (map->mtrr >= 0) {
-					int retcode;
-					retcode = mtrr_del(map->mtrr,
-							   map->offset,
-							   map->size);
-					DRM_DEBUG("mtrr_del = %d\n", retcode);
-				}
-#endif
-				drm_ioremapfree(map->handle, map->size);
-				break;
-			case _DRM_SHM:
-				drm_free_pages((unsigned long)map->handle,
-					       drm_order(map->size)
-					       - PAGE_SHIFT,
-					       DRM_MEM_SAREA);
-				break;
-			case _DRM_AGP:
-				/* Do nothing here, because this is all
-                                   handled in the AGP/GART driver. */
-				break;
-			}
-			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-		}
-		drm_free(dev->maplist,
-			 dev->map_count * sizeof(*dev->maplist),
-			 DRM_MEM_MAPS);
-		dev->maplist   = NULL;
-		dev->map_count = 0;
-	}
-
-	if (dev->lock.hw_lock) {
-		dev->lock.hw_lock    = NULL; /* SHM removed */
-		dev->lock.pid	     = 0;
-		wake_up_interruptible(&dev->lock.lock_queue);
-	}
-	up(&dev->struct_sem);
-
-	return 0;
-}
-
-/* tdfx_init is called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported). */
-
-static int __init tdfx_init(void)
-{
-	int		      retcode;
-	drm_device_t	      *dev = &tdfx_device;
-
-	DRM_DEBUG("\n");
-
-	memset((void *)dev, 0, sizeof(*dev));
-	dev->count_lock	  = SPIN_LOCK_UNLOCKED;
-	sema_init(&dev->struct_sem, 1);
-
-#ifdef MODULE
-	drm_parse_options(tdfx);
+__setup( DRIVER_NAME "=", tdfx_options );
 #endif
 
-	if ((retcode = misc_register(&tdfx_misc))) {
-		DRM_ERROR("Cannot register \"%s\"\n", TDFX_NAME);
-		return retcode;
-	}
-	dev->device = MKDEV(MISC_MAJOR, tdfx_misc.minor);
-	dev->name   = TDFX_NAME;
-
-	drm_mem_init();
-	drm_proc_init(dev);
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	dev->agp    = drm_agp_init();
-#endif
-	if((retcode = drm_ctxbitmap_init(dev))) {
-		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
-		drm_proc_cleanup();
-		misc_deregister(&tdfx_misc);
-		tdfx_takedown(dev);
-		return retcode;
-	}
-
-	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
-		 TDFX_NAME,
-		 TDFX_MAJOR,
-		 TDFX_MINOR,
-		 TDFX_PATCHLEVEL,
-		 TDFX_DATE,
-		 tdfx_misc.minor);
-
-	return 0;
-}
-
-/* tdfx_cleanup is called via cleanup_module at module unload time. */
-
-static void __exit tdfx_cleanup(void)
-{
-	drm_device_t	      *dev = &tdfx_device;
-
-	DRM_DEBUG("\n");
-
-	drm_proc_cleanup();
-	if (misc_deregister(&tdfx_misc)) {
-		DRM_ERROR("Cannot unload module\n");
-	} else {
-		DRM_INFO("Module unloaded\n");
-	}
-	drm_ctxbitmap_cleanup(dev);
-	tdfx_takedown(dev);
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-	if (dev->agp) {
-		drm_agp_uninit();
-		drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
-		dev->agp = NULL;
-	}
-#endif
-}
-
-module_init(tdfx_init);
-module_exit(tdfx_cleanup);
-
-
-int tdfx_version(struct inode *inode, struct file *filp, unsigned int cmd,
-		  unsigned long arg)
-{
-	drm_version_t version;
-	int	      len;
-
-	if (copy_from_user(&version,
-			   (drm_version_t *)arg,
-			   sizeof(version)))
-		return -EFAULT;
-
-#define DRM_COPY(name,value)				     \
-	len = strlen(value);				     \
-	if (len > name##_len) len = name##_len;		     \
-	name##_len = strlen(value);			     \
-	if (len && name) {				     \
-		if (copy_to_user(name, value, len))	     \
-			return -EFAULT;			     \
-	}
-
-	version.version_major	   = TDFX_MAJOR;
-	version.version_minor	   = TDFX_MINOR;
-	version.version_patchlevel = TDFX_PATCHLEVEL;
-
-	DRM_COPY(version.name, TDFX_NAME);
-	DRM_COPY(version.date, TDFX_DATE);
-	DRM_COPY(version.desc, TDFX_DESC);
-
-	if (copy_to_user((drm_version_t *)arg,
-			 &version,
-			 sizeof(version)))
-		return -EFAULT;
-	return 0;
-}
-
-int tdfx_open(struct inode *inode, struct file *filp)
-{
-	drm_device_t  *dev    = &tdfx_device;
-	int	      retcode = 0;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (!(retcode = drm_open_helper(inode, filp, dev))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-		atomic_inc(&dev->total_open);
-		spin_lock(&dev->count_lock);
-		if (!dev->open_count++) {
-			spin_unlock(&dev->count_lock);
-			return tdfx_setup(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-	return retcode;
-}
-
-int tdfx_release(struct inode *inode, struct file *filp)
-{
-	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev;
-	int	      retcode = 0;
-
-	lock_kernel();
-	dev = priv->dev;
-
-	DRM_DEBUG("open_count = %d\n", dev->open_count);
-	if (!(retcode = drm_release(inode, filp))) {
-#if LINUX_VERSION_CODE < 0x020333
-		MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-		atomic_inc(&dev->total_close);
-		spin_lock(&dev->count_lock);
-		if (!--dev->open_count) {
-			if (atomic_read(&dev->ioctl_count) || dev->blocked) {
-				DRM_ERROR("Device busy: %d %d\n",
-					  atomic_read(&dev->ioctl_count),
-					  dev->blocked);
-				spin_unlock(&dev->count_lock);
-				unlock_kernel();
-				return -EBUSY;
-			}
-			spin_unlock(&dev->count_lock);
-			unlock_kernel();
-			return tdfx_takedown(dev);
-		}
-		spin_unlock(&dev->count_lock);
-	}
-
-	unlock_kernel();
-	return retcode;
-}
-
-/* tdfx_ioctl is called whenever a process performs an ioctl on /dev/drm. */
-
-int tdfx_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
-{
-	int		 nr	 = DRM_IOCTL_NR(cmd);
-	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	int		 retcode = 0;
-	drm_ioctl_desc_t *ioctl;
-	drm_ioctl_t	 *func;
-
-	atomic_inc(&dev->ioctl_count);
-	atomic_inc(&dev->total_ioctl);
-	++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);
-
-	if (nr >= TDFX_IOCTL_COUNT) {
-		retcode = -EINVAL;
-	} else {
-		ioctl	  = &tdfx_ioctls[nr];
-		func	  = ioctl->func;
-
-		if (!func) {
-			DRM_DEBUG("no function\n");
-			retcode = -EINVAL;
-		} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
-			    || (ioctl->auth_needed && !priv->authenticated)) {
-			retcode = -EACCES;
-		} else {
-			retcode = (func)(inode, filp, cmd, arg);
-		}
-	}
-
-	atomic_dec(&dev->ioctl_count);
-	return retcode;
-}
-
-int tdfx_lock(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;
-        DECLARE_WAITQUEUE(entry, current);
-        int               ret   = 0;
-        drm_lock_t        lock;
-#if DRM_DMA_HISTOGRAM
-        cycles_t          start;
-
-        dev->lck_start = start = get_cycles();
-#endif
-
-        if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-        if (lock.context == DRM_KERNEL_CONTEXT) {
-                DRM_ERROR("Process %d using kernel context %d\n",
-                          current->pid, lock.context);
-                return -EINVAL;
-        }
-
-        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-                  lock.context, current->pid, dev->lock.hw_lock->lock,
-                  lock.flags);
-
-#if 0
-				/* dev->queue_count == 0 right now for
-                                   tdfx.  FIXME? */
-        if (lock.context < 0 || lock.context >= dev->queue_count)
-                return -EINVAL;
-#endif
-
-        if (!ret) {
-#if 0
-                if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
-                    != lock.context) {
-                        long j = jiffies - dev->lock.lock_time;
-
-                        if (lock.context == tdfx_res_ctx.handle &&
-				j >= 0 && j < DRM_LOCK_SLICE) {
-                                /* Can't take lock if we just had it and
-                                   there is contention. */
-                                DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n",
-					lock.context, current->pid, j,
-					dev->lock.lock_time, jiffies);
-                                current->state = TASK_INTERRUPTIBLE;
-				current->policy |= SCHED_YIELD;
-                                schedule_timeout(DRM_LOCK_SLICE-j);
-				DRM_DEBUG("jiffies=%d\n", jiffies);
-                        }
-                }
-#endif
-                add_wait_queue(&dev->lock.lock_queue, &entry);
-                for (;;) {
-                        current->state = TASK_INTERRUPTIBLE;
-                        if (!dev->lock.hw_lock) {
-                                /* Device has been unregistered */
-                                ret = -EINTR;
-                                break;
-                        }
-                        if (drm_lock_take(&dev->lock.hw_lock->lock,
-                                          lock.context)) {
-                                dev->lock.pid       = current->pid;
-                                dev->lock.lock_time = jiffies;
-                                atomic_inc(&dev->total_locks);
-                                break;  /* Got lock */
-                        }
-
-                                /* Contention */
-                        atomic_inc(&dev->total_sleeps);
-#if 1
-			current->policy |= SCHED_YIELD;
-#endif
-                        schedule();
-                        if (signal_pending(current)) {
-                                ret = -ERESTARTSYS;
-                                break;
-                        }
-                }
-                current->state = TASK_RUNNING;
-                remove_wait_queue(&dev->lock.lock_queue, &entry);
-        }
-
-#if 0
-	if (!ret && dev->last_context != lock.context &&
-		lock.context != tdfx_res_ctx.handle &&
-		dev->last_context != tdfx_res_ctx.handle) {
-		add_wait_queue(&dev->context_wait, &entry);
-	        current->state = TASK_INTERRUPTIBLE;
-                /* PRE: dev->last_context != lock.context */
-	        tdfx_context_switch(dev, dev->last_context, lock.context);
-		/* POST: we will wait for the context
-                   switch and will dispatch on a later call
-                   when dev->last_context == lock.context
-                   NOTE WE HOLD THE LOCK THROUGHOUT THIS
-                   TIME! */
-		current->policy |= SCHED_YIELD;
-	        schedule();
-	        current->state = TASK_RUNNING;
-	        remove_wait_queue(&dev->context_wait, &entry);
-	        if (signal_pending(current)) {
-	                ret = -EINTR;
-	        } else if (dev->last_context != lock.context) {
-			DRM_ERROR("Context mismatch: %d %d\n",
-                        	dev->last_context, lock.context);
-	        }
-	}
-#endif
-
-        if (!ret) {
-		sigemptyset(&dev->sigmask);
-		sigaddset(&dev->sigmask, SIGSTOP);
-		sigaddset(&dev->sigmask, SIGTSTP);
-		sigaddset(&dev->sigmask, SIGTTIN);
-		sigaddset(&dev->sigmask, SIGTTOU);
-		dev->sigdata.context = lock.context;
-		dev->sigdata.lock    = dev->lock.hw_lock;
-		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
-
-                if (lock.flags & _DRM_LOCK_READY) {
-				/* Wait for space in DMA/FIFO */
-		}
-                if (lock.flags & _DRM_LOCK_QUIESCENT) {
-				/* Make hardware quiescent */
-#if 0
-                        tdfx_quiescent(dev);
-#endif
-		}
-        }
-
-#if LINUX_VERSION_CODE < 0x020400
-	if (lock.context != tdfx_res_ctx.handle) {
-		current->counter = 5;
-		current->priority = DEF_PRIORITY/4;
-	}
-#endif
-        DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
-
-#if DRM_DMA_HISTOGRAM
-        atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
-#endif
-
-        return ret;
-}
-
-
-int tdfx_unlock(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_lock_t	  lock;
-
-	if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
-		return -EFAULT;
-
-	if (lock.context == DRM_KERNEL_CONTEXT) {
-		DRM_ERROR("Process %d using kernel context %d\n",
-			  current->pid, lock.context);
-		return -EINVAL;
-	}
-
-	DRM_DEBUG("%d frees lock (%d holds)\n",
-		  lock.context,
-		  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-	atomic_inc(&dev->total_unlocks);
-	if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
-		atomic_inc(&dev->total_contends);
-	drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
-				/* FIXME: Try to send data to card here */
-	if (!dev->context_flag) {
-		if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
-				  DRM_KERNEL_CONTEXT)) {
-			DRM_ERROR("\n");
-		}
-	}
-
-#if LINUX_VERSION_CODE < 0x020400
-	if (lock.context != tdfx_res_ctx.handle) {
-		current->counter = 5;
-		current->priority = DEF_PRIORITY;
-	}
-#endif
-
-	unblock_all_signals();
-	return 0;
-}
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff -urN linux-2.4.8-pre6/drivers/char/drm/tdfx_drv.h linux/drivers/char/drm/tdfx_drv.h
--- linux-2.4.8-pre6/drivers/char/drm/tdfx_drv.h	Thu Jul 27 15:05:40 2000
+++ linux/drivers/char/drm/tdfx_drv.h	Wed Dec 31 16:00:00 1969
@@ -1,67 +0,0 @@
-/* tdfx_drv.h -- Private header for tdfx driver -*- linux-c -*-
- * Created: Thu Oct  7 10:40:04 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>
- *    Daryll Strauss <daryll@valinux.com>
- * 
- */
-
-#ifndef _TDFX_DRV_H_
-#define _TDFX_DRV_H_
-
-				/* tdfx_drv.c */
-extern int  tdfx_version(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  tdfx_open(struct inode *inode, struct file *filp);
-extern int  tdfx_release(struct inode *inode, struct file *filp);
-extern int  tdfx_ioctl(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  tdfx_lock(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-extern int  tdfx_unlock(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-
-				/* tdfx_context.c */
-
-extern int  tdfx_resctx(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  tdfx_addctx(struct inode *inode, struct file *filp,
-		        unsigned int cmd, unsigned long arg);
-extern int  tdfx_modctx(struct inode *inode, struct file *filp,
-		        unsigned int cmd, unsigned long arg);
-extern int  tdfx_getctx(struct inode *inode, struct file *filp,
-		        unsigned int cmd, unsigned long arg);
-extern int  tdfx_switchctx(struct inode *inode, struct file *filp,
-			   unsigned int cmd, unsigned long arg);
-extern int  tdfx_newctx(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  tdfx_rmctx(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-
-extern int  tdfx_context_switch(drm_device_t *dev, int old, int new);
-extern int  tdfx_context_switch_complete(drm_device_t *dev, int new);
-#endif
diff -urN linux-2.4.8-pre6/drivers/char/drm/vm.c linux/drivers/char/drm/vm.c
--- linux-2.4.8-pre6/drivers/char/drm/vm.c	Sun Oct  1 20:00:00 2000
+++ linux/drivers/char/drm/vm.c	Wed Dec 31 16:00:00 1969
@@ -1,370 +0,0 @@
-/* vm.c -- Memory mapping for DRM -*- linux-c -*-
- * Created: Mon Jan  4 08:58:31 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>
- *
- */
-
-#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,
-};
-
-struct vm_operations_struct   drm_vm_shm_ops = {
-	nopage:	 drm_vm_shm_nopage,
-	open:	 drm_vm_open,
-	close:	 drm_vm_close,
-};
-
-struct vm_operations_struct   drm_vm_shm_lock_ops = {
-	nopage:	 drm_vm_shm_nopage_lock,
-	open:	 drm_vm_open,
-	close:	 drm_vm_close,
-};
-
-struct vm_operations_struct   drm_vm_dma_ops = {
-	nopage:	 drm_vm_dma_nopage,
-	open:	 drm_vm_open,
-	close:	 drm_vm_close,
-};
-
-#if LINUX_VERSION_CODE < 0x020317
-unsigned long drm_vm_nopage(struct vm_area_struct *vma,
-			    unsigned long address,
-			    int write_access)
-#else
-				/* Return type changed in 2.3.23 */
-struct page *drm_vm_nopage(struct vm_area_struct *vma,
-			   unsigned long address,
-			   int write_access)
-#endif
-{
-	return NOPAGE_SIGBUS;		/* Disallow mremap */
-}
-
-#if LINUX_VERSION_CODE < 0x020317
-unsigned long drm_vm_shm_nopage(struct vm_area_struct *vma,
-				unsigned long address,
-				int write_access)
-#else
-				/* Return type changed in 2.3.23 */
-struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
-			       unsigned long address,
-			       int write_access)
-#endif
-{
-#if LINUX_VERSION_CODE >= 0x020300
-	drm_map_t	 *map	 = (drm_map_t *)vma->vm_private_data;
-#else
-	drm_map_t	 *map	 = (drm_map_t *)vma->vm_pte;
-#endif
-	unsigned long	 physical;
-	unsigned long	 offset;
-
-	if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
-	if (!map)    		   return NOPAGE_OOM;  /* Nothing allocated */
-
-	offset	 = address - vma->vm_start;
-	physical = (unsigned long)map->handle + offset;
-	atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */
-
-	DRM_DEBUG("0x%08lx => 0x%08lx\n", address, physical);
-#if LINUX_VERSION_CODE < 0x020317
-	return physical;
-#else
-	return virt_to_page(physical);
-#endif
-}
-
-#if LINUX_VERSION_CODE < 0x020317
-unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
-				     unsigned long address,
-				     int write_access)
-#else
-				/* Return type changed in 2.3.23 */
-struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
-				    unsigned long address,
-				    int write_access)
-#endif
-{
-	drm_file_t	 *priv	 = vma->vm_file->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	unsigned long	 physical;
-	unsigned long	 offset;
-	unsigned long	 page;
-
-	if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
-	if (!dev->lock.hw_lock)    return NOPAGE_OOM;  /* Nothing allocated */
-
-	offset	 = address - vma->vm_start;
-	page	 = offset >> PAGE_SHIFT;
-	physical = (unsigned long)dev->lock.hw_lock + offset;
-	atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */
-
-	DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", address, page, physical);
-#if LINUX_VERSION_CODE < 0x020317
-	return physical;
-#else
-	return virt_to_page(physical);
-#endif
-}
-
-#if LINUX_VERSION_CODE < 0x020317
-unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma,
-				unsigned long address,
-				int write_access)
-#else
-				/* Return type changed in 2.3.23 */
-struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
-			       unsigned long address,
-			       int write_access)
-#endif
-{
-	drm_file_t	 *priv	 = vma->vm_file->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	drm_device_dma_t *dma	 = dev->dma;
-	unsigned long	 physical;
-	unsigned long	 offset;
-	unsigned long	 page;
-
-	if (!dma)		   return NOPAGE_SIGBUS; /* Error */
-	if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
-	if (!dma->pagelist)	   return NOPAGE_OOM ; /* Nothing allocated */
-
-	offset	 = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */
-	page	 = offset >> PAGE_SHIFT;
-	physical = dma->pagelist[page] + (offset & (~PAGE_MASK));
-	atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */
-
-	DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", address, page, physical);
-#if LINUX_VERSION_CODE < 0x020317
-	return physical;
-#else
-	return virt_to_page(physical);
-#endif
-}
-
-void drm_vm_open(struct vm_area_struct *vma)
-{
-	drm_file_t	*priv	= vma->vm_file->private_data;
-	drm_device_t	*dev	= priv->dev;
-#if DRM_DEBUG_CODE
-	drm_vma_entry_t *vma_entry;
-#endif
-
-	DRM_DEBUG("0x%08lx,0x%08lx\n",
-		  vma->vm_start, vma->vm_end - vma->vm_start);
-	atomic_inc(&dev->vma_count);
-#if LINUX_VERSION_CODE < 0x020333
-				/* The map can exist after the fd is closed. */
-	MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-
-
-#if DRM_DEBUG_CODE
-	vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
-	if (vma_entry) {
-		down(&dev->struct_sem);
-		vma_entry->vma	= vma;
-		vma_entry->next = dev->vmalist;
-		vma_entry->pid	= current->pid;
-		dev->vmalist	= vma_entry;
-		up(&dev->struct_sem);
-	}
-#endif
-}
-
-void drm_vm_close(struct vm_area_struct *vma)
-{
-	drm_file_t	*priv	= vma->vm_file->private_data;
-	drm_device_t	*dev	= priv->dev;
-#if DRM_DEBUG_CODE
-	drm_vma_entry_t *pt, *prev;
-#endif
-
-	DRM_DEBUG("0x%08lx,0x%08lx\n",
-		  vma->vm_start, vma->vm_end - vma->vm_start);
-#if LINUX_VERSION_CODE < 0x020333
-	MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
-#endif
-	atomic_dec(&dev->vma_count);
-
-#if DRM_DEBUG_CODE
-	down(&dev->struct_sem);
-	for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
-		if (pt->vma == vma) {
-			if (prev) {
-				prev->next = pt->next;
-			} else {
-				dev->vmalist = pt->next;
-			}
-			drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
-			break;
-		}
-	}
-	up(&dev->struct_sem);
-#endif
-}
-
-int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
-{
-	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev;
-	drm_device_dma_t *dma;
-	unsigned long	 length	 = vma->vm_end - vma->vm_start;
-	
-	lock_kernel();
-	dev	 = priv->dev;
-	dma	 = dev->dma;
-	DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
-		  vma->vm_start, vma->vm_end, VM_OFFSET(vma));
-
-				/* Length must match exact page count */
-	if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
-		unlock_kernel();
-		return -EINVAL;
-	}
-	unlock_kernel();
-
-	vma->vm_ops   = &drm_vm_dma_ops;
-	vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
-	
-#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
-				/* In Linux 2.2.3 and above, this is
-				   handled in do_mmap() in mm/mmap.c. */
-	++filp->f_count;
-#endif
-	vma->vm_file  =	 filp;	/* Needed for drm_vm_open() */
-	drm_vm_open(vma);
-	return 0;
-}
-
-int drm_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	drm_file_t	*priv	= filp->private_data;
-	drm_device_t	*dev	= priv->dev;
-	drm_map_t	*map	= NULL;
-	int		i;
-	
-	DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
-		  vma->vm_start, vma->vm_end, VM_OFFSET(vma));
-
-	if (!VM_OFFSET(vma)) return drm_mmap_dma(filp, vma);
-
-				/* A sequential search of a linked list is
-				   fine here because: 1) there will only be
-				   about 5-10 entries in the list and, 2) a
-				   DRI client only has to do this mapping
-				   once, so it doesn't have to be optimized
-				   for performance, even if the list was a
-				   bit longer. */
-	for (i = 0; i < dev->map_count; i++) {
-		map = dev->maplist[i];
-		if (map->offset == VM_OFFSET(vma)) break;
-	}
-	
-	if (i >= dev->map_count) return -EINVAL;
-	if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
-		return -EPERM;
-
-				/* Check for valid size. */
-	if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
-	
-	if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
-		vma->vm_flags &= VM_MAYWRITE;
-#if defined(__i386__)
-		pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
-#else
-				/* Ye gads this is ugly.  With more thought
-                                   we could move this up higher and use
-                                   `protection_map' instead.  */
-		vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
-			__pte(pgprot_val(vma->vm_page_prot)))));
-#endif
-	}
-
-	switch (map->type) {
-	case _DRM_FRAME_BUFFER:
-	case _DRM_REGISTERS:
-	case _DRM_AGP:
-		if (VM_OFFSET(vma) >= __pa(high_memory)) {
-#if defined(__i386__)
-			if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
-				pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-				pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
-			}
-#elif defined(__ia64__)
-			if (map->type != _DRM_AGP)
-				vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-#endif
-			vma->vm_flags |= VM_IO;	/* not in core dump */
-		}
-		if (remap_page_range(vma->vm_start,
-				     VM_OFFSET(vma),
-				     vma->vm_end - vma->vm_start,
-				     vma->vm_page_prot))
-				return -EAGAIN;
-		DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
-			  " offset = 0x%lx\n",
-			  map->type,
-			  vma->vm_start, vma->vm_end, VM_OFFSET(vma));
-		vma->vm_ops = &drm_vm_ops;
-		break;
-	case _DRM_SHM:
-		if (map->flags & _DRM_CONTAINS_LOCK)
-			vma->vm_ops = &drm_vm_shm_lock_ops;
-		else {
-			vma->vm_ops = &drm_vm_shm_ops;
-#if LINUX_VERSION_CODE >= 0x020300
-			vma->vm_private_data = (void *)map;
-#else
-			vma->vm_pte = (unsigned long)map;
-#endif
-		}
-
-				/* Don't let this area swap.  Change when
-				   DRM_KERNEL advisory is supported. */
-		vma->vm_flags |= VM_LOCKED;
-		break;
-	default:
-		return -EINVAL;	/* This should never happen. */
-	}
-	vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
-
-#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
-				/* In Linux 2.2.3 and above, this is
-				   handled in do_mmap() in mm/mmap.c. */
-	++filp->f_count;
-#endif
-	vma->vm_file  =	 filp;	/* Needed for drm_vm_open() */
-	drm_vm_open(vma);
-	return 0;
-}
diff -urN linux-2.4.8-pre6/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.8-pre6/fs/buffer.c	Mon Dec  3 22:59:37 2001
+++ linux/fs/buffer.c	Mon Dec  3 22:59:46 2001
@@ -231,6 +231,7 @@
 			return -EAGAIN;
 		}
 		unlock_buffer(bh);
+		__refile_buffer(bh);
 	}
 	spin_unlock(&lru_list_lock);
 
@@ -1116,15 +1117,17 @@
 	/* If we're getting into imbalance, start write-out */
 	spin_lock(&lru_list_lock);
 	write_some_buffers(dev);
-	wakeup_bdflush();
 
 	/*
 	 * And if we're _really_ out of balance, wait for
-	 * some of the dirty/locked buffers ourselves.
+	 * some of the dirty/locked buffers ourselves and
+	 * start bdflush.
 	 * This will throttle heavy writers.
 	 */
-	if (state > 0)
+	if (state > 0) {
 		wait_for_some_buffers(dev);
+		wakeup_bdflush();
+	}
 }
 
 static __inline__ void __mark_dirty(struct buffer_head *bh)
diff -urN linux-2.4.8-pre6/include/linux/swap.h linux/include/linux/swap.h
--- linux-2.4.8-pre6/include/linux/swap.h	Mon Dec  3 22:59:37 2001
+++ linux/include/linux/swap.h	Mon Dec  3 22:59:46 2001
@@ -125,10 +125,6 @@
 extern void wakeup_kswapd(void);
 extern int try_to_free_pages(unsigned int gfp_mask);
 
-extern unsigned int zone_free_shortage(zone_t *zone);
-extern unsigned int zone_inactive_shortage(zone_t *zone);
-extern unsigned int zone_inactive_plenty(zone_t *zone);
-
 /* linux/mm/page_io.c */
 extern void rw_swap_page(int, struct page *);
 extern void rw_swap_page_nolock(int, swp_entry_t, char *);
diff -urN linux-2.4.8-pre6/mm/page_alloc.c linux/mm/page_alloc.c
--- linux-2.4.8-pre6/mm/page_alloc.c	Mon Dec  3 22:59:37 2001
+++ linux/mm/page_alloc.c	Mon Dec  3 22:59:46 2001
@@ -585,25 +585,23 @@
  */
 unsigned int nr_free_buffer_pages (void)
 {
-	unsigned int sum;
-
-	sum = nr_free_pages();
-	sum += nr_inactive_clean_pages();
-	sum += nr_inactive_dirty_pages;
-
-	/*
-	 * Keep our write behind queue filled, even if
-	 * kswapd lags a bit right now.
-	 */
-	if (sum < freepages.high + inactive_target)
-		sum = freepages.high + inactive_target;
-	/*
-	 * We don't want dirty page writebehind to put too
-	 * much pressure on the working set, but we want it
-	 * to be possible to have some dirty pages in the
-	 * working set without upsetting the writebehind logic.
-	 */
-	sum += nr_active_pages >> 4;
+	unsigned int sum = 0;
+	zonelist_t *zonelist;
+	zone_t **zonep, *zone;
+
+	zonelist = contig_page_data.node_zonelists + (GFP_KERNEL & GFP_ZONEMASK);
+	zonep = zonelist->zones;
+
+	for (zone = *zonep++; zone; zone = *zonep++) {
+		unsigned int pages = zone->free_pages +
+			zone->inactive_clean_pages +
+			zone->inactive_dirty_pages;
+
+		/* Allow the buffer cache to fill up at least "pages_high" pages */
+		if (pages < zone->pages_high)
+			pages = zone->pages_high;
+		sum += pages;
+	}
 
 	return sum;
 }
@@ -621,53 +619,6 @@
 	return pages;
 }
 #endif
-
-unsigned int zone_free_shortage(zone_t *zone)
-{
-	int sum = 0;
-
-	if (!zone->size)
-		goto ret;
-
-	if (zone->inactive_clean_pages + zone->free_pages
-			< zone->pages_high) {
-		sum += zone->pages_high;
-		sum -= zone->free_pages;
-		sum -= zone->inactive_clean_pages;
-	}
-ret:
-	return sum;
-}
-
-unsigned int zone_inactive_plenty(zone_t *zone)
-{
-	int inactive;
-
-	if (!zone->size)
-		return 0;
-		
-	inactive = zone->inactive_dirty_pages;
-	inactive += zone->inactive_clean_pages;
-	inactive += zone->free_pages;
-
-	return (inactive > (zone->size / 3));
-
-}
-unsigned int zone_inactive_shortage(zone_t *zone) 
-{
-	int sum = 0;
-
-	if (!zone->size)
-		goto ret;
-
-	sum = zone->pages_high;
-	sum -= zone->inactive_dirty_pages;
-	sum -= zone->inactive_clean_pages;
-	sum -= zone->free_pages;
-
-ret:
-     return (sum > 0 ? sum : 0);
-}
 
 /*
  * Show free area list (used inside shift_scroll-lock stuff)
diff -urN linux-2.4.8-pre6/mm/vmscan.c linux/mm/vmscan.c
--- linux-2.4.8-pre6/mm/vmscan.c	Mon Dec  3 22:59:37 2001
+++ linux/mm/vmscan.c	Mon Dec  3 22:59:46 2001
@@ -35,6 +35,58 @@
  * doesn't count as having freed a page.
  */
 
+/*
+ * Estimate whether a zone has enough inactive or free pages..
+ */
+static unsigned int zone_inactive_plenty(zone_t *zone)
+{
+	unsigned int inactive;
+
+	if (!zone->size)
+		return 0;
+		
+	inactive = zone->inactive_dirty_pages;
+	inactive += zone->inactive_clean_pages;
+	inactive += zone->free_pages;
+
+	return (inactive > (zone->size / 3));
+}
+
+static unsigned int zone_inactive_shortage(zone_t *zone) 
+{
+	unsigned int inactive;
+
+	if (!zone->size)
+		return 0;
+
+	inactive = zone->inactive_dirty_pages;
+	inactive += zone->inactive_clean_pages;
+	inactive += zone->free_pages;
+
+	return inactive < zone->pages_high;
+}
+
+static unsigned int zone_free_plenty(zone_t *zone)
+{
+	unsigned int free;
+
+	free = zone->free_pages;
+	free += zone->inactive_clean_pages;
+
+	return free > zone->pages_high*2;
+}
+
+static unsigned int zone_free_shortage(zone_t *zone)
+{
+	unsigned int free;
+
+	free = zone->free_pages;
+	free += zone->inactive_clean_pages;
+
+	return zone->size && free < zone->pages_low;
+}
+
+
 /* mm->page_table_lock is held. mmap_sem is not held */
 static void try_to_swap_out(struct mm_struct * mm, struct vm_area_struct* vma, unsigned long address, pte_t * page_table, struct page *page)
 {
@@ -434,7 +486,7 @@
 #define MAX_LAUNDER 		(4 * (1 << page_cluster))
 #define CAN_DO_FS		(gfp_mask & __GFP_FS)
 #define CAN_DO_IO		(gfp_mask & __GFP_IO)
-int do_page_launder(zone_t *zone, int gfp_mask, int sync)
+int page_launder(int gfp_mask, int sync)
 {
 	int launder_loop, maxscan, cleaned_pages, maxlaunder;
 	struct list_head * page_lru;
@@ -470,11 +522,10 @@
 		}
 
 		/* 
-		 * If we are doing zone-specific laundering, 
-		 * avoid touching pages from zones which do 
-		 * not have a free shortage.
+		 * If this zone has plenty of pages free,
+		 * don't spend time on cleaning it.
 		 */
-		if (zone && !zone_free_shortage(page->zone)) {
+		if (zone_free_plenty(page->zone)) {
 			list_del(page_lru);
 			list_add(page_lru, &inactive_dirty_list);
 			continue;
@@ -649,31 +700,6 @@
 	return cleaned_pages;
 }
 
-int page_launder(int gfp_mask, int sync)
-{
-	int type = 0, ret = 0;
-	pg_data_t *pgdat = pgdat_list;
-	/*
-	 * First do a global scan if there is a 
-	 * global shortage.
-	 */
-	if (free_shortage())
-		ret += do_page_launder(NULL, gfp_mask, sync);
-
-	/*
-	 * Then check if there is any specific zone 
-	 * needs laundering.
-	 */
-	for (type = 0; type < MAX_NR_ZONES; type++) {
-		zone_t *zone = pgdat->node_zones + type;
-		
-		if (zone_free_shortage(zone)) 
-			ret += do_page_launder(zone, gfp_mask, sync);
-	} 
-
-	return ret;
-}
-
 static inline void age_page_up(struct page *page)
 {
 	unsigned age = page->age + PAGE_AGE_ADV;
@@ -807,12 +833,8 @@
 		int i;
 		for(i = 0; i < MAX_NR_ZONES; i++) {
 			zone_t *zone = pgdat->node_zones+ i;
-			if (zone->size && (zone->inactive_clean_pages +
-					zone->free_pages < zone->pages_min)) {
-				sum += zone->pages_min;
-				sum -= zone->free_pages;
-				sum -= zone->inactive_clean_pages;
-			}
+
+			sum += zone_free_shortage(zone);
 		}
 		pgdat = pgdat->node_next;
 	} while (pgdat);
