Index: drivers/char/drm/drmP.h
===================================================================
--- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drmP.h  (mode:100644)
+++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drmP.h  (mode:100644)
@@ -91,11 +91,12 @@
 #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_IRQ_SHARED  0x80
-#define DRIVER_IRQ_VBL     0x100
-#define DRIVER_DMA_QUEUE   0x200
+#define DRIVER_FB_DMA      0x20
+#define DRIVER_HAVE_DMA    0x40
+#define DRIVER_HAVE_IRQ    0x80
+#define DRIVER_IRQ_SHARED  0x100
+#define DRIVER_IRQ_VBL     0x200
+#define DRIVER_DMA_QUEUE   0x400
 
 /***********************************************************************/
 /** \name Begin the DRM... */
@@ -588,6 +589,7 @@
  	int (*version)(drm_version_t *version);
 	u32 driver_features;
 	int dev_priv_size;
+	int permanent_maps;
 	drm_ioctl_desc_t *ioctls;
 	int num_ioctls;
 	struct file_operations fops;
@@ -902,6 +904,9 @@
 				  unsigned int cmd, unsigned long arg );
 extern int	     drm_rmmap( struct inode *inode, struct file *filp,
 				 unsigned int cmd, unsigned long arg );
+extern int	     drm_initmap( drm_device_t *dev, unsigned int offset,
+				 unsigned int size, unsigned int resource,
+				 int type, int flags);
 extern int	     drm_addbufs( struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg );
 extern int	     drm_infobufs( struct inode *inode, struct file *filp,
@@ -912,6 +917,11 @@
 				    unsigned int cmd, unsigned long arg );
 extern int	     drm_mapbufs( struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg );
+extern unsigned long drm_get_resource_start(drm_device_t *dev,
+					    unsigned int resource);
+extern unsigned long drm_get_resource_len(drm_device_t *dev,
+					  unsigned int resource);
+
 
 				/* DMA support (drm_dma.h) */
 extern int	     drm_dma_setup(drm_device_t *dev);
Index: drivers/char/drm/drm_bufs.c
===================================================================
--- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drm_bufs.c  (mode:100644)
+++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drm_bufs.c  (mode:100644)
@@ -60,6 +60,79 @@
 }
 EXPORT_SYMBOL(drm_order);
 
+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
+{
+	return pci_resource_start(dev->pdev, resource);
+}
+EXPORT_SYMBOL(drm_get_resource_start);
+
+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
+{
+	return pci_resource_len(dev->pdev, resource);
+}
+EXPORT_SYMBOL(drm_get_resource_len);
+
+/**
+ * Adjusts the memory offset to its absolute value according to the mapping
+ * type.  Adds the map to the map list drm_device::maplist. Adds MTRR's where
+ * applicable and if supported by the kernel.
+ */
+int drm_initmap(drm_device_t * dev, unsigned int offset, unsigned int size,
+		unsigned int resource, int type, int flags)
+{
+	drm_map_t *map;
+	drm_map_list_t *list;
+	
+	DRM_DEBUG("\n");
+
+	if ((offset & (~PAGE_MASK)) || (size & (~PAGE_MASK)))
+		return -EINVAL;
+#if !defined(__sparc__) && !defined(__alpha__)
+	if (offset + size < offset || offset < virt_to_phys(high_memory))
+		return -EINVAL;
+#endif
+	if (!(list = drm_alloc(sizeof(*list), DRM_MEM_MAPS)))
+		return -ENOMEM;
+	memset(list, 0, sizeof(*list));
+
+	if (!(map = drm_alloc(sizeof(*map), DRM_MEM_MAPS))) {
+		drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+		return -ENOMEM;
+	}
+
+	*map = (drm_map_t) {
+	.offset = offset,.size = size,.type = type,.flags =
+		    flags,.mtrr = -1,.handle = 0,};
+	list->map = map;
+
+	DRM_DEBUG("initmap offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+		  map->offset, map->size, map->type);
+
+#ifdef __alpha__
+	map->offset += dev->hose->mem_space->start;
+#endif
+	if (drm_core_has_MTRR(dev)) {
+		if (map->type == _DRM_FRAME_BUFFER ||
+		    (map->flags & _DRM_WRITE_COMBINING)) {
+			map->mtrr = mtrr_add(map->offset, map->size,
+					     MTRR_TYPE_WRCOMB, 1);
+		}
+	}
+
+	if (map->type == _DRM_REGISTERS)
+		map->handle = drm_ioremap(map->offset, map->size, dev);
+
+	down(&dev->struct_sem);
+	list_add(&list->head, &dev->maplist->head);
+	up(&dev->struct_sem);
+
+	dev->driver->permanent_maps = 1;
+	DRM_DEBUG("finished\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_initmap);
+
 /**
  * Ioctl to specify a range of memory that is available for mapping by a non-root process.
  *
@@ -113,6 +186,39 @@
 	switch ( map->type ) {
 	case _DRM_REGISTERS:
 	case _DRM_FRAME_BUFFER:
+	{
+		/* after all the drivers switch to permanent mapping this should just return an error */
+		struct list_head *_list;
+		
+		/* If permanent maps are implemented, maps must match */
+		if (dev->driver->permanent_maps) {
+			DRM_DEBUG("Looking for: offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+				  map->offset, map->size, map->type);
+			list_for_each(_list, &dev->maplist->head) {
+				drm_map_list_t *_entry =
+					list_entry(_list, drm_map_list_t,
+						   head);
+				DRM_DEBUG("Checking: offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+					  _entry->map->offset,
+					  _entry->map->size,
+					  _entry->map->type);
+				if (_entry->map
+				    && map->type == _entry->map->type
+				    && map->offset ==
+				    _entry->map->offset) {
+					_entry->map->size = map->size;
+					drm_free(map, sizeof(*map),
+						 DRM_MEM_MAPS);
+					map = _entry->map;
+					DRM_DEBUG("Found existing: offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+						  map->offset, map->size,
+						  map->type);
+					goto found_it;
+				}
+			}
+			/* addmap didn't match an existing permanent map, that's an error */
+			return -EINVAL;
+		}
 #if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__)
 		if ( map->offset + map->size < map->offset ||
 		     map->offset < virt_to_phys(high_memory) ) {
@@ -134,7 +240,7 @@
 			map->handle = drm_ioremap( map->offset, map->size,
 						    dev );
 		break;
-
+	}
 	case _DRM_SHM:
 		map->handle = vmalloc_32(map->size);
 		DRM_DEBUG( "%lu %d %p\n",
@@ -188,7 +294,7 @@
 	down(&dev->struct_sem);
 	list_add(&list->head, &dev->maplist->head);
  	up(&dev->struct_sem);
-
+found_it:
 	if ( copy_to_user( argp, map, sizeof(*map) ) )
 		return -EFAULT;
 	if ( map->type != _DRM_SHM ) {
@@ -252,6 +358,12 @@
 		return -EINVAL;
 	}
 	map = r_list->map;
+	/* Register and framebuffer maps are permanent */
+	if ((map->type == _DRM_REGISTERS) || 
+	    (map->type == _DRM_FRAME_BUFFER)) {
+		up(&dev->struct_sem);
+		return 0;
+	}
 	list_del(list);
 	drm_free(list, sizeof(*list), DRM_MEM_MAPS);
 
@@ -263,16 +375,6 @@
 		switch (map->type) {
 		case _DRM_REGISTERS:
 		case _DRM_FRAME_BUFFER:
-		  if (drm_core_has_MTRR(dev)) {
-				if (map->mtrr >= 0) {
-					int retcode;
-					retcode = mtrr_del(map->mtrr,
-							   map->offset,
-							   map->size);
-					DRM_DEBUG("mtrr_del = %d\n", retcode);
-				}
-			}
-			drm_ioremapfree(map->handle, map->size, dev);
 			break;
 		case _DRM_SHM:
 			vfree(map->handle);
Index: drivers/char/drm/drm_drv.c
===================================================================
--- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drm_drv.c  (mode:100644)
+++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drm_drv.c  (mode:100644)
@@ -198,17 +198,7 @@
 				switch ( map->type ) {
 				case _DRM_REGISTERS:
 				case _DRM_FRAME_BUFFER:
-					if (drm_core_has_MTRR(dev)) {
-						if ( map->mtrr >= 0 ) {
-							int retcode;
-							retcode = mtrr_del( map->mtrr,
-									    map->offset,
-									    map->size );
-							DRM_DEBUG( "mtrr_del=%d\n", retcode );
-						}
-					}
-					drm_ioremapfree( map->handle, map->size, dev );
-					break;
+					continue;
 				case _DRM_SHM:
 					vfree(map->handle);
 					break;
@@ -231,8 +221,6 @@
 			list_del( list );
 			drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
  		}
-		drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
-		dev->maplist = NULL;
  	}
 
 	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
@@ -313,6 +301,10 @@
  */
 static void drm_cleanup( drm_device_t *dev )
 {
+	drm_map_t *map;
+	drm_map_list_t *r_list;
+	struct list_head *list, *list_next;
+
 	DRM_DEBUG( "\n" );
 
 	if (!dev) {
@@ -320,7 +312,47 @@
 		return;
 	}
 
-	drm_takedown( dev );	
+	drm_takedown( dev );
+
+	if (dev->maplist) {
+		list_for_each_safe(list, list_next, &dev->maplist->head) {
+			r_list = (drm_map_list_t *) list;
+			
+			if ((map = r_list->map)) {
+				switch (map->type) {
+				case _DRM_REGISTERS:
+					drm_ioremapfree(map->handle, map->size,
+							dev);
+					break;
+					
+				case _DRM_FRAME_BUFFER:
+					if (drm_core_has_MTRR(dev)) {
+						if (map->mtrr >= 0) {
+							int retcode;
+							retcode = 
+								mtrr_del(map->mtrr,
+									 map->
+									 offset,
+									 map->size);
+							DRM_DEBUG("mtrr_del=%d\n",
+								  retcode);
+						}
+					}
+					break;
+				case _DRM_SHM:
+				case _DRM_AGP:
+				case _DRM_SCATTER_GATHER:
+					DRM_DEBUG("Extra maplist item\n");
+					break;
+				}
+				drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			}
+			list_del(list);
+			drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+		}
+		drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
+		dev->maplist = NULL;
+	}
 
 	drm_ctxbitmap_cleanup( dev );
 	
Index: drivers/char/drm/drm_fops.c
===================================================================
--- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drm_fops.c  (mode:100644)
+++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drm_fops.c  (mode:100644)
@@ -69,12 +69,6 @@
 		dev->magiclist[i].tail = NULL;
 	}
 
-	dev->maplist = drm_alloc(sizeof(*dev->maplist),
-				  DRM_MEM_MAPS);
-	if(dev->maplist == NULL) return -ENOMEM;
-	memset(dev->maplist, 0, sizeof(*dev->maplist));
-	INIT_LIST_HEAD(&dev->maplist->head);
-
 	dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist),
 				  DRM_MEM_CTXLIST);
 	if(dev->ctxlist == NULL) return -ENOMEM;
Index: drivers/char/drm/drm_stub.c
===================================================================
--- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/drm_stub.c  (mode:100644)
+++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/drm_stub.c  (mode:100644)
@@ -75,6 +75,12 @@
 	dev->pci_func = PCI_FUNC(pdev->devfn);
 	dev->irq = pdev->irq;
 
+	dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
+	if(dev->maplist == NULL)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&dev->maplist->head);
+
+
 	/* the DRM has 6 basic counters */
 	dev->counters = 6;
 	dev->types[0]  = _DRM_STAT_LOCK;
Index: drivers/char/drm/radeon_cp.c
===================================================================
--- 1ec02e9402f82786095e58d99b1b25e95fc63c10/drivers/char/drm/radeon_cp.c  (mode:100644)
+++ 94b5458977901d93d06b802afa58615da0ebec32/drivers/char/drm/radeon_cp.c  (mode:100644)
@@ -2045,6 +2045,18 @@
 	/* all other chips have no hierarchical z buffer */
 		break;
 	}
+
+	ret = drm_initmap(dev, drm_get_resource_start(dev, 2),
+			  drm_get_resource_len(dev, 2), 2, _DRM_REGISTERS, 0);
+	if (ret != 0)
+		return ret;
+	
+	ret = drm_initmap(dev, drm_get_resource_start(dev, 0),
+			  drm_get_resource_len(dev, 0), 0, _DRM_FRAME_BUFFER,
+			  _DRM_WRITE_COMBINING);
+	if (ret != 0)
+		return ret;
+
 	return ret;
 }