# HG changeset patch
# User Hasso Tepper <hasso@estpak.ee>
# Date 1225264822 -7200
# Branch HEAD
# Node ID c661915aa9ecbfc3be14a26f897a0e2856b445ee
# Parent  e6f0a51f5688945b4a0a4598221b2b8f40bf6699
Update DRM code to the latest one (e2ebd033a8ecf9661d9c2936455ce2ff9ba5dccb).

diff --git a/sys/dev/drm/ati_pcigart.c b/sys/dev/drm/ati_pcigart.c
--- a/sys/dev/drm/ati_pcigart.c
+++ b/sys/dev/drm/ati_pcigart.c
@@ -35,74 +35,188 @@
 #include "drmP.h"
 
 #define ATI_PCIGART_PAGE_SIZE		4096	/* PCI GART page size */
+#define ATI_PCIGART_PAGE_MASK		(~(ATI_PCIGART_PAGE_SIZE-1))
 
-int drm_ati_pcigart_init(drm_device_t *dev, struct drm_ati_pcigart_info *gart_info)
+#define ATI_PCIE_WRITE 0x4
+#define ATI_PCIE_READ 0x8
+
+static void
+drm_ati_alloc_pcigart_table_cb(void *arg, bus_dma_segment_t *segs,
+			       int nsegs, int error)
 {
-	unsigned long pages;
-	u32 *pci_gart = NULL, page_base;
-	int i, j;
+	struct drm_dma_handle *dmah = arg;
 
+	if (error != 0)
+		return;
+
+	KASSERT(nsegs == 1,
+	    ("drm_ati_alloc_pcigart_table_cb: bad dma segment count"));
+
+	dmah->busaddr = segs[0].ds_addr;
+}
+
+static int
+drm_ati_alloc_pcigart_table(struct drm_device *dev,
+			    struct drm_ati_pcigart_info *gart_info)
+{
+	struct drm_dma_handle *dmah;
+	int flags, ret;
+
+	dmah = malloc(sizeof(struct drm_dma_handle), DRM_MEM_DMA,
+	    M_ZERO | M_NOWAIT);
+	if (dmah == NULL)
+		return ENOMEM;
+
+	DRM_UNLOCK();
+	ret = bus_dma_tag_create(NULL, PAGE_SIZE, 0, /* tag, align, boundary */
+	    gart_info->table_mask, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
+	    NULL, NULL, /* filtfunc, filtfuncargs */
+	    gart_info->table_size, 1, /* maxsize, nsegs */
+	    gart_info->table_size, /* maxsegsize */
+	    BUS_DMA_ALLOCNOW, /* flags */
+	    &dmah->tag);
+	if (ret != 0) {
+		free(dmah, DRM_MEM_DMA);
+		return ENOMEM;
+	}
+
+	flags = BUS_DMA_NOWAIT | BUS_DMA_ZERO;
+#if 0 /* XXX - not yet */
+	if (gart_info->gart_reg_if == DRM_ATI_GART_IGP)
+	    flags |= BUS_DMA_NOCACHE;
+#endif
+	
+	ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr, flags, &dmah->map);
+	if (ret != 0) {
+		bus_dma_tag_destroy(dmah->tag);
+		free(dmah, DRM_MEM_DMA);
+		return ENOMEM;
+	}
+	DRM_LOCK();
+
+	ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr,
+	    gart_info->table_size, drm_ati_alloc_pcigart_table_cb, dmah, 0);
+	if (ret != 0) {
+		bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+		bus_dma_tag_destroy(dmah->tag);
+		free(dmah, DRM_MEM_DMA);
+		return ENOMEM;
+	}
+
+	dev->sg->dmah = dmah;
+
+	return 0;
+}
+
+static void
+drm_ati_free_pcigart_table(struct drm_device *dev,
+			   struct drm_ati_pcigart_info *gart_info)
+{
+	struct drm_dma_handle *dmah = dev->sg->dmah;
+
+	bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+	bus_dma_tag_destroy(dmah->tag);
+	free(dmah, DRM_MEM_DMA);
+	dev->sg->dmah = NULL;
+}
+
+int
+drm_ati_pcigart_cleanup(struct drm_device *dev,
+			struct drm_ati_pcigart_info *gart_info)
+{
+	/* we need to support large memory configurations */
 	if (dev->sg == NULL) {
-		DRM_ERROR( "no scatter/gather memory!\n" );
+		DRM_ERROR("no scatter/gather memory!\n");
 		return 0;
 	}
 
-	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
-		/* GART table in system memory */
-		dev->sg->dmah = drm_pci_alloc(dev, gart_info->table_size, 0,
-		    0xfffffffful);
-		if (dev->sg->dmah == NULL) {
-			DRM_ERROR("cannot allocate PCI GART table!\n");
-			return 0;
-		}
-	
-		gart_info->addr = (void *)dev->sg->dmah->vaddr;
-		gart_info->bus_addr = dev->sg->dmah->busaddr;
-		pci_gart = (u32 *)dev->sg->dmah->vaddr;
-	} else {
-		/* GART table in framebuffer memory */
-		pci_gart = gart_info->addr;
-	}
-	
-	pages = DRM_MIN(dev->sg->pages, gart_info->table_size / sizeof(u32));
-
-	bzero(pci_gart, gart_info->table_size);
-
-	KASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE, ("page size too small"));
-
-	for ( i = 0 ; i < pages ; i++ ) {
-		page_base = (u32) dev->sg->busaddr[i];
-
-		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
-			switch(gart_info->gart_reg_if) {
-			case DRM_ATI_GART_IGP:
-				*pci_gart = cpu_to_le32(page_base | 0xc);
-				break;
-			case DRM_ATI_GART_PCIE:
-				*pci_gart = cpu_to_le32((page_base >> 8) | 0xc);
-				break;
-			default:
-				*pci_gart = cpu_to_le32(page_base);
-				break;
-			}
-			pci_gart++;
-			page_base += ATI_PCIGART_PAGE_SIZE;
+	if (gart_info->bus_addr) {
+		if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
+			gart_info->bus_addr = 0;
+			if (dev->sg->dmah)
+				drm_ati_free_pcigart_table(dev, gart_info);
 		}
 	}
-
-	DRM_MEMORYBARRIER();
 
 	return 1;
 }
 
-int drm_ati_pcigart_cleanup(drm_device_t *dev, struct drm_ati_pcigart_info *gart_info)
+int
+drm_ati_pcigart_init(struct drm_device *dev,
+		     struct drm_ati_pcigart_info *gart_info)
 {
+	void *address = NULL;
+	unsigned long pages;
+	u32 *pci_gart, page_base;
+	dma_addr_t bus_address = 0;
+	dma_addr_t entry_addr;
+	int i, j, ret = 0;
+	int max_pages;
+
+	/* we need to support large memory configurations */
 	if (dev->sg == NULL) {
-		DRM_ERROR( "no scatter/gather memory!\n" );
-		return 0;
+		DRM_ERROR("no scatter/gather memory!\n");
+		goto done;
 	}
 
-	drm_pci_free(dev, dev->sg->dmah);
+	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
+		DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
 
-	return 1;
+		ret = drm_ati_alloc_pcigart_table(dev, gart_info);
+		if (ret) {
+			DRM_ERROR("cannot allocate PCI GART page!\n");
+			goto done;
+		}
+
+		address = (void *)dev->sg->dmah->vaddr;
+		bus_address = dev->sg->dmah->busaddr;
+	} else {
+		address = gart_info->addr;
+		bus_address = gart_info->bus_addr;
+		DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
+			  (unsigned int)bus_address, (unsigned long)address);
+	}
+
+	pci_gart = (u32 *) address;
+
+	max_pages = (gart_info->table_size / sizeof(u32));
+	pages = (dev->sg->pages <= max_pages)
+	    ? dev->sg->pages : max_pages;
+
+	memset(pci_gart, 0, max_pages * sizeof(u32));
+
+	KASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE, ("page size too small"));
+
+	for (i = 0; i < pages; i++) {
+		entry_addr = dev->sg->busaddr[i];
+		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
+			page_base = (u32) entry_addr & ATI_PCIGART_PAGE_MASK;
+			switch(gart_info->gart_reg_if) {
+			case DRM_ATI_GART_IGP:
+				page_base |=
+				    (upper_32_bits(entry_addr) & 0xff) << 4;
+				page_base |= 0xc;
+				break;
+			case DRM_ATI_GART_PCIE:
+				page_base >>= 8;
+				page_base |=
+				    (upper_32_bits(entry_addr) & 0xff) << 24;
+				page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE;
+				break;
+			default:
+			case DRM_ATI_GART_PCI:
+				break;
+			}
+			*pci_gart = cpu_to_le32(page_base);
+			pci_gart++;
+			entry_addr += ATI_PCIGART_PAGE_SIZE;
+		}
+	}
+
+	ret = 1;
+
+    done:
+	gart_info->addr = address;
+	gart_info->bus_addr = bus_address;
+	return ret;
 }
diff --git a/sys/dev/drm/drm.h b/sys/dev/drm/drm.h
--- a/sys/dev/drm/drm.h
+++ b/sys/dev/drm/drm.h
@@ -557,6 +557,20 @@
 	struct drm_wait_vblank_reply reply;
 };
 
+
+#define _DRM_PRE_MODESET 1
+#define _DRM_POST_MODESET 2
+
+/**
+ * DRM_IOCTL_MODESET_CTL ioctl argument type
+ *
+ * \sa drmModesetCtl().
+ */
+struct drm_modeset_ctl {
+	uint32_t crtc;
+	uint32_t cmd;
+};
+
 /**
  * DRM_IOCTL_AGP_ENABLE ioctl argument type.
  *
@@ -632,8 +646,14 @@
 
 #define DRM_FENCE_FLAG_EMIT                0x00000001
 #define DRM_FENCE_FLAG_SHAREABLE           0x00000002
+/**
+ * On hardware with no interrupt events for operation completion,
+ * indicates that the kernel should sleep while waiting for any blocking
+ * operation to complete rather than spinning.
+ *
+ * Has no effect otherwise.
+ */
 #define DRM_FENCE_FLAG_WAIT_LAZY           0x00000004
-#define DRM_FENCE_FLAG_WAIT_IGNORE_SIGNALS 0x00000008
 #define DRM_FENCE_FLAG_NO_USER             0x00000010
 
 /* Reserved for driver use */
@@ -707,7 +727,14 @@
  */
 #define DRM_BO_FLAG_NO_MOVE     (1ULL << 8)
 
-/* Mask: Make sure the buffer is in cached memory when mapped
+/* Mask: Make sure the buffer is in cached memory when mapped.  In conjunction
+ * with DRM_BO_FLAG_CACHED it also allows the buffer to be bound into the GART
+ * with unsnooped PTEs instead of snooped, by using chipset-specific cache
+ * flushing at bind time.  A better name might be DRM_BO_FLAG_TT_UNSNOOPED,
+ * as the eviction to local memory (TTM unbind) on map is just a side effect
+ * to prevent aggressive cache prefetch from the GPU disturbing the cache
+ * management that the DRM is doing.
+ *
  * Flags: Acknowledge.
  * Buffers allocated with this flag should not be used for suballocators
  * This type may have issues on CPUs with over-aggressive caching
@@ -775,13 +802,12 @@
  * with it as a result of this operation
  */
 #define DRM_BO_HINT_DONT_FENCE  0x00000004
-/*
- * Sleep while waiting for the operation to complete.
- * Without this flag, the kernel will, instead, spin
- * until this operation has completed. I'm not sure
- * why you would ever want this, so please always
- * provide DRM_BO_HINT_WAIT_LAZY to any operation
- * which may block
+/**
+ * On hardware with no interrupt events for operation completion,
+ * indicates that the kernel should sleep while waiting for any blocking
+ * operation to complete rather than spinning.
+ *
+ * Has no effect otherwise.
  */
 #define DRM_BO_HINT_WAIT_LAZY   0x00000008
 /*
@@ -930,6 +956,36 @@
 	uint64_t p_size;
 };
 
+struct drm_mm_info_arg {
+	unsigned int mem_type;
+	uint64_t p_size;
+};
+
+struct drm_gem_close {
+	/** Handle of the object to be closed. */
+	uint32_t handle;
+	uint32_t pad;
+};
+
+struct drm_gem_flink {
+	/** Handle for the object being named */
+	uint32_t handle;
+
+	/** Returned global name */
+	uint32_t name;
+};
+
+struct drm_gem_open {
+	/** Name of object being opened */
+	uint32_t name;
+
+	/** Returned handle for the object */
+	uint32_t handle;
+	
+	/** Returned size of the object */
+	uint64_t size;
+};
+
 /**
  * \name Ioctls Definitions
  */
@@ -949,6 +1005,11 @@
 #define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
 #define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
 #define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, struct drm_set_version)
+#define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08,  struct drm_modeset_ctl)
+
+#define DRM_IOCTL_GEM_CLOSE		DRM_IOW (0x09, struct drm_gem_close)
+#define DRM_IOCTL_GEM_FLINK		DRM_IOWR(0x0a, struct drm_gem_flink)
+#define DRM_IOCTL_GEM_OPEN		DRM_IOWR(0x0b, struct drm_gem_open)
 
 #define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, struct drm_unique)
 #define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, struct drm_auth)
@@ -990,7 +1051,7 @@
 #define DRM_IOCTL_AGP_BIND		DRM_IOW( 0x36, struct drm_agp_binding)
 #define DRM_IOCTL_AGP_UNBIND		DRM_IOW( 0x37, struct drm_agp_binding)
 
-#define DRM_IOCTL_SG_ALLOC		DRM_IOW( 0x38, struct drm_scatter_gather)
+#define DRM_IOCTL_SG_ALLOC		DRM_IOWR(0x38, struct drm_scatter_gather)
 #define DRM_IOCTL_SG_FREE		DRM_IOW( 0x39, struct drm_scatter_gather)
 
 #define DRM_IOCTL_WAIT_VBLANK		DRM_IOWR(0x3a, union drm_wait_vblank)
@@ -1020,7 +1081,7 @@
 #define DRM_IOCTL_BO_INFO               DRM_IOWR(0xd4, struct drm_bo_reference_info_arg)
 #define DRM_IOCTL_BO_WAIT_IDLE          DRM_IOWR(0xd5, struct drm_bo_map_wait_idle_arg)
 #define DRM_IOCTL_BO_VERSION          DRM_IOR(0xd6, struct drm_bo_version_arg)
-
+#define DRM_IOCTL_MM_INFO               DRM_IOWR(0xd7, struct drm_mm_info_arg)
 
 /*@}*/
 
@@ -1036,8 +1097,7 @@
 #define DRM_COMMAND_END                 0xA0
 
 /* typedef area */
-#if !defined(__KERNEL__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
-    defined(__NetBSD__) || defined(__DragonFly__)
+#ifndef __KERNEL__
 typedef struct drm_clip_rect drm_clip_rect_t;
 typedef struct drm_tex_region drm_tex_region_t;
 typedef struct drm_hw_lock drm_hw_lock_t;
diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h
--- a/sys/dev/drm/drmP.h
+++ b/sys/dev/drm/drmP.h
@@ -37,8 +37,8 @@
 
 #if defined(_KERNEL) || defined(__KERNEL__)
 
-typedef struct drm_device drm_device_t;
-typedef struct drm_file drm_file_t;
+struct drm_device;
+struct drm_file;
 
 #include <sys/param.h>
 #include <sys/queue.h>
@@ -48,9 +48,6 @@
 #include <sys/systm.h>
 #include <sys/conf.h>
 #include <sys/stat.h>
-#if __FreeBSD_version >= 700000
-#include <sys/priv.h>
-#endif
 #include <sys/proc.h>
 #include <sys/lock.h>
 #include <sys/fcntl.h>
@@ -58,6 +55,7 @@
 #include <sys/filio.h>
 #include <sys/sysctl.h>
 #include <sys/bus.h>
+#include <sys/resource.h>
 #include <sys/signalvar.h>
 #include <sys/poll.h>
 #include <sys/tree.h>
@@ -69,56 +67,19 @@
 #include <vm/vm_param.h>
 #include <machine/param.h>
 #include <machine/pmap.h>
-#ifdef __DragonFly__
-#include <sys/bus.h>
-#include <sys/resource.h>
-#else
-#include <machine/bus.h>
-#include <machine/resource.h>
-#endif
+#include <machine/specialreg.h>
 #include <machine/sysarch.h>
 #include <sys/endian.h>
 #include <sys/mman.h>
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 #include <sys/rman.h>
 #include <sys/memrange.h>
-#if __FreeBSD_version >= 800004 || defined(__DragonFly__)
 #include <dev/agp/agpvar.h>
-#else /* __FreeBSD_version >= 800004 */
-#include <pci/agpvar.h>
-#endif /* __FreeBSD_version >= 800004 */
 #include <sys/agpio.h>
-#if defined(__DragonFly__)
+#include <sys/device.h>
 #include <sys/thread2.h>
-#include <sys/device.h>
-#include <sys/spinlock2.h>
+#include <sys/lock.h>
 #include <bus/pci/pcivar.h>
 #include <sys/selinfo.h>
-#elif __FreeBSD_version >= 500000
-#include <sys/mutex.h>
-#include <dev/pci/pcivar.h>
-#include <sys/selinfo.h>
-#else /* __FreeBSD_version >= 500000 */
-#include <pci/pcivar.h>
-#include <sys/select.h>
-#endif /* __FreeBSD_version < 500000 */
-#elif defined(__NetBSD__)
-#include <machine/mtrr.h>
-#include <sys/vnode.h>
-#include <sys/select.h>
-#include <sys/device.h>
-#include <sys/resourcevar.h>
-#include <sys/lkm.h>
-#include <sys/agpio.h>
-#include <sys/ttycom.h>
-#include <uvm/uvm.h>
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-#include <dev/pci/agpvar.h>
-#elif defined(__OpenBSD__)
-#include <sys/lkm.h>
-#include <uvm/uvm.h>
-#endif
 #include <sys/bus.h>
 
 #include "drm.h"
@@ -126,52 +87,49 @@
 #include "drm_atomic.h"
 #include "drm_internal.h"
 
-#ifdef __FreeBSD__
 #include <opt_drm.h>
 #ifdef DRM_DEBUG
 #undef DRM_DEBUG
 #define DRM_DEBUG_DEFAULT_ON 1
 #endif /* DRM_DEBUG */
-#endif
 
-#if defined(DRM_LINUX) && DRM_LINUX && !defined(__amd64__)
-#include <sys/file.h>
-#include <sys/proc.h>
-#include <machine/../linux/linux.h>
-#include <machine/../linux/linux_proto.h>
-#else
-/* Either it was defined when it shouldn't be (FreeBSD amd64) or it isn't
- * supported on this OS yet.
- */
+/* XXX - not yet */
 #undef DRM_LINUX
 #define DRM_LINUX 0
-#endif
+
+/* driver capabilities and requirements mask */
+#define DRIVER_USE_AGP     0x1
+#define DRIVER_REQUIRE_AGP 0x2
+#define DRIVER_USE_MTRR    0x4
+#define DRIVER_PCI_DMA     0x8
+#define DRIVER_SG          0x10
+#define DRIVER_HAVE_DMA    0x20
+#define DRIVER_HAVE_IRQ    0x40
+#define DRIVER_DMA_QUEUE   0x100
+
 
 #define DRM_HASH_SIZE	      16 /* Size of key hash table		  */
 #define DRM_KERNEL_CONTEXT    0	 /* Change drm_resctx if changed	  */
 #define DRM_RESERVED_CONTEXTS 1	 /* Change drm_resctx if changed	  */
 
-#define DRM_MEM_DMA	   0
-#define DRM_MEM_SAREA	   1
-#define DRM_MEM_DRIVER	   2
-#define DRM_MEM_MAGIC	   3
-#define DRM_MEM_IOCTLS	   4
-#define DRM_MEM_MAPS	   5
-#define DRM_MEM_BUFS	   6
-#define DRM_MEM_SEGS	   7
-#define DRM_MEM_PAGES	   8
-#define DRM_MEM_FILES	  9
-#define DRM_MEM_QUEUES	  10
-#define DRM_MEM_CMDS	  11
-#define DRM_MEM_MAPPINGS  12
-#define DRM_MEM_BUFLISTS  13
-#define DRM_MEM_AGPLISTS  14
-#define DRM_MEM_TOTALAGP  15
-#define DRM_MEM_BOUNDAGP  16
-#define DRM_MEM_CTXBITMAP 17
-#define DRM_MEM_STUB	  18
-#define DRM_MEM_SGLISTS	  19
-#define DRM_MEM_DRAWABLE  20
+MALLOC_DECLARE(DRM_MEM_DMA);
+MALLOC_DECLARE(DRM_MEM_SAREA);
+MALLOC_DECLARE(DRM_MEM_DRIVER);
+MALLOC_DECLARE(DRM_MEM_MAGIC);
+MALLOC_DECLARE(DRM_MEM_IOCTLS);
+MALLOC_DECLARE(DRM_MEM_MAPS);
+MALLOC_DECLARE(DRM_MEM_BUFS);
+MALLOC_DECLARE(DRM_MEM_SEGS);
+MALLOC_DECLARE(DRM_MEM_PAGES);
+MALLOC_DECLARE(DRM_MEM_FILES);
+MALLOC_DECLARE(DRM_MEM_QUEUES);
+MALLOC_DECLARE(DRM_MEM_CMDS);
+MALLOC_DECLARE(DRM_MEM_MAPPINGS);
+MALLOC_DECLARE(DRM_MEM_BUFLISTS);
+MALLOC_DECLARE(DRM_MEM_AGPLISTS);
+MALLOC_DECLARE(DRM_MEM_CTXBITMAP);
+MALLOC_DECLARE(DRM_MEM_SGLISTS);
+MALLOC_DECLARE(DRM_MEM_DRAWABLE);
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
 
@@ -181,8 +139,6 @@
 #define DRM_MAX(a,b) ((a)>(b)?(a):(b))
 
 #define DRM_IF_VERSION(maj, min) (maj << 16 | min)
-
-MALLOC_DECLARE(M_DRM);
 
 #define __OS_HAS_AGP	1
 
@@ -195,62 +151,23 @@
 #define DRM_WAKEUP_INT(w)	wakeup(w)
 #define DRM_INIT_WAITQUEUE(queue) do {(void)(queue);} while (0)
 
-#if defined(__FreeBSD__) && __FreeBSD_version < 502109
-#define bus_alloc_resource_any(dev, type, rid, flags) \
-	bus_alloc_resource(dev, type, rid, 0ul, ~0ul, 1, flags)
-#endif
-
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
 #define DRM_CURPROC		curthread
 #define DRM_STRUCTPROC		struct thread
-#define DRM_SPINTYPE		struct mtx
-#define DRM_SPININIT(l,name)	mtx_init(l, name, NULL, MTX_DEF)
-#define DRM_SPINUNINIT(l)	mtx_destroy(l)
-#define DRM_SPINLOCK(l)		mtx_lock(l)
-#define DRM_SPINUNLOCK(u)	mtx_unlock(u)
+#define DRM_SPINTYPE		struct lock
+#define DRM_SPININIT(l,name)	lockinit(l, name, 0, LK_CANRECURSE)
+#define DRM_SPINUNINIT(l)
+#define DRM_SPINLOCK(l)		lockmgr(l, LK_EXCLUSIVE|LK_RETRY|LK_CANRECURSE)
+#define DRM_SPINUNLOCK(u)	lockmgr(u, LK_RELEASE)
 #define DRM_SPINLOCK_IRQSAVE(l, irqflags) do {		\
-	mtx_lock(l);					\
-	(void)irqflags;					\
-} while (0)
-#define DRM_SPINUNLOCK_IRQRESTORE(u, irqflags) mtx_unlock(u)
-#define DRM_SPINLOCK_ASSERT(l)	mtx_assert(l, MA_OWNED)
-#define DRM_CURRENTPID		curthread->td_proc->p_pid
-#define DRM_LOCK()		mtx_lock(&dev->dev_lock)
-#define DRM_UNLOCK() 		mtx_unlock(&dev->dev_lock)
-#define DRM_SYSCTL_HANDLER_ARGS	(SYSCTL_HANDLER_ARGS)
-#elif defined(__DragonFly__)
-#define DRM_CURPROC		curthread
-#define DRM_STRUCTPROC		struct thread
-#define DRM_SPINTYPE		struct spinlock
-#define DRM_SPININIT(l,name)	spin_init(l)
-#define DRM_SPINUNINIT(l)	spin_uninit(l)
-#define DRM_SPINLOCK(l)		spin_lock_wr(l)
-#define DRM_SPINUNLOCK(u)	spin_unlock_wr(u)
-#define DRM_SPINLOCK_IRQSAVE(l, irqflags) do {		\
-	DRM_SPINLOCK(l);					\
-	(void)irqflags;					\
+       DRM_SPINLOCK(l);					\
+       (void)irqflags;					\
 } while (0)
 #define DRM_SPINUNLOCK_IRQRESTORE(u, irqflags) DRM_SPINUNLOCK(u)
 #define DRM_SPINLOCK_ASSERT(l)
 #define DRM_CURRENTPID		curthread->td_proc->p_pid
 #define DRM_LOCK()		DRM_SPINLOCK(&dev->dev_lock)
-#define DRM_UNLOCK() 		DRM_SPINUNLOCK(&dev->dev_lock)
+#define DRM_UNLOCK()		DRM_SPINUNLOCK(&dev->dev_lock)
 #define DRM_SYSCTL_HANDLER_ARGS	(SYSCTL_HANDLER_ARGS)
-#else /* __FreeBSD__ && __FreeBSD_version >= 500000 || __DragonFly__ */
-#define DRM_CURPROC		curproc
-#define DRM_STRUCTPROC		struct proc
-#define DRM_SPINTYPE		struct simplelock
-#define DRM_SPININIT(l,name)
-#define DRM_SPINUNINIT(l)
-#define DRM_SPINLOCK(l)	
-#define DRM_SPINUNLOCK(u)
-#define DRM_SPINLOCK_ASSERT(l)
-#define DRM_CURRENTPID		curproc->p_pid
-#define DRM_LOCK()
-#define DRM_UNLOCK()
-#define DRM_SYSCTL_HANDLER_ARGS	SYSCTL_HANDLER_ARGS
-#define spldrm()		spltty()
-#endif /* __NetBSD__ || __OpenBSD__ */
 
 #define DRM_IRQ_ARGS		void *arg
 typedef void			irqreturn_t;
@@ -264,16 +181,8 @@
 };
 #define DRM_AGP_MEM		struct agp_memory_info
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 #define drm_get_device_from_kdev(_kdev) (_kdev->si_drv1)
-#elif defined(__NetBSD__)
-#define drm_get_device_from_kdev(_kdev) device_lookup(&drm_cd, minor(_kdev))
-#elif defined(__OpenBSD__)
-#define drm_get_device_from_kdev(_kdev) device_lookup(&drm_cd, \
-    minor(_kdev)))->dv_cfdata->cf_driver->cd_devs[minor(_kdev)]
-#endif
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 #define PAGE_ALIGN(addr) round_page(addr)
 /* DRM_SUSER returns true if the user is superuser */
 #if __FreeBSD_version >= 700000
@@ -284,20 +193,6 @@
 #define DRM_AGP_FIND_DEVICE()	agp_find_device()
 #define DRM_MTRR_WC		MDF_WRITECOMBINE
 #define jiffies			ticks
-
-#else /* __FreeBSD__ || __DragonFly__ */
-
-#define CDEV_MAJOR		34
-#define PAGE_ALIGN(addr)	(((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-/* DRM_SUSER returns true if the user is superuser */
-#define DRM_SUSER(p)		(suser(p->p_ucred, &p->p_acflag) == 0)
-#define DRM_AGP_FIND_DEVICE()	agp_find_device(0)
-#define DRM_MTRR_WC		MTRR_TYPE_WC
-#define jiffies			hardclock_ticks
-
-typedef drm_device_t *device_t;
-extern struct cfdriver drm_cd;
-#endif /* !__FreeBSD__ && !__DragonFly__ */
 
 /* Capabilities taken from src/sys/dev/pci/pcireg.h. */
 #ifndef PCIY_AGP
@@ -336,7 +231,6 @@
 					"lock; addl $0,0(%%rsp)" : : : "memory");
 #endif
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 #define DRM_READ8(map, offset)						\
 	*(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset))
 #define DRM_READ16(map, offset)						\
@@ -353,27 +247,6 @@
 #define DRM_VERIFYAREA_READ( uaddr, size )		\
 	(!useracc(__DECONST(caddr_t, uaddr), size, VM_PROT_READ))
 
-#else /* __FreeBSD__ || __DragonFly__ */
-
-typedef vaddr_t vm_offset_t;
-
-#define DRM_READ8(map, offset)		\
-	bus_space_read_1( (map)->bst, (map)->bsh, (offset))
-#define DRM_READ16(map, offset)		\
-	bus_space_read_2( (map)->bst, (map)->bsh, (offset))
-#define DRM_READ32(map, offset)		\
-	bus_space_read_4( (map)->bst, (map)->bsh, (offset))
-#define DRM_WRITE8(map, offset, val)	\
-	bus_space_write_1((map)->bst, (map)->bsh, (offset), (val))
-#define DRM_WRITE16(map, offset, val)	\
-	bus_space_write_2((map)->bst, (map)->bsh, (offset), (val))
-#define DRM_WRITE32(map, offset, val)	\
-	bus_space_write_4((map)->bst, (map)->bsh, (offset), (val))
-
-#define DRM_VERIFYAREA_READ( uaddr, size )		\
-	(!uvm_useracc((caddr_t)uaddr, size, VM_PROT_READ))
-#endif /* !__FreeBSD__ && !__DragonFly__ */
-
 #define DRM_COPY_TO_USER(user, kern, size) \
 	copyout(kern, user, size)
 #define DRM_COPY_FROM_USER(kern, user, size) \
@@ -382,13 +255,8 @@
 	copyin(arg2, arg1, arg3)
 #define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3)	\
 	copyout(arg2, arg1, arg3)
-#if __FreeBSD_version > 500000
 #define DRM_GET_USER_UNCHECKED(val, uaddr)		\
 	((val) = fuword32(uaddr), 0)
-#else
-#define DRM_GET_USER_UNCHECKED(val, uaddr)		\
-	((val) = fuword(uaddr), 0)
-#endif
 
 #define cpu_to_le32(x) htole32(x)
 #define le32_to_cpu(x) le32toh(x)
@@ -411,53 +279,31 @@
 	}								\
 } while (0)
 
-#if defined(__FreeBSD__) && __FreeBSD_version > 500000
 /* Returns -errno to shared code */
-#define DRM_WAIT_ON( ret, queue, timeout, condition )		\
-for ( ret = 0 ; !ret && !(condition) ; ) {			\
-	DRM_UNLOCK();						\
-	mtx_lock(&dev->irq_lock);				\
-	if (!(condition))					\
-	   ret = -mtx_sleep(&(queue), &dev->irq_lock, 		\
-			 PZERO | PCATCH, "drmwtq", (timeout));	\
-	mtx_unlock(&dev->irq_lock);				\
-	DRM_LOCK();						\
-}
-#elif defined(__DragonFly__)
 #define DRM_WAIT_ON( ret, queue, timeout, condition )		\
 for ( ret = 0 ; !ret && !(condition) ; ) {			\
 	DRM_UNLOCK();						\
 	lwkt_serialize_enter(&dev->irq_lock);			\
 	if (!(condition)) {					\
-	   crit_enter();					\
-	   tsleep_interlock(&(queue));				\
-	   lwkt_serialize_exit(&dev->irq_lock);			\
-	   ret = -tsleep(&(queue), PCATCH,			\
-			 "drmwtq", (timeout));			\
-	   crit_exit();						\
-	} else {						\
+		crit_enter();					\
+		tsleep_interlock(&(queue));			\
 		lwkt_serialize_exit(&dev->irq_lock);		\
-	}							\
-	DRM_LOCK();						\
+		ret = -tsleep(&(queue), PCATCH,			\
+			      "drmwtq", (timeout));		\
+		crit_exit();					\
+	} else {                                                \
+		lwkt_serialize_exit(&dev->irq_lock);            \
+	}                                                       \
+	DRM_LOCK();                                             \
 }
-#else
-/* Returns -errno to shared code */
-#define DRM_WAIT_ON( ret, queue, timeout, condition )	\
-for ( ret = 0 ; !ret && !(condition) ; ) {		\
-        int s = spldrm();				\
-	if (!(condition))				\
-	   ret = -tsleep( &(queue), PZERO | PCATCH, 	\
-			 "drmwtq", (timeout) );		\
-	splx(s);					\
-}
-#endif
 
-#ifdef __DragonFly__
+/* #define TAILQ_FOREACH_SAFE TAILQ_FOREACH_MUTABLE */
 #define printf	kprintf
 #define snprintf ksnprintf
 #define sscanf	ksscanf
 #define malloc	kmalloc
 #define realloc	krealloc
+#define dev2unit(x)	((minor(x) & 0xff) | (minor(x) >> 8))
 
 __inline static void
 free(void *addr, struct malloc_type *type)
@@ -465,7 +311,6 @@
 	if (addr != NULL)
 		kfree(addr, type);
 }
-#endif
 
 #define DRM_ERROR(fmt, arg...) \
 	printf("error: [" DRM_NAME ":pid%d:%s] *ERROR* " fmt,		\
@@ -492,7 +337,8 @@
 #define DRM_ROOT_ONLY	0x4
 typedef struct drm_ioctl_desc {
 	unsigned long cmd;
-	int (*func)(drm_device_t *dev, void *data, struct drm_file *file_priv);
+	int (*func)(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv);
 	int flags;
 } drm_ioctl_desc_t;
 /**
@@ -550,12 +396,8 @@
 typedef struct drm_dma_handle {
 	void *vaddr;
 	bus_addr_t busaddr;
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	bus_dma_tag_t tag;
 	bus_dmamap_t map;
-#elif defined(__NetBSD__)
-	bus_dma_segment_t seg;
-#endif
 } drm_dma_handle_t;
 
 typedef struct drm_buf_entry {
@@ -572,6 +414,7 @@
 typedef TAILQ_HEAD(drm_file_list, drm_file) drm_file_list_t;
 struct drm_file {
 	TAILQ_ENTRY(drm_file) link;
+	struct drm_device *dev;
 	int		  authenticated;
 	int		  master;
 	int		  minor;
@@ -584,13 +427,14 @@
 };
 
 typedef struct drm_lock_data {
-	drm_hw_lock_t	  *hw_lock;	/* Hardware lock		   */
+	struct drm_hw_lock	*hw_lock;	/* Hardware lock		   */
 	struct drm_file   *file_priv;   /* Unique identifier of holding process (NULL is kernel)*/
 	int		  lock_queue;	/* Queue of blocked processes	   */
 	unsigned long	  lock_time;	/* Time of last lock in jiffies	   */
 } drm_lock_data_t;
 
-/* This structure, in the drm_device_t, is always initialized while the device
+/* This structure, in the struct drm_device, is always initialized while the
+ * device
  * is open.  dev->dma_lock protects the incrementing of dev->buf_use, which
  * when set marks that no further bufs may be allocated until device teardown
  * occurs (when the last open of the device has closed).  The high/low
@@ -646,8 +490,8 @@
 typedef struct drm_local_map {
 	unsigned long	offset;	 /* Physical address (0 for SAREA)*/
 	unsigned long	size;	 /* Physical size (bytes)	    */
-	drm_map_type_t	type;	 /* Type of memory mapped		    */
-	drm_map_flags_t flags;	 /* Flags				    */
+	enum drm_map_type	type;	 /* Type of memory mapped		    */
+	enum drm_map_flags	flags;	 /* Flags				    */
 	void		*handle; /* User-space: "Handle" to pass to mmap    */
 				 /* Kernel-space: kernel-virtual address    */
 	int		mtrr;	 /* Boolean: MTRR used */
@@ -668,6 +512,19 @@
 	int		pid;
 } drm_vbl_sig_t;
 
+struct drm_vblank_info {
+	wait_queue_head_t queue;	/* vblank wait queue */
+	atomic_t count;			/* number of VBLANK interrupts */
+					/* (driver must alloc the right number of counters) */
+	struct drm_vbl_sig_list sigs;	/* signal list to send on VBLANK */
+	atomic_t refcount;		/* number of users of vblank interrupts */
+	u32 last;			/* protected by dev->vbl_lock, used */
+					/* for wraparound handling */
+	int enabled;			/* so we don't call enable more than */
+					/* once per disable */
+	int inmodeset;			/* Display driver is setting mode */
+};
+
 /* location of GART table */
 #define DRM_ATI_GART_MAIN 1
 #define DRM_ATI_GART_FB   2
@@ -681,38 +538,49 @@
 	int gart_reg_if;
 	void *addr;
 	dma_addr_t bus_addr;
+	dma_addr_t table_mask;
+	dma_addr_t member_mask;
+	struct drm_dma_handle *table_handle;
 	drm_local_map_t mapping;
 	int table_size;
 };
 
+#ifndef DMA_BIT_MASK
+#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : (1ULL<<(n)) - 1)
+#endif
+
+#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
+
 struct drm_driver_info {
 	int	(*load)(struct drm_device *, unsigned long flags);
 	int	(*firstopen)(struct drm_device *);
-	int	(*open)(struct drm_device *, drm_file_t *);
+	int	(*open)(struct drm_device *, struct drm_file *);
 	void	(*preclose)(struct drm_device *, struct drm_file *file_priv);
-	void	(*postclose)(struct drm_device *, drm_file_t *);
+	void	(*postclose)(struct drm_device *, struct drm_file *);
 	void	(*lastclose)(struct drm_device *);
 	int	(*unload)(struct drm_device *);
 	void	(*reclaim_buffers_locked)(struct drm_device *,
 					  struct drm_file *file_priv);
-	int	(*dma_ioctl)(drm_device_t *dev, void *data, struct drm_file *file_priv);
+	int	(*dma_ioctl)(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
 	void	(*dma_ready)(struct drm_device *);
 	int	(*dma_quiescent)(struct drm_device *);
 	int	(*dma_flush_block_and_flush)(struct drm_device *, int context,
-					     drm_lock_flags_t flags);
+					     enum drm_lock_flags flags);
 	int	(*dma_flush_unblock)(struct drm_device *, int context,
-				     drm_lock_flags_t flags);
+				     enum drm_lock_flags flags);
 	int	(*context_ctor)(struct drm_device *dev, int context);
 	int	(*context_dtor)(struct drm_device *dev, int context);
 	int	(*kernel_context_switch)(struct drm_device *dev, int old,
 					 int new);
 	int	(*kernel_context_switch_unlock)(struct drm_device *dev);
-	void	(*irq_preinstall)(drm_device_t *dev);
-	void	(*irq_postinstall)(drm_device_t *dev);
-	void	(*irq_uninstall)(drm_device_t *dev);
+	void	(*irq_preinstall)(struct drm_device *dev);
+	int	(*irq_postinstall)(struct drm_device *dev);
+	void	(*irq_uninstall)(struct drm_device *dev);
 	void	(*irq_handler)(DRM_IRQ_ARGS);
-	int	(*vblank_wait)(drm_device_t *dev, unsigned int *sequence);
-	int	(*vblank_wait2)(drm_device_t *dev, unsigned int *sequence);
+	u32	(*get_vblank_counter)(struct drm_device *dev, int crtc);
+	int	(*enable_vblank)(struct drm_device *dev, int crtc);
+	void	(*disable_vblank)(struct drm_device *dev, int crtc);
 
 	drm_pci_id_list_t *id_entry;	/* PCI ID, name, and chipset private */
 
@@ -741,16 +609,7 @@
 	const char *desc;		/* Longer driver name		   */
 	const char *date;		/* Date of last major changes.	   */
 
-	unsigned use_agp :1;
-	unsigned require_agp :1;
-	unsigned use_sg :1;
-	unsigned use_dma :1;
-	unsigned use_pci_dma :1;
-	unsigned use_dma_queue :1;
-	unsigned use_irq :1;
-	unsigned use_vbl_irq :1;
-	unsigned use_vbl_irq2 :1;
-	unsigned use_mtrr :1;
+	u32 driver_features;
 };
 
 /* Length for the array of resource pointers for drm_get_resource_*. */
@@ -760,11 +619,7 @@
  * DRM device functions structure
  */
 struct drm_device {
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-	struct device	  device; /* softc is an extension of struct device */
-#endif
-
-	struct drm_driver_info driver;
+	struct drm_driver_info *driver;
 	drm_pci_id_list_t *id_entry;	/* PCI ID, name, and chipset private */
 
 	u_int16_t pci_device;		/* PCI device id */
@@ -772,25 +627,19 @@
 
 	char		  *unique;	/* Unique identifier: e.g., busid  */
 	int		  unique_len;	/* Length of unique field	   */
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	device_t	  device;	/* Device instance from newbus     */
-#endif
 	struct cdev	  *devnode;	/* Device number for mknod	   */
 	int		  if_version;	/* Highest interface version set */
 
 	int		  flags;	/* Flags to open(2)		   */
 
 				/* Locks */
-#if defined(__FreeBSD__) && __FreeBSD_version > 500000
-	struct mtx	  dma_lock;	/* protects dev->dma */
-	struct mtx	  irq_lock;	/* protects irq condition checks */
-	struct mtx	  dev_lock;	/* protects everything else */
-#elif defined(__DragonFly__)
-	struct spinlock	  dma_lock;	/* protects dev->dma */
+	DRM_SPINTYPE	  vbl_lock;	/* protects vblank operations */
+	DRM_SPINTYPE	  dma_lock;	/* protects dev->dma */
 	struct lwkt_serialize irq_lock;	/* protects irq condition checks */
-	struct spinlock	  dev_lock;	/* protects everything else */
-#endif
+	DRM_SPINTYPE	  dev_lock;	/* protects everything else */
 	DRM_SPINTYPE	  drw_lock;
+	DRM_SPINTYPE	  tsk_lock;
 
 				/* Usage Counters */
 	int		  open_count;	/* Outstanding files open	   */
@@ -798,7 +647,7 @@
 
 				/* Performance counters */
 	unsigned long     counters;
-	drm_stat_type_t   types[15];
+	enum drm_stat_type	types[15];
 	atomic_t          counts[15];
 
 				/* Authentication */
@@ -819,12 +668,8 @@
 				/* Context support */
 	int		  irq;		/* Interrupt used by board	   */
 	int		  irq_enabled;	/* True if the irq handler is enabled */
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	int		  irqrid;	/* Interrupt used by board */
 	struct resource   *irqr;	/* Resource for interrupt used by board	   */
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	struct pci_attach_args  pa;
-#endif
 	void		  *irqh;	/* Handle from bus_setup_intr      */
 
 	/* Storage of resource pointers for drm_get_resource_* */
@@ -838,15 +683,15 @@
 
 	atomic_t	  context_flag;	/* Context swapping flag	   */
 	int		  last_context;	/* Last current context		   */
-   	int		  vbl_queue;	/* vbl wait channel */
-   	atomic_t          vbl_received;
-   	atomic_t          vbl_received2;
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+	int		  vblank_disable_allowed;
+	atomic_t 	  vbl_signal_pending;	/* number of signals pending on all crtcs */
+	struct callout	  vblank_disable_timer;
+	u32		  max_vblank_count;	/* size of vblank counter register */
+	struct drm_vblank_info *vblank;		/* per crtc vblank info */
+	int		  num_crtcs;
+
 	struct sigio      *buf_sigio;	/* Processes waiting for SIGIO     */
-#elif defined(__NetBSD__)
-	pid_t		  buf_pgid;
-#endif
 
 				/* Sysctl support */
 	struct drm_sysctl_info *sysctl;
@@ -858,20 +703,32 @@
 	unsigned int	  agp_buffer_token;
 	drm_local_map_t   *agp_buffer_map;
 
-#ifdef __FreeBSD__
-	struct unrhdr	  *drw_unrhdr;
-#endif
+	/* struct unrhdr  *drw_unrhdr; XXX */
 	/* RB tree of drawable infos */
 	RB_HEAD(drawable_tree, bsd_drm_drawable_info) drw_head;
 
 	struct task	  locked_task;
-	void		  (*locked_task_call)(drm_device_t *dev);
+	void		  (*locked_task_call)(struct drm_device *dev);
 };
+
+static __inline__ int drm_core_check_feature(struct drm_device *dev,
+					     int feature)
+{
+	return ((dev->driver->driver_features & feature) ? 1 : 0);
+}
+
+#if __OS_HAS_AGP
+static inline int drm_core_has_AGP(struct drm_device *dev)
+{
+	return drm_core_check_feature(dev, DRIVER_USE_AGP);
+}
+#else
+#define drm_core_has_AGP(dev) (0)
+#endif
 
 extern int	drm_debug_flag;
 
 /* Device setup support (drm_drv.c) */
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 int	drm_probe(device_t nbdev, drm_pci_id_list_t *idlist);
 int	drm_attach(device_t nbdev, drm_pci_id_list_t *idlist);
 int	drm_detach(device_t nbdev);
@@ -881,209 +738,286 @@
 d_read_t drm_read;
 d_poll_t drm_poll;
 d_mmap_t drm_mmap;
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-int	drm_probe(struct pci_attach_args *pa, drm_pci_id_list_t *idlist);
-int	drm_attach(struct pci_attach_args *pa, dev_t kdev, drm_pci_id_list_t *idlist);
-dev_type_ioctl(drm_ioctl);
-dev_type_open(drm_open);
-dev_type_close(drm_close);
-dev_type_read(drm_read);
-dev_type_poll(drm_poll);
-dev_type_mmap(drm_mmap);
-#endif
-extern drm_local_map_t	*drm_getsarea(drm_device_t *dev);
+extern drm_local_map_t	*drm_getsarea(struct drm_device *dev);
 
 /* File operations helpers (drm_fops.c) */
-#if defined(__FreeBSD__) || defined(__DragonFly__)
-extern int		drm_open_helper(struct cdev *kdev, int flags, int fmt, 
-					 DRM_STRUCTPROC *p, drm_device_t *dev);
-extern drm_file_t	*drm_find_file_by_proc(drm_device_t *dev, 
-					 DRM_STRUCTPROC *p);
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-extern int		drm_open_helper(dev_t kdev, int flags, int fmt, 
-					DRM_STRUCTPROC *p, drm_device_t *dev);
-extern drm_file_t	*drm_find_file_by_proc(drm_device_t *dev, 
+extern int		drm_open_helper(struct cdev *kdev, int flags, int fmt,
+					 DRM_STRUCTPROC *p,
+					struct drm_device *dev);
+extern struct drm_file	*drm_find_file_by_proc(struct drm_device *dev,
 					       DRM_STRUCTPROC *p);
-#endif /* __NetBSD__ || __OpenBSD__ */
 
 /* Memory management support (drm_memory.c) */
 void	drm_mem_init(void);
 void	drm_mem_uninit(void);
-void	*drm_alloc(size_t size, int area);
-void	*drm_calloc(size_t nmemb, size_t size, int area);
-void	*drm_realloc(void *oldpt, size_t oldsize, size_t size,
-				   int area);
-void	drm_free(void *pt, size_t size, int area);
-void	*drm_ioremap(drm_device_t *dev, drm_local_map_t *map);
+void	*drm_ioremap_wc(struct drm_device *dev, drm_local_map_t *map);
+void	*drm_ioremap(struct drm_device *dev, drm_local_map_t *map);
 void	drm_ioremapfree(drm_local_map_t *map);
 int	drm_mtrr_add(unsigned long offset, size_t size, int flags);
 int	drm_mtrr_del(int handle, unsigned long offset, size_t size, int flags);
 
-int	drm_context_switch(drm_device_t *dev, int old, int new);
-int	drm_context_switch_complete(drm_device_t *dev, int new);
+int	drm_context_switch(struct drm_device *dev, int old, int new);
+int	drm_context_switch_complete(struct drm_device *dev, int new);
 
-int	drm_ctxbitmap_init(drm_device_t *dev);
-void	drm_ctxbitmap_cleanup(drm_device_t *dev);
-void	drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle);
-int	drm_ctxbitmap_next(drm_device_t *dev);
+int	drm_ctxbitmap_init(struct drm_device *dev);
+void	drm_ctxbitmap_cleanup(struct drm_device *dev);
+void	drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
+int	drm_ctxbitmap_next(struct drm_device *dev);
 
 /* Locking IOCTL support (drm_lock.c) */
-int	drm_lock_take(__volatile__ unsigned int *lock,
-				    unsigned int context);
-int	drm_lock_transfer(drm_device_t *dev,
-					__volatile__ unsigned int *lock,
-					unsigned int context);
-int	drm_lock_free(drm_device_t *dev,
-				    __volatile__ unsigned int *lock,
-				    unsigned int context);
+int	drm_lock_take(struct drm_lock_data *lock_data,
+		      unsigned int context);
+int	drm_lock_transfer(struct drm_lock_data *lock_data,
+			  unsigned int context);
+int	drm_lock_free(struct drm_lock_data *lock_data,
+		      unsigned int context);
 
 /* Buffer management support (drm_bufs.c) */
-unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource);
-unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource);
-void	drm_rmmap(drm_device_t *dev, drm_local_map_t *map);
+unsigned long drm_get_resource_start(struct drm_device *dev,
+				     unsigned int resource);
+unsigned long drm_get_resource_len(struct drm_device *dev,
+				   unsigned int resource);
+void	drm_rmmap(struct drm_device *dev, drm_local_map_t *map);
 int	drm_order(unsigned long size);
-int	drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
-		   drm_map_type_t type, drm_map_flags_t flags,
+int	drm_addmap(struct drm_device *dev, unsigned long offset,
+		   unsigned long size,
+		   enum drm_map_type type, enum drm_map_flags flags,
 		   drm_local_map_t **map_ptr);
-int	drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request);
-int	drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request);
-int	drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request);
+int	drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request);
+int	drm_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request);
+int	drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request);
 
 /* DMA support (drm_dma.c) */
-int	drm_dma_setup(drm_device_t *dev);
-void	drm_dma_takedown(drm_device_t *dev);
-void	drm_free_buffer(drm_device_t *dev, drm_buf_t *buf);
-void	drm_reclaim_buffers(drm_device_t *dev, struct drm_file *file_priv);
+int	drm_dma_setup(struct drm_device *dev);
+void	drm_dma_takedown(struct drm_device *dev);
+void	drm_free_buffer(struct drm_device *dev, drm_buf_t *buf);
+void	drm_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv);
 #define drm_core_reclaim_buffers drm_reclaim_buffers
 
 /* IRQ support (drm_irq.c) */
-int	drm_irq_install(drm_device_t *dev);
-int	drm_irq_uninstall(drm_device_t *dev);
+int	drm_irq_install(struct drm_device *dev);
+int	drm_irq_uninstall(struct drm_device *dev);
 irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
-void	drm_driver_irq_preinstall(drm_device_t *dev);
-void	drm_driver_irq_postinstall(drm_device_t *dev);
-void	drm_driver_irq_uninstall(drm_device_t *dev);
-int	drm_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
-void	drm_vbl_send_signals(drm_device_t *dev);
+void	drm_driver_irq_preinstall(struct drm_device *dev);
+void	drm_driver_irq_postinstall(struct drm_device *dev);
+void	drm_driver_irq_uninstall(struct drm_device *dev);
+void	drm_handle_vblank(struct drm_device *dev, int crtc);
+u32	drm_vblank_count(struct drm_device *dev, int crtc);
+int	drm_vblank_get(struct drm_device *dev, int crtc);
+void	drm_vblank_put(struct drm_device *dev, int crtc);
+int	drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
+int	drm_vblank_init(struct drm_device *dev, int num_crtcs);
+void	drm_vbl_send_signals(struct drm_device *dev, int crtc);
+int 	drm_modeset_ctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
 
 /* AGP/PCI Express/GART support (drm_agpsupport.c) */
-int	drm_device_is_agp(drm_device_t *dev);
-int	drm_device_is_pcie(drm_device_t *dev);
+int	drm_device_is_agp(struct drm_device *dev);
+int	drm_device_is_pcie(struct drm_device *dev);
 drm_agp_head_t *drm_agp_init(void);
-int	drm_agp_acquire(drm_device_t *dev);
-int	drm_agp_release(drm_device_t *dev);
-int	drm_agp_info(drm_device_t * dev, drm_agp_info_t *info);
-int	drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode);
+int	drm_agp_acquire(struct drm_device *dev);
+int	drm_agp_release(struct drm_device *dev);
+int	drm_agp_info(struct drm_device * dev, struct drm_agp_info *info);
+int	drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
 void	*drm_agp_allocate_memory(size_t pages, u32 type);
 int	drm_agp_free_memory(void *handle);
 int	drm_agp_bind_memory(void *handle, off_t start);
 int	drm_agp_unbind_memory(void *handle);
-int	drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request);
-int	drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request);
-int	drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request);
-int	drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);
+int	drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
+int	drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
+int	drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
+int	drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
 
 /* Scatter Gather Support (drm_scatter.c) */
 void	drm_sg_cleanup(drm_sg_mem_t *entry);
-int	drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request);
+int	drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request);
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 /* sysctl support (drm_sysctl.h) */
-extern int		drm_sysctl_init(drm_device_t *dev);
-extern int		drm_sysctl_cleanup(drm_device_t *dev);
-#endif /* __FreeBSD__ || __DragonFly__ */
+extern int		drm_sysctl_init(struct drm_device *dev);
+extern int		drm_sysctl_cleanup(struct drm_device *dev);
 
 /* ATI PCIGART support (ati_pcigart.c) */
-int	drm_ati_pcigart_init(drm_device_t *dev,
+int	drm_ati_pcigart_init(struct drm_device *dev,
 				struct drm_ati_pcigart_info *gart_info);
-int	drm_ati_pcigart_cleanup(drm_device_t *dev,
+int	drm_ati_pcigart_cleanup(struct drm_device *dev,
 				struct drm_ati_pcigart_info *gart_info);
 
 /* Locking IOCTL support (drm_drv.c) */
-int	drm_lock(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_unlock(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_version(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_setversion(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int	drm_lock(struct drm_device *dev, void *data,
+		 struct drm_file *file_priv);
+int	drm_unlock(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv);
+int	drm_version(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv);
+int	drm_setversion(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv);
 
 /* Misc. IOCTL support (drm_ioctl.c) */
-int	drm_irq_by_busid(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_getunique(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_setunique(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_getmap(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_getclient(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_getstats(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_noop(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int	drm_irq_by_busid(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int	drm_getunique(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv);
+int	drm_setunique(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv);
+int	drm_getmap(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv);
+int	drm_getclient(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv);
+int	drm_getstats(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv);
+int	drm_noop(struct drm_device *dev, void *data,
+		 struct drm_file *file_priv);
 
 /* Context IOCTL support (drm_context.c) */
-int	drm_resctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_addctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_modctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_getctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_switchctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_newctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_rmctx(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_setsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_getsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int	drm_resctx(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv);
+int	drm_addctx(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv);
+int	drm_modctx(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv);
+int	drm_getctx(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv);
+int	drm_switchctx(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv);
+int	drm_newctx(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv);
+int	drm_rmctx(struct drm_device *dev, void *data,
+		  struct drm_file *file_priv);
+int	drm_setsareactx(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int	drm_getsareactx(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
 
 /* Drawable IOCTL support (drm_drawable.c) */
-int	drm_adddraw(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_rmdraw(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_update_draw(drm_device_t *dev, void *data, struct drm_file *file_priv);
-struct drm_drawable_info *drm_get_drawable_info(drm_device_t *dev, int handle);
+int	drm_adddraw(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv);
+int	drm_rmdraw(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv);
+int	drm_update_draw(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
+						int handle);
+
+/* Drawable support (drm_drawable.c) */
+void drm_drawable_free_all(struct drm_device *dev);
 
 /* Authentication IOCTL support (drm_auth.c) */
-int	drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_authmagic(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int	drm_getmagic(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv);
+int	drm_authmagic(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv);
 
 /* Buffer management support (drm_bufs.c) */
-int	drm_addmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_rmmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_addbufs_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_infobufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_markbufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_freebufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_mapbufs(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int	drm_addmap_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int	drm_rmmap_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int	drm_addbufs_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv);
+int	drm_infobufs(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv);
+int	drm_markbufs(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv);
+int	drm_freebufs(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv);
+int	drm_mapbufs(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv);
 
 /* DMA support (drm_dma.c) */
-int	drm_dma(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int	drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv);
 
 /* IRQ support (drm_irq.c) */
-int	drm_control(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv);
-void	drm_locked_tasklet(drm_device_t *dev,
-			   void (*tasklet)(drm_device_t *dev));
+int	drm_control(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv);
+int	drm_wait_vblank(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+void	drm_locked_tasklet(struct drm_device *dev,
+			   void (*tasklet)(struct drm_device *dev));
 
 /* AGP/GART support (drm_agpsupport.c) */
-int	drm_agp_acquire_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_agp_release_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_agp_enable_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_agp_info_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_agp_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_agp_free_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_agp_unbind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_agp_bind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int	drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+int	drm_agp_release_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+int	drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
+int	drm_agp_info_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+int	drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
+int	drm_agp_free_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+int	drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
+int	drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
 
 /* Scatter Gather Support (drm_scatter.c) */
-int	drm_sg_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv);
-int	drm_sg_free(drm_device_t *dev, void *data, struct drm_file *file_priv);
+int	drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+int	drm_sg_free(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv);
 
 /* consistent PCI memory functions (drm_pci.c) */
-drm_dma_handle_t *drm_pci_alloc(drm_device_t *dev, size_t size, size_t align,
-				dma_addr_t maxaddr);
-void	drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah);
+drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
+				size_t align, dma_addr_t maxaddr);
+void	drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah);
+
+/* Inline replacements for drm_alloc and friends */
+static __inline__ void *
+drm_alloc(size_t size, struct malloc_type *area)
+{
+	return malloc(size, area, M_NOWAIT);
+}
+
+static __inline__ void *
+drm_calloc(size_t nmemb, size_t size, struct malloc_type *area)
+{
+	return malloc(size * nmemb, area, M_NOWAIT | M_ZERO);
+}
+
+static __inline__ void *
+drm_realloc(void *oldpt, size_t oldsize, size_t size,
+    struct malloc_type *area)
+{
+	void *pt;
+
+	pt = malloc(size, area, M_NOWAIT);
+	if (pt == NULL)
+		return NULL;
+	if (oldpt && oldsize) {
+		memcpy(pt, oldpt, oldsize);
+		free(oldpt, area);
+	}
+	return pt;
+}
+
+static __inline__ void
+drm_free(void *pt, size_t size, struct malloc_type *area)
+{
+	free(pt, area);
+}
 
 /* Inline replacements for DRM_IOREMAP macros */
-static __inline__ void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
+static __inline__ void
+drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev)
+{
+	map->handle = drm_ioremap_wc(dev, map);
+}
+static __inline__ void
+drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
 {
 	map->handle = drm_ioremap(dev, map);
 }
-static __inline__ void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
+static __inline__ void
+drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
 {
 	if ( map->handle && map->size )
 		drm_ioremapfree(map);
 }
 
-static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
+static __inline__ struct drm_local_map *
+drm_core_findmap(struct drm_device *dev, unsigned long offset)
 {
 	drm_local_map_t *map;
 
diff --git a/sys/dev/drm/drm_agpsupport.c b/sys/dev/drm/drm_agpsupport.c
--- a/sys/dev/drm/drm_agpsupport.c
+++ b/sys/dev/drm/drm_agpsupport.c
@@ -36,23 +36,13 @@
 
 #include "drmP.h"
 
-#ifdef __FreeBSD__
-#if __FreeBSD_version >= 800004
-#include <dev/agp/agpreg.h>
-#else /* __FreeBSD_version >= 800004 */
-#include <pci/agpreg.h>
-#endif /* __FreeBSD_version >= 800004 */
-#include <dev/pci/pcireg.h>
-#elif defined(__DragonFly__)
 #include <dev/agp/agpreg.h>
 #include <bus/pci/pcireg.h>
-#endif
 
 /* Returns 1 if AGP or 0 if not. */
 static int
-drm_device_find_capability(drm_device_t *dev, int cap)
+drm_device_find_capability(struct drm_device *dev, int cap)
 {
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 #if __FreeBSD_version >= 602102
 
 	return (pci_find_extcap(dev->device, cap, NULL) == 0);
@@ -86,21 +76,17 @@
 
 	return 0;
 #endif
-#else
-	/* XXX: fill me in for non-FreeBSD */
-	return 1;
-#endif
 }
 
-int drm_device_is_agp(drm_device_t *dev)
+int drm_device_is_agp(struct drm_device *dev)
 {
-	if (dev->driver.device_is_agp != NULL) {
+	if (dev->driver->device_is_agp != NULL) {
 		int ret;
 
 		/* device_is_agp returns a tristate, 0 = not AGP, 1 = definitely
 		 * AGP, 2 = fall back to PCI capability
 		 */
-		ret = (*dev->driver.device_is_agp)(dev);
+		ret = (*dev->driver->device_is_agp)(dev);
 		if (ret != DRM_MIGHT_BE_AGP)
 			return ret;
 	}
@@ -108,12 +94,12 @@
 	return (drm_device_find_capability(dev, PCIY_AGP));
 }
 
-int drm_device_is_pcie(drm_device_t *dev)
+int drm_device_is_pcie(struct drm_device *dev)
 {
 	return (drm_device_find_capability(dev, PCIY_EXPRESS));
 }
 
-int drm_agp_info(drm_device_t * dev, drm_agp_info_t *info)
+int drm_agp_info(struct drm_device * dev, struct drm_agp_info *info)
 {
 	struct agp_info *kern;
 
@@ -135,26 +121,28 @@
 	return 0;
 }
 
-int drm_agp_info_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
 {
 	int err;
-	drm_agp_info_t info;
+	struct drm_agp_info info;
 
 	err = drm_agp_info(dev, &info);
 	if (err != 0)
 		return err;
 
-	*(drm_agp_info_t *) data = info;
+	*(struct drm_agp_info *) data = info;
 	return 0;
 }
 
-int drm_agp_acquire_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
 {
 
 	return drm_agp_acquire(dev);
 }
 
-int drm_agp_acquire(drm_device_t *dev)
+int drm_agp_acquire(struct drm_device *dev)
 {
 	int retcode;
 
@@ -169,13 +157,14 @@
 	return 0;
 }
 
-int drm_agp_release_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
 {
 
 	return drm_agp_release(dev);
 }
 
-int drm_agp_release(drm_device_t * dev)
+int drm_agp_release(struct drm_device * dev)
 {
 	if (!dev->agp || !dev->agp->acquired)
 		return EINVAL;
@@ -184,7 +173,7 @@
 	return 0;
 }
 
-int drm_agp_enable(drm_device_t *dev, drm_agp_mode_t mode)
+int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
 {
 
 	if (!dev->agp || !dev->agp->acquired)
@@ -196,16 +185,17 @@
 	return 0;
 }
 
-int drm_agp_enable_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
 {
-	drm_agp_mode_t mode;
+	struct drm_agp_mode mode;
 
-	mode = *(drm_agp_mode_t *) data;
+	mode = *(struct drm_agp_mode *) data;
 
 	return drm_agp_enable(dev, mode);
 }
 
-int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
 {
 	drm_agp_mem_t    *entry;
 	void	         *handle;
@@ -216,7 +206,7 @@
 	if (!dev->agp || !dev->agp->acquired)
 		return EINVAL;
 
-	entry = malloc(sizeof(*entry), M_DRM, M_NOWAIT | M_ZERO);
+	entry = malloc(sizeof(*entry), DRM_MEM_AGPLISTS, M_NOWAIT | M_ZERO);
 	if (entry == NULL)
 		return ENOMEM;
 
@@ -227,7 +217,7 @@
 	handle = drm_agp_allocate_memory(pages, type);
 	DRM_LOCK();
 	if (handle == NULL) {
-		free(entry, M_DRM);
+		free(entry, DRM_MEM_AGPLISTS);
 		return ENOMEM;
 	}
 	
@@ -248,23 +238,25 @@
 	return 0;
 }
 
-int drm_agp_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
 {
-	drm_agp_buffer_t request;
+	struct drm_agp_buffer request;
 	int retcode;
 
-	request = *(drm_agp_buffer_t *) data;
+	request = *(struct drm_agp_buffer *) data;
 
 	DRM_LOCK();
 	retcode = drm_agp_alloc(dev, &request);
 	DRM_UNLOCK();
 
-	*(drm_agp_buffer_t *) data = request;
+	*(struct drm_agp_buffer *) data = request;
 
 	return retcode;
 }
 
-static drm_agp_mem_t * drm_agp_lookup_entry(drm_device_t *dev, void *handle)
+static drm_agp_mem_t * drm_agp_lookup_entry(struct drm_device *dev,
+					    void *handle)
 {
 	drm_agp_mem_t *entry;
 
@@ -274,7 +266,7 @@
 	return NULL;
 }
 
-int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
 {
 	drm_agp_mem_t     *entry;
 	int retcode;
@@ -296,12 +288,13 @@
 	return retcode;
 }
 
-int drm_agp_unbind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
 {
-	drm_agp_binding_t request;
+	struct drm_agp_binding request;
 	int retcode;
 
-	request = *(drm_agp_binding_t *) data;
+	request = *(struct drm_agp_binding *) data;
 
 	DRM_LOCK();
 	retcode = drm_agp_unbind(dev, &request);
@@ -310,7 +303,7 @@
 	return retcode;
 }
 
-int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
+int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
 {
 	drm_agp_mem_t     *entry;
 	int               retcode;
@@ -336,12 +329,13 @@
 	return retcode;
 }
 
-int drm_agp_bind_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
 {
-	drm_agp_binding_t request;
+	struct drm_agp_binding request;
 	int retcode;
 
-	request = *(drm_agp_binding_t *) data;
+	request = *(struct drm_agp_binding *) data;
 
 	DRM_LOCK();
 	retcode = drm_agp_bind(dev, &request);
@@ -350,7 +344,7 @@
 	return retcode;
 }
 
-int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
+int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
 {
 	drm_agp_mem_t    *entry;
 	
@@ -374,18 +368,19 @@
 	drm_agp_free_memory(entry->handle);
 	DRM_LOCK();
 
-	free(entry, M_DRM);
+	free(entry, DRM_MEM_AGPLISTS);
 
 	return 0;
 
 }
 
-int drm_agp_free_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_agp_free_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
 {
-	drm_agp_buffer_t request;
+	struct drm_agp_buffer request;
 	int retcode;
 
-	request = *(drm_agp_buffer_t *) data;
+	request = *(struct drm_agp_buffer *) data;
 
 	DRM_LOCK();
 	retcode = drm_agp_free(dev, &request);
@@ -407,7 +402,8 @@
 	DRM_DEBUG("agp_available = %d\n", agp_available);
 
 	if (agp_available) {
-		head = malloc(sizeof(*head), M_DRM, M_NOWAIT | M_ZERO);
+		head = malloc(sizeof(*head), DRM_MEM_AGPLISTS,
+		    M_NOWAIT | M_ZERO);
 		if (head == NULL)
 			return NULL;
 		head->agpdev = agpdev;
diff --git a/sys/dev/drm/drm_atomic.h b/sys/dev/drm/drm_atomic.h
--- a/sys/dev/drm/drm_atomic.h
+++ b/sys/dev/drm/drm_atomic.h
@@ -35,79 +35,12 @@
 
 typedef u_int32_t atomic_t;
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 #define atomic_set(p, v)	(*(p) = (v))
 #define atomic_read(p)		(*(p))
 #define atomic_inc(p)		atomic_add_int(p, 1)
 #define atomic_dec(p)		atomic_subtract_int(p, 1)
 #define atomic_add(n, p)	atomic_add_int(p, n)
 #define atomic_sub(n, p)	atomic_subtract_int(p, n)
-#else /* __FreeBSD__ || __DragonFly__ */
-/* FIXME */
-#define atomic_set(p, v)	(*(p) = (v))
-#define atomic_read(p)		(*(p))
-#define atomic_inc(p)		(*(p) += 1)
-#define atomic_dec(p)		(*(p) -= 1)
-#define atomic_add(n, p)	(*(p) += (n))
-#define atomic_sub(n, p)	(*(p) -= (n))
-/* FIXME */
-#define atomic_add_int(p, v)      *(p) += v
-#define atomic_subtract_int(p, v) *(p) -= v
-#define atomic_set_int(p, bits)   *(p) |= (bits)
-#define atomic_clear_int(p, bits) *(p) &= ~(bits)
-#endif /* !__FreeBSD__ && !__DragonFly__ */
-
-#ifndef __DragonFly__
-#if !defined(__FreeBSD_version) || (__FreeBSD_version < 500000)
-#if defined(__i386__)
-/* The extra atomic functions from 5.0 haven't been merged to 4.x */
-static __inline int
-atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src)
-{
-	int res = exp;
-
-	__asm __volatile (
-	"	lock ;			"
-	"	cmpxchgl %1,%2 ;	"
-	"       setz	%%al ;		"
-	"	movzbl	%%al,%0 ;	"
-	"1:				"
-	"# atomic_cmpset_int"
-	: "+a" (res)			/* 0 (result) */
-	: "r" (src),			/* 1 */
-	  "m" (*(dst))			/* 2 */
-	: "memory");				 
-
-	return (res);
-}
-#else /* __i386__ */
-static __inline int
-atomic_cmpset_int(__volatile__ int *dst, int old, int new)
-{
-	int s = splhigh();
-	if (*dst==old) {
-		*dst = new;
-		splx(s);
-		return 1;
-	}
-	splx(s);
-	return 0;
-}
-#endif /* !__i386__ */
-#endif /* !__FreeBSD_version || __FreeBSD_version < 500000 */
-
-static __inline atomic_t
-test_and_set_bit(int b, volatile void *p)
-{
-	int s = splhigh();
-	unsigned int m = 1<<b;
-	unsigned int r = *(volatile int *)p & m;
-	*(volatile int *)p |= m;
-	splx(s);
-	return r;
-}
-
-#else  /* __DragonFly__ */
 
 static __inline atomic_t
 test_and_set_bit(int b, volatile void *p)
@@ -122,8 +55,6 @@
 
 	return (o & m);
 }
-
-#endif /* __DragonFly__ */
 
 static __inline void
 clear_bit(int b, volatile void *p)
diff --git a/sys/dev/drm/drm_auth.c b/sys/dev/drm/drm_auth.c
--- a/sys/dev/drm/drm_auth.c
+++ b/sys/dev/drm/drm_auth.c
@@ -44,7 +44,7 @@
 /**
  * Returns the file private associated with the given magic number.
  */
-static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
+static struct drm_file *drm_find_file(struct drm_device *dev, drm_magic_t magic)
 {
 	drm_magic_entry_t *pt;
 	int hash = drm_hash_magic(magic);
@@ -64,7 +64,8 @@
  * Inserts the given magic number into the hash table of used magic number
  * lists.
  */
-static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
+static int drm_add_magic(struct drm_device *dev, struct drm_file *priv,
+			 drm_magic_t magic)
 {
 	int		  hash;
 	drm_magic_entry_t *entry;
@@ -74,8 +75,9 @@
 	DRM_SPINLOCK_ASSERT(&dev->dev_lock);
 
 	hash = drm_hash_magic(magic);
-	entry = malloc(sizeof(*entry), M_DRM, M_ZERO | M_NOWAIT);
-	if (!entry) return ENOMEM;
+	entry = malloc(sizeof(*entry), DRM_MEM_MAGIC, M_ZERO | M_NOWAIT);
+	if (!entry)
+		return ENOMEM;
 	entry->magic = magic;
 	entry->priv  = priv;
 	entry->next  = NULL;
@@ -95,7 +97,7 @@
  * Removes the given magic number from the hash table of used magic number
  * lists.
  */
-static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
+static int drm_remove_magic(struct drm_device *dev, drm_magic_t magic)
 {
 	drm_magic_entry_t *prev = NULL;
 	drm_magic_entry_t *pt;
@@ -117,11 +119,11 @@
 			if (prev) {
 				prev->next = pt->next;
 			}
+			free(pt, DRM_MEM_MAGIC);
 			return 0;
 		}
 	}
 
-	free(pt, M_DRM);
 	return EINVAL;
 }
 
@@ -133,12 +135,12 @@
  * connection that the magic is passed over) to determine if the magic number
  * should be authenticated.
  */
-int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	static drm_magic_t sequence = 0;
-	drm_auth_t *auth = data;
+	struct drm_auth *auth = data;
 
-				/* Find unique magic */
+	/* Find unique magic */
 	if (file_priv->magic) {
 		auth->magic = file_priv->magic;
 	} else {
@@ -164,10 +166,11 @@
 /**
  * Marks the client associated with the given magic number as authenticated.
  */
-int drm_authmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_authmagic(struct drm_device *dev, void *data,
+		  struct drm_file *file_priv)
 {
-	drm_auth_t *auth = data;
-	drm_file_t *priv;
+	struct drm_auth *auth = data;
+	struct drm_file *priv;
 
 	DRM_DEBUG("%u\n", auth->magic);
 
diff --git a/sys/dev/drm/drm_bufs.c b/sys/dev/drm/drm_bufs.c
--- a/sys/dev/drm/drm_bufs.c
+++ b/sys/dev/drm/drm_bufs.c
@@ -33,36 +33,15 @@
  * Implementation of the ioctls for setup of DRM mappings and DMA buffers.
  */
 
-#ifdef __DragonFly__
 #include <bus/pci/pcireg.h>
-#else
-#include "dev/pci/pcireg.h"
-#endif
 
 #include "drmP.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;
-}
 
 /* Allocation of PCI memory resources (framebuffer, registers, etc.) for
  * drm_get_resource_*.  Note that they are not RF_ACTIVE, so there's no virtual
  * address for accessing them.  Cleaned up at unload.
  */
-static int drm_alloc_resource(drm_device_t *dev, int resource)
+static int drm_alloc_resource(struct drm_device *dev, int resource)
 {
 	if (resource >= DRM_MAX_PCI_RESOURCE) {
 		DRM_ERROR("Resource %d too large\n", resource);
@@ -88,7 +67,8 @@
 	return 0;
 }
 
-unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
+unsigned long drm_get_resource_start(struct drm_device *dev,
+				     unsigned int resource)
 {
 	if (drm_alloc_resource(dev, resource) != 0)
 		return 0;
@@ -96,7 +76,8 @@
 	return rman_get_start(dev->pcir[resource]);
 }
 
-unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
+unsigned long drm_get_resource_len(struct drm_device *dev,
+				   unsigned int resource)
 {
 	if (drm_alloc_resource(dev, resource) != 0)
 		return 0;
@@ -104,8 +85,9 @@
 	return rman_get_size(dev->pcir[resource]);
 }
 
-int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
-    drm_map_type_t type, drm_map_flags_t flags, drm_local_map_t **map_ptr)
+int drm_addmap(struct drm_device * dev, unsigned long offset,
+	       unsigned long size,
+    enum drm_map_type type, enum drm_map_flags flags, drm_local_map_t **map_ptr)
 {
 	drm_local_map_t *map;
 	int align;
@@ -154,16 +136,18 @@
 	/* Allocate a new map structure, fill it in, and do any type-specific
 	 * initialization necessary.
 	 */
-	map = malloc(sizeof(*map), M_DRM, M_ZERO | M_NOWAIT);
-	if ( !map )
+	map = malloc(sizeof(*map), DRM_MEM_MAPS, M_ZERO | M_NOWAIT);
+	if (!map) {
+		DRM_LOCK();
 		return ENOMEM;
+	}
 
 	map->offset = offset;
 	map->size = size;
 	map->type = type;
 	map->flags = flags;
 
-	switch ( map->type ) {
+	switch (map->type) {
 	case _DRM_REGISTERS:
 		map->handle = drm_ioremap(dev, map);
 		if (!(map->flags & _DRM_WRITE_COMBINING))
@@ -174,21 +158,22 @@
 			map->mtrr = 1;
 		break;
 	case _DRM_SHM:
-		map->handle = malloc(map->size, M_DRM, M_NOWAIT);
-		DRM_DEBUG( "%lu %d %p\n",
-			   map->size, drm_order(map->size), map->handle );
-		if ( !map->handle ) {
-			free(map, M_DRM);
+		map->handle = malloc(map->size, DRM_MEM_MAPS, M_NOWAIT);
+		DRM_DEBUG("%lu %d %p\n",
+		    map->size, drm_order(map->size), map->handle);
+		if (!map->handle) {
+			free(map, DRM_MEM_MAPS);
+			DRM_LOCK();
 			return ENOMEM;
 		}
 		map->offset = (unsigned long)map->handle;
-		if ( map->flags & _DRM_CONTAINS_LOCK ) {
+		if (map->flags & _DRM_CONTAINS_LOCK) {
 			/* Prevent a 2nd X Server from creating a 2nd lock */
 			DRM_LOCK();
 			if (dev->lock.hw_lock != NULL) {
 				DRM_UNLOCK();
-				free(map->handle, M_DRM);
-				free(map, M_DRM);
+				free(map->handle, DRM_MEM_MAPS);
+				free(map, DRM_MEM_MAPS);
 				return EBUSY;
 			}
 			dev->lock.hw_lock = map->handle; /* Pointer to lock */
@@ -218,13 +203,15 @@
 			}
 		}
 		if (!valid) {
-			free(map, M_DRM);
+			free(map, DRM_MEM_MAPS);
+			DRM_LOCK();
 			return EACCES;
 		}*/
 		break;
 	case _DRM_SCATTER_GATHER:
 		if (!dev->sg) {
-			free(map, M_DRM);
+			free(map, DRM_MEM_MAPS);
+			DRM_LOCK();
 			return EINVAL;
 		}
 		map->offset = map->offset + dev->sg->handle;
@@ -241,7 +228,8 @@
 			align = PAGE_SIZE;
 		map->dmah = drm_pci_alloc(dev, map->size, align, 0xfffffffful);
 		if (map->dmah == NULL) {
-			free(map, M_DRM);
+			free(map, DRM_MEM_MAPS);
+			DRM_LOCK();
 			return ENOMEM;
 		}
 		map->handle = map->dmah->vaddr;
@@ -249,7 +237,8 @@
 		break;
 	default:
 		DRM_ERROR("Bad map type %d\n", map->type);
-		free(map, M_DRM);
+		free(map, DRM_MEM_MAPS);
+		DRM_LOCK();
 		return EINVAL;
 	}
 
@@ -267,9 +256,10 @@
 	return 0;
 }
 
-int drm_addmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_addmap_ioctl(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv)
 {
-	drm_map_t *request = data;
+	struct drm_map *request = data;
 	drm_local_map_t *map;
 	int err;
 
@@ -300,7 +290,7 @@
 	return 0;
 }
 
-void drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
+void drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
 {
 	DRM_SPINLOCK_ASSERT(&dev->dev_lock);
 
@@ -321,7 +311,7 @@
 		}
 		break;
 	case _DRM_SHM:
-		free(map->handle, M_DRM);
+		free(map->handle, DRM_MEM_MAPS);
 		break;
 	case _DRM_AGP:
 	case _DRM_SCATTER_GATHER:
@@ -339,17 +329,18 @@
 		    map->bsr);
 	}
 
-	free(map, M_DRM);
+	free(map, DRM_MEM_MAPS);
 }
 
 /* Remove a map private from list and deallocate resources if the mapping
  * isn't in use.
  */
 
-int drm_rmmap_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_rmmap_ioctl(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
 {
 	drm_local_map_t *map;
-	drm_map_t *request = data;
+	struct drm_map *request = data;
 
 	DRM_LOCK();
 	TAILQ_FOREACH(map, &dev->maplist, link) {
@@ -372,7 +363,8 @@
 }
 
 
-static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
+static void drm_cleanup_buf_error(struct drm_device *dev,
+				  drm_buf_entry_t *entry)
 {
 	int i;
 
@@ -380,22 +372,22 @@
 		for (i = 0; i < entry->seg_count; i++) {
 			drm_pci_free(dev, entry->seglist[i]);
 		}
-		free(entry->seglist, M_DRM);
+		free(entry->seglist, DRM_MEM_SEGS);
 
 		entry->seg_count = 0;
 	}
 
    	if (entry->buf_count) {
 	   	for (i = 0; i < entry->buf_count; i++) {
-			free(entry->buflist[i].dev_private, M_DRM);
+			free(entry->buflist[i].dev_private, DRM_MEM_BUFS);
 		}
-		free(entry->buflist, M_DRM);
+		free(entry->buflist, DRM_MEM_BUFS);
 
 		entry->buf_count = 0;
 	}
 }
 
-static int drm_do_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
+static int drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request)
 {
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_entry_t *entry;
@@ -419,20 +411,20 @@
 	size = 1 << order;
 
 	alignment  = (request->flags & _DRM_PAGE_ALIGN)
-		? round_page(size) : size;
+	    ? round_page(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: 0x%lx\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("count:      %d\n",  count);
+	DRM_DEBUG("order:      %d\n",  order);
+	DRM_DEBUG("size:       %d\n",  size);
+	DRM_DEBUG("agp_offset: 0x%lx\n", agp_offset);
+	DRM_DEBUG("alignment:  %d\n",  alignment);
+	DRM_DEBUG("page_order: %d\n",  page_order);
+	DRM_DEBUG("total:      %d\n",  total);
 
 	/* Make sure buffers are located in AGP memory that we own */
 	/* Breaks MGA due to drm_alloc_agp not setting up entries for the
@@ -456,9 +448,9 @@
 
 	entry = &dma->bufs[order];
 
-	entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM,
+	entry->buflist = malloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS,
 	    M_NOWAIT | M_ZERO);
-	if ( !entry->buflist ) {
+	if (!entry->buflist) {
 		return ENOMEM;
 	}
 
@@ -467,7 +459,7 @@
 
 	offset = 0;
 
-	while ( entry->buf_count < count ) {
+	while (entry->buf_count < count) {
 		buf          = &entry->buflist[entry->buf_count];
 		buf->idx     = dma->buf_count + entry->buf_count;
 		buf->total   = alignment;
@@ -481,8 +473,8 @@
 		buf->pending = 0;
 		buf->file_priv = NULL;
 
-		buf->dev_priv_size = dev->driver.buf_priv_size;
-		buf->dev_private = malloc(buf->dev_priv_size, M_DRM,
+		buf->dev_priv_size = dev->driver->buf_priv_size;
+		buf->dev_private = malloc(buf->dev_priv_size, DRM_MEM_BUFS,
 		    M_NOWAIT | M_ZERO);
 		if (buf->dev_private == NULL) {
 			/* Set count correctly so we free the proper amount. */
@@ -496,11 +488,11 @@
 		byte_count += PAGE_SIZE << page_order;
 	}
 
-	DRM_DEBUG( "byte_count: %d\n", byte_count );
+	DRM_DEBUG("byte_count: %d\n", byte_count);
 
 	temp_buflist = realloc(dma->buflist,
-	    (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist), M_DRM,
-	    M_NOWAIT);
+	    (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
+	    DRM_MEM_BUFS, M_NOWAIT);
 	if (temp_buflist == NULL) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
@@ -508,15 +500,15 @@
 	}
 	dma->buflist = temp_buflist;
 
-	for ( i = 0 ; i < entry->buf_count ; i++ ) {
+	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 );
+	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
 
 	request->count = entry->buf_count;
 	request->size = size;
@@ -526,7 +518,7 @@
 	return 0;
 }
 
-static int drm_do_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
+static int drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request)
 {
 	drm_device_dma_t *dma = dev->dma;
 	int count;
@@ -548,68 +540,71 @@
 	order = drm_order(request->size);
 	size = 1 << order;
 
-	DRM_DEBUG( "count=%d, size=%d (%d), order=%d\n",
-		   request->count, request->size, size, order );
+	DRM_DEBUG("count=%d, size=%d (%d), order=%d\n",
+	    request->count, request->size, size, order);
 
 	alignment = (request->flags & _DRM_PAGE_ALIGN)
-		? round_page(size) : size;
+	    ? round_page(size) : size;
 	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
 	total = PAGE_SIZE << page_order;
 
 	entry = &dma->bufs[order];
 
-	entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM,
+	entry->buflist = malloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS,
 	    M_NOWAIT | M_ZERO);
-	entry->seglist = malloc(count * sizeof(*entry->seglist), M_DRM,
+	entry->seglist = malloc(count * sizeof(*entry->seglist), DRM_MEM_SEGS,
 	    M_NOWAIT | M_ZERO);
 
 	/* Keep the original pagelist until we know all the allocations
 	 * have succeeded
 	 */
 	temp_pagelist = malloc((dma->page_count + (count << page_order)) *
-	    sizeof(*dma->pagelist), M_DRM, M_NOWAIT);
+	    sizeof(*dma->pagelist), DRM_MEM_PAGES, M_NOWAIT);
 
 	if (entry->buflist == NULL || entry->seglist == NULL || 
 	    temp_pagelist == NULL) {
-		free(entry->buflist, M_DRM);
-		free(entry->seglist, M_DRM);
+		free(temp_pagelist, DRM_MEM_PAGES);
+		free(entry->seglist, DRM_MEM_SEGS);
+		free(entry->buflist, DRM_MEM_BUFS);
 		return ENOMEM;
 	}
-	
+
 	memcpy(temp_pagelist, dma->pagelist, dma->page_count * 
 	    sizeof(*dma->pagelist));
 
-	DRM_DEBUG( "pagelist: %d entries\n",
-		   dma->page_count + (count << page_order) );
+	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 ) {
+	while (entry->buf_count < count) {
+		DRM_SPINUNLOCK(&dev->dma_lock);
 		drm_dma_handle_t *dmah = drm_pci_alloc(dev, size, alignment,
 		    0xfffffffful);
+		DRM_SPINLOCK(&dev->dma_lock);
 		if (dmah == NULL) {
 			/* Set count correctly so we free the proper amount. */
 			entry->buf_count = count;
 			entry->seg_count = count;
 			drm_cleanup_buf_error(dev, entry);
-			free(temp_pagelist, M_DRM);
+			free(temp_pagelist, DRM_MEM_PAGES);
 			return ENOMEM;
 		}
 
 		entry->seglist[entry->seg_count++] = dmah;
-		for ( i = 0 ; i < (1 << page_order) ; i++ ) {
-			DRM_DEBUG( "page %d @ %p\n",
-				   dma->page_count + page_count,
-				   (char *)dmah->vaddr + PAGE_SIZE * i );
+		for (i = 0; i < (1 << page_order); i++) {
+			DRM_DEBUG("page %d @ %p\n",
+			    dma->page_count + page_count,
+			    (char *)dmah->vaddr + PAGE_SIZE * i);
 			temp_pagelist[dma->page_count + page_count++] = 
 			    (long)dmah->vaddr + PAGE_SIZE * i;
 		}
-		for ( offset = 0 ;
-		      offset + size <= total && entry->buf_count < count ;
-		      offset += alignment, ++entry->buf_count ) {
+		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;
@@ -622,43 +617,43 @@
 			buf->pending = 0;
 			buf->file_priv = NULL;
 
-			buf->dev_priv_size = dev->driver.buf_priv_size;
-			buf->dev_private = malloc(buf->dev_priv_size, M_DRM,
-			    M_NOWAIT | M_ZERO);
+			buf->dev_priv_size = dev->driver->buf_priv_size;
+			buf->dev_private = malloc(buf->dev_priv_size,
+			    DRM_MEM_BUFS, M_NOWAIT | M_ZERO);
 			if (buf->dev_private == NULL) {
 				/* Set count correctly so we free the proper amount. */
 				entry->buf_count = count;
 				entry->seg_count = count;
 				drm_cleanup_buf_error(dev, entry);
-				free(temp_pagelist, M_DRM);
+				free(temp_pagelist, DRM_MEM_PAGES);
 				return ENOMEM;
 			}
 
-			DRM_DEBUG( "buffer %d @ %p\n",
-				   entry->buf_count, buf->address );
+			DRM_DEBUG("buffer %d @ %p\n",
+			    entry->buf_count, buf->address);
 		}
 		byte_count += PAGE_SIZE << page_order;
 	}
 
 	temp_buflist = realloc(dma->buflist,
-	    (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist), M_DRM,
-	    M_NOWAIT);
+	    (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
+	    DRM_MEM_BUFS, M_NOWAIT);
 	if (temp_buflist == NULL) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
-		free(temp_pagelist, M_DRM);
+		free(temp_pagelist, DRM_MEM_PAGES);
 		return ENOMEM;
 	}
 	dma->buflist = temp_buflist;
 
-	for ( i = 0 ; i < entry->buf_count ; i++ ) {
+	for (i = 0; i < entry->buf_count; i++) {
 		dma->buflist[i + dma->buf_count] = &entry->buflist[i];
 	}
 
 	/* No allocations failed, so now we can replace the orginal pagelist
 	 * with the new one.
 	 */
-	free(dma->pagelist, M_DRM);
+	free(dma->pagelist, DRM_MEM_PAGES);
 	dma->pagelist = temp_pagelist;
 
 	dma->buf_count += entry->buf_count;
@@ -673,7 +668,7 @@
 
 }
 
-static int drm_do_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
+static int drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request)
 {
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_entry_t *entry;
@@ -695,24 +690,24 @@
 	size = 1 << order;
 
 	alignment  = (request->flags & _DRM_PAGE_ALIGN)
-		? round_page(size) : size;
+	    ? round_page(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 );
+	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);
 
 	entry = &dma->bufs[order];
 
-	entry->buflist = malloc(count * sizeof(*entry->buflist), M_DRM,
+	entry->buflist = malloc(count * sizeof(*entry->buflist), DRM_MEM_BUFS,
 	    M_NOWAIT | M_ZERO);
 	if (entry->buflist == NULL)
 		return ENOMEM;
@@ -722,7 +717,7 @@
 
 	offset = 0;
 
-	while ( entry->buf_count < count ) {
+	while (entry->buf_count < count) {
 		buf          = &entry->buflist[entry->buf_count];
 		buf->idx     = dma->buf_count + entry->buf_count;
 		buf->total   = alignment;
@@ -736,8 +731,8 @@
 		buf->pending = 0;
 		buf->file_priv = NULL;
 
-		buf->dev_priv_size = dev->driver.buf_priv_size;
-		buf->dev_private = malloc(buf->dev_priv_size, M_DRM,
+		buf->dev_priv_size = dev->driver->buf_priv_size;
+		buf->dev_private = malloc(buf->dev_priv_size, DRM_MEM_BUFS,
 		    M_NOWAIT | M_ZERO);
 		if (buf->dev_private == NULL) {
 			/* Set count correctly so we free the proper amount. */
@@ -746,19 +741,19 @@
 			return ENOMEM;
 		}
 
-		DRM_DEBUG( "buffer %d @ %p\n",
-			   entry->buf_count, buf->address );
+		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 );
+	DRM_DEBUG("byte_count: %d\n", byte_count);
 
 	temp_buflist = realloc(dma->buflist,
-	    (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist), M_DRM,
-	    M_NOWAIT);
+	    (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
+	    DRM_MEM_BUFS, M_NOWAIT);
 	if (temp_buflist == NULL) {
 		/* Free the entry because it isn't valid */
 		drm_cleanup_buf_error(dev, entry);
@@ -766,15 +761,15 @@
 	}
 	dma->buflist = temp_buflist;
 
-	for ( i = 0 ; i < entry->buf_count ; i++ ) {
+	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 );
+	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
 
 	request->count = entry->buf_count;
 	request->size = size;
@@ -784,11 +779,9 @@
 	return 0;
 }
 
-int drm_addbufs_agp(drm_device_t *dev, drm_buf_desc_t *request)
+int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request)
 {
 	int order, ret;
-
-	DRM_SPINLOCK(&dev->dma_lock);
 
 	if (request->count < 0 || request->count > 4096)
 		return EINVAL;
@@ -796,6 +789,8 @@
 	order = drm_order(request->size);
 	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
 		return EINVAL;
+
+	DRM_SPINLOCK(&dev->dma_lock);
 
 	/* No more allocations after first buffer-using ioctl. */
 	if (dev->buf_use != 0) {
@@ -815,21 +810,21 @@
 	return ret;
 }
 
-int drm_addbufs_sg(drm_device_t *dev, drm_buf_desc_t *request)
+int drm_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request)
 {
 	int order, ret;
-
-	DRM_SPINLOCK(&dev->dma_lock);
 
 	if (!DRM_SUSER(DRM_CURPROC))
 		return EACCES;
 
 	if (request->count < 0 || request->count > 4096)
 		return EINVAL;
-	
+
 	order = drm_order(request->size);
 	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
 		return EINVAL;
+
+	DRM_SPINLOCK(&dev->dma_lock);
 
 	/* No more allocations after first buffer-using ioctl. */
 	if (dev->buf_use != 0) {
@@ -849,21 +844,21 @@
 	return ret;
 }
 
-int drm_addbufs_pci(drm_device_t *dev, drm_buf_desc_t *request)
+int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request)
 {
 	int order, ret;
-
-	DRM_SPINLOCK(&dev->dma_lock);
 
 	if (!DRM_SUSER(DRM_CURPROC))
 		return EACCES;
 
 	if (request->count < 0 || request->count > 4096)
 		return EINVAL;
-	
+
 	order = drm_order(request->size);
 	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
 		return EINVAL;
+
+	DRM_SPINLOCK(&dev->dma_lock);
 
 	/* No more allocations after first buffer-using ioctl. */
 	if (dev->buf_use != 0) {
@@ -883,9 +878,10 @@
 	return ret;
 }
 
-int drm_addbufs_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_addbufs_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
 {
-	drm_buf_desc_t *request = data;
+	struct drm_buf_desc *request = data;
 	int err;
 
 	if (request->flags & _DRM_AGP_BUFFER)
@@ -898,10 +894,10 @@
 	return err;
 }
 
-int drm_infobufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_infobufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_device_dma_t *dma = dev->dma;
-	drm_buf_info_t *request = data;
+	struct drm_buf_info *request = data;
 	int i;
 	int count;
 	int retcode = 0;
@@ -910,16 +906,17 @@
 	++dev->buf_use;		/* Can't allocate more after this call */
 	DRM_SPINUNLOCK(&dev->dma_lock);
 
-	for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) {
-		if ( dma->bufs[i].buf_count ) ++count;
+	for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
+		if (dma->bufs[i].buf_count)
+			++count;
 	}
 
-	DRM_DEBUG( "count = %d\n", 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 from;
+	if (request->count >= count) {
+		for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
+			if (dma->bufs[i].buf_count) {
+				struct drm_buf_desc from;
 
 				from.count = dma->bufs[i].buf_count;
 				from.size = dma->bufs[i].buf_size;
@@ -927,17 +924,16 @@
 				from.high_mark = dma->bufs[i].freelist.high_mark;
 
 				if (DRM_COPY_TO_USER(&request->list[count], &from,
-				    sizeof(drm_buf_desc_t)) != 0) {
+				    sizeof(struct drm_buf_desc)) != 0) {
 					retcode = EFAULT;
 					break;
 				}
 
-				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 );
+				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;
 			}
 		}
@@ -947,14 +943,14 @@
 	return retcode;
 }
 
-int drm_markbufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_markbufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_device_dma_t *dma = dev->dma;
-	drm_buf_desc_t *request = data;
+	struct drm_buf_desc *request = data;
 	int order;
 
-	DRM_DEBUG( "%d, %d, %d\n",
-		   request->size, request->low_mark, request->high_mark );
+	DRM_DEBUG("%d, %d, %d\n",
+		  request->size, request->low_mark, request->high_mark);
 	
 
 	order = drm_order(request->size);	
@@ -966,6 +962,7 @@
 	DRM_SPINLOCK(&dev->dma_lock);
 	if (request->low_mark > dma->bufs[order].buf_count ||
 	    request->high_mark > dma->bufs[order].buf_count) {
+		DRM_SPINUNLOCK(&dev->dma_lock);
 		return EINVAL;
 	}
 
@@ -976,33 +973,33 @@
 	return 0;
 }
 
-int drm_freebufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_freebufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_device_dma_t *dma = dev->dma;
-	drm_buf_free_t *request = data;
+	struct drm_buf_free *request = data;
 	int i;
 	int idx;
 	drm_buf_t *buf;
 	int retcode = 0;
 
-	DRM_DEBUG( "%d\n", request->count );
+	DRM_DEBUG("%d\n", request->count);
 	
 	DRM_SPINLOCK(&dev->dma_lock);
-	for ( i = 0 ; i < request->count ; i++ ) {
+	for (i = 0; i < request->count; i++) {
 		if (DRM_COPY_FROM_USER(&idx, &request->list[i], sizeof(idx))) {
 			retcode = EFAULT;
 			break;
 		}
-		if ( idx < 0 || idx >= dma->buf_count ) {
-			DRM_ERROR( "Index %d (of %d max)\n",
-				   idx, dma->buf_count - 1 );
+		if (idx < 0 || idx >= dma->buf_count) {
+			DRM_ERROR("Index %d (of %d max)\n",
+			    idx, dma->buf_count - 1);
 			retcode = EINVAL;
 			break;
 		}
 		buf = dma->buflist[idx];
-		if ( buf->file_priv != file_priv ) {
+		if (buf->file_priv != file_priv) {
 			DRM_ERROR("Process %d freeing buffer not owned\n",
-				   DRM_CURRENTPID);
+			    DRM_CURRENTPID);
 			retcode = EINVAL;
 			break;
 		}
@@ -1013,37 +1010,20 @@
 	return retcode;
 }
 
-int drm_mapbufs(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_mapbufs(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_device_dma_t *dma = dev->dma;
 	int retcode = 0;
 	const int zero = 0;
 	vm_offset_t address;
 	struct vmspace *vms;
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	vm_ooffset_t foff;
 	vm_size_t size;
 	vm_offset_t vaddr;
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	struct vnode *vn;
-	voff_t foff;
-	vsize_t size;
-	vaddr_t vaddr;
-#endif /* __NetBSD__ || __OpenBSD__ */
-
-	drm_buf_map_t *request = data;
+	struct drm_buf_map *request = data;
 	int i;
 
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-	if (!vfinddev(kdev, VCHR, &vn))
-		return 0;	/* FIXME: Shouldn't this be EINVAL or something? */
-#endif /* __NetBSD__ || __OpenBSD */
-
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 || defined(__DragonFly__)
 	vms = DRM_CURPROC->td_proc->p_vmspace;
-#else
-	vms = DRM_CURPROC->p_vmspace;
-#endif
 
 	DRM_SPINLOCK(&dev->dma_lock);
 	dev->buf_use++;		/* Can't allocate more after this call */
@@ -1052,8 +1032,9 @@
 	if (request->count < dma->buf_count)
 		goto done;
 
-	if ((dev->driver.use_agp && (dma->flags & _DRM_DMA_USE_AGP)) ||
-	    (dev->driver.use_sg && (dma->flags & _DRM_DMA_USE_SG))) {
+	if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) ||
+	    (drm_core_check_feature(dev, DRIVER_SG) &&
+	    (dma->flags & _DRM_DMA_USE_SG))) {
 		drm_local_map_t *map = dev->agp_buffer_map;
 
 		if (map == NULL) {
@@ -1067,28 +1048,17 @@
 		foff = 0;
 	}
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	vaddr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
-#if __FreeBSD_version >= 600023
-	retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
-	    VM_PROT_ALL, MAP_SHARED, OBJT_DEVICE, dev->devnode, foff);
-#else
 	retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
 	    VM_PROT_ALL, MAP_SHARED, SLIST_FIRST(&dev->devnode->si_hlist),
 	    foff);
-#endif
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	vaddr = round_page((vaddr_t)vms->vm_daddr + MAXDSIZ);
-	retcode = uvm_mmap(&vms->vm_map, &vaddr, size,
-	    UVM_PROT_READ | UVM_PROT_WRITE, UVM_PROT_ALL, MAP_SHARED,
-	    &vn->v_uobj, foff, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
-#endif /* __NetBSD__ || __OpenBSD */
+
 	if (retcode)
 		goto done;
 
 	request->virtual = (void *)vaddr;
 
-	for ( i = 0 ; i < dma->buf_count ; i++ ) {
+	for (i = 0; i < dma->buf_count; i++) {
 		if (DRM_COPY_TO_USER(&request->list[i].idx,
 		    &dma->buflist[i]->idx, sizeof(request->list[0].idx))) {
 			retcode = EFAULT;
@@ -1115,7 +1085,36 @@
  done:
 	request->count = dma->buf_count;
 
-	DRM_DEBUG( "%d buffers, retcode = %d\n", request->count, retcode );
+	DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
 
 	return retcode;
 }
+
+/* XXX */
+int ffsl(long mask)
+{
+	int bit;
+
+	if (mask == 0)
+		return 0;
+	for (bit = 1; !(mask & 1); bit++)
+		mask = (unsigned long)mask >> 1;
+	return bit;
+}
+
+/*
+ * Compute order.  Can be made faster.
+ */
+int drm_order(unsigned long size)
+{
+	int order;
+
+	if (size == 0)
+		return 0;
+
+	order = ffsl(size) - 1;
+	if (size & ~(1ul << order))
+		++order;
+
+	return order;
+}
diff --git a/sys/dev/drm/drm_context.c b/sys/dev/drm/drm_context.c
--- a/sys/dev/drm/drm_context.c
+++ b/sys/dev/drm/drm_context.c
@@ -39,7 +39,7 @@
  * Context bitmap support
  */
 
-void drm_ctxbitmap_free(drm_device_t *dev, int ctx_handle)
+void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle)
 {
 	if (ctx_handle < 0 || ctx_handle >= DRM_MAX_CTXBITMAP || 
 	    dev->ctx_bitmap == NULL) {
@@ -55,7 +55,7 @@
 	return;
 }
 
-int drm_ctxbitmap_next(drm_device_t *dev)
+int drm_ctxbitmap_next(struct drm_device *dev)
 {
 	int bit;
 
@@ -63,7 +63,7 @@
 		return -1;
 
 	DRM_LOCK();
-	bit = find_first_zero_bit( dev->ctx_bitmap, DRM_MAX_CTXBITMAP );
+	bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
 	if (bit >= DRM_MAX_CTXBITMAP) {
 		DRM_UNLOCK();
 		return -1;
@@ -78,7 +78,7 @@
 
 			ctx_sareas = realloc(dev->context_sareas,
 			    dev->max_context * sizeof(*dev->context_sareas),
-			    M_DRM, M_NOWAIT);
+			    DRM_MEM_SAREA, M_NOWAIT);
 			if (ctx_sareas == NULL) {
 				clear_bit(bit, dev->ctx_bitmap);
 				DRM_UNLOCK();
@@ -89,7 +89,8 @@
 		} else {
 			/* max_context == 1 at this point */
 			dev->context_sareas = malloc(dev->max_context * 
-			    sizeof(*dev->context_sareas), M_DRM, M_NOWAIT);
+			    sizeof(*dev->context_sareas), DRM_MEM_SAREA,
+			    M_NOWAIT);
 			if (dev->context_sareas == NULL) {
 				clear_bit(bit, dev->ctx_bitmap);
 				DRM_UNLOCK();
@@ -102,14 +103,15 @@
 	return bit;
 }
 
-int drm_ctxbitmap_init(drm_device_t *dev)
+int drm_ctxbitmap_init(struct drm_device *dev)
 {
 	int i;
    	int temp;
 
 	DRM_LOCK();
-	dev->ctx_bitmap = malloc(PAGE_SIZE, M_DRM, M_NOWAIT | M_ZERO);
-	if ( dev->ctx_bitmap == NULL ) {
+	dev->ctx_bitmap = malloc(PAGE_SIZE, DRM_MEM_CTXBITMAP,
+	    M_NOWAIT | M_ZERO);
+	if (dev->ctx_bitmap == NULL) {
 		DRM_UNLOCK();
 		return ENOMEM;
 	}
@@ -117,20 +119,20 @@
 	dev->max_context = -1;
 	DRM_UNLOCK();
 
-	for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
+	for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
 		temp = drm_ctxbitmap_next(dev);
-	   	DRM_DEBUG( "drm_ctxbitmap_init : %d\n", temp );
+		DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
 	}
 
 	return 0;
 }
 
-void drm_ctxbitmap_cleanup(drm_device_t *dev)
+void drm_ctxbitmap_cleanup(struct drm_device *dev)
 {
 	DRM_LOCK();
 	if (dev->context_sareas != NULL)
-		free(dev->context_sareas, M_DRM);
-	free(dev->ctx_bitmap, M_DRM);
+		free(dev->context_sareas, DRM_MEM_SAREA);
+	free(dev->ctx_bitmap, DRM_MEM_CTXBITMAP);
 	DRM_UNLOCK();
 }
 
@@ -138,9 +140,10 @@
  * Per Context SAREA Support
  */
 
-int drm_getsareactx( drm_device_t *dev, void *data, struct drm_file *file_priv )
+int drm_getsareactx(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
 {
-	drm_ctx_priv_map_t *request = data;
+	struct drm_ctx_priv_map *request = data;
 	drm_local_map_t *map;
 
 	DRM_LOCK();
@@ -158,9 +161,10 @@
 	return 0;
 }
 
-int drm_setsareactx(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_setsareactx(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
 {
-	drm_ctx_priv_map_t *request = data;
+	struct drm_ctx_priv_map *request = data;
 	drm_local_map_t *map = NULL;
 
 	DRM_LOCK();
@@ -185,51 +189,51 @@
  * The actual DRM context handling routines
  */
 
-int drm_context_switch(drm_device_t *dev, int old, int new)
+int drm_context_switch(struct drm_device *dev, int old, int new)
 {
-        if ( test_and_set_bit( 0, &dev->context_flag ) ) {
-                DRM_ERROR( "Reentering -- FIXME\n" );
-                return EBUSY;
-        }
+	if (test_and_set_bit(0, &dev->context_flag)) {
+		DRM_ERROR("Reentering -- FIXME\n");
+		return EBUSY;
+	}
 
-        DRM_DEBUG( "Context switch from %d to %d\n", old, new );
+	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 (new == dev->last_context) {
+		clear_bit(0, &dev->context_flag);
+		return 0;
+	}
 
-        return 0;
+	return 0;
 }
 
-int drm_context_switch_complete(drm_device_t *dev, int new)
+int drm_context_switch_complete(struct drm_device *dev, int new)
 {
-        dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
+	dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
 
-        if ( !_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ) {
-                DRM_ERROR( "Lock isn't held after context switch\n" );
-        }
+	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. */
-        clear_bit( 0, &dev->context_flag );
+	/* If a context switch is ever initiated
+	   when the kernel holds the lock, release
+	   that lock here. */
+	clear_bit(0, &dev->context_flag);
 
-        return 0;
+	return 0;
 }
 
-int drm_resctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_resctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_ctx_res_t *res = data;
-	drm_ctx_t ctx;
+	struct drm_ctx_res *res = data;
+	struct drm_ctx ctx;
 	int i;
 
-	if ( res->count >= DRM_RESERVED_CONTEXTS ) {
+	if (res->count >= DRM_RESERVED_CONTEXTS) {
 		bzero(&ctx, sizeof(ctx));
-		for ( i = 0 ; i < DRM_RESERVED_CONTEXTS ; i++ ) {
+		for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
 			ctx.handle = i;
-			if ( DRM_COPY_TO_USER( &res->contexts[i],
-					   &ctx, sizeof(ctx) ) )
+			if (DRM_COPY_TO_USER(&res->contexts[i],
+			    &ctx, sizeof(ctx)))
 				return EFAULT;
 		}
 	}
@@ -238,40 +242,40 @@
 	return 0;
 }
 
-int drm_addctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_addctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_ctx_t *ctx = data;
+	struct drm_ctx *ctx = data;
 
 	ctx->handle = drm_ctxbitmap_next(dev);
-	if ( ctx->handle == DRM_KERNEL_CONTEXT ) {
-				/* Skip kernel's context and get a new one. */
+	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? */
+	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 (dev->driver.context_ctor && ctx->handle != DRM_KERNEL_CONTEXT) {
+	if (dev->driver->context_ctor && ctx->handle != DRM_KERNEL_CONTEXT) {
 		DRM_LOCK();
-		dev->driver.context_ctor(dev, ctx->handle);
+		dev->driver->context_ctor(dev, ctx->handle);
 		DRM_UNLOCK();
 	}
 
 	return 0;
 }
 
-int drm_modctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	/* This does nothing */
 	return 0;
 }
 
-int drm_getctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_ctx_t *ctx = data;
+	struct drm_ctx *ctx = data;
 
 	/* This is 0, because we don't handle any context flags */
 	ctx->flags = 0;
@@ -279,33 +283,34 @@
 	return 0;
 }
 
-int drm_switchctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_switchctx(struct drm_device *dev, void *data,
+		  struct drm_file *file_priv)
 {
-	drm_ctx_t *ctx = data;
+	struct drm_ctx *ctx = data;
 
-	DRM_DEBUG( "%d\n", ctx->handle );
+	DRM_DEBUG("%d\n", ctx->handle);
 	return drm_context_switch(dev, dev->last_context, ctx->handle);
 }
 
-int drm_newctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_newctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_ctx_t *ctx = data;
+	struct drm_ctx *ctx = data;
 
-	DRM_DEBUG( "%d\n", ctx->handle );
+	DRM_DEBUG("%d\n", ctx->handle);
 	drm_context_switch_complete(dev, ctx->handle);
 
 	return 0;
 }
 
-int drm_rmctx(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_rmctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_ctx_t *ctx = data;
+	struct drm_ctx *ctx = data;
 
-	DRM_DEBUG( "%d\n", ctx->handle );
-	if ( ctx->handle != DRM_KERNEL_CONTEXT ) {
-		if (dev->driver.context_dtor) {
+	DRM_DEBUG("%d\n", ctx->handle);
+	if (ctx->handle != DRM_KERNEL_CONTEXT) {
+		if (dev->driver->context_dtor) {
 			DRM_LOCK();
-			dev->driver.context_dtor(dev, ctx->handle);
+			dev->driver->context_dtor(dev, ctx->handle);
 			DRM_UNLOCK();
 		}
 
diff --git a/sys/dev/drm/drm_dma.c b/sys/dev/drm/drm_dma.c
--- a/sys/dev/drm/drm_dma.c
+++ b/sys/dev/drm/drm_dma.c
@@ -39,10 +39,10 @@
 
 #include "drmP.h"
 
-int drm_dma_setup(drm_device_t *dev)
+int drm_dma_setup(struct drm_device *dev)
 {
 
-	dev->dma = malloc(sizeof(*dev->dma), M_DRM, M_NOWAIT | M_ZERO);
+	dev->dma = malloc(sizeof(*dev->dma), DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
 	if (dev->dma == NULL)
 		return ENOMEM;
 
@@ -51,7 +51,7 @@
 	return 0;
 }
 
-void drm_dma_takedown(drm_device_t *dev)
+void drm_dma_takedown(struct drm_device *dev)
 {
 	drm_device_dma_t  *dma = dev->dma;
 	int		  i, j;
@@ -59,52 +59,53 @@
 	if (dma == NULL)
 		return;
 
-				/* Clear dma buffers */
+	/* 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);
+			    " 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_pci_free(dev, dma->bufs[i].seglist[j]);
 			}
-			free(dma->bufs[i].seglist, M_DRM);
+			free(dma->bufs[i].seglist, DRM_MEM_SEGS);
 		}
 
 	   	if (dma->bufs[i].buf_count) {
 		   	for (j = 0; j < dma->bufs[i].buf_count; j++) {
 				free(dma->bufs[i].buflist[j].dev_private,
-				    M_DRM);
+				    DRM_MEM_BUFS);
 			}
-		   	free(dma->bufs[i].buflist, M_DRM);
+		   	free(dma->bufs[i].buflist, DRM_MEM_BUFS);
 		}
 	}
 
-	free(dma->buflist, M_DRM);
-	free(dma->pagelist, M_DRM);
-	free(dev->dma, M_DRM);
+	free(dma->buflist, DRM_MEM_BUFS);
+	free(dma->pagelist, DRM_MEM_PAGES);
+	free(dev->dma, DRM_MEM_DRIVER);
 	dev->dma = NULL;
 	DRM_SPINUNINIT(&dev->dma_lock);
 }
 
 
-void drm_free_buffer(drm_device_t *dev, drm_buf_t *buf)
+void drm_free_buffer(struct drm_device *dev, drm_buf_t *buf)
 {
-	if (!buf) return;
+	if (!buf)
+		return;
 
 	buf->pending  = 0;
 	buf->file_priv= NULL;
 	buf->used     = 0;
 }
 
-void drm_reclaim_buffers(drm_device_t *dev, struct drm_file *file_priv)
+void drm_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
 {
 	drm_device_dma_t *dma = dev->dma;
 	int		 i;
 
-	if (!dma) return;
+	if (!dma)
+		return;
+
 	for (i = 0; i < dma->buf_count; i++) {
 		if (dma->buflist[i]->file_priv == file_priv) {
 			switch (dma->buflist[i]->list) {
@@ -123,12 +124,12 @@
 }
 
 /* Call into the driver-specific DMA handler */
-int drm_dma(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_dma(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 
-	if (dev->driver.dma_ioctl) {
+	if (dev->driver->dma_ioctl) {
 		/* shared code returns -errno */
-		return -dev->driver.dma_ioctl(dev, data, file_priv);
+		return -dev->driver->dma_ioctl(dev, data, file_priv);
 	} else {
 		DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
 		return EINVAL;
diff --git a/sys/dev/drm/drm_drawable.c b/sys/dev/drm/drm_drawable.c
--- a/sys/dev/drm/drm_drawable.c
+++ b/sys/dev/drm/drm_drawable.c
@@ -52,13 +52,14 @@
 		return -1;
 	return 0;
 }
+
 RB_PROTOTYPE_STATIC(drawable_tree, bsd_drm_drawable_info, tree,
     drm_drawable_compare);
 RB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree,
     drm_drawable_compare);
 
 struct drm_drawable_info *
-drm_get_drawable_info(drm_device_t *dev, int handle)
+drm_get_drawable_info(struct drm_device *dev, int handle)
 {
 	struct bsd_drm_drawable_info find, *result;
 
@@ -68,24 +69,21 @@
 	return &result->info;
 }
 
-int drm_adddraw(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_draw_t *draw = data;
+	struct drm_draw *draw = data;
 	struct bsd_drm_drawable_info *info;
 
-	info = drm_calloc(1, sizeof(struct bsd_drm_drawable_info),
-	    DRM_MEM_DRAWABLE);
+	info = malloc(sizeof(struct bsd_drm_drawable_info), DRM_MEM_DRAWABLE,
+	    M_NOWAIT | M_ZERO);
 	if (info == NULL)
 		return ENOMEM;
 
-#ifdef __FreeBSD__
-	info->handle = alloc_unr(dev->drw_unrhdr);
-#else
 	/*
 	 * XXX Only valid for sizeof(int) == sizeof(void *)
 	 */
 	info->handle = (int)info;
-#endif
+
 	DRM_SPINLOCK(&dev->drw_lock);
 	RB_INSERT(drawable_tree, &dev->drw_head, info);
 	draw->handle = info->handle;
@@ -96,9 +94,9 @@
 	return 0;
 }
 
-int drm_rmdraw(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_draw_t *draw = (drm_draw_t *)data;
+	struct drm_draw *draw = (struct drm_draw *)data;
 	struct drm_drawable_info *info;
 
 	DRM_SPINLOCK(&dev->drw_lock);
@@ -107,11 +105,8 @@
 		RB_REMOVE(drawable_tree, &dev->drw_head,
 		    (struct bsd_drm_drawable_info *)info);
 		DRM_SPINUNLOCK(&dev->drw_lock);
-#ifdef __FreeBSD__
-		free_unr(dev->drw_unrhdr, draw->handle);
-#endif
-		drm_free(info, sizeof(struct bsd_drm_drawable_info),
-		    DRM_MEM_DRAWABLE);
+		free(info->rects, DRM_MEM_DRAWABLE);
+		free(info, DRM_MEM_DRAWABLE);
 		return 0;
 	} else {
 		DRM_SPINUNLOCK(&dev->drw_lock);
@@ -119,7 +114,8 @@
 	}
 }
 
-int drm_update_draw(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_update_draw(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
 {
 	struct drm_drawable_info *info;
 	struct drm_update_draw *update = (struct drm_update_draw *)data;
@@ -133,9 +129,7 @@
 	case DRM_DRAWABLE_CLIPRECTS:
 		DRM_SPINLOCK(&dev->drw_lock);
 		if (update->num != info->num_rects) {
-			drm_free(info->rects,
-			    sizeof(*info->rects) * info->num_rects,
-			    DRM_MEM_DRAWABLE);
+			free(info->rects, DRM_MEM_DRAWABLE);
 			info->rects = NULL;
 			info->num_rects = 0;
 		}
@@ -144,10 +138,12 @@
 			return 0;
 		}
 		if (info->rects == NULL) {
-			info->rects = drm_alloc(sizeof(*info->rects) *
-			    update->num, DRM_MEM_DRAWABLE);
-			if (info->rects == NULL)
+			info->rects = malloc(sizeof(*info->rects) *
+			    update->num, DRM_MEM_DRAWABLE, M_NOWAIT);
+			if (info->rects == NULL) {
+				DRM_SPINUNLOCK(&dev->drw_lock);
 				return ENOMEM;
+			}
 			info->num_rects = update->num;
 		}
 		/* For some reason the pointer arg is unsigned long long. */
@@ -159,3 +155,21 @@
 		return EINVAL;
 	}
 }
+
+void drm_drawable_free_all(struct drm_device *dev)
+{
+	struct bsd_drm_drawable_info *info, *next;
+
+	DRM_SPINLOCK(&dev->drw_lock);
+	for (info = RB_MIN(drawable_tree, &dev->drw_head);
+	    info != NULL ; info = next) {
+		next = RB_NEXT(drawable_tree, &dev->drw_head, info);
+		RB_REMOVE(drawable_tree, &dev->drw_head,
+		    (struct bsd_drm_drawable_info *)info);
+		DRM_SPINUNLOCK(&dev->drw_lock);
+		free(info->info.rects, DRM_MEM_DRAWABLE);
+		free(info, DRM_MEM_DRAWABLE);
+		DRM_SPINLOCK(&dev->drw_lock);
+	}
+	DRM_SPINUNLOCK(&dev->drw_lock);
+}
diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c
--- a/sys/dev/drm/drm_drv.c
+++ b/sys/dev/drm/drm_drv.c
@@ -34,11 +34,8 @@
  * open/close, and ioctl dispatch.
  */
 
-#ifdef __DragonFly__
+
 #include <machine/limits.h>
-#else
-#include <sys/limits.h>
-#endif
 #include "drmP.h"
 #include "drm.h"
 #include "drm_sarea.h"
@@ -49,27 +46,18 @@
 int drm_debug_flag = 0;
 #endif
 
-static int drm_load(drm_device_t *dev);
-static void drm_unload(drm_device_t *dev);
+static int drm_load(struct drm_device *dev);
+static void drm_unload(struct drm_device *dev);
 static drm_pci_id_list_t *drm_find_description(int vendor, int device,
     drm_pci_id_list_t *idlist);
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 #define DRIVER_SOFTC(unit) \
-	((drm_device_t *)devclass_get_softc(drm_devclass, unit))
+	((struct drm_device *)devclass_get_softc(drm_devclass, unit))
 
 MODULE_VERSION(drm, 1);
 MODULE_DEPEND(drm, agp, 1, 1, 1);
 MODULE_DEPEND(drm, pci, 1, 1, 1);
-#if __FreeBSD_version > 502127
 MODULE_DEPEND(drm, mem, 1, 1, 1);
-#endif
-#endif /* __FreeBSD__ || __DragonFly__ */
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-#define DRIVER_SOFTC(unit) \
-	((drm_device_t *)device_lookup(&drm_cd, unit))
-#endif /* __NetBSD__ || __OpenBSD__ */
 
 static drm_ioctl_desc_t		  drm_ioctls[256] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
@@ -129,33 +117,10 @@
 	DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 };
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
-#ifdef __FreeBSD__
-static struct cdevsw drm_cdevsw = {
-#if __FreeBSD_version >= 502103
-	.d_version =	D_VERSION,
-#endif
-	.d_open =	drm_open,
-	.d_close =	drm_close,
-	.d_read =	drm_read,
-	.d_ioctl =	drm_ioctl,
-	.d_poll =	drm_poll,
-	.d_mmap =	drm_mmap,
-	.d_name =	"drm",
-#if __FreeBSD_version >= 502103
-	.d_flags =	D_TRACKCLOSE | D_NEEDGIANT,
-#else
-	.d_maj =	145,
-	.d_flags =	D_TRACKCLOSE,
-#endif
-#if __FreeBSD_version < 500000
-	.d_bmaj =	-1
-#endif
-};
-#else	/* __FreeBSD__ */
 static struct dev_ops drm_cdevsw = {
 	{ "drm", 145, D_TRACKCLOSE },
 	.d_open =	drm_open,
@@ -165,13 +130,11 @@
 	.d_poll =	drm_poll,
 	.d_mmap =	drm_mmap
 };
-#endif	/* !__FreeBSD__ */
 
 int drm_probe(device_t dev, drm_pci_id_list_t *idlist)
 {
 	drm_pci_id_list_t *id_entry;
 	int vendor, device;
-#if __FreeBSD_version < 700010
 	device_t realdev;
 
 	if (!strcmp(device_get_name(dev), "drmsub"))
@@ -180,10 +143,6 @@
 		realdev = dev;
 	vendor = pci_get_vendor(realdev);
 	device = pci_get_device(realdev);
-#else
-	vendor = pci_get_vendor(dev);
-	device = pci_get_device(dev);
-#endif
 
 	id_entry = drm_find_description(vendor, device, idlist);
 	if (id_entry != NULL) {
@@ -196,37 +155,31 @@
 
 int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist)
 {
-	drm_device_t *dev;
+	struct drm_device *dev;
 	drm_pci_id_list_t *id_entry;
 	int unit;
 
 	unit = device_get_unit(nbdev);
 	dev = device_get_softc(nbdev);
 
-#if __FreeBSD_version < 700010
 	if (!strcmp(device_get_name(nbdev), "drmsub"))
 		dev->device = device_get_parent(nbdev);
 	else
 		dev->device = nbdev;
-#else
-	dev->device = nbdev;
-#endif
-#ifdef __DragonFly__
+
 	dev_ops_add(&drm_cdevsw, -1, unit);
-#endif
 	dev->devnode = make_dev(&drm_cdevsw,
 			unit,
 			DRM_DEV_UID,
 			DRM_DEV_GID,
 			DRM_DEV_MODE,
 			"dri/card%d", unit);
-#if __FreeBSD_version >= 500000
-	mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF);
-	mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF);
-#elif defined(__DragonFly__)
-	DRM_SPININIT(&dev->dev_lock, "drm device");
+
+	DRM_SPININIT(&dev->dev_lock, "drmdev");
+	lwkt_serialize_init(&dev->irq_lock);
+	DRM_SPININIT(&dev->vbl_lock, "drmvbl");
 	DRM_SPININIT(&dev->drw_lock, "drmdrw");
-#endif
+	DRM_SPININIT(&dev->tsk_lock, "drmtsk");
 
 	id_entry = drm_find_description(pci_get_vendor(dev->device),
 	    pci_get_device(dev->device), idlist);
@@ -247,146 +200,6 @@
 
 devclass_t drm_devclass;
 
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-
-static struct cdevsw drm_cdevsw = {
-	drm_open,
-	drm_close,
-	drm_read,
-	nowrite,
-	drm_ioctl,
-	nostop,
-	notty,
-	drm_poll,
-	drm_mmap,
-	nokqfilter,
-	D_TTY
-};
-
-int drm_refcnt = 0;
-
-#if defined(__NetBSD__) && __NetBSD_Version__ >= 106080000
-MOD_DEV("drm", DRIVER_NAME, NULL, -1, &drm_cdevsw, CDEV_MAJOR);
-#else
-MOD_DEV("drm", LM_DT_CHAR, CDEV_MAJOR, &drm_cdevsw);
-#endif
-
-int drm_lkmentry(struct lkm_table *lkmtp, int cmd, int ver);
-static int drm_lkmhandle(struct lkm_table *lkmtp, int cmd);
-
-int drm_modprobe(void);
-int drm_probe(struct pci_attach_args *pa);
-void drm_attach(struct pci_attach_args *pa, dev_t kdev);
-
-int drm_lkmentry(struct lkm_table *lkmtp, int cmd, int ver) {
-	DISPATCH(lkmtp, cmd, ver, drm_lkmhandle, drm_lkmhandle, drm_lkmhandle);
-}
-
-static int drm_lkmhandle(struct lkm_table *lkmtp, int cmd)
-{
-	int error = 0;
-
-	switch(cmd) {
-	case LKM_E_LOAD:
-		if (lkmexists(lkmtp))
-			return EEXIST;
-
-		if(drm_modprobe())
-			return 0;
-
-		return 1;
-
-	case LKM_E_UNLOAD:
-		if (drm_refcnt > 0)
-			return (EBUSY);
-		break;
-	case LKM_E_STAT:
-		break;
-
-	default:
-		error = EIO;
-		break;
-	}
-	
-	return error;
-}
-
-int drm_modprobe(void)
-{
-	struct pci_attach_args pa;
-	int error;
-
-	error = pci_find_device(&pa, drm_probe, idlist);
-	if (error != 0)
-		drm_attach(&pa, 0);
-
-	return error;
-}
-
-int drm_probe(struct pci_attach_args *pa, drm_pci_id_list_t idlist)
-{
-	const char *desc;
-	drm_pci_id_list_t *id_entry;
-
-	id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
-	    PCI_PRODUCT(pa->pa_id), idlist);
-	if (id_entry != NULL) {
-		return 1;
-	}
-
-	return 0;
-}
-
-void drm_attach(struct pci_attach_args *pa, dev_t kdev, 
-    drm_pci_id_list_t *idlist)
-{
-	int i;
-	drm_device_t *dev;
-	drm_pci_id_list_t *id_entry;
-
-	config_makeroom(kdev, &drm_cd);
-	drm_cd.cd_devs[(kdev)] = malloc(sizeof(drm_device_t), M_DRM, M_WAITOK);
-	dev = DRIVER_SOFTC(kdev);
-
-	memset(dev, 0, sizeof(drm_device_t));
-	memcpy(&dev->pa, pa, sizeof(dev->pa));
-
-	dev->irq = pa->pa_intrline;
-	dev->pci_domain = 0;
-	dev->pci_bus = pa->pa_bus;
-	dev->pci_slot = pa->pa_device;
-	dev->pci_func = pa->pa_function;
-	dev->dma_tag = pa->pa_dmat;
-
-	id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
-	    PCI_PRODUCT(pa->pa_id), idlist);
-	dev->driver.pci_id_entry = id_entry;
-
-	DRM_INFO("%s", id_entry->name);
-	drm_load(dev);
-}
-
-int drm_detach(struct device *self, int flags)
-{
-	drm_unload((drm_device_t *)self);
-	return 0;
-}
-
-int drm_activate(struct device *self, enum devact act)
-{
-	switch (act) {
-	case DVACT_ACTIVATE:
-		return (EOPNOTSUPP);
-		break;
-
-	case DVACT_DEACTIVATE:
-		/* FIXME */
-		break;
-	}
-	return (0);
-}
-#endif /* __NetBSD__ || __OpenBSD__ */
-
 drm_pci_id_list_t *drm_find_description(int vendor, int device,
     drm_pci_id_list_t *idlist)
 {
@@ -401,7 +214,7 @@
 	return NULL;
 }
 
-static int drm_firstopen(drm_device_t *dev)
+static int drm_firstopen(struct drm_device *dev)
 {
 	drm_local_map_t *map;
 	int i;
@@ -410,22 +223,22 @@
 
 	/* prebuild the SAREA */
 	i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
-		       _DRM_CONTAINS_LOCK, &map);
+	    _DRM_CONTAINS_LOCK, &map);
 	if (i != 0)
 		return i;
 
-	if (dev->driver.firstopen)
-		dev->driver.firstopen(dev);
+	if (dev->driver->firstopen)
+		dev->driver->firstopen(dev);
 
 	dev->buf_use = 0;
 
-	if (dev->driver.use_dma) {
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
 		i = drm_dma_setup(dev);
 		if (i != 0)
 			return i;
 	}
 
-	for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
+	for (i = 0; i < DRM_HASH_SIZE; i++) {
 		dev->magiclist[i].head = NULL;
 		dev->magiclist[i].tail = NULL;
 	}
@@ -436,18 +249,14 @@
 	dev->last_context = 0;
 	dev->if_version = 0;
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	dev->buf_sigio = NULL;
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	dev->buf_pgid = 0;
-#endif
 
-	DRM_DEBUG( "\n" );
+	DRM_DEBUG("\n");
 
 	return 0;
 }
 
-static int drm_lastclose(drm_device_t *dev)
+static int drm_lastclose(struct drm_device *dev)
 {
 	drm_magic_entry_t *pt, *next;
 	drm_local_map_t *map, *mapsave;
@@ -455,42 +264,46 @@
 
 	DRM_SPINLOCK_ASSERT(&dev->dev_lock);
 
-	DRM_DEBUG( "\n" );
+	DRM_DEBUG("\n");
 
-	if (dev->driver.lastclose != NULL)
-		dev->driver.lastclose(dev);
+	if (dev->driver->lastclose != NULL)
+		dev->driver->lastclose(dev);
 
 	if (dev->irq_enabled)
 		drm_irq_uninstall(dev);
 
-	if ( dev->unique ) {
-		free(dev->unique, M_DRM);
+	if (dev->unique) {
+		free(dev->unique, 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 ) {
+	/* Clear pid list */
+	for (i = 0; i < DRM_HASH_SIZE; i++) {
+		for (pt = dev->magiclist[i].head; pt; pt = next) {
 			next = pt->next;
-			free(pt, M_DRM);
+			free(pt, DRM_MEM_MAGIC);
 		}
 		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
 	}
 
-				/* Clear AGP information */
-	if ( dev->agp ) {
+	DRM_UNLOCK();
+	drm_drawable_free_all(dev);
+	DRM_LOCK();
+
+	/* 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
 		 * drm_unload is called.
 		 */
-		for ( entry = dev->agp->memory ; entry ; entry = nexte ) {
+		for (entry = dev->agp->memory; entry; entry = nexte) {
 			nexte = entry->next;
-			if ( entry->bound )
+			if (entry->bound)
 				drm_agp_unbind_memory(entry->handle);
 			drm_agp_free_memory(entry->handle);
-			free(entry, M_DRM);
+			free(entry, DRM_MEM_AGPLISTS);
 		}
 		dev->agp->memory = NULL;
 
@@ -511,7 +324,7 @@
 	}
 
 	drm_dma_takedown(dev);
-	if ( dev->lock.hw_lock ) {
+	if (dev->lock.hw_lock) {
 		dev->lock.hw_lock = NULL; /* SHM removed */
 		dev->lock.file_priv = NULL;
 		DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
@@ -520,18 +333,14 @@
 	return 0;
 }
 
-static int drm_load(drm_device_t *dev)
+static int drm_load(struct drm_device *dev)
 {
 	int i, retcode;
 
-	DRM_DEBUG( "\n" );
+	DRM_DEBUG("\n");
 
 	dev->irq = pci_get_irq(dev->device);
-#if defined(__FreeBSD__) && __FreeBSD_version >= 700053
-	dev->pci_domain = pci_get_domain(dev->device);
-#else
 	dev->pci_domain = 0;
-#endif
 	dev->pci_bus = pci_get_bus(dev->device);
 	dev->pci_slot = pci_get_slot(dev->device);
 	dev->pci_func = pci_get_function(dev->device);
@@ -542,9 +351,7 @@
 	TAILQ_INIT(&dev->maplist);
 
 	drm_mem_init();
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	drm_sysctl_init(dev);
-#endif
 	TAILQ_INIT(&dev->files);
 
 	dev->counters  = 6;
@@ -555,23 +362,25 @@
 	dev->types[4]  = _DRM_STAT_LOCKS;
 	dev->types[5]  = _DRM_STAT_UNLOCKS;
 
-	for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
-		atomic_set( &dev->counts[i], 0 );
+	for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
+		atomic_set(&dev->counts[i], 0);
 
-	if (dev->driver.load != NULL) {
+	if (dev->driver->load != NULL) {
 		DRM_LOCK();
 		/* Shared code returns -errno. */
-		retcode = -dev->driver.load(dev,
+		retcode = -dev->driver->load(dev,
 		    dev->id_entry->driver_private);
+		pci_enable_busmaster(dev->device);
 		DRM_UNLOCK();
 		if (retcode != 0)
 			goto error;
 	}
 
-	if (dev->driver.use_agp) {
+	if (drm_core_has_AGP(dev)) {
 		if (drm_device_is_agp(dev))
 			dev->agp = drm_agp_init();
-		if (dev->driver.require_agp && dev->agp == NULL) {
+		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) &&
+		    dev->agp == NULL) {
 			DRM_ERROR("Card isn't AGP, or couldn't initialize "
 			    "AGP.\n");
 			retcode = ENOMEM;
@@ -590,51 +399,38 @@
 		goto error;
 	}
 
-#ifdef __FreeBSD__
-	dev->drw_unrhdr = new_unrhdr(1, INT_MAX, NULL);
-	if (dev->drw_unrhdr == NULL) {
-		DRM_ERROR("Couldn't allocate drawable number allocator\n");
-		goto error;
-	}
-#endif
-
 	DRM_INFO("Initialized %s %d.%d.%d %s\n",
-	  	dev->driver.name,
-	  	dev->driver.major,
-	  	dev->driver.minor,
-	  	dev->driver.patchlevel,
-	  	dev->driver.date);
+	    dev->driver->name,
+	    dev->driver->major,
+	    dev->driver->minor,
+	    dev->driver->patchlevel,
+	    dev->driver->date);
 
 	return 0;
 
 error:
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	drm_sysctl_cleanup(dev);
-#endif
 	DRM_LOCK();
 	drm_lastclose(dev);
 	DRM_UNLOCK();
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	destroy_dev(dev->devnode);
-#if __FreeBSD_version >= 500000
-	mtx_destroy(&dev->dev_lock);
-#elif defined(__DragonFly__)
+
+	DRM_SPINUNINIT(&dev->tsk_lock);
+	DRM_SPINUNINIT(&dev->drw_lock);
+	DRM_SPINUNINIT(&dev->vbl_lock);
 	DRM_SPINUNINIT(&dev->dev_lock);
-#endif
-#endif
+
 	return retcode;
 }
 
-static void drm_unload(drm_device_t *dev)
+static void drm_unload(struct drm_device *dev)
 {
 	int i;
 
-	DRM_DEBUG( "\n" );
+	DRM_DEBUG("\n");
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	drm_sysctl_cleanup(dev);
 	destroy_dev(dev->devnode);
-#endif
 
 	drm_ctxbitmap_cleanup(dev);
 
@@ -663,30 +459,30 @@
 		dev->pcir[i] = NULL;
 	}
 
-	if ( dev->agp ) {
-		free(dev->agp, M_DRM);
+	if (dev->agp) {
+		free(dev->agp, DRM_MEM_AGPLISTS);
 		dev->agp = NULL;
 	}
 
-	if (dev->driver.unload != NULL)
-		dev->driver.unload(dev);
-
-#ifdef __FreeBSD__
-	delete_unrhdr(dev->drw_unrhdr);
-#endif
+	if (dev->driver->unload != NULL) {
+		DRM_LOCK();
+		dev->driver->unload(dev);
+		DRM_UNLOCK();
+	}
 
 	drm_mem_uninit();
-#if defined(__FreeBSD__) &&  __FreeBSD_version >= 500000
-	mtx_destroy(&dev->dev_lock);
-#elif defined(__DragonFly__)
+	pci_disable_busmaster(dev->device);
+
+	DRM_SPINUNINIT(&dev->tsk_lock);
+	DRM_SPINUNINIT(&dev->drw_lock);
+	DRM_SPINUNINIT(&dev->vbl_lock);
 	DRM_SPINUNINIT(&dev->dev_lock);
-#endif
 }
 
 
-int drm_version(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_version_t *version = data;
+	struct drm_version *version = data;
 	int len;
 
 #define DRM_COPY( name, value )						\
@@ -698,44 +494,37 @@
 			return EFAULT;				\
 	}
 
-	version->version_major		= dev->driver.major;
-	version->version_minor		= dev->driver.minor;
-	version->version_patchlevel	= dev->driver.patchlevel;
+	version->version_major		= dev->driver->major;
+	version->version_minor		= dev->driver->minor;
+	version->version_patchlevel	= dev->driver->patchlevel;
 
-	DRM_COPY(version->name, dev->driver.name);
-	DRM_COPY(version->date, dev->driver.date);
-	DRM_COPY(version->desc, dev->driver.desc);
+	DRM_COPY(version->name, dev->driver->name);
+	DRM_COPY(version->date, dev->driver->date);
+	DRM_COPY(version->desc, dev->driver->desc);
 
 	return 0;
 }
 
-#ifndef __DragonFly__
-int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
-{
-#else
 int drm_open(struct dev_open_args *ap)
 {
 	struct cdev *kdev = ap->a_head.a_dev;
 	int flags = ap->a_oflags;
 	int fmt = 0;
 	struct thread *p = curthread;
-#endif
-	drm_device_t *dev = NULL;
+	struct drm_device *dev = NULL;
 	int retcode = 0;
 
-	dev = DRIVER_SOFTC(minor(kdev));
+	dev = DRIVER_SOFTC(dev2unit(kdev));
 
-	DRM_DEBUG( "open_count = %d\n", dev->open_count );
+	DRM_DEBUG("open_count = %d\n", dev->open_count);
 
 	retcode = drm_open_helper(kdev, flags, fmt, p, dev);
 
-	if ( !retcode ) {
-		atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
+	if (!retcode) {
+		atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
 		DRM_LOCK();
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 		device_busy(dev->device);
-#endif
-		if ( !dev->open_count++ )
+		if (!dev->open_count++)
 			retcode = drm_firstopen(dev);
 		DRM_UNLOCK();
 	}
@@ -743,25 +532,20 @@
 	return retcode;
 }
 
-#ifndef __DragonFly__
-int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
-{
-#else
 int drm_close(struct dev_close_args *ap)
 {
 	struct cdev *kdev = ap->a_head.a_dev;
 	struct thread *p = curthread;
-#endif
-	drm_device_t *dev = drm_get_device_from_kdev(kdev);
-	drm_file_t *file_priv;
+	struct drm_device *dev = drm_get_device_from_kdev(kdev);
+	struct drm_file *file_priv;
 	int retcode = 0;
 
-	DRM_DEBUG( "open_count = %d\n", dev->open_count );
+	DRM_DEBUG("open_count = %d\n", dev->open_count);
 
 	DRM_LOCK();
 
 	file_priv = drm_find_file_by_proc(dev, p);
-	if (!file_priv) {
+	if (file_priv == NULL) {
 		DRM_UNLOCK();
 		DRM_ERROR("can't find authenticator\n");
 		return EINVAL;
@@ -770,57 +554,47 @@
 	if (--file_priv->refs != 0)
 		goto done;
 
-	if (dev->driver.preclose != NULL)
-		dev->driver.preclose(dev, file_priv);
+	if (dev->driver->preclose != NULL)
+		dev->driver->preclose(dev, file_priv);
 
 	/* ========================================================
 	 * Begin inline drm_release
 	 */
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
-	DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
-		   DRM_CURRENTPID, (long)dev->device, dev->open_count );
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
-		   DRM_CURRENTPID, (long)&dev->device, dev->open_count);
-#endif
+	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+	    DRM_CURRENTPID, (long)dev->device, dev->open_count);
 
 	if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
 	    && dev->lock.file_priv == file_priv) {
 		DRM_DEBUG("Process %d dead, freeing lock for context %d\n",
 			  DRM_CURRENTPID,
 			  _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-		if (dev->driver.reclaim_buffers_locked != NULL)
-			dev->driver.reclaim_buffers_locked(dev, file_priv);
+		if (dev->driver->reclaim_buffers_locked != NULL)
+			dev->driver->reclaim_buffers_locked(dev, file_priv);
 
-		drm_lock_free(dev, &dev->lock.hw_lock->lock,
+		drm_lock_free(&dev->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->driver.reclaim_buffers_locked != NULL &&
+	} else if (dev->driver->reclaim_buffers_locked != NULL &&
 	    dev->lock.hw_lock != NULL) {
 		/* The lock is required to reclaim buffers */
 		for (;;) {
-			if ( !dev->lock.hw_lock ) {
+			if (!dev->lock.hw_lock) {
 				/* Device has been unregistered */
 				retcode = EINTR;
 				break;
 			}
-			if (drm_lock_take(&dev->lock.hw_lock->lock,
-			    DRM_KERNEL_CONTEXT)) {
+			if (drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) {
 				dev->lock.file_priv = file_priv;
 				dev->lock.lock_time = jiffies;
-                                atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
+				atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
 				break;	/* Got lock */
 			}
-				/* Contention */
-#if defined(__FreeBSD__) && __FreeBSD_version > 500000
-			retcode = mtx_sleep((void *)&dev->lock.lock_queue,
-			    &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0);
-#elif defined(__DragonFly__)
+			/* Contention */
 			crit_enter();
 			tsleep_interlock((void *)&dev->lock.lock_queue);
 			DRM_UNLOCK();
@@ -828,75 +602,57 @@
 			    PCATCH, "drmlk2", 0);
 			crit_exit();
 			DRM_LOCK();
-#else
-			retcode = tsleep((void *)&dev->lock.lock_queue,
-			    PZERO | PCATCH, "drmlk2", 0);
-#endif
 			if (retcode)
 				break;
 		}
 		if (retcode == 0) {
-			dev->driver.reclaim_buffers_locked(dev, file_priv);
-			drm_lock_free(dev, &dev->lock.hw_lock->lock,
-			    DRM_KERNEL_CONTEXT);
+			dev->driver->reclaim_buffers_locked(dev, file_priv);
+			drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
 		}
 	}
 
-	if (dev->driver.use_dma && !dev->driver.reclaim_buffers_locked)
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
+	    !dev->driver->reclaim_buffers_locked)
 		drm_reclaim_buffers(dev, file_priv);
 
-#if defined (__FreeBSD__) && (__FreeBSD_version >= 500000)
-	funsetown(&dev->buf_sigio);
-#elif defined(__FreeBSD__) || defined(__DragonFly__)
 	funsetown(dev->buf_sigio);
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	dev->buf_pgid = 0;
-#endif /* __NetBSD__  || __OpenBSD__ */
 
-	if (dev->driver.postclose != NULL)
-		dev->driver.postclose(dev, file_priv);
+	if (dev->driver->postclose != NULL)
+		dev->driver->postclose(dev, file_priv);
 	TAILQ_REMOVE(&dev->files, file_priv, link);
-	free(file_priv, M_DRM);
+	free(file_priv, DRM_MEM_FILES);
 
 	/* ========================================================
 	 * End inline drm_release
 	 */
 
 done:
-	atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+	atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
 	device_unbusy(dev->device);
-#endif
 	if (--dev->open_count == 0) {
 		retcode = drm_lastclose(dev);
 	}
 
 	DRM_UNLOCK();
-	
+
 	return retcode;
 }
 
 /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm.
  */
-#ifndef __DragonFly__
-int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags, 
-    DRM_STRUCTPROC *p)
-{
-#else
 int drm_ioctl(struct dev_ioctl_args *ap)
 {
 	struct cdev *kdev = ap->a_head.a_dev;
 	u_long cmd = ap->a_cmd;
 	caddr_t data = ap->a_data;
 	struct thread *p = curthread;
-#endif
-	drm_device_t *dev = drm_get_device_from_kdev(kdev);
+	struct drm_device *dev = drm_get_device_from_kdev(kdev);
 	int retcode = 0;
 	drm_ioctl_desc_t *ioctl;
-	int (*func)(drm_device_t *dev, void *data, struct drm_file *file_priv);
+	int (*func)(struct drm_device *dev, void *data, struct drm_file *file_priv);
 	int nr = DRM_IOCTL_NR(cmd);
 	int is_driver_ioctl = 0;
-	drm_file_t *file_priv;
+	struct drm_file *file_priv;
 
 	DRM_LOCK();
 	file_priv = drm_find_file_by_proc(dev, p);
@@ -906,45 +662,24 @@
 		return EINVAL;
 	}
 
-	atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
+	atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
 	++file_priv->ioctl_count;
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
-	DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
+	DRM_DEBUG("pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
 	    DRM_CURRENTPID, cmd, nr, (long)dev->device,
-	    file_priv->authenticated );
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	DRM_DEBUG( "pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n",
-	    DRM_CURRENTPID, cmd, nr, (long)&dev->device,
-	    file_priv->authenticated );
-#endif
+	    file_priv->authenticated);
 
 	switch (cmd) {
 	case FIONBIO:
 	case FIOASYNC:
 		return 0;
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	case FIOSETOWN:
 		return fsetown(*(int *)data, &dev->buf_sigio);
 
 	case FIOGETOWN:
-#if (__FreeBSD_version >= 500000)
-		*(int *) data = fgetown(&dev->buf_sigio);
-#else
 		*(int *) data = fgetown(dev->buf_sigio);
-#endif
 		return 0;
-#endif /* __FreeBSD__ || __DragonFly__ */
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-	case TIOCSPGRP:
-		dev->buf_pgid = *(int *)data;
-		return 0;
-
-	case TIOCGPGRP:
-		*(int *)data = dev->buf_pgid;
-		return 0;
-#endif /* __NetBSD__ */
 	}
 
 	if (IOCGROUP(cmd) != DRM_IOCTL_BASE) {
@@ -957,18 +692,18 @@
 	if (ioctl->func == NULL && nr >= DRM_COMMAND_BASE) {
 		/* The array entries begin at DRM_COMMAND_BASE ioctl nr */
 		nr -= DRM_COMMAND_BASE;
-		if (nr > dev->driver.max_ioctl) {
+		if (nr > dev->driver->max_ioctl) {
 			DRM_DEBUG("Bad driver ioctl number, 0x%x (of 0x%x)\n",
-			    nr, dev->driver.max_ioctl);
+			    nr, dev->driver->max_ioctl);
 			return EINVAL;
 		}
-		ioctl = &dev->driver.ioctls[nr];
+		ioctl = &dev->driver->ioctls[nr];
 		is_driver_ioctl = 1;
 	}
 	func = ioctl->func;
 
 	if (func == NULL) {
-		DRM_DEBUG( "no function\n" );
+		DRM_DEBUG("no function\n");
 		return EINVAL;
 	}
 
@@ -992,7 +727,7 @@
 	return retcode;
 }
 
-drm_local_map_t *drm_getsarea(drm_device_t *dev)
+drm_local_map_t *drm_getsarea(struct drm_device *dev)
 {
 	drm_local_map_t *map;
 
diff --git a/sys/dev/drm/drm_fops.c b/sys/dev/drm/drm_fops.c
--- a/sys/dev/drm/drm_fops.c
+++ b/sys/dev/drm/drm_fops.c
@@ -37,34 +37,27 @@
 
 #include "drmP.h"
 
-drm_file_t *drm_find_file_by_proc(drm_device_t *dev, DRM_STRUCTPROC *p)
+struct drm_file *drm_find_file_by_proc(struct drm_device *dev, DRM_STRUCTPROC *p)
 {
-#if __FreeBSD_version >= 500021
-	uid_t uid = p->td_ucred->cr_svuid;
-	pid_t pid = p->td_proc->p_pid;
-#elif defined(__DragonFly__)
-	uid_t uid = p->td_proc->p_ucred->cr_svuid;
-	pid_t pid = p->td_proc->p_pid;
-#else
-	uid_t uid = p->p_cred->p_svuid;
-	pid_t pid = p->p_pid;
-#endif
-	drm_file_t *priv;
+	struct drm_file *priv;
 
-	DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+        uid_t uid = p->td_proc->p_ucred->cr_svuid;
+        pid_t pid = p->td_proc->p_pid;
 
-	TAILQ_FOREACH(priv, &dev->files, link)
-		if (priv->pid == pid && priv->uid == uid)
-			return priv;
-	return NULL;
+        DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+
+        TAILQ_FOREACH(priv, &dev->files, link)
+                if (priv->pid == pid && priv->uid == uid)
+                        return priv;
+        return NULL;
 }
 
 /* drm_open_helper is called whenever a process opens /dev/drm. */
 int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
-		    drm_device_t *dev)
+		    struct drm_device *dev)
 {
-	int	     m = minor(kdev);
-	drm_file_t   *priv;
+	struct drm_file *priv;
+	int m = dev2unit(kdev);
 	int retcode;
 
 	if (flags & O_EXCL)
@@ -78,34 +71,25 @@
 	if (priv) {
 		priv->refs++;
 	} else {
-		priv = malloc(sizeof(*priv), M_DRM, M_NOWAIT | M_ZERO);
+		priv = malloc(sizeof(*priv), DRM_MEM_FILES, M_NOWAIT | M_ZERO);
 		if (priv == NULL) {
 			DRM_UNLOCK();
 			return ENOMEM;
 		}
-#if __FreeBSD_version >= 500000
-		priv->uid		= p->td_ucred->cr_svuid;
-		priv->pid		= p->td_proc->p_pid;
-#elif defined(__DragonFly__)
 		priv->uid		= p->td_proc->p_ucred->cr_svuid;
 		priv->pid		= p->td_proc->p_pid;
-#else
-		priv->uid		= p->p_cred->p_svuid;
-		priv->pid		= p->p_pid;
-#endif
-
 		priv->refs		= 1;
 		priv->minor		= m;
-		priv->ioctl_count 	= 0;
+		priv->ioctl_count	= 0;
 
 		/* for compatibility root is always authenticated */
 		priv->authenticated	= DRM_SUSER(p);
 
-		if (dev->driver.open) {
+		if (dev->driver->open) {
 			/* shared code returns -errno */
-			retcode = -dev->driver.open(dev, priv);
+			retcode = -dev->driver->open(dev, priv);
 			if (retcode != 0) {
-				free(priv, M_DRM);
+				free(priv, DRM_MEM_FILES);
 				DRM_UNLOCK();
 				return retcode;
 			}
@@ -117,9 +101,7 @@
 		TAILQ_INSERT_TAIL(&dev->files, priv, link);
 	}
 	DRM_UNLOCK();
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	kdev->si_drv1 = dev;
-#endif
 	return 0;
 }
 
@@ -127,24 +109,12 @@
 /* The drm_read and drm_poll are stubs to prevent spurious errors
  * on older X Servers (4.3.0 and earlier) */
 
-#ifdef __DragonFly__
 int drm_read(struct dev_read_args *ap)
 {
-	return (0);
+	return 0;
 }
 
 int drm_poll(struct dev_poll_args *ap)
 {
-	return (0);
-}
-#else
-int drm_read(struct cdev *kdev, struct uio *uio, int ioflag)
-{
 	return 0;
 }
-
-int drm_poll(struct cdev *kdev, int events, DRM_STRUCTPROC *p)
-{
-	return 0;
-}
-#endif
diff --git a/sys/dev/drm/drm_ioctl.c b/sys/dev/drm/drm_ioctl.c
--- a/sys/dev/drm/drm_ioctl.c
+++ b/sys/dev/drm/drm_ioctl.c
@@ -42,9 +42,10 @@
  * before setunique has been called.  The format for the bus-specific part of
  * the unique is not defined for any other bus.
  */
-int drm_getunique(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_getunique(struct drm_device *dev, void *data,
+		  struct drm_file *file_priv)
 {
-	drm_unique_t	 *u = data;
+	struct drm_unique *u = data;
 
 	if (u->unique_len >= dev->unique_len) {
 		if (DRM_COPY_TO_USER(u->unique, dev->unique, dev->unique_len))
@@ -58,9 +59,10 @@
 /* Deprecated in DRM version 1.1, and will return EBUSY when setversion has
  * requested version 1.1 or greater.
  */
-int drm_setunique(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_setunique(struct drm_device *dev, void *data,
+		  struct drm_file *file_priv)
 {
-	drm_unique_t *u = data;
+	struct drm_unique *u = data;
 	int domain, bus, slot, func, ret;
 	char *busid;
 
@@ -68,12 +70,12 @@
 	if (!u->unique_len || u->unique_len > 1024)
 		return EINVAL;
 
-	busid = malloc(u->unique_len + 1, M_DRM, M_WAITOK);
+	busid = malloc(u->unique_len + 1, DRM_MEM_DRIVER, M_WAITOK);
 	if (busid == NULL)
 		return ENOMEM;
 
 	if (DRM_COPY_FROM_USER(busid, u->unique, u->unique_len)) {
-		free(busid, M_DRM);
+		free(busid, DRM_MEM_DRIVER);
 		return EFAULT;
 	}
 	busid[u->unique_len] = '\0';
@@ -83,7 +85,7 @@
 	 */
 	ret = sscanf(busid, "PCI:%d:%d:%d", &bus, &slot, &func);
 	if (ret != 3) {
-		free(busid, M_DRM);
+		free(busid, DRM_MEM_DRIVER);
 		return EINVAL;
 	}
 	domain = bus >> 8;
@@ -93,7 +95,7 @@
 	    (bus != dev->pci_bus) ||
 	    (slot != dev->pci_slot) ||
 	    (func != dev->pci_func)) {
-		free(busid, M_DRM);
+		free(busid, DRM_MEM_DRIVER);
 		return EINVAL;
 	}
 
@@ -113,7 +115,7 @@
 
 
 static int
-drm_set_busid(drm_device_t *dev)
+drm_set_busid(struct drm_device *dev)
 {
 
 	DRM_LOCK();
@@ -124,7 +126,7 @@
 	}
 
 	dev->unique_len = 20;
-	dev->unique = malloc(dev->unique_len + 1, M_DRM, M_NOWAIT);
+	dev->unique = malloc(dev->unique_len + 1, DRM_MEM_DRIVER, M_NOWAIT);
 	if (dev->unique == NULL) {
 		DRM_UNLOCK();
 		return ENOMEM;
@@ -138,9 +140,9 @@
 	return 0;
 }
 
-int drm_getmap(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_getmap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_map_t    *map = data;
+	struct drm_map     *map = data;
 	drm_local_map_t    *mapinlist;
 	int          idx;
 	int	     i = 0;
@@ -154,7 +156,7 @@
 	}
 
 	TAILQ_FOREACH(mapinlist, &dev->maplist, link) {
-		if (i==idx) {
+		if (i == idx) {
 			map->offset = mapinlist->offset;
 			map->size   = mapinlist->size;
 			map->type   = mapinlist->type;
@@ -174,18 +176,18 @@
 	return 0;
 }
 
-int drm_getclient(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_getclient(struct drm_device *dev, void *data,
+		  struct drm_file *file_priv)
 {
-	drm_client_t *client = data;
-	drm_file_t   *pt;
-	int          idx;
-	int          i = 0;
+	struct drm_client *client = data;
+	struct drm_file *pt;
+	int idx;
+	int i = 0;
 
 	idx = client->idx;
 	DRM_LOCK();
 	TAILQ_FOREACH(pt, &dev->files, link) {
-		if (i==idx)
-		{
+		if (i == idx) {
 			client->auth  = pt->authenticated;
 			client->pid   = pt->pid;
 			client->uid   = pt->uid;
@@ -201,23 +203,22 @@
 	return EINVAL;
 }
 
-int drm_getstats(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_getstats(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_stats_t  *stats = data;
+	struct drm_stats *stats = data;
 	int          i;
 
-	memset(stats, 0, sizeof(drm_stats_t));
+	memset(stats, 0, sizeof(struct drm_stats));
 	
 	DRM_LOCK();
 
 	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);
+			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->data[i].type = dev->types[i];
 	}
 	
 	stats->count = dev->counters;
@@ -230,10 +231,11 @@
 #define DRM_IF_MAJOR	1
 #define DRM_IF_MINOR	2
 
-int drm_setversion(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_setversion(struct drm_device *dev, void *data,
+		   struct drm_file *file_priv)
 {
-	drm_set_version_t *sv = data;
-	drm_set_version_t ver;
+	struct drm_set_version *sv = data;
+	struct drm_set_version ver;
 	int if_version;
 
 	/* Save the incoming data, and set the response before continuing
@@ -242,8 +244,8 @@
 	ver = *sv;
 	sv->drm_di_major = DRM_IF_MAJOR;
 	sv->drm_di_minor = DRM_IF_MINOR;
-	sv->drm_dd_major = dev->driver.major;
-	sv->drm_dd_minor = dev->driver.minor;
+	sv->drm_dd_major = dev->driver->major;
+	sv->drm_dd_minor = dev->driver->minor;
 
 	if (ver.drm_di_major != -1) {
 		if (ver.drm_di_major != DRM_IF_MAJOR ||
@@ -262,9 +264,9 @@
 	}
 
 	if (ver.drm_dd_major != -1) {
-		if (ver.drm_dd_major != dev->driver.major ||
+		if (ver.drm_dd_major != dev->driver->major ||
 		    ver.drm_dd_minor < 0 ||
-		    ver.drm_dd_minor > dev->driver.minor)
+		    ver.drm_dd_minor > dev->driver->minor)
 		{
 			return EINVAL;
 		}
@@ -274,7 +276,7 @@
 }
 
 
-int drm_noop(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_noop(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	DRM_DEBUG("\n");
 	return 0;
diff --git a/sys/dev/drm/drm_irq.c b/sys/dev/drm/drm_irq.c
--- a/sys/dev/drm/drm_irq.c
+++ b/sys/dev/drm/drm_irq.c
@@ -36,9 +36,10 @@
 
 static void drm_locked_task(void *context, int pending __unused);
 
-int drm_irq_by_busid(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_irq_by_busid(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv)
 {
-	drm_irq_busid_t *irq = data;
+	struct drm_irq_busid *irq = data;
 
 	if ((irq->busnum >> 8) != dev->pci_domain ||
 	    (irq->busnum & 0xff) != dev->pci_bus ||
@@ -49,34 +50,105 @@
 	irq->irq = dev->irq;
 
 	DRM_DEBUG("%d:%d:%d => IRQ %d\n",
-		  irq->busnum, irq->devnum, irq->funcnum, irq->irq);
+	    irq->busnum, irq->devnum, irq->funcnum, irq->irq);
 
 	return 0;
 }
 
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
-static irqreturn_t
-drm_irq_handler_wrap(DRM_IRQ_ARGS)
+static void vblank_disable_fn(void *arg)
 {
-	drm_device_t *dev = (drm_device_t *)arg;
+	struct drm_device *dev = (struct drm_device *)arg;
+	int i;
 
-	DRM_SPINLOCK(&dev->irq_lock);
-	dev->driver.irq_handler(arg);
-	DRM_SPINUNLOCK(&dev->irq_lock);
+	DRM_SPINLOCK(&dev->vbl_lock);
+	if (callout_pending(&dev->vblank_disable_timer)) {
+		/* callout was reset */
+		DRM_SPINUNLOCK(&dev->vbl_lock);
+		return;
+	}
+	if (!callout_active(&dev->vblank_disable_timer)) {
+		/* callout was stopped */
+		DRM_SPINUNLOCK(&dev->vbl_lock);
+		return;
+	}
+	callout_deactivate(&dev->vblank_disable_timer);
+
+	DRM_DEBUG("vblank_disable_allowed=%d\n", dev->vblank_disable_allowed);
+	if (!dev->vblank_disable_allowed)
+		return;
+
+	for (i = 0; i < dev->num_crtcs; i++) {
+		if (atomic_read(&dev->vblank[i].refcount) == 0 &&
+		    dev->vblank[i].enabled) {
+			DRM_DEBUG("disabling vblank on crtc %d\n", i);
+			dev->vblank[i].last =
+			    dev->driver->get_vblank_counter(dev, i);
+			dev->driver->disable_vblank(dev, i);
+			dev->vblank[i].enabled = 0;
+		}
+	}
+	DRM_SPINUNLOCK(&dev->vbl_lock);
 }
-#endif
 
-int drm_irq_install(drm_device_t *dev)
+static void drm_vblank_cleanup(struct drm_device *dev)
+{
+	unsigned long irqflags;
+
+	/* Bail if the driver didn't call drm_vblank_init() */
+	if (dev->num_crtcs == 0)
+		return;
+
+	DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
+	callout_stop(&dev->vblank_disable_timer);
+	DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
+
+	vblank_disable_fn((void *)dev);
+
+	free(dev->vblank, DRM_MEM_DRIVER);
+
+	dev->num_crtcs = 0;
+}
+
+int drm_vblank_init(struct drm_device *dev, int num_crtcs)
+{
+	int i, ret = ENOMEM;
+
+	callout_init(&dev->vblank_disable_timer);
+	atomic_set(&dev->vbl_signal_pending, 0);
+	dev->num_crtcs = num_crtcs;
+
+	dev->vblank = malloc(sizeof(struct drm_vblank_info) * num_crtcs,
+	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
+	if (!dev->vblank)
+	    goto err;
+
+	DRM_DEBUG("\n");
+
+	/* Zero per-crtc vblank stuff */
+	for (i = 0; i < num_crtcs; i++) {
+		DRM_INIT_WAITQUEUE(&dev->vblank[i].queue);
+		TAILQ_INIT(&dev->vblank[i].sigs);
+		atomic_set(&dev->vblank[i].count, 0);
+		atomic_set(&dev->vblank[i].refcount, 0);
+	}
+
+	dev->vblank_disable_allowed = 0;
+
+	return 0;
+
+err:
+	drm_vblank_cleanup(dev);
+	return ret;
+}
+
+int drm_irq_install(struct drm_device *dev)
 {
 	int retcode;
-#ifdef __NetBSD__
-	pci_intr_handle_t ih;
-#endif
 
 	if (dev->irq == 0 || dev->dev_private == NULL)
 		return EINVAL;
 
-	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
+	DRM_DEBUG("irq=%d\n", dev->irq);
 
 	DRM_LOCK();
 	if (dev->irq_enabled) {
@@ -87,18 +159,11 @@
 
 	dev->context_flag = 0;
 
-#ifndef __DragonFly__
-	DRM_SPININIT(&dev->irq_lock, "DRM IRQ lock");
-#else
-	lwkt_serialize_init(&dev->irq_lock);
-#endif
-
-				/* Before installing handler */
-	dev->driver.irq_preinstall(dev);
+	/* Before installing handler */
+	dev->driver->irq_preinstall(dev);
 	DRM_UNLOCK();
 
-				/* Install handler */
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+	/* Install handler */
 	dev->irqrid = 0;
 	dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ, 
 				      &dev->irqrid, RF_SHAREABLE);
@@ -106,38 +171,16 @@
 		retcode = ENOENT;
 		goto err;
 	}
-#if __FreeBSD_version >= 700031
-	retcode = bus_setup_intr(dev->device, dev->irqr,
-				 INTR_TYPE_TTY | INTR_MPSAFE,
-				 NULL, drm_irq_handler_wrap, dev, &dev->irqh);
-#elif defined(__DragonFly__)
-	retcode = bus_setup_intr(dev->device, dev->irqr,
-				 INTR_MPSAFE,
-				 dev->driver.irq_handler, dev, &dev->irqh,
+	retcode = bus_setup_intr(dev->device, dev->irqr, INTR_MPSAFE,
+				 dev->driver->irq_handler, dev, &dev->irqh,
 				 &dev->irq_lock);
-#else
-	retcode = bus_setup_intr(dev->device, dev->irqr,
-				 INTR_TYPE_TTY | INTR_MPSAFE,
-				 drm_irq_handler_wrap, dev, &dev->irqh);
-#endif
+
 	if (retcode != 0)
 		goto err;
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	if (pci_intr_map(&dev->pa, &ih) != 0) {
-		retcode = ENOENT;
-		goto err;
-	}
-	dev->irqh = pci_intr_establish(&dev->pa.pa_pc, ih, IPL_TTY,
-	    (irqreturn_t (*)(void *))dev->irq_handler, dev);
-	if (!dev->irqh) {
-		retcode = ENOENT;
-		goto err;
-	}
-#endif
 
-				/* After installing handler */
+	/* After installing handler */
 	DRM_LOCK();
-	dev->driver.irq_postinstall(dev);
+	dev->driver->irq_postinstall(dev);
 	DRM_UNLOCK();
 
 	TASK_INIT(&dev->locked_task, 0, drm_locked_task, dev);
@@ -145,72 +188,58 @@
 err:
 	DRM_LOCK();
 	dev->irq_enabled = 0;
-#if defined(___FreeBSD__) || defined(__DragonFly__)
 	if (dev->irqrid != 0) {
 		bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid,
 		    dev->irqr);
 		dev->irqrid = 0;
 	}
-#endif
-#ifndef __DragonFly__
-	DRM_SPINUNINIT(&dev->irq_lock);
-#endif
 	DRM_UNLOCK();
 	return retcode;
 }
 
-int drm_irq_uninstall(drm_device_t *dev)
+int drm_irq_uninstall(struct drm_device *dev)
 {
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	int irqrid;
-#endif
 
 	if (!dev->irq_enabled)
 		return EINVAL;
 
 	dev->irq_enabled = 0;
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	irqrid = dev->irqrid;
 	dev->irqrid = 0;
-#endif
 
-	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
+	DRM_DEBUG("irq=%d\n", dev->irq);
 
-	dev->driver.irq_uninstall(dev);
+	dev->driver->irq_uninstall(dev);
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	DRM_UNLOCK();
 	bus_teardown_intr(dev->device, dev->irqr, dev->irqh);
 	bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr);
 	DRM_LOCK();
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh);
-#endif
-#ifndef __DragonFly__
-	DRM_SPINUNINIT(&dev->irq_lock);
-#endif
+
+	drm_vblank_cleanup(dev);
 
 	return 0;
 }
 
-int drm_control(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_control_t *ctl = data;
+	struct drm_control *ctl = data;
 	int err;
 
-	switch ( ctl->func ) {
+	switch (ctl->func) {
 	case DRM_INST_HANDLER:
 		/* Handle drivers whose DRM used to require IRQ setup but the
 		 * no longer does.
 		 */
-		if (!dev->driver.use_irq)
+		if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 			return 0;
 		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
 		    ctl->irq != dev->irq)
 			return EINVAL;
 		return drm_irq_install(dev);
 	case DRM_UNINST_HANDLER:
-		if (!dev->driver.use_irq)
+		if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 			return 0;
 		DRM_LOCK();
 		err = drm_irq_uninstall(dev);
@@ -221,12 +250,131 @@
 	}
 }
 
-int drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv)
+u32 drm_vblank_count(struct drm_device *dev, int crtc)
 {
-	drm_wait_vblank_t *vblwait = data;
-	struct timeval now;
+	return atomic_read(&dev->vblank[crtc].count);
+}
+
+static void drm_update_vblank_count(struct drm_device *dev, int crtc)
+{
+	u32 cur_vblank, diff;
+
+	/*
+	 * Interrupts were disabled prior to this call, so deal with counter
+	 * wrap if needed.
+	 * NOTE!  It's possible we lost a full dev->max_vblank_count events
+	 * here if the register is small or we had vblank interrupts off for
+	 * a long time.
+	 */
+	cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
+	diff = cur_vblank - dev->vblank[crtc].last;
+	if (cur_vblank < dev->vblank[crtc].last) {
+		diff += dev->max_vblank_count;
+
+		DRM_DEBUG("vblank[%d].last=0x%x, cur_vblank=0x%x => diff=0x%x\n",
+		    crtc, dev->vblank[crtc].last, cur_vblank, diff);
+	}
+
+	DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n",
+	    crtc, diff);
+
+	atomic_add(diff, &dev->vblank[crtc].count);
+}
+
+int drm_vblank_get(struct drm_device *dev, int crtc)
+{
+	unsigned long irqflags;
 	int ret = 0;
-	int flags, seq;
+
+	DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
+	/* Going from 0->1 means we have to enable interrupts again */
+	atomic_add_int(&dev->vblank[crtc].refcount, 1);
+	if (dev->vblank[crtc].refcount == 1 &&
+	    !dev->vblank[crtc].enabled) {
+		ret = dev->driver->enable_vblank(dev, crtc);
+		if (ret)
+			atomic_dec(&dev->vblank[crtc].refcount);
+		else {
+			dev->vblank[crtc].enabled = 1;
+			drm_update_vblank_count(dev, crtc);
+		}
+	}
+	DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
+
+	return ret;
+}
+
+void drm_vblank_put(struct drm_device *dev, int crtc)
+{
+	unsigned long irqflags;
+
+	DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
+	/* Last user schedules interrupt disable */
+	atomic_subtract_int(&dev->vblank[crtc].refcount, 1);
+	if (dev->vblank[crtc].refcount == 0)
+	    callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ,
+		(timeout_t *)vblank_disable_fn, (void *)dev);
+	DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
+}
+
+int drm_modeset_ctl(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	struct drm_modeset_ctl *modeset = data;
+	unsigned long irqflags;
+	int crtc, ret = 0;
+
+	DRM_DEBUG("num_crtcs=%d\n", dev->num_crtcs);
+	/* If drm_vblank_init() hasn't been called yet, just no-op */
+	if (!dev->num_crtcs)
+		goto out;
+
+	crtc = modeset->crtc;
+	DRM_DEBUG("crtc=%d\n", crtc);
+	if (crtc >= dev->num_crtcs) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	/*
+	 * To avoid all the problems that might happen if interrupts
+	 * were enabled/disabled around or between these calls, we just
+	 * have the kernel take a reference on the CRTC (just once though
+	 * to avoid corrupting the count if multiple, mismatch calls occur),
+	 * so that interrupts remain enabled in the interim.
+	 */
+	switch (modeset->cmd) {
+	case _DRM_PRE_MODESET:
+		DRM_DEBUG("pre-modeset\n");
+		if (!dev->vblank[crtc].inmodeset) {
+			dev->vblank[crtc].inmodeset = 1;
+			drm_vblank_get(dev, crtc);
+		}
+		break;
+	case _DRM_POST_MODESET:
+		DRM_DEBUG("post-modeset\n");
+		if (dev->vblank[crtc].inmodeset) {
+			DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
+			dev->vblank_disable_allowed = 1;
+			dev->vblank[crtc].inmodeset = 0;
+			DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
+			drm_vblank_put(dev, crtc);
+		}
+		break;
+	default:
+		ret = EINVAL;
+		break;
+	}
+
+out:
+	return ret;
+}
+
+int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+	union drm_wait_vblank *vblwait = data;
+	int ret = 0;
+	int flags, seq, crtc;
 
 	if (!dev->irq_enabled)
 		return EINVAL;
@@ -240,12 +388,15 @@
 	}
 
 	flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
+	crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
 
-	if ((flags & _DRM_VBLANK_SECONDARY) && !dev->driver.use_vbl_irq2)
+	if (crtc >= dev->num_crtcs)
 		return EINVAL;
-	
-	seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ?
-	    &dev->vbl_received2 : &dev->vbl_received);
+
+	ret = drm_vblank_get(dev, crtc);
+	if (ret)
+		return ret;
+	seq = drm_vblank_count(dev, crtc);
 
 	switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
 	case _DRM_VBLANK_RELATIVE:
@@ -254,7 +405,8 @@
 	case _DRM_VBLANK_ABSOLUTE:
 		break;
 	default:
-		return EINVAL;
+		ret = EINVAL;
+		goto done;
 	}
 
 	if ((flags & _DRM_VBLANK_NEXTONMISS) &&
@@ -264,8 +416,8 @@
 
 	if (flags & _DRM_VBLANK_SIGNAL) {
 #if 0 /* disabled */
-		drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM,
-		    M_NOWAIT | M_ZERO);
+		drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t),
+		    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
 		if (vbl_sig == NULL)
 			return ENOMEM;
 
@@ -275,39 +427,42 @@
 
 		vblwait->reply.sequence = atomic_read(&dev->vbl_received);
 		
-		DRM_SPINLOCK(&dev->irq_lock);
+		DRM_SPINLOCK(&dev->vbl_lock);
 		TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link);
-		DRM_SPINUNLOCK(&dev->irq_lock);
+		DRM_SPINUNLOCK(&dev->vbl_lock);
 		ret = 0;
 #endif
 		ret = EINVAL;
 	} else {
 		DRM_LOCK();
 		/* shared code returns -errno */
-		if (flags & _DRM_VBLANK_SECONDARY) {
-			if (dev->driver.vblank_wait2)
-				ret = -dev->driver.vblank_wait2(dev,
-				    &vblwait->request.sequence);
-		} else if (dev->driver.vblank_wait)
-			ret = -dev->driver.vblank_wait(dev,
-			    &vblwait->request.sequence);
 
+		DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ,
+		    ((drm_vblank_count(dev, crtc)
+		      - vblwait->request.sequence) <= (1 << 23)));
 		DRM_UNLOCK();
 
-		microtime(&now);
-		vblwait->reply.tval_sec = now.tv_sec;
-		vblwait->reply.tval_usec = now.tv_usec;
+		if (ret != EINTR) {
+			struct timeval now;
+
+			microtime(&now);
+			vblwait->reply.tval_sec = now.tv_sec;
+			vblwait->reply.tval_usec = now.tv_usec;
+			vblwait->reply.sequence = drm_vblank_count(dev, crtc);
+		}
 	}
 
+done:
+	drm_vblank_put(dev, crtc);
 	return ret;
 }
 
-void drm_vbl_send_signals(drm_device_t *dev)
+void drm_vbl_send_signals(struct drm_device *dev, int crtc)
 {
 }
 
 #if 0 /* disabled */
-void drm_vbl_send_signals( drm_device_t *dev )
+void drm_vbl_send_signals(struct drm_device *dev, int crtc )
 {
 	drm_vbl_sig_t *vbl_sig;
 	unsigned int vbl_seq = atomic_read( &dev->vbl_received );
@@ -317,7 +472,7 @@
 	while (vbl_sig != NULL) {
 		drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link);
 
-		if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
+		if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
 			p = pfind(vbl_sig->pid);
 			if (p != NULL)
 				psignal(p, vbl_sig->signo);
@@ -330,52 +485,53 @@
 }
 #endif
 
+void drm_handle_vblank(struct drm_device *dev, int crtc)
+{
+	atomic_inc(&dev->vblank[crtc].count);
+	DRM_WAKEUP(&dev->vblank[crtc].queue);
+	drm_vbl_send_signals(dev, crtc);
+}
+
 static void drm_locked_task(void *context, int pending __unused)
 {
-	drm_device_t *dev = context;
+	struct drm_device *dev = context;
 
-	DRM_LOCK();
-	for (;;) {
-		int ret;
+	DRM_SPINLOCK(&dev->tsk_lock);
 
-		if (drm_lock_take(&dev->lock.hw_lock->lock,
-		    DRM_KERNEL_CONTEXT))
-		{
-			dev->lock.file_priv = NULL; /* kernel owned */
-			dev->lock.lock_time = jiffies;
-			atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
-			break;  /* Got lock */
-		}
+	DRM_LOCK(); /* XXX drm_lock_take() should do it's own locking */
+	if (dev->locked_task_call == NULL ||
+	    drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT) == 0) {
+		DRM_UNLOCK();
+		DRM_SPINUNLOCK(&dev->tsk_lock);
+		return;
+	}
 
-		/* Contention */
-#if defined(__FreeBSD__) && __FreeBSD_version > 500000
-		ret = mtx_sleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
-		    PZERO | PCATCH, "drmlk2", 0);
-#elif defined(__DragonFly__)
-		crit_enter();
-		tsleep_interlock((void *)&dev->lock.lock_queue);
-		DRM_UNLOCK();
-		ret = tsleep((void *)&dev->lock.lock_queue, PCATCH,
-		    "drmlk2", 0);
-		crit_exit();
-		DRM_LOCK();
-#else
-		ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH,
-		    "drmlk2", 0);
-#endif
-		if (ret != 0)
-			return;
-	}
+	dev->lock.file_priv = NULL; /* kernel owned */
+	dev->lock.lock_time = jiffies;
+	atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+
 	DRM_UNLOCK();
 
 	dev->locked_task_call(dev);
 
-	drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
+	drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
+
+	dev->locked_task_call = NULL;
+
+	DRM_SPINUNLOCK(&dev->tsk_lock);
 }
 
 void
-drm_locked_tasklet(drm_device_t *dev, void (*tasklet)(drm_device_t *dev))
+drm_locked_tasklet(struct drm_device *dev,
+		   void (*tasklet)(struct drm_device *dev))
 {
+	DRM_SPINLOCK(&dev->tsk_lock);
+	if (dev->locked_task_call != NULL) {
+		DRM_SPINUNLOCK(&dev->tsk_lock);
+		return;
+	}
+
 	dev->locked_task_call = tasklet;
+	DRM_SPINUNLOCK(&dev->tsk_lock);
 	taskqueue_enqueue(taskqueue_swi, &dev->locked_task);
 }
diff --git a/sys/dev/drm/drm_linux_list.h b/sys/dev/drm/drm_linux_list.h
--- a/sys/dev/drm/drm_linux_list.h
+++ b/sys/dev/drm/drm_linux_list.h
@@ -67,6 +67,6 @@
 
 #define list_for_each_safe(entry, temp, head)			\
     for (entry = (head)->next, temp = (entry)->next;		\
-	temp != head; 						\
-	entry = temp, temp = temp->next)
+	entry != head; 						\
+	entry = temp, temp = entry->next)
 
diff --git a/sys/dev/drm/drm_lock.c b/sys/dev/drm/drm_lock.c
--- a/sys/dev/drm/drm_lock.c
+++ b/sys/dev/drm/drm_lock.c
@@ -50,89 +50,28 @@
 
 #include "drmP.h"
 
-int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
+int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	unsigned int old, new;
+	struct drm_lock *lock = data;
+	int ret = 0;
 
-	do {
-		old = *lock;
-		if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
-		else			  new = context | _DRM_LOCK_HELD;
-	} while (!atomic_cmpset_int(lock, old, new));
+	if (lock->context == DRM_KERNEL_CONTEXT) {
+		DRM_ERROR("Process %d using kernel context %d\n",
+		    DRM_CURRENTPID, lock->context);
+		return EINVAL;
+	}
 
-	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;
-
-	dev->lock.file_priv = NULL;
-	do {
-		old  = *lock;
-		new  = context | _DRM_LOCK_HELD;
-	} while (!atomic_cmpset_int(lock, old, new));
-
-	return 1;
-}
-
-int drm_lock_free(drm_device_t *dev,
-		   __volatile__ unsigned int *lock, unsigned int context)
-{
-	unsigned int old, new;
-
-	dev->lock.file_priv = NULL;
-	do {
-		old  = *lock;
-		new  = 0;
-	} while (!atomic_cmpset_int(lock, old, new));
-
-	if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
-		DRM_ERROR("%d freed heavyweight lock held by %d\n",
-			  context, _DRM_LOCKING_CONTEXT(old));
-		return 1;
-	}
-	DRM_WAKEUP_INT((void *)&dev->lock.lock_queue);
-	return 0;
-}
-
-int drm_lock(drm_device_t *dev, void *data, struct drm_file *file_priv)
-{
-        drm_lock_t *lock = data;
-        int ret = 0;
-
-        if (lock->context == DRM_KERNEL_CONTEXT) {
-                DRM_ERROR("Process %d using kernel context %d\n",
-		    DRM_CURRENTPID, lock->context);
-                return EINVAL;
-        }
-
-        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+	DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
 	    lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
 	    lock->flags);
 
-        if (dev->driver.use_dma_queue && lock->context < 0)
-                return EINVAL;
+	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) &&
+	    lock->context < 0)
+		return EINVAL;
 
 	DRM_LOCK();
 	for (;;) {
-		if (drm_lock_take(&dev->lock.hw_lock->lock, lock->context)) {
+		if (drm_lock_take(&dev->lock, lock->context)) {
 			dev->lock.file_priv = file_priv;
 			dev->lock.lock_time = jiffies;
 			atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
@@ -140,10 +79,6 @@
 		}
 
 		/* Contention */
-#if defined(__FreeBSD__) && __FreeBSD_version > 500000
-		ret = mtx_sleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
-		    PZERO | PCATCH, "drmlk2", 0);
-#elif defined(__DragonFly__)
 		crit_enter();
 		tsleep_interlock((void *)&dev->lock.lock_queue);
 		DRM_UNLOCK();
@@ -151,10 +86,6 @@
 		    "drmlk2", 0);
 		crit_exit();
 		DRM_LOCK();
-#else
-		ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH,
-		    "drmlk2", 0);
-#endif
 		if (ret != 0)
 			break;
 	}
@@ -166,38 +97,108 @@
 
 	/* XXX: Add signal blocking here */
 
-	if (dev->driver.dma_quiescent != NULL &&
+	if (dev->driver->dma_quiescent != NULL &&
 	    (lock->flags & _DRM_LOCK_QUIESCENT))
-		dev->driver.dma_quiescent(dev);
+		dev->driver->dma_quiescent(dev);
 
 	return 0;
 }
 
-int drm_unlock(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_lock_t *lock = data;
+	struct drm_lock *lock = data;
+
+	DRM_DEBUG("%d (pid %d) requests unlock (0x%08x), flags = 0x%08x\n",
+	    lock->context, DRM_CURRENTPID, dev->lock.hw_lock->lock,
+	    lock->flags);
 
 	if (lock->context == DRM_KERNEL_CONTEXT) {
 		DRM_ERROR("Process %d using kernel context %d\n",
 		    DRM_CURRENTPID, lock->context);
 		return EINVAL;
 	}
-	/* Check that the context unlock being requested actually matches
-	 * who currently holds the lock.
-	 */
-	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) ||
-	    _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) != lock->context)
-		return EINVAL;
+
+	DRM_SPINLOCK(&dev->tsk_lock);
+	if (dev->locked_task_call != NULL) {
+		dev->locked_task_call(dev);
+		dev->locked_task_call = NULL;
+	}
+	DRM_SPINUNLOCK(&dev->tsk_lock);
 
 	atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
 
 	DRM_LOCK();
-	drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT);
+	drm_lock_transfer(&dev->lock, DRM_KERNEL_CONTEXT);
 
-	if (drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) {
+	if (drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT)) {
 		DRM_ERROR("\n");
 	}
 	DRM_UNLOCK();
 
 	return 0;
 }
+
+int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context)
+{
+	volatile unsigned int *lock = &lock_data->hw_lock->lock;
+	unsigned int old, new;
+
+	do {
+		old = *lock;
+		if (old & _DRM_LOCK_HELD)
+			new = old | _DRM_LOCK_CONT;
+		else
+			new = context | _DRM_LOCK_HELD;
+	} while (!atomic_cmpset_int(lock, old, new));
+
+	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(struct drm_lock_data *lock_data, unsigned int context)
+{
+	volatile unsigned int *lock = &lock_data->hw_lock->lock;
+	unsigned int old, new;
+
+	lock_data->file_priv = NULL;
+	do {
+		old = *lock;
+		new = context | _DRM_LOCK_HELD;
+	} while (!atomic_cmpset_int(lock, old, new));
+
+	return 1;
+}
+
+int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
+{
+	volatile unsigned int *lock = &lock_data->hw_lock->lock;
+	unsigned int old, new;
+
+	lock_data->file_priv = NULL;
+	do {
+		old = *lock;
+		new = 0;
+	} while (!atomic_cmpset_int(lock, old, new));
+
+	if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
+		DRM_ERROR("%d freed heavyweight lock held by %d\n",
+		    context, _DRM_LOCKING_CONTEXT(old));
+		return 1;
+	}
+	DRM_WAKEUP_INT((void *)&lock_data->lock_queue);
+	return 0;
+}
diff --git a/sys/dev/drm/drm_memory.c b/sys/dev/drm/drm_memory.c
--- a/sys/dev/drm/drm_memory.c
+++ b/sys/dev/drm/drm_memory.c
@@ -39,71 +39,51 @@
 
 #include "drmP.h"
 
-MALLOC_DEFINE(M_DRM, "drm", "DRM Data Structures");
+MALLOC_DEFINE(DRM_MEM_DMA, "drm_dma", "DRM DMA Data Structures");
+MALLOC_DEFINE(DRM_MEM_SAREA, "drm_sarea", "DRM SAREA Data Structures");
+MALLOC_DEFINE(DRM_MEM_DRIVER, "drm_driver", "DRM DRIVER Data Structures");
+MALLOC_DEFINE(DRM_MEM_MAGIC, "drm_magic", "DRM MAGIC Data Structures");
+MALLOC_DEFINE(DRM_MEM_IOCTLS, "drm_ioctls", "DRM IOCTL Data Structures");
+MALLOC_DEFINE(DRM_MEM_MAPS, "drm_maps", "DRM MAP Data Structures");
+MALLOC_DEFINE(DRM_MEM_BUFS, "drm_bufs", "DRM BUFFER Data Structures");
+MALLOC_DEFINE(DRM_MEM_SEGS, "drm_segs", "DRM SEGMENTS Data Structures");
+MALLOC_DEFINE(DRM_MEM_PAGES, "drm_pages", "DRM PAGES Data Structures");
+MALLOC_DEFINE(DRM_MEM_FILES, "drm_files", "DRM FILE Data Structures");
+MALLOC_DEFINE(DRM_MEM_QUEUES, "drm_queues", "DRM QUEUE Data Structures");
+MALLOC_DEFINE(DRM_MEM_CMDS, "drm_cmds", "DRM COMMAND Data Structures");
+MALLOC_DEFINE(DRM_MEM_MAPPINGS, "drm_mapping", "DRM MAPPING Data Structures");
+MALLOC_DEFINE(DRM_MEM_BUFLISTS, "drm_buflists", "DRM BUFLISTS Data Structures");
+MALLOC_DEFINE(DRM_MEM_AGPLISTS, "drm_agplists", "DRM AGPLISTS Data Structures");
+MALLOC_DEFINE(DRM_MEM_CTXBITMAP, "drm_ctxbitmap",
+    "DRM CTXBITMAP Data Structures");
+MALLOC_DEFINE(DRM_MEM_SGLISTS, "drm_sglists", "DRM SGLISTS Data Structures");
+MALLOC_DEFINE(DRM_MEM_DRAWABLE, "drm_drawable", "DRM DRAWABLE Data Structures");
 
 void drm_mem_init(void)
 {
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-	malloc_type_attach(M_DRM);
-#endif
 }
 
 void drm_mem_uninit(void)
 {
 }
 
-void *drm_alloc(size_t size, int area)
+void *drm_ioremap_wc(struct drm_device *dev, drm_local_map_t *map)
 {
-	return malloc(size, M_DRM, M_NOWAIT);
+	/* XXX - not yet
+	return pmap_mapdev_attr(map->offset, map->size, PAT_WRITE_COMBINING); */
+	return pmap_mapdev(map->offset, map->size);
 }
 
-void *drm_calloc(size_t nmemb, size_t size, int area)
+void *drm_ioremap(struct drm_device *dev, drm_local_map_t *map)
 {
-	return malloc(size * nmemb, M_DRM, M_NOWAIT | M_ZERO);
-}
-
-void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
-{
-	void *pt;
-
-	pt = malloc(size, M_DRM, M_NOWAIT);
-	if (pt == NULL)
-		return NULL;
-	if (oldpt && oldsize) {
-		memcpy(pt, oldpt, oldsize);
-		free(oldpt, M_DRM);
-	}
-	return pt;
-}
-
-void drm_free(void *pt, size_t size, int area)
-{
-	free(pt, M_DRM);
-}
-
-void *drm_ioremap(drm_device_t *dev, drm_local_map_t *map)
-{
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	return pmap_mapdev(map->offset, map->size);
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	map->bst = dev->pa.pa_memt;
-	if (bus_space_map(map->bst, map->offset, map->size, 
-	    BUS_SPACE_MAP_LINEAR, &map->bsh))
-		return NULL;
-	return bus_space_vaddr(map->bst, map->bsh);
-#endif
 }
 
 void drm_ioremapfree(drm_local_map_t *map)
 {
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	pmap_unmapdev((vm_offset_t) map->handle, map->size);
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-	bus_space_unmap(map->bst, map->bsh, map->size);
-#endif
 }
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 int
 drm_mtrr_add(unsigned long offset, size_t size, int flags)
 {
@@ -131,30 +111,3 @@
 	strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
 	return mem_range_attr_set(&mrdesc, &act);
 }
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-int
-drm_mtrr_add(unsigned long offset, size_t size, int flags)
-{
-	struct mtrr mtrrmap;
-	int one = 1;
-
-	mtrrmap.base = offset;
-	mtrrmap.len = size;
-	mtrrmap.type = flags;
-	mtrrmap.flags = MTRR_VALID;
-	return mtrr_set(&mtrrmap, &one, NULL, MTRR_GETSET_KERNEL);
-}
-
-int
-drm_mtrr_del(unsigned long offset, size_t size, int flags)
-{
-	struct mtrr mtrrmap;
-	int one = 1;
-
-	mtrrmap.base = offset;
-	mtrrmap.len = size;
-	mtrrmap.type = flags;
-	mtrrmap.flags = 0;
-	return mtrr_set(&mtrrmap, &one, NULL, MTRR_GETSET_KERNEL);
-}
-#endif
diff --git a/sys/dev/drm/drm_pci.c b/sys/dev/drm/drm_pci.c
--- a/sys/dev/drm/drm_pci.c
+++ b/sys/dev/drm/drm_pci.c
@@ -36,7 +36,6 @@
 /** \name PCI memory */
 /*@{*/
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 static void
 drm_pci_busdma_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 {
@@ -48,14 +47,14 @@
 	KASSERT(nsegs == 1, ("drm_pci_busdma_callback: bad dma segment count"));
 	dmah->busaddr = segs[0].ds_addr;
 }
-#endif
 
 /**
  * \brief Allocate a physically contiguous DMA-accessible consistent 
  * memory block.
  */
 drm_dma_handle_t *
-drm_pci_alloc(drm_device_t *dev, size_t size, size_t align, dma_addr_t maxaddr)
+drm_pci_alloc(struct drm_device *dev, size_t size,
+	      size_t align, dma_addr_t maxaddr)
 {
 	drm_dma_handle_t *dmah;
 	int ret;
@@ -67,22 +66,28 @@
 		return NULL;
 	}
 
-	dmah = malloc(sizeof(drm_dma_handle_t), M_DRM, M_ZERO | M_NOWAIT);
+	dmah = malloc(sizeof(drm_dma_handle_t), DRM_MEM_DMA, M_ZERO | M_NOWAIT);
 	if (dmah == NULL)
 		return NULL;
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+#if 0 /* FIXME */
+	/* Make sure we aren't holding locks here */
+	mtx_assert(&dev->dev_lock, MA_NOTOWNED);
+	if (mtx_owned(&dev->dev_lock))
+	    DRM_ERROR("called while holding dev_lock\n");
+	mtx_assert(&dev->dma_lock, MA_NOTOWNED);
+	if (mtx_owned(&dev->dma_lock))
+	    DRM_ERROR("called while holding dma_lock\n");
+#endif
+
 	ret = bus_dma_tag_create(NULL, align, 0, /* tag, align, boundary */
 	    maxaddr, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
 	    NULL, NULL, /* filtfunc, filtfuncargs */
 	    size, 1, size, /* maxsize, nsegs, maxsegsize */
 	    BUS_DMA_ALLOCNOW, /* flags */
-#ifdef __FreeBSD__
-	    NULL, NULL, /* lockfunc, lockfuncargs */
-#endif
 	    &dmah->tag);
 	if (ret != 0) {
-		free(dmah, M_DRM);
+		free(dmah, DRM_MEM_DMA);
 		return NULL;
 	}
 
@@ -90,7 +95,7 @@
 	    &dmah->map);
 	if (ret != 0) {
 		bus_dma_tag_destroy(dmah->tag);
-		free(dmah, M_DRM);
+		free(dmah, DRM_MEM_DMA);
 		return NULL;
 	}
 
@@ -99,27 +104,9 @@
 	if (ret != 0) {
 		bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
 		bus_dma_tag_destroy(dmah->tag);
-		free(dmah, M_DRM);
+		free(dmah, DRM_MEM_DMA);
 		return NULL;
 	}
-#elif defined(__NetBSD__)
-	ret = bus_dmamem_alloc(dev->dma_tag, size, align, PAGE_SIZE,
-	    &dmah->seg, 1, &nsegs, BUS_DMA_NOWAIT);
-	if ((ret != 0) || (nsegs != 1)) {
-		free(dmah, M_DRM);
-		return NULL;
-	}
-
-	ret = bus_dmamem_map(dev->dma_tag, &dmah->seg, 1, size, &dmah->addr,
-	    BUS_DMA_NOWAIT);
-	if (ret != 0) {
-		bus_dmamem_free(dev->dma_tag, &dmah->seg, 1);
-		free(dmah, M_DRM);
-		return NULL;
-	}
-
-	dmah->dmaaddr = h->seg.ds_addr;
-#endif
 
 	return dmah;
 }
@@ -128,19 +115,15 @@
  * \brief Free a DMA-accessible consistent memory block.
  */
 void
-drm_pci_free(drm_device_t *dev, drm_dma_handle_t *dmah)
+drm_pci_free(struct drm_device *dev, drm_dma_handle_t *dmah)
 {
 	if (dmah == NULL)
 		return;
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 	bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
 	bus_dma_tag_destroy(dmah->tag);
-#elif defined(__NetBSD__)
-	bus_dmamem_free(dev->dma_tag, &dmah->seg, 1);
-#endif
 
-	free(dmah, M_DRM);
+	free(dmah, DRM_MEM_DMA);
 }
 
 /*@}*/
diff --git a/sys/dev/drm/drm_scatter.c b/sys/dev/drm/drm_scatter.c
--- a/sys/dev/drm/drm_scatter.c
+++ b/sys/dev/drm/drm_scatter.c
@@ -41,37 +41,37 @@
 
 void drm_sg_cleanup(drm_sg_mem_t *entry)
 {
-	free((void *)entry->handle, M_DRM);
-	free(entry->busaddr, M_DRM);
-	free(entry, M_DRM);
+	free((void *)entry->handle, DRM_MEM_PAGES);
+	free(entry->busaddr, DRM_MEM_PAGES);
+	free(entry, DRM_MEM_SGLISTS);
 }
 
-int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request)
+int drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather * request)
 {
 	drm_sg_mem_t *entry;
 	unsigned long pages;
 	int i;
 
-	if ( dev->sg )
+	if (dev->sg)
 		return EINVAL;
 
-	entry = malloc(sizeof(*entry), M_DRM, M_WAITOK | M_ZERO);
-	if ( !entry )
+	entry = malloc(sizeof(*entry), DRM_MEM_SGLISTS, M_WAITOK | M_ZERO);
+	if (!entry)
 		return ENOMEM;
 
 	pages = round_page(request->size) / PAGE_SIZE;
-	DRM_DEBUG( "sg size=%ld pages=%ld\n", request->size, pages );
+	DRM_DEBUG("sg size=%ld pages=%ld\n", request->size, pages);
 
 	entry->pages = pages;
 
-	entry->busaddr = malloc(pages * sizeof(*entry->busaddr), M_DRM,
+	entry->busaddr = malloc(pages * sizeof(*entry->busaddr), DRM_MEM_PAGES,
 	    M_WAITOK | M_ZERO);
-	if ( !entry->busaddr ) {
+	if (!entry->busaddr) {
 		drm_sg_cleanup(entry);
 		return ENOMEM;
 	}
 
-	entry->handle = (long)malloc(pages << PAGE_SHIFT, M_DRM,
+	entry->handle = (long)malloc(pages << PAGE_SHIFT, DRM_MEM_PAGES,
 	    M_WAITOK | M_ZERO);
 	if (entry->handle == 0) {
 		drm_sg_cleanup(entry);
@@ -82,7 +82,7 @@
 		entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE);
 	}
 
-	DRM_DEBUG( "sg alloc handle  = %08lx\n", entry->handle );
+	DRM_DEBUG("sg alloc handle  = %08lx\n", entry->handle);
 
 	entry->virtual = (void *)entry->handle;
 	request->handle = entry->handle;
@@ -99,20 +99,21 @@
 	return 0;
 }
 
-int drm_sg_alloc_ioctl(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
 {
-	drm_scatter_gather_t *request = data;
+	struct drm_scatter_gather *request = data;
 	int ret;
 
-	DRM_DEBUG( "%s\n", __FUNCTION__ );
+	DRM_DEBUG("%s\n", __FUNCTION__);
 
 	ret = drm_sg_alloc(dev, request);
 	return ret;
 }
 
-int drm_sg_free(drm_device_t *dev, void *data, struct drm_file *file_priv)
+int drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-	drm_scatter_gather_t *request = data;
+	struct drm_scatter_gather *request = data;
 	drm_sg_mem_t *entry;
 
 	DRM_LOCK();
@@ -120,10 +121,10 @@
 	dev->sg = NULL;
 	DRM_UNLOCK();
 
-	if ( !entry || entry->handle != request->handle )
+	if (!entry || entry->handle != request->handle)
 		return EINVAL;
 
-	DRM_DEBUG( "sg free virtual  = 0x%lx\n", entry->handle );
+	DRM_DEBUG("sg free virtual = 0x%lx\n", entry->handle);
 
 	drm_sg_cleanup(entry);
 
diff --git a/sys/dev/drm/drm_sysctl.c b/sys/dev/drm/drm_sysctl.c
--- a/sys/dev/drm/drm_sysctl.c
+++ b/sys/dev/drm/drm_sysctl.c
@@ -54,14 +54,14 @@
 	char		       name[2];
 };
 
-int drm_sysctl_init(drm_device_t *dev)
+int drm_sysctl_init(struct drm_device *dev)
 {
 	struct drm_sysctl_info *info;
 	struct sysctl_oid *oid;
 	struct sysctl_oid *top, *drioid;
 	int		  i;
 
-	info = malloc(sizeof *info, M_DRM, M_WAITOK | M_ZERO);
+	info = malloc(sizeof *info, DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
 	if ( !info )
 		return 1;
 	dev->sysctl = info;
@@ -108,12 +108,12 @@
 	return 0;
 }
 
-int drm_sysctl_cleanup(drm_device_t *dev)
+int drm_sysctl_cleanup(struct drm_device *dev)
 {
 	int error;
 	error = sysctl_ctx_free( &dev->sysctl->ctx );
 
-	free(dev->sysctl, M_DRM);
+	free(dev->sysctl, DRM_MEM_DRIVER);
 	dev->sysctl = NULL;
 
 	return error;
@@ -129,12 +129,12 @@
 
 static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
 {
-	drm_device_t *dev = arg1;
+	struct drm_device *dev = arg1;
 	char buf[128];
 	int retcode;
 	int hasunique = 0;
 
-	DRM_SYSCTL_PRINT("%s 0x%x", dev->driver.name, dev2udev(dev->devnode));
+	DRM_SYSCTL_PRINT("%s 0x%x", dev->driver->name, dev2udev(dev->devnode));
 	
 	DRM_LOCK();
 	if (dev->unique) {
@@ -154,7 +154,7 @@
 
 static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
 {
-	drm_device_t *dev = arg1;
+	struct drm_device *dev = arg1;
 	drm_local_map_t *map, *tempmaps;
 	const char   *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
 	const char *type, *yesno;
@@ -171,7 +171,8 @@
 	TAILQ_FOREACH(map, &dev->maplist, link)
 		mapcount++;
 
-	tempmaps = malloc(sizeof(drm_local_map_t) * mapcount, M_DRM, M_NOWAIT);
+	tempmaps = malloc(sizeof(drm_local_map_t) * mapcount, DRM_MEM_DRIVER,
+	    M_NOWAIT);
 	if (tempmaps == NULL) {
 		DRM_UNLOCK();
 		return ENOMEM;
@@ -207,13 +208,13 @@
 	SYSCTL_OUT(req, "", 1);
 
 done:
-	free(tempmaps, M_DRM);
+	free(tempmaps, DRM_MEM_DRIVER);
 	return retcode;
 }
 
 static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
 {
-	drm_device_t	 *dev = arg1;
+	struct drm_device	 *dev = arg1;
 	drm_device_dma_t *dma = dev->dma;
 	drm_device_dma_t tempdma;
 	int *templists;
@@ -231,7 +232,8 @@
 	}
 	DRM_SPINLOCK(&dev->dma_lock);
 	tempdma = *dma;
-	templists = malloc(sizeof(int) * dma->buf_count, M_DRM, M_NOWAIT);
+	templists = malloc(sizeof(int) * dma->buf_count, DRM_MEM_DRIVER,
+	    M_NOWAIT);
 	for (i = 0; i < dma->buf_count; i++)
 		templists[i] = dma->buflist[i]->list;
 	dma = &tempdma;
@@ -263,14 +265,14 @@
 
 	SYSCTL_OUT(req, "", 1);
 done:
-	free(templists, M_DRM);
+	free(templists, DRM_MEM_DRIVER);
 	return retcode;
 }
 
 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
 {
-	drm_device_t *dev = arg1;
-	drm_file_t *priv, *tempprivs;
+	struct drm_device *dev = arg1;
+	struct drm_file *priv, *tempprivs;
 	char buf[128];
 	int retcode;
 	int privcount, i;
@@ -281,7 +283,8 @@
 	TAILQ_FOREACH(priv, &dev->files, link)
 		privcount++;
 
-	tempprivs = malloc(sizeof(drm_file_t) * privcount, M_DRM, M_NOWAIT);
+	tempprivs = malloc(sizeof(struct drm_file) * privcount, DRM_MEM_DRIVER,
+	    M_NOWAIT);
 	if (tempprivs == NULL) {
 		DRM_UNLOCK();
 		return ENOMEM;
@@ -306,6 +309,6 @@
 
 	SYSCTL_OUT(req, "", 1);
 done:
-	free(tempprivs, M_DRM);
+	free(tempprivs, DRM_MEM_DRIVER);
 	return retcode;
 }
diff --git a/sys/dev/drm/drm_vm.c b/sys/dev/drm/drm_vm.c
--- a/sys/dev/drm/drm_vm.c
+++ b/sys/dev/drm/drm_vm.c
@@ -30,35 +30,21 @@
 #include "drmP.h"
 #include "drm.h"
 
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500102
-int drm_mmap(struct cdev *kdev, vm_offset_t offset, vm_paddr_t *paddr,
-    int prot)
-#elif defined(__FreeBSD__)
-int drm_mmap(dev_t kdev, vm_offset_t offset, int prot)
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
-#endif
-#ifdef __DragonFly__
 int drm_mmap(struct dev_mmap_args *ap)
 {
 	struct cdev *kdev = ap->a_head.a_dev;
 	vm_offset_t offset = ap->a_offset;
-#else
-{
-#endif
-	drm_device_t *dev = drm_get_device_from_kdev(kdev);
+	struct drm_device *dev = drm_get_device_from_kdev(kdev);
+	struct drm_file *priv = NULL;
 	drm_local_map_t *map;
-	drm_file_t *priv;
-	drm_map_type_t type;
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+	enum drm_map_type type;
 	vm_paddr_t phys;
-#else
-	paddr_t phys;
-#endif
+	int error;
 
 	DRM_LOCK();
 	priv = drm_find_file_by_proc(dev, DRM_CURPROC);
 	DRM_UNLOCK();
+
 	if (priv == NULL) {
 		DRM_ERROR("can't find authenticator\n");
 		return EINVAL;
@@ -76,22 +62,13 @@
 			unsigned long page = offset >> PAGE_SHIFT;
 			unsigned long phys = dma->pagelist[page];
 
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500102
-			*paddr = phys;
+			ap->a_result = atop(phys);
 			DRM_SPINUNLOCK(&dev->dma_lock);
 			return 0;
-#elif defined(__DragonFly__)
-			ap->a_result = atop(phys);
-			DRM_SPINUNLOCK(&dev->dma_lock);
-			return (0);
-#else
-			return atop(phys);
-#endif
 		} else {
 			DRM_SPINUNLOCK(&dev->dma_lock);
 			return -1;
 		}
-		DRM_SPINUNLOCK(&dev->dma_lock);
 	}
 
 				/* A sequential search of a linked list is
@@ -138,14 +115,7 @@
 		return -1;	/* This should never happen. */
 	}
 
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500102
-	*paddr = phys;
+	ap->a_result = atop(phys);
 	return 0;
-#elif defined(__DragonFly__)
-	ap->a_result = atop(phys);
-	return (0);
-#else
-	return atop(phys);
-#endif
 }
 
diff --git a/sys/dev/drm/i915/Makefile b/sys/dev/drm/i915/Makefile
--- a/sys/dev/drm/i915/Makefile
+++ b/sys/dev/drm/i915/Makefile
@@ -4,7 +4,7 @@
 KMOD	= i915
 KMODDEPS= drm
 NO_MAN	= YES
-SRCS    = i915_dma.c i915_drv.c i915_irq.c i915_mem.c
+SRCS    = i915_dma.c i915_drv.c i915_irq.c i915_mem.c i915_suspend.c
 SRCS   += device_if.h bus_if.h pci_if.h opt_drm.h
 CFLAGS += ${DEBUG_FLAGS} -I. -I..
 
diff --git a/sys/dev/drm/i915_dma.c b/sys/dev/drm/i915_dma.c
--- a/sys/dev/drm/i915_dma.c
+++ b/sys/dev/drm/i915_dma.c
@@ -41,11 +41,15 @@
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
-	u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+	u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+	u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
+	u32 last_acthd = I915_READ(acthd_reg);
+	u32 acthd;
 	int i;
 
-	for (i = 0; i < 10000; i++) {
-		ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+	for (i = 0; i < 100000; i++) {
+		ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+		acthd = I915_READ(acthd_reg);
 		ring->space = ring->head - (ring->tail + 8);
 		if (ring->space < 0)
 			ring->space += ring->Size;
@@ -55,20 +59,96 @@
 		if (ring->head != last_head)
 			i = 0;
 
+		if (acthd != last_acthd)
+			i = 0;
+
 		last_head = ring->head;
-		DRM_UDELAY(1);
+		last_acthd = acthd;
+		DRM_UDELAY(10 * 1000);
 	}
 
 	return -EBUSY;
 }
+
+int i915_init_hardware_status(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_dma_handle_t *dmah;
+
+	/* Program Hardware Status Page */
+#ifdef __FreeBSD__
+	DRM_UNLOCK();
+#endif
+	dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+#ifdef __FreeBSD__
+	DRM_LOCK();
+#endif
+	if (!dmah) {
+		DRM_ERROR("Can not allocate hardware status page\n");
+		return -ENOMEM;
+	}
+
+	dev_priv->status_page_dmah = dmah;
+	dev_priv->hw_status_page = dmah->vaddr;
+	dev_priv->dma_status_page = dmah->busaddr;
+
+	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+
+	I915_WRITE(0x02080, dev_priv->dma_status_page);
+	DRM_DEBUG("Enabled hardware status page\n");
+	return 0;
+}
+
+void i915_free_hardware_status(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	if (dev_priv->status_page_dmah) {
+		drm_pci_free(dev, dev_priv->status_page_dmah);
+		dev_priv->status_page_dmah = NULL;
+		/* Need to rewrite hardware status page */
+		I915_WRITE(0x02080, 0x1ffff000);
+	}
+
+	if (dev_priv->status_gfx_addr) {
+		dev_priv->status_gfx_addr = 0;
+		drm_core_ioremapfree(&dev_priv->hws_map, dev);
+		I915_WRITE(0x02080, 0x1ffff000);
+	}
+}
+
+#if I915_RING_VALIDATE
+/**
+ * Validate the cached ring tail value
+ *
+ * If the X server writes to the ring and DRM doesn't
+ * reload the head and tail pointers, it will end up writing
+ * data to the wrong place in the ring, causing havoc.
+ */
+void i915_ring_validate(struct drm_device *dev, const char *func, int line)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+	u32	tail = I915_READ(PRB0_TAIL) & HEAD_ADDR;
+	u32	head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+
+	if (tail != ring->tail) {
+		DRM_ERROR("%s:%d head sw %x, hw %x. tail sw %x hw %x\n",
+			  func, line,
+			  ring->head, head, ring->tail, tail);
+#ifdef __linux__
+		BUG_ON(1);
+#endif
+	}
+}
+#endif
 
 void i915_kernel_lost_context(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
 
-	ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-	ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+	ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+	ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
 	ring->space = ring->head - (ring->tail + 8);
 	if (ring->space < 0)
 		ring->space += ring->Size;
@@ -81,7 +161,7 @@
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if (dev->irq)
+	if (dev->irq_enabled)
 		drm_irq_uninstall(dev);
 
 	if (dev_priv->ring.virtual_start) {
@@ -91,26 +171,81 @@
 		dev_priv->ring.map.size = 0;
 	}
 
-	if (dev_priv->status_page_dmah) {
-		drm_pci_free(dev, dev_priv->status_page_dmah);
-		dev_priv->status_page_dmah = NULL;
-		/* Need to rewrite hardware status page */
-		I915_WRITE(0x02080, 0x1ffff000);
+	if (I915_NEED_GFX_HWS(dev))
+		i915_free_hardware_status(dev);
+
+	return 0;
+}
+
+#if defined(I915_HAVE_BUFFER)
+#define DRI2_SAREA_BLOCK_TYPE(b) ((b) >> 16)
+#define DRI2_SAREA_BLOCK_SIZE(b) ((b) & 0xffff)
+#define DRI2_SAREA_BLOCK_NEXT(p)				\
+	((void *) ((unsigned char *) (p) +			\
+		   DRI2_SAREA_BLOCK_SIZE(*(unsigned int *) p)))
+
+#define DRI2_SAREA_BLOCK_END		0x0000
+#define DRI2_SAREA_BLOCK_LOCK		0x0001
+#define DRI2_SAREA_BLOCK_EVENT_BUFFER	0x0002
+
+static int
+setup_dri2_sarea(struct drm_device * dev,
+		 struct drm_file *file_priv,
+		 drm_i915_init_t * init)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int ret;
+	unsigned int *p, *end, *next;
+
+	mutex_lock(&dev->struct_mutex);
+	dev_priv->sarea_bo =
+		drm_lookup_buffer_object(file_priv,
+					 init->sarea_handle, 1);
+	mutex_unlock(&dev->struct_mutex);
+
+	if (!dev_priv->sarea_bo) {
+		DRM_ERROR("did not find sarea bo\n");
+		return -EINVAL;
 	}
 
-	if (dev_priv->status_gfx_addr) {
-		dev_priv->status_gfx_addr = 0;
-		drm_core_ioremapfree(&dev_priv->hws_map, dev);
-		I915_WRITE(0x02080, 0x1ffff000);
+	ret = drm_bo_kmap(dev_priv->sarea_bo, 0,
+			  dev_priv->sarea_bo->num_pages,
+			  &dev_priv->sarea_kmap);
+	if (ret) {
+		DRM_ERROR("could not map sarea bo\n");
+		return ret;
+	}
+
+	p = dev_priv->sarea_kmap.virtual;
+	end = (void *) p + (dev_priv->sarea_bo->num_pages << PAGE_SHIFT);
+	while (p < end && DRI2_SAREA_BLOCK_TYPE(*p) != DRI2_SAREA_BLOCK_END) {
+		switch (DRI2_SAREA_BLOCK_TYPE(*p)) {
+		case DRI2_SAREA_BLOCK_LOCK:
+			dev->lock.hw_lock = (void *) (p + 1);
+			dev->sigdata.lock = dev->lock.hw_lock;
+			break;
+		}
+		next = DRI2_SAREA_BLOCK_NEXT(p);
+		if (next <= p || end < next) {
+			DRM_ERROR("malformed dri2 sarea: next is %p should be within %p-%p\n",
+				  next, p, end);
+			return -EINVAL;
+		}
+		p = next;
 	}
 
 	return 0;
 }
+#endif
 
-static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
+static int i915_initialize(struct drm_device * dev,
+			   struct drm_file *file_priv,
+			   drm_i915_init_t * init)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-
+#if defined(I915_HAVE_BUFFER)
+	int ret;
+#endif
 	dev_priv->sarea = drm_getsarea(dev);
 	if (!dev_priv->sarea) {
 		DRM_ERROR("can not find sarea!\n");
@@ -118,51 +253,49 @@
 		return -EINVAL;
 	}
 
-	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
-	if (!dev_priv->mmio_map) {
-		i915_dma_cleanup(dev);
-		DRM_ERROR("can not find mmio map!\n");
-		return -EINVAL;
-	}
-
 #ifdef I915_HAVE_BUFFER
 	dev_priv->max_validate_buffers = I915_MAX_VALIDATE_BUFFERS;
 #endif
 
-	dev_priv->sarea_priv = (drm_i915_sarea_t *)
-	    ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
-
-	dev_priv->ring.Start = init->ring_start;
-	dev_priv->ring.End = init->ring_end;
-	dev_priv->ring.Size = init->ring_size;
-	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
-	dev_priv->ring.map.offset = init->ring_start;
-	dev_priv->ring.map.size = init->ring_size;
-	dev_priv->ring.map.type = 0;
-	dev_priv->ring.map.flags = 0;
-	dev_priv->ring.map.mtrr = 0;
-
-	drm_core_ioremap(&dev_priv->ring.map, dev);
-
-	if (dev_priv->ring.map.handle == NULL) {
-		i915_dma_cleanup(dev);
-		DRM_ERROR("can not ioremap virtual address for"
-			  " ring buffer\n");
-		return -ENOMEM;
+	if (init->sarea_priv_offset)
+		dev_priv->sarea_priv = (drm_i915_sarea_t *)
+			((u8 *) dev_priv->sarea->handle +
+			 init->sarea_priv_offset);
+	else {
+		/* No sarea_priv for you! */
+		dev_priv->sarea_priv = NULL;
 	}
 
-	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+	if (init->ring_size != 0) {
+		dev_priv->ring.Size = init->ring_size;
+		dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+		dev_priv->ring.map.offset = init->ring_start;
+		dev_priv->ring.map.size = init->ring_size;
+		dev_priv->ring.map.type = 0;
+		dev_priv->ring.map.flags = 0;
+		dev_priv->ring.map.mtrr = 0;
+
+		drm_core_ioremap(&dev_priv->ring.map, dev);
+
+		if (dev_priv->ring.map.handle == NULL) {
+			i915_dma_cleanup(dev);
+			DRM_ERROR("can not ioremap virtual address for"
+				  " ring buffer\n");
+			return -ENOMEM;
+		}
+
+		dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+	}
 
 	dev_priv->cpp = init->cpp;
-	dev_priv->sarea_priv->pf_current_page = 0;
+
+	if (dev_priv->sarea_priv)
+		dev_priv->sarea_priv->pf_current_page = 0;
 
 	/* We are using separate values as placeholders for mechanisms for
 	 * private backbuffer/depthbuffer usage.
 	 */
-	dev_priv->use_mi_batchbuffer_start = 0;
-	if (IS_I965G(dev)) /* 965 doesn't support older method */
-		dev_priv->use_mi_batchbuffer_start = 1;
 
 	/* Allow hardware batchbuffers unless told otherwise.
 	 */
@@ -172,27 +305,20 @@
 	 */
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
 
-	/* Program Hardware Status Page */
-	if (!IS_G33(dev)) {
-		dev_priv->status_page_dmah =
-			drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
-
-		if (!dev_priv->status_page_dmah) {
-			i915_dma_cleanup(dev);
-			DRM_ERROR("Can not allocate hardware status page\n");
-			return -ENOMEM;
-		}
-		dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
-		dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-
-		memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-
-		I915_WRITE(0x02080, dev_priv->dma_status_page);
-	}
-	DRM_DEBUG("Enabled hardware status page\n");
 #ifdef I915_HAVE_BUFFER
 	mutex_init(&dev_priv->cmdbuf_mutex);
 #endif
+#if defined(I915_HAVE_BUFFER)
+	if (init->func == I915_INIT_DMA2) {
+		ret = setup_dri2_sarea(dev, file_priv, init);
+		if (ret) {
+			i915_dma_cleanup(dev);
+			DRM_ERROR("could not set up dri2 sarea\n");
+			return ret;
+		}
+	}
+#endif
+
 	return 0;
 }
 
@@ -204,11 +330,6 @@
 
 	if (!dev_priv->sarea) {
 		DRM_ERROR("can not find sarea!\n");
-		return -EINVAL;
-	}
-
-	if (!dev_priv->mmio_map) {
-		DRM_ERROR("can not find mmio map!\n");
 		return -EINVAL;
 	}
 
@@ -242,7 +363,8 @@
 
 	switch (init->func) {
 	case I915_INIT_DMA:
-		retcode = i915_initialize(dev, init);
+	case I915_INIT_DMA2:
+		retcode = i915_initialize(dev, file_priv, init);
 		break;
 	case I915_CLEANUP_DMA:
 		retcode = i915_dma_cleanup(dev);
@@ -374,9 +496,9 @@
 	return 0;
 }
 
-static int i915_emit_box(struct drm_device * dev,
-			 struct drm_clip_rect __user * boxes,
-			 int i, int DR1, int DR4)
+int i915_emit_box(struct drm_device * dev,
+		  struct drm_clip_rect __user * boxes,
+		  int i, int DR1, int DR4)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_clip_rect box;
@@ -427,11 +549,12 @@
 		 DRM_DEBUG("Breadcrumb counter wrapped around\n");
 	}
 
-	dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
+	if (dev_priv->sarea_priv)
+		dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
 
 	BEGIN_LP_RING(4);
-	OUT_RING(CMD_STORE_DWORD_IDX);
-	OUT_RING(20);
+	OUT_RING(MI_STORE_DWORD_INDEX);
+	OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT);
 	OUT_RING(dev_priv->counter);
 	OUT_RING(0);
 	ADVANCE_LP_RING();
@@ -441,7 +564,7 @@
 int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t flush_cmd = CMD_MI_FLUSH;
+	uint32_t flush_cmd = MI_FLUSH;
 	RING_LOCALS;
 
 	flush_cmd |= flush;
@@ -492,13 +615,14 @@
 
 	i915_emit_breadcrumb(dev);
 #ifdef I915_HAVE_FENCE
-	drm_fence_flush_old(dev, 0, dev_priv->counter);
+	if (unlikely((dev_priv->counter & 0xFF) == 0))
+		drm_fence_flush_old(dev, 0, dev_priv->counter);
 #endif
 	return 0;
 }
 
-static int i915_dispatch_batchbuffer(struct drm_device * dev,
-				     drm_i915_batchbuffer_t * batch)
+int i915_dispatch_batchbuffer(struct drm_device * dev,
+			      drm_i915_batchbuffer_t * batch)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_clip_rect __user *boxes = batch->cliprects;
@@ -523,7 +647,14 @@
 				return ret;
 		}
 
-		if (dev_priv->use_mi_batchbuffer_start) {
+		if (IS_I830(dev) || IS_845G(dev)) {
+			BEGIN_LP_RING(4);
+			OUT_RING(MI_BATCH_BUFFER);
+			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+			OUT_RING(batch->start + batch->used - 4);
+			OUT_RING(0);
+			ADVANCE_LP_RING();
+		} else {
 			BEGIN_LP_RING(2);
 			if (IS_I965G(dev)) {
 				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
@@ -533,20 +664,13 @@
 				OUT_RING(batch->start | MI_BATCH_NON_SECURE);
 			}
 			ADVANCE_LP_RING();
-
-		} else {
-			BEGIN_LP_RING(4);
-			OUT_RING(MI_BATCH_BUFFER);
-			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
-			OUT_RING(batch->start + batch->used - 4);
-			OUT_RING(0);
-			ADVANCE_LP_RING();
 		}
 	}
 
 	i915_emit_breadcrumb(dev);
 #ifdef I915_HAVE_FENCE
-	drm_fence_flush_old(dev, 0, dev_priv->counter);
+	if (unlikely((dev_priv->counter & 0xFF) == 0))
+		drm_fence_flush_old(dev, 0, dev_priv->counter);
 #endif
 	return 0;
 }
@@ -619,17 +743,27 @@
 
 	i915_emit_breadcrumb(dev);
 #ifdef I915_HAVE_FENCE
-	if (!sync)
+	if (unlikely(!sync && ((dev_priv->counter & 0xFF) == 0)))
 		drm_fence_flush_old(dev, 0, dev_priv->counter);
 #endif
 }
 
-static int i915_quiescent(struct drm_device *dev)
+int i915_quiescent(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	int ret;
 
 	i915_kernel_lost_context(dev);
-	return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+	ret = i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+	if (ret)
+	{
+		i915_kernel_lost_context (dev);
+		DRM_ERROR ("not quiescent head %08x tail %08x space %08x\n",
+			   dev_priv->ring.head,
+			   dev_priv->ring.tail,
+			   dev_priv->ring.space);
+	}
+	return ret;
 }
 
 static int i915_flush_ioctl(struct drm_device *dev, void *data,
@@ -703,443 +837,10 @@
 	return 0;
 }
 
-#if DRM_DEBUG_CODE
+#if defined(DRM_DEBUG_CODE)
 #define DRM_DEBUG_RELOCATION	(drm_debug != 0)
 #else
 #define DRM_DEBUG_RELOCATION	0
-#endif
-
-#ifdef I915_HAVE_BUFFER
-
-struct i915_relocatee_info {
-	struct drm_buffer_object *buf;
-	unsigned long offset;
-	u32 *data_page;
-	unsigned page_offset;
-	struct drm_bo_kmap_obj kmap;
-	int is_iomem;
-};
-
-struct drm_i915_validate_buffer {
-	struct drm_buffer_object *buffer;
-	int presumed_offset_correct;
-};
-
-static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer *buffers,
-					    unsigned num_buffers)
-{
-	while (num_buffers--)
-		drm_bo_usage_deref_locked(&buffers[num_buffers].buffer);
-}
-
-int i915_apply_reloc(struct drm_file *file_priv, int num_buffers,
-		     struct drm_i915_validate_buffer *buffers,
-		     struct i915_relocatee_info *relocatee,
-		     uint32_t *reloc)
-{
-	unsigned index;
-	unsigned long new_cmd_offset;
-	u32 val;
-	int ret;
-
-	if (reloc[2] >= num_buffers) {
-		DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]);
-		return -EINVAL;
-	}
-
-	/*
-	 * Short-circuit relocations that were correctly
-	 * guessed by the client
-	 */
-	if (buffers[reloc[2]].presumed_offset_correct && !DRM_DEBUG_RELOCATION)
-		return 0;
-
-	new_cmd_offset = reloc[0];
-	if (!relocatee->data_page ||
-	    !drm_bo_same_page(relocatee->offset, new_cmd_offset)) {
-		drm_bo_kunmap(&relocatee->kmap);
-		relocatee->offset = new_cmd_offset;
-		mutex_lock (&relocatee->buf->mutex);
-		ret = drm_bo_wait (relocatee->buf, 0, 0, FALSE);
-		mutex_unlock (&relocatee->buf->mutex);
-		if (ret) {
-			DRM_ERROR("Could not wait for buffer to apply relocs\n %08lx", new_cmd_offset);
-			return ret;
-		}
-		ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT,
-				  1, &relocatee->kmap);
-		if (ret) {
-			DRM_ERROR("Could not map command buffer to apply relocs\n %08lx", new_cmd_offset);
-			return ret;
-		}
-
-		relocatee->data_page = drm_bmo_virtual(&relocatee->kmap,
-						       &relocatee->is_iomem);
-		relocatee->page_offset = (relocatee->offset & PAGE_MASK);
-	}
-
-	val = buffers[reloc[2]].buffer->offset;
-	index = (reloc[0] - relocatee->page_offset) >> 2;
-
-	/* add in validate */
-	val = val + reloc[1];
-
-	if (DRM_DEBUG_RELOCATION) {
-		if (buffers[reloc[2]].presumed_offset_correct &&
-		    relocatee->data_page[index] != val) {
-			DRM_DEBUG ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n",
-				   reloc[0], reloc[1], reloc[2], relocatee->data_page[index], val);
-		}
-	}
-	relocatee->data_page[index] = val;
-	return 0;
-}
-
-int i915_process_relocs(struct drm_file *file_priv,
-			uint32_t buf_handle,
-			uint32_t *reloc_buf_handle,
-			struct i915_relocatee_info *relocatee,
-			struct drm_i915_validate_buffer *buffers,
-			uint32_t num_buffers)
-{
-	struct drm_device *dev = file_priv->head->dev;
-	struct drm_buffer_object *reloc_list_object;
-	uint32_t cur_handle = *reloc_buf_handle;
-	uint32_t *reloc_page;
-	int ret, reloc_is_iomem, reloc_stride;
-	uint32_t num_relocs, reloc_offset, reloc_end, reloc_page_offset, next_offset, cur_offset;
-	struct drm_bo_kmap_obj reloc_kmap;
-
-	memset(&reloc_kmap, 0, sizeof(reloc_kmap));
-
-	mutex_lock(&dev->struct_mutex);
-	reloc_list_object = drm_lookup_buffer_object(file_priv, cur_handle, 1);
-	mutex_unlock(&dev->struct_mutex);
-	if (!reloc_list_object)
-		return -EINVAL;
-
-	ret = drm_bo_kmap(reloc_list_object, 0, 1, &reloc_kmap);
-	if (ret) {
-		DRM_ERROR("Could not map relocation buffer.\n");
-		goto out;
-	}
-
-	reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem);
-	num_relocs = reloc_page[0] & 0xffff;
-
-	if ((reloc_page[0] >> 16) & 0xffff) {
-		DRM_ERROR("Unsupported relocation type requested\n");
-		goto out;
-	}
-
-	/* get next relocate buffer handle */
-	*reloc_buf_handle = reloc_page[1];
-	reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */
-
-	DRM_DEBUG("num relocs is %d, next is %08X\n", num_relocs, reloc_page[1]);
-
-	reloc_page_offset = 0;
-	reloc_offset = I915_RELOC_HEADER * sizeof(uint32_t);
-	reloc_end = reloc_offset + (num_relocs * reloc_stride);
-
-	do {
-		next_offset = drm_bo_offset_end(reloc_offset, reloc_end);
-
-		do {
-			cur_offset = ((reloc_offset + reloc_page_offset) & ~PAGE_MASK) / sizeof(uint32_t);
-			ret = i915_apply_reloc(file_priv, num_buffers,
-					 buffers, relocatee, &reloc_page[cur_offset]);
-			if (ret)
-				goto out;
-
-			reloc_offset += reloc_stride;
-		} while (reloc_offset < next_offset);
-
-		drm_bo_kunmap(&reloc_kmap);
-
-		reloc_offset = next_offset;
-		if (reloc_offset != reloc_end) {
-			ret = drm_bo_kmap(reloc_list_object, reloc_offset >> PAGE_SHIFT, 1, &reloc_kmap);
-			if (ret) {
-				DRM_ERROR("Could not map relocation buffer.\n");
-				goto out;
-			}
-
-			reloc_page = drm_bmo_virtual(&reloc_kmap, &reloc_is_iomem);
-			reloc_page_offset = reloc_offset & ~PAGE_MASK;
-		}
-
-	} while (reloc_offset != reloc_end);
-out:
-	drm_bo_kunmap(&relocatee->kmap);
-	relocatee->data_page = NULL;
-
-	drm_bo_kunmap(&reloc_kmap);
-
-	mutex_lock(&dev->struct_mutex);
-	drm_bo_usage_deref_locked(&reloc_list_object);
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
-}
-
-static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle,
-			   drm_handle_t buf_reloc_handle,
-			   struct drm_i915_validate_buffer *buffers,
-			   uint32_t buf_count)
-{
-	struct drm_device *dev = file_priv->head->dev;
-	struct i915_relocatee_info relocatee;
-	int ret = 0;
-	int b;
-
-	/*
-	 * Short circuit relocations when all previous
-	 * buffers offsets were correctly guessed by
-	 * the client
-	 */
-	if (!DRM_DEBUG_RELOCATION) {
-		for (b = 0; b < buf_count; b++)
-			if (!buffers[b].presumed_offset_correct)
-				break;
-	
-		if (b == buf_count)
-			return 0;
-	}
-
-	memset(&relocatee, 0, sizeof(relocatee));
-
-	mutex_lock(&dev->struct_mutex);
-	relocatee.buf = drm_lookup_buffer_object(file_priv, buf_handle, 1);
-	mutex_unlock(&dev->struct_mutex);
-	if (!relocatee.buf) {
-		DRM_DEBUG("relocatee buffer invalid %08x\n", buf_handle);
-		ret = -EINVAL;
-		goto out_err;
-	}
-
-	while (buf_reloc_handle) {
-		ret = i915_process_relocs(file_priv, buf_handle, &buf_reloc_handle, &relocatee, buffers, buf_count);
-		if (ret) {
-			DRM_ERROR("process relocs failed\n");
-			break;
-		}
-	}
-
-	mutex_lock(&dev->struct_mutex);
-	drm_bo_usage_deref_locked(&relocatee.buf);
-	mutex_unlock(&dev->struct_mutex);
-
-out_err:
-	return ret;
-}
-
-/*
- * Validate, add fence and relocate a block of bos from a userspace list
- */
-int i915_validate_buffer_list(struct drm_file *file_priv,
-			      unsigned int fence_class, uint64_t data,
-			      struct drm_i915_validate_buffer *buffers,
-			      uint32_t *num_buffers)
-{
-	struct drm_i915_op_arg arg;
-	struct drm_bo_op_req *req = &arg.d.req;
-	struct drm_bo_arg_rep rep;
-	unsigned long next = 0;
-	int ret = 0;
-	unsigned buf_count = 0;
-	struct drm_device *dev = file_priv->head->dev;
-	uint32_t buf_reloc_handle, buf_handle;
-
-
-	do {
-		if (buf_count >= *num_buffers) {
-			DRM_ERROR("Buffer count exceeded %d\n.", *num_buffers);
-			ret = -EINVAL;
-			goto out_err;
-		}
-
-		buffers[buf_count].buffer = NULL;
-		buffers[buf_count].presumed_offset_correct = 0;
-
-		if (copy_from_user(&arg, (void __user *)(unsigned long)data, sizeof(arg))) {
-			ret = -EFAULT;
-			goto out_err;
-		}
-
-		if (arg.handled) {
-			data = arg.next;
-			mutex_lock(&dev->struct_mutex);
-			buffers[buf_count].buffer = drm_lookup_buffer_object(file_priv, req->arg_handle, 1);
-			mutex_unlock(&dev->struct_mutex);
-			buf_count++;
-			continue;
-		}
-
-		rep.ret = 0;
-		if (req->op != drm_bo_validate) {
-			DRM_ERROR
-			    ("Buffer object operation wasn't \"validate\".\n");
-			rep.ret = -EINVAL;
-			goto out_err;
-		}
-
-		buf_handle = req->bo_req.handle;
-		buf_reloc_handle = arg.reloc_handle;
-
-		if (buf_reloc_handle) {
-			ret = i915_exec_reloc(file_priv, buf_handle, buf_reloc_handle, buffers, buf_count);
-			if (ret)
-				goto out_err;
-			DRM_MEMORYBARRIER();
-		}
-
-		rep.ret = drm_bo_handle_validate(file_priv, req->bo_req.handle,
-						 req->bo_req.flags, req->bo_req.mask,
-						 req->bo_req.hint,
-						 req->bo_req.fence_class, 0,
-						 &rep.bo_info,
-						 &buffers[buf_count].buffer);
-
-		if (rep.ret) {
-			DRM_ERROR("error on handle validate %d\n", rep.ret);
-			goto out_err;
-		}
-		/*
-		 * If the user provided a presumed offset hint, check whether
-		 * the buffer is in the same place, if so, relocations relative to
-		 * this buffer need not be performed
-		 */
-		if ((req->bo_req.hint & DRM_BO_HINT_PRESUMED_OFFSET) &&
-		    buffers[buf_count].buffer->offset == req->bo_req.presumed_offset) {
-			buffers[buf_count].presumed_offset_correct = 1;
-		}
-
-		next = arg.next;
-		arg.handled = 1;
-		arg.d.rep = rep;
-
-		if (copy_to_user((void __user *)(unsigned long)data, &arg, sizeof(arg)))
-			return -EFAULT;
-
-		data = next;
-		buf_count++;
-
-	} while (next != 0);
-	*num_buffers = buf_count;
-	return 0;
-out_err:
-	mutex_lock(&dev->struct_mutex);
-	i915_dereference_buffers_locked(buffers, buf_count);
-	mutex_unlock(&dev->struct_mutex);
-	*num_buffers = 0;
-	return (ret) ? ret : rep.ret;
-}
-
-static int i915_execbuffer(struct drm_device *dev, void *data,
-			   struct drm_file *file_priv)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
-		dev_priv->sarea_priv;
-	struct drm_i915_execbuffer *exec_buf = data;
-	struct _drm_i915_batchbuffer *batch = &exec_buf->batch;
-	struct drm_fence_arg *fence_arg = &exec_buf->fence_arg;
-	int num_buffers;
-	int ret;
-	struct drm_i915_validate_buffer *buffers;
-	struct drm_fence_object *fence;
-
-	if (!dev_priv->allow_batchbuffer) {
-		DRM_ERROR("Batchbuffer ioctl disabled\n");
-		return -EINVAL;
-	}
-
-
-	if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
-							batch->num_cliprects *
-							sizeof(struct drm_clip_rect)))
-		return -EFAULT;
-
-	if (exec_buf->num_buffers > dev_priv->max_validate_buffers)
-		return -EINVAL;
-
-
-	ret = drm_bo_read_lock(&dev->bm.bm_lock);
-	if (ret)
-		return ret;
-
-	/*
-	 * The cmdbuf_mutex makes sure the validate-submit-fence
-	 * operation is atomic.
-	 */
-
-	ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
-	if (ret) {
-		drm_bo_read_unlock(&dev->bm.bm_lock);
-		return -EAGAIN;
-	}
-
-	num_buffers = exec_buf->num_buffers;
-
-	buffers = drm_calloc(num_buffers, sizeof(struct drm_i915_validate_buffer), DRM_MEM_DRIVER);
-	if (!buffers) {
-		drm_bo_read_unlock(&dev->bm.bm_lock);
-		mutex_unlock(&dev_priv->cmdbuf_mutex);
-		return -ENOMEM;
-	}
-
-	/* validate buffer list + fixup relocations */
-	ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list,
-					buffers, &num_buffers);
-	if (ret)
-		goto out_free;
-
-	/* make sure all previous memory operations have passed */
-	DRM_MEMORYBARRIER();
-	drm_agp_chipset_flush(dev);
-
-	/* submit buffer */
-	batch->start = buffers[num_buffers-1].buffer->offset;
-
-	DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n",
-		  batch->start, batch->used, batch->num_cliprects);
-
-	ret = i915_dispatch_batchbuffer(dev, batch);
-	if (ret)
-		goto out_err0;
-
-	sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-
-	/* fence */
-	ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence);
-	if (ret)
-		goto out_err0;
-
-	if (!(fence_arg->flags & DRM_FENCE_FLAG_NO_USER)) {
-		ret = drm_fence_add_user_object(file_priv, fence, fence_arg->flags & DRM_FENCE_FLAG_SHAREABLE);
-		if (!ret) {
-			fence_arg->handle = fence->base.hash.key;
-			fence_arg->fence_class = fence->fence_class;
-			fence_arg->type = fence->type;
-			fence_arg->signaled = fence->signaled;
-		}
-	}
-	drm_fence_usage_deref_unlocked(&fence);
-out_err0:
-
-	/* handle errors */
-	mutex_lock(&dev->struct_mutex);
-	i915_dereference_buffers_locked(buffers, num_buffers);
-	mutex_unlock(&dev->struct_mutex);
-
-out_free:
-	drm_free(buffers, (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), DRM_MEM_DRIVER);
-
-	mutex_unlock(&dev_priv->cmdbuf_mutex);
-	drm_bo_read_unlock(&dev->bm.bm_lock);
-	return ret;
-}
 #endif
 
 static int i915_do_cleanup_pageflip(struct drm_device * dev)
@@ -1199,13 +900,23 @@
 
 	switch (param->param) {
 	case I915_PARAM_IRQ_ACTIVE:
-		value = dev->irq ? 1 : 0;
+		value = dev->irq_enabled ? 1 : 0;
 		break;
 	case I915_PARAM_ALLOW_BATCHBUFFER:
 		value = dev_priv->allow_batchbuffer ? 1 : 0;
 		break;
 	case I915_PARAM_LAST_DISPATCH:
 		value = READ_BREADCRUMB(dev_priv);
+		break;
+	case I915_PARAM_CHIPSET_ID:
+		value = dev->pci_device;
+		break;
+	case I915_PARAM_HAS_GEM:
+#ifdef I915_HAVE_GEM
+		value = 1;
+#else
+		value = 0;
+#endif
 		break;
 	default:
 		DRM_ERROR("Unknown parameter %d\n", param->param);
@@ -1233,8 +944,6 @@
 
 	switch (param->param) {
 	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
-		if (!IS_I965G(dev))
-			dev_priv->use_mi_batchbuffer_start = param->value;
 		break;
 	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
 		dev_priv->tex_lru_log_granularity = param->value;
@@ -1313,6 +1022,9 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_hws_addr_t *hws = data;
 
+	if (!I915_NEED_GFX_HWS(dev))
+		return -EINVAL;
+
 	if (!dev_priv) {
 		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
@@ -1338,7 +1050,7 @@
 	dev_priv->hw_status_page = dev_priv->hws_map.handle;
 
 	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-	I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
 	DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
 			dev_priv->status_gfx_addr);
 	DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
@@ -1347,7 +1059,7 @@
 
 int i915_driver_load(struct drm_device *dev, unsigned long flags)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv;
 	unsigned long base, size;
 	int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
 
@@ -1365,6 +1077,7 @@
 	memset(dev_priv, 0, sizeof(drm_i915_private_t));
 
 	dev->dev_private = (void *)dev_priv;
+	dev_priv->dev = dev;
 
 	/* Add register map (needed for suspend/resume) */
 	base = drm_get_resource_start(dev, mmio_bar);
@@ -1372,12 +1085,27 @@
 
 	ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
 		_DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map);
+#ifdef I915_HAVE_GEM
+	i915_gem_load(dev);
+#endif
+	DRM_SPININIT(&dev_priv->swaps_lock, "swap");
+	DRM_SPININIT(&dev_priv->user_irq_lock, "userirq");
 
 #ifdef __linux__
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
 	intel_init_chipset_flush_compat(dev);
 #endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
+	intel_opregion_init(dev);
 #endif
+#endif
+
+	/* Init HWS */
+	if (!I915_NEED_GFX_HWS(dev)) {
+		ret = i915_init_hardware_status(dev);
+		if(ret)
+			return ret;
+	}
 
 	return ret;
 }
@@ -1386,11 +1114,23 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->mmio_map)
-		drm_rmmap(dev, dev_priv->mmio_map);
+	i915_free_hardware_status(dev);
+
+    	drm_rmmap(dev, dev_priv->mmio_map);
+
+	DRM_SPINUNINIT(&dev_priv->swaps_lock);
+	DRM_SPINUNINIT(&dev_priv->user_irq_lock);
+
+#ifdef __linux__
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
+	intel_opregion_free(dev);
+#endif
+#endif
 
 	drm_free(dev->dev_private, sizeof(drm_i915_private_t),
 		 DRM_MEM_DRIVER);
+	dev->dev_private = NULL;
+
 #ifdef __linux__
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
 	intel_fini_chipset_flush_compat(dev);
@@ -1403,18 +1143,73 @@
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
+	/* agp off can use this to get called before dev_priv */
+	if (!dev_priv)
+		return;
+
+#ifdef I915_HAVE_BUFFER
+	if (dev_priv->val_bufs) {
+		vfree(dev_priv->val_bufs);
+		dev_priv->val_bufs = NULL;
+	}
+#endif
+#ifdef I915_HAVE_GEM
+	i915_gem_lastclose(dev);
+#endif
 	if (drm_getsarea(dev) && dev_priv->sarea_priv)
 		i915_do_cleanup_pageflip(dev);
+	if (dev_priv->sarea_priv)
+		dev_priv->sarea_priv = NULL;
 	if (dev_priv->agp_heap)
 		i915_mem_takedown(&(dev_priv->agp_heap));
+#if defined(I915_HAVE_BUFFER)
+	if (dev_priv->sarea_kmap.virtual) {
+		drm_bo_kunmap(&dev_priv->sarea_kmap);
+		dev_priv->sarea_kmap.virtual = NULL;
+		dev->lock.hw_lock = NULL;
+		dev->sigdata.lock = NULL;
+	}
 
+	if (dev_priv->sarea_bo) {
+		mutex_lock(&dev->struct_mutex);
+		drm_bo_usage_deref_locked(&dev_priv->sarea_bo);
+		mutex_unlock(&dev->struct_mutex);
+		dev_priv->sarea_bo = NULL;
+	}
+#endif
 	i915_dma_cleanup(dev);
+}
+
+int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct drm_i915_file_private *i915_file_priv;
+
+	DRM_DEBUG("\n");
+	i915_file_priv = (struct drm_i915_file_private *)
+	    drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
+
+	if (!i915_file_priv)
+		return -ENOMEM;
+
+	file_priv->driver_priv = i915_file_priv;
+
+	i915_file_priv->mm.last_gem_seqno = 0;
+	i915_file_priv->mm.last_gem_throttle_seqno = 0;
+
+	return 0;
 }
 
 void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	i915_mem_release(dev, file_priv, dev_priv->agp_heap);
+}
+
+void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
+
+	drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
 }
 
 struct drm_ioctl_desc i915_ioctls[] = {
@@ -1438,6 +1233,24 @@
 	DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 #ifdef I915_HAVE_BUFFER
 	DRM_IOCTL_DEF(DRM_I915_EXECBUFFER, i915_execbuffer, DRM_AUTH),
+#endif
+#ifdef I915_HAVE_GEM
+	DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
+	DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
 #endif
 };
 
diff --git a/sys/dev/drm/i915_drm.h b/sys/dev/drm/i915_drm.h
--- a/sys/dev/drm/i915_drm.h
+++ b/sys/dev/drm/i915_drm.h
@@ -44,7 +44,12 @@
 	enum {
 		I915_INIT_DMA = 0x01,
 		I915_CLEANUP_DMA = 0x02,
-		I915_RESUME_DMA = 0x03
+		I915_RESUME_DMA = 0x03,
+
+		/* Since this struct isn't versioned, just used a new
+		 * 'func' code to indicate the presence of dri2 sarea
+		 * info. */
+		I915_INIT_DMA2 = 0x04
 	} func;
 	unsigned int mmio_offset;
 	int sarea_priv_offset;
@@ -62,9 +67,10 @@
 	unsigned int depth_pitch;
 	unsigned int cpp;
 	unsigned int chipset;
+	unsigned int sarea_handle;
 } drm_i915_init_t;
 
-typedef struct _drm_i915_sarea {
+typedef struct drm_i915_sarea {
 	struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
 	int last_upload;	/* last time texture was uploaded */
 	int last_enqueue;	/* last time a buffer was enqueued */
@@ -120,6 +126,15 @@
 	int third_offset;
 	int third_size;
 	unsigned int third_tiled;
+
+	/* buffer object handles for the static buffers.  May change
+	 * over the lifetime of the client, though it doesn't in our current
+	 * implementation.
+	 */
+	unsigned int front_bo_handle;
+	unsigned int back_bo_handle;
+	unsigned int third_bo_handle;
+	unsigned int depth_bo_handle;
 } drm_i915_sarea_t;
 
 /* Driver specific fence types and classes.
@@ -162,6 +177,23 @@
 #define DRM_I915_MMIO		0x10
 #define DRM_I915_HWS_ADDR	0x11
 #define DRM_I915_EXECBUFFER	0x12
+#define DRM_I915_GEM_INIT	0x13
+#define DRM_I915_GEM_EXECBUFFER	0x14
+#define DRM_I915_GEM_PIN	0x15
+#define DRM_I915_GEM_UNPIN	0x16
+#define DRM_I915_GEM_BUSY	0x17
+#define DRM_I915_GEM_THROTTLE	0x18
+#define DRM_I915_GEM_ENTERVT	0x19
+#define DRM_I915_GEM_LEAVEVT	0x1a
+#define DRM_I915_GEM_CREATE	0x1b
+#define DRM_I915_GEM_PREAD	0x1c
+#define DRM_I915_GEM_PWRITE	0x1d
+#define DRM_I915_GEM_MMAP	0x1e
+#define DRM_I915_GEM_SET_DOMAIN	0x1f
+#define DRM_I915_GEM_SW_FINISH	0x20
+#define DRM_I915_GEM_SET_TILING	0x21
+#define DRM_I915_GEM_GET_TILING	0x22
+#define DRM_I915_GEM_GET_APERTURE 0x23
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -181,6 +213,23 @@
 #define DRM_IOCTL_I915_VBLANK_SWAP	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
 #define DRM_IOCTL_I915_MMIO             DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_MMIO, drm_i915_mmio)
 #define DRM_IOCTL_I915_EXECBUFFER	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_EXECBUFFER, struct drm_i915_execbuffer)
+#define DRM_IOCTL_I915_GEM_INIT		DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
+#define DRM_IOCTL_I915_GEM_PIN		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
+#define DRM_IOCTL_I915_GEM_UNPIN	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
+#define DRM_IOCTL_I915_GEM_BUSY		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
+#define DRM_IOCTL_I915_GEM_THROTTLE	DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
+#define DRM_IOCTL_I915_GEM_ENTERVT	DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
+#define DRM_IOCTL_I915_GEM_LEAVEVT	DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
+#define DRM_IOCTL_I915_GEM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create)
+#define DRM_IOCTL_I915_GEM_PREAD	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread)
+#define DRM_IOCTL_I915_GEM_PWRITE	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
+#define DRM_IOCTL_I915_GEM_MMAP		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
+#define DRM_IOCTL_I915_GEM_SET_DOMAIN	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
+#define DRM_IOCTL_I915_GEM_SW_FINISH	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
+#define DRM_IOCTL_I915_GEM_SET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
+#define DRM_IOCTL_I915_GEM_GET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
+#define DRM_IOCTL_I915_GEM_GET_APERTURE	DRM_IOR  (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
 
 /* Asynchronous page flipping:
  */
@@ -197,7 +246,7 @@
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
  */
-typedef struct _drm_i915_batchbuffer {
+typedef struct drm_i915_batchbuffer {
 	int start;		/* agp offset */
 	int used;		/* nr bytes in use */
 	int DR1;		/* hw flags for GFX_OP_DRAWRECT_INFO */
@@ -233,6 +282,8 @@
 #define I915_PARAM_IRQ_ACTIVE            1
 #define I915_PARAM_ALLOW_BATCHBUFFER     2
 #define I915_PARAM_LAST_DISPATCH         3
+#define I915_PARAM_CHIPSET_ID            4
+#define I915_PARAM_HAS_GEM               5
 
 typedef struct drm_i915_getparam {
 	int param;
@@ -330,9 +381,9 @@
 
 /*
  * Relocation header is 4 uint32_ts
- * 0 - (16-bit relocation type << 16)| 16 bit reloc count
- * 1 - buffer handle for another list of relocs
- * 2-3 - spare.
+ * 0 - 32 bit reloc count
+ * 1 - 32-bit relocation type
+ * 2-3 - 64-bit user buffer handle ptr for another list of relocs.
  */
 #define I915_RELOC_HEADER 4
 
@@ -340,16 +391,31 @@
  * type 0 relocation has 4-uint32_t stride
  * 0 - offset into buffer
  * 1 - delta to add in
- * 2 - index into buffer list
+ * 2 - buffer handle
  * 3 - reserved (for optimisations later).
+ */
+/*
+ * type 1 relocation has 4-uint32_t stride.
+ * Hangs off the first item in the op list.
+ * Performed after all valiations are done.
+ * Try to group relocs into the same relocatee together for
+ * performance reasons.
+ * 0 - offset into buffer
+ * 1 - delta to add in
+ * 2 - buffer index in op list.
+ * 3 - relocatee index in op list.
  */
 #define I915_RELOC_TYPE_0 0
 #define I915_RELOC0_STRIDE 4
+#define I915_RELOC_TYPE_1 1
+#define I915_RELOC1_STRIDE 4
+
 
 struct drm_i915_op_arg {
 	uint64_t next;
-	uint32_t reloc_handle;
+	uint64_t reloc_ptr;
 	int handled;
+	unsigned int pad64;
 	union {
 		struct drm_bo_op_req req;
 		struct drm_bo_arg_rep rep;
@@ -360,9 +426,308 @@
 struct drm_i915_execbuffer {
 	uint64_t ops_list;
 	uint32_t num_buffers;
-	struct _drm_i915_batchbuffer batch;
+	struct drm_i915_batchbuffer batch;
 	drm_context_t context; /* for lockless use in the future */
 	struct drm_fence_arg fence_arg;
 };
 
+struct drm_i915_gem_init {
+	/**
+	 * Beginning offset in the GTT to be managed by the DRM memory
+	 * manager.
+	 */
+	uint64_t gtt_start;
+	/**
+	 * Ending offset in the GTT to be managed by the DRM memory
+	 * manager.
+	 */
+	uint64_t gtt_end;
+};
+
+struct drm_i915_gem_create {
+	/**
+	 * Requested size for the object.
+	 *
+	 * The (page-aligned) allocated size for the object will be returned.
+	 */
+	uint64_t size;
+	/**
+	 * Returned handle for the object.
+	 *
+	 * Object handles are nonzero.
+	 */
+	uint32_t handle;
+	uint32_t pad;
+};
+
+struct drm_i915_gem_pread {
+	/** Handle for the object being read. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset into the object to read from */
+	uint64_t offset;
+	/** Length of data to read */
+	uint64_t size;
+	/** Pointer to write the data into. */
+	uint64_t data_ptr;	/* void *, but pointers are not 32/64 compatible */
+};
+
+struct drm_i915_gem_pwrite {
+	/** Handle for the object being written to. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset into the object to write to */
+	uint64_t offset;
+	/** Length of data to write */
+	uint64_t size;
+	/** Pointer to read the data from. */
+	uint64_t data_ptr;	/* void *, but pointers are not 32/64 compatible */
+};
+
+struct drm_i915_gem_mmap {
+	/** Handle for the object being mapped. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset in the object to map. */
+	uint64_t offset;
+	/**
+	 * Length of data to map.
+	 *
+	 * The value will be page-aligned.
+	 */
+	uint64_t size;
+	/** Returned pointer the data was mapped at */
+	uint64_t addr_ptr;	/* void *, but pointers are not 32/64 compatible */
+};
+
+struct drm_i915_gem_set_domain {
+	/** Handle for the object */
+	uint32_t handle;
+
+	/** New read domains */
+	uint32_t read_domains;
+
+	/** New write domain */
+	uint32_t write_domain;
+};
+
+struct drm_i915_gem_sw_finish {
+	/** Handle for the object */
+	uint32_t handle;
+};
+
+struct drm_i915_gem_relocation_entry {
+	/**
+	 * Handle of the buffer being pointed to by this relocation entry.
+	 *
+	 * It's appealing to make this be an index into the mm_validate_entry
+	 * list to refer to the buffer, but this allows the driver to create
+	 * a relocation list for state buffers and not re-write it per
+	 * exec using the buffer.
+	 */
+	uint32_t target_handle;
+
+	/**
+	 * Value to be added to the offset of the target buffer to make up
+	 * the relocation entry.
+	 */
+	uint32_t delta;
+
+	/** Offset in the buffer the relocation entry will be written into */
+	uint64_t offset;
+
+	/**
+	 * Offset value of the target buffer that the relocation entry was last
+	 * written as.
+	 *
+	 * If the buffer has the same offset as last time, we can skip syncing
+	 * and writing the relocation.  This value is written back out by
+	 * the execbuffer ioctl when the relocation is written.
+	 */
+	uint64_t presumed_offset;
+
+	/**
+	 * Target memory domains read by this operation.
+	 */
+	uint32_t read_domains;
+
+	/**
+	 * Target memory domains written by this operation.
+	 *
+	 * Note that only one domain may be written by the whole
+	 * execbuffer operation, so that where there are conflicts,
+	 * the application will get -EINVAL back.
+	 */
+	uint32_t write_domain;
+};
+
+/** @{
+ * Intel memory domains
+ *
+ * Most of these just align with the various caches in
+ * the system and are used to flush and invalidate as
+ * objects end up cached in different domains.
+ */
+/** CPU cache */
+#define I915_GEM_DOMAIN_CPU		0x00000001
+/** Render cache, used by 2D and 3D drawing */
+#define I915_GEM_DOMAIN_RENDER		0x00000002
+/** Sampler cache, used by texture engine */
+#define I915_GEM_DOMAIN_SAMPLER		0x00000004
+/** Command queue, used to load batch buffers */
+#define I915_GEM_DOMAIN_COMMAND		0x00000008
+/** Instruction cache, used by shader programs */
+#define I915_GEM_DOMAIN_INSTRUCTION	0x00000010
+/** Vertex address cache */
+#define I915_GEM_DOMAIN_VERTEX		0x00000020
+/** GTT domain - aperture and scanout */
+#define I915_GEM_DOMAIN_GTT		0x00000040
+/** @} */
+
+struct drm_i915_gem_exec_object {
+	/**
+	 * User's handle for a buffer to be bound into the GTT for this
+	 * operation.
+	 */
+	uint32_t handle;
+
+	/** Number of relocations to be performed on this buffer */
+	uint32_t relocation_count;
+	/**
+	 * Pointer to array of struct drm_i915_gem_relocation_entry containing
+	 * the relocations to be performed in this buffer.
+	 */
+	uint64_t relocs_ptr;
+
+	/** Required alignment in graphics aperture */
+	uint64_t alignment;
+
+	/**
+	 * Returned value of the updated offset of the object, for future
+	 * presumed_offset writes.
+	 */
+	uint64_t offset;
+};
+
+struct drm_i915_gem_execbuffer {
+	/**
+	 * List of buffers to be validated with their relocations to be
+	 * performend on them.
+	 *
+	 * This is a pointer to an array of struct drm_i915_gem_validate_entry.
+	 *
+	 * These buffers must be listed in an order such that all relocations
+	 * a buffer is performing refer to buffers that have already appeared
+	 * in the validate list.
+	 */
+	uint64_t buffers_ptr;
+	uint32_t buffer_count;
+
+	/** Offset in the batchbuffer to start execution from. */
+	uint32_t batch_start_offset;
+	/** Bytes used in batchbuffer from batch_start_offset */
+	uint32_t batch_len;
+	uint32_t DR1;
+	uint32_t DR4;
+	uint32_t num_cliprects;
+	uint64_t cliprects_ptr;	/* struct drm_clip_rect *cliprects */
+};
+
+struct drm_i915_gem_pin {
+	/** Handle of the buffer to be pinned. */
+	uint32_t handle;
+	uint32_t pad;
+
+	/** alignment required within the aperture */
+	uint64_t alignment;
+
+	/** Returned GTT offset of the buffer. */
+	uint64_t offset;
+};
+
+struct drm_i915_gem_unpin {
+	/** Handle of the buffer to be unpinned. */
+	uint32_t handle;
+	uint32_t pad;
+};
+
+struct drm_i915_gem_busy {
+	/** Handle of the buffer to check for busy */
+	uint32_t handle;
+
+	/** Return busy status (1 if busy, 0 if idle) */
+	uint32_t busy;
+};
+
+#define I915_TILING_NONE	0
+#define I915_TILING_X		1
+#define I915_TILING_Y		2
+
+#define I915_BIT_6_SWIZZLE_NONE		0
+#define I915_BIT_6_SWIZZLE_9		1
+#define I915_BIT_6_SWIZZLE_9_10		2
+#define I915_BIT_6_SWIZZLE_9_11		3
+#define I915_BIT_6_SWIZZLE_9_10_11	4
+/* Not seen by userland */
+#define I915_BIT_6_SWIZZLE_UNKNOWN	5
+
+struct drm_i915_gem_set_tiling {
+	/** Handle of the buffer to have its tiling state updated */
+	uint32_t handle;
+
+	/**
+	 * Tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
+	 * I915_TILING_Y).
+	 *
+	 * This value is to be set on request, and will be updated by the
+	 * kernel on successful return with the actual chosen tiling layout.
+	 *
+	 * The tiling mode may be demoted to I915_TILING_NONE when the system
+	 * has bit 6 swizzling that can't be managed correctly by GEM.
+	 *
+	 * Buffer contents become undefined when changing tiling_mode.
+	 */
+	uint32_t tiling_mode;
+
+	/**
+	 * Stride in bytes for the object when in I915_TILING_X or
+	 * I915_TILING_Y.
+	 */
+	uint32_t stride;
+
+	/**
+	 * Returned address bit 6 swizzling required for CPU access through
+	 * mmap mapping.
+	 */
+	uint32_t swizzle_mode;
+};
+
+struct drm_i915_gem_get_tiling {
+	/** Handle of the buffer to get tiling state for. */
+	uint32_t handle;
+
+	/**
+	 * Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
+	 * I915_TILING_Y).
+	 */
+	uint32_t tiling_mode;
+
+	/**
+	 * Returned address bit 6 swizzling required for CPU access through
+	 * mmap mapping.
+	 */
+	uint32_t swizzle_mode;
+};
+
+struct drm_i915_gem_get_aperture {
+	/** Total size of the aperture used by i915_gem_execbuffer, in bytes */
+	uint64_t aper_size;
+
+	/**
+	 * Available space in the aperture used by i915_gem_execbuffer, in
+	 * bytes
+	 */
+	uint64_t aper_available_size;
+};
+
 #endif				/* _I915_DRM_H_ */
diff --git a/sys/dev/drm/i915_drv.c b/sys/dev/drm/i915_drv.c
--- a/sys/dev/drm/i915_drv.c
+++ b/sys/dev/drm/i915_drv.c
@@ -41,39 +41,64 @@
 	i915_PCI_IDS
 };
 
-static void i915_configure(drm_device_t *dev)
+static int i915_suspend(device_t nbdev)
 {
-	dev->driver.buf_priv_size	= 1;	/* No dev_priv */
-	dev->driver.load		= i915_driver_load;
-	dev->driver.preclose		= i915_driver_preclose;
-	dev->driver.lastclose		= i915_driver_lastclose;
-	dev->driver.device_is_agp	= i915_driver_device_is_agp;
-	dev->driver.vblank_wait		= i915_driver_vblank_wait;
-	dev->driver.vblank_wait2	= i915_driver_vblank_wait2;
-	dev->driver.irq_preinstall	= i915_driver_irq_preinstall;
-	dev->driver.irq_postinstall	= i915_driver_irq_postinstall;
-	dev->driver.irq_uninstall	= i915_driver_irq_uninstall;
-	dev->driver.irq_handler		= i915_driver_irq_handler;
+	struct drm_device *dev = device_get_softc(nbdev);
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	dev->driver.ioctls		= i915_ioctls;
-	dev->driver.max_ioctl		= i915_max_ioctl;
+	if (!dev || !dev_priv) {
+		DRM_ERROR("dev: 0x%lx, dev_priv: 0x%lx\n",
+			(unsigned long) dev, (unsigned long) dev_priv);
+		DRM_ERROR("DRM not initialized, aborting suspend.\n");
+		return -ENODEV;
+	}
 
-	dev->driver.name		= DRIVER_NAME;
-	dev->driver.desc		= DRIVER_DESC;
-	dev->driver.date		= DRIVER_DATE;
-	dev->driver.major		= DRIVER_MAJOR;
-	dev->driver.minor		= DRIVER_MINOR;
-	dev->driver.patchlevel		= DRIVER_PATCHLEVEL;
+	i915_save_state(dev);
 
-	dev->driver.use_agp		= 1;
-	dev->driver.require_agp		= 1;
-	dev->driver.use_mtrr		= 1;
-	dev->driver.use_irq		= 1;
-	dev->driver.use_vbl_irq		= 1;
-	dev->driver.use_vbl_irq2	= 1;
+	return (bus_generic_suspend(nbdev));
 }
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+static int i915_resume(device_t nbdev)
+{
+	struct drm_device *dev = device_get_softc(nbdev);
+
+	i915_restore_state(dev);
+
+	return (bus_generic_resume(nbdev));
+}
+
+static void i915_configure(struct drm_device *dev)
+{
+	dev->driver->driver_features =
+	   DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+	   DRIVER_HAVE_IRQ;
+
+	dev->driver->buf_priv_size	= sizeof(drm_i915_private_t);
+	dev->driver->load		= i915_driver_load;
+	dev->driver->unload		= i915_driver_unload;
+	dev->driver->firstopen		= i915_driver_firstopen;
+	dev->driver->preclose		= i915_driver_preclose;
+	dev->driver->lastclose		= i915_driver_lastclose;
+	dev->driver->device_is_agp	= i915_driver_device_is_agp;
+	dev->driver->get_vblank_counter	= i915_get_vblank_counter;
+	dev->driver->enable_vblank	= i915_enable_vblank;
+	dev->driver->disable_vblank	= i915_disable_vblank;
+	dev->driver->irq_preinstall	= i915_driver_irq_preinstall;
+	dev->driver->irq_postinstall	= i915_driver_irq_postinstall;
+	dev->driver->irq_uninstall	= i915_driver_irq_uninstall;
+	dev->driver->irq_handler	= i915_driver_irq_handler;
+
+	dev->driver->ioctls		= i915_ioctls;
+	dev->driver->max_ioctl		= i915_max_ioctl;
+
+	dev->driver->name		= DRIVER_NAME;
+	dev->driver->desc		= DRIVER_DESC;
+	dev->driver->date		= DRIVER_DATE;
+	dev->driver->major		= DRIVER_MAJOR;
+	dev->driver->minor		= DRIVER_MINOR;
+	dev->driver->patchlevel		= DRIVER_PATCHLEVEL;
+}
+
 static int
 i915_probe(device_t dev)
 {
@@ -83,18 +108,36 @@
 static int
 i915_attach(device_t nbdev)
 {
-	drm_device_t *dev = device_get_softc(nbdev);
+	struct drm_device *dev = device_get_softc(nbdev);
 
-	bzero(dev, sizeof(drm_device_t));
+	dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
+	    M_WAITOK | M_ZERO);
+
 	i915_configure(dev);
+
 	return drm_attach(nbdev, i915_pciidlist);
+}
+
+static int
+i915_detach(device_t nbdev)
+{
+	struct drm_device *dev = device_get_softc(nbdev);
+	int ret;
+
+	ret = drm_detach(nbdev);
+
+	free(dev->driver, DRM_MEM_DRIVER);
+
+	return ret;
 }
 
 static device_method_t i915_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		i915_probe),
 	DEVMETHOD(device_attach,	i915_attach),
-	DEVMETHOD(device_detach,	drm_detach),
+	DEVMETHOD(device_suspend,	i915_suspend),
+	DEVMETHOD(device_resume,	i915_resume),
+	DEVMETHOD(device_detach,	i915_detach),
 
 	{ 0, 0 }
 };
@@ -106,7 +149,7 @@
 	"drmsub",
 #endif
 	i915_methods,
-	sizeof(drm_device_t)
+	sizeof(struct drm_device)
 };
 
 extern devclass_t drm_devclass;
@@ -116,7 +159,3 @@
 DRIVER_MODULE(i915, agp, i915_driver, drm_devclass, 0, 0);
 #endif
 MODULE_DEPEND(i915, drm, 1, 1, 1);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-CFDRIVER_DECL(i915, DV_TTY, NULL);
-#endif
diff --git a/sys/dev/drm/i915_drv.h b/sys/dev/drm/i915_drv.h
--- a/sys/dev/drm/i915_drv.h
+++ b/sys/dev/drm/i915_drv.h
@@ -38,11 +38,12 @@
 
 #define DRIVER_NAME		"i915"
 #define DRIVER_DESC		"Intel Graphics"
-#define DRIVER_DATE		"20070209"
+#define DRIVER_DATE		"20080730"
 
 #if defined(__linux__)
 #define I915_HAVE_FENCE
 #define I915_HAVE_BUFFER
+#define I915_HAVE_GEM
 #endif
 
 /* Interface history:
@@ -62,26 +63,39 @@
  */
 #define DRIVER_MAJOR		1
 #if defined(I915_HAVE_FENCE) && defined(I915_HAVE_BUFFER)
-#define DRIVER_MINOR		12
+#define DRIVER_MINOR		13
 #else
 #define DRIVER_MINOR		6
 #endif
 #define DRIVER_PATCHLEVEL	0
 
+enum i915_pipe {
+    PIPE_A = 0,
+    PIPE_B,
+};
+
 #ifdef I915_HAVE_BUFFER
 #define I915_MAX_VALIDATE_BUFFERS 4096
+struct drm_i915_validate_buffer;
 #endif
+
+#define WATCH_COHERENCY	0
+#define WATCH_BUF	0
+#define WATCH_EXEC	0
+#define WATCH_LRU	0
+#define WATCH_RELOC	0
+#define WATCH_INACTIVE	0
+#define WATCH_PWRITE	0
 
 typedef struct _drm_i915_ring_buffer {
 	int tail_mask;
-	unsigned long Start;
-	unsigned long End;
 	unsigned long Size;
 	u8 *virtual_start;
 	int head;
 	int tail;
 	int space;
 	drm_local_map_t map;
+	struct drm_gem_object *ring_obj;
 } drm_i915_ring_buffer_t;
 
 struct mem_block {
@@ -100,7 +114,25 @@
 	int flip;
 } drm_i915_vbl_swap_t;
 
+#ifdef __linux__
+struct opregion_header;
+struct opregion_acpi;
+struct opregion_swsci;
+struct opregion_asle;
+
+struct intel_opregion {
+	struct opregion_header *header;
+	struct opregion_acpi *acpi;
+	struct opregion_swsci *swsci;
+	struct opregion_asle *asle;
+
+	int enabled;
+};
+#endif
+
 typedef struct drm_i915_private {
+	struct drm_device *dev;
+
 	drm_local_map_t *sarea;
 	drm_local_map_t *mmio_map;
 
@@ -113,13 +145,12 @@
 	uint32_t counter;
 	unsigned int status_gfx_addr;
 	drm_local_map_t hws_map;
+	struct drm_gem_object *hws_obj;
 
 	unsigned int cpp;
-	int use_mi_batchbuffer_start;
 
 	wait_queue_head_t irq_queue;
 	atomic_t irq_received;
-	atomic_t irq_emitted;
 
 	int tex_lru_log_granularity;
 	int allow_batchbuffer;
@@ -129,7 +160,7 @@
 	DRM_SPINTYPE user_irq_lock;
 	int user_irq_refcount;
 	int fence_irq_on;
-	uint32_t irq_enable_reg;
+	uint32_t irq_mask_reg;
 	int irq_enabled;
 
 #ifdef I915_HAVE_FENCE
@@ -142,16 +173,27 @@
 	void *agp_iomap;
 	unsigned int max_validate_buffers;
 	struct mutex cmdbuf_mutex;
+	struct drm_i915_validate_buffer *val_bufs;
 #endif
 
 	DRM_SPINTYPE swaps_lock;
 	drm_i915_vbl_swap_t vbl_swaps;
 	unsigned int swaps_pending;
+#if defined(I915_HAVE_BUFFER)
+	/* DRI2 sarea */
+	struct drm_buffer_object *sarea_bo;
+	struct drm_bo_kmap_obj sarea_kmap;
+#endif
+
+#ifdef __linux__
+	struct intel_opregion opregion;
+#endif
 
 	/* Register state */
 	u8 saveLBB;
 	u32 saveDSPACNTR;
 	u32 saveDSPBCNTR;
+	u32 saveDSPARB;
 	u32 savePIPEACONF;
 	u32 savePIPEBCONF;
 	u32 savePIPEASRC;
@@ -167,10 +209,11 @@
 	u32 saveVBLANK_A;
 	u32 saveVSYNC_A;
 	u32 saveBCLRPAT_A;
+	u32 savePIPEASTAT;
 	u32 saveDSPASTRIDE;
 	u32 saveDSPASIZE;
 	u32 saveDSPAPOS;
-	u32 saveDSPABASE;
+	u32 saveDSPAADDR;
 	u32 saveDSPASURF;
 	u32 saveDSPATILEOFF;
 	u32 savePFIT_PGM_RATIOS;
@@ -187,27 +230,28 @@
 	u32 saveVBLANK_B;
 	u32 saveVSYNC_B;
 	u32 saveBCLRPAT_B;
+	u32 savePIPEBSTAT;
 	u32 saveDSPBSTRIDE;
 	u32 saveDSPBSIZE;
 	u32 saveDSPBPOS;
-	u32 saveDSPBBASE;
+	u32 saveDSPBADDR;
 	u32 saveDSPBSURF;
 	u32 saveDSPBTILEOFF;
-	u32 saveVCLK_DIVISOR_VGA0;
-	u32 saveVCLK_DIVISOR_VGA1;
-	u32 saveVCLK_POST_DIV;
+	u32 saveVGA0;
+	u32 saveVGA1;
+	u32 saveVGA_PD;
 	u32 saveVGACNTRL;
 	u32 saveADPA;
 	u32 saveLVDS;
-	u32 saveLVDSPP_ON;
-	u32 saveLVDSPP_OFF;
+	u32 savePP_ON_DELAYS;
+	u32 savePP_OFF_DELAYS;
 	u32 saveDVOA;
 	u32 saveDVOB;
 	u32 saveDVOC;
 	u32 savePP_ON;
 	u32 savePP_OFF;
 	u32 savePP_CONTROL;
-	u32 savePP_CYCLE;
+	u32 savePP_DIVISOR;
 	u32 savePFIT_CONTROL;
 	u32 save_palette_a[256];
 	u32 save_palette_b[256];
@@ -215,24 +259,198 @@
 	u32 saveFBC_LL_BASE;
 	u32 saveFBC_CONTROL;
 	u32 saveFBC_CONTROL2;
+	u32 saveIER;
+	u32 saveIIR;
+	u32 saveIMR;
+	u32 saveCACHE_MODE_0;
+	u32 saveD_STATE;
+	u32 saveCG_2D_DIS;
+	u32 saveMI_ARB_STATE;
 	u32 saveSWF0[16];
 	u32 saveSWF1[16];
 	u32 saveSWF2[3];
 	u8 saveMSR;
 	u8 saveSR[8];
-	u8 saveGR[24];
+	u8 saveGR[25];
 	u8 saveAR_INDEX;
-	u8 saveAR[20];
+	u8 saveAR[21];
 	u8 saveDACMASK;
 	u8 saveDACDATA[256*3]; /* 256 3-byte colors */
-	u8 saveCR[36];
+	u8 saveCR[37];
+
+	struct {
+#ifdef __linux__
+		struct drm_mm gtt_space;
+#endif
+		/**
+		 * List of objects currently involved in rendering from the
+		 * ringbuffer.
+		 *
+		 * A reference is held on the buffer while on this list.
+		 */
+		struct list_head active_list;
+
+		/**
+		 * List of objects which are not in the ringbuffer but which
+		 * still have a write_domain which needs to be flushed before
+		 * unbinding.
+		 *
+		 * A reference is held on the buffer while on this list.
+		 */
+		struct list_head flushing_list;
+
+		/**
+		 * LRU list of objects which are not in the ringbuffer and
+		 * are ready to unbind, but are still in the GTT.
+		 *
+		 * A reference is not held on the buffer while on this list,
+		 * as merely being GTT-bound shouldn't prevent its being
+		 * freed, and we'll pull it off the list in the free path.
+		 */
+		struct list_head inactive_list;
+
+		/**
+		 * List of breadcrumbs associated with GPU requests currently
+		 * outstanding.
+		 */
+		struct list_head request_list;
+#ifdef __linux__
+		/**
+		 * We leave the user IRQ off as much as possible,
+		 * but this means that requests will finish and never
+		 * be retired once the system goes idle. Set a timer to
+		 * fire periodically while the ring is running. When it
+		 * fires, go retire requests.
+		 */
+		struct delayed_work retire_work;
+#endif
+		uint32_t next_gem_seqno;
+
+		/**
+		 * Waiting sequence number, if any
+		 */
+		uint32_t waiting_gem_seqno;
+
+		/**
+		 * Last seq seen at irq time
+		 */
+		uint32_t irq_gem_seqno;
+
+		/**
+		 * Flag if the X Server, and thus DRM, is not currently in
+		 * control of the device.
+		 *
+		 * This is set between LeaveVT and EnterVT.  It needs to be
+		 * replaced with a semaphore.  It also needs to be
+		 * transitioned away from for kernel modesetting.
+		 */
+		int suspended;
+
+		/**
+		 * Flag if the hardware appears to be wedged.
+		 *
+		 * This is set when attempts to idle the device timeout.
+		 * It prevents command submission from occuring and makes
+		 * every pending request fail
+		 */
+		int wedged;
+
+		/** Bit 6 swizzling required for X tiling */
+		uint32_t bit_6_swizzle_x;
+		/** Bit 6 swizzling required for Y tiling */
+		uint32_t bit_6_swizzle_y;
+	} mm;
 } drm_i915_private_t;
+
+struct drm_i915_file_private {
+	struct {
+		uint32_t last_gem_seqno;
+		uint32_t last_gem_throttle_seqno;
+	} mm;
+};
 
 enum intel_chip_family {
 	CHIP_I8XX = 0x01,
 	CHIP_I9XX = 0x02,
 	CHIP_I915 = 0x04,
 	CHIP_I965 = 0x08,
+};
+
+/** driver private structure attached to each drm_gem_object */
+struct drm_i915_gem_object {
+	struct drm_gem_object *obj;
+
+	/** Current space allocated to this object in the GTT, if any. */
+	struct drm_mm_node *gtt_space;
+
+	/** This object's place on the active/flushing/inactive lists */
+	struct list_head list;
+
+	/**
+	 * This is set if the object is on the active or flushing lists
+	 * (has pending rendering), and is not set if it's on inactive (ready
+	 * to be unbound).
+	 */
+	int active;
+
+	/**
+	 * This is set if the object has been written to since last bound
+	 * to the GTT
+	 */
+	int dirty;
+
+	/** AGP memory structure for our GTT binding. */
+	DRM_AGP_MEM *agp_mem;
+
+	struct page **page_list;
+
+	/**
+	 * Current offset of the object in GTT space.
+	 *
+	 * This is the same as gtt_space->start
+	 */
+	uint32_t gtt_offset;
+
+	/** Boolean whether this object has a valid gtt offset. */
+	int gtt_bound;
+
+	/** How many users have pinned this object in GTT space */
+	int pin_count;
+
+	/** Breadcrumb of last rendering to the buffer. */
+	uint32_t last_rendering_seqno;
+
+	/** Current tiling mode for the object. */
+	uint32_t tiling_mode;
+
+	/**
+	 * Flagging of which individual pages are valid in GEM_DOMAIN_CPU when
+	 * GEM_DOMAIN_CPU is not in the object's read domain.
+	 */
+	uint8_t *page_cpu_valid;
+};
+
+/**
+ * Request queue structure.
+ *
+ * The request queue allows us to note sequence numbers that have been emitted
+ * and may be associated with active buffers to be retired.
+ *
+ * By keeping this list, we can avoid having to do questionable
+ * sequence-number comparisons on buffer last_rendering_seqnos, and associate
+ * an emission time with seqnos for tracking how far ahead of the GPU we are.
+ */
+struct drm_i915_gem_request {
+	/** GEM sequence number associated with this request. */
+	uint32_t seqno;
+
+	/** Time at which this request was emitted, in jiffies. */
+	unsigned long emitted_jiffies;
+
+	/** Cache domains that were flushed at the start of the request. */
+	uint32_t flush_domains;
+
+	struct list_head list;
 };
 
 extern struct drm_ioctl_desc i915_ioctls[];
@@ -243,8 +461,11 @@
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
 extern int i915_driver_unload(struct drm_device *);
 extern void i915_driver_lastclose(struct drm_device * dev);
+extern int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv);
 extern void i915_driver_preclose(struct drm_device *dev,
 				 struct drm_file *file_priv);
+extern void i915_driver_postclose(struct drm_device *dev,
+				  struct drm_file *file_priv);
 extern int i915_driver_device_is_agp(struct drm_device * dev);
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
 			      unsigned long arg);
@@ -252,6 +473,15 @@
 extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync);
 extern int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush);
 extern int i915_driver_firstopen(struct drm_device *dev);
+extern int i915_dispatch_batchbuffer(struct drm_device * dev,
+				     drm_i915_batchbuffer_t * batch);
+extern int i915_quiescent(struct drm_device *dev);
+extern int i915_init_hardware_status(struct drm_device *dev);
+extern void i915_free_hardware_status(struct drm_device *dev);
+
+int i915_emit_box(struct drm_device * dev,
+		  struct drm_clip_rect __user * boxes,
+		  int i, int DR1, int DR4);
 
 /* i915_irq.c */
 extern int i915_irq_emit(struct drm_device *dev, void *data,
@@ -259,21 +489,23 @@
 extern int i915_irq_wait(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 
-extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
 extern void i915_driver_irq_preinstall(struct drm_device * dev);
-extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern int i915_driver_irq_postinstall(struct drm_device * dev);
 extern void i915_driver_irq_uninstall(struct drm_device * dev);
 extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
 extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
-extern int i915_emit_irq(struct drm_device *dev);
+extern int i915_emit_irq(struct drm_device * dev);
+extern int i915_wait_irq(struct drm_device * dev, int irq_nr);
+extern int i915_enable_vblank(struct drm_device *dev, int crtc);
+extern void i915_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int i915_vblank_swap(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
 extern void i915_user_irq_on(drm_i915_private_t *dev_priv);
 extern void i915_user_irq_off(drm_i915_private_t *dev_priv);
-extern int i915_vblank_swap(struct drm_device *dev, void *data,
-			    struct drm_file *file_priv);
 
 /* i915_mem.c */
 extern int i915_mem_alloc(struct drm_device *dev, void *data,
@@ -288,17 +520,16 @@
 extern void i915_mem_release(struct drm_device * dev,
 			     struct drm_file *file_priv,
 			     struct mem_block *heap);
+
+/* i915_suspend.c */
+extern int i915_save_state(struct drm_device *dev);
+extern int i915_restore_state(struct drm_device *dev);
+
 #ifdef I915_HAVE_FENCE
 /* i915_fence.c */
+extern void i915_fence_handler(struct drm_device *dev);
+extern void i915_invalidate_reported_sequence(struct drm_device *dev);
 
-
-extern void i915_fence_handler(struct drm_device *dev);
-extern int i915_fence_emit_sequence(struct drm_device *dev, uint32_t class,
-				    uint32_t flags,
-				    uint32_t *sequence,
-				    uint32_t *native_type);
-extern void i915_poke_flush(struct drm_device *dev, uint32_t class);
-extern int i915_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags);
 #endif
 
 #ifdef I915_HAVE_BUFFER
@@ -313,6 +544,76 @@
 extern int i915_move(struct drm_buffer_object *bo, int evict,
 		int no_wait, struct drm_bo_mem_reg *new_mem);
 void i915_flush_ttm(struct drm_ttm *ttm);
+/* i915_execbuf.c */
+int i915_execbuffer(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv);
+/* i915_gem.c */
+int i915_gem_init_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_create_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv);
+int i915_gem_pread_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv);
+int i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
+int i915_gem_execbuffer(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_pin_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv);
+int i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
+int i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+int i915_gem_set_tiling(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+int i915_gem_get_tiling(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
+void i915_gem_load(struct drm_device *dev);
+int i915_gem_proc_init(struct drm_minor *minor);
+void i915_gem_proc_cleanup(struct drm_minor *minor);
+int i915_gem_init_object(struct drm_gem_object *obj);
+void i915_gem_free_object(struct drm_gem_object *obj);
+int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
+void i915_gem_object_unpin(struct drm_gem_object *obj);
+void i915_gem_lastclose(struct drm_device *dev);
+uint32_t i915_get_gem_seqno(struct drm_device *dev);
+void i915_gem_retire_requests(struct drm_device *dev);
+void i915_gem_retire_work_handler(struct work_struct *work);
+void i915_gem_clflush_object(struct drm_gem_object *obj);
+#endif
+
+/* i915_gem_tiling.c */
+void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
+
+/* i915_gem_debug.c */
+#if WATCH_INACTIVE
+void i915_verify_inactive(struct drm_device *dev, char *file, int line);
+#else
+#define i915_verify_inactive(dev,file,line)
+#endif
+void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle);
+void i915_gem_dump_object(struct drm_gem_object *obj, int len,
+			  const char *where, uint32_t mark);
+void i915_dump_lru(struct drm_device *dev, const char *where);
+
+#ifdef __linux__
+/* i915_opregion.c */
+extern int intel_opregion_init(struct drm_device *dev);
+extern void intel_opregion_free(struct drm_device *dev);
+extern void opregion_asle_intr(struct drm_device *dev);
+extern void opregion_enable_asle(struct drm_device *dev);
 #endif
 
 #ifdef __linux__
@@ -326,16 +627,33 @@
 #define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
 #define I915_READ16(reg)	DRM_READ16(dev_priv->mmio_map, (reg))
 #define I915_WRITE16(reg,val)	DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
+#define I915_READ8(reg)		DRM_READ8(dev_priv->mmio_map, (reg))
+#define I915_WRITE8(reg,val)	DRM_WRITE8(dev_priv->mmio_map, (reg), (val))
+
+#if defined(__FreeBSD__)
+typedef boolean_t bool;
+#endif
 
 #define I915_VERBOSE 0
+#define I915_RING_VALIDATE 0
+
+#define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
 #define RING_LOCALS	unsigned int outring, ringmask, outcount; \
 			volatile char *virt;
+
+#if I915_RING_VALIDATE
+void i915_ring_validate(struct drm_device *dev, const char *func, int line);
+#define I915_RING_DO_VALIDATE(dev) i915_ring_validate(dev, __FUNCTION__, __LINE__)
+#else
+#define I915_RING_DO_VALIDATE(dev)
+#endif
 
 #define BEGIN_LP_RING(n) do {				\
 	if (I915_VERBOSE)				\
 		DRM_DEBUG("BEGIN_LP_RING(%d)\n",	\
 	                         (n));		        \
+	I915_RING_DO_VALIDATE(dev);			\
 	if (dev_priv->ring.space < (n)*4)                      \
 		i915_wait_ring(dev, (n)*4, __FUNCTION__);      \
 	outcount = 0;					\
@@ -354,15 +672,82 @@
 
 #define ADVANCE_LP_RING() do {						\
 	if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring);	\
+	I915_RING_DO_VALIDATE(dev);					\
 	dev_priv->ring.tail = outring;					\
 	dev_priv->ring.space -= outcount * 4;				\
-	I915_WRITE(LP_RING + RING_TAIL, outring);			\
+	I915_WRITE(PRB0_TAIL, outring);			\
 } while(0)
 
 extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
-/* Extended config space */
-#define LBB 0xf4
+#define BREADCRUMB_BITS 31
+#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
+
+#define READ_BREADCRUMB(dev_priv)  (((volatile u32*)(dev_priv->hw_status_page))[5])
+/**
+ * Reads a dword out of the status page, which is written to from the command
+ * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
+ * MI_STORE_DATA_IMM.
+ *
+ * The following dwords have a reserved meaning:
+ * 0: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
+ * 4: ring 0 head pointer
+ * 5: ring 1 head pointer (915-class)
+ * 6: ring 2 head pointer (915-class)
+ *
+ * The area from dword 0x10 to 0x3ff is available for driver usage.
+ */
+#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
+#define I915_GEM_HWS_INDEX		0x10
+
+/* MCH MMIO space */
+/** 915-945 and GM965 MCH register controlling DRAM channel access */
+#define DCC		0x200
+#define DCC_ADDRESSING_MODE_SINGLE_CHANNEL		(0 << 0)
+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC	(1 << 0)
+#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED	(2 << 0)
+#define DCC_ADDRESSING_MODE_MASK			(3 << 0)
+#define DCC_CHANNEL_XOR_DISABLE				(1 << 10)
+
+/** 965 MCH register controlling DRAM channel configuration */
+#define CHDECMISC		0x111
+#define CHDECMISC_FLEXMEMORY		(1 << 1)
+
+/*
+ * The Bridge device's PCI config space has information about the
+ * fb aperture size and the amount of pre-reserved memory.
+ */
+#define INTEL_GMCH_CTRL		0x52
+#define INTEL_GMCH_ENABLED	0x4
+#define INTEL_GMCH_MEM_MASK	0x1
+#define INTEL_GMCH_MEM_64M	0x1
+#define INTEL_GMCH_MEM_128M	0
+
+#define INTEL_855_GMCH_GMS_MASK		(0x7 << 4)
+#define INTEL_855_GMCH_GMS_DISABLED	(0x0 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_1M	(0x1 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_4M	(0x2 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_8M	(0x3 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_16M	(0x4 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_32M	(0x5 << 4)
+
+#define INTEL_915G_GMCH_GMS_STOLEN_48M	(0x6 << 4)
+#define INTEL_915G_GMCH_GMS_STOLEN_64M	(0x7 << 4)
+
+/* PCI config space */
+
+#define HPLLCC	0xc0 /* 855 only */
+#define   GC_CLOCK_CONTROL_MASK		(3 << 0)
+#define   GC_CLOCK_133_200		(0 << 0)
+#define   GC_CLOCK_100_200		(1 << 0)
+#define   GC_CLOCK_100_133		(2 << 0)
+#define   GC_CLOCK_166_250		(3 << 0)
+#define GCFGC	0xf0 /* 915+ only */
+#define   GC_LOW_FREQUENCY_ENABLE	(1 << 7)
+#define   GC_DISPLAY_CLOCK_190_200_MHZ	(0 << 4)
+#define   GC_DISPLAY_CLOCK_333_MHZ	(4 << 4)
+#define   GC_DISPLAY_CLOCK_MASK		(7 << 4)
+#define LBB	0xf4
 
 /* VGA stuff */
 
@@ -405,29 +790,153 @@
 #define VGA_CR_INDEX_CGA 0x3d4
 #define VGA_CR_DATA_CGA 0x3d5
 
-#define GFX_OP_USER_INTERRUPT		((0<<29)|(2<<23))
-#define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
-#define CMD_REPORT_HEAD			(7<<23)
-#define CMD_STORE_DWORD_IDX		((0x21<<23) | 0x1)
-#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
+/*
+ * Memory interface instructions used by the kernel
+ */
+#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
 
-#define CMD_MI_FLUSH         (0x04 << 23)
-#define MI_NO_WRITE_FLUSH    (1 << 2)
-#define MI_READ_FLUSH        (1 << 0)
-#define MI_EXE_FLUSH         (1 << 1)
-#define MI_END_SCENE         (1 << 4) /* flush binner and incr scene count */
-#define MI_SCENE_COUNT       (1 << 3) /* just increment scene count */
+#define MI_NOOP			MI_INSTR(0, 0)
+#define MI_USER_INTERRUPT	MI_INSTR(0x02, 0)
+#define MI_WAIT_FOR_EVENT       MI_INSTR(0x03, 0)
+#define   MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
+#define   MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
+#define   MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+#define MI_FLUSH		MI_INSTR(0x04, 0)
+#define   MI_READ_FLUSH		(1 << 0)
+#define   MI_EXE_FLUSH		(1 << 1)
+#define   MI_NO_WRITE_FLUSH	(1 << 2)
+#define   MI_SCENE_COUNT	(1 << 3) /* just increment scene count */
+#define   MI_END_SCENE		(1 << 4) /* flush binner and incr scene count */
+#define MI_BATCH_BUFFER_END	MI_INSTR(0x0a, 0)
+#define MI_REPORT_HEAD		MI_INSTR(0x07, 0)
+#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
+#define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)
+#define   MI_MEM_VIRTUAL	(1 << 22) /* 965+ only */
+#define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
+#define   MI_STORE_DWORD_INDEX_SHIFT 2
+#define MI_LOAD_REGISTER_IMM	MI_INSTR(0x22, 1)
+#define MI_BATCH_BUFFER		MI_INSTR(0x30, 1)
+#define   MI_BATCH_NON_SECURE	(1)
+#define   MI_BATCH_NON_SECURE_I965 (1<<8)
+#define MI_BATCH_BUFFER_START	MI_INSTR(0x31, 0)
 
-/* Packet to load a register value from the ring/batch command stream:
+/*
+ * 3D instructions used by the kernel
  */
-#define CMD_MI_LOAD_REGISTER_IMM	((0x22 << 23)|0x1)
+#define GFX_INSTR(opcode, flags) ((0x3 << 29) | ((opcode) << 24) | (flags))
 
-#define BB1_START_ADDR_MASK   (~0x7)
-#define BB1_PROTECTED         (1<<0)
-#define BB1_UNPROTECTED       (0<<0)
-#define BB2_END_ADDR_MASK     (~0x7)
+#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define   SC_UPDATE_SCISSOR       (0x1<<1)
+#define   SC_ENABLE_MASK          (0x1<<0)
+#define   SC_ENABLE               (0x1<<0)
+#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define   SCI_YMIN_MASK      (0xffff<<16)
+#define   SCI_XMIN_MASK      (0xffff<<0)
+#define   SCI_YMAX_MASK      (0xffff<<16)
+#define   SCI_XMAX_MASK      (0xffff<<0)
+#define GFX_OP_SCISSOR_ENABLE	 ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define GFX_OP_SCISSOR_RECT	 ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+#define GFX_OP_DRAWRECT_INFO_I965  ((0x7900<<16)|0x2)
+#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
+#define XY_SRC_COPY_BLT_CMD		((2<<29)|(0x53<<22)|6)
+#define XY_MONO_SRC_COPY_IMM_BLT	((2<<29)|(0x71<<22)|5)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB	(1<<20)
+#define   BLT_DEPTH_8			(0<<24)
+#define   BLT_DEPTH_16_565		(1<<24)
+#define   BLT_DEPTH_16_1555		(2<<24)
+#define   BLT_DEPTH_32			(3<<24)
+#define   BLT_ROP_GXCOPY		(0xcc<<16)
+#define XY_SRC_COPY_BLT_SRC_TILED	(1<<15) /* 965+ only */
+#define XY_SRC_COPY_BLT_DST_TILED	(1<<11) /* 965+ only */
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define   ASYNC_FLIP                (1<<22)
+#define   DISPLAY_PLANE_A           (0<<20)
+#define   DISPLAY_PLANE_B           (1<<20)
 
-/* Framebuffer compression */
+/*
+ * Instruction and interrupt control regs
+ */
+
+#define PRB0_TAIL	0x02030
+#define PRB0_HEAD	0x02034
+#define PRB0_START	0x02038
+#define PRB0_CTL	0x0203c
+#define   TAIL_ADDR		0x001FFFF8
+#define   HEAD_WRAP_COUNT	0xFFE00000
+#define   HEAD_WRAP_ONE		0x00200000
+#define   HEAD_ADDR		0x001FFFFC
+#define   RING_NR_PAGES		0x001FF000
+#define   RING_REPORT_MASK	0x00000006
+#define   RING_REPORT_64K	0x00000002
+#define   RING_REPORT_128K	0x00000004
+#define   RING_NO_REPORT	0x00000000
+#define   RING_VALID_MASK	0x00000001
+#define   RING_VALID		0x00000001
+#define   RING_INVALID		0x00000000
+#define PRB1_TAIL	0x02040 /* 915+ only */
+#define PRB1_HEAD	0x02044 /* 915+ only */
+#define PRB1_START	0x02048 /* 915+ only */
+#define PRB1_CTL	0x0204c /* 915+ only */
+#define ACTHD_I965	0x02074
+#define HWS_PGA		0x02080
+#define HWS_ADDRESS_MASK	0xfffff000
+#define HWS_START_ADDRESS_SHIFT	4
+#define IPEIR		0x02088
+#define NOPID		0x02094
+#define HWSTAM		0x02098
+#define SCPD0		0x0209c /* 915+ only */
+#define IER		0x020a0
+#define IIR		0x020a4
+#define IMR		0x020a8
+#define ISR		0x020ac
+#define   I915_PIPE_CONTROL_NOTIFY_INTERRUPT		(1<<18)
+#define   I915_DISPLAY_PORT_INTERRUPT			(1<<17)
+#define   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT	(1<<15)
+#define   I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT	(1<<14)
+#define   I915_HWB_OOM_INTERRUPT			(1<<13)
+#define   I915_SYNC_STATUS_INTERRUPT			(1<<12)
+#define   I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT	(1<<11)
+#define   I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT	(1<<10)
+#define   I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT	(1<<9)
+#define   I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT	(1<<8)
+#define   I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT		(1<<7)
+#define   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT		(1<<6)
+#define   I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT		(1<<5)
+#define   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT		(1<<4)
+#define   I915_DEBUG_INTERRUPT				(1<<2)
+#define   I915_USER_INTERRUPT				(1<<1)
+#define   I915_ASLE_INTERRUPT				(1<<0)
+#define EIR		0x020b0
+#define EMR		0x020b4
+#define ESR		0x020b8
+#define INSTPM	        0x020c0
+#define ACTHD	        0x020c8
+#define FW_BLC		0x020d8
+#define FW_BLC_SELF	0x020e0 /* 915+ only */
+#define MI_ARB_STATE	0x020e4 /* 915+ only */
+#define CACHE_MODE_0	0x02120 /* 915+ only */
+#define   CM0_MASK_SHIFT          16
+#define   CM0_IZ_OPT_DISABLE      (1<<6)
+#define   CM0_ZR_OPT_DISABLE      (1<<5)
+#define   CM0_DEPTH_EVICT_DISABLE (1<<4)
+#define   CM0_COLOR_EVICT_DISABLE (1<<3)
+#define   CM0_DEPTH_WRITE_DISABLE (1<<1)
+#define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
+#define GFX_FLSH_CNTL	0x02170 /* 915+ only */
+
+/*
+ * Framebuffer compression (915+ only)
+ */
+
 #define FBC_CFB_BASE		0x03200 /* 4k page aligned */
 #define FBC_LL_BASE		0x03204 /* 4k page aligned */
 #define FBC_CONTROL		0x03208
@@ -456,26 +965,89 @@
 #define FBC_FENCE_OFF		0x0321b
 
 #define FBC_LL_SIZE		(1536)
-#define FBC_LL_PAD		(32)
 
-/* Interrupt bits:
+/*
+ * GPIO regs
  */
-#define USER_INT_FLAG    (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
+#define GPIOA			0x5010
+#define GPIOB			0x5014
+#define GPIOC			0x5018
+#define GPIOD			0x501c
+#define GPIOE			0x5020
+#define GPIOF			0x5024
+#define GPIOG			0x5028
+#define GPIOH			0x502c
+# define GPIO_CLOCK_DIR_MASK		(1 << 0)
+# define GPIO_CLOCK_DIR_IN		(0 << 1)
+# define GPIO_CLOCK_DIR_OUT		(1 << 1)
+# define GPIO_CLOCK_VAL_MASK		(1 << 2)
+# define GPIO_CLOCK_VAL_OUT		(1 << 3)
+# define GPIO_CLOCK_VAL_IN		(1 << 4)
+# define GPIO_CLOCK_PULLUP_DISABLE	(1 << 5)
+# define GPIO_DATA_DIR_MASK		(1 << 8)
+# define GPIO_DATA_DIR_IN		(0 << 9)
+# define GPIO_DATA_DIR_OUT		(1 << 9)
+# define GPIO_DATA_VAL_MASK		(1 << 10)
+# define GPIO_DATA_VAL_OUT		(1 << 11)
+# define GPIO_DATA_VAL_IN		(1 << 12)
+# define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
 
-#define I915REG_HWSTAM		0x02098
-#define I915REG_INT_IDENTITY_R	0x020a4
-#define I915REG_INT_MASK_R	0x020a8
-#define I915REG_INT_ENABLE_R	0x020a0
-#define I915REG_INSTPM	        0x020c0
+/*
+ * Clock control & power management
+ */
 
-#define I915REG_PIPEASTAT	0x70024
-#define I915REG_PIPEBSTAT	0x71024
+#define VGA0	0x6000
+#define VGA1	0x6004
+#define VGA_PD	0x6010
+#define   VGA0_PD_P2_DIV_4	(1 << 7)
+#define   VGA0_PD_P1_DIV_2	(1 << 5)
+#define   VGA0_PD_P1_SHIFT	0
+#define   VGA0_PD_P1_MASK	(0x1f << 0)
+#define   VGA1_PD_P2_DIV_4	(1 << 15)
+#define   VGA1_PD_P1_DIV_2	(1 << 13)
+#define   VGA1_PD_P1_SHIFT	8
+#define   VGA1_PD_P1_MASK	(0x1f << 8)
+#define DPLL_A	0x06014
+#define DPLL_B	0x06018
+#define   DPLL_VCO_ENABLE		(1 << 31)
+#define   DPLL_DVO_HIGH_SPEED		(1 << 30)
+#define   DPLL_SYNCLOCK_ENABLE		(1 << 29)
+#define   DPLL_VGA_MODE_DIS		(1 << 28)
+#define   DPLLB_MODE_DAC_SERIAL		(1 << 26) /* i915 */
+#define   DPLLB_MODE_LVDS		(2 << 26) /* i915 */
+#define   DPLL_MODE_MASK		(3 << 26)
+#define   DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
+#define   DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
+#define   DPLLB_LVDS_P2_CLOCK_DIV_14	(0 << 24) /* i915 */
+#define   DPLLB_LVDS_P2_CLOCK_DIV_7	(1 << 24) /* i915 */
+#define   DPLL_P2_CLOCK_DIV_MASK	0x03000000 /* i915 */
+#define   DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000 /* i915 */
 
-#define I915_VBLANK_INTERRUPT_ENABLE	(1UL<<17)
-#define I915_VBLANK_CLEAR		(1UL<<1)
+#define I915_FIFO_UNDERRUN_STATUS		(1UL<<31)
+#define I915_CRC_ERROR_ENABLE			(1UL<<29)
+#define I915_CRC_DONE_ENABLE			(1UL<<28)
+#define I915_GMBUS_EVENT_ENABLE			(1UL<<27)
+#define I915_VSYNC_INTERRUPT_ENABLE		(1UL<<25)
+#define I915_DISPLAY_LINE_COMPARE_ENABLE	(1UL<<24)
+#define I915_DPST_EVENT_ENABLE			(1UL<<23)
+#define I915_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)
+#define I915_ODD_FIELD_INTERRUPT_ENABLE		(1UL<<21)
+#define I915_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)
+#define I915_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18)	/* 965 or later */
+#define I915_VBLANK_INTERRUPT_ENABLE		(1UL<<17)
+#define I915_OVERLAY_UPDATED_ENABLE		(1UL<<16)
+#define I915_CRC_ERROR_INTERRUPT_STATUS		(1UL<<13)
+#define I915_CRC_DONE_INTERRUPT_STATUS		(1UL<<12)
+#define I915_GMBUS_INTERRUPT_STATUS		(1UL<<11)
+#define I915_VSYNC_INTERRUPT_STATUS		(1UL<<9)
+#define I915_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8)
+#define I915_DPST_EVENT_STATUS			(1UL<<7)
+#define I915_LEGACY_BLC_EVENT_STATUS		(1UL<<6)
+#define I915_ODD_FIELD_INTERRUPT_STATUS		(1UL<<5)
+#define I915_EVEN_FIELD_INTERRUPT_STATUS	(1UL<<4)
+#define I915_START_VBLANK_INTERRUPT_STATUS	(1UL<<2)	/* 965 or later */
+#define I915_VBLANK_INTERRUPT_STATUS		(1UL<<1)
+#define I915_OVERLAY_UPDATED_STATUS		(1UL<<0)
 
 #define SRX_INDEX		0x3c4
 #define SRX_DATA		0x3c5
@@ -499,13 +1071,6 @@
 #define ADPA_DPMS_STANDBY	(2<<10)
 #define ADPA_DPMS_OFF		(3<<10)
 
-#define NOPID                   0x2094
-#define LP_RING			0x2030
-#define HP_RING			0x2040
-/* The binner has its own ring buffer:
- */
-#define HWB_RING		0x2400
-
 #define RING_TAIL		0x00
 #define TAIL_ADDR		0x001FFFF8
 #define RING_HEAD		0x04
@@ -513,7 +1078,7 @@
 #define HEAD_WRAP_ONE		0x00200000
 #define HEAD_ADDR		0x001FFFFC
 #define RING_START		0x08
-#define START_ADDR		0x0xFFFFF000
+#define START_ADDR		0xFFFFF000
 #define RING_LEN		0x0C
 #define RING_NR_PAGES		0x001FF000
 #define RING_REPORT_MASK	0x00000006
@@ -524,354 +1089,50 @@
 #define RING_VALID		0x00000001
 #define RING_INVALID		0x00000000
 
-/* Instruction parser error reg:
- */
-#define IPEIR			0x2088
-
 /* Scratch pad debug 0 reg:
  */
-#define SCPD0			0x209c
-
-/* Error status reg:
- */
-#define ESR			0x20b8
-
-/* Secondary DMA fetch address debug reg:
- */
-#define DMA_FADD_S		0x20d4
-
-/* Cache mode 0 reg.
- *  - Manipulating render cache behaviour is central
- *    to the concept of zone rendering, tuning this reg can help avoid
- *    unnecessary render cache reads and even writes (for z/stencil)
- *    at beginning and end of scene.
- *
- * - To change a bit, write to this reg with a mask bit set and the
- * bit of interest either set or cleared.  EG: (BIT<<16) | BIT to set.
- */
-#define Cache_Mode_0		0x2120
-#define CM0_MASK_SHIFT          16
-#define CM0_IZ_OPT_DISABLE      (1<<6)
-#define CM0_ZR_OPT_DISABLE      (1<<5)
-#define CM0_DEPTH_EVICT_DISABLE (1<<4)
-#define CM0_COLOR_EVICT_DISABLE (1<<3)
-#define CM0_DEPTH_WRITE_DISABLE (1<<1)
-#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
-
-
-/* Graphics flush control.  A CPU write flushes the GWB of all writes.
- * The data is discarded.
- */
-#define GFX_FLSH_CNTL		0x2170
-
-/* Binner control.  Defines the location of the bin pointer list:
- */
-#define BINCTL			0x2420
-#define BC_MASK			(1 << 9)
-
-/* Binned scene info.
- */
-#define BINSCENE		0x2428
-#define BS_OP_LOAD		(1 << 8)
-#define BS_MASK			(1 << 22)
-
-/* Bin command parser debug reg:
- */
-#define BCPD			0x2480
-
-/* Bin memory control debug reg:
- */
-#define BMCD			0x2484
-
-/* Bin data cache debug reg:
- */
-#define BDCD			0x2488
-
-/* Binner pointer cache debug reg:
- */
-#define BPCD			0x248c
-
-/* Binner scratch pad debug reg:
- */
-#define BINSKPD			0x24f0
-
-/* HWB scratch pad debug reg:
- */
-#define HWBSKPD			0x24f4
-
-/* Binner memory pool reg:
- */
-#define BMP_BUFFER		0x2430
-#define BMP_PAGE_SIZE_4K	(0 << 10)
-#define BMP_BUFFER_SIZE_SHIFT	1
-#define BMP_ENABLE		(1 << 0)
-
-/* Get/put memory from the binner memory pool:
- */
-#define BMP_GET			0x2438
-#define BMP_PUT			0x2440
-#define BMP_OFFSET_SHIFT	5
-
-/* 3D state packets:
- */
-#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
-
-#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define SC_UPDATE_SCISSOR       (0x1<<1)
-#define SC_ENABLE_MASK          (0x1<<0)
-#define SC_ENABLE               (0x1<<0)
-
-#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
-
-#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-#define SCI_YMIN_MASK      (0xffff<<16)
-#define SCI_XMIN_MASK      (0xffff<<0)
-#define SCI_YMAX_MASK      (0xffff<<16)
-#define SCI_XMAX_MASK      (0xffff<<0)
-
-#define GFX_OP_SCISSOR_ENABLE	 ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define GFX_OP_SCISSOR_RECT	 ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
-#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
-#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-
-#define GFX_OP_DRAWRECT_INFO_I965  ((0x7900<<16)|0x2)
-
-#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
-#define XY_SRC_COPY_BLT_CMD		((2<<29)|(0x53<<22)|6)
-#define XY_SRC_COPY_BLT_WRITE_ALPHA	(1<<21)
-#define XY_SRC_COPY_BLT_WRITE_RGB	(1<<20)
-
-#define MI_BATCH_BUFFER		((0x30<<23)|1)
-#define MI_BATCH_BUFFER_START	(0x31<<23)
-#define MI_BATCH_BUFFER_END	(0xA<<23)
-#define MI_BATCH_NON_SECURE	(1)
-
-#define MI_BATCH_NON_SECURE_I965 (1<<8)
-
-#define MI_WAIT_FOR_EVENT       ((0x3<<23))
-#define MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
-#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
-#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-
-#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
-
-#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
-#define ASYNC_FLIP                (1<<22)
-#define DISPLAY_PLANE_A           (0<<20)
-#define DISPLAY_PLANE_B           (1<<20)
-
-/* Display regs */
-#define DSPACNTR                0x70180
-#define DSPBCNTR                0x71180
-#define DISPPLANE_SEL_PIPE_MASK                 (1<<24)
-
-/* Define the region of interest for the binner:
- */
-#define CMD_OP_BIN_CONTROL	 ((0x3<<29)|(0x1d<<24)|(0x84<<16)|4)
-
-#define CMD_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
-
-#define BREADCRUMB_BITS 31
-#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
-
-#define READ_BREADCRUMB(dev_priv)  (((volatile u32*)(dev_priv->hw_status_page))[5])
-#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
-
-#define BLC_PWM_CTL		0x61254
-#define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
-
-#define BLC_PWM_CTL2		0x61250
-/**
- * This is the most significant 15 bits of the number of backlight cycles in a
- * complete cycle of the modulated backlight control.
- *
- * The actual value is this field multiplied by two.
- */
-#define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
-#define BLM_LEGACY_MODE				(1 << 16)
-/**
- * This is the number of cycles out of the backlight modulation cycle for which
- * the backlight is on.
- *
- * This field must be no greater than the number of cycles in the complete
- * backlight modulation cycle.
- */
-#define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
-#define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
-
-#define I915_GCFGC			0xf0
-#define I915_LOW_FREQUENCY_ENABLE		(1 << 7)
-#define I915_DISPLAY_CLOCK_190_200_MHZ		(0 << 4)
-#define I915_DISPLAY_CLOCK_333_MHZ		(4 << 4)
-#define I915_DISPLAY_CLOCK_MASK			(7 << 4)
-
-#define I855_HPLLCC			0xc0
-#define I855_CLOCK_CONTROL_MASK			(3 << 0)
-#define I855_CLOCK_133_200			(0 << 0)
-#define I855_CLOCK_100_200			(1 << 0)
-#define I855_CLOCK_100_133			(2 << 0)
-#define I855_CLOCK_166_250			(3 << 0)
-
-/* p317, 319
- */
-#define VCLK2_VCO_M        0x6008 /* treat as 16 bit? (includes msbs) */
-#define VCLK2_VCO_N        0x600a
-#define VCLK2_VCO_DIV_SEL  0x6012
-
-#define VCLK_DIVISOR_VGA0   0x6000
-#define VCLK_DIVISOR_VGA1   0x6004
-#define VCLK_POST_DIV	    0x6010
-/** Selects a post divisor of 4 instead of 2. */
-# define VGA1_PD_P2_DIV_4	(1 << 15)
-/** Overrides the p2 post divisor field */
-# define VGA1_PD_P1_DIV_2	(1 << 13)
-# define VGA1_PD_P1_SHIFT	8
-/** P1 value is 2 greater than this field */
-# define VGA1_PD_P1_MASK	(0x1f << 8)
-/** Selects a post divisor of 4 instead of 2. */
-# define VGA0_PD_P2_DIV_4	(1 << 7)
-/** Overrides the p2 post divisor field */
-# define VGA0_PD_P1_DIV_2	(1 << 5)
-# define VGA0_PD_P1_SHIFT	0
-/** P1 value is 2 greater than this field */
-# define VGA0_PD_P1_MASK	(0x1f << 0)
-
-/* I830 CRTC registers */
-#define HTOTAL_A	0x60000
-#define HBLANK_A	0x60004
-#define HSYNC_A		0x60008
-#define VTOTAL_A	0x6000c
-#define VBLANK_A	0x60010
-#define VSYNC_A		0x60014
-#define PIPEASRC	0x6001c
-#define BCLRPAT_A	0x60020
-#define VSYNCSHIFT_A	0x60028
-
-#define HTOTAL_B	0x61000
-#define HBLANK_B	0x61004
-#define HSYNC_B		0x61008
-#define VTOTAL_B	0x6100c
-#define VBLANK_B	0x61010
-#define VSYNC_B		0x61014
-#define PIPEBSRC	0x6101c
-#define BCLRPAT_B	0x61020
-#define VSYNCSHIFT_B	0x61028
-
-#define PP_STATUS	0x61200
-# define PP_ON					(1 << 31)
-/**
- * Indicates that all dependencies of the panel are on:
- *
- * - PLL enabled
- * - pipe enabled
- * - LVDS/DVOB/DVOC on
- */
-# define PP_READY				(1 << 30)
-# define PP_SEQUENCE_NONE			(0 << 28)
-# define PP_SEQUENCE_ON				(1 << 28)
-# define PP_SEQUENCE_OFF			(2 << 28)
-# define PP_SEQUENCE_MASK			0x30000000
-#define PP_CONTROL	0x61204
-# define POWER_TARGET_ON			(1 << 0)
-
-#define LVDSPP_ON       0x61208
-#define LVDSPP_OFF      0x6120c
-#define PP_CYCLE        0x61210
-
-#define PFIT_CONTROL	0x61230
-# define PFIT_ENABLE				(1 << 31)
-# define PFIT_PIPE_MASK				(3 << 29)
-# define PFIT_PIPE_SHIFT			29
-# define VERT_INTERP_DISABLE			(0 << 10)
-# define VERT_INTERP_BILINEAR			(1 << 10)
-# define VERT_INTERP_MASK			(3 << 10)
-# define VERT_AUTO_SCALE			(1 << 9)
-# define HORIZ_INTERP_DISABLE			(0 << 6)
-# define HORIZ_INTERP_BILINEAR			(1 << 6)
-# define HORIZ_INTERP_MASK			(3 << 6)
-# define HORIZ_AUTO_SCALE			(1 << 5)
-# define PANEL_8TO6_DITHER_ENABLE		(1 << 3)
-
-#define PFIT_PGM_RATIOS	0x61234
-# define PFIT_VERT_SCALE_MASK			0xfff00000
-# define PFIT_HORIZ_SCALE_MASK			0x0000fff0
-
-#define PFIT_AUTO_RATIOS	0x61238
-
-
-#define DPLL_A		0x06014
-#define DPLL_B		0x06018
-# define DPLL_VCO_ENABLE			(1 << 31)
-# define DPLL_DVO_HIGH_SPEED			(1 << 30)
-# define DPLL_SYNCLOCK_ENABLE			(1 << 29)
-# define DPLL_VGA_MODE_DIS			(1 << 28)
-# define DPLLB_MODE_DAC_SERIAL			(1 << 26) /* i915 */
-# define DPLLB_MODE_LVDS			(2 << 26) /* i915 */
-# define DPLL_MODE_MASK				(3 << 26)
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24) /* i915 */
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5		(1 << 24) /* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_14		(0 << 24) /* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24) /* i915 */
-# define DPLL_P2_CLOCK_DIV_MASK			0x03000000 /* i915 */
-# define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000 /* i915 */
-/**
- *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
- * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
- */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000
-/**
+#define   DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000
+/*
  * The i830 generation, in LVDS mode, defines P1 as the bit number set within
  * this field (only one bit may be set).
  */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
-# define DPLL_FPA01_P1_POST_DIV_SHIFT		16
-# define PLL_P2_DIVIDE_BY_4			(1 << 23) /* i830, required in DVO non-gang */
-# define PLL_P1_DIVIDE_BY_TWO			(1 << 21) /* i830 */
-# define PLL_REF_INPUT_DREFCLK			(0 << 13)
-# define PLL_REF_INPUT_TVCLKINA			(1 << 13) /* i830 */
-# define PLL_REF_INPUT_TVCLKINBC		(2 << 13) /* SDVO TVCLKIN */
-# define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
-# define PLL_REF_INPUT_MASK			(3 << 13)
-# define PLL_LOAD_PULSE_PHASE_SHIFT		9
+#define   DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
+#define   DPLL_FPA01_P1_POST_DIV_SHIFT	16
+/* i830, required in DVO non-gang */
+#define   PLL_P2_DIVIDE_BY_4		(1 << 23)
+#define   PLL_P1_DIVIDE_BY_TWO		(1 << 21) /* i830 */
+#define   PLL_REF_INPUT_DREFCLK		(0 << 13)
+#define   PLL_REF_INPUT_TVCLKINA	(1 << 13) /* i830 */
+#define   PLL_REF_INPUT_TVCLKINBC	(2 << 13) /* SDVO TVCLKIN */
+#define   PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
+#define   PLL_REF_INPUT_MASK		(3 << 13)
+#define   PLL_LOAD_PULSE_PHASE_SHIFT		9
 /*
  * Parallel to Serial Load Pulse phase selection.
  * Selects the phase for the 10X DPLL clock for the PCIe
  * digital display port. The range is 4 to 13; 10 or more
  * is just a flip delay. The default is 6
  */
-# define PLL_LOAD_PULSE_PHASE_MASK		(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-# define DISPLAY_RATE_SELECT_FPA1		(1 << 8)
-
-/**
+#define   PLL_LOAD_PULSE_PHASE_MASK		(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+#define   DISPLAY_RATE_SELECT_FPA1		(1 << 8)
+/*
  * SDVO multiplier for 945G/GM. Not used on 965.
- *
- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
  */
-# define SDVO_MULTIPLIER_MASK			0x000000ff
-# define SDVO_MULTIPLIER_SHIFT_HIRES		4
-# define SDVO_MULTIPLIER_SHIFT_VGA		0
-
-/** @defgroup DPLL_MD
- * @{
- */
-/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_A_MD		0x0601c
-/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_B_MD		0x06020
-/**
+#define   SDVO_MULTIPLIER_MASK			0x000000ff
+#define   SDVO_MULTIPLIER_SHIFT_HIRES		4
+#define   SDVO_MULTIPLIER_SHIFT_VGA		0
+#define DPLL_A_MD 0x0601c /* 965+ only */
+/*
  * UDI pixel divider, controlling how many pixels are stuffed into a packet.
  *
  * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
  */
-# define DPLL_MD_UDI_DIVIDER_MASK		0x3f000000
-# define DPLL_MD_UDI_DIVIDER_SHIFT		24
-/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-# define DPLL_MD_VGA_UDI_DIVIDER_MASK		0x003f0000
-# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT		16
-/**
+#define   DPLL_MD_UDI_DIVIDER_MASK		0x3f000000
+#define   DPLL_MD_UDI_DIVIDER_SHIFT		24
+/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+#define   DPLL_MD_VGA_UDI_DIVIDER_MASK		0x003f0000
+#define   DPLL_MD_VGA_UDI_DIVIDER_SHIFT		16
+/*
  * SDVO/UDI pixel multiplier.
  *
  * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
@@ -888,80 +1149,134 @@
  * This register field has values of multiplication factor minus 1, with
  * a maximum multiplier of 5 for SDVO.
  */
-# define DPLL_MD_UDI_MULTIPLIER_MASK		0x00003f00
-# define DPLL_MD_UDI_MULTIPLIER_SHIFT		8
-/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+#define   DPLL_MD_UDI_MULTIPLIER_MASK		0x00003f00
+#define   DPLL_MD_UDI_MULTIPLIER_SHIFT		8
+/*
+ * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
  * This best be set to the default value (3) or the CRT won't work. No,
  * I don't entirely understand what this does...
  */
-# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
-# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
-/** @} */
+#define   DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
+#define   DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
+#define DPLL_B_MD 0x06020 /* 965+ only */
+#define FPA0	0x06040
+#define FPA1	0x06044
+#define FPB0	0x06048
+#define FPB1	0x0604c
+#define   FP_N_DIV_MASK		0x003f0000
+#define   FP_N_DIV_SHIFT		16
+#define   FP_M1_DIV_MASK	0x00003f00
+#define   FP_M1_DIV_SHIFT		 8
+#define   FP_M2_DIV_MASK	0x0000003f
+#define   FP_M2_DIV_SHIFT		 0
+#define DPLL_TEST	0x606c
+#define   DPLLB_TEST_SDVO_DIV_1		(0 << 22)
+#define   DPLLB_TEST_SDVO_DIV_2		(1 << 22)
+#define   DPLLB_TEST_SDVO_DIV_4		(2 << 22)
+#define   DPLLB_TEST_SDVO_DIV_MASK	(3 << 22)
+#define   DPLLB_TEST_N_BYPASS		(1 << 19)
+#define   DPLLB_TEST_M_BYPASS		(1 << 18)
+#define   DPLLB_INPUT_BUFFER_ENABLE	(1 << 16)
+#define   DPLLA_TEST_N_BYPASS		(1 << 3)
+#define   DPLLA_TEST_M_BYPASS		(1 << 2)
+#define   DPLLA_INPUT_BUFFER_ENABLE	(1 << 0)
+#define D_STATE		0x6104
+#define CG_2D_DIS	0x6200
+#define CG_3D_DIS	0x6204
 
-#define DPLL_TEST		0x606c
-# define DPLLB_TEST_SDVO_DIV_1			(0 << 22)
-# define DPLLB_TEST_SDVO_DIV_2			(1 << 22)
-# define DPLLB_TEST_SDVO_DIV_4			(2 << 22)
-# define DPLLB_TEST_SDVO_DIV_MASK		(3 << 22)
-# define DPLLB_TEST_N_BYPASS			(1 << 19)
-# define DPLLB_TEST_M_BYPASS			(1 << 18)
-# define DPLLB_INPUT_BUFFER_ENABLE		(1 << 16)
-# define DPLLA_TEST_N_BYPASS			(1 << 3)
-# define DPLLA_TEST_M_BYPASS			(1 << 2)
-# define DPLLA_INPUT_BUFFER_ENABLE		(1 << 0)
+/*
+ * Palette regs
+ */
 
+#define PALETTE_A		0x0a000
+#define PALETTE_B		0x0a800
+
+/*
+ * Overlay regs
+ */
+
+#define OVADD			0x30000
+#define DOVSTA			0x30008
+#define OC_BUF			(0x3<<20)
+#define OGAMC5			0x30010
+#define OGAMC4			0x30014
+#define OGAMC3			0x30018
+#define OGAMC2			0x3001c
+#define OGAMC1			0x30020
+#define OGAMC0			0x30024
+
+/*
+ * Display engine regs
+ */
+
+/* Pipe A timing regs */
+#define HTOTAL_A	0x60000
+#define HBLANK_A	0x60004
+#define HSYNC_A		0x60008
+#define VTOTAL_A	0x6000c
+#define VBLANK_A	0x60010
+#define VSYNC_A		0x60014
+#define PIPEASRC	0x6001c
+#define BCLRPAT_A	0x60020
+
+/* Pipe B timing regs */
+#define HTOTAL_B	0x61000
+#define HBLANK_B	0x61004
+#define HSYNC_B		0x61008
+#define VTOTAL_B	0x6100c
+#define VBLANK_B	0x61010
+#define VSYNC_B		0x61014
+#define PIPEBSRC	0x6101c
+#define BCLRPAT_B	0x61020
+
+/* VGA port control */
 #define ADPA			0x61100
-#define ADPA_DAC_ENABLE		(1<<31)
-#define ADPA_DAC_DISABLE	0
-#define ADPA_PIPE_SELECT_MASK	(1<<30)
-#define ADPA_PIPE_A_SELECT	0
-#define ADPA_PIPE_B_SELECT	(1<<30)
-#define ADPA_USE_VGA_HVPOLARITY (1<<15)
-#define ADPA_SETS_HVPOLARITY	0
-#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
-#define ADPA_VSYNC_CNTL_ENABLE	0
-#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
-#define ADPA_HSYNC_CNTL_ENABLE	0
-#define ADPA_VSYNC_ACTIVE_HIGH	(1<<4)
-#define ADPA_VSYNC_ACTIVE_LOW	0
-#define ADPA_HSYNC_ACTIVE_HIGH	(1<<3)
-#define ADPA_HSYNC_ACTIVE_LOW	0
+#define   ADPA_DAC_ENABLE	(1<<31)
+#define   ADPA_DAC_DISABLE	0
+#define   ADPA_PIPE_SELECT_MASK	(1<<30)
+#define   ADPA_PIPE_A_SELECT	0
+#define   ADPA_PIPE_B_SELECT	(1<<30)
+#define   ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define   ADPA_SETS_HVPOLARITY	0
+#define   ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define   ADPA_VSYNC_CNTL_ENABLE 0
+#define   ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define   ADPA_HSYNC_CNTL_ENABLE 0
+#define   ADPA_VSYNC_ACTIVE_HIGH (1<<4)
+#define   ADPA_VSYNC_ACTIVE_LOW	0
+#define   ADPA_HSYNC_ACTIVE_HIGH (1<<3)
+#define   ADPA_HSYNC_ACTIVE_LOW	0
+#define   ADPA_DPMS_MASK	(~(3<<10))
+#define   ADPA_DPMS_ON		(0<<10)
+#define   ADPA_DPMS_SUSPEND	(1<<10)
+#define   ADPA_DPMS_STANDBY	(2<<10)
+#define   ADPA_DPMS_OFF		(3<<10)
 
-#define FPA0		0x06040
-#define FPA1		0x06044
-#define FPB0		0x06048
-#define FPB1		0x0604c
-# define FP_N_DIV_MASK				0x003f0000
-# define FP_N_DIV_SHIFT				16
-# define FP_M1_DIV_MASK				0x00003f00
-# define FP_M1_DIV_SHIFT			8
-# define FP_M2_DIV_MASK				0x0000003f
-# define FP_M2_DIV_SHIFT			0
-
-
+/* Hotplug control (945+ only) */
 #define PORT_HOTPLUG_EN		0x61110
-# define SDVOB_HOTPLUG_INT_EN			(1 << 26)
-# define SDVOC_HOTPLUG_INT_EN			(1 << 25)
-# define TV_HOTPLUG_INT_EN			(1 << 18)
-# define CRT_HOTPLUG_INT_EN			(1 << 9)
-# define CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
+#define   SDVOB_HOTPLUG_INT_EN			(1 << 26)
+#define   SDVOC_HOTPLUG_INT_EN			(1 << 25)
+#define   TV_HOTPLUG_INT_EN			(1 << 18)
+#define   CRT_HOTPLUG_INT_EN			(1 << 9)
+#define   CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
 
 #define PORT_HOTPLUG_STAT	0x61114
-# define CRT_HOTPLUG_INT_STATUS			(1 << 11)
-# define TV_HOTPLUG_INT_STATUS			(1 << 10)
-# define CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
-# define CRT_HOTPLUG_MONITOR_COLOR		(3 << 8)
-# define CRT_HOTPLUG_MONITOR_MONO		(2 << 8)
-# define CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
-# define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
-# define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
+#define   CRT_HOTPLUG_INT_STATUS		(1 << 11)
+#define   TV_HOTPLUG_INT_STATUS			(1 << 10)
+#define   CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
+#define   CRT_HOTPLUG_MONITOR_COLOR		(3 << 8)
+#define   CRT_HOTPLUG_MONITOR_MONO		(2 << 8)
+#define   CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
+#define   SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
+#define   SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
 
+/* SDVO port control */
 #define SDVOB			0x61140
 #define SDVOC			0x61160
-#define SDVO_ENABLE				(1 << 31)
-#define SDVO_PIPE_B_SELECT			(1 << 30)
-#define SDVO_STALL_SELECT			(1 << 29)
-#define SDVO_INTERRUPT_ENABLE			(1 << 26)
+#define   SDVO_ENABLE		(1 << 31)
+#define   SDVO_PIPE_B_SELECT	(1 << 30)
+#define   SDVO_STALL_SELECT	(1 << 29)
+#define   SDVO_INTERRUPT_ENABLE	(1 << 26)
 /**
  * 915G/GM SDVO pixel multiplier.
  *
@@ -969,188 +1284,800 @@
  *
  * \sa DPLL_MD_UDI_MULTIPLIER_MASK
  */
-#define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
-#define SDVO_PORT_MULTIPLY_SHIFT		23
-#define SDVO_PHASE_SELECT_MASK			(15 << 19)
-#define SDVO_PHASE_SELECT_DEFAULT		(6 << 19)
-#define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
-#define SDVOC_GANG_MODE				(1 << 16)
-#define SDVO_BORDER_ENABLE			(1 << 7)
-#define SDVOB_PCIE_CONCURRENCY			(1 << 3)
-#define SDVO_DETECTED				(1 << 2)
+#define   SDVO_PORT_MULTIPLY_MASK	(7 << 23)
+#define   SDVO_PORT_MULTIPLY_SHIFT		23
+#define   SDVO_PHASE_SELECT_MASK	(15 << 19)
+#define   SDVO_PHASE_SELECT_DEFAULT	(6 << 19)
+#define   SDVO_CLOCK_OUTPUT_INVERT	(1 << 18)
+#define   SDVOC_GANG_MODE		(1 << 16)
+#define   SDVO_BORDER_ENABLE		(1 << 7)
+#define   SDVOB_PCIE_CONCURRENCY	(1 << 3)
+#define   SDVO_DETECTED			(1 << 2)
 /* Bits to be preserved when writing */
-#define SDVOB_PRESERVE_MASK			((1 << 17) | (1 << 16) | (1 << 14))
-#define SDVOC_PRESERVE_MASK			(1 << 17)
+#define   SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26))
+#define   SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26))
 
-/** @defgroup LVDS
- * @{
- */
-/**
- * This register controls the LVDS output enable, pipe selection, and data
- * format selection.
- *
- * All of the clock/data pairs are force powered down by power sequencing.
- */
+/* DVO port control */
+#define DVOA			0x61120
+#define DVOB			0x61140
+#define DVOC			0x61160
+#define   DVO_ENABLE			(1 << 31)
+#define   DVO_PIPE_B_SELECT		(1 << 30)
+#define   DVO_PIPE_STALL_UNUSED		(0 << 28)
+#define   DVO_PIPE_STALL		(1 << 28)
+#define   DVO_PIPE_STALL_TV		(2 << 28)
+#define   DVO_PIPE_STALL_MASK		(3 << 28)
+#define   DVO_USE_VGA_SYNC		(1 << 15)
+#define   DVO_DATA_ORDER_I740		(0 << 14)
+#define   DVO_DATA_ORDER_FP		(1 << 14)
+#define   DVO_VSYNC_DISABLE		(1 << 11)
+#define   DVO_HSYNC_DISABLE		(1 << 10)
+#define   DVO_VSYNC_TRISTATE		(1 << 9)
+#define   DVO_HSYNC_TRISTATE		(1 << 8)
+#define   DVO_BORDER_ENABLE		(1 << 7)
+#define   DVO_DATA_ORDER_GBRG		(1 << 6)
+#define   DVO_DATA_ORDER_RGGB		(0 << 6)
+#define   DVO_DATA_ORDER_GBRG_ERRATA	(0 << 6)
+#define   DVO_DATA_ORDER_RGGB_ERRATA	(1 << 6)
+#define   DVO_VSYNC_ACTIVE_HIGH		(1 << 4)
+#define   DVO_HSYNC_ACTIVE_HIGH		(1 << 3)
+#define   DVO_BLANK_ACTIVE_HIGH		(1 << 2)
+#define   DVO_OUTPUT_CSTATE_PIXELS	(1 << 1)	/* SDG only */
+#define   DVO_OUTPUT_SOURCE_SIZE_PIXELS	(1 << 0)	/* SDG only */
+#define   DVO_PRESERVE_MASK		(0x7<<24)
+#define DVOA_SRCDIM		0x61124
+#define DVOB_SRCDIM		0x61144
+#define DVOC_SRCDIM		0x61164
+#define   DVO_SRCDIM_HORIZONTAL_SHIFT	12
+#define   DVO_SRCDIM_VERTICAL_SHIFT	0
+
+/* LVDS port control */
 #define LVDS			0x61180
-/**
+/*
  * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
  * the DPLL semantics change when the LVDS is assigned to that pipe.
  */
-# define LVDS_PORT_EN			(1 << 31)
-/** Selects pipe B for LVDS data.  Must be set on pre-965. */
-# define LVDS_PIPEB_SELECT		(1 << 30)
-
-/**
+#define   LVDS_PORT_EN			(1 << 31)
+/* Selects pipe B for LVDS data.  Must be set on pre-965. */
+#define   LVDS_PIPEB_SELECT		(1 << 30)
+/*
  * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
  * pixel.
  */
-# define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
-# define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
-# define LVDS_A0A2_CLKA_POWER_UP	(3 << 8)
-/**
+#define   LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
+#define   LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
+#define   LVDS_A0A2_CLKA_POWER_UP	(3 << 8)
+/*
  * Controls the A3 data pair, which contains the additional LSBs for 24 bit
  * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
  * on.
  */
-# define LVDS_A3_POWER_MASK		(3 << 6)
-# define LVDS_A3_POWER_DOWN		(0 << 6)
-# define LVDS_A3_POWER_UP		(3 << 6)
-/**
+#define   LVDS_A3_POWER_MASK		(3 << 6)
+#define   LVDS_A3_POWER_DOWN		(0 << 6)
+#define   LVDS_A3_POWER_UP		(3 << 6)
+/*
  * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
  * is set.
  */
-# define LVDS_CLKB_POWER_MASK		(3 << 4)
-# define LVDS_CLKB_POWER_DOWN		(0 << 4)
-# define LVDS_CLKB_POWER_UP		(3 << 4)
-
-/**
+#define   LVDS_CLKB_POWER_MASK		(3 << 4)
+#define   LVDS_CLKB_POWER_DOWN		(0 << 4)
+#define   LVDS_CLKB_POWER_UP		(3 << 4)
+/*
  * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
  * setting for whether we are in dual-channel mode.  The B3 pair will
  * additionally only be powered up when LVDS_A3_POWER_UP is set.
  */
-# define LVDS_B0B3_POWER_MASK		(3 << 2)
-# define LVDS_B0B3_POWER_DOWN		(0 << 2)
-# define LVDS_B0B3_POWER_UP		(3 << 2)
+#define   LVDS_B0B3_POWER_MASK		(3 << 2)
+#define   LVDS_B0B3_POWER_DOWN		(0 << 2)
+#define   LVDS_B0B3_POWER_UP		(3 << 2)
 
-#define PIPEACONF 0x70008
-#define PIPEACONF_ENABLE	(1<<31)
-#define PIPEACONF_DISABLE	0
-#define PIPEACONF_DOUBLE_WIDE	(1<<30)
-#define I965_PIPECONF_ACTIVE	(1<<30)
-#define PIPEACONF_SINGLE_WIDE	0
-#define PIPEACONF_PIPE_UNLOCKED 0
-#define PIPEACONF_PIPE_LOCKED	(1<<25)
-#define PIPEACONF_PALETTE	0
-#define PIPEACONF_GAMMA		(1<<24)
-#define PIPECONF_FORCE_BORDER	(1<<25)
-#define PIPECONF_PROGRESSIVE	(0 << 21)
-#define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
-#define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
+/* Panel power sequencing */
+#define PP_STATUS	0x61200
+#define   PP_ON		(1 << 31)
+/*
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+#define   PP_READY		(1 << 30)
+#define   PP_SEQUENCE_NONE	(0 << 28)
+#define   PP_SEQUENCE_ON	(1 << 28)
+#define   PP_SEQUENCE_OFF	(2 << 28)
+#define   PP_SEQUENCE_MASK	0x30000000
+#define PP_CONTROL	0x61204
+#define   POWER_TARGET_ON	(1 << 0)
+#define PP_ON_DELAYS	0x61208
+#define PP_OFF_DELAYS	0x6120c
+#define PP_DIVISOR	0x61210
 
-#define PIPEBCONF 0x71008
-#define PIPEBCONF_ENABLE	(1<<31)
-#define PIPEBCONF_DISABLE	0
-#define PIPEBCONF_DOUBLE_WIDE	(1<<30)
-#define PIPEBCONF_DISABLE	0
-#define PIPEBCONF_GAMMA		(1<<24)
-#define PIPEBCONF_PALETTE	0
+/* Panel fitting */
+#define PFIT_CONTROL	0x61230
+#define   PFIT_ENABLE		(1 << 31)
+#define   PFIT_PIPE_MASK	(3 << 29)
+#define   PFIT_PIPE_SHIFT	29
+#define   VERT_INTERP_DISABLE	(0 << 10)
+#define   VERT_INTERP_BILINEAR	(1 << 10)
+#define   VERT_INTERP_MASK	(3 << 10)
+#define   VERT_AUTO_SCALE	(1 << 9)
+#define   HORIZ_INTERP_DISABLE	(0 << 6)
+#define   HORIZ_INTERP_BILINEAR	(1 << 6)
+#define   HORIZ_INTERP_MASK	(3 << 6)
+#define   HORIZ_AUTO_SCALE	(1 << 5)
+#define   PANEL_8TO6_DITHER_ENABLE (1 << 3)
+#define PFIT_PGM_RATIOS	0x61234
+#define   PFIT_VERT_SCALE_MASK			0xfff00000
+#define   PFIT_HORIZ_SCALE_MASK			0x0000fff0
+#define PFIT_AUTO_RATIOS 0x61238
 
-#define PIPEBGCMAXRED		0x71010
-#define PIPEBGCMAXGREEN		0x71014
-#define PIPEBGCMAXBLUE		0x71018
+/* Backlight control */
+#define BLC_PWM_CTL		0x61254
+#define   BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
+#define BLC_PWM_CTL2		0x61250 /* 965+ only */
+/*
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define   BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
+#define   BLM_LEGACY_MODE				(1 << 16)
+/*
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define   BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
+#define   BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
+
+/* TV port control */
+#define TV_CTL			0x68000
+/** Enables the TV encoder */
+# define TV_ENC_ENABLE			(1 << 31)
+/** Sources the TV encoder input from pipe B instead of A. */
+# define TV_ENC_PIPEB_SELECT		(1 << 30)
+/** Outputs composite video (DAC A only) */
+# define TV_ENC_OUTPUT_COMPOSITE	(0 << 28)
+/** Outputs SVideo video (DAC B/C) */
+# define TV_ENC_OUTPUT_SVIDEO		(1 << 28)
+/** Outputs Component video (DAC A/B/C) */
+# define TV_ENC_OUTPUT_COMPONENT	(2 << 28)
+/** Outputs Composite and SVideo (DAC A/B/C) */
+# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE	(3 << 28)
+# define TV_TRILEVEL_SYNC		(1 << 21)
+/** Enables slow sync generation (945GM only) */
+# define TV_SLOW_SYNC			(1 << 20)
+/** Selects 4x oversampling for 480i and 576p */
+# define TV_OVERSAMPLE_4X		(0 << 18)
+/** Selects 2x oversampling for 720p and 1080i */
+# define TV_OVERSAMPLE_2X		(1 << 18)
+/** Selects no oversampling for 1080p */
+# define TV_OVERSAMPLE_NONE		(2 << 18)
+/** Selects 8x oversampling */
+# define TV_OVERSAMPLE_8X		(3 << 18)
+/** Selects progressive mode rather than interlaced */
+# define TV_PROGRESSIVE			(1 << 17)
+/** Sets the colorburst to PAL mode.  Required for non-M PAL modes. */
+# define TV_PAL_BURST			(1 << 16)
+/** Field for setting delay of Y compared to C */
+# define TV_YC_SKEW_MASK		(7 << 12)
+/** Enables a fix for 480p/576p standard definition modes on the 915GM only */
+# define TV_ENC_SDP_FIX			(1 << 11)
+/**
+ * Enables a fix for the 915GM only.
+ *
+ * Not sure what it does.
+ */
+# define TV_ENC_C0_FIX			(1 << 10)
+/** Bits that must be preserved by software */
+# define TV_CTL_SAVE			((3 << 8) | (3 << 6))
+# define TV_FUSE_STATE_MASK		(3 << 4)
+/** Read-only state that reports all features enabled */
+# define TV_FUSE_STATE_ENABLED		(0 << 4)
+/** Read-only state that reports that Macrovision is disabled in hardware*/
+# define TV_FUSE_STATE_NO_MACROVISION	(1 << 4)
+/** Read-only state that reports that TV-out is disabled in hardware. */
+# define TV_FUSE_STATE_DISABLED		(2 << 4)
+/** Normal operation */
+# define TV_TEST_MODE_NORMAL		(0 << 0)
+/** Encoder test pattern 1 - combo pattern */
+# define TV_TEST_MODE_PATTERN_1		(1 << 0)
+/** Encoder test pattern 2 - full screen vertical 75% color bars */
+# define TV_TEST_MODE_PATTERN_2		(2 << 0)
+/** Encoder test pattern 3 - full screen horizontal 75% color bars */
+# define TV_TEST_MODE_PATTERN_3		(3 << 0)
+/** Encoder test pattern 4 - random noise */
+# define TV_TEST_MODE_PATTERN_4		(4 << 0)
+/** Encoder test pattern 5 - linear color ramps */
+# define TV_TEST_MODE_PATTERN_5		(5 << 0)
+/**
+ * This test mode forces the DACs to 50% of full output.
+ *
+ * This is used for load detection in combination with TVDAC_SENSE_MASK
+ */
+# define TV_TEST_MODE_MONITOR_DETECT	(7 << 0)
+# define TV_TEST_MODE_MASK		(7 << 0)
+
+#define TV_DAC			0x68004
+/**
+ * Reports that DAC state change logic has reported change (RO).
+ *
+ * This gets cleared when TV_DAC_STATE_EN is cleared
+*/
+# define TVDAC_STATE_CHG		(1 << 31)
+# define TVDAC_SENSE_MASK		(7 << 28)
+/** Reports that DAC A voltage is above the detect threshold */
+# define TVDAC_A_SENSE			(1 << 30)
+/** Reports that DAC B voltage is above the detect threshold */
+# define TVDAC_B_SENSE			(1 << 29)
+/** Reports that DAC C voltage is above the detect threshold */
+# define TVDAC_C_SENSE			(1 << 28)
+/**
+ * Enables DAC state detection logic, for load-based TV detection.
+ *
+ * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set
+ * to off, for load detection to work.
+ */
+# define TVDAC_STATE_CHG_EN		(1 << 27)
+/** Sets the DAC A sense value to high */
+# define TVDAC_A_SENSE_CTL		(1 << 26)
+/** Sets the DAC B sense value to high */
+# define TVDAC_B_SENSE_CTL		(1 << 25)
+/** Sets the DAC C sense value to high */
+# define TVDAC_C_SENSE_CTL		(1 << 24)
+/** Overrides the ENC_ENABLE and DAC voltage levels */
+# define DAC_CTL_OVERRIDE		(1 << 7)
+/** Sets the slew rate.  Must be preserved in software */
+# define ENC_TVDAC_SLEW_FAST		(1 << 6)
+# define DAC_A_1_3_V			(0 << 4)
+# define DAC_A_1_1_V			(1 << 4)
+# define DAC_A_0_7_V			(2 << 4)
+# define DAC_A_OFF			(3 << 4)
+# define DAC_B_1_3_V			(0 << 2)
+# define DAC_B_1_1_V			(1 << 2)
+# define DAC_B_0_7_V			(2 << 2)
+# define DAC_B_OFF			(3 << 2)
+# define DAC_C_1_3_V			(0 << 0)
+# define DAC_C_1_1_V			(1 << 0)
+# define DAC_C_0_7_V			(2 << 0)
+# define DAC_C_OFF			(3 << 0)
+
+/**
+ * CSC coefficients are stored in a floating point format with 9 bits of
+ * mantissa and 2 or 3 bits of exponent.  The exponent is represented as 2**-n,
+ * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with
+ * -1 (0x3) being the only legal negative value.
+ */
+#define TV_CSC_Y		0x68010
+# define TV_RY_MASK			0x07ff0000
+# define TV_RY_SHIFT			16
+# define TV_GY_MASK			0x00000fff
+# define TV_GY_SHIFT			0
+
+#define TV_CSC_Y2		0x68014
+# define TV_BY_MASK			0x07ff0000
+# define TV_BY_SHIFT			16
+/**
+ * Y attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AY_MASK			0x000003ff
+# define TV_AY_SHIFT			0
+
+#define TV_CSC_U		0x68018
+# define TV_RU_MASK			0x07ff0000
+# define TV_RU_SHIFT			16
+# define TV_GU_MASK			0x000007ff
+# define TV_GU_SHIFT			0
+
+#define TV_CSC_U2		0x6801c
+# define TV_BU_MASK			0x07ff0000
+# define TV_BU_SHIFT			16
+/**
+ * U attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AU_MASK			0x000003ff
+# define TV_AU_SHIFT			0
+
+#define TV_CSC_V		0x68020
+# define TV_RV_MASK			0x0fff0000
+# define TV_RV_SHIFT			16
+# define TV_GV_MASK			0x000007ff
+# define TV_GV_SHIFT			0
+
+#define TV_CSC_V2		0x68024
+# define TV_BV_MASK			0x07ff0000
+# define TV_BV_SHIFT			16
+/**
+ * V attenuation for component video.
+ *
+ * Stored in 1.9 fixed point.
+ */
+# define TV_AV_MASK			0x000007ff
+# define TV_AV_SHIFT			0
+
+#define TV_CLR_KNOBS		0x68028
+/** 2s-complement brightness adjustment */
+# define TV_BRIGHTNESS_MASK		0xff000000
+# define TV_BRIGHTNESS_SHIFT		24
+/** Contrast adjustment, as a 2.6 unsigned floating point number */
+# define TV_CONTRAST_MASK		0x00ff0000
+# define TV_CONTRAST_SHIFT		16
+/** Saturation adjustment, as a 2.6 unsigned floating point number */
+# define TV_SATURATION_MASK		0x0000ff00
+# define TV_SATURATION_SHIFT		8
+/** Hue adjustment, as an integer phase angle in degrees */
+# define TV_HUE_MASK			0x000000ff
+# define TV_HUE_SHIFT			0
+
+#define TV_CLR_LEVEL		0x6802c
+/** Controls the DAC level for black */
+# define TV_BLACK_LEVEL_MASK		0x01ff0000
+# define TV_BLACK_LEVEL_SHIFT		16
+/** Controls the DAC level for blanking */
+# define TV_BLANK_LEVEL_MASK		0x000001ff
+# define TV_BLANK_LEVEL_SHIFT		0
+
+#define TV_H_CTL_1		0x68030
+/** Number of pixels in the hsync. */
+# define TV_HSYNC_END_MASK		0x1fff0000
+# define TV_HSYNC_END_SHIFT		16
+/** Total number of pixels minus one in the line (display and blanking). */
+# define TV_HTOTAL_MASK			0x00001fff
+# define TV_HTOTAL_SHIFT		0
+
+#define TV_H_CTL_2		0x68034
+/** Enables the colorburst (needed for non-component color) */
+# define TV_BURST_ENA			(1 << 31)
+/** Offset of the colorburst from the start of hsync, in pixels minus one. */
+# define TV_HBURST_START_SHIFT		16
+# define TV_HBURST_START_MASK		0x1fff0000
+/** Length of the colorburst */
+# define TV_HBURST_LEN_SHIFT		0
+# define TV_HBURST_LEN_MASK		0x0001fff
+
+#define TV_H_CTL_3		0x68038
+/** End of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_END_SHIFT		16
+# define TV_HBLANK_END_MASK		0x1fff0000
+/** Start of hblank, measured in pixels minus one from start of hsync */
+# define TV_HBLANK_START_SHIFT		0
+# define TV_HBLANK_START_MASK		0x0001fff
+
+#define TV_V_CTL_1		0x6803c
+/** XXX */
+# define TV_NBR_END_SHIFT		16
+# define TV_NBR_END_MASK		0x07ff0000
+/** XXX */
+# define TV_VI_END_F1_SHIFT		8
+# define TV_VI_END_F1_MASK		0x00003f00
+/** XXX */
+# define TV_VI_END_F2_SHIFT		0
+# define TV_VI_END_F2_MASK		0x0000003f
+
+#define TV_V_CTL_2		0x68040
+/** Length of vsync, in half lines */
+# define TV_VSYNC_LEN_MASK		0x07ff0000
+# define TV_VSYNC_LEN_SHIFT		16
+/** Offset of the start of vsync in field 1, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F1_MASK		0x00007f00
+# define TV_VSYNC_START_F1_SHIFT	8
+/**
+ * Offset of the start of vsync in field 2, measured in one less than the
+ * number of half lines.
+ */
+# define TV_VSYNC_START_F2_MASK		0x0000007f
+# define TV_VSYNC_START_F2_SHIFT	0
+
+#define TV_V_CTL_3		0x68044
+/** Enables generation of the equalization signal */
+# define TV_EQUAL_ENA			(1 << 31)
+/** Length of vsync, in half lines */
+# define TV_VEQ_LEN_MASK		0x007f0000
+# define TV_VEQ_LEN_SHIFT		16
+/** Offset of the start of equalization in field 1, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F1_MASK		0x0007f00
+# define TV_VEQ_START_F1_SHIFT		8
+/**
+ * Offset of the start of equalization in field 2, measured in one less than
+ * the number of half lines.
+ */
+# define TV_VEQ_START_F2_MASK		0x000007f
+# define TV_VEQ_START_F2_SHIFT		0
+
+#define TV_V_CTL_4		0x68048
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F1_MASK	0x003f0000
+# define TV_VBURST_START_F1_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F1_MASK		0x000000ff
+# define TV_VBURST_END_F1_SHIFT		0
+
+#define TV_V_CTL_5		0x6804c
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F2_MASK	0x003f0000
+# define TV_VBURST_START_F2_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F2_MASK		0x000000ff
+# define TV_VBURST_END_F2_SHIFT		0
+
+#define TV_V_CTL_6		0x68050
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F3_MASK	0x003f0000
+# define TV_VBURST_START_F3_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F3_MASK		0x000000ff
+# define TV_VBURST_END_F3_SHIFT		0
+
+#define TV_V_CTL_7		0x68054
+/**
+ * Offset to start of vertical colorburst, measured in one less than the
+ * number of lines from vertical start.
+ */
+# define TV_VBURST_START_F4_MASK	0x003f0000
+# define TV_VBURST_START_F4_SHIFT	16
+/**
+ * Offset to the end of vertical colorburst, measured in one less than the
+ * number of lines from the start of NBR.
+ */
+# define TV_VBURST_END_F4_MASK		0x000000ff
+# define TV_VBURST_END_F4_SHIFT		0
+
+#define TV_SC_CTL_1		0x68060
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA1_EN			(1 << 31)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA2_EN			(1 << 30)
+/** Turns on the first subcarrier phase generation DDA */
+# define TV_SC_DDA3_EN			(1 << 29)
+/** Sets the subcarrier DDA to reset frequency every other field */
+# define TV_SC_RESET_EVERY_2		(0 << 24)
+/** Sets the subcarrier DDA to reset frequency every fourth field */
+# define TV_SC_RESET_EVERY_4		(1 << 24)
+/** Sets the subcarrier DDA to reset frequency every eighth field */
+# define TV_SC_RESET_EVERY_8		(2 << 24)
+/** Sets the subcarrier DDA to never reset the frequency */
+# define TV_SC_RESET_NEVER		(3 << 24)
+/** Sets the peak amplitude of the colorburst.*/
+# define TV_BURST_LEVEL_MASK		0x00ff0000
+# define TV_BURST_LEVEL_SHIFT		16
+/** Sets the increment of the first subcarrier phase generation DDA */
+# define TV_SCDDA1_INC_MASK		0x00000fff
+# define TV_SCDDA1_INC_SHIFT		0
+
+#define TV_SC_CTL_2		0x68064
+/** Sets the rollover for the second subcarrier phase generation DDA */
+# define TV_SCDDA2_SIZE_MASK		0x7fff0000
+# define TV_SCDDA2_SIZE_SHIFT		16
+/** Sets the increent of the second subcarrier phase generation DDA */
+# define TV_SCDDA2_INC_MASK		0x00007fff
+# define TV_SCDDA2_INC_SHIFT		0
+
+#define TV_SC_CTL_3		0x68068
+/** Sets the rollover for the third subcarrier phase generation DDA */
+# define TV_SCDDA3_SIZE_MASK		0x7fff0000
+# define TV_SCDDA3_SIZE_SHIFT		16
+/** Sets the increent of the third subcarrier phase generation DDA */
+# define TV_SCDDA3_INC_MASK		0x00007fff
+# define TV_SCDDA3_INC_SHIFT		0
+
+#define TV_WIN_POS		0x68070
+/** X coordinate of the display from the start of horizontal active */
+# define TV_XPOS_MASK			0x1fff0000
+# define TV_XPOS_SHIFT			16
+/** Y coordinate of the display from the start of vertical active (NBR) */
+# define TV_YPOS_MASK			0x00000fff
+# define TV_YPOS_SHIFT			0
+
+#define TV_WIN_SIZE		0x68074
+/** Horizontal size of the display window, measured in pixels*/
+# define TV_XSIZE_MASK			0x1fff0000
+# define TV_XSIZE_SHIFT			16
+/**
+ * Vertical size of the display window, measured in pixels.
+ *
+ * Must be even for interlaced modes.
+ */
+# define TV_YSIZE_MASK			0x00000fff
+# define TV_YSIZE_SHIFT			0
+
+#define TV_FILTER_CTL_1		0x68080
+/**
+ * Enables automatic scaling calculation.
+ *
+ * If set, the rest of the registers are ignored, and the calculated values can
+ * be read back from the register.
+ */
+# define TV_AUTO_SCALE			(1 << 31)
+/**
+ * Disables the vertical filter.
+ *
+ * This is required on modes more than 1024 pixels wide */
+# define TV_V_FILTER_BYPASS		(1 << 29)
+/** Enables adaptive vertical filtering */
+# define TV_VADAPT			(1 << 28)
+# define TV_VADAPT_MODE_MASK		(3 << 26)
+/** Selects the least adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_LEAST		(0 << 26)
+/** Selects the moderately adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MODERATE	(1 << 26)
+/** Selects the most adaptive vertical filtering mode */
+# define TV_VADAPT_MODE_MOST		(3 << 26)
+/**
+ * Sets the horizontal scaling factor.
+ *
+ * This should be the fractional part of the horizontal scaling factor divided
+ * by the oversampling rate.  TV_HSCALE should be less than 1, and set to:
+ *
+ * (src width - 1) / ((oversample * dest width) - 1)
+ */
+# define TV_HSCALE_FRAC_MASK		0x00003fff
+# define TV_HSCALE_FRAC_SHIFT		0
+
+#define TV_FILTER_CTL_2		0x68084
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1)
+ */
+# define TV_VSCALE_INT_MASK		0x00038000
+# define TV_VSCALE_INT_SHIFT		15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * \sa TV_VSCALE_INT_MASK
+ */
+# define TV_VSCALE_FRAC_MASK		0x00007fff
+# define TV_VSCALE_FRAC_SHIFT		0
+
+#define TV_FILTER_CTL_3		0x68088
+/**
+ * Sets the integer part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1))
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ */
+# define TV_VSCALE_IP_INT_MASK		0x00038000
+# define TV_VSCALE_IP_INT_SHIFT		15
+/**
+ * Sets the fractional part of the 3.15 fixed-point vertical scaling factor.
+ *
+ * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes.
+ *
+ * \sa TV_VSCALE_IP_INT_MASK
+ */
+# define TV_VSCALE_IP_FRAC_MASK		0x00007fff
+# define TV_VSCALE_IP_FRAC_SHIFT		0
+
+#define TV_CC_CONTROL		0x68090
+# define TV_CC_ENABLE			(1 << 31)
+/**
+ * Specifies which field to send the CC data in.
+ *
+ * CC data is usually sent in field 0.
+ */
+# define TV_CC_FID_MASK			(1 << 27)
+# define TV_CC_FID_SHIFT		27
+/** Sets the horizontal position of the CC data.  Usually 135. */
+# define TV_CC_HOFF_MASK		0x03ff0000
+# define TV_CC_HOFF_SHIFT		16
+/** Sets the vertical position of the CC data.  Usually 21 */
+# define TV_CC_LINE_MASK		0x0000003f
+# define TV_CC_LINE_SHIFT		0
+
+#define TV_CC_DATA		0x68094
+# define TV_CC_RDY			(1 << 31)
+/** Second word of CC data to be transmitted. */
+# define TV_CC_DATA_2_MASK		0x007f0000
+# define TV_CC_DATA_2_SHIFT		16
+/** First word of CC data to be transmitted. */
+# define TV_CC_DATA_1_MASK		0x0000007f
+# define TV_CC_DATA_1_SHIFT		0
+
+#define TV_H_LUMA_0		0x68100
+#define TV_H_LUMA_59		0x681ec
+#define TV_H_CHROMA_0		0x68200
+#define TV_H_CHROMA_59		0x682ec
+#define TV_V_LUMA_0		0x68300
+#define TV_V_LUMA_42		0x683a8
+#define TV_V_CHROMA_0		0x68400
+#define TV_V_CHROMA_42		0x684a8
+
+/* Display & cursor control */
+
+/* Pipe A */
+#define PIPEADSL		0x70000
+#define PIPEACONF		 0x70008
+#define   PIPEACONF_ENABLE	(1<<31)
+#define   PIPEACONF_DISABLE	0
+#define   PIPEACONF_DOUBLE_WIDE	(1<<30)
+#define   I965_PIPECONF_ACTIVE	(1<<30)
+#define   PIPEACONF_SINGLE_WIDE	0
+#define   PIPEACONF_PIPE_UNLOCKED 0
+#define   PIPEACONF_PIPE_LOCKED	(1<<25)
+#define   PIPEACONF_PALETTE	0
+#define   PIPEACONF_GAMMA		(1<<24)
+#define   PIPECONF_FORCE_BORDER	(1<<25)
+#define   PIPECONF_PROGRESSIVE	(0 << 21)
+#define   PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
+#define   PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
+#define PIPEASTAT		0x70024
+#define   PIPE_FIFO_UNDERRUN_STATUS		(1UL<<31)
+#define   PIPE_CRC_ERROR_ENABLE			(1UL<<29)
+#define   PIPE_CRC_DONE_ENABLE			(1UL<<28)
+#define   PIPE_GMBUS_EVENT_ENABLE		(1UL<<27)
+#define   PIPE_HOTPLUG_INTERRUPT_ENABLE		(1UL<<26)
+#define   PIPE_VSYNC_INTERRUPT_ENABLE		(1UL<<25)
+#define   PIPE_DISPLAY_LINE_COMPARE_ENABLE	(1UL<<24)
+#define   PIPE_DPST_EVENT_ENABLE		(1UL<<23)
+#define   PIPE_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)
+#define   PIPE_ODD_FIELD_INTERRUPT_ENABLE	(1UL<<21)
+#define   PIPE_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)
+#define   PIPE_HOTPLUG_TV_INTERRUPT_ENABLE	(1UL<<18) /* pre-965 */
+#define   PIPE_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18) /* 965 or later */
+#define   PIPE_VBLANK_INTERRUPT_ENABLE		(1UL<<17)
+#define   PIPE_OVERLAY_UPDATED_ENABLE		(1UL<<16)
+#define   PIPE_CRC_ERROR_INTERRUPT_STATUS	(1UL<<13)
+#define   PIPE_CRC_DONE_INTERRUPT_STATUS	(1UL<<12)
+#define   PIPE_GMBUS_INTERRUPT_STATUS		(1UL<<11)
+#define   PIPE_HOTPLUG_INTERRUPT_STATUS		(1UL<<10)
+#define   PIPE_VSYNC_INTERRUPT_STATUS		(1UL<<9)
+#define   PIPE_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8)
+#define   PIPE_DPST_EVENT_STATUS		(1UL<<7)
+#define   PIPE_LEGACY_BLC_EVENT_STATUS		(1UL<<6)
+#define   PIPE_ODD_FIELD_INTERRUPT_STATUS	(1UL<<5)
+#define   PIPE_EVEN_FIELD_INTERRUPT_STATUS	(1UL<<4)
+#define   PIPE_HOTPLUG_TV_INTERRUPT_STATUS	(1UL<<2) /* pre-965 */
+#define   PIPE_START_VBLANK_INTERRUPT_STATUS	(1UL<<2) /* 965 or later */
+#define   PIPE_VBLANK_INTERRUPT_STATUS		(1UL<<1)
+#define   PIPE_OVERLAY_UPDATED_STATUS		(1UL<<0)
+
+#define DSPARB			0x70030
+#define   DSPARB_CSTART_MASK	(0x7f << 7)
+#define   DSPARB_CSTART_SHIFT	7
+#define   DSPARB_BSTART_MASK	(0x7f)		 
+#define   DSPARB_BSTART_SHIFT	0
+/*
+ * The two pipe frame counter registers are not synchronized, so
+ * reading a stable value is somewhat tricky. The following code 
+ * should work:
+ *
+ *  do {
+ *    high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ *             PIPE_FRAME_HIGH_SHIFT;
+ *    low1 =  ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
+ *             PIPE_FRAME_LOW_SHIFT);
+ *    high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ *             PIPE_FRAME_HIGH_SHIFT);
+ *  } while (high1 != high2);
+ *  frame = (high1 << 8) | low1;
+ */
+#define PIPEAFRAMEHIGH          0x70040
+#define   PIPE_FRAME_HIGH_MASK    0x0000ffff
+#define   PIPE_FRAME_HIGH_SHIFT   0
+#define PIPEAFRAMEPIXEL         0x70044
+#define   PIPE_FRAME_LOW_MASK     0xff000000
+#define   PIPE_FRAME_LOW_SHIFT    24
+#define   PIPE_PIXEL_MASK         0x00ffffff
+#define   PIPE_PIXEL_SHIFT        0
+
+/* Cursor A & B regs */
+#define CURACNTR		0x70080
+#define   CURSOR_MODE_DISABLE   0x00
+#define   CURSOR_MODE_64_32B_AX 0x07
+#define   CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
+#define   MCURSOR_GAMMA_ENABLE  (1 << 26)
+#define CURABASE		0x70084
+#define CURAPOS			0x70088
+#define   CURSOR_POS_MASK       0x007FF
+#define   CURSOR_POS_SIGN       0x8000
+#define   CURSOR_X_SHIFT        0
+#define   CURSOR_Y_SHIFT        16
+#define CURBCNTR		0x700c0
+#define CURBBASE		0x700c4
+#define CURBPOS			0x700c8
+
+/* Display A control */
+#define DSPACNTR                0x70180
+#define   DISPLAY_PLANE_ENABLE			(1<<31)
+#define   DISPLAY_PLANE_DISABLE			0
+#define   DISPPLANE_GAMMA_ENABLE		(1<<30)
+#define   DISPPLANE_GAMMA_DISABLE		0
+#define   DISPPLANE_PIXFORMAT_MASK		(0xf<<26)
+#define   DISPPLANE_8BPP			(0x2<<26)
+#define   DISPPLANE_15_16BPP			(0x4<<26)
+#define   DISPPLANE_16BPP			(0x5<<26)
+#define   DISPPLANE_32BPP_NO_ALPHA		(0x6<<26)
+#define   DISPPLANE_32BPP			(0x7<<26)
+#define   DISPPLANE_STEREO_ENABLE		(1<<25)
+#define   DISPPLANE_STEREO_DISABLE		0
+#define   DISPPLANE_SEL_PIPE_MASK		(1<<24)
+#define   DISPPLANE_SEL_PIPE_A			0
+#define   DISPPLANE_SEL_PIPE_B			(1<<24)
+#define   DISPPLANE_SRC_KEY_ENABLE		(1<<22)
+#define   DISPPLANE_SRC_KEY_DISABLE		0
+#define   DISPPLANE_LINE_DOUBLE			(1<<20)
+#define   DISPPLANE_NO_LINE_DOUBLE		0
+#define   DISPPLANE_STEREO_POLARITY_FIRST	0
+#define   DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
+#define DSPAADDR		0x70184
+#define DSPASTRIDE		0x70188
+#define DSPAPOS			0x7018C /* reserved */
+#define DSPASIZE		0x70190
+#define DSPASURF		0x7019C /* 965+ only */
+#define DSPATILEOFF		0x701A4 /* 965+ only */
+
+/* VBIOS flags */
+#define SWF00			0x71410
+#define SWF01			0x71414
+#define SWF02			0x71418
+#define SWF03			0x7141c
+#define SWF04			0x71420
+#define SWF05			0x71424
+#define SWF06			0x71428
+#define SWF10			0x70410
+#define SWF11			0x70414
+#define SWF14			0x71420
+#define SWF30			0x72414
+#define SWF31			0x72418
+#define SWF32			0x7241c
+
+/* Pipe B */
+#define PIPEBDSL		0x71000
+#define PIPEBCONF		0x71008
 #define PIPEBSTAT		0x71024
 #define PIPEBFRAMEHIGH		0x71040
 #define PIPEBFRAMEPIXEL		0x71044
 
-#define DSPACNTR		0x70180
+/* Display B control */
 #define DSPBCNTR		0x71180
-#define DISPLAY_PLANE_ENABLE			(1<<31)
-#define DISPLAY_PLANE_DISABLE			0
-#define DISPPLANE_GAMMA_ENABLE			(1<<30)
-#define DISPPLANE_GAMMA_DISABLE			0
-#define DISPPLANE_PIXFORMAT_MASK		(0xf<<26)
-#define DISPPLANE_8BPP				(0x2<<26)
-#define DISPPLANE_15_16BPP			(0x4<<26)
-#define DISPPLANE_16BPP				(0x5<<26)
-#define DISPPLANE_32BPP_NO_ALPHA		(0x6<<26)
-#define DISPPLANE_32BPP				(0x7<<26)
-#define DISPPLANE_STEREO_ENABLE			(1<<25)
-#define DISPPLANE_STEREO_DISABLE		0
-#define DISPPLANE_SEL_PIPE_MASK			(1<<24)
-#define DISPPLANE_SEL_PIPE_A			0
-#define DISPPLANE_SEL_PIPE_B			(1<<24)
-#define DISPPLANE_SRC_KEY_ENABLE		(1<<22)
-#define DISPPLANE_SRC_KEY_DISABLE		0
-#define DISPPLANE_LINE_DOUBLE			(1<<20)
-#define DISPPLANE_NO_LINE_DOUBLE		0
-#define DISPPLANE_STEREO_POLARITY_FIRST		0
-#define DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
-/* plane B only */
-#define DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
-#define DISPPLANE_ALPHA_TRANS_DISABLE		0
-#define DISPPLANE_SPRITE_ABOVE_DISPLAYA		0
-#define DISPPLANE_SPRITE_ABOVE_OVERLAY		(1)
-
-#define DSPABASE		0x70184
-#define DSPASTRIDE		0x70188
-
-#define DSPBBASE		0x71184
-#define DSPBADDR		DSPBBASE
+#define   DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
+#define   DISPPLANE_ALPHA_TRANS_DISABLE		0
+#define   DISPPLANE_SPRITE_ABOVE_DISPLAY	0
+#define   DISPPLANE_SPRITE_ABOVE_OVERLAY	(1)
+#define DSPBADDR		0x71184
 #define DSPBSTRIDE		0x71188
-
-#define DSPAKEYVAL		0x70194
-#define DSPAKEYMASK		0x70198
-
-#define DSPAPOS			0x7018C /* reserved */
-#define DSPASIZE		0x70190
 #define DSPBPOS			0x7118C
 #define DSPBSIZE		0x71190
-
-#define DSPASURF		0x7019C
-#define DSPATILEOFF		0x701A4
-
 #define DSPBSURF		0x7119C
 #define DSPBTILEOFF		0x711A4
 
+/* VBIOS regs */
 #define VGACNTRL		0x71400
 # define VGA_DISP_DISABLE			(1 << 31)
 # define VGA_2X_MODE				(1 << 30)
 # define VGA_PIPE_B_SELECT			(1 << 29)
 
-/*
- * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
- * of video memory available to the BIOS in SWF1.
- */
-
-#define SWF0			0x71410
-
-/*
- * 855 scratch registers.
- */
-#define SWF10			0x70410
-
-#define SWF30			0x72414
-
-/*
- * Overlay registers.  These are overlay registers accessed via MMIO.
- * Those loaded via the overlay register page are defined in i830_video.c.
- */
-#define OVADD			0x30000
-
-#define DOVSTA			0x30008
-#define OC_BUF			(0x3<<20)
-
-#define OGAMC5			0x30010
-#define OGAMC4			0x30014
-#define OGAMC3			0x30018
-#define OGAMC2			0x3001c
-#define OGAMC1			0x30020
-#define OGAMC0			0x30024
-/*
- * Palette registers
- */
-#define PALETTE_A		0x0a000
-#define PALETTE_B		0x0a800
+/* Chipset type macros */
 
 #define IS_I830(dev) ((dev)->pci_device == 0x3577)
 #define IS_845G(dev) ((dev)->pci_device == 0x2562)
@@ -1158,19 +2085,29 @@
 #define IS_I855(dev) ((dev)->pci_device == 0x3582)
 #define IS_I865G(dev) ((dev)->pci_device == 0x2572)
 
-#define IS_I915G(dev) (dev->pci_device == 0x2582)/* || dev->pci_device == PCI_DEVICE_ID_INTELPCI_CHIP_E7221_G)*/
+#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a)
 #define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
 #define IS_I945G(dev) ((dev)->pci_device == 0x2772)
-#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2)
-
+#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\
+		        (dev)->pci_device == 0x27AE)
 #define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
 		       (dev)->pci_device == 0x2982 || \
 		       (dev)->pci_device == 0x2992 || \
 		       (dev)->pci_device == 0x29A2 || \
 		       (dev)->pci_device == 0x2A02 || \
-		       (dev)->pci_device == 0x2A12)
+		       (dev)->pci_device == 0x2A12 || \
+		       (dev)->pci_device == 0x2A42 || \
+		       (dev)->pci_device == 0x2E02 || \
+		       (dev)->pci_device == 0x2E12 || \
+		       (dev)->pci_device == 0x2E22)
 
 #define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
+
+#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
+
+#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
+		     (dev)->pci_device == 0x2E12 || \
+		     (dev)->pci_device == 0x2E22)
 
 #define IS_G33(dev)    ((dev)->pci_device == 0x29C2 ||	\
 			(dev)->pci_device == 0x29B2 ||	\
@@ -1180,8 +2117,8 @@
 		      IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
 
 #define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
-			IS_I945GM(dev) || IS_I965GM(dev))
+			IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev))
 
-#define PRIMARY_RINGBUFFER_SIZE         (128*1024)
+#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
 
 #endif
diff --git a/sys/dev/drm/i915_irq.c b/sys/dev/drm/i915_irq.c
--- a/sys/dev/drm/i915_irq.c
+++ b/sys/dev/drm/i915_irq.c
@@ -32,20 +32,43 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-#define USER_INT_FLAG (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
+#define MAX_NOPID ((u32)~0)
 
-#define MAX_NOPID ((u32)~0)
+/*
+ * These are the interrupts used by the driver
+ */
+#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \
+				    I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
+				    I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+
+static inline void
+i915_enable_irq(drm_i915_private_t *dev_priv, uint32_t mask)
+{
+	if ((dev_priv->irq_mask_reg & mask) != 0) {
+		dev_priv->irq_mask_reg &= ~mask;
+		I915_WRITE(IMR, dev_priv->irq_mask_reg);
+		(void) I915_READ(IMR);
+	}
+}
+
+static inline void
+i915_disable_irq(drm_i915_private_t *dev_priv, uint32_t mask)
+{
+	if ((dev_priv->irq_mask_reg & mask) != mask) {
+		dev_priv->irq_mask_reg |= mask;
+		I915_WRITE(IMR, dev_priv->irq_mask_reg);
+		(void) I915_READ(IMR);
+	}
+}
 
 /**
  * i915_get_pipe - return the the pipe associated with a given plane
  * @dev: DRM device
  * @plane: plane to look for
  *
- * We need to get the pipe associated with a given plane to correctly perform
- * vblank driven swapping, and they may not always be equal.  So look up the
- * pipe associated with @plane here.
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a pipe number, since they may not always be equal.  This routine
+ * maps the given @plane back to a pipe number.
  */
 static int
 i915_get_pipe(struct drm_device *dev, int plane)
@@ -56,6 +79,44 @@
 	dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
 
 	return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
+}
+
+/**
+ * i915_get_plane - return the the plane associated with a given pipe
+ * @dev: DRM device
+ * @pipe: pipe to look for
+ *
+ * The Intel Mesa & 2D drivers call the vblank routines with a plane number
+ * rather than a plane number, since they may not always be equal.  This routine
+ * maps the given @pipe back to a plane number.
+ */
+static int
+i915_get_plane(struct drm_device *dev, int pipe)
+{
+	if (i915_get_pipe(dev, 0) == pipe)
+		return 0;
+	return 1;
+}
+
+/**
+ * i915_pipe_enabled - check if a pipe is enabled
+ * @dev: DRM device
+ * @pipe: pipe to check
+ *
+ * Reading certain registers when the pipe is disabled can hang the chip.
+ * Use this routine to make sure the PLL is running and the pipe is active
+ * before reading such registers if unsure.
+ */
+static int
+i915_pipe_enabled(struct drm_device *dev, int pipe)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
+
+	if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
+		return 1;
+
+	return 0;
 }
 
 /**
@@ -115,8 +176,7 @@
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	struct list_head *list, *tmp, hits, *hit;
 	int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
-	unsigned counter[2] = { atomic_read(&dev->vbl_received),
-				atomic_read(&dev->vbl_received2) };
+	unsigned counter[2];
 	struct drm_drawable_info *drw;
 	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	u32 cpp = dev_priv->cpp,  offsets[3];
@@ -124,9 +184,23 @@
 				XY_SRC_COPY_BLT_WRITE_ALPHA |
 				XY_SRC_COPY_BLT_WRITE_RGB)
 			     : XY_SRC_COPY_BLT_CMD;
-	u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
-			  (cpp << 23) | (1 << 24);
+	u32 src_pitch = sarea_priv->pitch * cpp;
+	u32 dst_pitch = sarea_priv->pitch * cpp;
+	/* COPY rop (0xcc), map cpp to magic color depth constants */
+	u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
 	RING_LOCALS;
+	
+	if (IS_I965G(dev) && sarea_priv->front_tiled) {
+		cmd |= XY_SRC_COPY_BLT_DST_TILED;
+		dst_pitch >>= 2;
+	}
+	if (IS_I965G(dev) && sarea_priv->back_tiled) {
+		cmd |= XY_SRC_COPY_BLT_SRC_TILED;
+		src_pitch >>= 2;
+	}
+	
+	counter[0] = drm_vblank_count(dev, 0);
+	counter[1] = drm_vblank_count(dev, 1);
 
 	DRM_DEBUG("\n");
 
@@ -152,6 +226,7 @@
 
 		list_del(list);
 		dev_priv->swaps_pending--;
+		drm_vblank_put(dev, pipe);
 
 		DRM_SPINUNLOCK(&dev_priv->swaps_lock);
 		DRM_SPINLOCK(&dev->drw_lock);
@@ -243,16 +318,29 @@
 			}
 
 			if (init_drawrect) {
-				BEGIN_LP_RING(6);
+				int width  = sarea_priv->width;
+				int height = sarea_priv->height;
+				if (IS_I965G(dev)) {
+					BEGIN_LP_RING(4);
 
-				OUT_RING(GFX_OP_DRAWRECT_INFO);
-				OUT_RING(0);
-				OUT_RING(0);
-				OUT_RING(sarea_priv->width | sarea_priv->height << 16);
-				OUT_RING(sarea_priv->width | sarea_priv->height << 16);
-				OUT_RING(0);
-
-				ADVANCE_LP_RING();
+					OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
+					OUT_RING(0);
+					OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
+					OUT_RING(0);
+					
+					ADVANCE_LP_RING();
+				} else {
+					BEGIN_LP_RING(6);
+	
+					OUT_RING(GFX_OP_DRAWRECT_INFO);
+					OUT_RING(0);
+					OUT_RING(0);
+					OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
+					OUT_RING(0);
+					OUT_RING(0);
+					
+					ADVANCE_LP_RING();
+				}
 
 				sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
 
@@ -277,12 +365,12 @@
 				BEGIN_LP_RING(8);
 
 				OUT_RING(cmd);
-				OUT_RING(pitchropcpp);
+				OUT_RING(ropcpp | dst_pitch);
 				OUT_RING((y1 << 16) | rect->x1);
 				OUT_RING((y2 << 16) | rect->x2);
 				OUT_RING(offsets[front]);
 				OUT_RING((y1 << 16) | rect->x1);
-				OUT_RING(pitchropcpp & 0xffff);
+				OUT_RING(src_pitch);
 				OUT_RING(offsets[back]);
 
 				ADVANCE_LP_RING();
@@ -302,65 +390,143 @@
 	}
 }
 
+u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	unsigned long high_frame;
+	unsigned long low_frame;
+	u32 high1, high2, low, count;
+	int pipe;
+
+	pipe = i915_get_pipe(dev, plane);
+	high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
+	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
+
+	if (!i915_pipe_enabled(dev, pipe)) {
+	    DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
+	    return 0;
+	}
+
+	/*
+	 * High & low register fields aren't synchronized, so make sure
+	 * we get a low value that's stable across two reads of the high
+	 * register.
+	 */
+	do {
+		high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+			 PIPE_FRAME_HIGH_SHIFT);
+		low =  ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+			PIPE_FRAME_LOW_SHIFT);
+		high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+			 PIPE_FRAME_HIGH_SHIFT);
+	} while (high1 != high2);
+
+	count = (high1 << 8) | low;
+
+	return count;
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u16 temp;
-	u32 pipea_stats, pipeb_stats;
+	u32 iir;
+	u32 pipea_stats = 0, pipeb_stats = 0;
+	int vblank = 0;
+#ifdef __linux__
+	if (dev->pdev->msi_enabled)
+		I915_WRITE(IMR, ~0);
+#endif
+	iir = I915_READ(IIR);
+#if 0
+	DRM_DEBUG("flag=%08x\n", iir);
+#endif
+	atomic_inc(&dev_priv->irq_received);
+	if (iir == 0) {
+#ifdef __linux__
+		if (dev->pdev->msi_enabled) {
+			I915_WRITE(IMR, dev_priv->irq_mask_reg);
+			(void) I915_READ(IMR);
+		}
+#endif
+		return IRQ_NONE;
+	}
 
-	pipea_stats = I915_READ(I915REG_PIPEASTAT);
-	pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+	/*
+	 * Clear the PIPE(A|B)STAT regs before the IIR otherwise
+	 * we may get extra interrupts.
+	 */
+	if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
+		pipea_stats = I915_READ(PIPEASTAT);
 
-	temp = I915_READ16(I915REG_INT_IDENTITY_R);
-	temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG);
+		/* The vblank interrupt gets enabled even if we didn't ask for
+		   it, so make sure it's shut down again */
+		if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A))
+			pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+					 PIPE_VBLANK_INTERRUPT_ENABLE);
+		else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
+					PIPE_VBLANK_INTERRUPT_STATUS))
+		{
+			vblank++;
+			drm_handle_vblank(dev, i915_get_plane(dev, 0));
+		}
 
-#if 0
-	DRM_DEBUG("flag=%08x\n", temp);
+		I915_WRITE(PIPEASTAT, pipea_stats);
+	}
+	if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
+		pipeb_stats = I915_READ(PIPEBSTAT);
+
+		/* The vblank interrupt gets enabled even if we didn't ask for
+		   it, so make sure it's shut down again */
+		if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
+			pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+					 PIPE_VBLANK_INTERRUPT_ENABLE);
+		else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
+					PIPE_VBLANK_INTERRUPT_STATUS))
+		{
+			vblank++;
+			drm_handle_vblank(dev, i915_get_plane(dev, 1));
+		}
+
+#ifdef __linux__
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
+		if (pipeb_stats & I915_LEGACY_BLC_EVENT_ENABLE)
+			opregion_asle_intr(dev);
 #endif
-	if (temp == 0)
-		return IRQ_NONE;
+#endif
+		I915_WRITE(PIPEBSTAT, pipeb_stats);
+	}
 
-	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
-	(void) I915_READ16(I915REG_INT_IDENTITY_R);
-	DRM_READMEMORYBARRIER();
+#ifdef __linux__
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
+	if (iir & I915_ASLE_INTERRUPT)
+		opregion_asle_intr(dev);
+#endif
+#endif
 
-	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+	if (dev_priv->sarea_priv)
+	    dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
 
-	if (temp & USER_INT_FLAG) {
+	I915_WRITE(IIR, iir);
+#ifdef __linux__
+	if (dev->pdev->msi_enabled)
+		I915_WRITE(IMR, dev_priv->irq_mask_reg);
+#endif
+	(void) I915_READ(IIR); /* Flush posted writes */
+
+	if (iir & I915_USER_INTERRUPT) {
+#ifdef I915_HAVE_GEM
+		dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
+#endif
 		DRM_WAKEUP(&dev_priv->irq_queue);
 #ifdef I915_HAVE_FENCE
 		i915_fence_handler(dev);
 #endif
 	}
 
-	if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
-		int vblank_pipe = dev_priv->vblank_pipe;
-
-		if ((vblank_pipe &
-		     (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
-		    == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
-			if (temp & VSYNC_PIPEA_FLAG)
-				atomic_inc(&dev->vbl_received);
-			if (temp & VSYNC_PIPEB_FLAG)
-				atomic_inc(&dev->vbl_received2);
-		} else if (((temp & VSYNC_PIPEA_FLAG) &&
-			    (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
-			   ((temp & VSYNC_PIPEB_FLAG) &&
-			    (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
-			atomic_inc(&dev->vbl_received);
-
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
-
+	if (vblank) {
 		if (dev_priv->swaps_pending > 0)
 			drm_locked_tasklet(dev, i915_vblank_tasklet);
-		I915_WRITE(I915REG_PIPEASTAT,
-			pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
-			I915_VBLANK_CLEAR);
-		I915_WRITE(I915REG_PIPEBSTAT,
-			pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
-			I915_VBLANK_CLEAR);
 	}
 
 	return IRQ_HANDLED;
@@ -379,7 +545,7 @@
 
 	BEGIN_LP_RING(2);
 	OUT_RING(0);
-	OUT_RING(GFX_OP_USER_INTERRUPT);
+	OUT_RING(MI_USER_INTERRUPT);
 	ADVANCE_LP_RING();
 
 	return dev_priv->counter;
@@ -388,37 +554,42 @@
 void i915_user_irq_on(drm_i915_private_t *dev_priv)
 {
 	DRM_SPINLOCK(&dev_priv->user_irq_lock);
-	if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){
-		dev_priv->irq_enable_reg |= USER_INT_FLAG;
-		I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
-	}
+	if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1))
+		i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
 	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
-
 }
 
 void i915_user_irq_off(drm_i915_private_t *dev_priv)
 {
 	DRM_SPINLOCK(&dev_priv->user_irq_lock);
-	if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
-		/*
-		dev_priv->irq_enable_reg &= ~USER_INT_FLAG;
-		I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
-		*/
-	}
+#ifdef __linux__
+	BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0);
+#endif
+	if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0))
+		i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
 	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
 }
 
 
-static int i915_wait_irq(struct drm_device * dev, int irq_nr)
+int i915_wait_irq(struct drm_device * dev, int irq_nr)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int ret = 0;
 
+	if (!dev_priv) {
+		DRM_ERROR("called with no initialization\n");
+		return -EINVAL;
+	}
+
 	DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
 		  READ_BREADCRUMB(dev_priv));
 
-	if (READ_BREADCRUMB(dev_priv) >= irq_nr)
+	if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
+		if (dev_priv->sarea_priv)
+			dev_priv->sarea_priv->last_dispatch =
+				READ_BREADCRUMB(dev_priv);
 		return 0;
+	}
 
 	i915_user_irq_on(dev_priv);
 	DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
@@ -430,53 +601,10 @@
 			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
 	}
 
-	dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+	if (dev_priv->sarea_priv)
+		dev_priv->sarea_priv->last_dispatch =
+			READ_BREADCRUMB(dev_priv);
 	return ret;
-}
-
-static int i915_driver_vblank_do_wait(struct drm_device *dev,
-				      unsigned int *sequence,
-				      atomic_t *counter)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	unsigned int cur_vblank;
-	int ret = 0;
-
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(counter))
-			- *sequence) <= (1<<23)));
-
-	*sequence = cur_vblank;
-
-	return ret;
-}
-
-int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-	atomic_t *counter;
-
-	if (i915_get_pipe(dev, 0) == 0)
-		counter = &dev->vbl_received;
-	else
-		counter = &dev->vbl_received2;
-	return i915_driver_vblank_do_wait(dev, sequence, counter);
-}
-
-int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-	atomic_t *counter;
-
-	if (i915_get_pipe(dev, 1) == 0)
-		counter = &dev->vbl_received;
-	else
-		counter = &dev->vbl_received2;
-
-	return i915_driver_vblank_do_wait(dev, sequence, counter);
 }
 
 /* Needs the lock as it touches the ring.
@@ -521,23 +649,130 @@
 	return i915_wait_irq(dev, irqwait->irq_seq);
 }
 
+int i915_enable_vblank(struct drm_device *dev, int plane)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe = i915_get_pipe(dev, plane);
+	u32	pipestat_reg = 0;
+	u32	mask_reg = 0;
+	u32	pipestat;
+
+	switch (pipe) {
+	case 0:
+		pipestat_reg = PIPEASTAT;
+		mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+		break;
+	case 1:
+		pipestat_reg = PIPEBSTAT;
+		mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+		break;
+	default:
+		DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
+			  pipe);
+		break;
+	}
+
+	if (pipestat_reg)
+	{
+		pipestat = I915_READ (pipestat_reg);
+		/*
+		 * Older chips didn't have the start vblank interrupt,
+		 * but 
+		 */
+		if (IS_I965G (dev))
+			pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE;
+		else
+			pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE;
+		/*
+		 * Clear any pending status
+		 */
+		pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
+			     PIPE_VBLANK_INTERRUPT_STATUS);
+		I915_WRITE(pipestat_reg, pipestat);
+	}
+	DRM_SPINLOCK(&dev_priv->user_irq_lock);
+	i915_enable_irq(dev_priv, mask_reg);
+	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
+
+	return 0;
+}
+
+void i915_disable_vblank(struct drm_device *dev, int plane)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe = i915_get_pipe(dev, plane);
+	u32	pipestat_reg = 0;
+	u32	mask_reg = 0;
+	u32	pipestat;
+
+	switch (pipe) {
+	case 0:
+		pipestat_reg = PIPEASTAT;
+		mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+		break;
+	case 1:
+		pipestat_reg = PIPEBSTAT;
+		mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+		break;
+	default:
+		DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
+			  pipe);
+		break;
+	}
+
+	DRM_SPINLOCK(&dev_priv->user_irq_lock);
+	i915_disable_irq(dev_priv, mask_reg);
+	DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
+
+	if (pipestat_reg)
+	{
+		pipestat = I915_READ (pipestat_reg);
+		pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE |
+			      PIPE_VBLANK_INTERRUPT_ENABLE);
+		/*
+		 * Clear any pending status
+		 */
+		pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS |
+			     PIPE_VBLANK_INTERRUPT_STATUS);
+		I915_WRITE(pipestat_reg, pipestat);
+		(void) I915_READ(pipestat_reg);
+	}
+}
+
 static void i915_enable_interrupt (struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	dev_priv->irq_enable_reg = USER_INT_FLAG;
-	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
-		dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
-	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
-		dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG;
+	dev_priv->irq_mask_reg = ~0;
+	I915_WRITE(IMR, dev_priv->irq_mask_reg);
+	I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
+	(void) I915_READ (IER);
 
-	I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+#ifdef __linux__
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
+	opregion_enable_asle(dev);
+#endif
+#endif
+
 	dev_priv->irq_enabled = 1;
 }
 
 /* Set the vblank monitor pipe
  */
 int i915_vblank_pipe_set(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (!dev_priv) {
+		DRM_ERROR("called with no initialization\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int i915_vblank_pipe_get(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -548,36 +783,7 @@
 		return -EINVAL;
 	}
 
-	if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
-		DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe);
-		return -EINVAL;
-	}
-
-	dev_priv->vblank_pipe = pipe->pipe;
-
-	i915_enable_interrupt (dev);
-
-	return 0;
-}
-
-int i915_vblank_pipe_get(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	drm_i915_vblank_pipe_t *pipe = data;
-	u16 flag;
-
-	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
-		return -EINVAL;
-	}
-
-	flag = I915_READ(I915REG_INT_ENABLE_R);
-	pipe->pipe = 0;
-	if (flag & VSYNC_PIPEA_FLAG)
-		pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
-	if (flag & VSYNC_PIPEB_FLAG)
-		pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
+	pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
 	return 0;
 }
@@ -594,13 +800,14 @@
 	unsigned int pipe, seqtype, curseq, plane;
 	unsigned long irqflags;
 	struct list_head *list;
+	int ret;
 
 	if (!dev_priv) {
 		DRM_ERROR("%s called with no initialization\n", __func__);
 		return -EINVAL;
 	}
 
-	if (dev_priv->sarea_priv->rotation) {
+	if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) {
 		DRM_DEBUG("Rotation not supported\n");
 		return -EINVAL;
 	}
@@ -637,7 +844,14 @@
 
 	DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags);
 
-	curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+	/*
+	 * We take the ref here and put it when the swap actually completes
+	 * in the tasklet.
+	 */
+	ret = drm_vblank_get(dev, pipe);
+	if (ret)
+		return ret;
+	curseq = drm_vblank_count(dev, pipe);
 
 	if (seqtype == _DRM_VBLANK_RELATIVE)
 		swap->sequence += curseq;
@@ -647,6 +861,7 @@
 			swap->sequence = curseq + 1;
 		} else {
 			DRM_DEBUG("Missed target sequence\n");
+			drm_vblank_put(dev, pipe);
 			return -EINVAL;
 		}
 	}
@@ -668,6 +883,7 @@
 				    irqflags);
 				DRM_DEBUG("Invalid drawable ID %d\n",
 					  swap->drawable);
+				drm_vblank_put(dev, pipe);
 				return -EINVAL;
 			}
 
@@ -675,6 +891,7 @@
 
 			DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags);
 
+			drm_vblank_put(dev, pipe);
 			return 0;
 		}
 	}
@@ -698,6 +915,7 @@
 
 	if (dev_priv->swaps_pending >= 100) {
 		DRM_DEBUG("Too many swaps queued\n");
+		drm_vblank_put(dev, pipe);
 		return -EBUSY;
 	}
 
@@ -705,6 +923,7 @@
 
 	if (!vbl_swap) {
 		DRM_ERROR("Failed to allocate memory to queue swap\n");
+		drm_vblank_put(dev, pipe);
 		return -ENOMEM;
 	}
 
@@ -734,21 +953,28 @@
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	I915_WRITE16(I915REG_HWSTAM, 0xeffe);
-	I915_WRITE16(I915REG_INT_MASK_R, 0x0);
-	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+	I915_WRITE(HWSTAM, 0xeffe);
+	I915_WRITE(IMR, 0xffffffff);
+	I915_WRITE(IER, 0x0);
 }
 
-void i915_driver_irq_postinstall(struct drm_device * dev)
+int i915_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int ret, num_pipes = 2;
 
-	DRM_SPININIT(&dev_priv->swaps_lock, "swap");
 	INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
 	dev_priv->swaps_pending = 0;
 
-	DRM_SPININIT(&dev_priv->user_irq_lock, "userirq");
 	dev_priv->user_irq_refcount = 0;
+	dev_priv->irq_mask_reg = ~0;
+
+	ret = drm_vblank_init(dev, num_pipes);
+	if (ret)
+		return ret;
+
+	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
+	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
 
 	i915_enable_interrupt(dev);
 	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
@@ -757,22 +983,29 @@
 	 * Initialize the hardware status page IRQ location.
 	 */
 
-	I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
+	I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
+	return 0;
 }
 
 void i915_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u16 temp;
+	u32 temp;
 
 	if (!dev_priv)
 		return;
 
+	dev_priv->vblank_pipe = 0;
+
 	dev_priv->irq_enabled = 0;
-	I915_WRITE16(I915REG_HWSTAM, 0xffff);
-	I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
-	I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+	I915_WRITE(HWSTAM, 0xffffffff);
+	I915_WRITE(IMR, 0xffffffff);
+	I915_WRITE(IER, 0x0);
 
-	temp = I915_READ16(I915REG_INT_IDENTITY_R);
-	I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+	temp = I915_READ(PIPEASTAT);
+	I915_WRITE(PIPEASTAT, temp);
+	temp = I915_READ(PIPEBSTAT);
+	I915_WRITE(PIPEBSTAT, temp);
+	temp = I915_READ(IIR);
+	I915_WRITE(IIR, temp);
 }
diff --git a/sys/dev/drm/i915_suspend.c b/sys/dev/drm/i915_suspend.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/drm/i915_suspend.c
@@ -0,0 +1,521 @@
+/* i915_suspend.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
+ */
+/*
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * $DragonFly$
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+static boolean_t i915_pipe_enabled(struct drm_device *dev, enum i915_pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (pipe == PIPE_A)
+		return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
+	else
+		return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
+}
+
+static void i915_save_palette(struct drm_device *dev, enum i915_pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+	u32 *array;
+	int i;
+
+	if (!i915_pipe_enabled(dev, pipe))
+		return;
+
+	if (pipe == PIPE_A)
+		array = dev_priv->save_palette_a;
+	else
+		array = dev_priv->save_palette_b;
+
+	for(i = 0; i < 256; i++)
+		array[i] = I915_READ(reg + (i << 2));
+}
+
+static void i915_restore_palette(struct drm_device *dev, enum i915_pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+	u32 *array;
+	int i;
+
+	if (!i915_pipe_enabled(dev, pipe))
+		return;
+
+	if (pipe == PIPE_A)
+		array = dev_priv->save_palette_a;
+	else
+		array = dev_priv->save_palette_b;
+
+	for(i = 0; i < 256; i++)
+		I915_WRITE(reg + (i << 2), array[i]);
+}
+
+static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE8(index_port, reg);
+	return I915_READ8(data_port);
+}
+
+static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_READ8(st01);
+	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
+	return I915_READ8(VGA_AR_DATA_READ);
+}
+
+static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_READ8(st01);
+	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
+	I915_WRITE8(VGA_AR_DATA_WRITE, val);
+}
+
+static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE8(index_port, reg);
+	I915_WRITE8(data_port, val);
+}
+
+static void i915_save_vga(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+	u16 cr_index, cr_data, st01;
+
+	/* VGA color palette registers */
+	dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
+	/* DACCRX automatically increments during read */
+	I915_WRITE8(VGA_DACRX, 0);
+	/* Read 3 bytes of color data from each index */
+	for (i = 0; i < 256 * 3; i++)
+		dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);
+
+	/* MSR bits */
+	dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
+	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+		cr_index = VGA_CR_INDEX_CGA;
+		cr_data = VGA_CR_DATA_CGA;
+		st01 = VGA_ST01_CGA;
+	} else {
+		cr_index = VGA_CR_INDEX_MDA;
+		cr_data = VGA_CR_DATA_MDA;
+		st01 = VGA_ST01_MDA;
+	}
+
+	/* CRT controller regs */
+	i915_write_indexed(dev, cr_index, cr_data, 0x11,
+			   i915_read_indexed(dev, cr_index, cr_data, 0x11) &
+			   (~0x80));
+	for (i = 0; i <= 0x24; i++)
+		dev_priv->saveCR[i] =
+			i915_read_indexed(dev, cr_index, cr_data, i);
+	/* Make sure we don't turn off CR group 0 writes */
+	dev_priv->saveCR[0x11] &= ~0x80;
+
+	/* Attribute controller registers */
+	I915_READ8(st01);
+	dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
+	for (i = 0; i <= 0x14; i++)
+		dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0);
+	I915_READ8(st01);
+	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX);
+	I915_READ8(st01);
+
+	/* Graphics controller registers */
+	for (i = 0; i < 9; i++)
+		dev_priv->saveGR[i] =
+			i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
+
+	dev_priv->saveGR[0x10] =
+		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
+	dev_priv->saveGR[0x11] =
+		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
+	dev_priv->saveGR[0x18] =
+		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
+
+	/* Sequencer registers */
+	for (i = 0; i < 8; i++)
+		dev_priv->saveSR[i] =
+			i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
+}
+
+static void i915_restore_vga(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+	u16 cr_index, cr_data, st01;
+
+	/* MSR bits */
+	I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR);
+	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+		cr_index = VGA_CR_INDEX_CGA;
+		cr_data = VGA_CR_DATA_CGA;
+		st01 = VGA_ST01_CGA;
+	} else {
+		cr_index = VGA_CR_INDEX_MDA;
+		cr_data = VGA_CR_DATA_MDA;
+		st01 = VGA_ST01_MDA;
+	}
+
+	/* Sequencer registers, don't write SR07 */
+	for (i = 0; i < 7; i++)
+		i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
+				   dev_priv->saveSR[i]);
+
+	/* CRT controller regs */
+	/* Enable CR group 0 writes */
+	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
+	for (i = 0; i <= 0x24; i++)
+		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]);
+
+	/* Graphics controller regs */
+	for (i = 0; i < 9; i++)
+		i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
+				   dev_priv->saveGR[i]);
+
+	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
+			   dev_priv->saveGR[0x10]);
+	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
+			   dev_priv->saveGR[0x11]);
+	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
+			   dev_priv->saveGR[0x18]);
+
+	/* Attribute controller registers */
+	I915_READ8(st01); /* switch back to index mode */
+	for (i = 0; i <= 0x14; i++)
+		i915_write_ar(dev, st01, i, dev_priv->saveAR[i], 0);
+	I915_READ8(st01); /* switch back to index mode */
+	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX | 0x20);
+	I915_READ8(st01);
+
+	/* VGA color palette registers */
+	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
+	/* DACCRX automatically increments during read */
+	I915_WRITE8(VGA_DACWX, 0);
+	/* Read 3 bytes of color data from each index */
+	for (i = 0; i < 256 * 3; i++)
+		I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);
+
+}
+
+int i915_save_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+#if (defined(__FreeBSD__) || defined(__DragonFly__))
+	dev_priv->saveLBB = (u8) pci_read_config(dev->device, LBB, 1);
+#else
+	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
+#endif
+
+	/* Display arbitration control */
+	dev_priv->saveDSPARB = I915_READ(DSPARB);
+
+	/* Pipe & plane A info */
+	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
+	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
+	dev_priv->saveFPA0 = I915_READ(FPA0);
+	dev_priv->saveFPA1 = I915_READ(FPA1);
+	dev_priv->saveDPLL_A = I915_READ(DPLL_A);
+	if (IS_I965G(dev))
+		dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
+	dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
+	dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
+	dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
+	dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
+	dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
+	dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
+	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+	dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
+	dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
+	dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
+	dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
+	dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
+	if (IS_I965G(dev)) {
+		dev_priv->saveDSPASURF = I915_READ(DSPASURF);
+		dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
+	}
+	i915_save_palette(dev, PIPE_A);
+	dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
+
+	/* Pipe & plane B info */
+	dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
+	dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
+	dev_priv->saveFPB0 = I915_READ(FPB0);
+	dev_priv->saveFPB1 = I915_READ(FPB1);
+	dev_priv->saveDPLL_B = I915_READ(DPLL_B);
+	if (IS_I965G(dev))
+		dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
+	dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
+	dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
+	dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
+	dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
+	dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
+	dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
+	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+	dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
+	dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
+	dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
+	dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
+	dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
+	if (IS_I965GM(dev) || IS_GM45(dev)) {
+		dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
+		dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
+	}
+	i915_save_palette(dev, PIPE_B);
+	dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
+
+	/* CRT state */
+	dev_priv->saveADPA = I915_READ(ADPA);
+
+	/* LVDS state */
+	dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
+	dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
+	dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+	if (IS_I965G(dev))
+		dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+	if (IS_MOBILE(dev) && !IS_I830(dev))
+		dev_priv->saveLVDS = I915_READ(LVDS);
+	if (!IS_I830(dev) && !IS_845G(dev))
+		dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
+	dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
+	dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
+	dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
+
+	/* FIXME: save TV & SDVO state */
+
+	/* FBC state */
+	dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
+	dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
+	dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
+	dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
+
+	/* Interrupt state */
+	dev_priv->saveIIR = I915_READ(IIR);
+	dev_priv->saveIER = I915_READ(IER);
+	dev_priv->saveIMR = I915_READ(IMR);
+
+	/* VGA state */
+	dev_priv->saveVGA0 = I915_READ(VGA0);
+	dev_priv->saveVGA1 = I915_READ(VGA1);
+	dev_priv->saveVGA_PD = I915_READ(VGA_PD);
+	dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
+
+	/* Clock gating state */
+	dev_priv->saveD_STATE = I915_READ(D_STATE);
+	dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
+
+	/* Cache mode state */
+	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
+
+	/* Memory Arbitration state */
+	dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
+
+	/* Scratch space */
+	for (i = 0; i < 16; i++) {
+		dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
+		dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
+	}
+	for (i = 0; i < 3; i++)
+		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
+
+	i915_save_vga(dev);
+
+	return 0;
+}
+
+int i915_restore_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+#if (defined(__FreeBSD__) || defined(__DragonFly__))
+	pci_write_config(dev->device, LBB, dev_priv->saveLBB, 1);
+#else
+	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
+#endif
+
+	I915_WRITE(DSPARB, dev_priv->saveDSPARB);
+
+	/* Pipe & plane A info */
+	/* Prime the clock */
+	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
+		I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
+			   ~DPLL_VCO_ENABLE);
+		DRM_UDELAY(150);
+	}
+	I915_WRITE(FPA0, dev_priv->saveFPA0);
+	I915_WRITE(FPA1, dev_priv->saveFPA1);
+	/* Actually enable it */
+	I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+	DRM_UDELAY(150);
+	if (IS_I965G(dev))
+		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+	DRM_UDELAY(150);
+
+	/* Restore mode */
+	I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
+	I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
+	I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
+	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
+	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
+	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
+	I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+
+	/* Restore plane info */
+	I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
+	I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
+	I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
+	I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
+	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+	if (IS_I965G(dev)) {
+		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
+		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+	}
+
+	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+
+	i915_restore_palette(dev, PIPE_A);
+	/* Enable the plane */
+	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
+	I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
+
+	/* Pipe & plane B info */
+	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
+		I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
+			   ~DPLL_VCO_ENABLE);
+		DRM_UDELAY(150);
+	}
+	I915_WRITE(FPB0, dev_priv->saveFPB0);
+	I915_WRITE(FPB1, dev_priv->saveFPB1);
+	/* Actually enable it */
+	I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+	DRM_UDELAY(150);
+	if (IS_I965G(dev))
+		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+	DRM_UDELAY(150);
+
+	/* Restore mode */
+	I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
+	I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
+	I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
+	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
+	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
+	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
+	I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+
+	/* Restore plane info */
+	I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
+	I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
+	I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
+	I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
+	I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+	if (IS_I965G(dev)) {
+		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
+		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+	}
+
+	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+
+	i915_restore_palette(dev, PIPE_B);
+	/* Enable the plane */
+	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
+	I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
+
+	/* CRT state */
+	I915_WRITE(ADPA, dev_priv->saveADPA);
+
+	/* LVDS state */
+	if (IS_I965G(dev))
+		I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
+	if (IS_MOBILE(dev) && !IS_I830(dev))
+		I915_WRITE(LVDS, dev_priv->saveLVDS);
+	if (!IS_I830(dev) && !IS_845G(dev))
+		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
+
+	I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
+	I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
+	I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
+	I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
+	I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
+	I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+
+	/* FIXME: restore TV & SDVO state */
+
+	/* FBC info */
+	I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
+	I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
+	I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
+	I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
+
+	/* VGA state */
+	I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
+	I915_WRITE(VGA0, dev_priv->saveVGA0);
+	I915_WRITE(VGA1, dev_priv->saveVGA1);
+	I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
+	DRM_UDELAY(150);
+
+	/* Clock gating state */
+	I915_WRITE (D_STATE, dev_priv->saveD_STATE);
+	I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS);
+
+	/* Cache mode state */
+	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+
+	/* Memory arbitration state */
+	I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
+
+	for (i = 0; i < 16; i++) {
+		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
+		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
+	}
+	for (i = 0; i < 3; i++)
+		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
+
+	i915_restore_vga(dev);
+
+	return 0;
+}
+
diff --git a/sys/dev/drm/mach64_dma.c b/sys/dev/drm/mach64_dma.c
--- a/sys/dev/drm/mach64_dma.c
+++ b/sys/dev/drm/mach64_dma.c
@@ -836,8 +836,14 @@
 
 	/* FIXME: get a dma buffer from the freelist here */
 	DRM_DEBUG("Allocating data memory ...\n");
+#ifdef __FreeBSD__
+	DRM_UNLOCK();
+#endif
 	cpu_addr_dmah =
 	    drm_pci_alloc(dev, 0x1000, 0x1000, 0xfffffffful);
+#ifdef __FreeBSD__
+	DRM_LOCK();
+#endif
 	if (!cpu_addr_dmah) {
 		DRM_INFO("data-memory allocation failed!\n");
 		return -ENOMEM;
diff --git a/sys/dev/drm/mach64_drv.c b/sys/dev/drm/mach64_drv.c
--- a/sys/dev/drm/mach64_drv.c
+++ b/sys/dev/drm/mach64_drv.c
@@ -46,36 +46,34 @@
 	mach64_PCI_IDS
 };
 
-static void mach64_configure(drm_device_t *dev)
+static void mach64_configure(struct drm_device *dev)
 {
-	dev->driver.buf_priv_size	= 1; /* No dev_priv */
-	dev->driver.lastclose		= mach64_driver_lastclose;
-	dev->driver.vblank_wait		= mach64_driver_vblank_wait;
-	dev->driver.irq_preinstall	= mach64_driver_irq_preinstall;
-	dev->driver.irq_postinstall	= mach64_driver_irq_postinstall;
-	dev->driver.irq_uninstall	= mach64_driver_irq_uninstall;
-	dev->driver.irq_handler		= mach64_driver_irq_handler;
-	dev->driver.dma_ioctl		= mach64_dma_buffers;
+	dev->driver->driver_features =
+	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
+	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
 
-	dev->driver.ioctls		= mach64_ioctls;
-	dev->driver.max_ioctl		= mach64_max_ioctl;
+	dev->driver->buf_priv_size	= 1; /* No dev_priv */
+	dev->driver->lastclose		= mach64_driver_lastclose;
+	dev->driver->get_vblank_counter	= mach64_get_vblank_counter;
+	dev->driver->enable_vblank	= mach64_enable_vblank;
+	dev->driver->disable_vblank	= mach64_disable_vblank;
+	dev->driver->irq_preinstall	= mach64_driver_irq_preinstall;
+	dev->driver->irq_postinstall	= mach64_driver_irq_postinstall;
+	dev->driver->irq_uninstall	= mach64_driver_irq_uninstall;
+	dev->driver->irq_handler	= mach64_driver_irq_handler;
+	dev->driver->dma_ioctl		= mach64_dma_buffers;
 
-	dev->driver.name		= DRIVER_NAME;
-	dev->driver.desc		= DRIVER_DESC;
-	dev->driver.date		= DRIVER_DATE;
-	dev->driver.major		= DRIVER_MAJOR;
-	dev->driver.minor		= DRIVER_MINOR;
-	dev->driver.patchlevel		= DRIVER_PATCHLEVEL;
+	dev->driver->ioctls		= mach64_ioctls;
+	dev->driver->max_ioctl		= mach64_max_ioctl;
 
-	dev->driver.use_agp		= 1;
-	dev->driver.use_mtrr		= 1;
-	dev->driver.use_pci_dma		= 1;
-	dev->driver.use_dma		= 1;
-	dev->driver.use_irq		= 1;
-	dev->driver.use_vbl_irq		= 1;
+	dev->driver->name		= DRIVER_NAME;
+	dev->driver->desc		= DRIVER_DESC;
+	dev->driver->date		= DRIVER_DATE;
+	dev->driver->major		= DRIVER_MAJOR;
+	dev->driver->minor		= DRIVER_MINOR;
+	dev->driver->patchlevel		= DRIVER_PATCHLEVEL;
 }
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 static int
 mach64_probe(device_t dev)
 {
@@ -85,18 +83,34 @@
 static int
 mach64_attach(device_t nbdev)
 {
-	drm_device_t *dev = device_get_softc(nbdev);
+	struct drm_device *dev = device_get_softc(nbdev);
 
-	bzero(dev, sizeof(drm_device_t));
+	dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
+	    M_WAITOK | M_ZERO);
+
 	mach64_configure(dev);
+
 	return drm_attach(nbdev, mach64_pciidlist);
+}
+
+static int
+mach64_detach(device_t nbdev)
+{
+	struct drm_device *dev = device_get_softc(nbdev);
+	int ret;
+
+	ret = drm_detach(nbdev);
+
+	free(dev->driver, DRM_MEM_DRIVER);
+
+	return ret;
 }
 
 static device_method_t mach64_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		mach64_probe),
 	DEVMETHOD(device_attach,	mach64_attach),
-	DEVMETHOD(device_detach,	drm_detach),
+	DEVMETHOD(device_detach,	mach64_detach),
 
 	{ 0, 0 }
 };
@@ -104,7 +118,7 @@
 static driver_t mach64_driver = {
 	"drm",
 	mach64_methods,
-	sizeof(drm_device_t)
+	sizeof(struct drm_device)
 };
 
 extern devclass_t drm_devclass;
@@ -114,7 +128,3 @@
 DRIVER_MODULE(mach64, pci, mach64_driver, drm_devclass, 0, 0);
 #endif
 MODULE_DEPEND(mach64, drm, 1, 1, 1);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-CFDRIVER_DECL(mach64, DV_TTY, NULL);
-#endif
diff --git a/sys/dev/drm/mach64_drv.h b/sys/dev/drm/mach64_drv.h
--- a/sys/dev/drm/mach64_drv.h
+++ b/sys/dev/drm/mach64_drv.h
@@ -98,6 +98,8 @@
 	unsigned int depth_bpp;
 	unsigned int depth_offset, depth_pitch;
 
+	atomic_t vbl_received;          /**< Number of vblanks received. */
+
 	u32 front_offset_pitch;
 	u32 back_offset_pitch;
 	u32 depth_offset_pitch;
@@ -162,13 +164,14 @@
 			   struct drm_file *file_priv);
 extern int mach64_get_param(struct drm_device *dev, void *data,
 			    struct drm_file *file_priv);
-extern int mach64_driver_vblank_wait(struct drm_device * dev,
-				     unsigned int *sequence);
 
+extern u32 mach64_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int mach64_enable_vblank(struct drm_device *dev, int crtc);
+extern void mach64_disable_vblank(struct drm_device *dev, int crtc);
 extern irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS);
-extern void mach64_driver_irq_preinstall(struct drm_device * dev);
-extern void mach64_driver_irq_postinstall(struct drm_device * dev);
-extern void mach64_driver_irq_uninstall(struct drm_device * dev);
+extern void mach64_driver_irq_preinstall(struct drm_device *dev);
+extern int mach64_driver_irq_postinstall(struct drm_device *dev);
+extern void mach64_driver_irq_uninstall(struct drm_device *dev);
 
 /* ================================================================
  * Registers
diff --git a/sys/dev/drm/mach64_irq.c b/sys/dev/drm/mach64_irq.c
--- a/sys/dev/drm/mach64_irq.c
+++ b/sys/dev/drm/mach64_irq.c
@@ -44,9 +44,8 @@
 
 irqreturn_t mach64_driver_irq_handler(DRM_IRQ_ARGS)
 {
-	struct drm_device *dev = (struct drm_device *) arg;
-	drm_mach64_private_t *dev_priv =
-	    (drm_mach64_private_t *) dev->dev_private;
+	struct drm_device *dev = arg;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
 	int status;
 
 	status = MACH64_READ(MACH64_CRTC_INT_CNTL);
@@ -64,74 +63,98 @@
 			     (status & ~MACH64_CRTC_INT_ACKS)
 			     | MACH64_CRTC_VBLANK_INT);
 
-		atomic_inc(&dev->vbl_received);
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
+		atomic_inc(&dev_priv->vbl_received);
+		drm_handle_vblank(dev, 0);
 		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
 }
 
-int mach64_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+u32 mach64_get_vblank_counter(struct drm_device * dev, int crtc)
 {
-	unsigned int cur_vblank;
-	int ret = 0;
+	const drm_mach64_private_t *const dev_priv = dev->dev_private;
 
-	/* Assume that the user has missed the current sequence number
-	 * by about a day rather than she wants to wait for years
-	 * using vertical blanks...
-	 */
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(&dev->vbl_received))
-		      - *sequence) <= (1 << 23)));
+	if (crtc != 0)
+		return 0;
 
-	*sequence = cur_vblank;
-
-	return ret;
+	return atomic_read(&dev_priv->vbl_received);
 }
 
-/* drm_dma.h hooks
-*/
-void mach64_driver_irq_preinstall(struct drm_device * dev)
+int mach64_enable_vblank(struct drm_device * dev, int crtc)
 {
-	drm_mach64_private_t *dev_priv =
-	    (drm_mach64_private_t *) dev->dev_private;
-
+	drm_mach64_private_t *dev_priv = dev->dev_private;
 	u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL);
 
-	DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status);
+	if (crtc != 0) {
+		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+			  crtc);
+		return -EINVAL;
+	}
+
+	DRM_DEBUG("before enable vblank CRTC_INT_CTNL: 0x%08x\n", status);
+
+	/* Turn on VBLANK interrupt */
+	MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL)
+		     | MACH64_CRTC_VBLANK_INT_EN);
+
+	return 0;
+}
+
+void mach64_disable_vblank(struct drm_device * dev, int crtc)
+{
+	if (crtc != 0) {
+		DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
+			  crtc);
+		return;
+	}
+
+	/*
+	 * FIXME: implement proper interrupt disable by using the vblank
+	 * counter register (if available).
+	 */
+}
+
+static void mach64_disable_vblank_local(struct drm_device * dev, int crtc)
+{
+	drm_mach64_private_t *dev_priv = dev->dev_private;
+	u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL);
+
+	if (crtc != 0) {
+		DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
+			  crtc);
+		return;
+	}
+
+	DRM_DEBUG("before disable vblank CRTC_INT_CTNL: 0x%08x\n", status);
 
 	/* Disable and clear VBLANK interrupt */
 	MACH64_WRITE(MACH64_CRTC_INT_CNTL, (status & ~MACH64_CRTC_VBLANK_INT_EN)
 		     | MACH64_CRTC_VBLANK_INT);
 }
 
-void mach64_driver_irq_postinstall(struct drm_device * dev)
+void mach64_driver_irq_preinstall(struct drm_device * dev)
 {
-	drm_mach64_private_t *dev_priv =
-	    (drm_mach64_private_t *) dev->dev_private;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
 
-	/* Turn on VBLANK interrupt */
-	MACH64_WRITE(MACH64_CRTC_INT_CNTL, MACH64_READ(MACH64_CRTC_INT_CNTL)
-		     | MACH64_CRTC_VBLANK_INT_EN);
+	u32 status = MACH64_READ(MACH64_CRTC_INT_CNTL);
 
-	DRM_DEBUG("after install CRTC_INT_CTNL: 0x%08x\n",
-		  MACH64_READ(MACH64_CRTC_INT_CNTL));
+	DRM_DEBUG("before install CRTC_INT_CTNL: 0x%08x\n", status);
 
+	mach64_disable_vblank_local(dev, 0);
+}
+
+int mach64_driver_irq_postinstall(struct drm_device * dev)
+{
+	return drm_vblank_init(dev, 1);
 }
 
 void mach64_driver_irq_uninstall(struct drm_device * dev)
 {
-	drm_mach64_private_t *dev_priv =
-	    (drm_mach64_private_t *) dev->dev_private;
+	drm_mach64_private_t *dev_priv = dev->dev_private;
 	if (!dev_priv)
 		return;
 
-	/* Disable and clear VBLANK interrupt */
-	MACH64_WRITE(MACH64_CRTC_INT_CNTL,
-		     (MACH64_READ(MACH64_CRTC_INT_CNTL) &
-		      ~MACH64_CRTC_VBLANK_INT_EN)
-		     | MACH64_CRTC_VBLANK_INT);
+	mach64_disable_vblank_local(dev, 0);
 
 	DRM_DEBUG("after uninstall CRTC_INT_CTNL: 0x%08x\n",
 		  MACH64_READ(MACH64_CRTC_INT_CNTL));
diff --git a/sys/dev/drm/mga_drv.c b/sys/dev/drm/mga_drv.c
--- a/sys/dev/drm/mga_drv.c
+++ b/sys/dev/drm/mga_drv.c
@@ -60,7 +60,7 @@
  * This function needs to be filled in!  The implementation in
  * linux-core/mga_drv.c shows what needs to be done.
  */
-static int mga_driver_device_is_agp(drm_device_t * dev)
+static int mga_driver_device_is_agp(struct drm_device * dev)
 {
 	device_t bus;
 
@@ -85,42 +85,38 @@
 		return DRM_MIGHT_BE_AGP;
 }
 
-static void mga_configure(drm_device_t *dev)
+static void mga_configure(struct drm_device *dev)
 {
-	dev->driver.buf_priv_size	= sizeof(drm_mga_buf_priv_t);
-	dev->driver.load		= mga_driver_load;
-	dev->driver.unload		= mga_driver_unload;
-	dev->driver.lastclose		= mga_driver_lastclose;
-	dev->driver.vblank_wait		= mga_driver_vblank_wait;
-	dev->driver.irq_preinstall	= mga_driver_irq_preinstall;
-	dev->driver.irq_postinstall	= mga_driver_irq_postinstall;
-	dev->driver.irq_uninstall	= mga_driver_irq_uninstall;
-	dev->driver.irq_handler		= mga_driver_irq_handler;
-	dev->driver.dma_ioctl		= mga_dma_buffers;
-	dev->driver.dma_quiescent	= mga_driver_dma_quiescent;
-	dev->driver.device_is_agp	= mga_driver_device_is_agp;
+	dev->driver->driver_features =
+	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+	    DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
 
-	dev->driver.ioctls		= mga_ioctls;
-	dev->driver.max_ioctl		= mga_max_ioctl;
+	dev->driver->buf_priv_size	= sizeof(drm_mga_buf_priv_t);
+	dev->driver->load		= mga_driver_load;
+	dev->driver->unload		= mga_driver_unload;
+	dev->driver->lastclose		= mga_driver_lastclose;
+	dev->driver->get_vblank_counter	= mga_get_vblank_counter;
+	dev->driver->enable_vblank	= mga_enable_vblank;
+	dev->driver->disable_vblank	= mga_disable_vblank;
+	dev->driver->irq_preinstall	= mga_driver_irq_preinstall;
+	dev->driver->irq_postinstall	= mga_driver_irq_postinstall;
+	dev->driver->irq_uninstall	= mga_driver_irq_uninstall;
+	dev->driver->irq_handler	= mga_driver_irq_handler;
+	dev->driver->dma_ioctl		= mga_dma_buffers;
+	dev->driver->dma_quiescent	= mga_driver_dma_quiescent;
+	dev->driver->device_is_agp	= mga_driver_device_is_agp;
 
-	dev->driver.name		= DRIVER_NAME;
-	dev->driver.desc		= DRIVER_DESC;
-	dev->driver.date		= DRIVER_DATE;
-	dev->driver.major		= DRIVER_MAJOR;
-	dev->driver.minor		= DRIVER_MINOR;
-	dev->driver.patchlevel		= DRIVER_PATCHLEVEL;
+	dev->driver->ioctls		= mga_ioctls;
+	dev->driver->max_ioctl		= mga_max_ioctl;
 
-	dev->driver.use_agp		= 1;
-	dev->driver.require_agp		= 1;
-	dev->driver.use_mtrr		= 1;
-	dev->driver.use_dma		= 1;
-	dev->driver.use_irq		= 1;
-	dev->driver.use_vbl_irq		= 1;
+	dev->driver->name		= DRIVER_NAME;
+	dev->driver->desc		= DRIVER_DESC;
+	dev->driver->date		= DRIVER_DATE;
+	dev->driver->major		= DRIVER_MAJOR;
+	dev->driver->minor		= DRIVER_MINOR;
+	dev->driver->patchlevel		= DRIVER_PATCHLEVEL;
 }
 
-
-
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 static int
 mga_probe(device_t dev)
 {
@@ -130,18 +126,34 @@
 static int
 mga_attach(device_t nbdev)
 {
-	drm_device_t *dev = device_get_softc(nbdev);
+	struct drm_device *dev = device_get_softc(nbdev);
 
-	bzero(dev, sizeof(drm_device_t));
+	dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
+	    M_WAITOK | M_ZERO);
+
 	mga_configure(dev);
+
 	return drm_attach(nbdev, mga_pciidlist);
+}
+
+static int
+mga_detach(device_t nbdev)
+{
+	struct drm_device *dev = device_get_softc(nbdev);
+	int ret;
+
+	ret = drm_detach(nbdev);
+
+	free(dev->driver, DRM_MEM_DRIVER);
+
+	return ret;
 }
 
 static device_method_t mga_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		mga_probe),
 	DEVMETHOD(device_attach,	mga_attach),
-	DEVMETHOD(device_detach,	drm_detach),
+	DEVMETHOD(device_detach,	mga_detach),
 
 	{ 0, 0 }
 };
@@ -149,7 +161,7 @@
 static driver_t mga_driver = {
 	"drm",
 	mga_methods,
-	sizeof(drm_device_t)
+	sizeof(struct drm_device)
 };
 
 extern devclass_t drm_devclass;
@@ -159,12 +171,3 @@
 DRIVER_MODULE(mga, pci, mga_driver, drm_devclass, 0, 0);
 #endif
 MODULE_DEPEND(mga, drm, 1, 1, 1);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-#ifdef _LKM
-CFDRIVER_DECL(mga, DV_TTY, NULL);
-#else
-CFATTACH_DECL(mga, sizeof(drm_device_t), drm_probe, drm_attach, drm_detach,
-    drm_activate);
-#endif
-#endif
diff --git a/sys/dev/drm/mga_drv.h b/sys/dev/drm/mga_drv.h
--- a/sys/dev/drm/mga_drv.h
+++ b/sys/dev/drm/mga_drv.h
@@ -115,13 +115,14 @@
 	 * \sa drm_mga_private_t::mmio
 	 */
 	/*@{*/
-	u32 mmio_base;             /**< Bus address of base of MMIO. */
-	u32 mmio_size;             /**< Size of the MMIO region. */
+	u32 mmio_base;			/**< Bus address of base of MMIO. */
+	u32 mmio_size;			/**< Size of the MMIO region. */
 	/*@}*/
 
 	u32 clear_cmd;
 	u32 maccess;
 
+	atomic_t vbl_received;		/**< Number of vblanks received. */
 	wait_queue_head_t fence_queue;
 	atomic_t last_fence_retired;
 	u32 next_fence_to_post;
@@ -183,11 +184,14 @@
 extern int mga_warp_init(drm_mga_private_t * dev_priv);
 
 				/* mga_irq.c */
+extern int mga_enable_vblank(struct drm_device *dev, int crtc);
+extern void mga_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
 extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
 extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
 extern void mga_driver_irq_preinstall(struct drm_device * dev);
-extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern int mga_driver_irq_postinstall(struct drm_device * dev);
 extern void mga_driver_irq_uninstall(struct drm_device * dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
 			     unsigned long arg);
diff --git a/sys/dev/drm/mga_irq.c b/sys/dev/drm/mga_irq.c
--- a/sys/dev/drm/mga_irq.c
+++ b/sys/dev/drm/mga_irq.c
@@ -38,6 +38,20 @@
 #include "mga_drm.h"
 #include "mga_drv.h"
 
+u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+	const drm_mga_private_t *const dev_priv = 
+		(drm_mga_private_t *) dev->dev_private;
+
+	if (crtc != 0) {
+		return 0;
+	}
+
+
+	return atomic_read(&dev_priv->vbl_received);
+}
+
+
 irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -50,9 +64,8 @@
 	/* VBLANK interrupt */
 	if (status & MGA_VLINEPEN) {
 		MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
-		atomic_inc(&dev->vbl_received);
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
+		atomic_inc(&dev_priv->vbl_received);
+		drm_handle_vblank(dev, 0);
 		handled = 1;
 	}
 
@@ -81,22 +94,34 @@
 	return IRQ_NONE;
 }
 
-int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int mga_enable_vblank(struct drm_device *dev, int crtc)
 {
-	unsigned int cur_vblank;
-	int ret = 0;
+	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
-	/* Assume that the user has missed the current sequence number
-	 * by about a day rather than she wants to wait for years
-	 * using vertical blanks...
+	if (crtc != 0) {
+		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+			  crtc);
+		return 0;
+	}
+
+	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+	return 0;
+}
+
+
+void mga_disable_vblank(struct drm_device *dev, int crtc)
+{
+	if (crtc != 0) {
+		DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
+			  crtc);
+	}
+
+	/* Do *NOT* disable the vertical refresh interrupt.  MGA doesn't have
+	 * a nice hardware counter that tracks the number of refreshes when
+	 * the interrupt is disabled, and the kernel doesn't know the refresh
+	 * rate to calculate an estimate.
 	 */
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(&dev->vbl_received))
-		      - *sequence) <= (1 << 23)));
-
-	*sequence = cur_vblank;
-
-	return ret;
+	/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
 }
 
 int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
@@ -128,14 +153,22 @@
 	MGA_WRITE(MGA_ICLEAR, ~0);
 }
 
-void mga_driver_irq_postinstall(struct drm_device * dev)
+int mga_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+	int ret;
+
+	ret = drm_vblank_init(dev, 1);
+	if (ret)
+		return ret;
 
 	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
 
-	/* Turn on vertical blank interrupt and soft trap interrupt. */
-	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+	/* Turn on soft trap interrupt.  Vertical blank interrupts are enabled
+	 * in mga_enable_vblank.
+	 */
+	MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
+	return 0;
 }
 
 void mga_driver_irq_uninstall(struct drm_device * dev)
diff --git a/sys/dev/drm/r128_cce.c b/sys/dev/drm/r128_cce.c
--- a/sys/dev/drm/r128_cce.c
+++ b/sys/dev/drm/r128_cce.c
@@ -560,6 +560,7 @@
 #if __OS_HAS_AGP
 	if (dev_priv->is_pci) {
 #endif
+		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
 		dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
 		dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
 		dev_priv->gart_info.addr = NULL;
diff --git a/sys/dev/drm/r128_drv.c b/sys/dev/drm/r128_drv.c
--- a/sys/dev/drm/r128_drv.c
+++ b/sys/dev/drm/r128_drv.c
@@ -43,38 +43,35 @@
 	r128_PCI_IDS
 };
 
-static void r128_configure(drm_device_t *dev)
+static void r128_configure(struct drm_device *dev)
 {
-	dev->driver.buf_priv_size	= sizeof(drm_r128_buf_priv_t);
-	dev->driver.preclose		= r128_driver_preclose;
-	dev->driver.lastclose		= r128_driver_lastclose;
-	dev->driver.vblank_wait		= r128_driver_vblank_wait;
-	dev->driver.irq_preinstall	= r128_driver_irq_preinstall;
-	dev->driver.irq_postinstall	= r128_driver_irq_postinstall;
-	dev->driver.irq_uninstall	= r128_driver_irq_uninstall;
-	dev->driver.irq_handler		= r128_driver_irq_handler;
-	dev->driver.dma_ioctl		= r128_cce_buffers;
+	dev->driver->driver_features =
+	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
+	    DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
 
-	dev->driver.ioctls		= r128_ioctls;
-	dev->driver.max_ioctl		= r128_max_ioctl;
+	dev->driver->buf_priv_size	= sizeof(drm_r128_buf_priv_t);
+	dev->driver->preclose		= r128_driver_preclose;
+	dev->driver->lastclose		= r128_driver_lastclose;
+	dev->driver->get_vblank_counter	= r128_get_vblank_counter;
+	dev->driver->enable_vblank	= r128_enable_vblank;
+	dev->driver->disable_vblank	= r128_disable_vblank;
+	dev->driver->irq_preinstall	= r128_driver_irq_preinstall;
+	dev->driver->irq_postinstall	= r128_driver_irq_postinstall;
+	dev->driver->irq_uninstall	= r128_driver_irq_uninstall;
+	dev->driver->irq_handler	= r128_driver_irq_handler;
+	dev->driver->dma_ioctl		= r128_cce_buffers;
 
-	dev->driver.name		= DRIVER_NAME;
-	dev->driver.desc		= DRIVER_DESC;
-	dev->driver.date		= DRIVER_DATE;
-	dev->driver.major		= DRIVER_MAJOR;
-	dev->driver.minor		= DRIVER_MINOR;
-	dev->driver.patchlevel		= DRIVER_PATCHLEVEL;
+	dev->driver->ioctls		= r128_ioctls;
+	dev->driver->max_ioctl		= r128_max_ioctl;
 
-	dev->driver.use_agp		= 1;
-	dev->driver.use_mtrr		= 1;
-	dev->driver.use_pci_dma		= 1;
-	dev->driver.use_sg		= 1;
-	dev->driver.use_dma		= 1;
-	dev->driver.use_irq		= 1;
-	dev->driver.use_vbl_irq		= 1;
+	dev->driver->name		= DRIVER_NAME;
+	dev->driver->desc		= DRIVER_DESC;
+	dev->driver->date		= DRIVER_DATE;
+	dev->driver->major		= DRIVER_MAJOR;
+	dev->driver->minor		= DRIVER_MINOR;
+	dev->driver->patchlevel		= DRIVER_PATCHLEVEL;
 }
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 static int
 r128_probe(device_t dev)
 {
@@ -84,18 +81,34 @@
 static int
 r128_attach(device_t nbdev)
 {
-	drm_device_t *dev = device_get_softc(nbdev);
+	struct drm_device *dev = device_get_softc(nbdev);
 
-	bzero(dev, sizeof(drm_device_t));
+	dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
+	    M_WAITOK | M_ZERO);
+
 	r128_configure(dev);
+
 	return drm_attach(nbdev, r128_pciidlist);
+}
+
+static int
+r128_detach(device_t nbdev)
+{
+	struct drm_device *dev = device_get_softc(nbdev);
+	int ret;
+
+	ret = drm_detach(nbdev);
+
+	free(dev->driver, DRM_MEM_DRIVER);
+
+	return ret;
 }
 
 static device_method_t r128_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		r128_probe),
 	DEVMETHOD(device_attach,	r128_attach),
-	DEVMETHOD(device_detach,	drm_detach),
+	DEVMETHOD(device_detach,	r128_detach),
 
 	{ 0, 0 }
 };
@@ -103,7 +116,7 @@
 static driver_t r128_driver = {
 	"drm",
 	r128_methods,
-	sizeof(drm_device_t)
+	sizeof(struct drm_device)
 };
 
 extern devclass_t drm_devclass;
@@ -113,12 +126,3 @@
 DRIVER_MODULE(r128, pci, r128_driver, drm_devclass, 0, 0);
 #endif
 MODULE_DEPEND(r128, drm, 1, 1, 1);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-#ifdef _LKM
-CFDRIVER_DECL(r128, DV_TTY, NULL);
-#else
-CFATTACH_DECL(r128, sizeof(drm_device_t), drm_probe, drm_attach, drm_detach,
-    drm_activate);
-#endif
-#endif
diff --git a/sys/dev/drm/r128_drv.h b/sys/dev/drm/r128_drv.h
--- a/sys/dev/drm/r128_drv.h
+++ b/sys/dev/drm/r128_drv.h
@@ -99,6 +99,8 @@
 	u32 crtc_offset;
 	u32 crtc_offset_cntl;
 
+	atomic_t vbl_received;
+
 	u32 color_fmt;
 	unsigned int front_offset;
 	unsigned int front_pitch;
@@ -151,11 +153,12 @@
 extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
 extern int r128_do_cleanup_cce(struct drm_device * dev);
 
-extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
-
+extern int r128_enable_vblank(struct drm_device *dev, int crtc);
+extern void r128_disable_vblank(struct drm_device *dev, int crtc);
+extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
 extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
 extern void r128_driver_irq_preinstall(struct drm_device * dev);
-extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern int r128_driver_irq_postinstall(struct drm_device * dev);
 extern void r128_driver_irq_uninstall(struct drm_device * dev);
 extern void r128_driver_lastclose(struct drm_device * dev);
 extern void r128_driver_preclose(struct drm_device * dev,
diff --git a/sys/dev/drm/r128_irq.c b/sys/dev/drm/r128_irq.c
--- a/sys/dev/drm/r128_irq.c
+++ b/sys/dev/drm/r128_irq.c
@@ -37,6 +37,16 @@
 #include "r128_drm.h"
 #include "r128_drv.h"
 
+u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
+{
+	const drm_r128_private_t *dev_priv = dev->dev_private;
+
+	if (crtc != 0)
+		return 0;
+
+	return atomic_read(&dev_priv->vbl_received);
+}
+
 irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
 {
 	struct drm_device *dev = (struct drm_device *) arg;
@@ -48,30 +58,38 @@
 	/* VBLANK interrupt */
 	if (status & R128_CRTC_VBLANK_INT) {
 		R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
-		atomic_inc(&dev->vbl_received);
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
+		atomic_inc(&dev_priv->vbl_received);
+		drm_handle_vblank(dev, 0);
 		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
 }
 
-int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+int r128_enable_vblank(struct drm_device *dev, int crtc)
 {
-	unsigned int cur_vblank;
-	int ret = 0;
+	drm_r128_private_t *dev_priv = dev->dev_private;
 
-	/* Assume that the user has missed the current sequence number
-	 * by about a day rather than she wants to wait for years
-	 * using vertical blanks...
+	if (crtc != 0) {
+		DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
+		return -EINVAL;
+	}
+
+	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+	return 0;
+}
+
+void r128_disable_vblank(struct drm_device *dev, int crtc)
+{
+	if (crtc != 0)
+		DRM_ERROR("%s:  bad crtc %d\n", __FUNCTION__, crtc);
+
+	/*
+	 * FIXME: implement proper interrupt disable by using the vblank
+	 * counter register (if available)
+	 *
+	 * R128_WRITE(R128_GEN_INT_CNTL,
+	 *            R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
 	 */
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(&dev->vbl_received))
-		      - *sequence) <= (1 << 23)));
-
-	*sequence = cur_vblank;
-
-	return ret;
 }
 
 void r128_driver_irq_preinstall(struct drm_device * dev)
@@ -84,12 +102,9 @@
 	R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
 }
 
-void r128_driver_irq_postinstall(struct drm_device * dev)
+int r128_driver_irq_postinstall(struct drm_device * dev)
 {
-	drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-
-	/* Turn on VBL interrupt */
-	R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+	return drm_vblank_init(dev, 1);
 }
 
 void r128_driver_irq_uninstall(struct drm_device * dev)
diff --git a/sys/dev/drm/r300_cmdbuf.c b/sys/dev/drm/r300_cmdbuf.c
--- a/sys/dev/drm/r300_cmdbuf.c
+++ b/sys/dev/drm/r300_cmdbuf.c
@@ -79,6 +79,9 @@
 				return -EFAULT;
 			}
 
+			box.x2--; /* Hardware expects inclusive bottom-right corner */
+			box.y2--;
+
 			if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
 				box.x1 = (box.x1) &
 					R300_CLIPRECT_MASK;
@@ -97,8 +100,8 @@
 					R300_CLIPRECT_MASK;
 				box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
 					R300_CLIPRECT_MASK;
+			}
 
-			}
 			OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
 				 (box.y1 << R300_CLIPRECT_Y_SHIFT));
 			OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
@@ -138,6 +141,18 @@
 		ADVANCE_RING();
 	}
 
+	/* flus cache and wait idle clean after cliprect change */
+	BEGIN_RING(2);
+	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+	OUT_RING(R300_RB3D_DC_FLUSH);
+	ADVANCE_RING();
+	BEGIN_RING(2);
+	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
+	ADVANCE_RING();
+	/* set flush flag */
+	dev_priv->track_flush |= RADEON_FLUSH_EMITED;
+
 	return 0;
 }
 
@@ -168,13 +183,13 @@
 	ADD_RANGE(0x21DC, 1);
 	ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
 	ADD_RANGE(R300_VAP_CLIP_X_0, 4);
-	ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
+	ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1);
 	ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
 	ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
 	ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
 	ADD_RANGE(R300_GB_ENABLE, 1);
 	ADD_RANGE(R300_GB_MSPOS0, 5);
-	ADD_RANGE(R300_TX_CNTL, 1);
+	ADD_RANGE(R300_TX_INVALTAGS, 1);
 	ADD_RANGE(R300_TX_ENABLE, 1);
 	ADD_RANGE(0x4200, 4);
 	ADD_RANGE(0x4214, 1);
@@ -191,18 +206,12 @@
 	ADD_RANGE(R300_RE_CULL_CNTL, 1);
 	ADD_RANGE(0x42C0, 2);
 	ADD_RANGE(R300_RS_CNTL_0, 2);
-	ADD_RANGE(R300_RS_INTERP_0, 8);
-	ADD_RANGE(R300_RS_ROUTE_0, 8);
-	ADD_RANGE(0x43A4, 2);
+
+	ADD_RANGE(R300_SC_HYPERZ, 2);
 	ADD_RANGE(0x43E8, 1);
-	ADD_RANGE(R300_PFS_CNTL_0, 3);
-	ADD_RANGE(R300_PFS_NODE_0, 4);
-	ADD_RANGE(R300_PFS_TEXI_0, 64);
+
 	ADD_RANGE(0x46A4, 5);
-	ADD_RANGE(R300_PFS_INSTR0_0, 64);
-	ADD_RANGE(R300_PFS_INSTR1_0, 64);
-	ADD_RANGE(R300_PFS_INSTR2_0, 64);
-	ADD_RANGE(R300_PFS_INSTR3_0, 64);
+
 	ADD_RANGE(R300_RE_FOG_STATE, 1);
 	ADD_RANGE(R300_FOG_COLOR_R, 3);
 	ADD_RANGE(R300_PP_ALPHA_TEST, 2);
@@ -217,14 +226,12 @@
 	ADD_RANGE(0x4E50, 9);
 	ADD_RANGE(0x4E88, 1);
 	ADD_RANGE(0x4EA0, 2);
-	ADD_RANGE(R300_RB3D_ZSTENCIL_CNTL_0, 3);
-	ADD_RANGE(R300_RB3D_ZSTENCIL_FORMAT, 4);
-	ADD_RANGE_MARK(R300_RB3D_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);	/* check offset */
-	ADD_RANGE(R300_RB3D_DEPTHPITCH, 1);
-	ADD_RANGE(0x4F28, 1);
-	ADD_RANGE(0x4F30, 2);
-	ADD_RANGE(0x4F44, 1);
-	ADD_RANGE(0x4F54, 1);
+	ADD_RANGE(R300_ZB_CNTL, 3);
+	ADD_RANGE(R300_ZB_FORMAT, 4);
+	ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);	/* check offset */
+	ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
+	ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
+	ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
 
 	ADD_RANGE(R300_TX_FILTER_0, 16);
 	ADD_RANGE(R300_TX_FILTER1_0, 16);
@@ -237,13 +244,32 @@
 	ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
 
 	/* Sporadic registers used as primitives are emitted */
-	ADD_RANGE(R300_RB3D_ZCACHE_CTLSTAT, 1);
+	ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1);
 	ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
 	ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
 	ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
 
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
-		ADD_RANGE(0x4074, 16);
+		ADD_RANGE(R500_VAP_INDEX_OFFSET, 1);
+		ADD_RANGE(R500_US_CONFIG, 2);
+		ADD_RANGE(R500_US_CODE_ADDR, 3);
+		ADD_RANGE(R500_US_FC_CTRL, 1);
+		ADD_RANGE(R500_RS_IP_0, 16);
+		ADD_RANGE(R500_RS_INST_0, 16);
+		ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
+		ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
+		ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
+	} else {
+		ADD_RANGE(R300_PFS_CNTL_0, 3);
+		ADD_RANGE(R300_PFS_NODE_0, 4);
+		ADD_RANGE(R300_PFS_TEXI_0, 64);
+		ADD_RANGE(R300_PFS_INSTR0_0, 64);
+		ADD_RANGE(R300_PFS_INSTR1_0, 64);
+		ADD_RANGE(R300_PFS_INSTR2_0, 64);
+		ADD_RANGE(R300_PFS_INSTR3_0, 64);
+		ADD_RANGE(R300_RS_INTERP_0, 8);
+		ADD_RANGE(R300_RS_ROUTE_0, 8);
+
 	}
 }
 
@@ -328,6 +354,7 @@
 	sz = header.packet0.count;
 	reg = (header.packet0.reghi << 8) | header.packet0.reglo;
 
+	DRM_DEBUG("R300_CMD_PACKET0: reg %04x, sz %d\n", reg, sz);
 	if (!sz)
 		return 0;
 
@@ -379,15 +406,28 @@
 	if (sz * 16 > cmdbuf->bufsz)
 		return -EINVAL;
 
-	BEGIN_RING(5 + sz * 4);
-	/* Wait for VAP to come to senses.. */
-	/* there is no need to emit it multiple times, (only once before VAP is programmed,
-	   but this optimization is for later */
-	OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0);
+	/* VAP is very sensitive so we purge cache before we program it
+	 * and we also flush its state before & after */
+	BEGIN_RING(6);
+	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+	OUT_RING(R300_RB3D_DC_FLUSH);
+	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
+	OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
+	OUT_RING(0);
+	ADVANCE_RING();
+	/* set flush flag */
+	dev_priv->track_flush |= RADEON_FLUSH_EMITED;
+
+	BEGIN_RING(3 + sz * 4);
 	OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
 	OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
 	OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
+	ADVANCE_RING();
 
+	BEGIN_RING(2);
+	OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0));
+	OUT_RING(0);
 	ADVANCE_RING();
 
 	cmdbuf->buf += sz * 16;
@@ -414,6 +454,15 @@
 		 (1 << R300_PRIM_NUM_VERTICES_SHIFT));
 	OUT_RING_TABLE((int *)cmdbuf->buf, 8);
 	ADVANCE_RING();
+
+	BEGIN_RING(4);
+	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+	OUT_RING(R300_RB3D_DC_FLUSH);
+	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
+	ADVANCE_RING();
+	/* set flush flag */
+	dev_priv->track_flush |= RADEON_FLUSH_EMITED;
 
 	cmdbuf->buf += 8 * 4;
 	cmdbuf->bufsz -= 8 * 4;
@@ -534,22 +583,23 @@
 	return 0;
 }
 
-static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
-					     drm_radeon_kcmd_buffer_t *cmdbuf)
+static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
+					    drm_radeon_kcmd_buffer_t *cmdbuf)
 {
-	u32 *cmd = (u32 *) cmdbuf->buf;
-	int count, ret;
+	u32 *cmd;
+	int count;
+	int expected_count;
 	RING_LOCALS;
 
-	count=(cmd[0]>>16) & 0x3fff;
+	cmd = (u32 *) cmdbuf->buf;
+	count = (cmd[0]>>16) & 0x3fff;
+	expected_count = cmd[1] >> 16;
+	if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
+		expected_count = (expected_count+1)/2;
 
-	if ((cmd[1] & 0x8000ffff) != 0x80000810) {
-		DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
-		return -EINVAL;
-	}
-	ret = !radeon_check_offset(dev_priv, cmd[2]);
-	if (ret) {
-		DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+	if (count && count != expected_count) {
+		DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n",
+			count, expected_count);
 		return -EINVAL;
 	}
 
@@ -560,6 +610,50 @@
 
 	cmdbuf->buf += (count+2)*4;
 	cmdbuf->bufsz -= (count+2)*4;
+
+	if (!count) {
+		drm_r300_cmd_header_t header;
+
+		if (cmdbuf->bufsz < 4*4 + sizeof(header)) {
+			DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
+			return -EINVAL;
+		}
+
+		header.u = *(unsigned int *)cmdbuf->buf;
+
+		cmdbuf->buf += sizeof(header);
+		cmdbuf->bufsz -= sizeof(header);
+		cmd = (u32 *) cmdbuf->buf;
+
+		if (header.header.cmd_type != R300_CMD_PACKET3 ||
+		    header.packet3.packet != R300_CMD_PACKET3_RAW ||
+		    cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
+			DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
+			return -EINVAL;
+		}
+
+		if ((cmd[1] & 0x8000ffff) != 0x80000810) {
+			DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+			return -EINVAL;
+		}
+		if (!radeon_check_offset(dev_priv, cmd[2])) {
+			DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+			return -EINVAL;
+		}
+		if (cmd[3] != expected_count) {
+			DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
+				cmd[3], expected_count);
+			return -EINVAL;
+		}
+
+		BEGIN_RING(4);
+		OUT_RING(cmd[0]);
+		OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3);
+		ADVANCE_RING();
+
+		cmdbuf->buf += 4*4;
+		cmdbuf->bufsz -= 4*4;
+	}
 
 	return 0;
 }
@@ -604,11 +698,22 @@
 	case RADEON_CNTL_BITBLT_MULTI:
 		return r300_emit_bitblt_multi(dev_priv, cmdbuf);
 
-	case RADEON_CP_INDX_BUFFER:	/* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
-		return r300_emit_indx_buffer(dev_priv, cmdbuf);
-	case RADEON_CP_3D_DRAW_IMMD_2:	/* triggers drawing using in-packet vertex data */
-	case RADEON_CP_3D_DRAW_VBUF_2:	/* triggers drawing of vertex buffers setup elsewhere */
-	case RADEON_CP_3D_DRAW_INDX_2:	/* triggers drawing using indices to vertex buffer */
+	case RADEON_CP_INDX_BUFFER:
+		DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n");
+		return -EINVAL;
+	case RADEON_CP_3D_DRAW_IMMD_2:
+		/* triggers drawing using in-packet vertex data */
+	case RADEON_CP_3D_DRAW_VBUF_2:
+		/* triggers drawing of vertex buffers setup elsewhere */
+		dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
+					   RADEON_PURGE_EMITED);
+		break;
+	case RADEON_CP_3D_DRAW_INDX_2:
+		/* triggers drawing using indices to vertex buffer */
+		/* whenever we send vertex we clear flush & purge */
+		dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
+					   RADEON_PURGE_EMITED);
+		return r300_emit_draw_indx_2(dev_priv, cmdbuf);
 	case RADEON_WAIT_FOR_IDLE:
 	case RADEON_CP_NOP:
 		/* these packets are safe */
@@ -704,16 +809,53 @@
  */
 static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
 {
+	uint32_t cache_z, cache_3d, cache_2d;
 	RING_LOCALS;
 
-	BEGIN_RING(6);
+	cache_z = R300_ZC_FLUSH;
+	cache_2d = R300_RB2D_DC_FLUSH;
+	cache_3d = R300_RB3D_DC_FLUSH;
+	if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) {
+		/* we can purge, primitive where draw since last purge */
+		cache_z |= R300_ZC_FREE;
+		cache_2d |= R300_RB2D_DC_FREE;
+		cache_3d |= R300_RB3D_DC_FREE;
+	}
+
+	/* flush & purge zbuffer */
+	BEGIN_RING(2);
+	OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
+	OUT_RING(cache_z);
+	ADVANCE_RING();
+	/* flush & purge 3d */
+	BEGIN_RING(2);
 	OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-	OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A);
-	OUT_RING(CP_PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
-	OUT_RING(R300_RB3D_ZCACHE_UNKNOWN_03);
-	OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
-	OUT_RING(0x0);
+	OUT_RING(cache_3d);
 	ADVANCE_RING();
+	/* flush & purge texture */
+	BEGIN_RING(2);
+	OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0));
+	OUT_RING(0);
+	ADVANCE_RING();
+	/* FIXME: is this one really needed ? */
+	BEGIN_RING(2);
+	OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0));
+	OUT_RING(0);
+	ADVANCE_RING();
+	BEGIN_RING(2);
+	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+	OUT_RING(RADEON_WAIT_3D_IDLECLEAN);
+	ADVANCE_RING();
+	/* flush & purge 2d through E2 as RB2D will trigger lockup */
+	BEGIN_RING(4);
+	OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0));
+	OUT_RING(cache_2d);
+	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+	OUT_RING(RADEON_WAIT_2D_IDLECLEAN |
+		 RADEON_WAIT_HOST_IDLECLEAN);
+	ADVANCE_RING();
+	/* set flush & purge flags */
+	dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
 }
 
 /**
@@ -729,6 +871,47 @@
 	buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
 	buf->pending = 1;
 	buf->used = 0;
+}
+
+static void r300_cmd_wait(drm_radeon_private_t * dev_priv,
+			  drm_r300_cmd_header_t header)
+{
+	u32 wait_until;
+	RING_LOCALS;
+
+	if (!header.wait.flags)
+		return;
+
+	wait_until = 0;
+
+	switch(header.wait.flags) {
+	case R300_WAIT_2D:
+		wait_until = RADEON_WAIT_2D_IDLE;
+		break;
+	case R300_WAIT_3D:
+		wait_until = RADEON_WAIT_3D_IDLE;
+		break;
+	case R300_NEW_WAIT_2D_3D:
+		wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE;
+		break;
+	case R300_NEW_WAIT_2D_2D_CLEAN:
+		wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
+		break;
+	case R300_NEW_WAIT_3D_3D_CLEAN:
+		wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
+		break;
+	case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
+		wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
+		wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
+		break;
+	default:
+		return;
+	}
+
+	BEGIN_RING(2);
+	OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+	OUT_RING(wait_until);
+	ADVANCE_RING();
 }
 
 static int r300_scratch(drm_radeon_private_t *dev_priv,
@@ -789,6 +972,54 @@
 }
 
 /**
+ * Uploads user-supplied vertex program instructions or parameters onto
+ * the graphics card.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static __inline__ int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
+				       drm_radeon_kcmd_buffer_t *cmdbuf,
+				       drm_r300_cmd_header_t header)
+{
+	int sz;
+	int addr;
+	int type;
+	int clamp;
+	int stride;
+	RING_LOCALS;
+
+	sz = header.r500fp.count;
+	/* address is 9 bits 0 - 8, bit 1 of flags is part of address */
+	addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;
+
+	type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
+	clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
+
+	addr |= (type << 16);
+	addr |= (clamp << 17);
+
+	stride = type ? 4 : 6;
+
+	DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
+	if (!sz)
+		return 0;
+	if (sz * stride * 4 > cmdbuf->bufsz)
+		return -EINVAL;
+
+	BEGIN_RING(3 + sz * stride);
+	OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
+	OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
+	OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride);
+
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * stride * 4;
+	cmdbuf->bufsz -= sz * stride * 4;
+
+	return 0;
+}
+
+
+/**
  * Parses and validates a user-supplied command buffer and emits appropriate
  * commands on the DMA ring buffer.
  * Called by the ioctl handler function radeon_cp_cmdbuf.
@@ -805,8 +1036,7 @@
 
 	DRM_DEBUG("\n");
 
-	/* See the comment above r300_emit_begin3d for why this call must be here,
-	 * and what the cleanup gotos are for. */
+	/* pacify */
 	r300_pacify(dev_priv);
 
 	if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
@@ -826,7 +1056,6 @@
 
 		switch (header.header.cmd_type) {
 		case R300_CMD_PACKET0:
-			DRM_DEBUG("R300_CMD_PACKET0\n");
 			ret = r300_emit_packet0(dev_priv, cmdbuf, header);
 			if (ret) {
 				DRM_ERROR("r300_emit_packet0 failed\n");
@@ -910,19 +1139,8 @@
 			break;
 
 		case R300_CMD_WAIT:
-			/* simple enough, we can do it here */
 			DRM_DEBUG("R300_CMD_WAIT\n");
-			if (header.wait.flags == 0)
-				break;	/* nothing to do */
-
-			{
-				RING_LOCALS;
-
-				BEGIN_RING(2);
-				OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-				OUT_RING((header.wait.flags & 0xf) << 14);
-				ADVANCE_RING();
-			}
+			r300_cmd_wait(dev_priv, header);
 			break;
 
 		case R300_CMD_SCRATCH:
@@ -934,6 +1152,19 @@
 			}
 			break;
 
+		case R300_CMD_R500FP:
+			if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
+				DRM_ERROR("Calling r500 command on r300 card\n");
+				ret = -EINVAL;
+				goto cleanup;
+			}
+			DRM_DEBUG("R300_CMD_R500FP\n");
+			ret = r300_emit_r500fp(dev_priv, cmdbuf, header);
+			if (ret) {
+				DRM_ERROR("r300_emit_r500fp failed\n");
+				goto cleanup;
+			}
+			break;
 		default:
 			DRM_ERROR("bad cmd_type %i at %p\n",
 				  header.header.cmd_type,
diff --git a/sys/dev/drm/r300_reg.h b/sys/dev/drm/r300_reg.h
--- a/sys/dev/drm/r300_reg.h
+++ b/sys/dev/drm/r300_reg.h
@@ -322,7 +322,7 @@
  * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
  * avoids bugs caused by still running shaders reading bad data from memory.
  */
-#define R300_VAP_PVS_WAITIDLE               0x2284 /* GUESS */
+#define R300_VAP_PVS_STATE_FLUSH_REG        0x2284
 
 /* Absolutely no clue what this register is about. */
 #define R300_VAP_UNKNOWN_2288               0x2288
@@ -518,7 +518,7 @@
 /* gap */
 
 /* Zero to flush caches. */
-#define R300_TX_CNTL                        0x4100
+#define R300_TX_INVALTAGS                   0x4100
 #define R300_TX_FLUSH                       0x0
 
 /* The upper enable bits are guessed, based on fglrx reported limits. */
@@ -706,6 +706,27 @@
 #		define R300_RS_ROUTE_1_COLOR1_DEST_MASK  (31 << 17)
 #		define R300_RS_ROUTE_1_UNKNOWN11         (1 << 11)
 /* END: Rasterization / Interpolators - many guesses */
+
+/* Hierarchical Z Enable */
+#define R300_SC_HYPERZ                   0x43a4
+#	define R300_SC_HYPERZ_DISABLE     (0 << 0)
+#	define R300_SC_HYPERZ_ENABLE      (1 << 0)
+#	define R300_SC_HYPERZ_MIN         (0 << 1)
+#	define R300_SC_HYPERZ_MAX         (1 << 1)
+#	define R300_SC_HYPERZ_ADJ_256     (0 << 2)
+#	define R300_SC_HYPERZ_ADJ_128     (1 << 2)
+#	define R300_SC_HYPERZ_ADJ_64      (2 << 2)
+#	define R300_SC_HYPERZ_ADJ_32      (3 << 2)
+#	define R300_SC_HYPERZ_ADJ_16      (4 << 2)
+#	define R300_SC_HYPERZ_ADJ_8       (5 << 2)
+#	define R300_SC_HYPERZ_ADJ_4       (6 << 2)
+#	define R300_SC_HYPERZ_ADJ_2       (7 << 2)
+#	define R300_SC_HYPERZ_HZ_Z0MIN_NO (0 << 5)
+#	define R300_SC_HYPERZ_HZ_Z0MIN    (1 << 5)
+#	define R300_SC_HYPERZ_HZ_Z0MAX_NO (0 << 6)
+#	define R300_SC_HYPERZ_HZ_Z0MAX    (1 << 6)
+
+#define R300_SC_EDGERULE                 0x43a8
 
 /* BEGIN: Scissors and cliprects */
 
@@ -1346,12 +1367,13 @@
 #define R300_RB3D_COLORPITCH2               0x4E40 /* GUESS */
 #define R300_RB3D_COLORPITCH3               0x4E44 /* GUESS */
 
+#define R300_RB3D_AARESOLVE_CTL             0x4E88
 /* gap */
 
 /* Guess by Vladimir.
  * Set to 0A before 3D operations, set to 02 afterwards.
  */
-#define R300_RB3D_DSTCACHE_CTLSTAT          0x4E4C
+/*#define R300_RB3D_DSTCACHE_CTLSTAT          0x4E4C*/
 #       define R300_RB3D_DSTCACHE_UNKNOWN_02             0x00000002
 #       define R300_RB3D_DSTCACHE_UNKNOWN_0A             0x0000000A
 
@@ -1360,19 +1382,14 @@
  * for this.
  * Bit (1<<8) is the "test" bit. so plain write is 6  - vd
  */
-#define R300_RB3D_ZSTENCIL_CNTL_0                   0x4F00
-#       define R300_RB3D_Z_DISABLED_1            0x00000010
-#       define R300_RB3D_Z_DISABLED_2            0x00000014
-#       define R300_RB3D_Z_TEST                  0x00000012
-#       define R300_RB3D_Z_TEST_AND_WRITE        0x00000016
-#       define R300_RB3D_Z_WRITE_ONLY		 0x00000006
+#define R300_ZB_CNTL                             0x4F00
+#	define R300_STENCIL_ENABLE		 (1 << 0)
+#	define R300_Z_ENABLE		         (1 << 1)
+#	define R300_Z_WRITE_ENABLE		 (1 << 2)
+#	define R300_Z_SIGNED_COMPARE		 (1 << 3)
+#	define R300_STENCIL_FRONT_BACK		 (1 << 4)
 
-#       define R300_RB3D_Z_TEST                  0x00000012
-#       define R300_RB3D_Z_TEST_AND_WRITE        0x00000016
-#       define R300_RB3D_Z_WRITE_ONLY		 0x00000006
-#	define R300_RB3D_STENCIL_ENABLE		 0x00000001
-
-#define R300_RB3D_ZSTENCIL_CNTL_1                   0x4F04
+#define R300_ZB_ZSTENCILCNTL                   0x4f04
 	/* functions */
 #	define R300_ZS_NEVER			0
 #	define R300_ZS_LESS			1
@@ -1392,52 +1409,166 @@
 #	define R300_ZS_INVERT			5
 #	define R300_ZS_INCR_WRAP		6
 #	define R300_ZS_DECR_WRAP		7
+#	define R300_Z_FUNC_SHIFT		0
 	/* front and back refer to operations done for front
 	   and back faces, i.e. separate stencil function support */
-#	define R300_RB3D_ZS1_DEPTH_FUNC_SHIFT		0
-#	define R300_RB3D_ZS1_FRONT_FUNC_SHIFT		3
-#	define R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT	6
-#	define R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT	9
-#	define R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT      12
-#	define R300_RB3D_ZS1_BACK_FUNC_SHIFT           15
-#	define R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT        18
-#	define R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT       21
-#	define R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT       24
+#	define R300_S_FRONT_FUNC_SHIFT	        3
+#	define R300_S_FRONT_SFAIL_OP_SHIFT	6
+#	define R300_S_FRONT_ZPASS_OP_SHIFT	9
+#	define R300_S_FRONT_ZFAIL_OP_SHIFT      12
+#	define R300_S_BACK_FUNC_SHIFT           15
+#	define R300_S_BACK_SFAIL_OP_SHIFT       18
+#	define R300_S_BACK_ZPASS_OP_SHIFT       21
+#	define R300_S_BACK_ZFAIL_OP_SHIFT       24
 
-#define R300_RB3D_ZSTENCIL_CNTL_2                   0x4F08
-#	define R300_RB3D_ZS2_STENCIL_REF_SHIFT		0
-#	define R300_RB3D_ZS2_STENCIL_MASK		0xFF
-#	define R300_RB3D_ZS2_STENCIL_MASK_SHIFT	        8
-#	define R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT	16
+#define R300_ZB_STENCILREFMASK                        0x4f08
+#	define R300_STENCILREF_SHIFT       0
+#	define R300_STENCILREF_MASK        0x000000ff
+#	define R300_STENCILMASK_SHIFT      8
+#	define R300_STENCILMASK_MASK       0x0000ff00
+#	define R300_STENCILWRITEMASK_SHIFT 16
+#	define R300_STENCILWRITEMASK_MASK  0x00ff0000
 
 /* gap */
 
-#define R300_RB3D_ZSTENCIL_FORMAT                   0x4F10
-#	define R300_DEPTH_FORMAT_16BIT_INT_Z     (0 << 0)
-#	define R300_DEPTH_FORMAT_24BIT_INT_Z     (2 << 0)
-	/* 16 bit format or some aditional bit ? */
-#	define R300_DEPTH_FORMAT_UNK32          (32 << 0)
+#define R300_ZB_FORMAT                             0x4f10
+#	define R300_DEPTHFORMAT_16BIT_INT_Z   (0 << 0)
+#	define R300_DEPTHFORMAT_16BIT_13E3    (1 << 0)
+#	define R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL   (2 << 0)
+/* reserved up to (15 << 0) */
+#	define R300_INVERT_13E3_LEADING_ONES  (0 << 4)
+#	define R300_INVERT_13E3_LEADING_ZEROS (1 << 4)
 
-#define R300_RB3D_EARLY_Z                           0x4F14
-#	define R300_EARLY_Z_DISABLE              (0 << 0)
-#	define R300_EARLY_Z_ENABLE               (1 << 0)
+#define R300_ZB_ZTOP                             0x4F14
+#	define R300_ZTOP_DISABLE                 (0 << 0)
+#	define R300_ZTOP_ENABLE                  (1 << 0)
 
 /* gap */
 
-#define R300_RB3D_ZCACHE_CTLSTAT            0x4F18 /* GUESS */
-#       define R300_RB3D_ZCACHE_UNKNOWN_01  0x1
-#       define R300_RB3D_ZCACHE_UNKNOWN_03  0x3
+#define R300_ZB_ZCACHE_CTLSTAT            0x4f18
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_NO_EFFECT      (0 << 0)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE (1 << 0)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_NO_EFFECT       (0 << 1)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE            (1 << 1)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_IDLE            (0 << 31)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_BUSY            (1 << 31)
+
+#define R300_ZB_BW_CNTL                     0x4f1c
+#	define R300_HIZ_DISABLE                              (0 << 0)
+#	define R300_HIZ_ENABLE                               (1 << 0)
+#	define R300_HIZ_MIN                                  (0 << 1)
+#	define R300_HIZ_MAX                                  (1 << 1)
+#	define R300_FAST_FILL_DISABLE                        (0 << 2)
+#	define R300_FAST_FILL_ENABLE                         (1 << 2)
+#	define R300_RD_COMP_DISABLE                          (0 << 3)
+#	define R300_RD_COMP_ENABLE                           (1 << 3)
+#	define R300_WR_COMP_DISABLE                          (0 << 4)
+#	define R300_WR_COMP_ENABLE                           (1 << 4)
+#	define R300_ZB_CB_CLEAR_RMW                          (0 << 5)
+#	define R300_ZB_CB_CLEAR_CACHE_LINEAR                 (1 << 5)
+#	define R300_FORCE_COMPRESSED_STENCIL_VALUE_DISABLE   (0 << 6)
+#	define R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE    (1 << 6)
+
+#	define R500_ZEQUAL_OPTIMIZE_ENABLE                   (0 << 7)
+#	define R500_ZEQUAL_OPTIMIZE_DISABLE                  (1 << 7)
+#	define R500_SEQUAL_OPTIMIZE_ENABLE                   (0 << 8)
+#	define R500_SEQUAL_OPTIMIZE_DISABLE                  (1 << 8)
+
+#	define R500_BMASK_ENABLE                             (0 << 10)
+#	define R500_BMASK_DISABLE                            (1 << 10)
+#	define R500_HIZ_EQUAL_REJECT_DISABLE                 (0 << 11)
+#	define R500_HIZ_EQUAL_REJECT_ENABLE                  (1 << 11)
+#	define R500_HIZ_FP_EXP_BITS_DISABLE                  (0 << 12)
+#	define R500_HIZ_FP_EXP_BITS_1                        (1 << 12)
+#	define R500_HIZ_FP_EXP_BITS_2                        (2 << 12)
+#	define R500_HIZ_FP_EXP_BITS_3                        (3 << 12)
+#	define R500_HIZ_FP_EXP_BITS_4                        (4 << 12)
+#	define R500_HIZ_FP_EXP_BITS_5                        (5 << 12)
+#	define R500_HIZ_FP_INVERT_LEADING_ONES               (0 << 15)
+#	define R500_HIZ_FP_INVERT_LEADING_ZEROS              (1 << 15)
+#	define R500_TILE_OVERWRITE_RECOMPRESSION_ENABLE      (0 << 16)
+#	define R500_TILE_OVERWRITE_RECOMPRESSION_DISABLE     (1 << 16)
+#	define R500_CONTIGUOUS_6XAA_SAMPLES_ENABLE           (0 << 17)
+#	define R500_CONTIGUOUS_6XAA_SAMPLES_DISABLE          (1 << 17)
+#	define R500_PEQ_PACKING_DISABLE                      (0 << 18)
+#	define R500_PEQ_PACKING_ENABLE                       (1 << 18)
+#	define R500_COVERED_PTR_MASKING_DISABLE              (0 << 18)
+#	define R500_COVERED_PTR_MASKING_ENABLE               (1 << 18)
+
 
 /* gap */
 
-#define R300_RB3D_DEPTHOFFSET               0x4F20
-#define R300_RB3D_DEPTHPITCH                0x4F24
-#       define R300_DEPTHPITCH_MASK              0x00001FF8 /* GUESS */
-#       define R300_DEPTH_TILE_ENABLE            (1 << 16) /* GUESS */
-#       define R300_DEPTH_MICROTILE_ENABLE       (1 << 17) /* GUESS */
-#       define R300_DEPTH_ENDIAN_NO_SWAP         (0 << 18) /* GUESS */
-#       define R300_DEPTH_ENDIAN_WORD_SWAP       (1 << 18) /* GUESS */
-#       define R300_DEPTH_ENDIAN_DWORD_SWAP      (2 << 18) /* GUESS */
+/* Z Buffer Address Offset.
+ * Bits 31 to 5 are used for aligned Z buffer address offset for macro tiles.
+ */
+#define R300_ZB_DEPTHOFFSET               0x4f20
+
+/* Z Buffer Pitch and Endian Control */
+#define R300_ZB_DEPTHPITCH                0x4f24
+#       define R300_DEPTHPITCH_MASK              0x00003FFC
+#       define R300_DEPTHMACROTILE_DISABLE      (0 << 16)
+#       define R300_DEPTHMACROTILE_ENABLE       (1 << 16)
+#       define R300_DEPTHMICROTILE_LINEAR       (0 << 17)
+#       define R300_DEPTHMICROTILE_TILED        (1 << 17)
+#       define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17)
+#       define R300_DEPTHENDIAN_NO_SWAP         (0 << 18)
+#       define R300_DEPTHENDIAN_WORD_SWAP       (1 << 18)
+#       define R300_DEPTHENDIAN_DWORD_SWAP      (2 << 18)
+#       define R300_DEPTHENDIAN_HALF_DWORD_SWAP (3 << 18)
+
+/* Z Buffer Clear Value */
+#define R300_ZB_DEPTHCLEARVALUE                  0x4f28
+
+#define R300_ZB_ZMASK_OFFSET			 0x4f30
+#define R300_ZB_ZMASK_PITCH			 0x4f34
+#define R300_ZB_ZMASK_WRINDEX			 0x4f38
+#define R300_ZB_ZMASK_DWORD			 0x4f3c
+#define R300_ZB_ZMASK_RDINDEX			 0x4f40
+
+/* Hierarchical Z Memory Offset */
+#define R300_ZB_HIZ_OFFSET                       0x4f44
+
+/* Hierarchical Z Write Index */
+#define R300_ZB_HIZ_WRINDEX                      0x4f48
+
+/* Hierarchical Z Data */
+#define R300_ZB_HIZ_DWORD                        0x4f4c
+
+/* Hierarchical Z Read Index */
+#define R300_ZB_HIZ_RDINDEX                      0x4f50
+
+/* Hierarchical Z Pitch */
+#define R300_ZB_HIZ_PITCH                        0x4f54
+
+/* Z Buffer Z Pass Counter Data */
+#define R300_ZB_ZPASS_DATA                       0x4f58
+
+/* Z Buffer Z Pass Counter Address */
+#define R300_ZB_ZPASS_ADDR                       0x4f5c
+
+/* Depth buffer X and Y coordinate offset */
+#define R300_ZB_DEPTHXY_OFFSET                   0x4f60
+#	define R300_DEPTHX_OFFSET_SHIFT  1
+#	define R300_DEPTHX_OFFSET_MASK   0x000007FE
+#	define R300_DEPTHY_OFFSET_SHIFT  17
+#	define R300_DEPTHY_OFFSET_MASK   0x07FE0000
+
+/* Sets the fifo sizes */
+#define R500_ZB_FIFO_SIZE                        0x4fd0
+#	define R500_OP_FIFO_SIZE_FULL   (0 << 0)
+#	define R500_OP_FIFO_SIZE_HALF   (1 << 0)
+#	define R500_OP_FIFO_SIZE_QUATER (2 << 0)
+#	define R500_OP_FIFO_SIZE_EIGTHS (4 << 0)
+
+/* Stencil Reference Value and Mask for backfacing quads */
+/* R300_ZB_STENCILREFMASK handles front face */
+#define R500_ZB_STENCILREFMASK_BF                0x4fd4
+#	define R500_STENCILREF_SHIFT       0
+#	define R500_STENCILREF_MASK        0x000000ff
+#	define R500_STENCILMASK_SHIFT      8
+#	define R500_STENCILMASK_MASK       0x0000ff00
+#	define R500_STENCILWRITEMASK_SHIFT 16
+#	define R500_STENCILWRITEMASK_MASK  0x00ff0000
 
 /* BEGIN: Vertex program instruction set */
 
@@ -1628,6 +1759,22 @@
  */
 #define R300_CP_CMD_BITBLT_MULTI	0xC0009B00
 
+#define R500_VAP_INDEX_OFFSET		0x208c
+
+#define R500_GA_US_VECTOR_INDEX         0x4250
+#define R500_GA_US_VECTOR_DATA          0x4254
+
+#define R500_RS_IP_0                    0x4074
+#define R500_RS_INST_0                  0x4320
+
+#define R500_US_CONFIG                  0x4600
+
+#define R500_US_FC_CTRL			0x4624
+#define R500_US_CODE_ADDR		0x4630
+
+#define R500_RB3D_COLOR_CLEAR_VALUE_AR  0x46c0
+#define R500_RB3D_CONSTANT_COLOR_AR     0x4ef8
+
 #endif /* _R300_REG_H */
 
 /* *INDENT-ON* */
diff --git a/sys/dev/drm/radeon_cp.c b/sys/dev/drm/radeon_cp.c
--- a/sys/dev/drm/radeon_cp.c
+++ b/sys/dev/drm/radeon_cp.c
@@ -2,6 +2,7 @@
 /*
  * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * Copyright 2007 Advanced Micro Devices, Inc.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -36,789 +37,13 @@
 #include "radeon_drv.h"
 #include "r300_reg.h"
 
+#include "radeon_microcode.h"
 #define RADEON_FIFO_DEBUG	0
 
 static int radeon_do_cleanup_cp(struct drm_device * dev);
+static void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
 
-/* CP microcode (from ATI) */
-static const u32 R200_cp_microcode[][2] = {
-	{0x21007000, 0000000000},
-	{0x20007000, 0000000000},
-	{0x000000ab, 0x00000004},
-	{0x000000af, 0x00000004},
-	{0x66544a49, 0000000000},
-	{0x49494174, 0000000000},
-	{0x54517d83, 0000000000},
-	{0x498d8b64, 0000000000},
-	{0x49494949, 0000000000},
-	{0x49da493c, 0000000000},
-	{0x49989898, 0000000000},
-	{0xd34949d5, 0000000000},
-	{0x9dc90e11, 0000000000},
-	{0xce9b9b9b, 0000000000},
-	{0x000f0000, 0x00000016},
-	{0x352e232c, 0000000000},
-	{0x00000013, 0x00000004},
-	{0x000f0000, 0x00000016},
-	{0x352e272c, 0000000000},
-	{0x000f0001, 0x00000016},
-	{0x3239362f, 0000000000},
-	{0x000077ef, 0x00000002},
-	{0x00061000, 0x00000002},
-	{0x00000020, 0x0000001a},
-	{0x00004000, 0x0000001e},
-	{0x00061000, 0x00000002},
-	{0x00000020, 0x0000001a},
-	{0x00004000, 0x0000001e},
-	{0x00061000, 0x00000002},
-	{0x00000020, 0x0000001a},
-	{0x00004000, 0x0000001e},
-	{0x00000016, 0x00000004},
-	{0x0003802a, 0x00000002},
-	{0x040067e0, 0x00000002},
-	{0x00000016, 0x00000004},
-	{0x000077e0, 0x00000002},
-	{0x00065000, 0x00000002},
-	{0x000037e1, 0x00000002},
-	{0x040067e1, 0x00000006},
-	{0x000077e0, 0x00000002},
-	{0x000077e1, 0x00000002},
-	{0x000077e1, 0x00000006},
-	{0xffffffff, 0000000000},
-	{0x10000000, 0000000000},
-	{0x0003802a, 0x00000002},
-	{0x040067e0, 0x00000006},
-	{0x00007675, 0x00000002},
-	{0x00007676, 0x00000002},
-	{0x00007677, 0x00000002},
-	{0x00007678, 0x00000006},
-	{0x0003802b, 0x00000002},
-	{0x04002676, 0x00000002},
-	{0x00007677, 0x00000002},
-	{0x00007678, 0x00000006},
-	{0x0000002e, 0x00000018},
-	{0x0000002e, 0x00000018},
-	{0000000000, 0x00000006},
-	{0x0000002f, 0x00000018},
-	{0x0000002f, 0x00000018},
-	{0000000000, 0x00000006},
-	{0x01605000, 0x00000002},
-	{0x00065000, 0x00000002},
-	{0x00098000, 0x00000002},
-	{0x00061000, 0x00000002},
-	{0x64c0603d, 0x00000004},
-	{0x00080000, 0x00000016},
-	{0000000000, 0000000000},
-	{0x0400251d, 0x00000002},
-	{0x00007580, 0x00000002},
-	{0x00067581, 0x00000002},
-	{0x04002580, 0x00000002},
-	{0x00067581, 0x00000002},
-	{0x00000046, 0x00000004},
-	{0x00005000, 0000000000},
-	{0x00061000, 0x00000002},
-	{0x0000750e, 0x00000002},
-	{0x00019000, 0x00000002},
-	{0x00011055, 0x00000014},
-	{0x00000055, 0x00000012},
-	{0x0400250f, 0x00000002},
-	{0x0000504a, 0x00000004},
-	{0x00007565, 0x00000002},
-	{0x00007566, 0x00000002},
-	{0x00000051, 0x00000004},
-	{0x01e655b4, 0x00000002},
-	{0x4401b0dc, 0x00000002},
-	{0x01c110dc, 0x00000002},
-	{0x2666705d, 0x00000018},
-	{0x040c2565, 0x00000002},
-	{0x0000005d, 0x00000018},
-	{0x04002564, 0x00000002},
-	{0x00007566, 0x00000002},
-	{0x00000054, 0x00000004},
-	{0x00401060, 0x00000008},
-	{0x00101000, 0x00000002},
-	{0x000d80ff, 0x00000002},
-	{0x00800063, 0x00000008},
-	{0x000f9000, 0x00000002},
-	{0x000e00ff, 0x00000002},
-	{0000000000, 0x00000006},
-	{0x00000080, 0x00000018},
-	{0x00000054, 0x00000004},
-	{0x00007576, 0x00000002},
-	{0x00065000, 0x00000002},
-	{0x00009000, 0x00000002},
-	{0x00041000, 0x00000002},
-	{0x0c00350e, 0x00000002},
-	{0x00049000, 0x00000002},
-	{0x00051000, 0x00000002},
-	{0x01e785f8, 0x00000002},
-	{0x00200000, 0x00000002},
-	{0x00600073, 0x0000000c},
-	{0x00007563, 0x00000002},
-	{0x006075f0, 0x00000021},
-	{0x20007068, 0x00000004},
-	{0x00005068, 0x00000004},
-	{0x00007576, 0x00000002},
-	{0x00007577, 0x00000002},
-	{0x0000750e, 0x00000002},
-	{0x0000750f, 0x00000002},
-	{0x00a05000, 0x00000002},
-	{0x00600076, 0x0000000c},
-	{0x006075f0, 0x00000021},
-	{0x000075f8, 0x00000002},
-	{0x00000076, 0x00000004},
-	{0x000a750e, 0x00000002},
-	{0x0020750f, 0x00000002},
-	{0x00600079, 0x00000004},
-	{0x00007570, 0x00000002},
-	{0x00007571, 0x00000002},
-	{0x00007572, 0x00000006},
-	{0x00005000, 0x00000002},
-	{0x00a05000, 0x00000002},
-	{0x00007568, 0x00000002},
-	{0x00061000, 0x00000002},
-	{0x00000084, 0x0000000c},
-	{0x00058000, 0x00000002},
-	{0x0c607562, 0x00000002},
-	{0x00000086, 0x00000004},
-	{0x00600085, 0x00000004},
-	{0x400070dd, 0000000000},
-	{0x000380dd, 0x00000002},
-	{0x00000093, 0x0000001c},
-	{0x00065095, 0x00000018},
-	{0x040025bb, 0x00000002},
-	{0x00061096, 0x00000018},
-	{0x040075bc, 0000000000},
-	{0x000075bb, 0x00000002},
-	{0x000075bc, 0000000000},
-	{0x00090000, 0x00000006},
-	{0x00090000, 0x00000002},
-	{0x000d8002, 0x00000006},
-	{0x00005000, 0x00000002},
-	{0x00007821, 0x00000002},
-	{0x00007800, 0000000000},
-	{0x00007821, 0x00000002},
-	{0x00007800, 0000000000},
-	{0x01665000, 0x00000002},
-	{0x000a0000, 0x00000002},
-	{0x000671cc, 0x00000002},
-	{0x0286f1cd, 0x00000002},
-	{0x000000a3, 0x00000010},
-	{0x21007000, 0000000000},
-	{0x000000aa, 0x0000001c},
-	{0x00065000, 0x00000002},
-	{0x000a0000, 0x00000002},
-	{0x00061000, 0x00000002},
-	{0x000b0000, 0x00000002},
-	{0x38067000, 0x00000002},
-	{0x000a00a6, 0x00000004},
-	{0x20007000, 0000000000},
-	{0x01200000, 0x00000002},
-	{0x20077000, 0x00000002},
-	{0x01200000, 0x00000002},
-	{0x20007000, 0000000000},
-	{0x00061000, 0x00000002},
-	{0x0120751b, 0x00000002},
-	{0x8040750a, 0x00000002},
-	{0x8040750b, 0x00000002},
-	{0x00110000, 0x00000002},
-	{0x000380dd, 0x00000002},
-	{0x000000bd, 0x0000001c},
-	{0x00061096, 0x00000018},
-	{0x844075bd, 0x00000002},
-	{0x00061095, 0x00000018},
-	{0x840075bb, 0x00000002},
-	{0x00061096, 0x00000018},
-	{0x844075bc, 0x00000002},
-	{0x000000c0, 0x00000004},
-	{0x804075bd, 0x00000002},
-	{0x800075bb, 0x00000002},
-	{0x804075bc, 0x00000002},
-	{0x00108000, 0x00000002},
-	{0x01400000, 0x00000002},
-	{0x006000c4, 0x0000000c},
-	{0x20c07000, 0x00000020},
-	{0x000000c6, 0x00000012},
-	{0x00800000, 0x00000006},
-	{0x0080751d, 0x00000006},
-	{0x000025bb, 0x00000002},
-	{0x000040c0, 0x00000004},
-	{0x0000775c, 0x00000002},
-	{0x00a05000, 0x00000002},
-	{0x00661000, 0x00000002},
-	{0x0460275d, 0x00000020},
-	{0x00004000, 0000000000},
-	{0x00007999, 0x00000002},
-	{0x00a05000, 0x00000002},
-	{0x00661000, 0x00000002},
-	{0x0460299b, 0x00000020},
-	{0x00004000, 0000000000},
-	{0x01e00830, 0x00000002},
-	{0x21007000, 0000000000},
-	{0x00005000, 0x00000002},
-	{0x00038042, 0x00000002},
-	{0x040025e0, 0x00000002},
-	{0x000075e1, 0000000000},
-	{0x00000001, 0000000000},
-	{0x000380d9, 0x00000002},
-	{0x04007394, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-};
-
-static const u32 radeon_cp_microcode[][2] = {
-	{0x21007000, 0000000000},
-	{0x20007000, 0000000000},
-	{0x000000b4, 0x00000004},
-	{0x000000b8, 0x00000004},
-	{0x6f5b4d4c, 0000000000},
-	{0x4c4c427f, 0000000000},
-	{0x5b568a92, 0000000000},
-	{0x4ca09c6d, 0000000000},
-	{0xad4c4c4c, 0000000000},
-	{0x4ce1af3d, 0000000000},
-	{0xd8afafaf, 0000000000},
-	{0xd64c4cdc, 0000000000},
-	{0x4cd10d10, 0000000000},
-	{0x000f0000, 0x00000016},
-	{0x362f242d, 0000000000},
-	{0x00000012, 0x00000004},
-	{0x000f0000, 0x00000016},
-	{0x362f282d, 0000000000},
-	{0x000380e7, 0x00000002},
-	{0x04002c97, 0x00000002},
-	{0x000f0001, 0x00000016},
-	{0x333a3730, 0000000000},
-	{0x000077ef, 0x00000002},
-	{0x00061000, 0x00000002},
-	{0x00000021, 0x0000001a},
-	{0x00004000, 0x0000001e},
-	{0x00061000, 0x00000002},
-	{0x00000021, 0x0000001a},
-	{0x00004000, 0x0000001e},
-	{0x00061000, 0x00000002},
-	{0x00000021, 0x0000001a},
-	{0x00004000, 0x0000001e},
-	{0x00000017, 0x00000004},
-	{0x0003802b, 0x00000002},
-	{0x040067e0, 0x00000002},
-	{0x00000017, 0x00000004},
-	{0x000077e0, 0x00000002},
-	{0x00065000, 0x00000002},
-	{0x000037e1, 0x00000002},
-	{0x040067e1, 0x00000006},
-	{0x000077e0, 0x00000002},
-	{0x000077e1, 0x00000002},
-	{0x000077e1, 0x00000006},
-	{0xffffffff, 0000000000},
-	{0x10000000, 0000000000},
-	{0x0003802b, 0x00000002},
-	{0x040067e0, 0x00000006},
-	{0x00007675, 0x00000002},
-	{0x00007676, 0x00000002},
-	{0x00007677, 0x00000002},
-	{0x00007678, 0x00000006},
-	{0x0003802c, 0x00000002},
-	{0x04002676, 0x00000002},
-	{0x00007677, 0x00000002},
-	{0x00007678, 0x00000006},
-	{0x0000002f, 0x00000018},
-	{0x0000002f, 0x00000018},
-	{0000000000, 0x00000006},
-	{0x00000030, 0x00000018},
-	{0x00000030, 0x00000018},
-	{0000000000, 0x00000006},
-	{0x01605000, 0x00000002},
-	{0x00065000, 0x00000002},
-	{0x00098000, 0x00000002},
-	{0x00061000, 0x00000002},
-	{0x64c0603e, 0x00000004},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x00080000, 0x00000016},
-	{0000000000, 0000000000},
-	{0x0400251d, 0x00000002},
-	{0x00007580, 0x00000002},
-	{0x00067581, 0x00000002},
-	{0x04002580, 0x00000002},
-	{0x00067581, 0x00000002},
-	{0x00000049, 0x00000004},
-	{0x00005000, 0000000000},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x00061000, 0x00000002},
-	{0x0000750e, 0x00000002},
-	{0x00019000, 0x00000002},
-	{0x00011055, 0x00000014},
-	{0x00000055, 0x00000012},
-	{0x0400250f, 0x00000002},
-	{0x0000504f, 0x00000004},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x00007565, 0x00000002},
-	{0x00007566, 0x00000002},
-	{0x00000058, 0x00000004},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x01e655b4, 0x00000002},
-	{0x4401b0e4, 0x00000002},
-	{0x01c110e4, 0x00000002},
-	{0x26667066, 0x00000018},
-	{0x040c2565, 0x00000002},
-	{0x00000066, 0x00000018},
-	{0x04002564, 0x00000002},
-	{0x00007566, 0x00000002},
-	{0x0000005d, 0x00000004},
-	{0x00401069, 0x00000008},
-	{0x00101000, 0x00000002},
-	{0x000d80ff, 0x00000002},
-	{0x0080006c, 0x00000008},
-	{0x000f9000, 0x00000002},
-	{0x000e00ff, 0x00000002},
-	{0000000000, 0x00000006},
-	{0x0000008f, 0x00000018},
-	{0x0000005b, 0x00000004},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x00007576, 0x00000002},
-	{0x00065000, 0x00000002},
-	{0x00009000, 0x00000002},
-	{0x00041000, 0x00000002},
-	{0x0c00350e, 0x00000002},
-	{0x00049000, 0x00000002},
-	{0x00051000, 0x00000002},
-	{0x01e785f8, 0x00000002},
-	{0x00200000, 0x00000002},
-	{0x0060007e, 0x0000000c},
-	{0x00007563, 0x00000002},
-	{0x006075f0, 0x00000021},
-	{0x20007073, 0x00000004},
-	{0x00005073, 0x00000004},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x00007576, 0x00000002},
-	{0x00007577, 0x00000002},
-	{0x0000750e, 0x00000002},
-	{0x0000750f, 0x00000002},
-	{0x00a05000, 0x00000002},
-	{0x00600083, 0x0000000c},
-	{0x006075f0, 0x00000021},
-	{0x000075f8, 0x00000002},
-	{0x00000083, 0x00000004},
-	{0x000a750e, 0x00000002},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x0020750f, 0x00000002},
-	{0x00600086, 0x00000004},
-	{0x00007570, 0x00000002},
-	{0x00007571, 0x00000002},
-	{0x00007572, 0x00000006},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x00005000, 0x00000002},
-	{0x00a05000, 0x00000002},
-	{0x00007568, 0x00000002},
-	{0x00061000, 0x00000002},
-	{0x00000095, 0x0000000c},
-	{0x00058000, 0x00000002},
-	{0x0c607562, 0x00000002},
-	{0x00000097, 0x00000004},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x00600096, 0x00000004},
-	{0x400070e5, 0000000000},
-	{0x000380e6, 0x00000002},
-	{0x040025c5, 0x00000002},
-	{0x000380e5, 0x00000002},
-	{0x000000a8, 0x0000001c},
-	{0x000650aa, 0x00000018},
-	{0x040025bb, 0x00000002},
-	{0x000610ab, 0x00000018},
-	{0x040075bc, 0000000000},
-	{0x000075bb, 0x00000002},
-	{0x000075bc, 0000000000},
-	{0x00090000, 0x00000006},
-	{0x00090000, 0x00000002},
-	{0x000d8002, 0x00000006},
-	{0x00007832, 0x00000002},
-	{0x00005000, 0x00000002},
-	{0x000380e7, 0x00000002},
-	{0x04002c97, 0x00000002},
-	{0x00007820, 0x00000002},
-	{0x00007821, 0x00000002},
-	{0x00007800, 0000000000},
-	{0x01200000, 0x00000002},
-	{0x20077000, 0x00000002},
-	{0x01200000, 0x00000002},
-	{0x20007000, 0x00000002},
-	{0x00061000, 0x00000002},
-	{0x0120751b, 0x00000002},
-	{0x8040750a, 0x00000002},
-	{0x8040750b, 0x00000002},
-	{0x00110000, 0x00000002},
-	{0x000380e5, 0x00000002},
-	{0x000000c6, 0x0000001c},
-	{0x000610ab, 0x00000018},
-	{0x844075bd, 0x00000002},
-	{0x000610aa, 0x00000018},
-	{0x840075bb, 0x00000002},
-	{0x000610ab, 0x00000018},
-	{0x844075bc, 0x00000002},
-	{0x000000c9, 0x00000004},
-	{0x804075bd, 0x00000002},
-	{0x800075bb, 0x00000002},
-	{0x804075bc, 0x00000002},
-	{0x00108000, 0x00000002},
-	{0x01400000, 0x00000002},
-	{0x006000cd, 0x0000000c},
-	{0x20c07000, 0x00000020},
-	{0x000000cf, 0x00000012},
-	{0x00800000, 0x00000006},
-	{0x0080751d, 0x00000006},
-	{0000000000, 0000000000},
-	{0x0000775c, 0x00000002},
-	{0x00a05000, 0x00000002},
-	{0x00661000, 0x00000002},
-	{0x0460275d, 0x00000020},
-	{0x00004000, 0000000000},
-	{0x01e00830, 0x00000002},
-	{0x21007000, 0000000000},
-	{0x6464614d, 0000000000},
-	{0x69687420, 0000000000},
-	{0x00000073, 0000000000},
-	{0000000000, 0000000000},
-	{0x00005000, 0x00000002},
-	{0x000380d0, 0x00000002},
-	{0x040025e0, 0x00000002},
-	{0x000075e1, 0000000000},
-	{0x00000001, 0000000000},
-	{0x000380e0, 0x00000002},
-	{0x04002394, 0x00000002},
-	{0x00005000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0x00000008, 0000000000},
-	{0x00000004, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-	{0000000000, 0000000000},
-};
-
-static const u32 R300_cp_microcode[][2] = {
-	{ 0x4200e000, 0000000000 },
-	{ 0x4000e000, 0000000000 },
-	{ 0x000000af, 0x00000008 },
-	{ 0x000000b3, 0x00000008 },
-	{ 0x6c5a504f, 0000000000 },
-	{ 0x4f4f497a, 0000000000 },
-	{ 0x5a578288, 0000000000 },
-	{ 0x4f91906a, 0000000000 },
-	{ 0x4f4f4f4f, 0000000000 },
-	{ 0x4fe24f44, 0000000000 },
-	{ 0x4f9c9c9c, 0000000000 },
-	{ 0xdc4f4fde, 0000000000 },
-	{ 0xa1cd4f4f, 0000000000 },
-	{ 0xd29d9d9d, 0000000000 },
-	{ 0x4f0f9fd7, 0000000000 },
-	{ 0x000ca000, 0x00000004 },
-	{ 0x000d0012, 0x00000038 },
-	{ 0x0000e8b4, 0x00000004 },
-	{ 0x000d0014, 0x00000038 },
-	{ 0x0000e8b6, 0x00000004 },
-	{ 0x000d0016, 0x00000038 },
-	{ 0x0000e854, 0x00000004 },
-	{ 0x000d0018, 0x00000038 },
-	{ 0x0000e855, 0x00000004 },
-	{ 0x000d001a, 0x00000038 },
-	{ 0x0000e856, 0x00000004 },
-	{ 0x000d001c, 0x00000038 },
-	{ 0x0000e857, 0x00000004 },
-	{ 0x000d001e, 0x00000038 },
-	{ 0x0000e824, 0x00000004 },
-	{ 0x000d0020, 0x00000038 },
-	{ 0x0000e825, 0x00000004 },
-	{ 0x000d0022, 0x00000038 },
-	{ 0x0000e830, 0x00000004 },
-	{ 0x000d0024, 0x00000038 },
-	{ 0x0000f0c0, 0x00000004 },
-	{ 0x000d0026, 0x00000038 },
-	{ 0x0000f0c1, 0x00000004 },
-	{ 0x000d0028, 0x00000038 },
-	{ 0x0000f041, 0x00000004 },
-	{ 0x000d002a, 0x00000038 },
-	{ 0x0000f184, 0x00000004 },
-	{ 0x000d002c, 0x00000038 },
-	{ 0x0000f185, 0x00000004 },
-	{ 0x000d002e, 0x00000038 },
-	{ 0x0000f186, 0x00000004 },
-	{ 0x000d0030, 0x00000038 },
-	{ 0x0000f187, 0x00000004 },
-	{ 0x000d0032, 0x00000038 },
-	{ 0x0000f180, 0x00000004 },
-	{ 0x000d0034, 0x00000038 },
-	{ 0x0000f393, 0x00000004 },
-	{ 0x000d0036, 0x00000038 },
-	{ 0x0000f38a, 0x00000004 },
-	{ 0x000d0038, 0x00000038 },
-	{ 0x0000f38e, 0x00000004 },
-	{ 0x0000e821, 0x00000004 },
-	{ 0x0140a000, 0x00000004 },
-	{ 0x00000043, 0x00000018 },
-	{ 0x00cce800, 0x00000004 },
-	{ 0x001b0001, 0x00000004 },
-	{ 0x08004800, 0x00000004 },
-	{ 0x001b0001, 0x00000004 },
-	{ 0x08004800, 0x00000004 },
-	{ 0x001b0001, 0x00000004 },
-	{ 0x08004800, 0x00000004 },
-	{ 0x0000003a, 0x00000008 },
-	{ 0x0000a000, 0000000000 },
-	{ 0x02c0a000, 0x00000004 },
-	{ 0x000ca000, 0x00000004 },
-	{ 0x00130000, 0x00000004 },
-	{ 0x000c2000, 0x00000004 },
-	{ 0xc980c045, 0x00000008 },
-	{ 0x2000451d, 0x00000004 },
-	{ 0x0000e580, 0x00000004 },
-	{ 0x000ce581, 0x00000004 },
-	{ 0x08004580, 0x00000004 },
-	{ 0x000ce581, 0x00000004 },
-	{ 0x0000004c, 0x00000008 },
-	{ 0x0000a000, 0000000000 },
-	{ 0x000c2000, 0x00000004 },
-	{ 0x0000e50e, 0x00000004 },
-	{ 0x00032000, 0x00000004 },
-	{ 0x00022056, 0x00000028 },
-	{ 0x00000056, 0x00000024 },
-	{ 0x0800450f, 0x00000004 },
-	{ 0x0000a050, 0x00000008 },
-	{ 0x0000e565, 0x00000004 },
-	{ 0x0000e566, 0x00000004 },
-	{ 0x00000057, 0x00000008 },
-	{ 0x03cca5b4, 0x00000004 },
-	{ 0x05432000, 0x00000004 },
-	{ 0x00022000, 0x00000004 },
-	{ 0x4ccce063, 0x00000030 },
-	{ 0x08274565, 0x00000004 },
-	{ 0x00000063, 0x00000030 },
-	{ 0x08004564, 0x00000004 },
-	{ 0x0000e566, 0x00000004 },
-	{ 0x0000005a, 0x00000008 },
-	{ 0x00802066, 0x00000010 },
-	{ 0x00202000, 0x00000004 },
-	{ 0x001b00ff, 0x00000004 },
-	{ 0x01000069, 0x00000010 },
-	{ 0x001f2000, 0x00000004 },
-	{ 0x001c00ff, 0x00000004 },
-	{ 0000000000, 0x0000000c },
-	{ 0x00000085, 0x00000030 },
-	{ 0x0000005a, 0x00000008 },
-	{ 0x0000e576, 0x00000004 },
-	{ 0x000ca000, 0x00000004 },
-	{ 0x00012000, 0x00000004 },
-	{ 0x00082000, 0x00000004 },
-	{ 0x1800650e, 0x00000004 },
-	{ 0x00092000, 0x00000004 },
-	{ 0x000a2000, 0x00000004 },
-	{ 0x000f0000, 0x00000004 },
-	{ 0x00400000, 0x00000004 },
-	{ 0x00000079, 0x00000018 },
-	{ 0x0000e563, 0x00000004 },
-	{ 0x00c0e5f9, 0x000000c2 },
-	{ 0x0000006e, 0x00000008 },
-	{ 0x0000a06e, 0x00000008 },
-	{ 0x0000e576, 0x00000004 },
-	{ 0x0000e577, 0x00000004 },
-	{ 0x0000e50e, 0x00000004 },
-	{ 0x0000e50f, 0x00000004 },
-	{ 0x0140a000, 0x00000004 },
-	{ 0x0000007c, 0x00000018 },
-	{ 0x00c0e5f9, 0x000000c2 },
-	{ 0x0000007c, 0x00000008 },
-	{ 0x0014e50e, 0x00000004 },
-	{ 0x0040e50f, 0x00000004 },
-	{ 0x00c0007f, 0x00000008 },
-	{ 0x0000e570, 0x00000004 },
-	{ 0x0000e571, 0x00000004 },
-	{ 0x0000e572, 0x0000000c },
-	{ 0x0000a000, 0x00000004 },
-	{ 0x0140a000, 0x00000004 },
-	{ 0x0000e568, 0x00000004 },
-	{ 0x000c2000, 0x00000004 },
-	{ 0x00000089, 0x00000018 },
-	{ 0x000b0000, 0x00000004 },
-	{ 0x18c0e562, 0x00000004 },
-	{ 0x0000008b, 0x00000008 },
-	{ 0x00c0008a, 0x00000008 },
-	{ 0x000700e4, 0x00000004 },
-	{ 0x00000097, 0x00000038 },
-	{ 0x000ca099, 0x00000030 },
-	{ 0x080045bb, 0x00000004 },
-	{ 0x000c209a, 0x00000030 },
-	{ 0x0800e5bc, 0000000000 },
-	{ 0x0000e5bb, 0x00000004 },
-	{ 0x0000e5bc, 0000000000 },
-	{ 0x00120000, 0x0000000c },
-	{ 0x00120000, 0x00000004 },
-	{ 0x001b0002, 0x0000000c },
-	{ 0x0000a000, 0x00000004 },
-	{ 0x0000e821, 0x00000004 },
-	{ 0x0000e800, 0000000000 },
-	{ 0x0000e821, 0x00000004 },
-	{ 0x0000e82e, 0000000000 },
-	{ 0x02cca000, 0x00000004 },
-	{ 0x00140000, 0x00000004 },
-	{ 0x000ce1cc, 0x00000004 },
-	{ 0x050de1cd, 0x00000004 },
-	{ 0x000000a7, 0x00000020 },
-	{ 0x4200e000, 0000000000 },
-	{ 0x000000ae, 0x00000038 },
-	{ 0x000ca000, 0x00000004 },
-	{ 0x00140000, 0x00000004 },
-	{ 0x000c2000, 0x00000004 },
-	{ 0x00160000, 0x00000004 },
-	{ 0x700ce000, 0x00000004 },
-	{ 0x001400aa, 0x00000008 },
-	{ 0x4000e000, 0000000000 },
-	{ 0x02400000, 0x00000004 },
-	{ 0x400ee000, 0x00000004 },
-	{ 0x02400000, 0x00000004 },
-	{ 0x4000e000, 0000000000 },
-	{ 0x000c2000, 0x00000004 },
-	{ 0x0240e51b, 0x00000004 },
-	{ 0x0080e50a, 0x00000005 },
-	{ 0x0080e50b, 0x00000005 },
-	{ 0x00220000, 0x00000004 },
-	{ 0x000700e4, 0x00000004 },
-	{ 0x000000c1, 0x00000038 },
-	{ 0x000c209a, 0x00000030 },
-	{ 0x0880e5bd, 0x00000005 },
-	{ 0x000c2099, 0x00000030 },
-	{ 0x0800e5bb, 0x00000005 },
-	{ 0x000c209a, 0x00000030 },
-	{ 0x0880e5bc, 0x00000005 },
-	{ 0x000000c4, 0x00000008 },
-	{ 0x0080e5bd, 0x00000005 },
-	{ 0x0000e5bb, 0x00000005 },
-	{ 0x0080e5bc, 0x00000005 },
-	{ 0x00210000, 0x00000004 },
-	{ 0x02800000, 0x00000004 },
-	{ 0x00c000c8, 0x00000018 },
-	{ 0x4180e000, 0x00000040 },
-	{ 0x000000ca, 0x00000024 },
-	{ 0x01000000, 0x0000000c },
-	{ 0x0100e51d, 0x0000000c },
-	{ 0x000045bb, 0x00000004 },
-	{ 0x000080c4, 0x00000008 },
-	{ 0x0000f3ce, 0x00000004 },
-	{ 0x0140a000, 0x00000004 },
-	{ 0x00cc2000, 0x00000004 },
-	{ 0x08c053cf, 0x00000040 },
-	{ 0x00008000, 0000000000 },
-	{ 0x0000f3d2, 0x00000004 },
-	{ 0x0140a000, 0x00000004 },
-	{ 0x00cc2000, 0x00000004 },
-	{ 0x08c053d3, 0x00000040 },
-	{ 0x00008000, 0000000000 },
-	{ 0x0000f39d, 0x00000004 },
-	{ 0x0140a000, 0x00000004 },
-	{ 0x00cc2000, 0x00000004 },
-	{ 0x08c0539e, 0x00000040 },
-	{ 0x00008000, 0000000000 },
-	{ 0x03c00830, 0x00000004 },
-	{ 0x4200e000, 0000000000 },
-	{ 0x0000a000, 0x00000004 },
-	{ 0x200045e0, 0x00000004 },
-	{ 0x0000e5e1, 0000000000 },
-	{ 0x00000001, 0000000000 },
-	{ 0x000700e1, 0x00000004 },
-	{ 0x0800e394, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-	{ 0000000000, 0000000000 },
-};
-
-static u32 RADEON_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
 {
 	u32 ret;
 	RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff));
@@ -827,13 +52,43 @@
 	return ret;
 }
 
+static u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+	u32 ret;
+	RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff);
+	ret = RADEON_READ(RS480_NB_MC_DATA);
+	RADEON_WRITE(RS480_NB_MC_INDEX, 0xff);
+	return ret;
+}
+
+static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+	u32 ret;
+	RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK));
+	ret = RADEON_READ(RS690_MC_DATA);
+	RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK);
+	return ret;
+}
+
+static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
+	    return RS690_READ_MCIND(dev_priv, addr);
+	else
+	    return RS480_READ_MCIND(dev_priv, addr);
+}
+
 u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
 {
-	
+
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-		return RADEON_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
+		return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
+	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
+		return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION);
 	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-		return RADEON_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
+		return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
 	else
 		return RADEON_READ(RADEON_MC_FB_LOCATION);
 }
@@ -841,9 +96,12 @@
 static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
 {
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-		RADEON_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
+		R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
+	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
+		RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc);
 	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-		RADEON_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
+		R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
 	else
 		RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc);
 }
@@ -851,11 +109,40 @@
 static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc)
 {
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-		RADEON_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
+		R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
+	else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		 ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
+		RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc);
 	else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-		RADEON_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
+		R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
 	else
 		RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc);
+}
+
+static void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base)
+{
+	u32 agp_base_hi = upper_32_bits(agp_base);
+	u32 agp_base_lo = agp_base & 0xffffffff;
+
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) {
+		R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo);
+		R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi);
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
+		RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo);
+		RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi);
+	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) {
+		R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo);
+		R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi);
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
+		RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
+		RADEON_WRITE(RS480_AGP_BASE_2, agp_base_hi);
+	} else {
+		RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
+		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200)
+			RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi);
+	}
 }
 
 static int RADEON_READ_PLL(struct drm_device * dev, int addr)
@@ -870,15 +157,6 @@
 {
 	RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
 	return RADEON_READ(RADEON_PCIE_DATA);
-}
-
-static u32 RADEON_READ_IGPGART(drm_radeon_private_t *dev_priv, int addr)
-{
-	u32 ret;
-	RADEON_WRITE(RADEON_IGPGART_INDEX, addr & 0x7f);
-	ret = RADEON_READ(RADEON_IGPGART_DATA);
-	RADEON_WRITE(RADEON_IGPGART_INDEX, 0x7f);
-	return ret;
 }
 
 #if RADEON_FIFO_DEBUG
@@ -915,16 +193,21 @@
 
 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
-	tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
-	tmp |= RADEON_RB3D_DC_FLUSH_ALL;
-	RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {
+		tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
+		tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+		RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
 
-	for (i = 0; i < dev_priv->usec_timeout; i++) {
-		if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
-		      & RADEON_RB3D_DC_BUSY)) {
-			return 0;
+		for (i = 0; i < dev_priv->usec_timeout; i++) {
+			if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
+			      & RADEON_RB3D_DC_BUSY)) {
+				return 0;
+			}
+			DRM_UDELAY(1);
 		}
-		DRM_UDELAY(1);
+	} else {
+		/* don't flush or purge cache here or lockup */
+		return 0;
 	}
 
 #if RADEON_FIFO_DEBUG
@@ -947,6 +230,9 @@
 			return 0;
 		DRM_UDELAY(1);
 	}
+	DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n",
+		 RADEON_READ(RADEON_RBBM_STATUS),
+		 RADEON_READ(R300_VAP_CNTL_STATUS));
 
 #if RADEON_FIFO_DEBUG
 	DRM_ERROR("failed!\n");
@@ -973,12 +259,59 @@
 		}
 		DRM_UDELAY(1);
 	}
+	DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n",
+		 RADEON_READ(RADEON_RBBM_STATUS),
+		 RADEON_READ(R300_VAP_CNTL_STATUS));
 
 #if RADEON_FIFO_DEBUG
 	DRM_ERROR("failed!\n");
 	radeon_status(dev_priv);
 #endif
 	return -EBUSY;
+}
+
+static void radeon_init_pipes(drm_radeon_private_t * dev_priv)
+{
+	uint32_t gb_tile_config, gb_pipe_sel = 0;
+
+	/* RS4xx/RS6xx/R4xx/R5xx */
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
+		gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
+		dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
+	} else {
+		/* R3xx */
+		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
+		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) {
+			dev_priv->num_gb_pipes = 2;
+		} else {
+			/* R3Vxx */
+			dev_priv->num_gb_pipes = 1;
+		}
+	}
+	DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes);
+
+	gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/);
+
+	switch(dev_priv->num_gb_pipes) {
+	case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
+	case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
+	case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
+	default:
+	case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
+	}
+
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
+		RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
+		RADEON_WRITE(R500_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
+	}
+	RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config);
+	radeon_do_wait_for_idle(dev_priv);
+	RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
+	RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) |
+					       R300_DC_AUTOFLUSH_ENABLE |
+					       R300_DC_DC_DISABLE_IGNORE_PE));
+
+
 }
 
 /* ================================================================
@@ -995,7 +328,22 @@
 
 	RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
 
-	if (dev_priv->microcode_version == UCODE_R200) {
+	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
+		DRM_INFO("Loading R100 Microcode\n");
+		for (i = 0; i < 256; i++) {
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+				     R100_cp_microcode[i][1]);
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+				     R100_cp_microcode[i][0]);
+		}
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
 		DRM_INFO("Loading R200 Microcode\n");
 		for (i = 0; i < 256; i++) {
 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
@@ -1003,7 +351,12 @@
 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
 				     R200_cp_microcode[i][0]);
 		}
-	} else if (dev_priv->microcode_version == UCODE_R300) {
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
 		DRM_INFO("Loading R300 Microcode\n");
 		for (i = 0; i < 256; i++) {
 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
@@ -1011,12 +364,37 @@
 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
 				     R300_cp_microcode[i][0]);
 		}
-	} else {
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
+		DRM_INFO("Loading R400 Microcode\n");
 		for (i = 0; i < 256; i++) {
 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-				     radeon_cp_microcode[i][1]);
+				     R420_cp_microcode[i][1]);
 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-				     radeon_cp_microcode[i][0]);
+				     R420_cp_microcode[i][0]);
+		}
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
+		DRM_INFO("Loading RS690/RS740 Microcode\n");
+		for (i = 0; i < 256; i++) {
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+				     RS690_cp_microcode[i][1]);
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+				     RS690_cp_microcode[i][0]);
+		}
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
+		DRM_INFO("Loading R500 Microcode\n");
+		for (i = 0; i < 256; i++) {
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+				     R520_cp_microcode[i][1]);
+			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+				     R520_cp_microcode[i][0]);
 		}
 	}
 }
@@ -1068,14 +446,20 @@
 
 	dev_priv->cp_running = 1;
 
-	BEGIN_RING(6);
-
+	BEGIN_RING(8);
+	/* isync can only be written through cp on r5xx write it here */
+	OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0));
+	OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D |
+		 RADEON_ISYNC_ANY3D_IDLE2D |
+		 RADEON_ISYNC_WAIT_IDLEGUI |
+		 RADEON_ISYNC_CPSCRATCH_IDLEGUI);
 	RADEON_PURGE_CACHE();
 	RADEON_PURGE_ZCACHE();
 	RADEON_WAIT_UNTIL_IDLE();
-
 	ADVANCE_RING();
 	COMMIT_RING();
+
+	dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED;
 }
 
 /* Reset the Command Processor.  This will not flush any pending
@@ -1111,15 +495,16 @@
 static int radeon_do_engine_reset(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+	u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset;
 	DRM_DEBUG("\n");
 
 	radeon_do_pixcache_flush(dev_priv);
 
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
+	        /* may need something similar for newer chips */
 		clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
 		mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
-		
+
 		RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
 						    RADEON_FORCEON_MCLKA |
 						    RADEON_FORCEON_MCLKB |
@@ -1127,32 +512,38 @@
 						    RADEON_FORCEON_YCLKB |
 						    RADEON_FORCEON_MC |
 						    RADEON_FORCEON_AIC));
-		
-		rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
-		
-		RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
-						      RADEON_SOFT_RESET_CP |
-						      RADEON_SOFT_RESET_HI |
-						      RADEON_SOFT_RESET_SE |
-						      RADEON_SOFT_RESET_RE |
-						      RADEON_SOFT_RESET_PP |
-						      RADEON_SOFT_RESET_E2 |
-						      RADEON_SOFT_RESET_RB));
-		RADEON_READ(RADEON_RBBM_SOFT_RESET);
-		RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
-						      ~(RADEON_SOFT_RESET_CP |
-							RADEON_SOFT_RESET_HI |
-							RADEON_SOFT_RESET_SE |
-							RADEON_SOFT_RESET_RE |
-							RADEON_SOFT_RESET_PP |
-							RADEON_SOFT_RESET_E2 |
-							RADEON_SOFT_RESET_RB)));
-		RADEON_READ(RADEON_RBBM_SOFT_RESET);
-		
+	}
+
+	rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
+					      RADEON_SOFT_RESET_CP |
+					      RADEON_SOFT_RESET_HI |
+					      RADEON_SOFT_RESET_SE |
+					      RADEON_SOFT_RESET_RE |
+					      RADEON_SOFT_RESET_PP |
+					      RADEON_SOFT_RESET_E2 |
+					      RADEON_SOFT_RESET_RB));
+	RADEON_READ(RADEON_RBBM_SOFT_RESET);
+	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
+					      ~(RADEON_SOFT_RESET_CP |
+						RADEON_SOFT_RESET_HI |
+						RADEON_SOFT_RESET_SE |
+						RADEON_SOFT_RESET_RE |
+						RADEON_SOFT_RESET_PP |
+						RADEON_SOFT_RESET_E2 |
+						RADEON_SOFT_RESET_RB)));
+	RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
 		RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
 		RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
 		RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
 	}
+
+	/* setup the raster pipes */
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300)
+	    radeon_init_pipes(dev_priv);
 
 	/* Reset the CP ring */
 	radeon_do_cp_reset(dev_priv);
@@ -1184,7 +575,8 @@
 
 #if __OS_HAS_AGP
 	if (dev_priv->flags & RADEON_IS_AGP) {
-		RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
+		radeon_write_agp_base(dev_priv, dev->agp->base);
+
 		radeon_write_agp_location(dev_priv,
 			     (((dev_priv->gart_vm_start - 1 +
 				dev_priv->gart_size) & 0xffff0000) |
@@ -1245,9 +637,6 @@
 		     dev_priv->ring.size_l2qw);
 #endif
 
-	/* Start with assuming that writeback doesn't work */
-	dev_priv->writeback_works = 0;
-
 	/* Initialize the scratch register pointer.  This will cause
 	 * the scratch register values to be written out to memory
 	 * whenever they are updated.
@@ -1265,8 +654,19 @@
 	RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
 
 	/* Turn on bus mastering */
-	tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
-	RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
+		/* rs600/rs690/rs740 */
+		tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
+		RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV350) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
+		/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */
+		tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+		RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+	} /* PCIE cards appears to not need this */
 
 	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
 	RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
@@ -1328,40 +728,73 @@
 /* Enable or disable IGP GART on the chip */
 static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
 {
-	u32 temp, tmp;
+	u32 temp;
 
-	tmp = RADEON_READ(RADEON_AIC_CNTL);
-	DRM_DEBUG("setting igpgart AIC CNTL is %08X\n", tmp);
 	if (on) {
-		DRM_DEBUG("programming igpgart %08X %08lX %08X\n",
+		DRM_DEBUG("programming igp gart %08X %08lX %08X\n",
 			 dev_priv->gart_vm_start,
 			 (long)dev_priv->gart_info.bus_addr,
 			 dev_priv->gart_size);
 
-		RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_18, 0x1000);
-		RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, 0x1);
-		RADEON_WRITE_IGPGART(RADEON_IGPGART_CTRL, 0x42040800);
-		RADEON_WRITE_IGPGART(RADEON_IGPGART_BASE_ADDR,
-				     dev_priv->gart_info.bus_addr);
+		temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL);
 
-		temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_UNK_39);
-		RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_39, temp);
+		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))
+			IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN |
+							     RS690_BLOCK_GFX_D3_EN));
+		else
+			IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN);
 
-		RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev_priv->gart_vm_start);
+		IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
+							       RS480_VA_SIZE_32MB));
+
+		temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID);
+		IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN |
+							RS480_TLB_ENABLE |
+							RS480_GTW_LAC_EN |
+							RS480_1LEVEL_GART));
+
+		temp = dev_priv->gart_info.bus_addr & 0xfffff000;
+		temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4;
+		IGP_WRITE_MCIND(RS480_GART_BASE, temp);
+
+		temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL);
+		IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) |
+						      RS480_REQ_TYPE_SNOOP_DIS));
+
+		radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start);
+
 		dev_priv->gart_size = 32*1024*1024;
-		radeon_write_agp_location(dev_priv,
-			     (((dev_priv->gart_vm_start - 1 +
-			       dev_priv->gart_size) & 0xffff0000) |
-			     (dev_priv->gart_vm_start >> 16)));
+		temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & 
+			0xffff0000) | (dev_priv->gart_vm_start >> 16));
 
-		temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_ENABLE);
-		RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, temp);
+		radeon_write_agp_location(dev_priv, temp);
 
-		RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
-		RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x1);
-		RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
-		RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x0);
-       }
+		temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE);
+		IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
+							       RS480_VA_SIZE_32MB));
+
+		do {
+			temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
+			if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
+				break;
+			DRM_UDELAY(1);
+		} while(1);
+
+		IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL,
+				RS480_GART_CACHE_INVALIDATE);
+
+		do {
+			temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
+			if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
+				break;
+			DRM_UDELAY(1);
+		} while(1);
+
+		IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0);
+	} else {
+		IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0);
+	}
 }
 
 static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
@@ -1398,7 +831,9 @@
 {
 	u32 tmp;
 
-	if (dev_priv->flags & RADEON_IS_IGPGART) {
+	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740) ||
+	    (dev_priv->flags & RADEON_IS_IGPGART)) {
 		radeon_set_igpgart(dev_priv, on);
 		return;
 	}
@@ -1477,17 +912,6 @@
 	 */
 	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
 
-	switch(init->func) {
-	case RADEON_INIT_R200_CP:
-		dev_priv->microcode_version = UCODE_R200;
-		break;
-	case RADEON_INIT_R300_CP:
-		dev_priv->microcode_version = UCODE_R300;
-		break;
-	default:
-		dev_priv->microcode_version = UCODE_R100;
-	}
-
 	dev_priv->do_boxes = 0;
 	dev_priv->cp_mode = init->cp_mode;
 
@@ -1535,8 +959,7 @@
 	 */
 	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
 					   (dev_priv->color_fmt << 10) |
-					   (dev_priv->microcode_version ==
-					    UCODE_R100 ? RADEON_ZBLOCK16 : 0));
+					   (dev_priv->chip_family < CHIP_R200 ? RADEON_ZBLOCK16 : 0));
 
 	dev_priv->depth_clear.rb3d_zstencilcntl =
 	    (dev_priv->depth_fmt |
@@ -1732,6 +1155,7 @@
 	} else
 #endif
 	{
+		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
 		/* if we have an offset set from userspace */
 		if (dev_priv->pcigart_offset_set) {
 			dev_priv->gart_info.bus_addr =
@@ -1741,7 +1165,7 @@
 			dev_priv->gart_info.mapping.size =
 			    dev_priv->gart_info.table_size;
 
-			drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
+			drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev);
 			dev_priv->gart_info.addr =
 			    dev_priv->gart_info.mapping.handle;
 
@@ -1781,6 +1205,9 @@
 		/* Turn on PCI GART */
 		radeon_set_pcigart(dev_priv, 1);
 	}
+
+	/* Start with assuming that writeback doesn't work */
+	dev_priv->writeback_works = 0;
 
 	radeon_cp_load_microcode(dev_priv);
 	radeon_cp_init_ring_buffer(dev, dev_priv);
@@ -1875,6 +1302,7 @@
 	radeon_cp_init_ring_buffer(dev, dev_priv);
 
 	radeon_do_engine_reset(dev);
+	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
 
 	DRM_DEBUG("radeon_do_resume_cp() complete\n");
 
@@ -1983,15 +1411,8 @@
 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
 				mtx_sleep(&ret, &dev->dev_lock, PZERO, "rdnrel",
 				       1);
-#elif defined(__DragonFly__)
-				crit_enter();
-				tsleep_interlock(&ret);
-				DRM_UNLOCK();
+#else
 				tsleep(&ret, 0, "rdnrel", 1);
-				crit_exit();
-				DRM_LOCK();
-#else
-				tsleep(&ret, PZERO, "rdnrel", 1);
 #endif
 #endif
 			}
@@ -2308,6 +1729,7 @@
 	case CHIP_R300:
 	case CHIP_R350:
 	case CHIP_R420:
+	case CHIP_R423:
 	case CHIP_RV410:
 	case CHIP_RV515:
 	case CHIP_R520:
@@ -2320,6 +1742,7 @@
 		break;
 	}
 
+	dev_priv->chip_family = flags & RADEON_FAMILY_MASK;
 	if (drm_device_is_agp(dev))
 		dev_priv->flags |= RADEON_IS_AGP;
 	else if (drm_device_is_pcie(dev))
diff --git a/sys/dev/drm/radeon_drm.h b/sys/dev/drm/radeon_drm.h
--- a/sys/dev/drm/radeon_drm.h
+++ b/sys/dev/drm/radeon_drm.h
@@ -227,9 +227,22 @@
 #define R300_CMD_WAIT			7
 #	define R300_WAIT_2D		0x1
 #	define R300_WAIT_3D		0x2
+/* these two defines are DOING IT WRONG - however
+ * we have userspace which relies on using these.
+ * The wait interface is backwards compat new 
+ * code should use the NEW_WAIT defines below
+ * THESE ARE NOT BIT FIELDS
+ */
 #	define R300_WAIT_2D_CLEAN	0x3
 #	define R300_WAIT_3D_CLEAN	0x4
+
+#	define R300_NEW_WAIT_2D_3D	0x3
+#	define R300_NEW_WAIT_2D_2D_CLEAN	0x4
+#	define R300_NEW_WAIT_3D_3D_CLEAN	0x6
+#	define R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN	0x8
+
 #define R300_CMD_SCRATCH		8
+#define R300_CMD_R500FP                 9
 
 typedef union {
 	unsigned int u;
@@ -258,6 +271,9 @@
 	struct {
 		unsigned char cmd_type, reg, n_bufs, flags;
 	} scratch;
+	struct {
+		unsigned char cmd_type, count, adrlo, adrhi_flags;
+	} r500fp;
 } drm_r300_cmd_header_t;
 
 #define RADEON_FRONT			0x1
@@ -267,6 +283,9 @@
 #define RADEON_CLEAR_FASTZ		0x80000000
 #define RADEON_USE_HIERZ		0x40000000
 #define RADEON_USE_COMP_ZBUF		0x20000000
+
+#define R500FP_CONSTANT_TYPE  (1 << 1)
+#define R500FP_CONSTANT_CLAMP (1 << 2)
 
 /* Primitive types
  */
@@ -659,6 +678,7 @@
 #define RADEON_PARAM_CARD_TYPE             12
 #define RADEON_PARAM_VBLANK_CRTC           13   /* VBLANK CRTC */
 #define RADEON_PARAM_FB_LOCATION           14   /* FB location */
+#define RADEON_PARAM_NUM_GB_PIPES          15   /* num GB pipes */
 
 typedef struct drm_radeon_getparam {
 	int param;
diff --git a/sys/dev/drm/radeon_drv.c b/sys/dev/drm/radeon_drv.c
--- a/sys/dev/drm/radeon_drv.c
+++ b/sys/dev/drm/radeon_drv.c
@@ -43,45 +43,40 @@
 	radeon_PCI_IDS
 };
 
-static void radeon_configure(drm_device_t *dev)
+static void radeon_configure(struct drm_device *dev)
 {
-	dev->driver.buf_priv_size	= sizeof(drm_radeon_buf_priv_t);
-	dev->driver.load		= radeon_driver_load;
-	dev->driver.unload		= radeon_driver_unload;
-	dev->driver.firstopen		= radeon_driver_firstopen;
-	dev->driver.open		= radeon_driver_open;
-	dev->driver.preclose		= radeon_driver_preclose;
-	dev->driver.postclose		= radeon_driver_postclose;
-	dev->driver.lastclose		= radeon_driver_lastclose;
-	dev->driver.vblank_wait		= radeon_driver_vblank_wait;
-	dev->driver.vblank_wait2	= radeon_driver_vblank_wait2;
-	dev->driver.irq_preinstall	= radeon_driver_irq_preinstall;
-	dev->driver.irq_postinstall	= radeon_driver_irq_postinstall;
-	dev->driver.irq_uninstall	= radeon_driver_irq_uninstall;
-	dev->driver.irq_handler		= radeon_driver_irq_handler;
-	dev->driver.dma_ioctl		= radeon_cp_buffers;
+	dev->driver->driver_features =
+	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
+	    DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
 
-	dev->driver.ioctls		= radeon_ioctls;
-	dev->driver.max_ioctl		= radeon_max_ioctl;
+	dev->driver->buf_priv_size	= sizeof(drm_radeon_buf_priv_t);
+	dev->driver->load		= radeon_driver_load;
+	dev->driver->unload		= radeon_driver_unload;
+	dev->driver->firstopen		= radeon_driver_firstopen;
+	dev->driver->open		= radeon_driver_open;
+	dev->driver->preclose		= radeon_driver_preclose;
+	dev->driver->postclose		= radeon_driver_postclose;
+	dev->driver->lastclose		= radeon_driver_lastclose;
+	dev->driver->get_vblank_counter	= radeon_get_vblank_counter;
+	dev->driver->enable_vblank	= radeon_enable_vblank;
+	dev->driver->disable_vblank	= radeon_disable_vblank;
+	dev->driver->irq_preinstall	= radeon_driver_irq_preinstall;
+	dev->driver->irq_postinstall	= radeon_driver_irq_postinstall;
+	dev->driver->irq_uninstall	= radeon_driver_irq_uninstall;
+	dev->driver->irq_handler	= radeon_driver_irq_handler;
+	dev->driver->dma_ioctl		= radeon_cp_buffers;
 
-	dev->driver.name		= DRIVER_NAME;
-	dev->driver.desc		= DRIVER_DESC;
-	dev->driver.date		= DRIVER_DATE;
-	dev->driver.major		= DRIVER_MAJOR;
-	dev->driver.minor		= DRIVER_MINOR;
-	dev->driver.patchlevel		= DRIVER_PATCHLEVEL;
+	dev->driver->ioctls		= radeon_ioctls;
+	dev->driver->max_ioctl		= radeon_max_ioctl;
 
-	dev->driver.use_agp		= 1;
-	dev->driver.use_mtrr		= 1;
-	dev->driver.use_pci_dma		= 1;
-	dev->driver.use_sg		= 1;
-	dev->driver.use_dma		= 1;
-	dev->driver.use_irq		= 1;
-	dev->driver.use_vbl_irq		= 1;
-	dev->driver.use_vbl_irq2	= 1;
+	dev->driver->name		= DRIVER_NAME;
+	dev->driver->desc		= DRIVER_DESC;
+	dev->driver->date		= DRIVER_DATE;
+	dev->driver->major		= DRIVER_MAJOR;
+	dev->driver->minor		= DRIVER_MINOR;
+	dev->driver->patchlevel		= DRIVER_PATCHLEVEL;
 }
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 static int
 radeon_probe(device_t dev)
 {
@@ -91,18 +86,34 @@
 static int
 radeon_attach(device_t nbdev)
 {
-	drm_device_t *dev = device_get_softc(nbdev);
+	struct drm_device *dev = device_get_softc(nbdev);
 
-	bzero(dev, sizeof(drm_device_t));
+	dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
+	    M_WAITOK | M_ZERO);
+
 	radeon_configure(dev);
+
 	return drm_attach(nbdev, radeon_pciidlist);
+}
+
+static int
+radeon_detach(device_t nbdev)
+{
+	struct drm_device *dev = device_get_softc(nbdev);
+	int ret;
+
+	ret = drm_detach(nbdev);
+
+	free(dev->driver, DRM_MEM_DRIVER);
+
+	return ret;
 }
 
 static device_method_t radeon_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		radeon_probe),
 	DEVMETHOD(device_attach,	radeon_attach),
-	DEVMETHOD(device_detach,	drm_detach),
+	DEVMETHOD(device_detach,	radeon_detach),
 
 	{ 0, 0 }
 };
@@ -110,7 +121,7 @@
 static driver_t radeon_driver = {
 	"drm",
 	radeon_methods,
-	sizeof(drm_device_t)
+	sizeof(struct drm_device)
 };
 
 extern devclass_t drm_devclass;
@@ -120,12 +131,3 @@
 DRIVER_MODULE(radeon, pci, radeon_driver, drm_devclass, 0, 0);
 #endif
 MODULE_DEPEND(radeon, drm, 1, 1, 1);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-#ifdef _LKM
-CFDRIVER_DECL(radeon, DV_TTY, NULL);
-#else
-CFATTACH_DECL(radeon, sizeof(drm_device_t), drm_probe, drm_attach, drm_detach,
-    drm_activate);
-#endif
-#endif /* __FreeBSD__ || __DragonFly__ */
diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h
--- a/sys/dev/drm/radeon_drv.h
+++ b/sys/dev/drm/radeon_drv.h
@@ -40,7 +40,7 @@
 
 #define DRIVER_NAME		"radeon"
 #define DRIVER_DESC		"ATI Radeon"
-#define DRIVER_DATE		"20060524"
+#define DRIVER_DATE		"20080613"
 
 /* Interface history:
  *
@@ -100,10 +100,11 @@
  * 1.26- Add support for variable size PCI(E) gart aperture
  * 1.27- Add support for IGP GART
  * 1.28- Add support for VBL on CRTC2
+ * 1.29- R500 3D cmd buffer support
  */
 
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		28
+#define DRIVER_MINOR		29
 #define DRIVER_PATCHLEVEL	0
 
 /*
@@ -124,8 +125,12 @@
 	CHIP_RV350,
 	CHIP_RV380,
 	CHIP_R420,
+	CHIP_R423,
 	CHIP_RV410,
 	CHIP_RS400,
+	CHIP_RS480,
+	CHIP_RS690,
+	CHIP_RS740,
 	CHIP_RV515,
 	CHIP_R520,
 	CHIP_RV530,
@@ -133,12 +138,6 @@
 	CHIP_RV570,
 	CHIP_R580,
 	CHIP_LAST,
-};
-
-enum radeon_cp_microcode_version {
-	UCODE_R100,
-	UCODE_R200,
-	UCODE_R300,
 };
 
 /*
@@ -221,6 +220,9 @@
 	struct drm_file *file_priv;
 };
 
+#define RADEON_FLUSH_EMITED	(1 < 0)
+#define RADEON_PURGE_EMITED	(1 < 1)
+
 typedef struct drm_radeon_private {
 
 	drm_radeon_ring_buffer_t ring;
@@ -244,8 +246,6 @@
 	int writeback_works;
 
 	int usec_timeout;
-
-	int microcode_version;
 
 	struct {
 		u32 boxes;
@@ -297,6 +297,7 @@
 	int vblank_crtc;
 	uint32_t irq_enable_reg;
 	int irq_enabled;
+	uint32_t r500_disp_irq_reg;
 
 	struct radeon_surface surfaces[RADEON_MAX_SURFACES];
 	struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
@@ -307,10 +308,16 @@
 
 	u32 scratch_ages[5];
 
+	unsigned int crtc_last_cnt;
+	unsigned int crtc2_last_cnt;
+
 	/* starting from here on, data is preserved accross an open */
 	uint32_t flags;		/* see radeon_chip_flags */
 	unsigned long fb_aper_offset;
 
+	int num_gb_pipes;
+	int track_flush;
+	uint32_t chip_family; /* extract from flags */
 } drm_radeon_private_t;
 
 typedef struct drm_radeon_buf_priv {
@@ -370,17 +377,17 @@
 			       struct mem_block *heap);
 
 				/* radeon_irq.c */
+extern void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state);
 extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv);
 extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
 
 extern void radeon_do_release(struct drm_device * dev);
-extern int radeon_driver_vblank_wait(struct drm_device * dev,
-				     unsigned int *sequence);
-extern int radeon_driver_vblank_wait2(struct drm_device * dev,
-				      unsigned int *sequence);
+extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
+extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
+extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
 extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
 extern void radeon_driver_irq_preinstall(struct drm_device * dev);
-extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern int radeon_driver_irq_postinstall(struct drm_device * dev);
 extern void radeon_driver_irq_uninstall(struct drm_device * dev);
 extern int radeon_vblank_crtc_get(struct drm_device *dev);
 extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
@@ -427,8 +434,31 @@
 #	define RADEON_SCISSOR_1_ENABLE		(1 << 29)
 #	define RADEON_SCISSOR_2_ENABLE		(1 << 30)
 
+/*
+ * PCIE radeons (rv370/rv380, rv410, r423/r430/r480, r5xx)
+ * don't have an explicit bus mastering disable bit.  It's handled
+ * by the PCI D-states.  PMI_BM_DIS disables D-state bus master
+ * handling, not bus mastering itself.
+ */
 #define RADEON_BUS_CNTL			0x0030
+/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */
 #	define RADEON_BUS_MASTER_DIS		(1 << 6)
+/* rs600/rs690/rs740 */
+#	define RS600_BUS_MASTER_DIS		(1 << 14)
+#	define RS600_MSI_REARM		        (1 << 20)
+/* see RS480_MSI_REARM in AIC_CNTL for rs480 */
+
+#define RADEON_BUS_CNTL1		0x0034
+#	define RADEON_PMI_BM_DIS		(1 << 2)
+#	define RADEON_PMI_INT_DIS		(1 << 3)
+
+#define RV370_BUS_CNTL			0x004c
+#	define RV370_PMI_BM_DIS		        (1 << 5)
+#	define RV370_PMI_INT_DIS		(1 << 6)
+
+#define RADEON_MSI_REARM_EN		0x0160
+/* rv370/rv380, rv410, r423/r430/r480, r5xx */
+#	define RV370_MSI_REARM_EN		(1 << 0)
 
 #define RADEON_CLOCK_CNTL_DATA		0x000c
 #	define RADEON_PLL_WR_EN			(1 << 7)
@@ -446,13 +476,13 @@
 #define RADEON_PCIE_DATA                0x0034
 #define RADEON_PCIE_TX_GART_CNTL	0x10
 #	define RADEON_PCIE_TX_GART_EN		(1 << 0)
-#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0<<1)
-#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO  (1<<1)
-#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD   (3<<1)
-#	define RADEON_PCIE_TX_GART_MODE_32_128_CACHE	(0<<3)
-#	define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE	(1<<3)
-#	define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN      (1<<5)
-#	define RADEON_PCIE_TX_GART_INVALIDATE_TLB	(1<<8)
+#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1)
+#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO  (1 << 1)
+#	define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD   (3 << 1)
+#	define RADEON_PCIE_TX_GART_MODE_32_128_CACHE	(0 << 3)
+#	define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE	(1 << 3)
+#	define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN      (1 << 5)
+#	define RADEON_PCIE_TX_GART_INVALIDATE_TLB	(1 << 8)
 #define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11
 #define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12
 #define RADEON_PCIE_TX_GART_BASE	0x13
@@ -461,29 +491,100 @@
 #define RADEON_PCIE_TX_GART_END_LO	0x16
 #define RADEON_PCIE_TX_GART_END_HI	0x17
 
-#define RADEON_IGPGART_INDEX            0x168
-#define RADEON_IGPGART_DATA             0x16c
-#define RADEON_IGPGART_UNK_18           0x18
-#define RADEON_IGPGART_CTRL             0x2b
-#define RADEON_IGPGART_BASE_ADDR        0x2c
-#define RADEON_IGPGART_FLUSH            0x2e
-#define RADEON_IGPGART_ENABLE           0x38
-#define RADEON_IGPGART_UNK_39           0x39
+#define RS480_NB_MC_INDEX               0x168
+#	define RS480_NB_MC_IND_WR_EN	(1 << 8)
+#define RS480_NB_MC_DATA                0x16c
+
+#define RS690_MC_INDEX                  0x78
+#   define RS690_MC_INDEX_MASK          0x1ff
+#   define RS690_MC_INDEX_WR_EN         (1 << 9)
+#   define RS690_MC_INDEX_WR_ACK        0x7f
+#define RS690_MC_DATA                   0x7c
+
+/* MC indirect registers */
+#define RS480_MC_MISC_CNTL              0x18
+#	define RS480_DISABLE_GTW	(1 << 1)
+/* switch between MCIND GART and MM GART registers. 0 = mmgart, 1 = mcind gart */
+#	define RS480_GART_INDEX_REG_EN	(1 << 12)
+#	define RS690_BLOCK_GFX_D3_EN	(1 << 14)
+#define RS480_K8_FB_LOCATION            0x1e
+#define RS480_GART_FEATURE_ID           0x2b
+#	define RS480_HANG_EN	        (1 << 11)
+#	define RS480_TLB_ENABLE	        (1 << 18)
+#	define RS480_P2P_ENABLE	        (1 << 19)
+#	define RS480_GTW_LAC_EN	        (1 << 25)
+#	define RS480_2LEVEL_GART	(0 << 30)
+#	define RS480_1LEVEL_GART	(1 << 30)
+#	define RS480_PDC_EN	        (1 << 31)
+#define RS480_GART_BASE                 0x2c
+#define RS480_GART_CACHE_CNTRL          0x2e
+#	define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */
+#define RS480_AGP_ADDRESS_SPACE_SIZE    0x38
+#	define RS480_GART_EN	        (1 << 0)
+#	define RS480_VA_SIZE_32MB	(0 << 1)
+#	define RS480_VA_SIZE_64MB	(1 << 1)
+#	define RS480_VA_SIZE_128MB	(2 << 1)
+#	define RS480_VA_SIZE_256MB	(3 << 1)
+#	define RS480_VA_SIZE_512MB	(4 << 1)
+#	define RS480_VA_SIZE_1GB	(5 << 1)
+#	define RS480_VA_SIZE_2GB	(6 << 1)
+#define RS480_AGP_MODE_CNTL             0x39
+#	define RS480_POST_GART_Q_SIZE	(1 << 18)
+#	define RS480_NONGART_SNOOP	(1 << 19)
+#	define RS480_AGP_RD_BUF_SIZE	(1 << 20)
+#	define RS480_REQ_TYPE_SNOOP_SHIFT 22
+#	define RS480_REQ_TYPE_SNOOP_MASK  0x3
+#	define RS480_REQ_TYPE_SNOOP_DIS	(1 << 24)
+#define RS480_MC_MISC_UMA_CNTL          0x5f
+#define RS480_MC_MCLK_CNTL              0x7a
+#define RS480_MC_UMA_DUALCH_CNTL        0x86
+
+#define RS690_MC_FB_LOCATION            0x100
+#define RS690_MC_AGP_LOCATION           0x101
+#define RS690_MC_AGP_BASE               0x102
+#define RS690_MC_AGP_BASE_2             0x103
 
 #define R520_MC_IND_INDEX 0x70
-#define R520_MC_IND_WR_EN (1<<24)
+#define R520_MC_IND_WR_EN (1 << 24)
 #define R520_MC_IND_DATA  0x74
 
 #define RV515_MC_FB_LOCATION 0x01
 #define RV515_MC_AGP_LOCATION 0x02
+#define RV515_MC_AGP_BASE     0x03
+#define RV515_MC_AGP_BASE_2   0x04
 
 #define R520_MC_FB_LOCATION 0x04
 #define R520_MC_AGP_LOCATION 0x05
+#define R520_MC_AGP_BASE     0x06
+#define R520_MC_AGP_BASE_2   0x07
 
 #define RADEON_MPP_TB_CONFIG		0x01c0
 #define RADEON_MEM_CNTL			0x0140
 #define RADEON_MEM_SDRAM_MODE_REG	0x0158
+#define RADEON_AGP_BASE_2		0x015c /* r200+ only */
+#define RS480_AGP_BASE_2		0x0164
 #define RADEON_AGP_BASE			0x0170
+
+/* pipe config regs */
+#define R400_GB_PIPE_SELECT             0x402c
+#define R500_DYN_SCLK_PWMEM_PIPE        0x000d /* PLL */
+#define R500_SU_REG_DEST                0x42c8
+#define R300_GB_TILE_CONFIG             0x4018
+#       define R300_ENABLE_TILING       (1 << 0)
+#       define R300_PIPE_COUNT_RV350    (0 << 1)
+#       define R300_PIPE_COUNT_R300     (3 << 1)
+#       define R300_PIPE_COUNT_R420_3P  (6 << 1)
+#       define R300_PIPE_COUNT_R420     (7 << 1)
+#       define R300_TILE_SIZE_8         (0 << 4)
+#       define R300_TILE_SIZE_16        (1 << 4)
+#       define R300_TILE_SIZE_32        (2 << 4)
+#       define R300_SUBPIXEL_1_12       (0 << 16)
+#       define R300_SUBPIXEL_1_16       (1 << 16)
+#define R300_DST_PIPE_CONFIG            0x170c
+#       define R300_PIPE_AUTO_CONFIG    (1 << 31)
+#define R300_RB2D_DSTCACHE_MODE         0x3428
+#       define R300_DC_AUTOFLUSH_ENABLE (1 << 8)
+#       define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17)
 
 #define RADEON_RB3D_COLOROFFSET		0x1c40
 #define RADEON_RB3D_COLORPITCH		0x1c48
@@ -530,6 +631,12 @@
 				? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
 				: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
 
+#define RADEON_CRTC_CRNT_FRAME 0x0214
+#define RADEON_CRTC2_CRNT_FRAME 0x0314
+
+#define RADEON_CRTC_STATUS		0x005c
+#define RADEON_CRTC2_STATUS		0x03fc
+
 #define RADEON_GEN_INT_CNTL		0x0040
 #	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
 #	define RADEON_CRTC2_VBLANK_MASK		(1 << 9)
@@ -545,6 +652,8 @@
 #	define RADEON_SW_INT_TEST		(1 << 25)
 #	define RADEON_SW_INT_TEST_ACK		(1 << 25)
 #	define RADEON_SW_INT_FIRE		(1 << 26)
+#       define R500_DISPLAY_INT_STATUS          (1 << 0)
+
 
 #define RADEON_HOST_PATH_CNTL		0x0130
 #	define RADEON_HDP_SOFT_RESET		(1 << 26)
@@ -588,11 +697,12 @@
 #define RADEON_PP_TXFILTER_1		0x1c6c
 #define RADEON_PP_TXFILTER_2		0x1c84
 
-#define RADEON_RB2D_DSTCACHE_CTLSTAT	0x342c
-#	define RADEON_RB2D_DC_FLUSH		(3 << 0)
-#	define RADEON_RB2D_DC_FREE		(3 << 2)
-#	define RADEON_RB2D_DC_FLUSH_ALL		0xf
-#	define RADEON_RB2D_DC_BUSY		(1 << 31)
+#define R300_RB2D_DSTCACHE_CTLSTAT	0x342c /* use R300_DSTCACHE_CTLSTAT */
+#define R300_DSTCACHE_CTLSTAT		0x1714
+#	define R300_RB2D_DC_FLUSH		(3 << 0)
+#	define R300_RB2D_DC_FREE		(3 << 2)
+#	define R300_RB2D_DC_FLUSH_ALL		0xf
+#	define R300_RB2D_DC_BUSY		(1 << 31)
 #define RADEON_RB3D_CNTL		0x1c3c
 #	define RADEON_ALPHA_BLEND_ENABLE	(1 << 0)
 #	define RADEON_PLANE_MASK_ENABLE		(1 << 1)
@@ -615,11 +725,19 @@
 #	define RADEON_RB3D_ZC_FREE		(1 << 2)
 #	define RADEON_RB3D_ZC_FLUSH_ALL		0x5
 #	define RADEON_RB3D_ZC_BUSY		(1 << 31)
+#define R300_ZB_ZCACHE_CTLSTAT                  0x4f18
+#	define R300_ZC_FLUSH		        (1 << 0)
+#	define R300_ZC_FREE		        (1 << 1)
+#	define R300_ZC_BUSY		        (1 << 31)
 #define RADEON_RB3D_DSTCACHE_CTLSTAT            0x325c
 #	define RADEON_RB3D_DC_FLUSH		(3 << 0)
 #	define RADEON_RB3D_DC_FREE		(3 << 2)
 #	define RADEON_RB3D_DC_FLUSH_ALL		0xf
 #	define RADEON_RB3D_DC_BUSY		(1 << 31)
+#define R300_RB3D_DSTCACHE_CTLSTAT              0x4e4c
+#	define R300_RB3D_DC_FLUSH		(2 << 0)
+#	define R300_RB3D_DC_FREE		(2 << 2)
+#	define R300_RB3D_DC_FINISH		(1 << 4)
 #define RADEON_RB3D_ZSTENCILCNTL	0x1c2c
 #	define RADEON_Z_TEST_MASK		(7 << 4)
 #	define RADEON_Z_TEST_ALWAYS		(7 << 4)
@@ -820,6 +938,7 @@
 
 #define RADEON_AIC_CNTL			0x01d0
 #	define RADEON_PCIGART_TRANSLATE_EN	(1 << 0)
+#	define RS400_MSI_REARM	                (1 << 3)
 #define RADEON_AIC_STAT			0x01d4
 #define RADEON_AIC_PT_BASE		0x01d8
 #define RADEON_AIC_LO_ADDR		0x01dc
@@ -1037,7 +1156,7 @@
 #define RADEON_VHA_SETTO1AND70S                    0x19d8
 #define RADEON_VHA_DST_PITCH                       0x1408
 
-/* set as reference header */
+// set as reference header
 #define RADEON_VHA_BACKFRAME0_OFF_Y              0x1840
 #define RADEON_VHA_BACKFRAME1_OFF_PITCH_Y        0x1844
 #define RADEON_VHA_BACKFRAME0_OFF_U              0x1848
@@ -1057,7 +1176,30 @@
 #define RADEON_VHA_BACKFRAME0_OFF_V_2            0x1894
 #define RADEON_VHA_BACKFRAME1_OFF_PITCH_V_2      0x1898
 
+#define R500_D1CRTC_STATUS 0x609c
+#define R500_D2CRTC_STATUS 0x689c
+#define R500_CRTC_V_BLANK (1<<0)
 
+#define R500_D1CRTC_FRAME_COUNT 0x60a4
+#define R500_D2CRTC_FRAME_COUNT 0x68a4
+
+#define R500_D1MODE_V_COUNTER 0x6530
+#define R500_D2MODE_V_COUNTER 0x6d30
+
+#define R500_D1MODE_VBLANK_STATUS 0x6534
+#define R500_D2MODE_VBLANK_STATUS 0x6d34
+#define R500_VBLANK_OCCURED (1<<0)
+#define R500_VBLANK_ACK     (1<<4)
+#define R500_VBLANK_STAT    (1<<12)
+#define R500_VBLANK_INT     (1<<16)
+
+#define R500_DxMODE_INT_MASK 0x6540
+#define R500_D1MODE_INT_MASK (1<<0)
+#define R500_D2MODE_INT_MASK (1<<8)
+
+#define R500_DISP_INTERRUPT_STATUS 0x7edc
+#define R500_D1_VBLANK_INTERRUPT (1 << 4)
+#define R500_D2_VBLANK_INTERRUPT (1 << 5)
 
 /* Constants */
 #define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
@@ -1075,8 +1217,8 @@
 
 #define RADEON_PCIGART_TABLE_SIZE      (32*1024)
 
-#define RADEON_READ(reg)	DRM_READ32(  dev_priv->mmio, (reg) )
-#define RADEON_WRITE(reg,val)	DRM_WRITE32( dev_priv->mmio, (reg), (val) )
+#define RADEON_READ(reg)    DRM_READ32(  dev_priv->mmio, (reg) )
+#define RADEON_WRITE(reg,val)  DRM_WRITE32( dev_priv->mmio, (reg), (val) )
 #define RADEON_READ8(reg)	DRM_READ8(  dev_priv->mmio, (reg) )
 #define RADEON_WRITE8(reg,val)	DRM_WRITE8( dev_priv->mmio, (reg), (val) )
 
@@ -1087,14 +1229,6 @@
 	RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) );			\
 } while (0)
 
-#define RADEON_WRITE_IGPGART( addr, val )				\
-do {									\
-	RADEON_WRITE( RADEON_IGPGART_INDEX,				\
-			((addr) & 0x7f) | (1 << 8));			\
-	RADEON_WRITE( RADEON_IGPGART_DATA, (val) );			\
-	RADEON_WRITE( RADEON_IGPGART_INDEX, 0x7f );			\
-} while (0)
-
 #define RADEON_WRITE_PCIE( addr, val )					\
 do {									\
 	RADEON_WRITE8( RADEON_PCIE_INDEX,				\
@@ -1102,12 +1236,36 @@
 	RADEON_WRITE( RADEON_PCIE_DATA, (val) );			\
 } while (0)
 
-#define RADEON_WRITE_MCIND( addr, val )					\
-	do {								\
-		RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff));	\
-		RADEON_WRITE(R520_MC_IND_DATA, (val));			\
-		RADEON_WRITE(R520_MC_IND_INDEX, 0);	\
-	} while (0)
+#define R500_WRITE_MCIND( addr, val )					\
+do {								\
+	RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff));	\
+	RADEON_WRITE(R520_MC_IND_DATA, (val));			\
+	RADEON_WRITE(R520_MC_IND_INDEX, 0);	\
+} while (0)
+
+#define RS480_WRITE_MCIND( addr, val )				\
+do {									\
+	RADEON_WRITE( RS480_NB_MC_INDEX,				\
+			((addr) & 0xff) | RS480_NB_MC_IND_WR_EN);	\
+	RADEON_WRITE( RS480_NB_MC_DATA, (val) );			\
+	RADEON_WRITE( RS480_NB_MC_INDEX, 0xff );			\
+} while (0)
+
+#define RS690_WRITE_MCIND( addr, val )					\
+do {								\
+	RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_EN | ((addr) & RS690_MC_INDEX_MASK));	\
+	RADEON_WRITE(RS690_MC_DATA, val);			\
+	RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);	\
+} while (0)
+
+#define IGP_WRITE_MCIND( addr, val )				\
+do {									\
+    if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||	\
+	((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740))		\
+	        RS690_WRITE_MCIND( addr, val );                         \
+	else                                                            \
+	        RS480_WRITE_MCIND( addr, val );                         \
+} while (0)
 
 #define CP_PACKET0( reg, n )						\
 	(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
@@ -1149,23 +1307,43 @@
 } while (0)
 
 #define RADEON_FLUSH_CACHE() do {					\
-	OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) );	\
-	OUT_RING( RADEON_RB3D_DC_FLUSH );				\
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {	\
+	        OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));	\
+	        OUT_RING(RADEON_RB3D_DC_FLUSH);				\
+	} else {                                                        \
+	        OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));	\
+	        OUT_RING(R300_RB3D_DC_FLUSH);				\
+        }                                                               \
 } while (0)
 
 #define RADEON_PURGE_CACHE() do {					\
-	OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) );	\
-	OUT_RING( RADEON_RB3D_DC_FLUSH_ALL );				\
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {	\
+	        OUT_RING(CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0));	\
+	        OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE);	\
+	} else {                                                        \
+	        OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));	\
+	        OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE );	\
+        }                                                               \
 } while (0)
 
 #define RADEON_FLUSH_ZCACHE() do {					\
-	OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );	\
-	OUT_RING( RADEON_RB3D_ZC_FLUSH );				\
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {	\
+	        OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
+	        OUT_RING( RADEON_RB3D_ZC_FLUSH );			\
+	} else {                                                        \
+	        OUT_RING( CP_PACKET0( R300_ZB_ZCACHE_CTLSTAT, 0 ) );	\
+	        OUT_RING( R300_ZC_FLUSH );				\
+        }                                                               \
 } while (0)
 
 #define RADEON_PURGE_ZCACHE() do {					\
-	OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) );	\
-	OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL );				\
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {	\
+	        OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));	\
+	        OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE);	\
+	} else {                                                        \
+	        OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));	\
+	        OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE);			\
+        }                                                               \
 } while (0)
 
 /* ================================================================
diff --git a/sys/dev/drm/radeon_irq.c b/sys/dev/drm/radeon_irq.c
--- a/sys/dev/drm/radeon_irq.c
+++ b/sys/dev/drm/radeon_irq.c
@@ -37,12 +37,130 @@
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
-					      u32 mask)
+void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
 {
-	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	if (state)
+		dev_priv->irq_enable_reg |= mask;
+	else
+		dev_priv->irq_enable_reg &= ~mask;
+
+	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+}
+
+static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	if (state)
+		dev_priv->r500_disp_irq_reg |= mask;
+	else
+		dev_priv->r500_disp_irq_reg &= ~mask;
+
+	RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
+}
+
+int radeon_enable_vblank(struct drm_device *dev, int crtc)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {	
+		switch (crtc) {
+		case 0:
+			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1);
+			break;
+		case 1:
+			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1);
+			break;
+		default:
+			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+				  crtc);
+			return EINVAL;
+		}
+	} else {
+		switch (crtc) {
+		case 0:
+			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
+			break;
+		case 1:
+			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
+			break;
+		default:
+			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+				  crtc);
+			return EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+void radeon_disable_vblank(struct drm_device *dev, int crtc)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {	
+		switch (crtc) {
+		case 0:
+			r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0);
+			break;
+		case 1:
+			r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0);
+			break;
+		default:
+			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+				  crtc);
+			break;
+		}
+	} else {
+		switch (crtc) {
+		case 0:
+			radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
+			break;
+		case 1:
+			radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
+			break;
+		default:
+			DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+				  crtc);
+			break;
+		}
+	}
+}
+
+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, u32 *r500_disp_int)
+{
+	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS);
+	u32 irq_mask = RADEON_SW_INT_TEST;
+
+	*r500_disp_int = 0;
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+		/* vbl interrupts in a different place */
+
+		if (irqs & R500_DISPLAY_INT_STATUS) {
+			/* if a display interrupt */
+			u32 disp_irq;
+
+			disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS);
+
+			*r500_disp_int = disp_irq;
+			if (disp_irq & R500_D1_VBLANK_INTERRUPT) {
+				RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK);
+			}
+			if (disp_irq & R500_D2_VBLANK_INTERRUPT) {
+				RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK);
+			}
+		}
+		irq_mask |= R500_DISPLAY_INT_STATUS;
+	} else
+		irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT;
+
+	irqs &=	irq_mask;
+
 	if (irqs)
 		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+	
 	return irqs;
 }
 
@@ -70,44 +188,33 @@
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
 	u32 stat;
+	u32 r500_disp_int;
 
 	/* Only consider the bits we're interested in - others could be used
 	 * outside the DRM
 	 */
-	stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-						  RADEON_CRTC_VBLANK_STAT |
-						  RADEON_CRTC2_VBLANK_STAT));
+	stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int);
 	if (!stat)
 		return IRQ_NONE;
 
 	stat &= dev_priv->irq_enable_reg;
 
 	/* SW interrupt */
-	if (stat & RADEON_SW_INT_TEST) {
+	if (stat & RADEON_SW_INT_TEST)
 		DRM_WAKEUP(&dev_priv->swi_queue);
-	}
 
 	/* VBLANK interrupt */
-	if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
-		int vblank_crtc = dev_priv->vblank_crtc;
-
-		if ((vblank_crtc &
-		     (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
-		    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
-			if (stat & RADEON_CRTC_VBLANK_STAT)
-				atomic_inc(&dev->vbl_received);
-			if (stat & RADEON_CRTC2_VBLANK_STAT)
-				atomic_inc(&dev->vbl_received2);
-		} else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
-			   (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
-			   ((stat & RADEON_CRTC2_VBLANK_STAT) &&
-			    (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
-			atomic_inc(&dev->vbl_received);
-
-		DRM_WAKEUP(&dev->vbl_queue);
-		drm_vbl_send_signals(dev);
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+		if (r500_disp_int & R500_D1_VBLANK_INTERRUPT)
+			drm_handle_vblank(dev, 0);
+		if (r500_disp_int & R500_D2_VBLANK_INTERRUPT)
+			drm_handle_vblank(dev, 1);
+	} else {
+		if (stat & RADEON_CRTC_VBLANK_STAT)
+			drm_handle_vblank(dev, 0);
+		if (stat & RADEON_CRTC2_VBLANK_STAT)
+			drm_handle_vblank(dev, 1);
 	}
-
 	return IRQ_HANDLED;
 }
 
@@ -146,54 +253,31 @@
 	return ret;
 }
 
-static int radeon_driver_vblank_do_wait(struct drm_device * dev,
-					unsigned int *sequence, int crtc)
+u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
 {
-	drm_radeon_private_t *dev_priv =
-	    (drm_radeon_private_t *) dev->dev_private;
-	unsigned int cur_vblank;
-	int ret = 0;
-	int ack = 0;
-	atomic_t *counter;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+
 	if (!dev_priv) {
 		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
 	}
 
-	if (crtc == DRM_RADEON_VBLANK_CRTC1) {
-		counter = &dev->vbl_received;
-		ack |= RADEON_CRTC_VBLANK_STAT;
-	} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
-		counter = &dev->vbl_received2;
-		ack |= RADEON_CRTC2_VBLANK_STAT;
-	} else
+	if (crtc < 0 || crtc > 1) {
+		DRM_ERROR("Invalid crtc %d\n", crtc);
 		return -EINVAL;
+	}
 
-	radeon_acknowledge_irqs(dev_priv, ack);
-
-	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-	/* Assume that the user has missed the current sequence number
-	 * by about a day rather than she wants to wait for years
-	 * using vertical blanks...
-	 */
-	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-		    (((cur_vblank = atomic_read(counter))
-		      - *sequence) <= (1 << 23)));
-
-	*sequence = cur_vblank;
-
-	return ret;
-}
-
-int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
-}
-
-int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-	return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
+		if (crtc == 0)
+			return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
+		else
+			return RADEON_READ(R500_D2CRTC_FRAME_COUNT);
+	} else {
+		if (crtc == 0)
+			return RADEON_READ(RADEON_CRTC_CRNT_FRAME);
+		else
+			return RADEON_READ(RADEON_CRTC2_CRNT_FRAME);
+	}
 }
 
 /* Needs the lock as it touches the ring.
@@ -236,46 +320,41 @@
 	return radeon_wait_irq(dev, irqwait->irq_seq);
 }
 
-static void radeon_enable_interrupt(struct drm_device *dev)
-{
-	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-
-	dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
-	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
-		dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
-
-	if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
-		dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
-
-	RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
-	dev_priv->irq_enabled = 1;
-}
-
 /* drm_dma.h hooks
 */
 void radeon_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
+	u32 dummy;
 
 	/* Disable *all* interrupts */
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
 	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
 
 	/* Clear bits if they're already high */
-	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-					   RADEON_CRTC_VBLANK_STAT |
-					   RADEON_CRTC2_VBLANK_STAT));
+	radeon_acknowledge_irqs(dev_priv, &dummy);
 }
 
-void radeon_driver_irq_postinstall(struct drm_device * dev)
+int radeon_driver_irq_postinstall(struct drm_device * dev)
 {
 	drm_radeon_private_t *dev_priv =
 	    (drm_radeon_private_t *) dev->dev_private;
+	int ret;
 
 	atomic_set(&dev_priv->swi_emitted, 0);
 	DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
 
-	radeon_enable_interrupt(dev);
+	ret = drm_vblank_init(dev, 2);
+	if (ret)
+		return ret;
+
+	dev->max_vblank_count = 0x001fffff;
+
+	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
+
+	return 0;
 }
 
 void radeon_driver_irq_uninstall(struct drm_device * dev)
@@ -287,6 +366,8 @@
 
 	dev_priv->irq_enabled = 0;
 
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690)
+		RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
 	/* Disable *all* interrupts */
 	RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
 }
@@ -295,18 +376,8 @@
 int radeon_vblank_crtc_get(struct drm_device *dev)
 {
 	drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-	u32 flag;
-	u32 value;
 
-	flag = RADEON_READ(RADEON_GEN_INT_CNTL);
-	value = 0;
-
-	if (flag & RADEON_CRTC_VBLANK_MASK)
-		value |= DRM_RADEON_VBLANK_CRTC1;
-
-	if (flag & RADEON_CRTC2_VBLANK_MASK)
-		value |= DRM_RADEON_VBLANK_CRTC2;
-	return value;
+	return dev_priv->vblank_crtc;
 }
 
 int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
@@ -317,6 +388,5 @@
 		return -EINVAL;
 	}
 	dev_priv->vblank_crtc = (unsigned int)value;
-	radeon_enable_interrupt(dev);
 	return 0;
 }
diff --git a/sys/dev/drm/radeon_mem.c b/sys/dev/drm/radeon_mem.c
--- a/sys/dev/drm/radeon_mem.c
+++ b/sys/dev/drm/radeon_mem.c
@@ -90,7 +90,7 @@
 
 	list_for_each(p, heap) {
 		int start = (p->start + mask) & ~mask;
-		if (p->file_priv == 0 && start + size <= p->start + p->size)
+		if (p->file_priv == NULL && start + size <= p->start + p->size)
 			return split_block(p, start, size, file_priv);
 	}
 
@@ -115,7 +115,7 @@
 	/* Assumes a single contiguous range.  Needs a special file_priv in
 	 * 'heap' to stop it being subsumed.
 	 */
-	if (p->next->file_priv == 0) {
+	if (p->next->file_priv == NULL) {
 		struct mem_block *q = p->next;
 		p->size += q->size;
 		p->next = q->next;
@@ -123,7 +123,7 @@
 		drm_free(q, sizeof(*q), DRM_MEM_BUFS);
 	}
 
-	if (p->prev->file_priv == 0) {
+	if (p->prev->file_priv == NULL) {
 		struct mem_block *q = p->prev;
 		q->size += p->size;
 		q->next = p->next;
@@ -176,7 +176,7 @@
 	 * 'heap' to stop it being subsumed.
 	 */
 	list_for_each(p, heap) {
-		while (p->file_priv == 0 && p->next->file_priv == 0) {
+		while (p->file_priv == NULL && p->next->file_priv == NULL) {
 			struct mem_block *q = p->next;
 			p->size += q->size;
 			p->next = q->next;
diff --git a/sys/dev/drm/radeon_microcode.h b/sys/dev/drm/radeon_microcode.h
new file mode 100644
--- /dev/null
+++ b/sys/dev/drm/radeon_microcode.h
@@ -0,0 +1,1845 @@
+/*
+ * Copyright 2007 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * $DragonFly$
+ */
+
+#ifndef RADEON_MICROCODE_H
+#define RADEON_MICROCODE_H
+
+/* production radeon ucode r1xx-r6xx */
+static const u32 R100_cp_microcode[][2]={
+    { 0x21007000, 0000000000 },
+    { 0x20007000, 0000000000 },
+    { 0x000000b4, 0x00000004 },
+    { 0x000000b8, 0x00000004 },
+    { 0x6f5b4d4c, 0000000000 },
+    { 0x4c4c427f, 0000000000 },
+    { 0x5b568a92, 0000000000 },
+    { 0x4ca09c6d, 0000000000 },
+    { 0xad4c4c4c, 0000000000 },
+    { 0x4ce1af3d, 0000000000 },
+    { 0xd8afafaf, 0000000000 },
+    { 0xd64c4cdc, 0000000000 },
+    { 0x4cd10d10, 0000000000 },
+    { 0x000f0000, 0x00000016 },
+    { 0x362f242d, 0000000000 },
+    { 0x00000012, 0x00000004 },
+    { 0x000f0000, 0x00000016 },
+    { 0x362f282d, 0000000000 },
+    { 0x000380e7, 0x00000002 },
+    { 0x04002c97, 0x00000002 },
+    { 0x000f0001, 0x00000016 },
+    { 0x333a3730, 0000000000 },
+    { 0x000077ef, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x00000021, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00061000, 0x00000002 },
+    { 0x00000021, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00061000, 0x00000002 },
+    { 0x00000021, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00000017, 0x00000004 },
+    { 0x0003802b, 0x00000002 },
+    { 0x040067e0, 0x00000002 },
+    { 0x00000017, 0x00000004 },
+    { 0x000077e0, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x000037e1, 0x00000002 },
+    { 0x040067e1, 0x00000006 },
+    { 0x000077e0, 0x00000002 },
+    { 0x000077e1, 0x00000002 },
+    { 0x000077e1, 0x00000006 },
+    { 0xffffffff, 0000000000 },
+    { 0x10000000, 0000000000 },
+    { 0x0003802b, 0x00000002 },
+    { 0x040067e0, 0x00000006 },
+    { 0x00007675, 0x00000002 },
+    { 0x00007676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0000002f, 0x00000018 },
+    { 0x0000002f, 0x00000018 },
+    { 0000000000, 0x00000006 },
+    { 0x00000030, 0x00000018 },
+    { 0x00000030, 0x00000018 },
+    { 0000000000, 0x00000006 },
+    { 0x01605000, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x00098000, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x64c0603e, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00080000, 0x00000016 },
+    { 0000000000, 0000000000 },
+    { 0x0400251d, 0x00000002 },
+    { 0x00007580, 0x00000002 },
+    { 0x00067581, 0x00000002 },
+    { 0x04002580, 0x00000002 },
+    { 0x00067581, 0x00000002 },
+    { 0x00000049, 0x00000004 },
+    { 0x00005000, 0000000000 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x0000750e, 0x00000002 },
+    { 0x00019000, 0x00000002 },
+    { 0x00011055, 0x00000014 },
+    { 0x00000055, 0x00000012 },
+    { 0x0400250f, 0x00000002 },
+    { 0x0000504f, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00007565, 0x00000002 },
+    { 0x00007566, 0x00000002 },
+    { 0x00000058, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x01e655b4, 0x00000002 },
+    { 0x4401b0e4, 0x00000002 },
+    { 0x01c110e4, 0x00000002 },
+    { 0x26667066, 0x00000018 },
+    { 0x040c2565, 0x00000002 },
+    { 0x00000066, 0x00000018 },
+    { 0x04002564, 0x00000002 },
+    { 0x00007566, 0x00000002 },
+    { 0x0000005d, 0x00000004 },
+    { 0x00401069, 0x00000008 },
+    { 0x00101000, 0x00000002 },
+    { 0x000d80ff, 0x00000002 },
+    { 0x0080006c, 0x00000008 },
+    { 0x000f9000, 0x00000002 },
+    { 0x000e00ff, 0x00000002 },
+    { 0000000000, 0x00000006 },
+    { 0x0000008f, 0x00000018 },
+    { 0x0000005b, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00007576, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x00009000, 0x00000002 },
+    { 0x00041000, 0x00000002 },
+    { 0x0c00350e, 0x00000002 },
+    { 0x00049000, 0x00000002 },
+    { 0x00051000, 0x00000002 },
+    { 0x01e785f8, 0x00000002 },
+    { 0x00200000, 0x00000002 },
+    { 0x0060007e, 0x0000000c },
+    { 0x00007563, 0x00000002 },
+    { 0x006075f0, 0x00000021 },
+    { 0x20007073, 0x00000004 },
+    { 0x00005073, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00007576, 0x00000002 },
+    { 0x00007577, 0x00000002 },
+    { 0x0000750e, 0x00000002 },
+    { 0x0000750f, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00600083, 0x0000000c },
+    { 0x006075f0, 0x00000021 },
+    { 0x000075f8, 0x00000002 },
+    { 0x00000083, 0x00000004 },
+    { 0x000a750e, 0x00000002 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x0020750f, 0x00000002 },
+    { 0x00600086, 0x00000004 },
+    { 0x00007570, 0x00000002 },
+    { 0x00007571, 0x00000002 },
+    { 0x00007572, 0x00000006 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00005000, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00007568, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x00000095, 0x0000000c },
+    { 0x00058000, 0x00000002 },
+    { 0x0c607562, 0x00000002 },
+    { 0x00000097, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00600096, 0x00000004 },
+    { 0x400070e5, 0000000000 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x000380e5, 0x00000002 },
+    { 0x000000a8, 0x0000001c },
+    { 0x000650aa, 0x00000018 },
+    { 0x040025bb, 0x00000002 },
+    { 0x000610ab, 0x00000018 },
+    { 0x040075bc, 0000000000 },
+    { 0x000075bb, 0x00000002 },
+    { 0x000075bc, 0000000000 },
+    { 0x00090000, 0x00000006 },
+    { 0x00090000, 0x00000002 },
+    { 0x000d8002, 0x00000006 },
+    { 0x00007832, 0x00000002 },
+    { 0x00005000, 0x00000002 },
+    { 0x000380e7, 0x00000002 },
+    { 0x04002c97, 0x00000002 },
+    { 0x00007820, 0x00000002 },
+    { 0x00007821, 0x00000002 },
+    { 0x00007800, 0000000000 },
+    { 0x01200000, 0x00000002 },
+    { 0x20077000, 0x00000002 },
+    { 0x01200000, 0x00000002 },
+    { 0x20007000, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x0120751b, 0x00000002 },
+    { 0x8040750a, 0x00000002 },
+    { 0x8040750b, 0x00000002 },
+    { 0x00110000, 0x00000002 },
+    { 0x000380e5, 0x00000002 },
+    { 0x000000c6, 0x0000001c },
+    { 0x000610ab, 0x00000018 },
+    { 0x844075bd, 0x00000002 },
+    { 0x000610aa, 0x00000018 },
+    { 0x840075bb, 0x00000002 },
+    { 0x000610ab, 0x00000018 },
+    { 0x844075bc, 0x00000002 },
+    { 0x000000c9, 0x00000004 },
+    { 0x804075bd, 0x00000002 },
+    { 0x800075bb, 0x00000002 },
+    { 0x804075bc, 0x00000002 },
+    { 0x00108000, 0x00000002 },
+    { 0x01400000, 0x00000002 },
+    { 0x006000cd, 0x0000000c },
+    { 0x20c07000, 0x00000020 },
+    { 0x000000cf, 0x00000012 },
+    { 0x00800000, 0x00000006 },
+    { 0x0080751d, 0x00000006 },
+    { 0000000000, 0000000000 },
+    { 0x0000775c, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00661000, 0x00000002 },
+    { 0x0460275d, 0x00000020 },
+    { 0x00004000, 0000000000 },
+    { 0x01e00830, 0x00000002 },
+    { 0x21007000, 0000000000 },
+    { 0x6464614d, 0000000000 },
+    { 0x69687420, 0000000000 },
+    { 0x00000073, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x00005000, 0x00000002 },
+    { 0x000380d0, 0x00000002 },
+    { 0x040025e0, 0x00000002 },
+    { 0x000075e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000380e0, 0x00000002 },
+    { 0x04002394, 0x00000002 },
+    { 0x00005000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x00000008, 0000000000 },
+    { 0x00000004, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 R200_cp_microcode[][2]={
+    { 0x21007000, 0000000000 },
+    { 0x20007000, 0000000000 },
+    { 0x000000bf, 0x00000004 },
+    { 0x000000c3, 0x00000004 },
+    { 0x7a685e5d, 0000000000 },
+    { 0x5d5d5588, 0000000000 },
+    { 0x68659197, 0000000000 },
+    { 0x5da19f78, 0000000000 },
+    { 0x5d5d5d5d, 0000000000 },
+    { 0x5dee5d50, 0000000000 },
+    { 0xf2acacac, 0000000000 },
+    { 0xe75df9e9, 0000000000 },
+    { 0xb1dd0e11, 0000000000 },
+    { 0xe2afafaf, 0000000000 },
+    { 0x000f0000, 0x00000016 },
+    { 0x452f232d, 0000000000 },
+    { 0x00000013, 0x00000004 },
+    { 0x000f0000, 0x00000016 },
+    { 0x452f272d, 0000000000 },
+    { 0x000f0001, 0x00000016 },
+    { 0x3e4d4a37, 0000000000 },
+    { 0x000077ef, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x00000020, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00061000, 0x00000002 },
+    { 0x00000020, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00061000, 0x00000002 },
+    { 0x00000020, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00000016, 0x00000004 },
+    { 0x0003802a, 0x00000002 },
+    { 0x040067e0, 0x00000002 },
+    { 0x00000016, 0x00000004 },
+    { 0x000077e0, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x000037e1, 0x00000002 },
+    { 0x040067e1, 0x00000006 },
+    { 0x000077e0, 0x00000002 },
+    { 0x000077e1, 0x00000002 },
+    { 0x000077e1, 0x00000006 },
+    { 0xffffffff, 0000000000 },
+    { 0x10000000, 0000000000 },
+    { 0x07f007f0, 0000000000 },
+    { 0x0003802a, 0x00000002 },
+    { 0x040067e0, 0x00000006 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002743, 0x00000002 },
+    { 0x00007675, 0x00000002 },
+    { 0x00007676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002743, 0x00000002 },
+    { 0x00007676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0003802b, 0x00000002 },
+    { 0x04002676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002743, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002743, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0000002f, 0x00000018 },
+    { 0x0000002f, 0x00000018 },
+    { 0000000000, 0x00000006 },
+    { 0x00000037, 0x00000018 },
+    { 0x00000037, 0x00000018 },
+    { 0000000000, 0x00000006 },
+    { 0x01605000, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x00098000, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x64c06051, 0x00000004 },
+    { 0x00080000, 0x00000016 },
+    { 0000000000, 0000000000 },
+    { 0x0400251d, 0x00000002 },
+    { 0x00007580, 0x00000002 },
+    { 0x00067581, 0x00000002 },
+    { 0x04002580, 0x00000002 },
+    { 0x00067581, 0x00000002 },
+    { 0x0000005a, 0x00000004 },
+    { 0x00005000, 0000000000 },
+    { 0x00061000, 0x00000002 },
+    { 0x0000750e, 0x00000002 },
+    { 0x00019000, 0x00000002 },
+    { 0x00011064, 0x00000014 },
+    { 0x00000064, 0x00000012 },
+    { 0x0400250f, 0x00000002 },
+    { 0x0000505e, 0x00000004 },
+    { 0x00007565, 0x00000002 },
+    { 0x00007566, 0x00000002 },
+    { 0x00000065, 0x00000004 },
+    { 0x01e655b4, 0x00000002 },
+    { 0x4401b0f0, 0x00000002 },
+    { 0x01c110f0, 0x00000002 },
+    { 0x26667071, 0x00000018 },
+    { 0x040c2565, 0x00000002 },
+    { 0x00000071, 0x00000018 },
+    { 0x04002564, 0x00000002 },
+    { 0x00007566, 0x00000002 },
+    { 0x00000068, 0x00000004 },
+    { 0x00401074, 0x00000008 },
+    { 0x00101000, 0x00000002 },
+    { 0x000d80ff, 0x00000002 },
+    { 0x00800077, 0x00000008 },
+    { 0x000f9000, 0x00000002 },
+    { 0x000e00ff, 0x00000002 },
+    { 0000000000, 0x00000006 },
+    { 0x00000094, 0x00000018 },
+    { 0x00000068, 0x00000004 },
+    { 0x00007576, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x00009000, 0x00000002 },
+    { 0x00041000, 0x00000002 },
+    { 0x0c00350e, 0x00000002 },
+    { 0x00049000, 0x00000002 },
+    { 0x00051000, 0x00000002 },
+    { 0x01e785f8, 0x00000002 },
+    { 0x00200000, 0x00000002 },
+    { 0x00600087, 0x0000000c },
+    { 0x00007563, 0x00000002 },
+    { 0x006075f0, 0x00000021 },
+    { 0x2000707c, 0x00000004 },
+    { 0x0000507c, 0x00000004 },
+    { 0x00007576, 0x00000002 },
+    { 0x00007577, 0x00000002 },
+    { 0x0000750e, 0x00000002 },
+    { 0x0000750f, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x0060008a, 0x0000000c },
+    { 0x006075f0, 0x00000021 },
+    { 0x000075f8, 0x00000002 },
+    { 0x0000008a, 0x00000004 },
+    { 0x000a750e, 0x00000002 },
+    { 0x0020750f, 0x00000002 },
+    { 0x0060008d, 0x00000004 },
+    { 0x00007570, 0x00000002 },
+    { 0x00007571, 0x00000002 },
+    { 0x00007572, 0x00000006 },
+    { 0x00005000, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00007568, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x00000098, 0x0000000c },
+    { 0x00058000, 0x00000002 },
+    { 0x0c607562, 0x00000002 },
+    { 0x0000009a, 0x00000004 },
+    { 0x00600099, 0x00000004 },
+    { 0x400070f1, 0000000000 },
+    { 0x000380f1, 0x00000002 },
+    { 0x000000a7, 0x0000001c },
+    { 0x000650a9, 0x00000018 },
+    { 0x040025bb, 0x00000002 },
+    { 0x000610aa, 0x00000018 },
+    { 0x040075bc, 0000000000 },
+    { 0x000075bb, 0x00000002 },
+    { 0x000075bc, 0000000000 },
+    { 0x00090000, 0x00000006 },
+    { 0x00090000, 0x00000002 },
+    { 0x000d8002, 0x00000006 },
+    { 0x00005000, 0x00000002 },
+    { 0x00007821, 0x00000002 },
+    { 0x00007800, 0000000000 },
+    { 0x00007821, 0x00000002 },
+    { 0x00007800, 0000000000 },
+    { 0x01665000, 0x00000002 },
+    { 0x000a0000, 0x00000002 },
+    { 0x000671cc, 0x00000002 },
+    { 0x0286f1cd, 0x00000002 },
+    { 0x000000b7, 0x00000010 },
+    { 0x21007000, 0000000000 },
+    { 0x000000be, 0x0000001c },
+    { 0x00065000, 0x00000002 },
+    { 0x000a0000, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x000b0000, 0x00000002 },
+    { 0x38067000, 0x00000002 },
+    { 0x000a00ba, 0x00000004 },
+    { 0x20007000, 0000000000 },
+    { 0x01200000, 0x00000002 },
+    { 0x20077000, 0x00000002 },
+    { 0x01200000, 0x00000002 },
+    { 0x20007000, 0000000000 },
+    { 0x00061000, 0x00000002 },
+    { 0x0120751b, 0x00000002 },
+    { 0x8040750a, 0x00000002 },
+    { 0x8040750b, 0x00000002 },
+    { 0x00110000, 0x00000002 },
+    { 0x000380f1, 0x00000002 },
+    { 0x000000d1, 0x0000001c },
+    { 0x000610aa, 0x00000018 },
+    { 0x844075bd, 0x00000002 },
+    { 0x000610a9, 0x00000018 },
+    { 0x840075bb, 0x00000002 },
+    { 0x000610aa, 0x00000018 },
+    { 0x844075bc, 0x00000002 },
+    { 0x000000d4, 0x00000004 },
+    { 0x804075bd, 0x00000002 },
+    { 0x800075bb, 0x00000002 },
+    { 0x804075bc, 0x00000002 },
+    { 0x00108000, 0x00000002 },
+    { 0x01400000, 0x00000002 },
+    { 0x006000d8, 0x0000000c },
+    { 0x20c07000, 0x00000020 },
+    { 0x000000da, 0x00000012 },
+    { 0x00800000, 0x00000006 },
+    { 0x0080751d, 0x00000006 },
+    { 0x000025bb, 0x00000002 },
+    { 0x000040d4, 0x00000004 },
+    { 0x0000775c, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00661000, 0x00000002 },
+    { 0x0460275d, 0x00000020 },
+    { 0x00004000, 0000000000 },
+    { 0x00007999, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00661000, 0x00000002 },
+    { 0x0460299b, 0x00000020 },
+    { 0x00004000, 0000000000 },
+    { 0x01e00830, 0x00000002 },
+    { 0x21007000, 0000000000 },
+    { 0x00005000, 0x00000002 },
+    { 0x00038056, 0x00000002 },
+    { 0x040025e0, 0x00000002 },
+    { 0x000075e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000380ed, 0x00000002 },
+    { 0x04007394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000078c4, 0x00000002 },
+    { 0x000078c5, 0x00000002 },
+    { 0x000078c6, 0x00000002 },
+    { 0x00007924, 0x00000002 },
+    { 0x00007925, 0x00000002 },
+    { 0x00007926, 0x00000002 },
+    { 0x000000f2, 0x00000004 },
+    { 0x00007924, 0x00000002 },
+    { 0x00007925, 0x00000002 },
+    { 0x00007926, 0x00000002 },
+    { 0x000000f9, 0x00000004 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 R300_cp_microcode[][2]={
+    { 0x4200e000, 0000000000 },
+    { 0x4000e000, 0000000000 },
+    { 0x000000ae, 0x00000008 },
+    { 0x000000b2, 0x00000008 },
+    { 0x67554b4a, 0000000000 },
+    { 0x4a4a4475, 0000000000 },
+    { 0x55527d83, 0000000000 },
+    { 0x4a8c8b65, 0000000000 },
+    { 0x4aef4af6, 0000000000 },
+    { 0x4ae14a4a, 0000000000 },
+    { 0xe4979797, 0000000000 },
+    { 0xdb4aebdd, 0000000000 },
+    { 0x9ccc4a4a, 0000000000 },
+    { 0xd1989898, 0000000000 },
+    { 0x4a0f9ad6, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000f041, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000f184, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000f185, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000f186, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000f187, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000080, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00012000, 0x00000004 },
+    { 0x00082000, 0x00000004 },
+    { 0x1800650e, 0x00000004 },
+    { 0x00092000, 0x00000004 },
+    { 0x000a2000, 0x00000004 },
+    { 0x000f0000, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x00000074, 0x00000018 },
+    { 0x0000e563, 0x00000004 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0000a069, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000077, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000077, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0007a, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000084, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000086, 0x00000008 },
+    { 0x00c00085, 0x00000008 },
+    { 0x000700e3, 0x00000004 },
+    { 0x00000092, 0x00000038 },
+    { 0x000ca094, 0x00000030 },
+    { 0x080045bb, 0x00000004 },
+    { 0x000c2095, 0x00000030 },
+    { 0x0800e5bc, 0000000000 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x00120000, 0x0000000c },
+    { 0x00120000, 0x00000004 },
+    { 0x001b0002, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x000000a4, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x000000a1, 0x00000008 },
+    { 0x000000a6, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x000000ad, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x001400a9, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700e3, 0x00000004 },
+    { 0x000000c0, 0x00000038 },
+    { 0x000c2095, 0x00000030 },
+    { 0x0880e5bd, 0x00000005 },
+    { 0x000c2094, 0x00000030 },
+    { 0x0800e5bb, 0x00000005 },
+    { 0x000c2095, 0x00000030 },
+    { 0x0880e5bc, 0x00000005 },
+    { 0x000000c3, 0x00000008 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000c7, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000c9, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080c3, 0x00000008 },
+    { 0x0000f3ce, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053cf, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f3d2, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053d3, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f39d, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c0539e, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700e0, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000e4, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000eb, 0x00000008 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000f3, 0x00000034 },
+    { 0x000000f0, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 R420_cp_microcode[][2]={
+    { 0x4200e000, 0000000000 },
+    { 0x4000e000, 0000000000 },
+    { 0x00000099, 0x00000008 },
+    { 0x0000009d, 0x00000008 },
+    { 0x4a554b4a, 0000000000 },
+    { 0x4a4a4467, 0000000000 },
+    { 0x55526f75, 0000000000 },
+    { 0x4a7e7d65, 0000000000 },
+    { 0xd9d3dff6, 0000000000 },
+    { 0x4ac54a4a, 0000000000 },
+    { 0xc8828282, 0000000000 },
+    { 0xbf4acfc1, 0000000000 },
+    { 0x87b04a4a, 0000000000 },
+    { 0xb5838383, 0000000000 },
+    { 0x4a0f85ba, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000f041, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000f184, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000f185, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000f186, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000f187, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000072, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000069, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0006c, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000076, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000078, 0x00000008 },
+    { 0x00c00077, 0x00000008 },
+    { 0x000700c7, 0x00000004 },
+    { 0x00000080, 0x00000038 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x0000008f, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x0000008c, 0x00000008 },
+    { 0x00000091, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x00000098, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x00140094, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700c7, 0x00000004 },
+    { 0x000000a4, 0x00000038 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000ab, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000ad, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080a7, 0x00000008 },
+    { 0x0000f3ce, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053cf, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f3d2, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053d3, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f39d, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c0539e, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700c4, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000c8, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000cf, 0x00000008 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000d7, 0x00000034 },
+    { 0x000000d4, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0x0000e1cc, 0x00000004 },
+    { 0x0500e1cd, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000000de, 0x00000034 },
+    { 0x000000da, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x0019e1cc, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x0500a000, 0x00000004 },
+    { 0x080041cd, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 RS600_cp_microcode[][2]={
+    { 0x4200e000, 0000000000 },
+    { 0x4000e000, 0000000000 },
+    { 0x000000a0, 0x00000008 },
+    { 0x000000a4, 0x00000008 },
+    { 0x4a554b4a, 0000000000 },
+    { 0x4a4a4467, 0000000000 },
+    { 0x55526f75, 0000000000 },
+    { 0x4a7e7d65, 0000000000 },
+    { 0x4ae74af6, 0000000000 },
+    { 0x4ad34a4a, 0000000000 },
+    { 0xd6898989, 0000000000 },
+    { 0xcd4addcf, 0000000000 },
+    { 0x8ebe4ae2, 0000000000 },
+    { 0xc38a8a8a, 0000000000 },
+    { 0x4a0f8cc8, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000f041, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000f184, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000f185, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000f186, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000f187, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000072, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000069, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0006c, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000076, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000078, 0x00000008 },
+    { 0x00c00077, 0x00000008 },
+    { 0x000700d5, 0x00000004 },
+    { 0x00000084, 0x00000038 },
+    { 0x000ca086, 0x00000030 },
+    { 0x080045bb, 0x00000004 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0800e5bc, 0000000000 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x00120000, 0x0000000c },
+    { 0x00120000, 0x00000004 },
+    { 0x001b0002, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x00000096, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x00000093, 0x00000008 },
+    { 0x00000098, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000009f, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x0014009b, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700d5, 0x00000004 },
+    { 0x000000b2, 0x00000038 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0880e5bd, 0x00000005 },
+    { 0x000c2086, 0x00000030 },
+    { 0x0800e5bb, 0x00000005 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0880e5bc, 0x00000005 },
+    { 0x000000b5, 0x00000008 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000b9, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000bb, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080b5, 0x00000008 },
+    { 0x0000f3ce, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053cf, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f3d2, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053d3, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f39d, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c0539e, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700d2, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000d6, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000dd, 0x00000008 },
+    { 0x00e00116, 0000000000 },
+    { 0x000700e1, 0x00000004 },
+    { 0x0800401c, 0x00000004 },
+    { 0x200050e7, 0x00000004 },
+    { 0x0000e01d, 0x00000004 },
+    { 0x000000e4, 0x00000008 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000eb, 0x00000034 },
+    { 0x000000e8, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 RS690_cp_microcode[][2]={
+    { 0x000000dd, 0x00000008 },
+    { 0x000000df, 0x00000008 },
+    { 0x000000a0, 0x00000008 },
+    { 0x000000a4, 0x00000008 },
+    { 0x4a554b4a, 0000000000 },
+    { 0x4a4a4467, 0000000000 },
+    { 0x55526f75, 0000000000 },
+    { 0x4a7e7d65, 0000000000 },
+    { 0x4ad74af6, 0000000000 },
+    { 0x4ac94a4a, 0000000000 },
+    { 0xcc898989, 0000000000 },
+    { 0xc34ad3c5, 0000000000 },
+    { 0x8e4a4a4a, 0000000000 },
+    { 0x4a8a8a8a, 0000000000 },
+    { 0x4a0f8c4a, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000f041, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000f184, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000f185, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000f186, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000f187, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000072, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000069, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0006c, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000076, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000078, 0x00000008 },
+    { 0x00c00077, 0x00000008 },
+    { 0x000700cb, 0x00000004 },
+    { 0x00000084, 0x00000038 },
+    { 0x000ca086, 0x00000030 },
+    { 0x080045bb, 0x00000004 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0800e5bc, 0000000000 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x00120000, 0x0000000c },
+    { 0x00120000, 0x00000004 },
+    { 0x001b0002, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x00000096, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x00000093, 0x00000008 },
+    { 0x00000098, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000009f, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x0014009b, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x00100000, 0x0000002c },
+    { 0x00004000, 0000000000 },
+    { 0x080045c8, 0x00000004 },
+    { 0x00240005, 0x00000004 },
+    { 0x08004d0b, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700cb, 0x00000004 },
+    { 0x000000b7, 0x00000038 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0880e5bd, 0x00000005 },
+    { 0x000c2086, 0x00000030 },
+    { 0x0800e5bb, 0x00000005 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0880e5bc, 0x00000005 },
+    { 0x000000ba, 0x00000008 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000be, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000c0, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080ba, 0x00000008 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700c8, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000cc, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000d3, 0x00000008 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000db, 0x00000034 },
+    { 0x000000d8, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0x000000e1, 0x00000030 },
+    { 0x4200e000, 0000000000 },
+    { 0x000000e1, 0x00000030 },
+    { 0x4000e000, 0000000000 },
+    { 0x0025001b, 0x00000004 },
+    { 0x00230000, 0x00000004 },
+    { 0x00250005, 0x00000004 },
+    { 0x000000e6, 0x00000034 },
+    { 0000000000, 0x0000000c },
+    { 0x00244000, 0x00000004 },
+    { 0x080045c8, 0x00000004 },
+    { 0x00240005, 0x00000004 },
+    { 0x08004d0b, 0x0000000c },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 R520_cp_microcode[][2]={
+    { 0x4200e000, 0000000000 },
+    { 0x4000e000, 0000000000 },
+    { 0x00000099, 0x00000008 },
+    { 0x0000009d, 0x00000008 },
+    { 0x4a554b4a, 0000000000 },
+    { 0x4a4a4467, 0000000000 },
+    { 0x55526f75, 0000000000 },
+    { 0x4a7e7d65, 0000000000 },
+    { 0xe0dae6f6, 0000000000 },
+    { 0x4ac54a4a, 0000000000 },
+    { 0xc8828282, 0000000000 },
+    { 0xbf4acfc1, 0000000000 },
+    { 0x87b04ad5, 0000000000 },
+    { 0xb5838383, 0000000000 },
+    { 0x4a0f85ba, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000072, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000069, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0006c, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000076, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000078, 0x00000008 },
+    { 0x00c00077, 0x00000008 },
+    { 0x000700c7, 0x00000004 },
+    { 0x00000080, 0x00000038 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x0000008f, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x0000008c, 0x00000008 },
+    { 0x00000091, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x00000098, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x00140094, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700c7, 0x00000004 },
+    { 0x000000a4, 0x00000038 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000ab, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000ad, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080a7, 0x00000008 },
+    { 0x0000f3ce, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053cf, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f3d2, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053d3, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f39d, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c0539e, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700c4, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000c8, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000cf, 0x00000008 },
+    { 0xdeadbeef, 0000000000 },
+    { 0x00000116, 0000000000 },
+    { 0x000700d3, 0x00000004 },
+    { 0x080050e7, 0x00000004 },
+    { 0x000700d4, 0x00000004 },
+    { 0x0800401c, 0x00000004 },
+    { 0x0000e01d, 0000000000 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000de, 0x00000034 },
+    { 0x000000db, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0x0000e1cc, 0x00000004 },
+    { 0x0500e1cd, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000000e5, 0x00000034 },
+    { 0x000000e1, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x0019e1cc, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x0500a000, 0x00000004 },
+    { 0x080041cd, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+
+#endif
diff --git a/sys/dev/drm/radeon_state.c b/sys/dev/drm/radeon_state.c
--- a/sys/dev/drm/radeon_state.c
+++ b/sys/dev/drm/radeon_state.c
@@ -307,8 +307,9 @@
 	case RADEON_CP_3D_DRAW_INDX_2:
 	case RADEON_3D_CLEAR_HIZ:
 		/* safe but r200 only */
-		if (dev_priv->microcode_version != UCODE_R200) {
-			DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+		if ((dev_priv->chip_family < CHIP_R200) ||
+		    (dev_priv->chip_family > CHIP_RV280)) {
+			DRM_ERROR("Invalid 3d packet for non r200-class chip\n");
 			return -EINVAL;
 		}
 		break;
@@ -361,8 +362,8 @@
 		break;
 
 	case RADEON_3D_RNDR_GEN_INDX_PRIM:
-		if (dev_priv->microcode_version != UCODE_R100) {
-			DRM_ERROR("Invalid 3d packet for r200-class chip\n");
+		if (dev_priv->chip_family > CHIP_RS200) {
+			DRM_ERROR("Invalid 3d packet for non-r100-class chip\n");
 			return -EINVAL;
 		}
 		if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) {
@@ -372,8 +373,10 @@
 		break;
 
 	case RADEON_CP_INDX_BUFFER:
-		if (dev_priv->microcode_version != UCODE_R200) {
-			DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+		/* safe but r200 only */
+		if ((dev_priv->chip_family < CHIP_R200) ||
+		    (dev_priv->chip_family > CHIP_RV280)) {
+			DRM_ERROR("Invalid 3d packet for non-r200-class chip\n");
 			return -EINVAL;
 		}
 		if ((cmd[1] & 0x8000ffff) != 0x80000810) {
@@ -1017,7 +1020,7 @@
 			int tileoffset, nrtilesx, nrtilesy, j;
 			/* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
 			if ((dev_priv->flags & RADEON_HAS_HIERZ)
-			    && !(dev_priv->microcode_version == UCODE_R200)) {
+			    && (dev_priv->chip_family < CHIP_R200)) {
 				/* FIXME : figure this out for r200 (when hierz is enabled). Or
 				   maybe r200 actually doesn't need to put the low-res z value into
 				   the tile cache like r100, but just needs to clear the hi-level z-buffer?
@@ -1046,7 +1049,8 @@
 					ADVANCE_RING();
 					tileoffset += depthpixperline >> 6;
 				}
-			} else if (dev_priv->microcode_version == UCODE_R200) {
+			} else if ((dev_priv->chip_family >= CHIP_R200) &&
+				   (dev_priv->chip_family <= CHIP_RV280)) {
 				/* works for rv250. */
 				/* find first macro tile (8x2 4x4 z-pixels on rv250) */
 				tileoffset =
@@ -1101,7 +1105,8 @@
 
 		/* TODO don't always clear all hi-level z tiles */
 		if ((dev_priv->flags & RADEON_HAS_HIERZ)
-		    && (dev_priv->microcode_version == UCODE_R200)
+		    && ((dev_priv->chip_family >= CHIP_R200) &&
+			(dev_priv->chip_family <= CHIP_RV280))
 		    && (flags & RADEON_USE_HIERZ))
 			/* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
 			/* FIXME : the mask supposedly contains low-res z values. So can't set
@@ -1121,8 +1126,9 @@
 	 * rendering a quad into just those buffers.  Thus, we have to
 	 * make sure the 3D engine is configured correctly.
 	 */
-	else if ((dev_priv->microcode_version == UCODE_R200) &&
-		(flags & (RADEON_DEPTH | RADEON_STENCIL))) {
+	else if ((dev_priv->chip_family >= CHIP_R200) &&
+		 (dev_priv->chip_family <= CHIP_RV280) &&
+		 (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
 
 		int tempPP_CNTL;
 		int tempRE_CNTL;
@@ -1664,7 +1670,7 @@
 	u32 height;
 	int i;
 	u32 texpitch, microtile;
-	u32 offset;
+	u32 offset, byte_offset;
 	RING_LOCALS;
 
 	if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) {
@@ -1728,6 +1734,13 @@
 		}
 	} else
 		microtile = 0;
+
+	/* this might fail for zero-sized uploads - are those illegal? */
+	if (!radeon_check_offset(dev_priv, tex->offset + image->height *
+				blit_width - 1)) {
+		DRM_ERROR("Invalid final destination offset\n");
+		return -EINVAL;
+	}
 
 	DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
 
@@ -1842,6 +1855,7 @@
 		}
 
 #undef RADEON_COPY_MT
+		byte_offset = (image->y & ~2047) * blit_width;
 		buf->file_priv = file_priv;
 		buf->used = size;
 		offset = dev_priv->gart_buffers_offset + buf->offset;
@@ -1856,9 +1870,9 @@
 			 RADEON_DP_SRC_SOURCE_MEMORY |
 			 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
 		OUT_RING((spitch << 22) | (offset >> 10));
-		OUT_RING((texpitch << 22) | (tex->offset >> 10));
+		OUT_RING((texpitch << 22) | ((tex->offset >> 10) + (byte_offset >> 10)));
 		OUT_RING(0);
-		OUT_RING((image->x << 16) | image->y);
+		OUT_RING((image->x << 16) | (image->y % 2048));
 		OUT_RING((image->width << 16) | height);
 		RADEON_WAIT_UNTIL_2D_IDLE();
 		ADVANCE_RING();
@@ -2883,7 +2897,7 @@
 
 	orig_nbox = cmdbuf->nbox;
 
-	if (dev_priv->microcode_version == UCODE_R300) {
+	if (dev_priv->chip_family >= CHIP_R300) {
 		int temp;
 		temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
 
@@ -3085,6 +3099,9 @@
 	case RADEON_PARAM_FB_LOCATION:
 		value = radeon_read_fb_location(dev_priv);
 		break;
+	case RADEON_PARAM_NUM_GB_PIPES:
+		value = dev_priv->num_gb_pipes;
+		break;
 	default:
 		DRM_DEBUG( "Invalid parameter %d\n", param->param );
 		return -EINVAL;
@@ -3120,12 +3137,14 @@
 			DRM_DEBUG("color tiling disabled\n");
 			dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
 			dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
-			dev_priv->sarea_priv->tiling_enabled = 0;
+			if (dev_priv->sarea_priv)
+				dev_priv->sarea_priv->tiling_enabled = 0;
 		} else if (sp->value == 1) {
 			DRM_DEBUG("color tiling enabled\n");
 			dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
 			dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
-			dev_priv->sarea_priv->tiling_enabled = 1;
+			if (dev_priv->sarea_priv)
+				dev_priv->sarea_priv->tiling_enabled = 1;
 		}
 		break;
 	case RADEON_SETPARAM_PCIGART_LOCATION:
diff --git a/sys/dev/drm/savage_drv.c b/sys/dev/drm/savage_drv.c
--- a/sys/dev/drm/savage_drv.c
+++ b/sys/dev/drm/savage_drv.c
@@ -39,33 +39,31 @@
 	savage_PCI_IDS
 };
 
-static void savage_configure(drm_device_t *dev)
+static void savage_configure(struct drm_device *dev)
 {
-	dev->driver.buf_priv_size	= sizeof(drm_savage_buf_priv_t);
-	dev->driver.load		= savage_driver_load;
-	dev->driver.firstopen		= savage_driver_firstopen;
-	dev->driver.lastclose		= savage_driver_lastclose;
-	dev->driver.unload		= savage_driver_unload;
-	dev->driver.reclaim_buffers_locked = savage_reclaim_buffers;
-	dev->driver.dma_ioctl		= savage_bci_buffers;
+	dev->driver->driver_features =
+	    DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
+	    DRIVER_HAVE_DMA;
 
-	dev->driver.ioctls		= savage_ioctls;
-	dev->driver.max_ioctl		= savage_max_ioctl;
+	dev->driver->buf_priv_size	= sizeof(drm_savage_buf_priv_t);
+	dev->driver->load		= savage_driver_load;
+	dev->driver->firstopen		= savage_driver_firstopen;
+	dev->driver->lastclose		= savage_driver_lastclose;
+	dev->driver->unload		= savage_driver_unload;
+	dev->driver->reclaim_buffers_locked = savage_reclaim_buffers;
+	dev->driver->dma_ioctl		= savage_bci_buffers;
 
-	dev->driver.name		= DRIVER_NAME;
-	dev->driver.desc		= DRIVER_DESC;
-	dev->driver.date		= DRIVER_DATE;
-	dev->driver.major		= DRIVER_MAJOR;
-	dev->driver.minor		= DRIVER_MINOR;
-	dev->driver.patchlevel		= DRIVER_PATCHLEVEL;
+	dev->driver->ioctls		= savage_ioctls;
+	dev->driver->max_ioctl		= savage_max_ioctl;
 
-	dev->driver.use_agp		= 1;
-	dev->driver.use_mtrr		= 1;
-	dev->driver.use_pci_dma		= 1;
-	dev->driver.use_dma		= 1;
+	dev->driver->name		= DRIVER_NAME;
+	dev->driver->desc		= DRIVER_DESC;
+	dev->driver->date		= DRIVER_DATE;
+	dev->driver->major		= DRIVER_MAJOR;
+	dev->driver->minor		= DRIVER_MINOR;
+	dev->driver->patchlevel		= DRIVER_PATCHLEVEL;
 }
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 static int
 savage_probe(device_t dev)
 {
@@ -75,18 +73,34 @@
 static int
 savage_attach(device_t nbdev)
 {
-	drm_device_t *dev = device_get_softc(nbdev);
+	struct drm_device *dev = device_get_softc(nbdev);
 
-	bzero(dev, sizeof(drm_device_t));
+	dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
+	    M_WAITOK | M_ZERO);
+
 	savage_configure(dev);
+
 	return drm_attach(nbdev, savage_pciidlist);
+}
+
+static int
+savage_detach(device_t nbdev)
+{
+	struct drm_device *dev = device_get_softc(nbdev);
+	int ret;
+
+	ret = drm_detach(nbdev);
+
+	free(dev->driver, DRM_MEM_DRIVER);
+
+	return ret;
 }
 
 static device_method_t savage_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		savage_probe),
 	DEVMETHOD(device_attach,	savage_attach),
-	DEVMETHOD(device_detach,	drm_detach),
+	DEVMETHOD(device_detach,	savage_detach),
 
 	{ 0, 0 }
 };
@@ -94,7 +108,7 @@
 static driver_t savage_driver = {
 	"drm",
 	savage_methods,
-	sizeof(drm_device_t)
+	sizeof(struct drm_device)
 };
 
 extern devclass_t drm_devclass;
@@ -104,7 +118,3 @@
 DRIVER_MODULE(savage, pci, savage_driver, drm_devclass, 0, 0);
 #endif
 MODULE_DEPEND(savage, drm, 1, 1, 1);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-CFDRIVER_DECL(savage, DV_TTY, NULL);
-#endif
diff --git a/sys/dev/drm/sis_drv.c b/sys/dev/drm/sis_drv.c
--- a/sys/dev/drm/sis_drv.c
+++ b/sys/dev/drm/sis_drv.c
@@ -37,27 +37,26 @@
 	sis_PCI_IDS
 };
 
-static void sis_configure(drm_device_t *dev)
+static void sis_configure(struct drm_device *dev)
 {
-	dev->driver.buf_priv_size	= 1; /* No dev_priv */
-	dev->driver.context_ctor	= sis_init_context;
-	dev->driver.context_dtor	= sis_final_context;
+	dev->driver->driver_features =
+	    DRIVER_USE_AGP | DRIVER_USE_MTRR;
 
-	dev->driver.ioctls		= sis_ioctls;
-	dev->driver.max_ioctl		= sis_max_ioctl;
+	dev->driver->buf_priv_size	= 1; /* No dev_priv */
+	dev->driver->context_ctor	= sis_init_context;
+	dev->driver->context_dtor	= sis_final_context;
 
-	dev->driver.name		= DRIVER_NAME;
-	dev->driver.desc		= DRIVER_DESC;
-	dev->driver.date		= DRIVER_DATE;
-	dev->driver.major		= DRIVER_MAJOR;
-	dev->driver.minor		= DRIVER_MINOR;
-	dev->driver.patchlevel		= DRIVER_PATCHLEVEL;
+	dev->driver->ioctls		= sis_ioctls;
+	dev->driver->max_ioctl		= sis_max_ioctl;
 
-	dev->driver.use_agp		= 1;
-	dev->driver.use_mtrr		= 1;
+	dev->driver->name		= DRIVER_NAME;
+	dev->driver->desc		= DRIVER_DESC;
+	dev->driver->date		= DRIVER_DATE;
+	dev->driver->major		= DRIVER_MAJOR;
+	dev->driver->minor		= DRIVER_MINOR;
+	dev->driver->patchlevel		= DRIVER_PATCHLEVEL;
 }
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 static int
 sis_probe(device_t dev)
 {
@@ -67,18 +66,34 @@
 static int
 sis_attach(device_t nbdev)
 {
-	drm_device_t *dev = device_get_softc(nbdev);
+	struct drm_device *dev = device_get_softc(nbdev);
 
-	bzero(dev, sizeof(drm_device_t));
+	dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
+	    M_WAITOK | M_ZERO);
+
 	sis_configure(dev);
+
 	return drm_attach(nbdev, sis_pciidlist);
+}
+
+static int
+sis_detach(device_t nbdev)
+{
+	struct drm_device *dev = device_get_softc(nbdev);
+	int ret;
+
+	ret = drm_detach(nbdev);
+
+	free(dev->driver, DRM_MEM_DRIVER);
+
+	return ret;
 }
 
 static device_method_t sis_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		sis_probe),
 	DEVMETHOD(device_attach,	sis_attach),
-	DEVMETHOD(device_detach,	drm_detach),
+	DEVMETHOD(device_detach,	sis_detach),
 
 	{ 0, 0 }
 };
@@ -86,7 +101,7 @@
 static driver_t sis_driver = {
 	"drm",
 	sis_methods,
-	sizeof(drm_device_t)
+	sizeof(struct drm_device)
 };
 
 extern devclass_t drm_devclass;
@@ -96,12 +111,3 @@
 DRIVER_MODULE(sisdrm, pci, sis_driver, drm_devclass, 0, 0);
 #endif
 MODULE_DEPEND(sisdrm, drm, 1, 1, 1);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-#ifdef _LKM
-CFDRIVER_DECL(sis, DV_TTY, NULL);
-#else
-CFATTACH_DECL(sis, sizeof(drm_device_t), drm_probe, drm_attach, drm_detach,
-    drm_activate);
-#endif
-#endif
diff --git a/sys/dev/drm/tdfx_drv.c b/sys/dev/drm/tdfx_drv.c
--- a/sys/dev/drm/tdfx_drv.c
+++ b/sys/dev/drm/tdfx_drv.c
@@ -42,23 +42,23 @@
 	tdfx_PCI_IDS
 };
 
-static void tdfx_configure(drm_device_t *dev)
+static void tdfx_configure(struct drm_device *dev)
 {
-	dev->driver.buf_priv_size	= 1; /* No dev_priv */
+	dev->driver->driver_features =
+	    DRIVER_USE_MTRR;
 
-	dev->driver.max_ioctl		= 0;
+	dev->driver->buf_priv_size	= 1; /* No dev_priv */
 
-	dev->driver.name		= DRIVER_NAME;
-	dev->driver.desc		= DRIVER_DESC;
-	dev->driver.date		= DRIVER_DATE;
-	dev->driver.major		= DRIVER_MAJOR;
-	dev->driver.minor		= DRIVER_MINOR;
-	dev->driver.patchlevel		= DRIVER_PATCHLEVEL;
+	dev->driver->max_ioctl		= 0;
 
-	dev->driver.use_mtrr		= 1;
+	dev->driver->name		= DRIVER_NAME;
+	dev->driver->desc		= DRIVER_DESC;
+	dev->driver->date		= DRIVER_DATE;
+	dev->driver->major		= DRIVER_MAJOR;
+	dev->driver->minor		= DRIVER_MINOR;
+	dev->driver->patchlevel		= DRIVER_PATCHLEVEL;
 }
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
 static int
 tdfx_probe(device_t dev)
 {
@@ -68,18 +68,34 @@
 static int
 tdfx_attach(device_t nbdev)
 {
-	drm_device_t *dev = device_get_softc(nbdev);
+	struct drm_device *dev = device_get_softc(nbdev);
 
-	bzero(dev, sizeof(drm_device_t));
+	dev->driver = malloc(sizeof(struct drm_driver_info), DRM_MEM_DRIVER,
+	    M_WAITOK | M_ZERO);
+
 	tdfx_configure(dev);
+
 	return drm_attach(nbdev, tdfx_pciidlist);
+}
+
+static int
+tdfx_detach(device_t nbdev)
+{
+	struct drm_device *dev = device_get_softc(nbdev);
+	int ret;
+
+	ret = drm_detach(nbdev);
+
+	free(dev->driver, DRM_MEM_DRIVER);
+
+	return ret;
 }
 
 static device_method_t tdfx_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		tdfx_probe),
 	DEVMETHOD(device_attach,	tdfx_attach),
-	DEVMETHOD(device_detach,	drm_detach),
+	DEVMETHOD(device_detach,	tdfx_detach),
 
 	{ 0, 0 }
 };
@@ -87,7 +103,7 @@
 static driver_t tdfx_driver = {
 	"drm",
 	tdfx_methods,
-	sizeof(drm_device_t)
+	sizeof(struct drm_device)
 };
 
 extern devclass_t drm_devclass;
@@ -97,12 +113,3 @@
 DRIVER_MODULE(tdfx, pci, tdfx_driver, drm_devclass, 0, 0);
 #endif
 MODULE_DEPEND(tdfx, drm, 1, 1, 1);
-
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-#ifdef _LKM
-CFDRIVER_DECL(tdfx, DV_TTY, NULL);
-#else
-CFATTACH_DECL(tdfx, sizeof(drm_device_t), drm_probe, drm_attach, drm_detach,
-    drm_activate);
-#endif
-#endif
