drm: add _DRM_CONSISTENT map type

Added a new DRM map type _DRM_CONSISTENT for consistent PCI memory. It
uses drm_pci_alloc/free for allocating/freeing the memory.

From: Felix Kuhling <fxkuehl@gmx.de>
Signed-off-by: David Airlie <airlied@linux.ie>
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index e8371dd..50c4d98 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -209,7 +209,8 @@
 	_DRM_REGISTERS	    = 1,  /**< no caching, no core dump */
 	_DRM_SHM	    = 2,  /**< shared, cached */
 	_DRM_AGP            = 3,  /**< AGP/GART */
-	_DRM_SCATTER_GATHER = 4	  /**< Scatter/gather memory for PCI DMA */
+	_DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
+	_DRM_CONSISTENT     = 5,  /**< Consistent memory for PCI DMA */
 } drm_map_type_t;
 
 
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 4c6191d..89f301f 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -180,7 +180,22 @@
 		}
 		map->offset += dev->sg->handle;
 		break;
-
+	case _DRM_CONSISTENT: 
+	{
+		/* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
+		 * As we're limit the address to 2^32-1 (or lses),
+		 * casting it down to 32 bits is no problem, but we
+		 * need to point to a 64bit variable first. */
+		dma_addr_t bus_addr;
+		map->handle = drm_pci_alloc(dev, map->size, map->size,
+					    0xffffffffUL, &bus_addr);
+		map->offset = (unsigned long)bus_addr;
+		if (!map->handle) {
+			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			return -ENOMEM;
+		}
+		break;
+	}
 	default:
 		drm_free( map, sizeof(*map), DRM_MEM_MAPS );
 		return -EINVAL;
@@ -291,6 +306,9 @@
 		case _DRM_AGP:
 		case _DRM_SCATTER_GATHER:
 			break;
+		case _DRM_CONSISTENT:
+			drm_pci_free(dev, map->size, map->handle, map->offset);
+			break;
 		}
 		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 	}
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 3333c25..f4046c8 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -228,6 +228,10 @@
 						dev->sg = NULL;
 					}
 					break;
+				case _DRM_CONSISTENT:
+					drm_pci_free(dev, map->size,
+						     map->handle, map->offset);
+					break;
 				}
 				drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 			}
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 4774087..f4154cc 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -210,8 +210,8 @@
 
 				/* Hardcoded from _DRM_FRAME_BUFFER,
                                    _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
-                                   _DRM_SCATTER_GATHER. */
-	const char   *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
+                                   _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
+	const char   *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
 	const char   *type;
 	int	     i;
 
@@ -229,9 +229,12 @@
 	if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) {
 		r_list = list_entry(list, drm_map_list_t, head);
 		map = r_list->map;
-		if(!map) continue;
-		if (map->type < 0 || map->type > 4) type = "??";
-		else				    type = types[map->type];
+		if(!map)
+			continue;
+		if (map->type < 0 || map->type > 5)
+			type = "??";
+		else	
+			type = types[map->type];
 		DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
 			       i,
 			       map->offset,
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index 621220f..644ec9da 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -228,6 +228,10 @@
 			case _DRM_AGP:
 			case _DRM_SCATTER_GATHER:
 				break;
+			case _DRM_CONSISTENT:
+				drm_pci_free(dev, map->size, map->handle,
+					     map->offset);
+				break;
 			}
 			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 		}
@@ -645,6 +649,9 @@
 		vma->vm_ops = &drm_vm_ops;
 		break;
 	case _DRM_SHM:
+	case _DRM_CONSISTENT:
+		/* Consistent memory is really like shared memory. It's only
+		 * allocate in a different way */
 		vma->vm_ops = &drm_vm_shm_ops;
 		vma->vm_private_data = (void *)map;
 				/* Don't let this area swap.  Change when