The attached patch adds a new mapping type _DRM_CONSISTENT. It works
basically like shared memory but allocates consistent memory and returns
the physical address to user space as handle. I wouldn't be surprised if
I missed something, but it works for me. I'm typing this in an X session
with the Savage 2D driver with shadow status, where the status page is a
_DRM_CONSISTENT mapping.

Best regards,
  Felix

P.S.: The patch for Xorg is basically a one-liner (for completeness):

--- programs/Xserver/hw/xfree86/os-support/xf86drm.h.~1.3.~    
2004-06-16 11:39:14.000000000 +0200
+++ programs/Xserver/hw/xfree86/os-support/xf86drm.h    2004-10-16
02:00:35.000000000 +0200
@@ -104,7 +104,8 @@
     DRM_REGISTERS       = 1,      /**< no caching, no core dump */
     DRM_SHM             = 2,      /**< shared, cached */
     DRM_AGP             = 3,     /**< AGP/GART */
-    DRM_SCATTER_GATHER  = 4      /**< PCI scatter/gather */
+    DRM_SCATTER_GATHER  = 4,     /**< PCI scatter/gather */
+    DRM_CONSISTENT      = 5      /**< PCI consistent */
 } drmMapType;

 typedef enum {

-- 
| Felix K�hling <[EMAIL PROTECTED]>                     http://fxk.de.vu |
| PGP Fingerprint: 6A3C 9566 5B30 DDED 73C3  B152 151C 5CC1 D888 E595 |
--- linux-core/drm_bufs.c.~1.50.~	2004-10-13 23:01:50.000000000 +0200
+++ linux-core/drm_bufs.c	2004-10-16 01:56:25.000000000 +0200
@@ -244,7 +244,21 @@
 		}
 		map->offset += dev->sg->handle;
 		break;
-
+	case _DRM_CONSISTENT: {
+		int order, page_order;
+		order = drm_order(map->size);
+		page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+		map->size = PAGE_SIZE << page_order;
+		map->handle = (void *)drm_alloc_pages(page_order, DRM_MEM_DMA);
+		DRM_DEBUG("%lu %d %d %p\n",
+			  map->size, order, page_order, map->handle);
+		if (!map->handle) {
+			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+			return -ENOMEM;
+		}
+		map->offset = virt_to_bus(map->handle);
+		break;
+	}
 	default:
 		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 		return -EINVAL;
@@ -348,6 +362,11 @@
 		case _DRM_AGP:
 		case _DRM_SCATTER_GATHER:
 			break;
+		case _DRM_CONSISTENT:
+			drm_free_pages((unsigned long)map->handle,
+				       drm_order(map->size)-PAGE_SHIFT,
+				       DRM_MEM_DMA);
+			break;
 		}
 		drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 	}
--- linux-core/drm_drv.c.~1.98.~	2004-10-13 23:01:50.000000000 +0200
+++ linux-core/drm_drv.c	2004-10-16 01:56:45.000000000 +0200
@@ -240,6 +240,12 @@
 						dev->sg = NULL;
 					}
 					break;
+				case _DRM_CONSISTENT:
+					drm_free_pages(
+						(unsigned long)map->handle,
+						drm_order(map->size)-PAGE_SHIFT,
+						DRM_MEM_DMA);
+					break;
 				}
 				drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 			}
@@ -418,6 +424,7 @@
 				case _DRM_SHM:
 				case _DRM_AGP:
 				case _DRM_SCATTER_GATHER:
+				case _DRM_CONSISTENT:
 					DRM_DEBUG("Extra maplist item\n");
 					break;
 				}
--- linux-core/drm_proc.c.~1.21.~	2004-10-13 23:01:50.000000000 +0200
+++ linux-core/drm_proc.c	2004-10-16 02:09:34.000000000 +0200
@@ -211,9 +211,9 @@
 	struct list_head *list;
 
 	/* Hardcoded from _DRM_FRAME_BUFFER,
-	   _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
-	   _DRM_SCATTER_GATHER. */
-	const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
+	   _DRM_REGISTERS, _DRM_SHM, _DRM_AGP,
+	   _DRM_SCATTER_GATHER, and _DRM_CONSISTENT. */
+	const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
 	const char *type;
 	int i;
 
@@ -234,7 +234,7 @@
 		map = r_list->map;
 		if (!map)
 			continue;
-		if (map->type < 0 || map->type > 4)
+		if (map->type < 0 || map->type > 5)
 			type = "??";
 		else
 			type = types[map->type];
--- linux-core/drm_vm.c.~1.44.~	2004-10-13 23:01:50.000000000 +0200
+++ linux-core/drm_vm.c	2004-10-16 02:10:48.000000000 +0200
@@ -232,6 +232,11 @@
 			case _DRM_AGP:
 			case _DRM_SCATTER_GATHER:
 				break;
+			case _DRM_CONSISTENT:
+				drm_free_pages((unsigned long)map->handle,
+					       drm_order(map->size)-PAGE_SHIFT,
+					       DRM_MEM_DMA);
+				break;
 			}
 			drm_free(map, sizeof(*map), DRM_MEM_MAPS);
 		}
@@ -658,6 +663,9 @@
 		vma->vm_ops = &drm_vm_ops;
 		break;
 	case _DRM_SHM:
+	case _DRM_CONSISTENT:
+		/* Consistent memory is really like shared memory. It's only
+		 * allocated 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
--- shared-core/drm.h.~1.59.~	2004-09-30 23:38:48.000000000 +0200
+++ shared-core/drm.h	2004-10-16 01:46:00.000000000 +0200
@@ -246,7 +246,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;
 
 /**

Reply via email to