xf86-video-intel: 10 commits - man/intel.man src/i830_accel.c src/i830_common.h src/i830_dri.c src/i830_dri.h src/i830_driver.c src/i830_exa.c src/i830.h src/i830_memory.c

Eric Anholt anholt at kemper.freedesktop.org
Fri Sep 21 17:20:36 PDT 2007


 man/intel.man     |    5 
 src/i830.h        |   19 +-
 src/i830_accel.c  |    6 
 src/i830_common.h |    9 +
 src/i830_dri.c    |  196 +++++++++++-------------
 src/i830_dri.h    |    2 
 src/i830_driver.c |  284 +++++++++++++++-------------------
 src/i830_exa.c    |    9 -
 src/i830_memory.c |  441 ++++++++++++++++++++++++++++++++++++++++++++++--------
 9 files changed, 636 insertions(+), 335 deletions(-)

New commits:
diff-tree 130f79613bfe6a8cfa7f431c8cce06cbb93cc91a (from parents)
Merge: b73235f40497cfb10792ba191d4f6eac3a5df009 126031655c3c1db9881ad17d712461533eb59632
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Sep 21 17:14:44 2007 -0700

    Merge branch 'buffer-objects'
    
    This branch changes i830_memory.c's allocator to use TTM when available to
    allocate memory, which also allows TTM to control almost the entire aperture.
    As a result, our front/back/depth buffers are created as real buffer objects,
    which may be used by the DRI driver instead of the fake buffer type in TTM.
    The updated DRM with bo_set_pin ioctl is required, to allow us to pin and
    unpin our buffers as needed.

diff-tree 126031655c3c1db9881ad17d712461533eb59632 (from parents)
Merge: c3438356d6b7b63ad9d0086efb084be8e048980e bda3c69a7a044869ea63514b97f8aa9260d6b5a7
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Sep 20 08:57:58 2007 -0700

    Merge remote branch 'origin/master' into buffer-objects
    
    Conflicts:
    
    	src/i830.h
    	src/i830_driver.c

diff --cc src/i830.h
index a39514b,71c46b4..b1f1f68
@@@ -294,14 -291,9 +295,15 @@@
  
     /* These are set in PreInit and never changed. */
     long FbMapSize;
+    long GTTMapSize;
  
 -   i830_memory *memory_list;	/**< Linked list of video memory allocations */
 +   /**
 +    * Linked list of video memory allocations.  The head and tail are
 +    * dummy entries that bound the allocation area.
 +    */
 +   i830_memory *memory_list;
 +   /** Linked list of buffer object memory allocations */
 +   i830_memory *bo_list;
     long stolen_size;		/**< bytes of pre-bound stolen memory */
     int gtt_acquired;		/**< whether we currently own the AGP */
  
@@@ -649,7 -646,14 +655,15 @@@
  
  Bool i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
  			 unsigned long size);
 +void i830_allocator_fini(ScrnInfoPtr pScrn);
+ i830_memory * i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
+ 				   unsigned long size, unsigned long alignment,
+ 				   int flags);
+ i830_memory *i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
+ 					unsigned long size,
+ 					unsigned long pitch,
+ 					unsigned long alignment, int flags,
+ 					enum tile_format tile_format);
  void i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity,
  			       const char *prefix);
  void i830_reset_allocations(ScrnInfoPtr pScrn);
diff --cc src/i830_driver.c
index 1fbf9d5,1db511b..dc27170
@@@ -2155,9 -2247,16 +2266,13 @@@
     VisualPtr visual;
     I830Ptr pI8301 = NULL;
     unsigned long sys_mem;
-    int i;
+    int i, c;
     Bool allocation_done = FALSE;
     MessageType from;
+ #ifdef XF86DRI
+    Bool driDisabled;
+    xf86CrtcConfigPtr config;
 -#ifdef XF86DRI_MM
 -   unsigned long savedMMSize;
 -#endif
+ #endif
  
     pScrn = xf86Screens[pScreen->myNum];
     pI830 = I830PTR(pScrn);
@@@ -2573,13 -2695,41 +2688,38 @@@
 -	 i830_free_3d_memory(pScrn);
        }
     }
  
 -   driDisabled = !pI830->directRenderingEnabled;
 -
     if (pI830->directRenderingEnabled)
 -      pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
 +      pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
  
 -   if (!pI830->directRenderingEnabled) {
 +   /* If we failed for any reason, free DRI memory. */
 +   if (!pI830->directRenderingEnabled)
        i830_free_3d_memory(pScrn);
 -   }
  
+    config = XF86_CRTC_CONFIG_PTR(pScrn);
+ 
+    /*
+     * If an LVDS display is present, swap the plane/pipe mappings so we can
+     * use FBC on the builtin display.
+     * Note: 965+ chips can compress either plane, so we leave the mapping
+     *       alone in that case.
+     * Also make sure the DRM can handle the swap.
+     */
+    if (I830LVDSPresent(pScrn) && !IS_I965GM(pI830) &&
+        (!pI830->directRenderingEnabled ||
+ 	(pI830->directRenderingEnabled && pI830->drmMinor >= 10))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "adjusting plane->pipe mappings "
+ 		  "to allow for framebuffer compression\n");
+        for (c = 0; c < config->num_crtc; c++) {
+ 	   xf86CrtcPtr	      crtc = config->crtc[c];
+ 	   I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
+ 
+ 	   if (intel_crtc->pipe == 0)
+ 	       intel_crtc->plane = 1;
+ 	   else if (intel_crtc->pipe == 1)
+ 	       intel_crtc->plane = 0;
+       }
+    }
+ 
  #else
     pI830->directRenderingEnabled = FALSE;
  #endif
diff --cc src/i830_exa.c
index 353ab8f,273c626..c97e514
@@@ -456,16 -472,21 +472,26 @@@
  
      pI830->bufferOffset = 0;
      pI830->EXADriverPtr->exa_major = 2;
+     /* If compiled against EXA 2.2, require 2.2 so we can use the
+      * PixmapIsOffscreen hook.
+      */
+ #if EXA_VERSION_MINOR >= 2
+     pI830->EXADriverPtr->exa_minor = 2;
+ #else
      pI830->EXADriverPtr->exa_minor = 1;
+     xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 	       "EXA compatibility mode.  Output rotation rendering "
+ 	       "performance may suffer\n");
+ #endif
      pI830->EXADriverPtr->memoryBase = pI830->FbBase;
 -    pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
 -    pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
 +    if (pI830->exa_offscreen) {
 +	pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
 +	pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
  	pI830->exa_offscreen->size;
 +    } else {
 +	pI830->EXADriverPtr->offScreenBase = pI830->FbMapSize;
 +	pI830->EXADriverPtr->memorySize = pI830->FbMapSize;
 +    }
      pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
  
      DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, "
diff --cc src/i830_memory.c
index 902ca2d,3da489d..42e88a6
@@@ -725,22 -513,9 +725,22 @@@
  /* Allocates video memory at the given size and alignment.
   *
   * The memory will be bound automatically when the driver is in control of the
 - * VT.
 + * VT.  When the kernel memory manager is available and compatible with flags
 + * (that is, flags doesn't say that the allocation must include a physical
 + * address), that will be used for the allocation.
 + *
 + * flags:
 + * - NEED_PHYSICAL_ADDR: Allocates the memory physically contiguous, and return
 + *   the bus address for that memory.
 + * - ALIGN_BOTH_ENDS: after choosing the alignment, align the end offset to
 + *   @alignment as well.
 + * - NEED_NON-STOLEN: don't allow any part of the memory allocation to lie
 + *   within stolen memory
 + * - NEED_LIFETIME_FIXED: don't allow the buffer object to move throughout
 + *   the entire Screen lifetime.  This means not using buffer objects, which
 + *   get their offsets chosen at each EnterVT time.
   */
- static i830_memory *
+ i830_memory *
  i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
  		     unsigned long size, unsigned long alignment, int flags)
  {
@@@ -1424,16 -1146,10 +1423,15 @@@
  	     * memory if a low videoRam is specified.
  	     */
  	    size = 3 * pitch * pScrn->virtualY;
- 	    size += 1920 * 1088 * 2 * 2;
  	    size = ROUND_TO_PAGE(size);
  
 -	    pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen",
 -							size, 1, 0);
 +	    /* EXA has no way to tell it that the offscreen memory manager has
 +	     * moved its base and all the contents with it, so we have to have
 +	     * it locked in place for the whole driver instance.
 +	     */
 +	    pI830->exa_offscreen =
 +		i830_allocate_memory(pScrn, "exa offscreen",
 +				     size, 1, NEED_LIFETIME_FIXED);
  	    if (pI830->exa_offscreen == NULL) {
  		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  			   "Failed to allocate EXA offscreen memory.");
diff-tree c3438356d6b7b63ad9d0086efb084be8e048980e (from 0c9e4aeea84e20a18e3b76d8cf8e802af004df57)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Aug 16 11:34:02 2007 -0700

    Add tiling information to BO layout description.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 2328858..902ca2d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -926,15 +926,22 @@ i830_describe_allocations(ScrnInfoPtr pS
 		       "%s0x%08lx:            start of memory manager\n",
 		       prefix, pI830->memory_manager->offset);
 	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
+	    char *tile_suffix = "";
+
+	    if (mem->tiling == TILE_XMAJOR)
+		tile_suffix = " X tiled";
+	    else if (mem->tiling == TILE_YMAJOR)
+		tile_suffix = " Y tiled";
+
 	    if (mem->bound) {
 		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			       "%s0x%08lx-0x%08lx: %s (%ld kB)\n", prefix,
+			       "%s0x%08lx-0x%08lx: %s (%ld kB)%s\n", prefix,
 			       mem->offset, mem->end - 1, mem->name,
-			       mem->size / 1024);
+			       mem->size / 1024, tile_suffix);
 	    } else {
 		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			       "%sunpinned          : %s (%ld kB)\n", prefix,
-			       mem->name, mem->size / 1024);
+			       "%sunpinned          : %s (%ld kB)%s\n", prefix,
+			       mem->name, mem->size / 1024, tile_suffix);
 	    }
 	}
 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
diff-tree 0c9e4aeea84e20a18e3b76d8cf8e802af004df57 (from parents)
Merge: 79d9a309b19e22561e000a47b732c67479c2e6d4 2231cdcd8f1ee81b3e59cc5e3a325c22ee0f40e4
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Aug 16 11:30:16 2007 -0700

    Merge branch 'master' into buffer-objects
    
    Conflicts:
    
    	src/i830_dri.c
    	src/i830_memory.c

diff --cc src/i830.h
index ccbae4f,ca48b52..a39514b
@@@ -338,12 -334,9 +344,8 @@@
  
     int TexGranularity;
     int drmMinor;
 -   int mmModeFlags;
 -   int mmSize;
 +   Bool allocate_classic_textures;
  
-    unsigned int back_tiled;
-    unsigned int third_tiled;
-    unsigned int depth_tiled;
- 
     Bool want_vblank_interrupts;
  #ifdef DAMAGE
     DamagePtr pDamage;
diff --cc src/i830_dri.c
index f97edd7,e2b42b4..c25a084
@@@ -591,30 -591,29 +591,31 @@@
     pDRIInfo->MoveBuffers = I830DRIMoveBuffers;
     pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
  
 -   {
 -#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
 -      int major, minor, patch;
 -
 -      DRIQueryVersion(&major, &minor, &patch);
 -
 -#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3
 -      if (minor >= 3)
 -#endif
  #if DRIINFO_MAJOR_VERSION > 5 || \
      (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3)
-       pDRIInfo->texOffsetStart = I830TexOffsetStart;
+       if (pI830->useEXA)
+ 	 pDRIInfo->texOffsetStart = I830TexOffsetStart;
  #endif
  
 -#if DRI_SUPPORTS_CLIP_NOTIFY && DRIINFO_MAJOR_VERSION == 5
 -      if (minor >= 1)
 -#endif
  #if DRI_SUPPORTS_CLIP_NOTIFY
 -	 pDRIInfo->ClipNotify = I830DRIClipNotify;
 +      pDRIInfo->ClipNotify = I830DRIClipNotify;
 +#endif
 +
 +#if DRI_DRIVER_FRAMEBUFFER_MAP
 +   /* DRI version is high enough that we can get the DRI code to not
 +    * try to manage the framebuffer.
 +    */
 +   pDRIInfo->frameBufferPhysicalAddress = 0;
 +   pDRIInfo->frameBufferSize = 0;
 +   pDRIInfo->frameBufferStride = 0;
 +   pDRIInfo->dontMapFrameBuffer = TRUE;
 +#else
 +   /* Supply a dummy mapping info required by DRI setup.
 +    */
 +   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
 +   pDRIInfo->frameBufferSize = GTT_PAGE_SIZE;
 +   pDRIInfo->frameBufferStride = 1;
  #endif
 -#endif /* DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1 */
 -   }
  
     pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
     pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
diff --cc src/i830_exa.c
index e801d50,fdf94d7..353ab8f
@@@ -405,21 -458,17 +458,22 @@@
      pI830->EXADriverPtr->exa_major = 2;
      pI830->EXADriverPtr->exa_minor = 1;
      pI830->EXADriverPtr->memoryBase = pI830->FbBase;
 -    pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
 -    pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
 +    if (pI830->exa_offscreen) {
 +	pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
 +	pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
  	pI830->exa_offscreen->size;
 +    } else {
 +	pI830->EXADriverPtr->offScreenBase = pI830->FbMapSize;
 +	pI830->EXADriverPtr->memorySize = pI830->FbMapSize;
 +    }
      pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
  
-     DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n",
- 		pI830->EXADriverPtr->memoryBase,
- 		pI830->EXADriverPtr->memoryBase + pI830->EXADriverPtr->memorySize,
- 		pI830->EXADriverPtr->offScreenBase,
- 		pI830->EXADriverPtr->memorySize);
+     DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, "
+ 	    "memorySize 0x%x\n",
+ 	    pI830->EXADriverPtr->memoryBase,
+ 	    pI830->EXADriverPtr->memoryBase + pI830->EXADriverPtr->memorySize,
+ 	    pI830->EXADriverPtr->offScreenBase,
+ 	    pI830->EXADriverPtr->memorySize);
  
  
      /* Limits are described in the BLT engine chapter under Graphics Data Size
diff --cc src/i830_memory.c
index 96a4d67,15d3a48..2328858
@@@ -108,18 -108,6 +108,13 @@@
  
  #define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
  
 +/* Our hardware status area is just a single page */
 +#define HWSTATUS_PAGE_SIZE GTT_PAGE_SIZE
 +
- enum tile_format {
-     TILING_NONE,
-     TILING_XMAJOR,
-     TILING_YMAJOR
- };
- 
 +static i830_memory *
 +i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name,
 +		       long size, unsigned long alignment, int flags);
++
  static void i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset,
  			   unsigned int pitch, unsigned int size,
  			   enum tile_format tile_format);
@@@ -749,22 -519,19 +744,24 @@@
  i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
  		     unsigned long size, unsigned long alignment, int flags)
  {
 +    I830Ptr pI830 = I830PTR(pScrn);
      i830_memory *mem;
  
 -    mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
 -    if (mem == NULL)
 -	return NULL;
 +    if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR)) {
 +	return i830_allocate_memory_bo(pScrn, name, size, alignment, flags);
 +    } else {
 +	mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
 +	if (mem == NULL)
 +	    return NULL;
  
 -    if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
 -	i830_free_memory(pScrn, mem);
 -	return NULL;
 +	if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
 +	    i830_free_memory(pScrn, mem);
 +	    return NULL;
 +	}
      }
  
+     mem->tiling = TILE_NONE;
+ 
      return mem;
  }
  
@@@ -789,15 -556,9 +786,15 @@@
      i830_memory *mem;
      int fence_divide, i;
  
-     if (tile_format == TILING_NONE)
+     if (tile_format == TILE_NONE)
  	return i830_allocate_memory(pScrn, name, size, alignment, flags);
  
 +    /* XXX: for now, refuse to tile with movable buffer object allocations,
 +     * until we can move the set_fence (and failure recovery) into bind time.
 +     */
 +    if (pI830->memory_manager != NULL && !(flags & NEED_LIFETIME_FIXED))
 +	return NULL;
 +
      /* Only allocate page-sized increments. */
      size = ALIGN(size, GTT_PAGE_SIZE);
  
@@@ -898,9 -657,11 +887,11 @@@
      }
  
      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 -		   "%sMemory allocation layout:\n", prefix);
 +		   "%sFixed memory allocation layout:\n", prefix);
  
      for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) {
+ 	char phys_suffix[32] = "";
+ 	char *tile_suffix = "";
  
  	if (mem->offset >= pI830->stolen_size &&
  	    mem->prev->offset < pI830->stolen_size)
@@@ -927,50 -687,6 +917,31 @@@
      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
  		   "%s0x%08lx:            end of aperture\n",
  		   prefix, pI830->FbMapSize);
 +
 +#ifdef XF86DRI_MM
 +    if (pI830->memory_manager) {
 +	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 +		       "%sBO memory allocation layout:\n", prefix);
 +	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 +		       "%s0x%08lx:            start of memory manager\n",
 +		       prefix, pI830->memory_manager->offset);
 +	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
 +	    if (mem->bound) {
 +		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 +			       "%s0x%08lx-0x%08lx: %s (%ld kB)\n", prefix,
 +			       mem->offset, mem->end - 1, mem->name,
 +			       mem->size / 1024);
 +	    } else {
 +		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 +			       "%sunpinned          : %s (%ld kB)\n", prefix,
 +			       mem->name, mem->size / 1024);
 +	    }
 +	}
 +	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 +		       "%s0x%08lx:            end of memory manager\n",
 +		       prefix, pI830->memory_manager->end);
 +    }
 +#endif /* XF86DRI_MM */
- 
-     if (pI830->front_buffer != NULL) {
- 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->front_buffer,
- 			     pI830->front_tiled);
-     }
- #ifdef XF86DRI
-     if (pI830->back_buffer != NULL) {
- 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->back_buffer,
- 			     pI830->back_tiled);
-     }
-     if (pI830->third_buffer != NULL) {
- 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->third_buffer,
- 			     pI830->third_tiled);
-     }
-     if (pI830->depth_buffer != NULL) {
- 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->depth_buffer,
- 			     pI830->depth_tiled);
-     }
- #endif
  }
  
  static Bool
@@@ -1096,15 -804,9 +1067,16 @@@
      int align;
      long size, fb_height;
      char *name;
 +    int flags;
      i830_memory *front_buffer = NULL;
+     Bool tiling;
  
 +    /* The front buffer is currently marked as NEED_LIFETIME_FIXED because
 +     * DRIDoMappings is the only caller of the rm/add map functions,
 +     * and it's only called at startup.  This should be easily fixable.
 +     */
 +    flags = NEED_LIFETIME_FIXED | ALLOW_SHARING;
 +
      /* Clear everything first. */
      memset(FbMemBox, 0, sizeof(*FbMemBox));
  
@@@ -1180,10 -891,8 +1161,8 @@@
  	else
  	    align = KB(512);
  	front_buffer = i830_allocate_memory_tiled(pScrn, name, size,
--						  pitch, align,
- 						  flags,
- 						  TILING_XMAJOR);
- 	pI830->front_tiled = FENCE_XMAJOR;
 -						  0, TILE_XMAJOR);
++						  pitch, align, flags,
++						  TILE_XMAJOR);
      }
  
      /* If not, attempt it linear */
@@@ -1539,24 -1235,15 +1514,22 @@@
      {
  	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
  	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
 -					     GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
 +					     GTT_PAGE_SIZE,
 +					     ALIGN_BOTH_ENDS |
 +					     NEED_LIFETIME_FIXED |
 +					     ALLOW_SHARING,
- 					     TILING_XMAJOR);
- 	*tiled = FENCE_XMAJOR;
+ 					     TILE_XMAJOR);
      }
  
 -    /* Otherwise, just allocate it linear */
 +    /* Otherwise, just allocate it linear.  The offset must stay constant
 +     * currently because we don't ever update the DRI maps after screen init.
 +     */
      if (*buffer == NULL) {
  	size = ROUND_TO_PAGE(pitch * height);
  	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
 -				       ALIGN_BOTH_ENDS);
 +				       ALIGN_BOTH_ENDS |
 +				       NEED_LIFETIME_FIXED |
 +				       ALLOW_SHARING);
- 	*tiled = FENCE_LINEAR;
      }
  
      if (*buffer == NULL) {
@@@ -1596,24 -1283,16 +1569,21 @@@
  
  	pI830->depth_buffer =
  	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
 -				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
 +				       GTT_PAGE_SIZE,
 +				       ALIGN_BOTH_ENDS |
 +				       NEED_LIFETIME_FIXED |
 +				       ALLOW_SHARING,
  				       tile_format);
- 	pI830->depth_tiled = (tile_format == TILING_YMAJOR) ? FENCE_YMAJOR :
- 	    FENCE_XMAJOR;
      }
  
 -    /* Otherwise, allocate it linear. */
 +    /* Otherwise, allocate it linear. The offset must stay constant
 +     * currently because we don't ever update the DRI maps after screen init.
 +     */
      if (pI830->depth_buffer == NULL) {
  	size = ROUND_TO_PAGE(pitch * height);
  	pI830->depth_buffer =
  	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
 -				 0);
 +				 ALLOW_SHARING | NEED_LIFETIME_FIXED);
- 	pI830->depth_tiled = FENCE_LINEAR;
      }
  
      if (pI830->depth_buffer == NULL) {
diff-tree 79d9a309b19e22561e000a47b732c67479c2e6d4 (from 857b4a7bcb69ca43b866b4283fe075abbafb1d22)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Aug 2 15:50:42 2007 -0700

    Mark DRI buffers as shareable, and pass their buffer handles through the SAREA.

diff --git a/src/i830.h b/src/i830.h
index 730d6bc..ccbae4f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -756,6 +756,7 @@ extern const int I830CopyROP[16];
 #define ALIGN_BOTH_ENDS			0x00000002
 #define NEED_NON_STOLEN			0x00000004
 #define NEED_LIFETIME_FIXED		0x00000008
+#define ALLOW_SHARING			0x00000010
 
 /* Chipset registers for VIDEO BIOS memory RW access */
 #define _855_DRAM_RW_CONTROL 0x58
diff --git a/src/i830_common.h b/src/i830_common.h
index 9c8616c..1ca2642 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -138,6 +138,15 @@ typedef struct {
 	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;
 } drmI830Sarea;
 
 /* Flags for perf_boxes
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 0ffafca..f97edd7 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1664,6 +1664,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
       sarea->third_offset = 0;
       sarea->third_size = 0;
    }
+
    sarea->depth_offset = pI830->depth_buffer->offset;
    sarea->depth_size = pI830->depth_buffer->size;
    if (pI830->textures != NULL) {
@@ -1678,6 +1679,21 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->virtualX = pScrn->virtualX;
    sarea->virtualY = pScrn->virtualY;
 
+   sarea->front_bo_handle = -1;
+   sarea->back_bo_handle = -1;
+   sarea->third_bo_handle = -1;
+   sarea->depth_bo_handle = -1;
+#ifdef XF86DRI_MM
+   if (pI830->front_buffer->bo.size)
+       sarea->front_bo_handle = pI830->front_buffer->bo.handle;
+   if (pI830->back_buffer->bo.size)
+       sarea->back_bo_handle = pI830->back_buffer->bo.handle;
+   if (pI830->third_buffer != NULL && pI830->third_buffer->bo.size)
+       sarea->third_bo_handle = pI830->third_buffer->bo.handle;
+   if (pI830->depth_buffer->bo.size)
+       sarea->depth_bo_handle = pI830->depth_buffer->bo.handle;
+#endif
+
    /* The rotation is now handled entirely by the X Server, so just leave the
     * DRI unaware.
     */
diff --git a/src/i830_dri.h b/src/i830_dri.h
index a2cf78e..b6a8366 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -9,7 +9,7 @@
 #define I830_MAX_DRAWABLES 256
 
 #define I830_MAJOR_VERSION 1
-#define I830_MINOR_VERSION 8
+#define I830_MINOR_VERSION 9
 #define I830_PATCHLEVEL 0
 
 #define I830_REG_SIZE 0x80000
diff --git a/src/i830_memory.c b/src/i830_memory.c
index e4d5d3d..96a4d67 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -692,6 +692,8 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
 
     mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE |
 	DRM_BO_FLAG_MEM_TT;
+    if (flags & ALLOW_SHARING)
+	mask |= DRM_BO_FLAG_SHAREABLE;
 
     ret = drmBOCreate(pI830->drmSubFD, 0, size, align / GTT_PAGE_SIZE, NULL,
 		      drm_bo_type_dc, mask, 0, &mem->bo);
@@ -1101,7 +1103,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
      * DRIDoMappings is the only caller of the rm/add map functions,
      * and it's only called at startup.  This should be easily fixable.
      */
-    flags = NEED_LIFETIME_FIXED;
+    flags = NEED_LIFETIME_FIXED | ALLOW_SHARING;
 
     /* Clear everything first. */
     memset(FbMemBox, 0, sizeof(*FbMemBox));
@@ -1537,9 +1539,11 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
     {
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
-					     GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
-					     TILING_XMAJOR |
-					     NEED_LIFETIME_FIXED);
+					     GTT_PAGE_SIZE,
+					     ALIGN_BOTH_ENDS |
+					     NEED_LIFETIME_FIXED |
+					     ALLOW_SHARING,
+					     TILING_XMAJOR);
 	*tiled = FENCE_XMAJOR;
     }
 
@@ -1549,7 +1553,9 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
     if (*buffer == NULL) {
 	size = ROUND_TO_PAGE(pitch * height);
 	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
-				       ALIGN_BOTH_ENDS | NEED_LIFETIME_FIXED);
+				       ALIGN_BOTH_ENDS |
+				       NEED_LIFETIME_FIXED |
+				       ALLOW_SHARING);
 	*tiled = FENCE_LINEAR;
     }
 
@@ -1591,7 +1597,9 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	pI830->depth_buffer =
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
 				       GTT_PAGE_SIZE,
-				       ALIGN_BOTH_ENDS | NEED_LIFETIME_FIXED,
+				       ALIGN_BOTH_ENDS |
+				       NEED_LIFETIME_FIXED |
+				       ALLOW_SHARING,
 				       tile_format);
 	pI830->depth_tiled = (tile_format == TILING_YMAJOR) ? FENCE_YMAJOR :
 	    FENCE_XMAJOR;
@@ -1604,7 +1612,7 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 	size = ROUND_TO_PAGE(pitch * height);
 	pI830->depth_buffer =
 	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
-				 NEED_LIFETIME_FIXED);
+				 ALLOW_SHARING | NEED_LIFETIME_FIXED);
 	pI830->depth_tiled = FENCE_LINEAR;
     }
 
@@ -1646,6 +1654,7 @@ i830_allocate_texture_memory(ScrnInfoPtr
 	 */
 	pI830->textures = i830_allocate_memory(pScrn, "classic textures", size,
 					       GTT_PAGE_SIZE,
+					       ALLOW_SHARING |
 					       NEED_LIFETIME_FIXED);
 	if (pI830->textures == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff-tree 857b4a7bcb69ca43b866b4283fe075abbafb1d22 (from d7b5b595ad29ae0ac3adbd3a176be3fe7ffa6474)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jul 27 18:03:12 2007 -0700

    Pin some buffer objects at creation time, which can't be moved yet.
    
    A number of other interfaces of ours don't allow buffer offsets to be updated
    after screeninit.  This attempts to catalog why for each one, so that they
    can be fixed one by one.
    
    This happens to restore the EXA offscreen allocator for now, as a fixed-offset
    object.

diff --git a/src/i830.h b/src/i830.h
index 14de7f0..730d6bc 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -160,6 +160,7 @@ struct _i830_memory {
 
 #ifdef XF86DRI_MM
     drmBO bo;
+    Bool lifetime_fixed_offset;
 #endif
 };
 
@@ -754,6 +755,7 @@ extern const int I830CopyROP[16];
 #define NEED_PHYSICAL_ADDR		0x00000001
 #define ALIGN_BOTH_ENDS			0x00000002
 #define NEED_NON_STOLEN			0x00000004
+#define NEED_LIFETIME_FIXED		0x00000008
 
 /* Chipset registers for VIDEO BIOS memory RW access */
 #define _855_DRAM_RW_CONTROL 0x58
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 676b4cb..c86840a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -712,6 +712,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    }
 }
 
+#if 0
+/* This code ended up unused, but will be at least a reference when we let the
+ * front buffer move.
+ */
 static void
 i830UpdateFrontOffset(ScrnInfoPtr pScrn)
 {
@@ -755,6 +759,7 @@ i830CreateScreenResources(ScreenPtr pScr
 
    return TRUE;
 }
+#endif
 
 int
 i830_output_clones (ScrnInfoPtr pScrn, int type_mask)
@@ -2724,8 +2729,10 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pScreen->SaveScreen = xf86SaveScreen;
    pI830->CloseScreen = pScreen->CloseScreen;
    pScreen->CloseScreen = I830CloseScreen;
+#if 0
    pI830->CreateScreenResources = pScreen->CreateScreenResources;
    pScreen->CreateScreenResources = i830CreateScreenResources;
+#endif
 
    if (!xf86CrtcScreenInit (pScreen))
        return FALSE;
@@ -2872,7 +2879,9 @@ I830EnterVT(int scrnIndex, int flags)
 
    i830_describe_allocations(pScrn, 1, "");
 
+#if 0
    i830UpdateFrontOffset(pScrn);
+#endif
 
    if (i830_check_error_state(pScrn)) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 80e3536..e4d5d3d 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -108,6 +108,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 #define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
 
+/* Our hardware status area is just a single page */
+#define HWSTATUS_PAGE_SIZE GTT_PAGE_SIZE
+
 enum tile_format {
     TILING_NONE,
     TILING_XMAJOR,
@@ -155,23 +158,29 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (mem == NULL || mem->bound || !pI830->gtt_acquired)
+    if (mem == NULL || mem->bound)
 	return TRUE;
 
 #ifdef XF86DRI_MM
     if (mem->bo.size != 0) {
+	I830Ptr pI830 = I830PTR(pScrn);
 	int ret;
 
 	ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 1);
-	mem->offset = mem->bo.offset;
-	mem->end = mem->offset + mem->size;
-	if (ret)
-	    return FALSE;
-	else
+	if (ret == 0) {
+	    mem->bound = TRUE;
+	    mem->offset = mem->bo.offset;
+	    mem->end = mem->bo.offset + mem->size;
 	    return TRUE;
+	} else {
+	    return FALSE;
+	}
     }
 #endif
 
+    if (!pI830->gtt_acquired)
+	return TRUE;
+
     if (mem->key == -1 ||
 	xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
 	mem->bound = TRUE;
@@ -195,10 +204,15 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i8
 	int ret;
 
 	ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 0);
-	if (ret)
-	    return FALSE;
-	else
+	if (ret == 0) {
+	    mem->bound = FALSE;
+	    /* Give buffer obviously wrong offset/end until it's re-pinned. */
+	    mem->offset = -1;
+	    mem->end = -1;
 	    return TRUE;
+	} else {
+	    return FALSE;
+	}
     }
 #endif
 
@@ -213,15 +227,16 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i8
 void
 i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
-#ifdef XF86DRI_MM
-    I830Ptr pI830 = I830PTR(pScrn);
-#endif
-
     if (mem == NULL)
 	return;
 
+    /* Free any AGP memory. */
+    i830_unbind_memory(pScrn, mem);
+
 #ifdef XF86DRI_MM
     if (mem->bo.size != 0) {
+	I830Ptr pI830 = I830PTR(pScrn);
+
 	drmBOUnReference(pI830->drmSubFD, &mem->bo);
 	if (pI830->bo_list == mem)
 	    pI830->bo_list = mem->next;
@@ -240,9 +255,6 @@ i830_free_memory(ScrnInfoPtr pScrn, i830
     if (mem->next != NULL)
 	mem->next->prev = mem->prev;
 
-    /* Free any AGP memory. */
-    i830_unbind_memory(pScrn, mem);
-
     if (mem->key != -1) {
 	xf86DeallocateGARTMemory(pScrn->scrnIndex, mem->key);
 	mem->key = -1;
@@ -326,6 +338,9 @@ i830_allocator_init(ScrnInfoPtr pScrn, u
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *start, *end;
     int ret;
+#ifdef XF86DRI_MM
+    int dri_major, dri_minor, dri_patch;
+#endif
 
     start = xcalloc(1, sizeof(*start));
     if (start == NULL)
@@ -363,16 +378,23 @@ i830_allocator_init(ScrnInfoPtr pScrn, u
     pI830->memory_list = start;
 
 #ifdef XF86DRI_MM
+    DRIQueryVersion(&dri_major, &dri_minor, &dri_patch);
+
     /* Now that we have our manager set up, initialize the kernel MM if
-     * possible, covering almost all of the aperture.
+     * possible, covering almost all of the aperture.  We need libdri interface
+     * 5.4 or newer so we can rely on the lock being held after DRIScreenInit,
+     * rather than after DRIFinishScreenInit.
      */
-    if (pI830->directRenderingEnabled && pI830->drmMinor >= 7) {
+    if (pI830->directRenderingEnabled && pI830->drmMinor >= 7 &&
+	(dri_major > 5 || (dri_major == 5 && dri_minor >= 4)))
+    {
 	int mmsize;
 
 	/* Take over all of the graphics aperture minus enough to for
 	 * physical-address allocations of cursor/overlay registers.
 	 */
 	mmsize = size;
+	/* Overlay is always set up as fixed, currently. */
 	if (!OVERLAY_NOPHYSICAL(pI830) && !IS_I965G(pI830)) {
 	    mmsize -= ROUND_TO(OVERLAY_SIZE, GTT_PAGE_SIZE);
 	    if (pI830->CursorNeedsPhysical) {
@@ -678,10 +700,19 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
 	xfree(mem);
 	return NULL;
     }
-
-    mem->offset = mem->bo.offset;
-    mem->end = mem->bo.start + size;
+    /* Give buffer obviously wrong offset/end until it's pinned. */
+    mem->offset = -1;
+    mem->end = -1;
     mem->size = size;
+    if (flags & NEED_LIFETIME_FIXED) {
+	if (!i830_bind_memory(pScrn, mem)) {
+	    drmBOUnReference(pI830->drmSubFD, &mem->bo);
+	    xfree(mem->name);
+	    xfree(mem);
+	    return NULL;
+	}
+	mem->lifetime_fixed_offset = TRUE;
+    }
 
     /* Insert new allocation into the list */
     mem->prev = NULL;
@@ -700,6 +731,17 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
  * VT.  When the kernel memory manager is available and compatible with flags
  * (that is, flags doesn't say that the allocation must include a physical
  * address), that will be used for the allocation.
+ *
+ * flags:
+ * - NEED_PHYSICAL_ADDR: Allocates the memory physically contiguous, and return
+ *   the bus address for that memory.
+ * - ALIGN_BOTH_ENDS: after choosing the alignment, align the end offset to
+ *   @alignment as well.
+ * - NEED_NON-STOLEN: don't allow any part of the memory allocation to lie
+ *   within stolen memory
+ * - NEED_LIFETIME_FIXED: don't allow the buffer object to move throughout
+ *   the entire Screen lifetime.  This means not using buffer objects, which
+ *   get their offsets chosen at each EnterVT time.
  */
 static i830_memory *
 i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
@@ -748,10 +790,10 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
     if (tile_format == TILING_NONE)
 	return i830_allocate_memory(pScrn, name, size, alignment, flags);
 
-    /* XXX: for now, refuse to tile with buffer object allocations,
-     * until we can move the set_fence (and failure recovery) into EnterVT.
+    /* XXX: for now, refuse to tile with movable buffer object allocations,
+     * until we can move the set_fence (and failure recovery) into bind time.
      */
-    if (pI830->memory_manager != NULL)
+    if (pI830->memory_manager != NULL && !(flags & NEED_LIFETIME_FIXED))
 	return NULL;
 
     /* Only allocate page-sized increments. */
@@ -892,10 +934,16 @@ i830_describe_allocations(ScrnInfoPtr pS
 		       "%s0x%08lx:            start of memory manager\n",
 		       prefix, pI830->memory_manager->offset);
 	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
-	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			   "%s0x%08lx-0x%08lx: %s (%ld kB)\n", prefix,
-			   mem->offset, mem->end - 1, mem->name,
-			   mem->size / 1024);
+	    if (mem->bound) {
+		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			       "%s0x%08lx-0x%08lx: %s (%ld kB)\n", prefix,
+			       mem->offset, mem->end - 1, mem->name,
+			       mem->size / 1024);
+	    } else {
+		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			       "%sunpinned          : %s (%ld kB)\n", prefix,
+			       mem->name, mem->size / 1024);
+	    }
 	}
 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 		       "%s0x%08lx:            end of memory manager\n",
@@ -931,9 +979,13 @@ i830_allocate_ringbuffer(ScrnInfoPtr pSc
     if (pI830->noAccel || pI830->LpRing->mem != NULL)
 	return TRUE;
 
+    /* We don't have any mechanism in the DRM yet to alert it that we've moved
+     * the ringbuffer since init time, so allocate it fixed for its lifetime.
+     */
     pI830->LpRing->mem = i830_allocate_memory(pScrn, "ring buffer",
 					      PRIMARY_RINGBUFFER_SIZE,
-					      GTT_PAGE_SIZE, 0);
+					      GTT_PAGE_SIZE,
+					      NEED_LIFETIME_FIXED);
     if (pI830->LpRing->mem == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Failed to allocate Ring Buffer space\n");
@@ -953,7 +1005,7 @@ static Bool
 i830_allocate_overlay(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    int flags = NEED_PHYSICAL_ADDR;
+    int flags = NEED_PHYSICAL_ADDR | NEED_LIFETIME_FIXED;
 
     /* Only allocate if overlay is going to be enabled. */
     if (!pI830->XvEnabled)
@@ -963,6 +1015,10 @@ i830_allocate_overlay(ScrnInfoPtr pScrn)
 	flags = 0;
 
     if (!IS_I965G(pI830)) {
+	/* XXX: The lifetime fixed offset for overlay register is bogus, and we
+	 * should just tell i830_video.c about the new location at EnterVT
+	 * time.
+	 */
 	pI830->overlay_regs = i830_allocate_memory(pScrn, "overlay registers",
 						   OVERLAY_SIZE, GTT_PAGE_SIZE,
 						   flags);
@@ -1030,7 +1086,7 @@ IsTileable(ScrnInfoPtr pScrn, int pitch)
  */
 static i830_memory *
 i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
-			  Bool secondary, int flags)
+			  Bool secondary)
 {
     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
     unsigned long minspace, avail;
@@ -1038,8 +1094,15 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
     int align;
     long size, fb_height;
     char *name;
+    int flags;
     i830_memory *front_buffer = NULL;
 
+    /* The front buffer is currently marked as NEED_LIFETIME_FIXED because
+     * DRIDoMappings is the only caller of the rm/add map functions,
+     * and it's only called at startup.  This should be easily fixable.
+     */
+    flags = NEED_LIFETIME_FIXED;
+
     /* Clear everything first. */
     memset(FbMemBox, 0, sizeof(*FbMemBox));
 
@@ -1107,7 +1170,7 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 
     name = secondary ? "secondary front buffer" : "front buffer";
 
-    /* Attempt to allocate it tiled first if we have page flipping on. */
+    /* Attempt to allocate it tiled first if possible. */
     if (pI830->tiling && IsTileable(pScrn, pitch)) {
 	/* XXX: probably not the case on 965 */
 	if (IS_I9XX(pI830))
@@ -1116,7 +1179,8 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 	    align = KB(512);
 	front_buffer = i830_allocate_memory_tiled(pScrn, name, size,
 						  pitch, align,
-						  0, TILING_XMAJOR);
+						  flags,
+						  TILING_XMAJOR);
 	pI830->front_tiled = FENCE_XMAJOR;
     }
 
@@ -1149,7 +1213,7 @@ i830_allocate_cursor_buffers(ScrnInfoPtr
 
     /* Try to allocate one big blob for our cursor memory.  This works
      * around a limitation in the FreeBSD AGP driver that allows only one
-     * physical allocation larger than a page, and could allos us
+     * physical allocation larger than a page, and could allow us
      * to pack the cursors smaller.
      */
     size = xf86_config->num_crtc * (HWCURSOR_SIZE + HWCURSOR_SIZE_ARGB);
@@ -1356,23 +1420,18 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 
 	pI830->front_buffer_2 =
 	    i830_allocate_framebuffer(pI830Ent->pScrn_2, pI8302,
-				      &pI830->FbMemBox2, TRUE, 0);
+				      &pI830->FbMemBox2, TRUE);
 	if (pI830->front_buffer_2 == NULL)
 	    return FALSE;
     }
     pI830->front_buffer =
-	i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, FALSE, 0);
+	i830_allocate_framebuffer(pScrn, pI830, &pI830->FbMemBox, FALSE);
     if (pI830->front_buffer == NULL)
 	return FALSE;
 
 #ifdef I830_USE_EXA
     if (pI830->useEXA) {
-	/* With the kernel memory manager, the exa offscreen allocation would
-	 * change locations at EnterVT, which EXA is unprepared for.  The
-	 * performance of EXA offscreen memory management was low enough
-	 * that just not using it is reasonable.
-	 */
-	if (pI830->exa_offscreen == NULL && pI830->memory_manager == NULL) {
+	if (pI830->exa_offscreen == NULL) {
 	    /* Default EXA to having 3 screens worth of offscreen memory space
 	     * (for pixmaps), plus a double-buffered, 1920x1088 video's worth.
 	     *
@@ -1384,8 +1443,13 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 	    size += 1920 * 1088 * 2 * 2;
 	    size = ROUND_TO_PAGE(size);
 
-	    pI830->exa_offscreen = i830_allocate_memory(pScrn, "exa offscreen",
-							size, 1, 0);
+	    /* EXA has no way to tell it that the offscreen memory manager has
+	     * moved its base and all the contents with it, so we have to have
+	     * it locked in place for the whole driver instance.
+	     */
+	    pI830->exa_offscreen =
+		i830_allocate_memory(pScrn, "exa offscreen",
+				     size, 1, NEED_LIFETIME_FIXED);
 	    if (pI830->exa_offscreen == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			   "Failed to allocate EXA offscreen memory.");
@@ -1396,14 +1460,18 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 #endif /* I830_USE_EXA */
 
     if (!pI830->noAccel && !pI830->useEXA) {
+	/* The lifetime fixed offset of xaa scratch is probably not required,
+	 * but we do some setup using it at XAAInit() time.  And XAA may not
+	 * end up being supported with TTM anyway.
+	 */
 	pI830->xaa_scratch =
 	    i830_allocate_memory(pScrn, "xaa scratch", MAX_SCRATCH_BUFFER_SIZE,
-				 GTT_PAGE_SIZE, 0);
+				 GTT_PAGE_SIZE, NEED_LIFETIME_FIXED);
 	if (pI830->xaa_scratch == NULL) {
 	    pI830->xaa_scratch =
 		i830_allocate_memory(pScrn, "xaa scratch",
 				     MIN_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
-				     0);
+				     NEED_LIFETIME_FIXED);
 	    if (pI830->xaa_scratch == NULL) {
 		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			   "Failed to allocate scratch buffer space\n");
@@ -1418,12 +1486,12 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 	    pI830->xaa_scratch_2 =
 		i830_allocate_memory(pScrn, "xaa scratch 2",
 				     MAX_SCRATCH_BUFFER_SIZE, GTT_PAGE_SIZE,
-				     0);
+				     NEED_LIFETIME_FIXED);
 	    if (pI830->xaa_scratch_2 == NULL) {
 		pI830->xaa_scratch_2 =
 		    i830_allocate_memory(pScrn, "xaa scratch 2",
 					 MIN_SCRATCH_BUFFER_SIZE,
-					 GTT_PAGE_SIZE, 0);
+					 GTT_PAGE_SIZE, NEED_LIFETIME_FIXED);
 		if (pI830->xaa_scratch_2 == NULL) {
 		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			       "Failed to allocate secondary scratch "
@@ -1470,15 +1538,18 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
 	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
 					     GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
-					     TILING_XMAJOR);
+					     TILING_XMAJOR |
+					     NEED_LIFETIME_FIXED);
 	*tiled = FENCE_XMAJOR;
     }
 
-    /* Otherwise, just allocate it linear */
+    /* Otherwise, just allocate it linear.  The offset must stay constant
+     * currently because we don't ever update the DRI maps after screen init.
+     */
     if (*buffer == NULL) {
 	size = ROUND_TO_PAGE(pitch * height);
 	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
-				       ALIGN_BOTH_ENDS);
+				       ALIGN_BOTH_ENDS | NEED_LIFETIME_FIXED);
 	*tiled = FENCE_LINEAR;
     }
 
@@ -1519,18 +1590,21 @@ i830_allocate_depthbuffer(ScrnInfoPtr pS
 
 	pI830->depth_buffer =
 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
-				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
+				       GTT_PAGE_SIZE,
+				       ALIGN_BOTH_ENDS | NEED_LIFETIME_FIXED,
 				       tile_format);
 	pI830->depth_tiled = (tile_format == TILING_YMAJOR) ? FENCE_YMAJOR :
 	    FENCE_XMAJOR;
     }
 
-    /* Otherwise, allocate it linear. */
+    /* Otherwise, allocate it linear. The offset must stay constant
+     * currently because we don't ever update the DRI maps after screen init.
+     */
     if (pI830->depth_buffer == NULL) {
 	size = ROUND_TO_PAGE(pitch * height);
 	pI830->depth_buffer =
 	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
-				 0);
+				 NEED_LIFETIME_FIXED);
 	pI830->depth_tiled = FENCE_LINEAR;
     }
 
@@ -1567,8 +1641,12 @@ i830_allocate_texture_memory(ScrnInfoPtr
 		       size / 1024);
 	    return FALSE;
 	}
+	/* The offset must stay constant currently because we don't ever update
+	 * the DRI maps after screen init.
+	 */
 	pI830->textures = i830_allocate_memory(pScrn, "classic textures", size,
-					       GTT_PAGE_SIZE, 0);
+					       GTT_PAGE_SIZE,
+					       NEED_LIFETIME_FIXED);
 	if (pI830->textures == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "Failed to allocate texture space.\n");
@@ -1582,11 +1660,14 @@ i830_allocate_texture_memory(ScrnInfoPtr
 static Bool
 i830_allocate_hwstatus(ScrnInfoPtr pScrn)
 {
-#define HWSTATUS_PAGE_SIZE (4*1024)
     I830Ptr pI830 = I830PTR(pScrn);
 
+    /* The current DRM will leak the HWS mapping if we update the address
+     * after init (at best), so allocate it fixed for its lifetime
+     * (i.e. not through buffer objects).
+     */
     pI830->hw_status = i830_allocate_memory(pScrn, "G33 hw status",
-	    HWSTATUS_PAGE_SIZE, GTT_PAGE_SIZE, 0);
+	    HWSTATUS_PAGE_SIZE, GTT_PAGE_SIZE, NEED_LIFETIME_FIXED);
     if (pI830->hw_status == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		"Failed to allocate hw status page for G33.\n");
@@ -1866,10 +1947,12 @@ i830_bind_all_memory(ScrnInfoPtr pScrn)
 		FatalError("Couldn't bind memory for %s\n", mem->name);
 	    }
 	}
+#ifdef XF86DRI_MM
 	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
-	    if (!i830_bind_memory(pScrn, mem))
+	    if (!mem->lifetime_fixed_offset && !i830_bind_memory(pScrn, mem))
 		FatalError("Couldn't bind memory for BO %s\n", mem->name);
 	}
+#endif
     }
 
     return TRUE;
@@ -1892,8 +1975,15 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn
 	{
 	    i830_unbind_memory(pScrn, mem);
 	}
-	for (mem = pI830->bo_list; mem != NULL; mem = mem->next)
-	    i830_unbind_memory(pScrn, mem);
+#ifdef XF86DRI_MM
+	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
+	    /* Don't unpin objects which require that their offsets never
+	     * change.
+	     */
+	    if (!mem->lifetime_fixed_offset)
+		i830_unbind_memory(pScrn, mem);
+	}
+#endif
 
 	pI830->gtt_acquired = FALSE;
 
diff-tree d7b5b595ad29ae0ac3adbd3a176be3fe7ffa6474 (from 2b1ec0f51479c1d7e5e62803c68feca29375519d)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jul 27 12:48:08 2007 -0700

    Delay the first screen pixmap update to CreateScreenResources.
    
    The return value of GetScreenPixmap before CreateScreenResources is not, in
    fact, a pixmap.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 929a541..676b4cb 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -712,6 +712,50 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    }
 }
 
+static void
+i830UpdateFrontOffset(ScrnInfoPtr pScrn)
+{
+   ScreenPtr pScreen = pScrn->pScreen;
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   /* If we are still in ScreenInit, there is no screen pixmap to be updated
+    * yet.  We'll fix it up at CreateScreenResources.
+    */
+   if (pI830->starting)
+      return;
+
+   /* Update buffer locations, which may have changed as a result of
+    * i830_bind_all_memory().
+    */
+   pScrn->fbOffset = pI830->front_buffer->offset;
+   if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
+				    -1, -1, -1, -1, -1,
+				    (pointer)(pI830->FbBase +
+					      pScrn->fbOffset)))
+       FatalError("Couldn't adjust screen pixmap\n");
+}
+
+/**
+ * Adjust the screen pixmap for the current location of the front buffer.
+ * This is done at EnterVT when buffers are bound as long as the resources
+ * have already been created, but the first EnterVT happens before
+ * CreateScreenResources.
+ */
+static Bool
+i830CreateScreenResources(ScreenPtr pScreen)
+{
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   pScreen->CreateScreenResources = pI830->CreateScreenResources;
+   if (!(*pScreen->CreateScreenResources)(pScreen))
+      return FALSE;
+
+   i830UpdateFrontOffset(pScrn);
+
+   return TRUE;
+}
+
 int
 i830_output_clones (ScrnInfoPtr pScrn, int type_mask)
 {
@@ -2680,6 +2724,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pScreen->SaveScreen = xf86SaveScreen;
    pI830->CloseScreen = pScreen->CloseScreen;
    pScreen->CloseScreen = I830CloseScreen;
+   pI830->CreateScreenResources = pScreen->CreateScreenResources;
+   pScreen->CreateScreenResources = i830CreateScreenResources;
 
    if (!xf86CrtcScreenInit (pScreen))
        return FALSE;
@@ -2803,7 +2849,6 @@ static Bool
 I830EnterVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-   ScreenPtr pScreen = pScrn->pScreen;
    I830Ptr  pI830 = I830PTR(pScrn);
    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
    int o;
@@ -2827,15 +2872,7 @@ I830EnterVT(int scrnIndex, int flags)
 
    i830_describe_allocations(pScrn, 1, "");
 
-   /* Update buffer locations, which may have changed as a result of
-    * i830_bind_all_memory().
-    */
-   pScrn->fbOffset = pI830->front_buffer->offset;
-   if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
-				    -1, -1, -1, -1, -1,
-				    (pointer)(pI830->FbBase +
-					      pScrn->fbOffset)))
-       FatalError("Couldn't adjust screen pixmap\n");
+   i830UpdateFrontOffset(pScrn);
 
    if (i830_check_error_state(pScrn)) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
diff-tree 2b1ec0f51479c1d7e5e62803c68feca29375519d (from 1a585d03972394cb97dec2462937b0104bdf4de2)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jul 27 10:00:35 2007 -0700

    Use the dontMapFramebuffer option available with DRIINFO 5.4.
    
    If not available, AIGLX init will fail.  While here, simplify DRIINFO tests
    since we refuse to init with a version queried less than the version we
    compiled against, anyway.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 0d511d2..0ffafca 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -124,11 +124,20 @@ static void I830DRIMoveBuffers(WindowPtr
 
 static void I830DRITransitionTo2d(ScreenPtr pScreen);
 static void I830DRITransitionTo3d(ScreenPtr pScreen);
-static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
-static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
 #if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 ||		\
 			(DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1))
 #define DRI_SUPPORTS_CLIP_NOTIFY 1
+#else
+#define DRI_SUPPORTS_CLIP_NOTIFY 0
+static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
+static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
+#endif
+
+#if (DRIINFO_MAJOR_VERSION > 5 || \
+     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 4))
+#define DRI_DRIVER_FRAMEBUFFER_MAP 1
+#else
+#define DRI_DRIVER_FRAMEBUFFER_MAP 0
 #endif
 
 #ifdef DRI_SUPPORTS_CLIP_NOTIFY
@@ -491,7 +500,8 @@ I830CheckDRIAvailable(ScrnInfoPtr pScrn)
       int major, minor, patch;
 
       DRIQueryVersion(&major, &minor, &patch);
-      if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
+      if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ||
+	  major < 5) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "[dri] %s failed because of a version mismatch.\n"
 		    "[dri] libDRI version is %d.%d.%d but version %d.%d.x is needed.\n"
@@ -546,12 +556,6 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION;
    pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION;
    pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL;
-   /* Supply a dummy mapping info required by DRI setup.  See bug #5714 for
-    * progress on removing this requirement.
-    */
-   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
-   pDRIInfo->frameBufferSize = GTT_PAGE_SIZE;
-   pDRIInfo->frameBufferStride = 1;
    pDRIInfo->ddxDrawableTableEntry = I830_MAX_DRAWABLES;
 
    if (SAREA_MAX_DRAWABLES < I830_MAX_DRAWABLES)
@@ -587,40 +591,38 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->MoveBuffers = I830DRIMoveBuffers;
    pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
 
-   {
-#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
-      int major, minor, patch;
-
-      DRIQueryVersion(&major, &minor, &patch);
-
-#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3
-      if (minor >= 3)
-#endif
 #if DRIINFO_MAJOR_VERSION > 5 || \
     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3)
-	 pDRIInfo->texOffsetStart = I830TexOffsetStart;
+      pDRIInfo->texOffsetStart = I830TexOffsetStart;
 #endif
 
-#if DRI_SUPPORTS_CLIP_NOTIFY && DRIINFO_MAJOR_VERSION == 5
-      if (minor >= 1)
-#endif
 #if DRI_SUPPORTS_CLIP_NOTIFY
-	 pDRIInfo->ClipNotify = I830DRIClipNotify;
+      pDRIInfo->ClipNotify = I830DRIClipNotify;
+#endif
+
+#if DRI_DRIVER_FRAMEBUFFER_MAP
+   /* DRI version is high enough that we can get the DRI code to not
+    * try to manage the framebuffer.
+    */
+   pDRIInfo->frameBufferPhysicalAddress = 0;
+   pDRIInfo->frameBufferSize = 0;
+   pDRIInfo->frameBufferStride = 0;
+   pDRIInfo->dontMapFrameBuffer = TRUE;
+#else
+   /* Supply a dummy mapping info required by DRI setup.
+    */
+   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
+   pDRIInfo->frameBufferSize = GTT_PAGE_SIZE;
+   pDRIInfo->frameBufferStride = 1;
 #endif
-#endif /* DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1 */
-   }
 
    pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
    pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
 
-#if DRIINFO_MAJOR_VERSION > 5 || \
-    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
-   if (!pDRIInfo->ClipNotify)
+#if !DRI_SUPPORTS_CLIP_NOTIFY
+   pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
+   pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
 #endif
-   {
-      pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
-      pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
-   }
 
    /* do driver-independent DRI screen initialization here */
    if (!DRIScreenInit(pScreen, pDRIInfo, &pI830->drmSubFD)) {
@@ -633,30 +635,14 @@ I830DRIScreenInit(ScreenPtr pScreen)
       return FALSE;
    }
 
-   /* Now, nuke dri.c's frontbuffer map setup. */
-#if 0
-   if (xf86LoaderCheckSymbol("DRIGetScreenPrivate")) {
-      DRIScreenPrivPtr pDRIPriv =
-	  (DRIScreenPrivPtr) DRIGetScreenPrivate(pScreen);
-
-      if (pDRIPriv && pDRIPriv->drmFD && pDRIPriv->hFrameBuffer) {
-         xf86DrvMsg(pScreen->myNum, X_ERROR,
-                    "[intel] removing original screen mapping\n");
-         drmRmMap(pDRIPriv->drmFD, pDRIPriv->hFrameBuffer);
-         pDRIPriv->hFrameBuffer = 0;
-         xf86DrvMsg(pScreen->myNum, X_ERROR,
-                    "[intel] done removing original screen mapping\n");
-      }
-   }
-#endif
-   {
+   /* Now, nuke dri.c's dummy frontbuffer map setup if we did that. */
+   if (pDRIInfo->frameBufferSize != 0) {
        int tmp;
        unsigned int fb_handle;
        void *ptmp;
 
        /* With the compat method, it will continue to report
-	* the wrong map out of GetDeviceInfo, but we don't have any consumers
-	* of the frontbuffer handle from there.
+	* the wrong map out of GetDeviceInfo, which will break AIGLX.
 	*/
        DRIGetDeviceInfo(pScreen, &fb_handle, &tmp, &tmp, &tmp, &tmp, &ptmp);
        drmRmMap(pI830->drmSubFD, fb_handle);
@@ -763,11 +749,12 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
 {
    ScreenPtr pScreen = pScrn->pScreen;
    I830Ptr pI830 = I830PTR(pScrn);
+   drm_handle_t front_handle;
 
-#if 1 /* Remove this soon - see bug 5714 */
-   pI830->pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth *
-					     pScrn->virtualY * pI830->cpp);
-#endif
+   pI830->pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
+   pI830->pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp;
+   pI830->pDRIInfo->frameBufferSize =
+      ROUND_TO_PAGE(pI830->pDRIInfo->frameBufferStride * pScrn->virtualY);
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	      "[drm] Mapping front buffer\n");
@@ -776,12 +763,17 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
 		 sarea->front_size,
 		 DRM_AGP,
 		 0,
-		 (drmAddress) &sarea->front_handle) < 0) {
+		 &front_handle) < 0) {
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		  "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
        DRICloseScreen(pScreen);
        return FALSE;
    }
+   sarea->front_handle = front_handle;
+#if DRI_DRIVER_FRAMEBUFFER_MAP
+   pI830->pDRIInfo->hFrameBuffer = front_handle;
+#endif
+
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n",
 	      (int)sarea->front_handle);
 
@@ -1530,6 +1522,7 @@ I830DRISetPfMask(ScreenPtr pScreen, int 
       pSAREAPriv->pf_active = 0;
 }
 
+#if !DRI_SUPPORTS_CLIP_NOTIFY
 static void
 I830DRITransitionSingleToMulti3d(ScreenPtr pScreen)
 {
@@ -1550,6 +1543,7 @@ I830DRITransitionMultiToSingle3d(ScreenP
     */
    I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
 }
+#endif /* !DRI_SUPPORTS_CLIP_NOTIFY */
 
 static void
 I830DRITransitionTo3d(ScreenPtr pScreen)
diff-tree 1a585d03972394cb97dec2462937b0104bdf4de2 (from 18c707a8c13ac5fffdd30d55e6f5926a68b367df)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jul 26 10:46:35 2007 -0700

    Use new drmBOSetPin interface instead of NO_EVICT/NO_MOVE buffers.
    
    To do this, we have to deal with buffer offsets being set at EnterVT time
    instead of screen init time. We've wanted to move this direction for a long
    time, but there are repercussions.  The EXA offscreen memory manager has to
    be disabled, because it can't be moved.  That will be replaced by BO-backed
    pixmaps soon.  Also unresolved is whether our moving
    front/back/depth/texture buffers will break the classic-mode DRI driver.
    
    This code doesn't actually work yet.

diff --git a/src/i830.h b/src/i830.h
index 6e1f88a..14de7f0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -286,7 +286,13 @@ typedef struct _I830Rec {
    /* These are set in PreInit and never changed. */
    long FbMapSize;
 
-   i830_memory *memory_list;	/**< Linked list of video memory allocations */
+   /**
+    * Linked list of video memory allocations.  The head and tail are
+    * dummy entries that bound the allocation area.
+    */
+   i830_memory *memory_list;
+   /** Linked list of buffer object memory allocations */
+   i830_memory *bo_list;
    long stolen_size;		/**< bytes of pre-bound stolen memory */
    int gtt_acquired;		/**< whether we currently own the AGP */
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 20c6c68..929a541 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2403,8 +2403,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
    I830UnmapMMIO(pScrn);
 
-   i830_describe_allocations(pScrn, 1, "");
-
    if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Cannot support DRI with frame buffer width > 2048.\n");
@@ -2632,6 +2630,14 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    } else
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing SW Cursor!\n");
 
+#ifdef XF86DRI
+   /* Must be called before EnterVT, so we can acquire the DRI lock when
+    * binding our memory.
+    */
+   if (pI830->directRenderingEnabled)
+      pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
+#endif
+
    if (!I830EnterVT(scrnIndex, 0))
       return FALSE;
 
@@ -2654,11 +2660,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       I830InitVideo(pScreen);
 #endif
 
-#ifdef XF86DRI
-   if (pI830->directRenderingEnabled)
-      pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
-#endif
-
    /* Setup 3D engine, needed for rotation too */
    IntelEmitInvarientState(pScrn);
 
@@ -2802,6 +2803,7 @@ static Bool
 I830EnterVT(int scrnIndex, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+   ScreenPtr pScreen = pScrn->pScreen;
    I830Ptr  pI830 = I830PTR(pScrn);
    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
    int o;
@@ -2823,6 +2825,18 @@ I830EnterVT(int scrnIndex, int flags)
       if (!i830_bind_all_memory(pScrn))
          return FALSE;
 
+   i830_describe_allocations(pScrn, 1, "");
+
+   /* Update buffer locations, which may have changed as a result of
+    * i830_bind_all_memory().
+    */
+   pScrn->fbOffset = pI830->front_buffer->offset;
+   if (!pScreen->ModifyPixmapHeader(pScreen->GetScreenPixmap(pScreen),
+				    -1, -1, -1, -1, -1,
+				    (pointer)(pI830->FbBase +
+					      pScrn->fbOffset)))
+       FatalError("Couldn't adjust screen pixmap\n");
+
    if (i830_check_error_state(pScrn)) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		 "Existing errors found in hardware state.\n");
diff --git a/src/i830_exa.c b/src/i830_exa.c
index fed4067..e801d50 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -405,9 +405,14 @@ I830EXAInit(ScreenPtr pScreen)
     pI830->EXADriverPtr->exa_major = 2;
     pI830->EXADriverPtr->exa_minor = 1;
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
-    pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
-    pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
+    if (pI830->exa_offscreen) {
+	pI830->EXADriverPtr->offScreenBase = pI830->exa_offscreen->offset;
+	pI830->EXADriverPtr->memorySize = pI830->exa_offscreen->offset +
 	pI830->exa_offscreen->size;
+    } else {
+	pI830->EXADriverPtr->offScreenBase = pI830->FbMapSize;
+	pI830->EXADriverPtr->memorySize = pI830->FbMapSize;
+    }
     pI830->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
 
     DPRINTF(PFX, "EXA Mem: memoryBase 0x%x, end 0x%x, offscreen base 0x%x, memorySize 0x%x\n",
diff --git a/src/i830_memory.c b/src/i830_memory.c
index d4e9bff..80e3536 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -155,10 +155,25 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (mem == NULL || mem->key == -1 || mem->bound || !pI830->gtt_acquired)
+    if (mem == NULL || mem->bound || !pI830->gtt_acquired)
 	return TRUE;
 
-    if (xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
+#ifdef XF86DRI_MM
+    if (mem->bo.size != 0) {
+	int ret;
+
+	ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 1);
+	mem->offset = mem->bo.offset;
+	mem->end = mem->offset + mem->size;
+	if (ret)
+	    return FALSE;
+	else
+	    return TRUE;
+    }
+#endif
+
+    if (mem->key == -1 ||
+	xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
 	mem->bound = TRUE;
 	return TRUE;
     } else {
@@ -171,10 +186,23 @@ i830_bind_memory(ScrnInfoPtr pScrn, i830
 static Bool
 i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
-    if (mem == NULL || mem->key == -1 || !mem->bound)
+    if (mem == NULL || !mem->bound)
 	return TRUE;
 
-    if (xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) {
+#ifdef XF86DRI_MM
+    if (mem->bo.size != 0) {
+	I830Ptr pI830 = I830PTR(pScrn);
+	int ret;
+
+	ret = drmBOSetPin(pI830->drmSubFD, &mem->bo, 0);
+	if (ret)
+	    return FALSE;
+	else
+	    return TRUE;
+    }
+#endif
+
+    if (mem->key == -1 || xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) {
 	mem->bound = FALSE;
 	return TRUE;
     } else {
@@ -195,6 +223,12 @@ i830_free_memory(ScrnInfoPtr pScrn, i830
 #ifdef XF86DRI_MM
     if (mem->bo.size != 0) {
 	drmBOUnReference(pI830->drmSubFD, &mem->bo);
+	if (pI830->bo_list == mem)
+	    pI830->bo_list = mem->next;
+	if (mem->next)
+	    mem->next->prev = NULL;
+	if (mem->prev)
+	    mem->prev->next = NULL;
 	xfree(mem->name);
 	xfree(mem);
 	return;
@@ -615,7 +649,7 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
 {
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *mem;
-    unsigned long hint, mask;
+    unsigned long mask;
     int ret;
 
     assert((flags & NEED_PHYSICAL_ADDR) == 0);
@@ -635,14 +669,10 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
     }
 
     mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE |
-	DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE;
-    hint = DRM_BO_HINT_DONT_FENCE | DRM_BO_HINT_DONT_BLOCK |
-	DRM_BO_HINT_ALLOW_UNFENCED_MAP;
+	DRM_BO_FLAG_MEM_TT;
 
-    I830DRILock(pScrn);
     ret = drmBOCreate(pI830->drmSubFD, 0, size, align / GTT_PAGE_SIZE, NULL,
-		      drm_bo_type_dc, mask, hint, &mem->bo);
-    I830DRIUnlock(pScrn);
+		      drm_bo_type_dc, mask, 0, &mem->bo);
     if (ret) {
 	xfree(mem->name);
 	xfree(mem);
@@ -653,6 +683,13 @@ i830_allocate_memory_bo(ScrnInfoPtr pScr
     mem->end = mem->bo.start + size;
     mem->size = size;
 
+    /* Insert new allocation into the list */
+    mem->prev = NULL;
+    mem->next = pI830->bo_list;
+    if (pI830->bo_list != NULL)
+	pI830->bo_list->prev = mem;
+    pI830->bo_list = mem;
+
     return mem;
 }
 #endif /* XF86DRI_MM */
@@ -711,6 +748,12 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
     if (tile_format == TILING_NONE)
 	return i830_allocate_memory(pScrn, name, size, alignment, flags);
 
+    /* XXX: for now, refuse to tile with buffer object allocations,
+     * until we can move the set_fence (and failure recovery) into EnterVT.
+     */
+    if (pI830->memory_manager != NULL)
+	return NULL;
+
     /* Only allocate page-sized increments. */
     size = ALIGN(size, GTT_PAGE_SIZE);
 
@@ -811,7 +854,7 @@ i830_describe_allocations(ScrnInfoPtr pS
     }
 
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		   "%sMemory allocation layout:\n", prefix);
+		   "%sFixed memory allocation layout:\n", prefix);
 
     for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) {
 
@@ -831,7 +874,7 @@ i830_describe_allocations(ScrnInfoPtr pS
 	} else {
 	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
 			   "%s0x%08lx-0x%08lx: %s "
-			   "(%ld kB, 0x%16llx physical)\n",
+			   "(%ld kB, 0x%016llx physical)\n",
 			   prefix,
 			   mem->offset, mem->end - 1, mem->name,
 			   mem->size / 1024, mem->bus_addr);
@@ -841,6 +884,25 @@ i830_describe_allocations(ScrnInfoPtr pS
 		   "%s0x%08lx:            end of aperture\n",
 		   prefix, pI830->FbMapSize);
 
+#ifdef XF86DRI_MM
+    if (pI830->memory_manager) {
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%sBO memory allocation layout:\n", prefix);
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%s0x%08lx:            start of memory manager\n",
+		       prefix, pI830->memory_manager->offset);
+	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
+	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+			   "%s0x%08lx-0x%08lx: %s (%ld kB)\n", prefix,
+			   mem->offset, mem->end - 1, mem->name,
+			   mem->size / 1024);
+	}
+	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		       "%s0x%08lx:            end of memory manager\n",
+		       prefix, pI830->memory_manager->end);
+    }
+#endif /* XF86DRI_MM */
+
     if (pI830->front_buffer != NULL) {
 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->front_buffer,
 			     pI830->front_tiled);
@@ -1305,7 +1367,12 @@ i830_allocate_2d_memory(ScrnInfoPtr pScr
 
 #ifdef I830_USE_EXA
     if (pI830->useEXA) {
-	if (pI830->exa_offscreen == NULL) {
+	/* With the kernel memory manager, the exa offscreen allocation would
+	 * change locations at EnterVT, which EXA is unprepared for.  The
+	 * performance of EXA offscreen memory management was low enough
+	 * that just not using it is reasonable.
+	 */
+	if (pI830->exa_offscreen == NULL && pI830->memory_manager == NULL) {
 	    /* Default EXA to having 3 screens worth of offscreen memory space
 	     * (for pixmaps), plus a double-buffered, 1920x1088 video's worth.
 	     *
@@ -1799,6 +1866,10 @@ i830_bind_all_memory(ScrnInfoPtr pScrn)
 		FatalError("Couldn't bind memory for %s\n", mem->name);
 	    }
 	}
+	for (mem = pI830->bo_list; mem != NULL; mem = mem->next) {
+	    if (!i830_bind_memory(pScrn, mem))
+		FatalError("Couldn't bind memory for BO %s\n", mem->name);
+	}
     }
 
     return TRUE;
@@ -1821,6 +1892,8 @@ i830_unbind_all_memory(ScrnInfoPtr pScrn
 	{
 	    i830_unbind_memory(pScrn, mem);
 	}
+	for (mem = pI830->bo_list; mem != NULL; mem = mem->next)
+	    i830_unbind_memory(pScrn, mem);
 
 	pI830->gtt_acquired = FALSE;
 
diff-tree 18c707a8c13ac5fffdd30d55e6f5926a68b367df (from 45962eed51120ff77326c29d72cf8b6cd8a934b5)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jul 25 10:11:16 2007 -0700

    When TTM is available, use it instead of manual AGP allocations when possible.
    
    This is a step towards being able to expose buffer objects through the screen
    private to DRI clients, instead of having them have to use the fake buffer
    object type.
    
    This fails in two ways.  First, the kernel memory manager is not currently
    suitable for doing the physical allocations we need, so we still use AGP for
    those.  Additionally, the DRI lock can't be initialized early enough for us, so
    these buffer object allocations fail.  This will be fixed by improving the
    DRM interface.

diff --git a/man/intel.man b/man/intel.man
index 33dc319..c682d55 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -128,9 +128,8 @@ Default: XVideo is enabled for configura
 Enable support for the legacy i915_dri.so 3D driver.
 This will, among other things, make the 2D driver tell libGL to
 load the 3D driver i915_dri.so instead of the newer i915tex_dri.so.
-This option is only used for chipsets in the range i830-i945. 
-Default for i830-i945 series: Enabled for i915 drm versions < 1.7.0. Otherwise
-disabled. 
+This option is only used for chipsets in the range i830-i945.
+Default for i830-i945 series: Enabled.
 Default for i810: The option is not used.
 Default for i965: The option is always true.
 .TP
diff --git a/src/i830.h b/src/i830.h
index aa2b240..6e1f88a 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -158,6 +158,9 @@ struct _i830_memory {
     i830_memory *prev;
     /** @} */
 
+#ifdef XF86DRI_MM
+    drmBO bo;
+#endif
 };
 
 typedef struct {
@@ -328,8 +331,7 @@ typedef struct _I830Rec {
 
    int TexGranularity;
    int drmMinor;
-   int mmModeFlags;
-   int mmSize;
+   Bool allocate_classic_textures;
 
    unsigned int back_tiled;
    unsigned int third_tiled;
@@ -635,6 +637,7 @@ extern void I830SubsequentSolidFillRect(
 
 Bool i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
 			 unsigned long size);
+void i830_allocator_fini(ScrnInfoPtr pScrn);
 void i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity,
 			       const char *prefix);
 void i830_reset_allocations(ScrnInfoPtr pScrn);
@@ -744,6 +747,7 @@ extern const int I830CopyROP[16];
 /* Flags for memory allocation function */
 #define NEED_PHYSICAL_ADDR		0x00000001
 #define ALIGN_BOTH_ENDS			0x00000002
+#define NEED_NON_STOLEN			0x00000004
 
 /* Chipset registers for VIDEO BIOS memory RW access */
 #define _855_DRAM_RW_CONTROL 0x58
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 5cbad44..4d9ea79 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -254,6 +254,12 @@ I830RefreshRing(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
 
+   /* If we're reaching RefreshRing as a result of grabbing the DRI lock
+    * before we've set up the ringbuffer, don't bother.
+    */
+   if (pI830->LpRing->mem == NULL)
+       return;
+
    pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
    pI830->LpRing->tail = INREG(LP_RING + RING_TAIL);
    pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index ca1190c..0d511d2 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -546,16 +546,12 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION;
    pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION;
    pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL;
-#if 1 /* Remove this soon - see bug 5714 */
-   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr +
-					  pI830->front_buffer->offset;
-   pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth *
-					     pScrn->virtualY * pI830->cpp);
-#else
-   /* For rotation we map a 0 length framebuffer as we remap ourselves later */
-   pDRIInfo->frameBufferSize = 0;
-#endif
-   pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp;
+   /* Supply a dummy mapping info required by DRI setup.  See bug #5714 for
+    * progress on removing this requirement.
+    */
+   pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr;
+   pDRIInfo->frameBufferSize = GTT_PAGE_SIZE;
+   pDRIInfo->frameBufferStride = 1;
    pDRIInfo->ddxDrawableTableEntry = I830_MAX_DRAWABLES;
 
    if (SAREA_MAX_DRAWABLES < I830_MAX_DRAWABLES)
@@ -637,11 +633,11 @@ I830DRIScreenInit(ScreenPtr pScreen)
       return FALSE;
    }
 
-#if 0 /* disabled now, see frameBufferSize above being set to 0 */
-   /* for this driver, get rid of the front buffer mapping now */
+   /* Now, nuke dri.c's frontbuffer map setup. */
+#if 0
    if (xf86LoaderCheckSymbol("DRIGetScreenPrivate")) {
-      DRIScreenPrivPtr pDRIPriv 
-         = (DRIScreenPrivPtr) DRIGetScreenPrivate(pScreen);
+      DRIScreenPrivPtr pDRIPriv =
+	  (DRIScreenPrivPtr) DRIGetScreenPrivate(pScreen);
 
       if (pDRIPriv && pDRIPriv->drmFD && pDRIPriv->hFrameBuffer) {
          xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -652,11 +648,25 @@ I830DRIScreenInit(ScreenPtr pScreen)
                     "[intel] done removing original screen mapping\n");
       }
    }
-   else {
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
-                 "[intel] DRIGetScreenPrivate not found!!!!\n");
-   }      
 #endif
+   {
+       int tmp;
+       unsigned int fb_handle;
+       void *ptmp;
+
+       /* With the compat method, it will continue to report
+	* the wrong map out of GetDeviceInfo, but we don't have any consumers
+	* of the frontbuffer handle from there.
+	*/
+       DRIGetDeviceInfo(pScreen, &fb_handle, &tmp, &tmp, &tmp, &tmp, &ptmp);
+       drmRmMap(pI830->drmSubFD, fb_handle);
+
+       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		  "Removed DRI frontbuffer mapping in compatibility mode.\n");
+       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		  "DRIGetDeviceInfo will report incorrect frontbuffer "
+		  "handle.\n");
+   }
 
    /* Check the i915 DRM versioning */
    {
@@ -724,27 +734,6 @@ I830DRIScreenInit(ScreenPtr pScreen)
 	    return FALSE;
 	 }
 	 pI830->drmMinor = version->version_minor;
-	 if (version->version_minor < 7) {
-	    if (pI830->mmModeFlags & I830_KERNEL_MM) {
-	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			  "Unable to use TTM-based memory manager with DRM version %d.%d\n",
-			  version->version_major, version->version_minor);
-	       pI830->mmModeFlags &= ~I830_KERNEL_MM;
-
-	       i830_free_memory(pScrn, pI830->memory_manager);
-	       pI830->memory_manager = NULL;
-
-	       if (!(pI830->mmModeFlags & I830_KERNEL_TEX)) {
-		  pI830->mmModeFlags |= I830_KERNEL_TEX;
-
-		  if (!i830_allocate_texture_memory(pScrn)) {
-		     I830DRICloseScreen(pScreen);
-		     drmFreeVersion(version);
-		     return FALSE;
-		  }
-	       }
-	    }
-	 }
 #ifdef DAMAGE
 	 if (pI830->allowPageFlip && pI830->drmMinor < 9) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -762,7 +751,7 @@ I830DRIScreenInit(ScreenPtr pScreen)
     */
 
    if ((pDRIInfo->clientDriverName == I830ClientDriverName) && 
-       (pI830->mmModeFlags & I830_KERNEL_TEX)) {
+       (pI830->allocate_classic_textures)) {
       pDRIInfo->clientDriverName = I830LegacyClientDriverName;
    }
 
@@ -780,26 +769,21 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
 					     pScrn->virtualY * pI830->cpp);
 #endif
 
-   /* The I965G isn't ready for the front buffer mapping to be moved around,
-    * because of issues with rmmap, it seems.
-    */
-   if (!IS_I965G(pI830)) {
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "[drm] Mapping front buffer\n");
-      if (drmAddMap(pI830->drmSubFD,
-		    (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
-		    sarea->front_size,
-		    DRM_AGP,
-		    0,
-		    (drmAddress) &sarea->front_handle) < 0) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
-	 DRICloseScreen(pScreen);
-	 return FALSE;
-      }
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n",
-		 (int)sarea->front_handle);
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	      "[drm] Mapping front buffer\n");
+   if (drmAddMap(pI830->drmSubFD,
+		 (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
+		 sarea->front_size,
+		 DRM_AGP,
+		 0,
+		 (drmAddress) &sarea->front_handle) < 0) {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		  "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
+       DRICloseScreen(pScreen);
+       return FALSE;
    }
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n",
+	      (int)sarea->front_handle);
 
    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)(sarea->back_offset + pI830->LinearAddr),
@@ -841,7 +825,7 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Depth Buffer = 0x%08x\n",
               (int)sarea->depth_handle);
 
-   if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+   if (pI830->allocate_classic_textures) {
       if (drmAddMap(pI830->drmSubFD,
 		    (drm_handle_t)sarea->tex_offset + pI830->LinearAddr,
 		    sarea->tex_size, DRM_AGP, 0,
@@ -1710,7 +1694,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
 
    success = I830DRIMapScreenRegions(pScrn, sarea);
 
-   if (success && (pI830->mmModeFlags & I830_KERNEL_TEX))
+   if (success && pI830->allocate_classic_textures)
       I830InitTextureHeap(pScrn, sarea);
 
    return success;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9bb12c6..20c6c68 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -290,7 +290,6 @@ typedef enum {
    OPTION_TILING,
 #ifdef XF86DRI_MM
    OPTION_INTELTEXPOOL,
-   OPTION_INTELMMSIZE,
 #endif
    OPTION_TRIPLEBUFFER,
 } I830Opts;
@@ -313,7 +312,6 @@ static OptionInfoRec I830Options[] = {
    {OPTION_TILING,	"Tiling",	OPTV_BOOLEAN,	{0},	TRUE},
 #ifdef XF86DRI_MM
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
-   {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
 #endif
    {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN,	{0},	FALSE},
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
@@ -1319,50 +1317,22 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 pI830->directRenderingDisabled = TRUE;
       }
 
-      pI830->mmModeFlags = 0;
-
       if (!pI830->directRenderingDisabled) {
-	 pI830->mmModeFlags = I830_KERNEL_TEX;
-#ifdef XF86DRI_MM
-	 Bool tmp = FALSE;
-
-	 if (!IS_I965G(pI830))
-	    pI830->mmModeFlags |= I830_KERNEL_MM;
-#endif
+	 pI830->allocate_classic_textures = TRUE;
 
 	 from = X_PROBED;
 
 #ifdef XF86DRI_MM
-	 if (xf86GetOptValBool(pI830->Options, 
-			       OPTION_INTELTEXPOOL, &tmp)) {
-	    from = X_CONFIG;
-	    if (tmp) {
-	       pI830->mmModeFlags |= I830_KERNEL_TEX;
-	       pI830->mmModeFlags &= ~I830_KERNEL_MM;
-	    } else {
-	       pI830->mmModeFlags &= ~I830_KERNEL_TEX;
-	       pI830->mmModeFlags |= I830_KERNEL_MM;
-	    }	       
-	 }
-#endif
-
-	 xf86DrvMsg(pScrn->scrnIndex, from,
-		    "Will %stry to allocate texture pool "
-		    "for old Mesa 3D driver.\n",
-		    (pI830->mmModeFlags & I830_KERNEL_TEX) ?
-		    "" : "not ");
+	 if (!IS_I965G(pI830)) {
+	    Bool tmp;
 
-#ifdef XF86DRI_MM
-	 pI830->mmSize = I830_MM_MAXSIZE;
-	 from = X_INFO;
-	 if (xf86GetOptValInteger(pI830->Options, OPTION_INTELMMSIZE,
-				  &(pI830->mmSize))) {
-	    from = X_CONFIG;
+	    if (xf86GetOptValBool(pI830->Options,
+				  OPTION_INTELTEXPOOL, &tmp)) {
+	       from = X_CONFIG;
+	       if (!tmp)
+		  pI830->allocate_classic_textures = FALSE;
+	    }
 	 }
-	 xf86DrvMsg(pScrn->scrnIndex, from, 
-		    "Will try to reserve %d kiB of AGP aperture space\n"
-		    "\tfor the DRM memory manager.\n",
-		    pI830->mmSize);
 #endif
       }
    } 
@@ -2128,12 +2098,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    int i;
    Bool allocation_done = FALSE;
    MessageType from;
-#ifdef XF86DRI
-   Bool driDisabled;
-#ifdef XF86DRI_MM
-   unsigned long savedMMSize;
-#endif
-#endif
 
    pScrn = xf86Screens[pScreen->myNum];
    pI830 = I830PTR(pScrn);
@@ -2227,6 +2191,23 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pScrn->videoRam &= ~3;
    }
 
+#ifdef XF86DRI
+   /* Check for appropriate bpp and module support to initialize DRI. */
+   if (!I830CheckDRIAvailable(pScrn)) {
+      pI830->directRenderingDisabled = TRUE;
+   }
+
+   /* If DRI hasn't been explicitly disabled, try to initialize it.
+    * It will be used by the memory allocator.
+    */
+   if (!pI830->directRenderingDisabled)
+      pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
+   else
+      pI830->directRenderingEnabled = FALSE;
+#else
+   pI830->directRenderingEnabled = FALSE;
+#endif
+
    /* Set up our video memory allocator for the chosen videoRam */
    if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -2321,12 +2302,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
     * for it, and if there's also enough to allow tiling to be enabled.
     */
 
-   if (!I830CheckDRIAvailable(pScrn)) {
-      pI830->directRenderingDisabled = TRUE;
-#ifdef XF86DRI_MM
-      pI830->mmSize = 0;
-#endif
-   }
 
 #ifdef I830_XV
     /*
@@ -2336,7 +2311,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
     pI830->XvEnabled = !pI830->XvDisabled;
 #endif
 
-   if (!pI830->directRenderingDisabled) {
+   if (pI830->directRenderingEnabled) {
       int savedDisplayWidth = pScrn->displayWidth;
       Bool tiled = FALSE;
 
@@ -2366,25 +2341,18 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 }
       }
 
-      /* Attempt several rounds of allocation to get 2d and 3d memory to fit:
+      /* Attempt two rounds of allocation to get 2d and 3d memory to fit:
        *
-       * 0: tiled, large memory manager
-       * 1: tiled, small memory manager
-       * 2: untiled, large
-       * 3: untiled, small
+       * 0: untiled
+       * 1: tiled
        */
 
-#ifdef XF86DRI_MM
-      savedMMSize = pI830->mmSize;
-#define MM_TURNS 4
-#else
 #define MM_TURNS 2
-#endif
       for (i = 0; i < MM_TURNS; i++) {
-	 if (!tiled && i < 2)
+	 if (!tiled && i == 0)
 	    continue;
 
-	 if (i >= MM_TURNS/2) {
+	 if (i >= 1) {
 	    /* For further allocations, disable tiling */
 	    pI830->tiling = FALSE;
 	    pScrn->displayWidth = savedDisplayWidth;
@@ -2395,26 +2363,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	    pI830->allowPageFlip = FALSE;
 	 }
 
-#ifdef XF86DRI_MM
-	 if (i & 1) {
-	    /* For this allocation, switch to a smaller DRI memory manager
-	     * size.
-	     */
-	    pI830->mmSize = I830_MM_MINPAGES * GTT_PAGE_SIZE / KB(1);
-	 } else {
-	    pI830->mmSize = savedMMSize;
-	 }
-
-	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Attempting memory allocation with %s buffers and \n"
-		    "\t       %s DRI memory manager reservation:\n",
-		    (i & 2) ? "untiled" : "tiled",
-		    (i & 1) ? "small" : "large");
-#else
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		    "Attempting memory allocation with %s buffers:\n",
+		    "Attempting memory allocation with %s buffers.\n",
 		    (i & 1) ? "untiled" : "tiled");
-#endif
 
 	 if (i830_allocate_2d_memory(pScrn) &&
 	     i830_allocate_3d_memory(pScrn))
@@ -2436,10 +2387,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       if (i == MM_TURNS) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		    "Not enough video memory.  Disabling DRI.\n");
-#ifdef XF86DRI_MM
-	 pI830->mmSize = 0;
-#endif
-	 pI830->directRenderingDisabled = TRUE;
+	 pI830->directRenderingEnabled = FALSE;
       }
    }
 #endif
@@ -2461,7 +2409,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Cannot support DRI with frame buffer width > 2048.\n");
       pI830->tiling = FALSE;
-      pI830->directRenderingDisabled = TRUE;
+      pI830->directRenderingEnabled = FALSE;
    }
 
    pScrn->displayWidth = pScrn->displayWidth;
@@ -2563,11 +2511,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 
 #ifdef XF86DRI
    /*
-    * pI830->directRenderingDisabled is set once in PreInit.  Reinitialise
-    * pI830->directRenderingEnabled based on it each generation.
-    */
-   pI830->directRenderingEnabled = !pI830->directRenderingDisabled;
-   /*
     * Setup DRI after visuals have been established, but before fbScreenInit
     * is called.   fbScreenInit will eventually call into the drivers
     * InitGLXVisuals call back.
@@ -2578,26 +2521,21 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 	 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRI is disabled because it "
 		    "needs HW cursor, 2D accel and AGPGART.\n");
 	 pI830->directRenderingEnabled = FALSE;
-	 i830_free_3d_memory(pScrn);
       }
    }
 
-   driDisabled = !pI830->directRenderingEnabled;
-
    if (pI830->directRenderingEnabled)
-      pI830->directRenderingEnabled = I830DRIScreenInit(pScreen);
+      pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
 
-   if (!pI830->directRenderingEnabled) {
+   /* If we failed for any reason, free DRI memory. */
+   if (!pI830->directRenderingEnabled)
       i830_free_3d_memory(pScrn);
-   }
 
 #else
    pI830->directRenderingEnabled = FALSE;
 #endif
 
 #ifdef XF86DRI
-   if (pI830->directRenderingEnabled)
-      pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
 
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page Flipping %sabled\n",
 	      pI830->allowPageFlip ? "en" : "dis");
@@ -2717,9 +2655,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
 #endif
 
 #ifdef XF86DRI
-   if (pI830->directRenderingEnabled) {
+   if (pI830->directRenderingEnabled)
       pI830->directRenderingEnabled = I830DRIFinishScreenInit(pScreen);
-   }
 #endif
 
    /* Setup 3D engine, needed for rotation too */
@@ -2730,7 +2667,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       pI830->directRenderingOpen = TRUE;
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Enabled\n");
    } else {
-      if (driDisabled)
+      if (pI830->directRenderingDisabled)
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Disabled\n");
       else
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering: Failed\n");
@@ -2771,37 +2708,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    pI830->closing = FALSE;
    pI830->suspended = FALSE;
 
-#ifdef XF86DRI_MM
-   if (pI830->directRenderingEnabled && (pI830->mmModeFlags & I830_KERNEL_MM))
-   {
-      if (pI830->memory_manager == NULL) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
-		    "Too little AGP aperture space for DRM memory manager.\n"
-		    "\tPlease increase AGP aperture size from BIOS configuration screen.\n"
-		    "\tDisabling DRI.\n");
-	 pI830->directRenderingOpen = FALSE;
-	 I830DRICloseScreen(pScreen);
-	 pI830->directRenderingEnabled = FALSE;
-      } else {
-	 unsigned long aperEnd = ROUND_DOWN_TO(pI830->memory_manager->offset +
-					       pI830->memory_manager->size,
-					       GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
-	 unsigned long aperStart = ROUND_TO(pI830->memory_manager->offset,
-					    GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
-
-	 if (drmMMInit(pI830->drmSubFD, aperStart, aperEnd - aperStart,
-		       DRM_BO_MEM_TT)) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
-		       "Could not initialize the DRM memory manager.\n");
-	    
-	    pI830->directRenderingOpen = FALSE;
-	    I830DRICloseScreen(pScreen);
-	    pI830->directRenderingEnabled = FALSE;
-	 }
-      }
-   }
-#endif /* XF86DRI_MM */
-
    return TRUE;
 }
 
@@ -2862,7 +2768,7 @@ I830LeaveVT(int scrnIndex, int flags)
    if (pI830->directRenderingOpen) {
       DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
 #ifdef XF86DRI_MM
-      if (pI830->mmModeFlags & I830_KERNEL_MM) {
+      if (pI830->memory_manager != NULL) {
 	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT);
       }
 #endif /* XF86DRI_MM */
@@ -2967,7 +2873,7 @@ I830EnterVT(int scrnIndex, int flags)
 	    sarea->texList[i].age = sarea->texAge;
 
 #ifdef XF86DRI_MM
-	 if (pI830->mmModeFlags & I830_KERNEL_MM) {
+	 if (pI830->memory_manager != NULL) {
 	    drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT);
 	 }
 #endif /* XF86DRI_MM */
@@ -3014,26 +2920,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 #endif
 
    pI830->closing = TRUE;
-#ifdef XF86DRI
-   if (pI830->directRenderingOpen) {
-#ifdef DAMAGE
-      if (pI830->pDamage) {
-	 PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
-
-	 DamageUnregister(&pPix->drawable, pI830->pDamage);
-	 DamageDestroy(pI830->pDamage);
-	 pI830->pDamage = NULL;
-      }
-#endif
-#ifdef XF86DRI_MM
-      if (pI830->mmModeFlags & I830_KERNEL_MM) {
-	 drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);	 
-      }
-#endif /* XF86DRI_MM */
-      pI830->directRenderingOpen = FALSE;
-      I830DRICloseScreen(pScreen);
-   }
-#endif
 
    if (pScrn->vtSema == TRUE) {
       I830LeaveVT(scrnIndex, 0);
@@ -3068,7 +2954,22 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 #endif
    xf86_cursors_fini (pScreen);
 
-   i830_reset_allocations(pScrn);
+   i830_allocator_fini(pScrn);
+#ifdef XF86DRI
+   if (pI830->directRenderingOpen) {
+#ifdef DAMAGE
+      if (pI830->pDamage) {
+	 PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
+
+	 DamageUnregister(&pPix->drawable, pI830->pDamage);
+	 DamageDestroy(pI830->pDamage);
+	 pI830->pDamage = NULL;
+      }
+#endif
+      pI830->directRenderingOpen = FALSE;
+      I830DRICloseScreen(pScreen);
+   }
+#endif
 
    if (I830IsPrimary(pScrn)) {
       xf86GARTCloseScreen(scrnIndex);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index b38a5df..d4e9bff 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -114,6 +114,9 @@ enum tile_format {
     TILING_YMAJOR
 };
 
+static i830_memory *
+i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name,
+		       long size, unsigned long alignment, int flags);
 static void i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset,
 			   unsigned int pitch, unsigned int size,
 			   enum tile_format tile_format);
@@ -182,10 +185,22 @@ i830_unbind_memory(ScrnInfoPtr pScrn, i8
 void
 i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
 {
+#ifdef XF86DRI_MM
+    I830Ptr pI830 = I830PTR(pScrn);
+#endif
+
     if (mem == NULL)
 	return;
 
-    /* Disconnect from the list of allocations */
+#ifdef XF86DRI_MM
+    if (mem->bo.size != 0) {
+	drmBOUnReference(pI830->drmSubFD, &mem->bo);
+	xfree(mem->name);
+	xfree(mem);
+	return;
+    }
+#endif
+	    /* Disconnect from the list of allocations */
     if (mem->prev != NULL)
 	mem->prev->next = mem->next;
     if (mem->next != NULL)
@@ -237,7 +252,6 @@ i830_reset_allocations(ScrnInfoPtr pScrn
     pI830->third_buffer = NULL;
     pI830->depth_buffer = NULL;
     pI830->textures = NULL;
-    pI830->memory_manager = NULL;
 #endif
     pI830->LpRing->mem = NULL;
 
@@ -260,21 +274,24 @@ i830_free_3d_memory(ScrnInfoPtr pScrn)
     pI830->depth_buffer = NULL;
     i830_free_memory(pScrn, pI830->textures);
     pI830->textures = NULL;
-    i830_free_memory(pScrn, pI830->memory_manager);
-    pI830->memory_manager = NULL;
 #endif
 }
 
 /**
  * Initialize's the driver's video memory allocator to allocate in the
  * given range.
+ *
+ * This sets up the kernel memory manager to manage as much of the memory
+ * as we think it can, while leaving enough to us to fulfill our non-TTM
+ * static allocations.  Some of these exist because of the need for physical
+ * addresses to reference.
  */
 Bool
-i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
-		    unsigned long size)
+i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset, unsigned long size)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *start, *end;
+    int ret;
 
     start = xcalloc(1, sizeof(*start));
     if (start == NULL)
@@ -311,9 +328,82 @@ i830_allocator_init(ScrnInfoPtr pScrn, u
 
     pI830->memory_list = start;
 
+#ifdef XF86DRI_MM
+    /* Now that we have our manager set up, initialize the kernel MM if
+     * possible, covering almost all of the aperture.
+     */
+    if (pI830->directRenderingEnabled && pI830->drmMinor >= 7) {
+	int mmsize;
+
+	/* Take over all of the graphics aperture minus enough to for
+	 * physical-address allocations of cursor/overlay registers.
+	 */
+	mmsize = size;
+	if (!OVERLAY_NOPHYSICAL(pI830) && !IS_I965G(pI830)) {
+	    mmsize -= ROUND_TO(OVERLAY_SIZE, GTT_PAGE_SIZE);
+	    if (pI830->CursorNeedsPhysical) {
+		mmsize -= 2 * (ROUND_TO(HWCURSOR_SIZE, GTT_PAGE_SIZE) +
+			     ROUND_TO(HWCURSOR_SIZE_ARGB, GTT_PAGE_SIZE));
+	    }
+	}
+	if (pI830->fb_compression)
+	    mmsize -= MB(6);
+	/* Can't do TTM on stolen memory */
+	mmsize -= pI830->stolen_size;
+
+	/* Create the aperture allocation */
+	pI830->memory_manager =
+	    i830_allocate_aperture(pScrn, "DRI memory manager",
+				   mmsize, GTT_PAGE_SIZE,
+				   ALIGN_BOTH_ENDS | NEED_NON_STOLEN);
+
+	if (pI830->memory_manager != NULL) {
+	    /* Tell the kernel to manage it */
+	    ret = drmMMInit(pI830->drmSubFD,
+			    pI830->memory_manager->offset / GTT_PAGE_SIZE,
+			    pI830->memory_manager->size / GTT_PAGE_SIZE,
+			    DRM_BO_MEM_TT);
+	    if (ret != 0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to initialize kernel memory manager\n");
+		i830_free_memory(pScrn, pI830->memory_manager);
+		pI830->memory_manager = NULL;
+	    }
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Failed to allocate space for kernel memory manager\n");
+	    i830_free_memory(pScrn, pI830->memory_manager);
+	    pI830->memory_manager = NULL;
+	}
+    }
+#endif /* XF86DRI_MM */
+
     return TRUE;
 }
 
+void
+i830_allocator_fini(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* Free most of the allocations */
+    i830_reset_allocations(pScrn);
+
+#ifdef XF86DRI_MM
+    /* The memory manager is more special */
+    if (pI830->memory_manager) {
+	 drmMMTakedown(pI830->drmSubFD, DRM_BO_MEM_TT);
+	 i830_free_memory(pScrn, pI830->memory_manager);
+	 pI830->memory_manager = NULL;
+    }
+#endif /* XF86DRI_MM */
+
+    /* Free the start/end markers */
+    free(pI830->memory_list->next);
+    free(pI830->memory_list);
+    pI830->memory_list = NULL;
+}
+
 /**
  * Reads a GTT entry for the memory at the given offset and returns the
  * physical address.
@@ -447,6 +537,9 @@ i830_allocate_aperture(ScrnInfoPtr pScrn
 		mem->offset = ROUND_TO(pI830->stolen_size, alignment);
 	    }
 	}
+	if ((flags & NEED_NON_STOLEN) && mem->offset < pI830->stolen_size) {
+	    mem->offset = ROUND_TO(pI830->stolen_size, alignment);
+	}
 
 	mem->end = mem->offset + size;
 	if (flags & ALIGN_BOTH_ENDS)
@@ -515,25 +608,80 @@ i830_allocate_agp_memory(ScrnInfoPtr pSc
     return TRUE;
 }
 
+#ifdef XF86DRI_MM
+static i830_memory *
+i830_allocate_memory_bo(ScrnInfoPtr pScrn, const char *name,
+			unsigned long size, unsigned long align, int flags)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    i830_memory *mem;
+    unsigned long hint, mask;
+    int ret;
+
+    assert((flags & NEED_PHYSICAL_ADDR) == 0);
+
+    /* Only allocate page-sized increments. */
+    size = ALIGN(size, GTT_PAGE_SIZE);
+    align = ROUND_TO(align, GTT_PAGE_SIZE);
+
+    mem = xcalloc(1, sizeof(*mem));
+    if (mem == NULL)
+	return NULL;
+
+    mem->name = xstrdup(name);
+    if (name == NULL) {
+	xfree(mem);
+	return NULL;
+    }
+
+    mask = DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_MAPPABLE |
+	DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE;
+    hint = DRM_BO_HINT_DONT_FENCE | DRM_BO_HINT_DONT_BLOCK |
+	DRM_BO_HINT_ALLOW_UNFENCED_MAP;
+
+    I830DRILock(pScrn);
+    ret = drmBOCreate(pI830->drmSubFD, 0, size, align / GTT_PAGE_SIZE, NULL,
+		      drm_bo_type_dc, mask, hint, &mem->bo);
+    I830DRIUnlock(pScrn);
+    if (ret) {
+	xfree(mem->name);
+	xfree(mem);
+	return NULL;
+    }
+
+    mem->offset = mem->bo.offset;
+    mem->end = mem->bo.start + size;
+    mem->size = size;
+
+    return mem;
+}
+#endif /* XF86DRI_MM */
 
 /* Allocates video memory at the given size and alignment.
  *
  * The memory will be bound automatically when the driver is in control of the
- * VT.
+ * VT.  When the kernel memory manager is available and compatible with flags
+ * (that is, flags doesn't say that the allocation must include a physical
+ * address), that will be used for the allocation.
  */
 static i830_memory *
 i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
 		     unsigned long size, unsigned long alignment, int flags)
 {
+    I830Ptr pI830 = I830PTR(pScrn);
     i830_memory *mem;
 
-    mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
-    if (mem == NULL)
-	return NULL;
+    if (pI830->memory_manager && !(flags & NEED_PHYSICAL_ADDR)) {
+	return i830_allocate_memory_bo(pScrn, name, size, alignment, flags);
+    } else {
+	mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
+	if (mem == NULL)
+	    return NULL;
 
-    if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
-	i830_free_memory(pScrn, mem);
-	return NULL;
+	if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
+	    i830_free_memory(pScrn, mem);
+	    return NULL;
+	}
     }
 
     return mem;
@@ -588,7 +736,7 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
 	aper_align = alignment;
 
     fence_divide = 1;
-    mem = i830_allocate_aperture(pScrn, name, aper_size, aper_align, flags);
+    mem = i830_allocate_memory(pScrn, name, aper_size, aper_align, flags);
     if (mem == NULL && !IS_I965G(pI830)) {
 	/* For the older hardware with stricter fencing limits, if we
 	 * couldn't allocate with the large alignment, try relaxing the
@@ -604,8 +752,8 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
 		break;
 	    }
 
-	    mem = i830_allocate_aperture(pScrn, name, aper_size,
-					 aper_align / fence_divide, flags);
+	    mem = i830_allocate_memory(pScrn, name, aper_size,
+				       aper_align / fence_divide, flags);
 	}
     }
 
@@ -623,12 +771,6 @@ i830_allocate_memory_tiled(ScrnInfoPtr p
 	return NULL;
     }
 
-    /* Allocate any necessary AGP memory to back this allocation */
-    if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
-	i830_free_memory(pScrn, mem);
-	return NULL;
-    }
-
     /* Set up the fence registers. */
     for (i = 0; i < fence_divide; i++) {
 	i830_set_fence(pScrn, pI830->next_fence++,
@@ -1341,17 +1483,7 @@ i830_allocate_texture_memory(ScrnInfoPtr
     unsigned long size;
     int i;
 
-    if (pI830->mmModeFlags & I830_KERNEL_MM) {
-	pI830->memory_manager =
-	    i830_allocate_aperture(pScrn, "DRI memory manager",
-				   pI830->mmSize * KB(1), GTT_PAGE_SIZE,
-				   ALIGN_BOTH_ENDS);
-	/* XXX: try memory manager size backoff here? */
-	if (pI830->memory_manager == NULL)
-	    return FALSE;
-    }
-
-    if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+    if (pI830->allocate_classic_textures) {
 	/* XXX: auto-sizing */
 	size = MB(32);
 	i = myLog2(size / I830_NR_TEX_REGIONS);
@@ -1368,7 +1500,7 @@ i830_allocate_texture_memory(ScrnInfoPtr
 		       size / 1024);
 	    return FALSE;
 	}
-	pI830->textures = i830_allocate_memory(pScrn, "textures", size,
+	pI830->textures = i830_allocate_memory(pScrn, "classic textures", size,
 					       GTT_PAGE_SIZE, 0);
 	if (pI830->textures == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,


More information about the xorg-commit mailing list