Blob Blame History Raw
diff -up xf86-video-ati-6.12.2/configure.ac.modeset xf86-video-ati-6.12.2/configure.ac
--- xf86-video-ati-6.12.2/configure.ac.modeset	2009-04-08 10:29:53.000000000 -0400
+++ xf86-video-ati-6.12.2/configure.ac	2009-05-21 11:01:45.000000000 -0400
@@ -31,6 +31,7 @@ AM_CONFIG_HEADER([config.h])
 AC_CONFIG_AUX_DIR(.)
 
 AM_INIT_AUTOMAKE([dist-bzip2])
+AC_SYS_LARGEFILE
 
 AM_MAINTAINER_MODE
 
@@ -114,8 +115,19 @@ if test "$DRI" = yes; then
 	if test "$have_damage_h" = yes; then
 		AC_DEFINE(DAMAGE,1,[Use Damage extension])
 	fi
+
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$XORG_CFLAGS $DRI_CFLAGS"
+        AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include <stdint.h>
+#include <stdlib.h>])
+        if test "x$DRM_MODE" = xyes; then
+                AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting])
+        fi
+	CFLAGS="$save_CFLAGS"
 fi
 
+AC_DEFINE(DRI2, 1,[Enable DRI2 code])
+
 save_CFLAGS="$CFLAGS"
 CFLAGS="$XORG_CFLAGS"
 AC_CHECK_HEADER(xf86Modes.h,[XMODES=yes],[XMODES=no],[#include "xorg-server.h"])
diff -up /dev/null xf86-video-ati-6.12.2/src/drmmode_display.c
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/drmmode_display.c	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,1035 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef XF86DRM_MODE
+#include <sys/ioctl.h>
+#include "micmap.h"
+#include "xf86cmap.h"
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "radeon_drm.h"
+#include "sarea.h"
+
+/* DPMS */
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+static void
+drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
+		     drmModeModeInfo *kmode,
+		     DisplayModePtr	mode)
+{
+	memset(mode, 0, sizeof(DisplayModeRec));
+	mode->status = MODE_OK;
+	
+	mode->Clock = kmode->clock;
+	
+	mode->HDisplay = kmode->hdisplay;
+	mode->HSyncStart = kmode->hsync_start;
+	mode->HSyncEnd = kmode->hsync_end;
+	mode->HTotal = kmode->htotal;
+	mode->HSkew = kmode->hskew;
+    
+	mode->VDisplay = kmode->vdisplay;
+	mode->VSyncStart = kmode->vsync_start;
+	mode->VSyncEnd = kmode->vsync_end;
+	mode->VTotal = kmode->vtotal;
+	mode->VScan = kmode->vscan;
+
+	mode->Flags = kmode->flags; //& FLAG_BITS;
+	mode->name = strdup(kmode->name);
+
+	if (kmode->type & DRM_MODE_TYPE_DRIVER)
+		mode->type = M_T_DRIVER;
+	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
+		mode->type |= M_T_PREFERRED;
+	xf86SetModeCrtc (mode, scrn->adjustFlags);
+}
+
+static void
+drmmode_ConvertToKMode(ScrnInfoPtr	scrn,
+		     drmModeModeInfo *kmode,
+		     DisplayModePtr	mode)
+{
+	memset(kmode, 0, sizeof(*kmode));
+
+	kmode->clock = mode->Clock;
+	kmode->hdisplay = mode->HDisplay;
+	kmode->hsync_start = mode->HSyncStart;
+	kmode->hsync_end = mode->HSyncEnd;
+	kmode->htotal = mode->HTotal;
+	kmode->hskew = mode->HSkew;
+    
+	kmode->vdisplay = mode->VDisplay;
+	kmode->vsync_start = mode->VSyncStart;
+	kmode->vsync_end = mode->VSyncEnd;
+	kmode->vtotal = mode->VTotal;
+	kmode->vscan = mode->VScan;
+
+	kmode->flags = mode->Flags; //& FLAG_BITS;
+	if (mode->name)
+		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
+	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+
+}
+
+static void
+drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+#if 0
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+//	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+//	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+	/* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
+	if (mode == DPMSModeOff) {
+//		drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+//			       0, 0, 0, NULL, 0, NULL);
+	}
+#endif
+}
+
+static PixmapPtr
+create_pixmap_for_fbcon(drmmode_ptr drmmode,
+			ScrnInfoPtr pScrn, int crtc_id)
+{
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	drmmode_crtc_private_ptr drmmode_crtc;
+	ScreenPtr pScreen = pScrn->pScreen;
+	PixmapPtr pixmap;
+	dri_bo *bo;
+	drmModeFBPtr fbcon;
+	struct drm_gem_flink flink;
+	
+	drmmode_crtc = xf86_config->crtc[crtc_id]->driver_private;
+
+	fbcon = drmModeGetFB(drmmode->fd, drmmode_crtc->mode_crtc->buffer_id);
+	if (fbcon == NULL)
+		return NULL;
+
+	flink.handle = fbcon->handle;
+	if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't flink fbcon handle\n");
+		return NULL;
+	}
+	
+	bo = radeon_bo_gem_create_from_name(drmmode->bufmgr, "fbcon",
+					    flink.name);
+	if (bo == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't allocate bo for fbcon handle\n");
+		return NULL;
+	}
+
+	pixmap = GetScratchPixmapHeader(pScreen,
+					fbcon->width, fbcon->height,
+					fbcon->depth, fbcon->bpp,
+					fbcon->pitch, NULL);
+	if (pixmap == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't allocate pixmap fbcon contents\n");
+		return NULL;
+	}
+
+	radeon_set_pixmap_bo(pixmap, bo);
+	
+	dri_bo_unreference(bo);
+	drmModeFreeFB(fbcon);
+    	return pixmap;
+}
+
+void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+{
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+	PixmapPtr src, dst;
+	ScreenPtr pScreen = pScrn->pScreen;
+	int crtc_id = 0;
+	int i;
+	int pitch = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
+
+	if (info->ChipFamily >= CHIP_FAMILY_R600)
+		return;
+
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+		xf86CrtcPtr crtc = xf86_config->crtc[i];
+		drmmode_crtc_private_ptr drmmode_crtc;
+
+		drmmode_crtc = crtc->driver_private;
+		if (drmmode_crtc->mode_crtc->buffer_id)
+			crtc_id = i;
+	}
+			
+	src = create_pixmap_for_fbcon(drmmode, pScrn, crtc_id);
+	if (!src)
+		return;
+
+	dst = GetScratchPixmapHeader(pScreen,
+				     pScrn->virtualX, pScrn->virtualY,
+				     pScrn->depth, pScrn->bitsPerPixel,
+				     pitch, NULL);
+	radeon_set_pixmap_bo(dst, info->mm.front_buffer);
+	info->accel_state->exa->PrepareCopy (src, dst,
+					     -1, -1, GXcopy, FB_ALLONES);
+	info->accel_state->exa->Copy (dst, 0, 0, 0, 0,
+			 	      pScrn->virtualX, pScrn->virtualY);
+	info->accel_state->exa->DoneCopy (dst);
+	RADEONCPFlushIndirect(pScrn, 0);
+
+	(*pScreen->DestroyPixmap)(dst);
+	(*pScreen->DestroyPixmap)(src);
+
+}
+
+static Bool
+drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+		     Rotation rotation, int x, int y)
+{
+	ScrnInfoPtr pScrn = crtc->scrn;
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	int saved_x, saved_y;
+	Rotation saved_rotation;
+	DisplayModeRec saved_mode;
+	uint32_t *output_ids;
+	int output_count = 0;
+	Bool ret = TRUE;
+	int i;
+	int fb_id;
+	drmModeModeInfo kmode;
+	int pitch = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
+
+	if (drmmode->fb_id == 0) {
+		ret = drmModeAddFB(drmmode->fd,
+				   pScrn->virtualX, pScrn->virtualY,
+                                   pScrn->depth, pScrn->bitsPerPixel,
+                                   pitch, dri_bo_get_handle(info->mm.front_buffer),
+                                   &drmmode->fb_id);
+                if (ret < 0) {
+                        ErrorF("failed to add fb\n");
+                        return FALSE;
+                }
+        }
+
+	saved_mode = crtc->mode;
+	saved_x = crtc->x;
+	saved_y = crtc->y;
+	saved_rotation = crtc->rotation;
+
+	if (mode) {
+		crtc->mode = *mode;
+		crtc->x = x;
+		crtc->y = y;
+		crtc->rotation = rotation;
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,99,0,0)
+		crtc->transformPresent = FALSE;
+#endif
+	}
+
+	output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output);
+	if (!output_ids) {
+		ret = FALSE;
+		goto done;
+	}
+
+	if (mode) {
+		for (i = 0; i < xf86_config->num_output; i++) {
+			xf86OutputPtr output = xf86_config->output[i];
+			drmmode_output_private_ptr drmmode_output;
+
+			if (output->crtc != crtc)
+				continue;
+
+			drmmode_output = output->driver_private;
+			output_ids[output_count] = drmmode_output->mode_output->connector_id;
+			output_count++;
+		}
+
+		if (!xf86CrtcRotate(crtc)) {
+			goto done;
+		}
+
+		drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
+	
+		fb_id = drmmode->fb_id;
+		if (drmmode_crtc->rotate_fb_id) {
+			fb_id = drmmode_crtc->rotate_fb_id;
+			x = y = 0;
+		}
+		ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+				     fb_id, x, y, output_ids, output_count, &kmode);
+		if (ret)
+			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+				   "failed to set mode: %s", strerror(-ret));
+		else
+			ret = TRUE;
+
+		if (crtc->scrn->pScreen)
+			xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+		/* go through all the outputs and force DPMS them back on? */
+		for (i = 0; i < xf86_config->num_output; i++) {
+			xf86OutputPtr output = xf86_config->output[i];
+			drmmode_output_private_ptr drmmode_output;
+
+			if (output->crtc != crtc)
+				continue;
+
+			output->funcs->dpms(output, DPMSModeOn);
+		}
+	}
+		
+
+
+done:
+	if (!ret) {
+		crtc->x = saved_x;
+		crtc->y = saved_y;
+		crtc->rotation = saved_rotation;
+		crtc->mode = saved_mode;
+	}
+	return ret;
+}
+
+static void
+drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
+{
+  
+}
+
+static void
+drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+	drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
+}
+
+static void
+drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	void *ptr;
+
+	/* cursor should be mapped already */
+	ptr = drmmode_crtc->cursor_bo->virtual;
+
+	memcpy (ptr, image, 64 * 64 * 4);
+
+	return;
+}
+
+
+static void
+drmmode_hide_cursor (xf86CrtcPtr crtc)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	
+	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64);
+
+}
+
+static void
+drmmode_show_cursor (xf86CrtcPtr crtc)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	uint32_t handle = dri_bo_get_handle(drmmode_crtc->cursor_bo);
+
+	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
+}
+
+static void *
+drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	int size;
+	dri_bo *rotate_bo;
+	int ret;
+	unsigned long rotate_pitch;
+
+	width = RADEON_ALIGN(width, 63);
+	rotate_pitch = width * drmmode->cpp;
+
+	size = rotate_pitch * height;
+
+	rotate_bo = dri_bo_alloc(drmmode->bufmgr, "rotate", size, 0, RADEON_GEM_DOMAIN_VRAM);
+	if (rotate_bo == NULL)
+		return NULL;
+
+	dri_bo_map(rotate_bo, 1);
+
+	ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
+			   crtc->scrn->bitsPerPixel, rotate_pitch, dri_bo_get_handle(rotate_bo),
+			   &drmmode_crtc->rotate_fb_id);
+	if (ret) {
+		ErrorF("failed to add rotate fb\n");
+	}
+
+	drmmode_crtc->rotate_bo = rotate_bo;
+	return drmmode_crtc->rotate_bo->virtual;
+}
+
+static PixmapPtr
+drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
+{
+	ScrnInfoPtr pScrn = crtc->scrn;
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	unsigned long rotate_pitch;
+	PixmapPtr rotate_pixmap;
+	
+	if (!data)
+		data = drmmode_crtc_shadow_allocate (crtc, width, height);
+
+	rotate_pitch = RADEON_ALIGN(width, 63) * drmmode->cpp;
+	
+	rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
+					       width, height,
+					       pScrn->depth,
+					       pScrn->bitsPerPixel,
+					       rotate_pitch,
+					       data);
+	
+	if (rotate_pixmap == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
+	}
+
+	if (drmmode_crtc->rotate_bo)
+		radeon_set_pixmap_bo(rotate_pixmap, drmmode_crtc->rotate_bo);
+	return rotate_pixmap;
+
+}
+
+static void
+drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+	if (rotate_pixmap)
+	    FreeScratchPixmapHeader(rotate_pixmap);
+	
+	if (data) {
+		drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
+		drmmode_crtc->rotate_fb_id = 0;
+		dri_bo_unmap(drmmode_crtc->rotate_bo);
+		dri_bo_unreference(drmmode_crtc->rotate_bo);
+		drmmode_crtc->rotate_bo = NULL;
+	}
+
+}
+
+static void
+drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
+                      uint16_t *blue, int size)
+{
+	return;
+}
+
+static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
+    .dpms = drmmode_crtc_dpms,
+    .set_mode_major = drmmode_set_mode_major,
+    .set_cursor_colors = drmmode_set_cursor_colors,
+    .set_cursor_position = drmmode_set_cursor_position,
+    .show_cursor = drmmode_show_cursor,
+    .hide_cursor = drmmode_hide_cursor,
+    .load_cursor_argb = drmmode_load_cursor_argb,
+
+    .gamma_set = drmmode_crtc_gamma_set,
+    .shadow_create = drmmode_crtc_shadow_create,
+    .shadow_allocate = drmmode_crtc_shadow_allocate,
+    .shadow_destroy = drmmode_crtc_shadow_destroy,
+    .destroy = NULL, /* XXX */
+};
+
+
+static void
+drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+{
+	xf86CrtcPtr crtc;
+	drmmode_crtc_private_ptr drmmode_crtc;
+
+	crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
+	if (crtc == NULL)
+		return;
+
+	drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
+	drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
+	drmmode_crtc->drmmode = drmmode;
+	crtc->driver_private = drmmode_crtc;
+
+	return;
+}
+
+static xf86OutputStatus
+drmmode_output_detect(xf86OutputPtr output)
+{
+	/* go to the hw and retrieve a new output struct */
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	drmmode_ptr drmmode = drmmode_output->drmmode;
+	xf86OutputStatus status;
+	drmModeFreeConnector(drmmode_output->mode_output);
+	
+	drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
+	
+	switch (drmmode_output->mode_output->connection) {
+	case DRM_MODE_CONNECTED:
+		status = XF86OutputStatusConnected;
+		break;
+	case DRM_MODE_DISCONNECTED:
+		status = XF86OutputStatusDisconnected;
+		break;
+	default:
+	case DRM_MODE_UNKNOWNCONNECTION:
+		status = XF86OutputStatusUnknown;
+		break;
+	}
+	return status;
+}
+
+static Bool
+drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
+{
+	return MODE_OK;
+}
+
+static DisplayModePtr
+drmmode_output_get_modes(xf86OutputPtr output)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	drmModeConnectorPtr koutput = drmmode_output->mode_output;
+	drmmode_ptr drmmode = drmmode_output->drmmode;
+	int i;
+	DisplayModePtr Modes = NULL, Mode;
+	drmModePropertyPtr props;
+
+	/* look for an EDID property */
+	for (i = 0; i < koutput->count_props; i++) {
+		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+		if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
+			if (!strcmp(props->name, "EDID")) {
+				if (drmmode_output->edid_blob)
+					drmModeFreePropertyBlob(drmmode_output->edid_blob);
+				drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
+			}
+			drmModeFreeProperty(props);
+		}
+	}
+
+	if (drmmode_output->edid_blob)
+		xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, drmmode_output->edid_blob->data));
+	else
+		xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, NULL));
+
+	/* modes should already be available */
+	for (i = 0; i < koutput->count_modes; i++) {
+		Mode = xnfalloc(sizeof(DisplayModeRec));
+
+		drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
+		Modes = xf86ModesAdd(Modes, Mode);
+
+	}
+	return Modes;
+}
+
+static void
+drmmode_output_destroy(xf86OutputPtr output)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+
+	if (drmmode_output->edid_blob)
+		drmModeFreePropertyBlob(drmmode_output->edid_blob);
+	drmModeFreeConnector(drmmode_output->mode_output);
+	xfree(drmmode_output);
+	output->driver_private = NULL;
+}
+
+static void
+drmmode_output_dpms(xf86OutputPtr output, int mode)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	drmModeConnectorPtr koutput = drmmode_output->mode_output;
+	drmmode_ptr drmmode = drmmode_output->drmmode;
+
+	drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
+				    drmmode_output->dpms_enum_id, mode);
+	return;
+}
+
+static const xf86OutputFuncsRec drmmode_output_funcs = {
+    .dpms = drmmode_output_dpms,
+#if 0
+
+    .save = drmmode_crt_save,
+    .restore = drmmode_crt_restore,
+    .mode_fixup = drmmode_crt_mode_fixup,
+    .prepare = drmmode_output_prepare,
+    .mode_set = drmmode_crt_mode_set,
+    .commit = drmmode_output_commit,
+#endif
+    .detect = drmmode_output_detect,
+    .mode_valid = drmmode_output_mode_valid,
+
+    .get_modes = drmmode_output_get_modes,
+    .destroy = drmmode_output_destroy
+};
+
+static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
+				      SubPixelHorizontalRGB,
+				      SubPixelHorizontalBGR,
+				      SubPixelVerticalRGB,
+				      SubPixelVerticalBGR,
+				      SubPixelNone };
+
+const char *output_names[] = { "None",
+			       "VGA",
+			       "DVI",
+			       "DVI",
+			       "DVI",
+			       "Composite",
+			       "TV",
+			       "LVDS",
+			       "CTV",
+			       "DIN",
+			       "DP",
+			       "HDMI",
+			       "HDMI",
+};
+   
+
+static void
+drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+{
+	xf86OutputPtr output;
+	drmModeConnectorPtr koutput;
+	drmModeEncoderPtr kencoder;
+	drmmode_output_private_ptr drmmode_output;
+	drmModePropertyPtr props;
+	char name[32];
+	int i;
+
+	koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
+	if (!koutput)
+		return;
+
+	kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
+	if (!kencoder) {
+		drmModeFreeConnector(koutput);
+		return;
+	}
+
+	/* need to do smart conversion here for compat with non-kms ATI driver */
+	if (koutput->connector_type_id == 1) {
+	    switch(koutput->connector_type) {
+	    case DRM_MODE_CONNECTOR_VGA:
+	    case DRM_MODE_CONNECTOR_DVII:
+	    case DRM_MODE_CONNECTOR_DVID:
+	    case DRM_MODE_CONNECTOR_DVIA:
+	    case DRM_MODE_CONNECTOR_HDMIA:
+	    case DRM_MODE_CONNECTOR_HDMIB:
+		snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
+		break;
+	    default:
+		snprintf(name, 32, "%s", output_names[koutput->connector_type]);
+		break;
+	    }
+	} else {
+	    snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
+	}
+		
+	output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
+	if (!output) {
+		drmModeFreeEncoder(kencoder);
+		drmModeFreeConnector(koutput);
+		return;
+	}
+
+	drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1);
+	if (!drmmode_output) {
+		xf86OutputDestroy(output);
+		drmModeFreeConnector(koutput);
+		drmModeFreeEncoder(kencoder);
+		return;
+	}
+
+	drmmode_output->output_id = drmmode->mode_res->connectors[num];
+	drmmode_output->mode_output = koutput;
+	drmmode_output->mode_encoder = kencoder;
+	drmmode_output->drmmode = drmmode;
+	output->mm_width = koutput->mmWidth;
+	output->mm_height = koutput->mmHeight;
+
+	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
+	output->driver_private = drmmode_output;
+
+	output->possible_crtcs = kencoder->possible_crtcs;
+	output->possible_clones = kencoder->possible_clones;
+
+	for (i = 0; i < koutput->count_props; i++) {
+		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+		if (props && (props->flags && DRM_MODE_PROP_ENUM)) {
+			if (!strcmp(props->name, "DPMS")) {
+				drmmode_output->dpms_enum_id = koutput->props[i];
+				drmModeFreeProperty(props);
+				break;
+			}
+			drmModeFreeProperty(props);
+		}
+	}
+
+	return;
+}
+
+static Bool
+drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
+{
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	drmmode_crtc_private_ptr
+		    drmmode_crtc = xf86_config->crtc[0]->driver_private;
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	RADEONInfoPtr info = RADEONPTR(scrn);
+	dri_bo *old_front = NULL;
+	BoxRec	    mem_box;
+	Bool	    tiled, ret;
+	ScreenPtr   screen = screenInfo.screens[scrn->scrnIndex];
+	uint32_t    old_fb_id;
+	int	    i, pitch, old_width, old_height, old_pitch;
+	int screen_size;
+	int cpp = info->CurrentLayout.pixel_bytes;
+	dri_bo *front_bo;
+
+	if (scrn->virtualX == width && scrn->virtualY == height)
+		return TRUE;
+
+	front_bo = radeon_get_pixmap_bo(screen->GetScreenPixmap(screen));
+	RADEONCPFlushIndirect(scrn, 0);
+
+	if (front_bo)
+		radeon_bufmgr_gem_wait_rendering(front_bo);
+
+	pitch = RADEON_ALIGN(width, 63);
+	height = RADEON_ALIGN(height, 16);
+
+	screen_size = pitch * height * cpp;
+
+	xf86DrvMsg(scrn->scrnIndex, X_INFO,
+		   "Allocate new frame buffer %dx%d stride %d\n",
+		   width, height, pitch);
+
+	old_width = scrn->virtualX;
+	old_height = scrn->virtualY;
+	old_pitch = scrn->displayWidth;
+	old_fb_id = drmmode->fb_id;
+	old_front = info->mm.front_buffer;
+
+	scrn->virtualX = width;
+	scrn->virtualY = height;
+	scrn->displayWidth = pitch;
+
+	info->mm.front_buffer = dri_bo_alloc(info->bufmgr, "front", screen_size, 0, RADEON_GEM_DOMAIN_VRAM);
+	if (!info->mm.front_buffer)
+		goto fail;
+
+	ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
+			   scrn->bitsPerPixel, pitch * cpp,
+			   dri_bo_get_handle(info->mm.front_buffer),
+			   &drmmode->fb_id);
+	if (ret)
+		goto fail;
+
+	radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), info->mm.front_buffer);
+	screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen),
+				   width, height, -1, -1, pitch * cpp, NULL);
+
+	xf86DrvMsg(scrn->scrnIndex, X_INFO, "New front buffer at 0x%lx\n",
+		   info->mm.front_buffer->offset);
+
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+		xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+		if (!crtc->enabled)
+			continue;
+
+		drmmode_set_mode_major(crtc, &crtc->mode,
+				       crtc->rotation, crtc->x, crtc->y);
+	}
+
+	if (old_fb_id)
+		drmModeRmFB(drmmode->fd, old_fb_id);
+	if (old_front)
+		dri_bo_unreference(old_front);
+
+	return TRUE;
+
+ fail:
+	if (info->mm.front_buffer)
+		radeon_free_memory(scrn, info->mm.front_buffer);
+	info->mm.front_buffer = old_front;
+	scrn->virtualX = old_width;
+	scrn->virtualY = old_height;
+	scrn->displayWidth = old_pitch;
+	drmmode->fb_id = old_fb_id;
+
+	return FALSE;
+}
+
+static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
+	drmmode_xf86crtc_resize
+};
+
+
+Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp, int zaphod_mask)
+{
+	xf86CrtcConfigPtr   xf86_config;
+    	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+	int i;
+	Bool ret;
+
+	/* Create a bus Id */
+	/* Low level DRM open */
+	if (!pRADEONEnt->fd) {
+		ret = DRIOpenDRMMaster(pScrn, SAREA_MAX, busId, driver_name);
+		if (!ret) {
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				   "[dri] DRIGetVersion failed to open the DRM\n"
+				   "[dri] Disabling DRI.\n");
+			return FALSE;
+		}
+
+		drmmode->fd = DRIMasterFD(pScrn);
+		pRADEONEnt->fd = drmmode->fd;
+	} else {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				" reusing fd for second head\n");
+		drmmode->fd = pRADEONEnt->fd;
+	}
+	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
+	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+	drmmode->cpp = cpp;
+	drmmode->mode_res = drmModeGetResources(drmmode->fd);
+	if (!drmmode->mode_res)
+		return FALSE;
+
+	xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
+	for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
+		if (zaphod_mask & (1 << i))
+			drmmode_crtc_init(pScrn, drmmode, i);
+
+	for (i = 0; i < drmmode->mode_res->count_connectors; i++)
+		if (zaphod_mask & (1 << i))
+			drmmode_output_init(pScrn, drmmode, i);
+
+	xf86InitialConfiguration(pScrn, TRUE);
+
+	return TRUE;
+}
+
+Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, dri_bufmgr *bufmgr)
+{
+	drmmode->bufmgr = bufmgr;
+	return TRUE;
+}
+
+
+
+void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, dri_bo *bo)
+{
+  	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	xf86CrtcPtr crtc = xf86_config->crtc[id];
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	drmmode_crtc->cursor_bo = bo;
+}
+
+void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags)
+{
+	xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+	xf86OutputPtr  output = config->output[config->compat_output];
+	xf86CrtcPtr	crtc = output->crtc;
+
+	if (crtc && crtc->enabled) {
+		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
+				       x, y);
+	}
+}
+
+Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+{
+	xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+	int			c, o;
+
+	drmmode_copy_fb(pScrn, drmmode);
+
+	for (c = 0; c < config->num_crtc; c++) {
+		xf86CrtcPtr	crtc = config->crtc[c];
+		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+		xf86OutputPtr	output = NULL;
+		int		o;
+		
+		/* Skip disabled CRTCs */
+		if (!crtc->enabled) {
+			drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+				       0, 0, 0, NULL, 0, NULL);
+			continue;
+		}
+
+		if (config->output[config->compat_output]->crtc == crtc)
+			output = config->output[config->compat_output];
+		else
+		{
+			for (o = 0; o < config->num_output; o++)
+				if (config->output[o]->crtc == crtc)
+				{
+					output = config->output[o];
+					break;
+				}
+		}
+		/* paranoia */
+		if (!output)
+			continue;
+
+		/* Mark that we'll need to re-set the mode for sure */
+		memset(&crtc->mode, 0, sizeof(crtc->mode));
+		if (!crtc->desiredMode.CrtcHDisplay)
+		{
+			DisplayModePtr  mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
+			
+			if (!mode)
+				return FALSE;
+			crtc->desiredMode = *mode;
+			crtc->desiredRotation = RR_Rotate_0;
+			crtc->desiredX = 0;
+			crtc->desiredY = 0;
+		}
+
+		if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
+						 crtc->desiredX, crtc->desiredY))
+			return FALSE;
+	}
+	return TRUE;
+}
+
+static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
+                                 int *indices, LOCO *colors, VisualPtr pVisual)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    uint16_t       lut_r[256], lut_g[256], lut_b[256];
+    int index, j, i;
+    int c;
+
+
+
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+        xf86CrtcPtr crtc = xf86_config->crtc[c];
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+        for (i = 0 ; i < 256; i++) {
+            lut_r[i] = drmmode_crtc->lut_r[i] << 6;
+            lut_g[i] = drmmode_crtc->lut_g[i] << 6;
+            lut_b[i] = drmmode_crtc->lut_b[i] << 6;
+        }
+
+#if 0 //TODO
+        switch (info->CurrentLayout.depth) {
+        case 15:
+            for (i = 0; i < numColors; i++) {
+                index = indices[i];
+                for (j = 0; j < 8; j++) {
+                    lut_r[index * 8 + j] = colors[index].red << 6;
+                    lut_g[index * 8 + j] = colors[index].green << 6;
+                    lut_b[index * 8 + j] = colors[index].blue << 6;
+                }
+            }
+         break;
+         case 16:
+             for (i = 0; i < numColors; i++) {
+                 index = indices[i];
+
+                  if (i <= 31) {
+                      for (j = 0; j < 8; j++) {
+                          lut_r[index * 8 + j] = colors[index].red << 6;
+                          lut_b[index * 8 + j] = colors[index].blue << 6;
+                      }
+                  }
+
+                  for (j = 0; j < 4; j++) {
+                      lut_g[index * 4 + j] = colors[index].green << 6;
+                  }
+              }
+	  break;
+          default:
+              for (i = 0; i < numColors; i++) {
+                  index = indices[i];
+                  lut_r[index] = colors[index].red << 6;
+                  lut_g[index] = colors[index].green << 6;
+                  lut_b[index] = colors[index].blue << 6;
+              }
+              break;
+          }
+#endif
+
+    /* Make the change through RandR */
+#ifdef RANDR_12_INTERFACE
+        if (crtc->randr_crtc)
+            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
+        else
+#endif
+            crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
+     }
+}
+
+Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
+{
+    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+                  "Initializing kms color map\n");
+    if (!miCreateDefColormap(pScreen))
+        return FALSE;
+    /* all radeons support 10 bit CLUTs */
+    if (!xf86HandleColormaps(pScreen, 256, 10,
+                             drmmode_load_palette, NULL,
+                             CMAP_PALETTED_TRUECOLOR
+#if 0 /* This option messes up text mode! (eich@suse.de) */
+                             | CMAP_LOAD_EVEN_IF_OFFSCREEN
+#endif
+                             | CMAP_RELOAD_ON_MODE_SWITCH))
+         return FALSE;
+    return TRUE;
+}
+#endif
diff -up /dev/null xf86-video-ati-6.12.2/src/drmmode_display.h
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/drmmode_display.h	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *     Dave Airlie <airlied@redhat.com>
+ *
+ */
+#ifndef DRMMODE_DISPLAY_H
+#define DRMMODE_DISPLAY_H
+
+#ifdef XF86DRM_MODE
+
+#include "xf86drmMode.h"
+
+#include "radeon_probe.h"
+#include "radeon_bufmgr.h"
+
+typedef struct {
+  int fd;
+  int fb_id;
+  drmModeResPtr mode_res;
+  drmModeFBPtr mode_fb;
+  int cpp;
+  dri_bufmgr *bufmgr;
+} drmmode_rec, *drmmode_ptr;
+
+typedef struct {
+
+    drmmode_ptr drmmode;
+    drmModeCrtcPtr mode_crtc;
+    dri_bo *cursor_bo;
+    dri_bo *rotate_bo;
+    int rotate_fb_id;
+    uint16_t lut_r[256], lut_g[256], lut_b[256];
+} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
+
+typedef struct {
+    drmmode_ptr drmmode;
+    int output_id;
+    drmModeConnectorPtr mode_output;
+    drmModeEncoderPtr mode_encoder;
+    drmModePropertyBlobPtr edid_blob;
+    int dpms_enum_id;
+} drmmode_output_private_rec, *drmmode_output_private_ptr;
+
+
+extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp, int zaphod_mask);
+extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, dri_bufmgr *bufmgr);
+extern void drmmode_set_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int width, int height, int pitch, dri_bo *bo);
+extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, dri_bo *bo);
+void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags);
+extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
+extern void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
+extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
+#endif
+
+#endif
diff -up xf86-video-ati-6.12.2/src/Makefile.am.modeset xf86-video-ati-6.12.2/src/Makefile.am
--- xf86-video-ati-6.12.2/src/Makefile.am.modeset	2009-03-31 15:11:10.000000000 -0400
+++ xf86-video-ati-6.12.2/src/Makefile.am	2009-05-21 11:01:45.000000000 -0400
@@ -90,12 +90,14 @@ radeon_drv_ladir = @moduledir@/drivers
 radeon_drv_la_SOURCES = \
 	radeon_accel.c radeon_cursor.c radeon_dga.c radeon_legacy_memory.c \
 	radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \
-	radeon_vip.c radeon_misc.c radeon_probe.c \
+	radeon_vip.c radeon_misc.c radeon_probe.c radeon_memory.c \
 	legacy_crtc.c legacy_output.c \
 	radeon_textured_video.c \
 	radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \
 	$(RADEON_ATOMBIOS_SOURCES) radeon_atombios.c radeon_atomwrapper.c \
-	$(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c
+	$(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c \
+	atombios_crtc.c  drmmode_display.c radeon_bufmgr_gem.c \
+	radeon_dri_bufmgr.c radeon_dri2.c
 
 if XMODES
 radeon_drv_la_SOURCES += \
@@ -144,6 +146,7 @@ EXTRA_DIST = \
 	radeon_exa_render.c \
 	radeon_exa_funcs.c \
 	radeon.h \
+	radeon_dri2.h \
 	radeon_macros.h \
 	radeon_probe.h \
 	radeon_reg.h \
@@ -164,4 +167,6 @@ EXTRA_DIST = \
 	radeon_pci_device_match_gen.h \
 	pcidb/ati_pciids.csv \
 	pcidb/parse_pci_ids.pl \
-	radeon_atombios.h
+	radeon_atombios.h \
+	drmmode_display.h \
+	radeon_dri_bufmgr.h
diff -up xf86-video-ati-6.12.2/src/r600_textured_videofuncs.c.modeset xf86-video-ati-6.12.2/src/r600_textured_videofuncs.c
--- xf86-video-ati-6.12.2/src/r600_textured_videofuncs.c.modeset	2009-04-07 11:32:33.000000000 -0400
+++ xf86-video-ati-6.12.2/src/r600_textured_videofuncs.c	2009-05-21 11:01:45.000000000 -0400
@@ -215,7 +215,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pSc
     switch(pPriv->id) {
     case FOURCC_YV12:
     case FOURCC_I420:
-	accel_state->src_mc_addr[0] = pPriv->src_offset;
+	accel_state->src_mc_addr[0] = pPriv->src_offset + info->fbLocation + pScrn->fbOffset;
 	accel_state->src_size[0] = accel_state->src_pitch[0] * pPriv->h;
 
 	/* flush texture cache */
@@ -316,7 +316,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pSc
     case FOURCC_UYVY:
     case FOURCC_YUY2:
     default:
-	accel_state->src_mc_addr[0] = pPriv->src_offset;
+	accel_state->src_mc_addr[0] = pPriv->src_offset + info->fbLocation + pScrn->fbOffset;
 	accel_state->src_size[0] = accel_state->src_pitch[0] * pPriv->h;
 
 	/* flush texture cache */
diff -up xf86-video-ati-6.12.2/src/radeon_accel.c.modeset xf86-video-ati-6.12.2/src/radeon_accel.c
--- xf86-video-ati-6.12.2/src/radeon_accel.c.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_accel.c	2009-05-21 11:03:18.000000000 -0400
@@ -94,6 +94,7 @@
 
 				/* X and server generic header files */
 #include "xf86.h"
+#include "radeon_bufmgr_gem.h"
 
 static void R600EngineReset(ScrnInfoPtr pScrn);
 
@@ -375,6 +376,9 @@ void RADEONEngineRestore(ScrnInfoPtr pSc
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
 
+    if (info->drm_mode_setting)
+      return;
+
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "EngineRestore (%d/%d)\n",
 		   info->CurrentLayout.pixel_code,
@@ -435,8 +439,8 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
 		   info->CurrentLayout.bitsPerPixel);
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled && (IS_R300_3D || IS_R500_3D)) {
-	drm_radeon_getparam_t np;
+    if ((info->directRenderingEnabled || info->drm_mode_setting) && (IS_R300_3D || IS_R500_3D)) {
+        drm_radeon_getparam_t np;
 	int num_pipes;
 
 	memset(&np, 0, sizeof(np));
@@ -455,64 +459,66 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
     }
 #endif
 
-    if ((info->ChipFamily == CHIP_FAMILY_RV410) ||
-	(info->ChipFamily == CHIP_FAMILY_R420)  ||
-	(info->ChipFamily == CHIP_FAMILY_RS600) ||
-	(info->ChipFamily == CHIP_FAMILY_RS690) ||
-	(info->ChipFamily == CHIP_FAMILY_RS740) ||
-	(info->ChipFamily == CHIP_FAMILY_RS400) ||
-	(info->ChipFamily == CHIP_FAMILY_RS480) ||
-	IS_R500_3D) {
-	if (info->accel_state->num_gb_pipes == 0) {
-	    uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT);
-
-	    info->accel_state->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
-	    if (IS_R500_3D)
-		OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
-	}
-    } else {
-	if (info->accel_state->num_gb_pipes == 0) {
-	    if ((info->ChipFamily == CHIP_FAMILY_R300) ||
-		(info->ChipFamily == CHIP_FAMILY_R350)) {
-		/* R3xx chips */
-		info->accel_state->num_gb_pipes = 2;
-	    } else {
-		/* RV3xx chips */
-		info->accel_state->num_gb_pipes = 1;
+    if (!info->drm_mode_setting) {
+	if ((info->ChipFamily == CHIP_FAMILY_RV410) ||
+	    (info->ChipFamily == CHIP_FAMILY_R420)  ||
+	    (info->ChipFamily == CHIP_FAMILY_RS600) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS690) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS740) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS400) ||
+	    (info->ChipFamily == CHIP_FAMILY_RS480) ||
+	    IS_R500_3D) {
+	    if (info->accel_state->num_gb_pipes == 0) {
+		uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT);
+
+		info->accel_state->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
+		if (IS_R500_3D)
+		    OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
+	    }
+	} else {
+	    if (info->accel_state->num_gb_pipes == 0) {
+		if ((info->ChipFamily == CHIP_FAMILY_R300) ||
+		    (info->ChipFamily == CHIP_FAMILY_R350)) {
+		    /* R3xx chips */
+		    info->accel_state->num_gb_pipes = 2;
+		} else {
+		    /* RV3xx chips */
+		    info->accel_state->num_gb_pipes = 1;
+		}
 	    }
 	}
-    }
 
-    /* RV410 SE cards only have 1 quadpipe */
-    if ((info->Chipset == PCI_CHIP_RV410_5E4C) ||
-	(info->Chipset == PCI_CHIP_RV410_5E4F))
-	info->accel_state->num_gb_pipes = 1;
-
-    if (IS_R300_3D || IS_R500_3D)
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "num quad-pipes is %d\n", info->accel_state->num_gb_pipes);
-
-    if (IS_R300_3D || IS_R500_3D) {
-	uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
-
-	switch(info->accel_state->num_gb_pipes) {
-	case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
-	case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
-	case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
-	default:
-	case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
-	}
-
-	OUTREG(R300_GB_TILE_CONFIG, gb_tile_config);
-	OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
-	OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
-	OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) |
-					 R300_DC_AUTOFLUSH_ENABLE |
-					 R300_DC_DC_DISABLE_IGNORE_PE));
-    } else
-	OUTREG(RADEON_RB3D_CNTL, 0);
+	/* RV410 SE cards only have 1 quadpipe */
+	if ((info->Chipset == PCI_CHIP_RV410_5E4C) ||
+	    (info->Chipset == PCI_CHIP_RV410_5E4F))
+	    info->accel_state->num_gb_pipes = 1;
+
+	if (IS_R300_3D || IS_R500_3D)
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "num quad-pipes is %d\n", info->accel_state->num_gb_pipes);
+
+	if (IS_R300_3D || IS_R500_3D) {
+	    uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
+
+	    switch(info->accel_state->num_gb_pipes) {
+	    case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
+	    case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
+	    case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
+	    default:
+	    case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
+	    }
+
+	    OUTREG(R300_GB_TILE_CONFIG, gb_tile_config);
+	    OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
+	    OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
+	    OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) |
+					     R300_DC_AUTOFLUSH_ENABLE |
+					     R300_DC_DC_DISABLE_IGNORE_PE));
+	} else
+	    OUTREG(RADEON_RB3D_CNTL, 0);
 
-    RADEONEngineReset(pScrn);
+	RADEONEngineReset(pScrn);
+    }
 
     switch (info->CurrentLayout.pixel_code) {
     case 8:  datatype = 2; break;
@@ -620,6 +626,119 @@ int RADEONCPStop(ScrnInfoPtr pScrn, RADE
     }
 }
 
+#define RADEON_IB_RESERVE (16 * sizeof(uint32_t))
+drmBufPtr RADEONCSGetBuffer(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+
+    info->cp->relocs.size = getpagesize();
+    info->cp->relocs.num_reloc = 0;
+    info->cp->relocs.max_bo = info->cp->relocs.size / RADEON_RELOC_SIZE;
+    info->cp->relocs.buf = xcalloc(1, info->cp->relocs.size);
+    if (!info->cp->relocs.buf)
+        return NULL;
+
+    info->cp->relocs.bo_list = xcalloc(info->cp->relocs.max_bo, sizeof(dri_bo *));
+    if (!info->cp->relocs.bo_list) {
+	xfree(info->cp->relocs.buf);
+	return NULL;
+    }
+
+    info->cp->ib_gem_fake.address = xcalloc(1, RADEON_BUFFER_SIZE);
+    if (!info->cp->ib_gem_fake.address) {
+        xfree(info->cp->relocs.buf);
+        xfree(info->cp->relocs.bo_list);
+	return NULL;
+    }
+
+
+    info->cp->ib_gem_fake.used = 0;
+    info->cp->ib_gem_fake.total = RADEON_BUFFER_SIZE - RADEON_IB_RESERVE; // reserve 16 dwords
+    return &info->cp->ib_gem_fake;
+}
+
+void RADEONCSFlushIndirect(ScrnInfoPtr pScrn, int discard)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    struct drm_radeon_cs args;
+    struct drm_radeon_cs_chunk chunk[2];
+    uint64_t chunk_array[2];
+    int retry = 0;
+    int ret;
+    RING_LOCALS;
+
+    if (info->cp->indirectBuffer->used == 0)
+	return;
+
+    /* always add the cache flushes to the end of the IB */
+    info->cp->indirectBuffer->total += RADEON_IB_RESERVE;
+    
+    /* end of IB purge caches */
+    if (info->cs_used_depth) {
+	RADEON_PURGE_ZCACHE();
+	info->cs_used_depth = 0;
+    }
+
+    chunk[0].chunk_data = (unsigned long)info->cp->ib_gem_fake.address;
+    chunk[0].length_dw = info->cp->indirectBuffer->used / sizeof(uint32_t);
+    chunk[0].chunk_id = RADEON_CHUNK_ID_IB;
+
+    chunk[1].chunk_data = (unsigned long)info->cp->relocs.buf;
+    chunk[1].length_dw = info->cp->relocs.num_reloc * RADEON_RELOC_SIZE;
+    chunk[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
+
+    chunk_array[0] = (uint64_t)(unsigned long)&chunk[0];
+    chunk_array[1] = (uint64_t)(unsigned long)&chunk[1];
+
+    args.num_chunks = 2;
+    args.chunks = (uint64_t)(unsigned long)chunk_array;
+
+    do {
+	ret = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_CS,
+				  &args, sizeof(args));
+	retry++;
+    } while (ret == -EAGAIN && retry < 1000);
+    if (ret) {
+        /* submit failed */
+        ErrorF("RADEON DRM CS failure - corruptions/glitches may occur %d\n", ret);
+    }
+
+
+    info->cp->indirectStart = 0;
+    info->cp->indirectBuffer->used = 0;
+    info->cp->indirectBuffer->total -= RADEON_IB_RESERVE;
+
+    if (info->bufmgr)
+      radeon_gem_bufmgr_post_submit(info->bufmgr, &info->cp->relocs, ret);
+    
+    info->cp->relocs.num_reloc = 0;
+    /* copy some state into the buffer now - we need to add 2D state to each
+       buffer as the kernel needs to use the blit engine to move stuff around */
+    if (info->reemit_current2d)
+      info->reemit_current2d(pScrn, 0);
+    if (info->dri2.enabled) {
+    info->accel_state->XInited3D = FALSE;
+    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+    }
+}
+
+void RADEONCSReleaseIndirect(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+
+    if (!info->cp->indirectBuffer) return;
+    RADEONCSFlushIndirect(pScrn, 0);
+    xfree(info->cp->relocs.buf);
+    xfree(info->cp->relocs.bo_list);
+    info->cp->relocs.buf = 0;
+    info->cp->relocs.size = 0;
+    info->cp->relocs.num_reloc = 0;
+    xfree(info->cp->ib_gem_fake.address);
+    info->cp->ib_gem_fake.address = NULL;
+    info->cp->indirectBuffer = NULL;
+
+}
+
 /* Get an indirect buffer for the CP 2D acceleration commands  */
 drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn)
 {
@@ -630,6 +749,9 @@ drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr 
     int            size = 0;
     int            i = 0;
     int            ret;
+    
+    if (info->new_cs)
+	return RADEONCSGetBuffer(pScrn);
 
 #if 0
     /* FIXME: pScrn->pScreen has not been initialized when this is first
@@ -699,6 +821,11 @@ void RADEONCPFlushIndirect(ScrnInfoPtr p
     if (!buffer) return;
     if (start == buffer->used && !discard) return;
 
+    if (info->new_cs) {
+	RADEONCSFlushIndirect(pScrn, discard);
+	return;
+    }
+
     if (RADEON_VERBOSE) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing buffer %d\n",
 		   buffer->idx);
@@ -757,10 +884,16 @@ void RADEONCPReleaseIndirect(ScrnInfoPtr
 	}
     }
 
+    if (info->new_cs) {
+      RADEONCSReleaseIndirect(pScrn);
+      return;
+    }
+
     info->cp->indirectBuffer = NULL;
     info->cp->indirectStart  = 0;
 
     if (!buffer) return;
+      
 
     if (RADEON_VERBOSE) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing buffer %d\n",
@@ -887,6 +1020,7 @@ RADEONHostDataBlit(
     ret = ( uint8_t* )&__head[__count];
 
     __count += dwords;
+
     ADVANCE_RING();
 
     *y += *hpass;
@@ -1021,7 +1155,7 @@ Bool RADEONAccelInit(ScreenPtr pScreen)
 #ifdef USE_EXA
     if (info->useEXA) {
 # ifdef XF86DRI
-	if (info->directRenderingEnabled) {
+	if (info->directRenderingEnabled || info->drm_mode_setting) {
 	    if (info->ChipFamily >= CHIP_FAMILY_R600) {
 		if (!R600DrawInit(pScreen))
 		    return FALSE;
@@ -1054,7 +1188,7 @@ Bool RADEONAccelInit(ScreenPtr pScreen)
 	}
 
 #ifdef XF86DRI
-	if (info->directRenderingEnabled)
+	if (info->directRenderingEnabled || info->drm_mode_setting)
 	    RADEONAccelInitCP(pScreen, a);
 	else
 #endif /* XF86DRI */
@@ -1076,11 +1210,13 @@ void RADEONInit3DEngine(ScrnInfoPtr pScr
     RADEONInfoPtr info = RADEONPTR (pScrn);
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled) {
-	drm_radeon_sarea_t *pSAREAPriv;
+    if (info->directRenderingEnabled || info->drm_mode_setting) {
+	if (info->directRenderingEnabled && !info->dri2.enabled) {
+	    drm_radeon_sarea_t *pSAREAPriv;
 
-	pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-	pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen);
+	    pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+	    pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen);
+	}
 	RADEONInit3DEngineCP(pScrn);
     } else
 #endif
@@ -1088,7 +1224,7 @@ void RADEONInit3DEngine(ScrnInfoPtr pScr
 
     info->accel_state->XInited3D = TRUE;
 }
-
+    
 #ifdef USE_XAA
 #ifdef XF86DRI
 Bool
diff -up /dev/null xf86-video-ati-6.12.2/src/radeon_bufmgr_gem.c
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/radeon_bufmgr_gem.c	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,639 @@
+/**************************************************************************
+ *
+ * Copyright © 2007-2008 Red Hat Inc.
+ * Copyright © 2007 Intel Corporation
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ *	    Eric Anholt <eric@anholt.net>
+ *	    Dave Airlie <airlied@linux.ie>
+ *	    Kristian Høgsberg <krh@redhat.com>
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xf86drm.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "xf86.h"
+#include "errno.h"
+#include "string.h"
+
+#include "radeon_reg.h"
+#include "radeon_probe.h"
+#include "radeon.h"
+#include "radeon_bufmgr.h"
+#include "radeon_drm.h"
+
+#define DBG(...) do {					\
+   if (bufmgr_gem->bufmgr.debug)			\
+      fprintf(stderr, __VA_ARGS__);			\
+} while (0)
+
+typedef struct _dri_bo_gem {
+	dri_bo bo;
+	int refcount;
+	int reloc_count;
+	int map_count;
+	/* reloc list - add to list for relocs */
+	uint32_t gem_handle;
+	const char *name;
+	struct _dri_bo_gem *next;
+	int in_vram; /* have we migrated this bo to VRAM ever */
+	int force_gtt;
+	int pinned;
+	int touched;
+	void *priv_map;
+	uint32_t space_accounted;
+} dri_bo_gem;
+
+typedef struct _dri_bufmgr_gem {
+	dri_bufmgr bufmgr;
+	struct radeon_bufmgr radeon_bufmgr;
+	int fd;
+	uint32_t vram_limit, gart_limit;
+	uint32_t vram_write_used, gart_write_used;
+	uint32_t read_used;
+
+	struct _dri_bo_gem *bo_list;
+} dri_bufmgr_gem;
+
+static dri_bo *
+dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
+		 unsigned long size, unsigned int alignment, uint64_t location_mask)
+
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
+	struct drm_radeon_gem_create args;
+	int ret;
+	dri_bo_gem *gem_bo;
+
+	gem_bo = calloc(1, sizeof(*gem_bo));
+	if (!gem_bo)
+		return NULL;
+
+	gem_bo->bo.size = size;
+	args.size = size;
+	args.alignment = alignment;
+	args.initial_domain = RADEON_GEM_DOMAIN_CPU;
+	args.flags = 0;
+
+	ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_CREATE, &args, sizeof(args));
+	gem_bo->gem_handle = args.handle;
+	if (ret != 0) {
+		free(gem_bo);
+		return NULL;
+	}
+	gem_bo->bo.bufmgr = bufmgr;
+
+	gem_bo->refcount = 1;
+	gem_bo->reloc_count = 0;
+	gem_bo->map_count = 0;
+	gem_bo->in_vram = 0;
+	gem_bo->name = strdup(name);
+	gem_bo->touched = 0;
+
+	gem_bo->next = bufmgr_gem->bo_list;
+	bufmgr_gem->bo_list = gem_bo;
+
+	DBG("bo_create: buf %d (%s) %ldb\n",
+	    gem_bo->gem_handle, gem_bo->name, size);
+
+	return &gem_bo->bo;
+}
+
+static void
+dri_gem_bo_reference(dri_bo *bo)
+{
+	dri_bo_gem *gem_bo = (dri_bo_gem *)bo;
+	gem_bo->refcount++;
+}
+
+static void dri_gem_bo_free(dri_bo *bo)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
+	dri_bo_gem *gem_bo = (dri_bo_gem *)bo, *trav, *prev;
+	struct drm_gem_close args;
+
+	if (gem_bo->priv_map)
+		munmap(gem_bo->priv_map, gem_bo->bo.size);
+
+	/* close object */
+	args.handle = gem_bo->gem_handle;
+	ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &args);
+
+	if (gem_bo == bufmgr_gem->bo_list)
+		bufmgr_gem->bo_list = gem_bo->next;
+	else {
+		prev = trav = bufmgr_gem->bo_list;
+		while (trav) {
+			if (trav == gem_bo) {
+				if (prev)
+					prev->next = trav->next;
+				break;
+			}
+			prev = trav;
+			trav = trav->next;
+		}
+	}
+	free(gem_bo->name);
+	free(gem_bo);
+}
+
+static void
+dri_gem_bo_unreference(dri_bo *bo)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
+	dri_bo_gem *gem_bo = (dri_bo_gem *)bo;
+
+	if (!bo)
+		return;
+	
+	if (--gem_bo->refcount == 0) {
+		DBG("bo_unreference final: %d (%s) 0 - free %d\n",
+		    gem_bo->gem_handle, gem_bo->name, gem_bo->in_vram);
+		dri_gem_bo_free(bo);
+		return;
+	}
+}
+
+static int
+dri_gem_bo_map(dri_bo *bo, int write_enable)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
+	dri_bo_gem *gem_bo = (dri_bo_gem *)bo;
+	struct drm_radeon_gem_mmap args;
+	int ret = 0;
+	void *ptr;
+
+	if (gem_bo->map_count++ != 0)
+		return 0;
+
+	if (!gem_bo->priv_map) {
+		args.handle = gem_bo->gem_handle;
+		args.offset = 0;
+		args.size = gem_bo->bo.size;
+
+		ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_MMAP, &args, sizeof(args));
+		if (ret)
+			return ret;
+
+		ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bufmgr_gem->fd, args.addr_ptr);
+		if (ptr == MAP_FAILED)
+			return -errno;
+		gem_bo->priv_map = ptr;
+	}
+
+	gem_bo->bo.virtual = gem_bo->priv_map;
+
+	return ret;
+}
+
+static int
+dri_gem_bo_unmap(dri_bo *buf)
+{
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+
+	if (--gem_bo->map_count > 0)
+		return 0;
+
+	gem_bo->bo.virtual = NULL;
+	return 0;
+}
+
+static void
+dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)
+{
+	free(bufmgr);
+}
+
+void radeon_bufmgr_gem_wait_rendering(dri_bo *buf)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr;
+	struct drm_radeon_gem_wait_idle args;
+	struct drm_radeon_gem_set_domain sd_args;
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+	int ret;
+
+	if (!gem_bo->touched)
+		return;
+
+	/* do a set domain */
+	if (gem_bo->force_gtt) {
+		sd_args.handle = gem_bo->gem_handle;
+		sd_args.read_domains = RADEON_GEM_DOMAIN_GTT;
+		sd_args.write_domain = 0;
+
+		ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_SET_DOMAIN,
+					  &sd_args, sizeof(sd_args));
+
+	} else {
+		args.handle = gem_bo->gem_handle;
+
+		do {
+		ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_WAIT_IDLE,
+					  &args, sizeof(args));
+		} while (ret == -EBUSY);
+	}
+	return;
+}
+
+dri_bo *
+radeon_bo_gem_create_from_handle(dri_bufmgr *bufmgr,
+				 uint32_t handle, unsigned long size)
+{
+    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
+    dri_bo_gem *bo_gem;
+    char name[32];
+
+    sprintf(name, "handle:%8x", handle);
+    bo_gem = calloc(1, sizeof(*bo_gem));
+    if (!bo_gem)
+	return NULL;
+
+    bo_gem->bo.size = size;
+    bo_gem->bo.offset = 0;
+    bo_gem->bo.virtual = NULL;
+    bo_gem->bo.bufmgr = bufmgr;
+    bo_gem->name = strdup(name);
+    bo_gem->refcount = 1;
+    bo_gem->pinned = 1;
+    bo_gem->gem_handle = handle;
+    bo_gem->in_vram = 1;
+    /* if we get from kernel assume touched */
+    bo_gem->touched = 1;
+
+    bo_gem->next = bufmgr_gem->bo_list;
+    bufmgr_gem->bo_list = bo_gem;
+    return &bo_gem->bo;
+}
+
+/**
+ * Returns a dri_bo wrapping the given buffer object handle.
+ *
+ * This can be used when one application needs to pass a buffer object
+ * to another.
+ */
+dri_bo *
+radeon_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name,
+			       unsigned int handle)
+{
+    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
+    int ret;
+    struct drm_gem_open open_arg;
+
+    memset(&open_arg, 0, sizeof(open_arg));
+    open_arg.name = handle;
+    ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
+    if (ret != 0) {
+	fprintf(stderr, "Couldn't reference %s handle 0x%08x: %s\n",
+	       name, handle, strerror(-ret));
+	return NULL;
+    }
+
+    return radeon_bo_gem_create_from_handle(bufmgr,
+					    open_arg.handle, open_arg.size);
+}
+
+#define BUF_OUT_RING(x)	 do {			\
+		__head[__count++] = (x);				\
+	} while (0)
+
+void radeon_bufmgr_gem_emit_reloc(dri_bo *buf, struct radeon_relocs_info *reloc_info, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr;
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+	uint32_t *__head = head;
+	uint32_t __count = *count_p;
+	int i;
+	int index;
+	int have_reloc = -1;
+
+	for (i = 0; i < reloc_info->num_reloc; i++) {
+		if (reloc_info->buf[i * 4] == gem_bo->gem_handle) {
+			have_reloc = i;
+			break;
+		}
+	}
+
+	if (gem_bo->force_gtt && (read_domains & RADEON_GEM_DOMAIN_VRAM))
+		read_domains = RADEON_GEM_DOMAIN_GTT;
+
+	if (have_reloc != -1) {
+		uint32_t old_write, old_read;
+
+		index = have_reloc * 4;
+		old_read = reloc_info->buf[index + 1];
+		old_write = reloc_info->buf[index + 2];
+
+		/* error up for now - work out new domains - if we have a write */
+		if (write_domain && (old_read & write_domain)) {
+			reloc_info->buf[index + 1] = 0;
+			reloc_info->buf[index + 2] = write_domain;
+		} else if (read_domains & old_write) {
+			reloc_info->buf[index + 1] = 0;
+		} else {
+			/* rewrite the domains */
+			if (write_domain != old_write)
+				ErrorF("WRITE DOMAIN RELOC FAILURE 0x%x %d %d\n", gem_bo->gem_handle, write_domain, old_write);
+			if (read_domains != old_read)
+				ErrorF("READ DOMAIN RELOC FAILURE 0x%x %d %d\n", gem_bo->gem_handle, read_domains, old_read);
+		}
+		reloc_info->buf[index + 3]++;
+
+	} else {
+
+		if ((reloc_info->num_reloc + 1) * RADEON_RELOC_SIZE > reloc_info->size) {
+			/* resize the buffer */
+			reloc_info->size += getpagesize();
+			reloc_info->buf = xrealloc(reloc_info->buf, reloc_info->size);
+			if (!reloc_info->buf)
+				FatalError("failed to increase reloc buffer size\n");
+			reloc_info->max_bo = reloc_info->size / RADEON_RELOC_SIZE;
+			reloc_info->bo_list = xrealloc(reloc_info->bo_list, reloc_info->max_bo * (sizeof(dri_bo *)));
+		}
+
+		dri_bo_reference(buf);
+		gem_bo->touched = 1;
+
+		index = reloc_info->num_reloc * 4;
+		reloc_info->bo_list[index/4] = buf;
+		reloc_info->buf[index] = gem_bo->gem_handle;
+		reloc_info->buf[index + 1] = read_domains;
+		reloc_info->buf[index + 2] = write_domain;
+		reloc_info->buf[index + 3] = 1;
+		reloc_info->num_reloc++;
+	}
+
+	if (write_domain == RADEON_GEM_DOMAIN_VRAM) {
+		if (gem_bo->in_vram == 0)
+			DBG("bo_into vram: buf %d (%s) %d %d\n",
+			    gem_bo->gem_handle, gem_bo->name, read_domains, write_domain);
+		
+		gem_bo->in_vram = 1;
+	}
+
+	BUF_OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 0));
+	BUF_OUT_RING(index);
+	*count_p = __count;
+}
+
+static uint32_t radeon_gem_bufmgr_get_handle(dri_bo *buf)
+{
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+	
+	return gem_bo->gem_handle;
+}
+
+static int radeon_gem_bufmgr_check_aperture_space(struct radeon_space_check *bos, int num_bo)
+{
+	dri_bufmgr_gem *bufmgr_gem;
+ 	dri_bo_gem *gem_bo;
+	dri_bo *buf;
+	int this_op_read = 0, this_op_gart_write = 0, this_op_vram_write = 0;
+	uint32_t read_domains, write_domain;
+	int i;
+	/* check the totals for this operation */
+
+	if (num_bo == 0)
+		return 0;
+
+	bufmgr_gem = (dri_bufmgr_gem *)bos[0].buf->bufmgr;
+
+	/* prepare */
+	for (i = 0; i < num_bo; i++) {
+		buf = bos[i].buf;
+		gem_bo = (dri_bo_gem *)buf;
+
+		bos[i].new_accounted = 0;
+		read_domains = bos[i].read_domains;
+		write_domain = bos[i].write_domain;
+		
+		/* pinned bos don't count */
+		if (gem_bo->pinned)
+			continue;
+ 
+		/* already accounted this bo */
+		if (write_domain && (write_domain == gem_bo->space_accounted))
+			continue;
+
+		if (read_domains && ((read_domains << 16) == gem_bo->space_accounted))
+			continue;
+
+		if (gem_bo->space_accounted == 0) {
+			if (write_domain == RADEON_GEM_DOMAIN_VRAM)
+				this_op_vram_write += buf->size;
+			else if (write_domain == RADEON_GEM_DOMAIN_GTT)
+				this_op_gart_write += buf->size;
+			else
+				this_op_read += buf->size;
+			bos[i].new_accounted = (read_domains << 16) | write_domain;
+		} else {
+			uint16_t old_read, old_write;
+
+			old_read = gem_bo->space_accounted >> 16;
+			old_write = gem_bo->space_accounted & 0xffff;
+
+			if (write_domain && (old_read & write_domain)) {
+				bos[i].new_accounted = write_domain;
+				/* moving from read to a write domain */
+				if (write_domain == RADEON_GEM_DOMAIN_VRAM) {
+					this_op_read -= buf->size;
+					this_op_vram_write += buf->size;
+				} else if (write_domain == RADEON_GEM_DOMAIN_VRAM) {
+					this_op_read -= buf->size;
+					this_op_gart_write += buf->size;
+				}
+			} else if (read_domains & old_write) {
+				bos[i].new_accounted = gem_bo->space_accounted & 0xffff;
+			} else {
+				/* rewrite the domains */
+				if (write_domain != old_write)
+					ErrorF("WRITE DOMAIN RELOC FAILURE 0x%x %d %d\n", gem_bo->gem_handle, write_domain, old_write);
+				if (read_domains != old_read)
+					ErrorF("READ DOMAIN RELOC FAILURE 0x%x %d %d\n", gem_bo->gem_handle, read_domains, old_read);
+				return BUFMGR_SPACE_FLUSH;
+			}
+		}
+	}
+	
+	if (this_op_read < 0)
+		this_op_read = 0;
+
+	/* check sizes - operation first */
+	if ((this_op_read + this_op_gart_write > bufmgr_gem->gart_limit) ||
+	    (this_op_vram_write > bufmgr_gem->vram_limit)) {
+		return BUFMGR_SPACE_OP_TO_BIG;
+	}
+
+	if (((bufmgr_gem->vram_write_used + this_op_vram_write) > bufmgr_gem->vram_limit) ||
+	    ((bufmgr_gem->read_used + bufmgr_gem->gart_write_used + this_op_gart_write + this_op_read) > bufmgr_gem->gart_limit)) {
+		return BUFMGR_SPACE_FLUSH;
+	}
+
+	bufmgr_gem->gart_write_used += this_op_gart_write;
+	bufmgr_gem->vram_write_used += this_op_vram_write;
+	bufmgr_gem->read_used += this_op_read;
+	/* commit */
+	for (i = 0; i < num_bo; i++) {
+		buf = bos[i].buf;
+		gem_bo = (dri_bo_gem *)buf;
+		gem_bo->space_accounted = bos[i].new_accounted;
+	}
+
+	return BUFMGR_SPACE_OK;
+}
+
+/**
+ * Initializes the GEM buffer manager, which is just a thin wrapper
+ * around the GEM allocator.
+ *
+ * \param fd File descriptor of the opened DRM device.
+ * \param fence_type Driver-specific fence type used for fences with no flush.
+ * \param fence_type_flush Driver-specific fence type used for fences with a
+ *	  flush.
+ */
+dri_bufmgr *
+radeon_bufmgr_gem_init(int fd)
+{
+	dri_bufmgr_gem *bufmgr_gem;
+
+	bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
+	bufmgr_gem->fd = fd;
+
+	bufmgr_gem->bufmgr.bo_alloc = dri_gem_bo_alloc;
+	bufmgr_gem->bufmgr.bo_reference = dri_gem_bo_reference;
+	bufmgr_gem->bufmgr.bo_unreference = dri_gem_bo_unreference;
+	bufmgr_gem->bufmgr.bo_map = dri_gem_bo_map;
+	bufmgr_gem->bufmgr.bo_unmap = dri_gem_bo_unmap;
+	bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy;
+	//bufmgr_gem->bufmgr.bo_wait_rendering = radeon_bufmgr_gem_wait_rendering;
+	bufmgr_gem->radeon_bufmgr.emit_reloc = radeon_bufmgr_gem_emit_reloc;
+	bufmgr_gem->bufmgr.get_handle = radeon_gem_bufmgr_get_handle;
+	bufmgr_gem->bufmgr.check_aperture_space = radeon_gem_bufmgr_check_aperture_space;
+	bufmgr_gem->bufmgr.debug = 0;
+	return &bufmgr_gem->bufmgr;
+}
+
+
+void radeon_gem_bufmgr_post_submit(dri_bufmgr *bufmgr, struct radeon_relocs_info *reloc_info, int error)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
+	struct _dri_bo_gem *trav, *prev;
+	int i;
+	
+	if (error) {
+		ErrorF("bufmgr: last submission : r:%d vs g:%d w:%d vs v:%d\n",
+		       bufmgr_gem->read_used, bufmgr_gem->gart_limit, 
+		       bufmgr_gem->vram_write_used, bufmgr_gem->vram_limit);
+	}
+
+	if (!bufmgr_gem->bo_list)
+		return;
+
+	for (i = 0; i < reloc_info->num_reloc; i++) {
+		trav = (dri_bo_gem *)reloc_info->bo_list[i];
+
+		trav->space_accounted = 0;
+		dri_bo_unreference(&trav->bo);
+	}
+
+	bufmgr_gem->read_used = 0;
+	bufmgr_gem->vram_write_used = 0;
+	bufmgr_gem->gart_write_used = 0;
+	
+}
+
+
+
+void radeon_bufmgr_emit_reloc(dri_bo *buf, struct radeon_relocs_info *relocs, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain)
+{
+	struct radeon_bufmgr *radeon_bufmgr;
+
+	radeon_bufmgr = (struct radeon_bufmgr *)(buf->bufmgr + 1);
+	radeon_bufmgr->emit_reloc(buf, relocs, head, count_p, read_domains, write_domain);
+}
+
+/* if the buffer is references by the current IB we need to flush the IB */
+int radeon_bufmgr_gem_has_references(dri_bo *buf)
+{
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+
+	return gem_bo->touched;
+}
+
+void radeon_bufmgr_gem_set_limit(dri_bufmgr *bufmgr, uint32_t domain, uint32_t limit)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
+
+	if (domain == RADEON_GEM_DOMAIN_VRAM)
+	    bufmgr_gem->vram_limit = limit;
+	else
+	    bufmgr_gem->gart_limit = limit;
+
+}
+
+void radeon_bufmgr_gem_force_gtt(dri_bo *buf)
+{
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+
+	if (!gem_bo->pinned && !gem_bo->force_gtt)
+	    gem_bo->force_gtt = 1;
+}
+
+int radeon_bufmgr_gem_in_vram(dri_bo *buf)
+{
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+	return gem_bo->in_vram;
+}
+
+int radeon_bo_gem_name_buffer(dri_bo *bo, uint32_t *name)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
+	dri_bo_gem *gem_bo = (dri_bo_gem *)bo;
+    struct drm_gem_flink flink;
+    int r;
+
+    flink.handle = gem_bo->gem_handle;
+	fprintf(stderr,"naming attemp %d\n", flink.handle);
+    r = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink);
+    if (r) {
+        DBG("[drm] failed to name buffer %d\n", -errno);
+        return r;
+    }
+	fprintf(stderr,"naming %d with %d\n", flink.handle, flink.name);
+    *name = flink.name;
+    return 0;
+}
diff -up /dev/null xf86-video-ati-6.12.2/src/radeon_bufmgr_gem.h
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/radeon_bufmgr_gem.h	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,16 @@
+#ifndef RADEON_BUFMGR_GEM_H
+#define RADEON_BUFMGR_GEM_H
+
+#include "radeon_dri_bufmgr.h"
+
+
+extern void radeon_bufmgr_gem_wait_rendering(dri_bo *bo);
+void radeon_bufmgr_gem_emit_reloc(dri_bo *bo, struct radeon_relocs_info *reloc_info, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain);
+void radeon_gem_bufmgr_post_submit(dri_bufmgr *bufmgr, struct radeon_relocs_info *reloc_info, int error);
+uint32_t radeon_bufmgr_get_handle(dri_bo *buf);
+int radeon_bufmgr_gem_has_references(dri_bo *buf);
+int radeon_bufmgr_gem_force_gtt(dri_bo *buf);
+void radeon_bufmgr_gem_set_limit(dri_bufmgr *bufmgr, uint32_t domain, uint32_t limit);
+int radeon_bufmgr_gem_in_vram(dri_bo *buf);
+int radeon_bo_gem_name_buffer(dri_bo *bo, uint32_t *name);
+#endif
diff -up /dev/null xf86-video-ati-6.12.2/src/radeon_bufmgr.h
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/radeon_bufmgr.h	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,25 @@
+/**
+ * @file intel_bufmgr.h
+ *
+ * Public definitions of Intel-specific bufmgr functions.
+ */
+
+#ifndef RADEON_BUFMGR_H
+#define RADEON_BUFMGR_H
+
+#include "radeon_dri_bufmgr.h"
+
+struct radeon_bufmgr {
+  void (*emit_reloc)(dri_bo *buf, struct radeon_relocs_info *relocs, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain);
+};
+
+dri_bufmgr *radeon_bufmgr_gem_init(int fd);
+dri_bo *radeon_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name,
+				       unsigned int handle);
+dri_bo *radeon_bo_gem_create_from_handle(dri_bufmgr *bufmgr,
+					 uint32_t handle, unsigned long size);
+
+void radeon_bufmgr_emit_reloc(dri_bo *buf, struct radeon_relocs_info *relocs, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain);
+
+void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr);
+#endif
diff -up xf86-video-ati-6.12.2/src/radeon_commonfuncs.c.modeset xf86-video-ati-6.12.2/src/radeon_commonfuncs.c
--- xf86-video-ati-6.12.2/src/radeon_commonfuncs.c.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_commonfuncs.c	2009-05-21 11:05:44.000000000 -0400
@@ -62,12 +62,15 @@ static void FUNC_NAME(RADEONInit3DEngine
 	info->accel_state->texW[1] = info->accel_state->texH[1] = 1;
 
     if (IS_R300_3D || IS_R500_3D) {
+	int size;
 
-	BEGIN_ACCEL(3);
-	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
-	OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
-	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
-	FINISH_ACCEL();
+	if (!info->new_cs) {
+	    BEGIN_ACCEL(3);
+	    OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
+	    OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
+	    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
+	    FINISH_ACCEL();
+	}
 
 	gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
 
@@ -79,10 +82,12 @@ static void FUNC_NAME(RADEONInit3DEngine
 	case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
 	}
 
-	BEGIN_ACCEL(5);
+	size = (info->ChipFamily >= CHIP_FAMILY_R420) ? 5 : 4;
+	BEGIN_ACCEL(size);
 	OUT_ACCEL_REG(R300_GB_TILE_CONFIG, gb_tile_config);
 	OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
-	OUT_ACCEL_REG(R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG);
+	if (info->ChipFamily >= CHIP_FAMILY_R420)
+	    OUT_ACCEL_REG(R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG);
 	OUT_ACCEL_REG(R300_GB_SELECT, 0);
 	OUT_ACCEL_REG(R300_GB_ENABLE, 0);
 	FINISH_ACCEL();
@@ -626,6 +631,39 @@ static void FUNC_NAME(RADEONInit3DEngine
 
 }
 
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+void drmmode_wait_for_vline(ScrnInfoPtr pScrn, PixmapPtr pPix,
+			    int crtc, int start, int stop)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr  xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    uint32_t offset;
+    drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[crtc]->driver_private;
+    ACCEL_PREAMBLE();
+
+    BEGIN_ACCEL(3);
+
+    if (IS_AVIVO_VARIANT) {
+	uint32_t reg = AVIVO_D1MODE_VLINE_START_END; /* this is just a marker */
+	OUT_ACCEL_REG(reg,
+		      ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
+		       (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
+		       AVIVO_D1MODE_VLINE_INV));
+    } else {
+	OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE, /* another placeholder */
+		      ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+		      (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
+		      RADEON_CRTC_GUI_TRIG_VLINE_INV));
+    }
+    OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
+				      RADEON_ENG_DISPLAY_SELECT_CRTC0));
+
+    OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 0));
+    OUT_RING(drmmode_crtc->mode_crtc->crtc_id);
+    FINISH_ACCEL();
+}
+#endif
+
 /* inserts a wait for vline in the command stream */
 void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
 	int crtc, int start, int stop)
@@ -644,16 +682,19 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnI
     if (!xf86_config->crtc[crtc]->enabled)
 	return;
 
+    if (info->drm_mode_setting) {
+        if (pPix != pScrn->pScreen->GetScreenPixmap(pScrn->pScreen))
+	    return;
+    } else {
+        if (info->useEXA)
 #ifdef USE_EXA
-    if (info->useEXA)
-	offset = exaGetPixmapOffset(pPix);
-    else
+           offset = exaGetPixmapOffset(pPix);
+        else
 #endif
-	offset = pPix->devPrivate.ptr - info->FB;
-
-    /* if drawing to front buffer */
-    if (offset != 0)
-	return;
+	    offset = pPix->devPrivate.ptr - info->FB;
+        if (offset != 0)
+            return;
+    }
 
     start = max(start, 0);
     stop = min(stop, xf86_config->crtc[crtc]->mode.VDisplay);
@@ -661,6 +702,13 @@ void FUNC_NAME(RADEONWaitForVLine)(ScrnI
     if (start > xf86_config->crtc[crtc]->mode.VDisplay)
 	return;
 
+#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
+    if (info->drm_mode_setting) {
+	drmmode_wait_for_vline(pScrn, pPix, crtc, start, stop);
+	return;
+    }
+#endif
+
     BEGIN_ACCEL(2);
 
     if (IS_AVIVO_VARIANT) {
@@ -712,7 +760,7 @@ void FUNC_NAME(RADEONWaitForIdle)(ScrnIn
 
 #ifdef ACCEL_CP
     /* Make sure the CP is idle first */
-    if (info->cp->CPStarted) {
+    if (info->cp->CPStarted || info->drm_mode_setting) {
 	int  ret;
 
 	FLUSH_RING();
diff -up xf86-video-ati-6.12.2/src/radeon_cursor.c.modeset xf86-video-ati-6.12.2/src/radeon_cursor.c
--- xf86-video-ati-6.12.2/src/radeon_cursor.c.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_cursor.c	2009-05-21 11:01:45.000000000 -0400
@@ -202,6 +202,7 @@ radeon_crtc_set_cursor_position (xf86Crt
     int xorigin = 0, yorigin = 0;
     int stride = 256;
     DisplayModePtr mode = &crtc->mode;
+    uint32_t offset;
 
     if (x < 0)                        xorigin = -x+1;
     if (y < 0)                        yorigin = -y+1;
@@ -255,8 +256,9 @@ radeon_crtc_set_cursor_position (xf86Crt
 					       | (yorigin ? 0 : y)));
 	    RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n",
 			  radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp));
+	    offset = radeon_crtc->cursor_offset + pScrn->fbOffset;
 	    OUTREG(RADEON_CUR_OFFSET,
-		   radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride);
+		   offset + yorigin * stride);
 	} else if (crtc_id == 1) {
 	    OUTREG(RADEON_CUR2_HORZ_VERT_OFF,  (RADEON_CUR2_LOCK
 						| (xorigin << 16)
@@ -266,8 +268,9 @@ radeon_crtc_set_cursor_position (xf86Crt
 						| (yorigin ? 0 : y)));
 	    RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n",
 			  radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp));
+	    offset = radeon_crtc->cursor_offset + pScrn->fbOffset;
 	    OUTREG(RADEON_CUR2_OFFSET,
-		   radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride);
+		   offset + yorigin * stride);
 	}
     }
 }
@@ -321,10 +324,12 @@ radeon_crtc_load_cursor_argb (xf86CrtcPt
     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
     RADEONInfoPtr  info = RADEONPTR(pScrn);
     CURSOR_SWAPPING_DECL_MMIO
-    uint32_t *d = (uint32_t *)(pointer)(info->FB + radeon_crtc->cursor_offset);
+    uint32_t *d;
 
     RADEONCTRACE(("RADEONLoadCursorARGB\n"));
 
+    d = (uint32_t *)(pointer)(info->FB + radeon_crtc->cursor_offset);
+
     info->cursor_argb = TRUE;
 
     CURSOR_SWAPPING_START();
diff -up /dev/null xf86-video-ati-6.12.2/src/radeon_dri2.c
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/radeon_dri2.c	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2008 Kristian Høgsberg 
+ * Copyright 2008 Jérôme Glisse
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "radeon.h"
+#include "radeon_dri2.h"
+#include "radeon_version.h"
+
+#ifdef DRI2
+
+struct dri2_buffer_priv {
+    PixmapPtr   pixmap;
+};
+
+
+static DRI2BufferPtr
+radeon_dri2_create_buffers(DrawablePtr drawable,
+                           unsigned int *attachments,
+                           int count)
+{
+    ScreenPtr pScreen = drawable->pScreen;
+    DRI2BufferPtr buffers;
+    struct dri2_buffer_priv *privates;
+    PixmapPtr pixmap, depth_pixmap;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int i, r;
+
+    buffers = xcalloc(count, sizeof *buffers);
+    if (buffers == NULL) {
+        return NULL;
+    }
+    privates = xcalloc(count, sizeof(struct dri2_buffer_priv));
+    if (privates == NULL) {
+        xfree(buffers);
+        return NULL;
+    }
+
+    depth_pixmap = NULL;
+    for (i = 0; i < count; i++) {
+        if (attachments[i] == DRI2BufferFrontLeft) {
+            if (drawable->type == DRAWABLE_PIXMAP) {
+                pixmap = (Pixmap*)drawable;
+            } else {
+                pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
+            }
+            pixmap->refcnt++;
+        } else if (attachments[i] == DRI2BufferStencil && depth_pixmap) {
+            pixmap = depth_pixmap;
+            pixmap->refcnt++;
+        } else {
+            pixmap = (*pScreen->CreatePixmap)(pScreen,
+                                              drawable->width,
+                                              drawable->height,
+                                              drawable->depth,
+                                              0);
+        }
+
+        if (attachments[i] == DRI2BufferDepth) {
+            depth_pixmap = pixmap;
+        }
+        driver_priv = exaGetPixmapDriverPrivate(pixmap);
+        r = radeon_bo_gem_name_buffer(driver_priv->bo, &buffers[i].name);
+        if (r) {
+            /* FIXME: cleanup */
+            fprintf(stderr, "flink error: %d %s\n", r, strerror(r));
+            xfree(buffers);
+            xfree(privates);
+            return NULL;
+        }
+        buffers[i].attachment = attachments[i];
+        buffers[i].pitch = pixmap->devKind;
+        buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8;
+        buffers[i].driverPrivate = &privates[i];
+        buffers[i].flags = 0; /* not tiled */
+        privates[i].pixmap = pixmap;
+    }
+    return buffers;
+}
+
+static void
+radeon_dri2_destroy_buffers(DrawablePtr drawable,
+                            DRI2BufferPtr buffers,
+                            int count)
+{
+    ScreenPtr pScreen = drawable->pScreen;
+    struct dri2_buffer_priv *private;
+    int i;
+
+    for (i = 0; i < count; i++) {
+        private = buffers[i].driverPrivate;
+        (*pScreen->DestroyPixmap)(private->pixmap);
+    }
+    if (buffers) {
+        xfree(buffers[0].driverPrivate);
+        xfree(buffers);
+    }
+}
+
+static void
+radeon_dri2_copy_region(DrawablePtr drawable,
+                        RegionPtr region,
+                        DRI2BufferPtr dest_buffer,
+                        DRI2BufferPtr src_buffer)
+{
+    struct dri2_buffer_priv *private = src_buffer->driverPrivate;
+    ScreenPtr pScreen = drawable->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    PixmapPtr pixmap = private->pixmap;
+    RegionPtr copy_clip;
+    GCPtr gc;
+
+    gc = GetScratchGC(drawable->depth, pScreen);
+    copy_clip = REGION_CREATE(pScreen, NULL, 0);
+    REGION_COPY(pScreen, copy_clip, region);
+    (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0);
+    ValidateGC(drawable, gc);
+    (*gc->ops->CopyArea)(&pixmap->drawable, drawable, gc,
+                         0, 0, drawable->width, drawable->height, 0, 0);
+    FreeScratchGC(gc);
+    RADEONCPReleaseIndirect(pScrn);
+}
+
+Bool
+radeon_dri2_screen_init(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    DRI2InfoRec dri2_info;
+    int fd;
+    char *bus_id;
+    char *tmp_bus_id;
+    int cmp;
+    int i;
+
+    if (!info->useEXA) {
+        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requires EXA\n");
+        return FALSE;
+    }
+
+    /* The whole drmOpen thing is a fiasco and we need to find a way
+     * back to just using open(2).  For now, however, lets just make
+     * things worse with even more ad hoc directory walking code to
+     * discover the device file name. */
+    bus_id = DRICreatePCIBusID(info->PciInfo);
+    for (i = 0; i < DRM_MAX_MINOR; i++) {
+        sprintf(info->dri2.device_name, DRM_DEV_NAME, DRM_DIR_NAME, i);
+        fd = open(info->dri2.device_name, O_RDWR);
+        if (fd < 0)
+            continue;
+
+        tmp_bus_id = drmGetBusid(fd);
+        close(fd);
+        if (tmp_bus_id == NULL)
+            continue;
+
+        cmp = strcmp(tmp_bus_id, bus_id);
+        drmFree(tmp_bus_id);
+        if (cmp == 0)
+            break;
+    }
+    xfree(bus_id);
+
+    if (i == DRM_MAX_MINOR) {
+        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+                   "DRI2: failed to open drm device\n");
+        return FALSE;
+    }
+
+    if ( (info->ChipFamily >= CHIP_FAMILY_R300) ) {
+        dri2_info.driverName = R300_DRIVER_NAME;
+    } else if ( info->ChipFamily >= CHIP_FAMILY_R200 ) {
+        dri2_info.driverName = R200_DRIVER_NAME;
+    } else {
+        dri2_info.driverName = RADEON_DRIVER_NAME;
+    }
+    dri2_info.fd = info->dri2.drm_fd;
+    dri2_info.deviceName = info->dri2.device_name;
+    dri2_info.version = 1;
+    dri2_info.CreateBuffers = radeon_dri2_create_buffers;
+    dri2_info.DestroyBuffers = radeon_dri2_destroy_buffers;
+    dri2_info.CopyRegion = radeon_dri2_copy_region;
+    info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info);
+    return info->dri2.enabled;
+}
+
+void
+radeon_dri2_close_screen(ScreenPtr pScreen)
+{
+    DRI2CloseScreen(pScreen);
+}
+
+#endif
diff -up /dev/null xf86-video-ati-6.12.2/src/radeon_dri2.h
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/radeon_dri2.h	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 Jerome Glisse
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifndef RADEON_DRI2_H
+#define RADEON_DRI2_H
+
+struct radeon_dri2 {
+    int         drm_fd;
+    Bool        enabled;
+    char        device_name[64];
+};
+
+#ifdef DRI2
+#include "dri2.h"
+Bool radeon_dri2_screen_init(ScreenPtr pScreen);
+void radeon_dri2_close_screen(ScreenPtr pScreen);
+#endif
+
+#endif
diff -up /dev/null xf86-video-ati-6.12.2/src/radeon_dri_bufmgr.c
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/radeon_dri_bufmgr.c	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,177 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "radeon_dri_bufmgr.h"
+
+/** @file dri_bufmgr.c
+ *
+ * Convenience functions for buffer management methods.
+ */
+
+dri_bo *
+dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size,
+	     unsigned int alignment, uint64_t location_mask)
+{
+   return bufmgr->bo_alloc(bufmgr, name, size, alignment, location_mask);
+}
+
+dri_bo *
+dri_bo_alloc_static(dri_bufmgr *bufmgr, const char *name, unsigned long offset,
+		    unsigned long size, void *virtual,
+		    uint64_t location_mask)
+{
+   return bufmgr->bo_alloc_static(bufmgr, name, offset, size, virtual,
+				  location_mask);
+}
+
+void
+dri_bo_reference(dri_bo *bo)
+{
+   bo->bufmgr->bo_reference(bo);
+}
+
+void
+dri_bo_unreference(dri_bo *bo)
+{
+   if (bo == NULL)
+      return;
+
+   bo->bufmgr->bo_unreference(bo);
+}
+
+int
+dri_bo_map(dri_bo *buf, int write_enable)
+{
+   return buf->bufmgr->bo_map(buf, write_enable);
+}
+
+int
+dri_bo_unmap(dri_bo *buf)
+{
+   return buf->bufmgr->bo_unmap(buf);
+}
+
+void
+dri_fence_wait(dri_fence *fence)
+{
+   fence->bufmgr->fence_wait(fence);
+}
+
+void
+dri_fence_reference(dri_fence *fence)
+{
+   fence->bufmgr->fence_reference(fence);
+}
+
+void
+dri_fence_unreference(dri_fence *fence)
+{
+   if (fence == NULL)
+      return;
+
+   fence->bufmgr->fence_unreference(fence);
+}
+
+void
+dri_bo_subdata(dri_bo *bo, unsigned long offset,
+	       unsigned long size, const void *data)
+{
+   if (size == 0 || data == NULL)
+      return;
+
+   dri_bo_map(bo, 1);
+   memcpy((unsigned char *)bo->virtual + offset, data, size);
+   dri_bo_unmap(bo);
+}
+
+void
+dri_bo_get_subdata(dri_bo *bo, unsigned long offset,
+		   unsigned long size, void *data)
+{
+   if (size == 0 || data == NULL)
+      return;
+
+   dri_bo_map(bo, 0);
+   memcpy(data, (unsigned char *)bo->virtual + offset, size);
+   dri_bo_unmap(bo);
+}
+
+void
+dri_bufmgr_destroy(dri_bufmgr *bufmgr)
+{
+   bufmgr->destroy(bufmgr);
+}
+
+
+int dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, uint32_t delta,
+		    uint32_t offset, dri_bo *target_buf)
+{
+   return reloc_buf->bufmgr->emit_reloc(reloc_buf, flags, delta, offset, target_buf);
+}
+
+void *dri_process_relocs(dri_bo *batch_buf, uint32_t *count)
+{
+   return batch_buf->bufmgr->process_relocs(batch_buf, count);
+}
+
+void dri_post_submit(dri_bo *batch_buf, dri_fence **last_fence)
+{
+   batch_buf->bufmgr->post_submit(batch_buf, last_fence);
+}
+
+void
+dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug)
+{
+   bufmgr->debug = enable_debug;
+}
+
+int
+dri_bufmgr_check_aperture_space(struct radeon_space_check *bos, int num_bo)
+{
+  if (num_bo == 0)
+    return BUFMGR_SPACE_OK;
+
+  return bos[0].buf->bufmgr->check_aperture_space(bos, num_bo);
+}
+
+int dri_bo_pin(dri_bo *bo, int domain)
+{
+    return bo->bufmgr->pin(bo, domain);
+}
+
+void dri_bo_unpin(dri_bo *bo)
+{
+    bo->bufmgr->unpin(bo);
+}
+
+uint32_t dri_bo_get_handle(dri_bo *bo)
+{
+    return bo->bufmgr->get_handle(bo);
+}
diff -up /dev/null xf86-video-ati-6.12.2/src/radeon_dri_bufmgr.h
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/radeon_dri_bufmgr.h	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,291 @@
+/**************************************************************************
+ * 
+ * Copyright © 2007 Intel Corporation
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * 
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ *	    Eric Anholt <eric@anholt.net>
+ */
+
+#ifndef _DRI_BUFMGR_H_
+#define _DRI_BUFMGR_H_
+#include <xf86drm.h>
+
+typedef struct _dri_bufmgr dri_bufmgr;
+typedef struct _dri_bo dri_bo;
+typedef struct _dri_fence dri_fence;
+
+#define BUFMGR_SPACE_OK 0
+#define BUFMGR_SPACE_OP_TO_BIG 1
+#define BUFMGR_SPACE_FLUSH 2
+struct radeon_space_check {
+	dri_bo *buf;
+	uint32_t read_domains;
+	uint32_t write_domain;
+	uint32_t new_accounted;
+};
+
+/* reloc format */
+/* gem handle, read_domains, write_domain, reloc_count */
+#define RADEON_RELOC_SIZE 4
+struct radeon_relocs_info {
+    uint32_t *buf;
+    dri_bo **bo_list;
+    int size;
+    int max_bo;
+    int num_reloc;
+};
+
+struct _dri_bo {
+   /** Size in bytes of the buffer object. */
+   unsigned long size;
+   /**
+    * Card virtual address (offset from the beginning of the aperture) for the
+    * object.  Only valid while validated.
+    */
+   unsigned long offset;
+   /**
+    * Virtual address for accessing the buffer data.  Only valid while mapped.
+    */
+   void *virtual;
+   /** Buffer manager context associated with this buffer object */
+   dri_bufmgr *bufmgr;
+};
+
+struct _dri_fence {
+   /**
+    * This is an ORed mask of DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE, and
+    * DRM_FLAG_EXE indicating the operations associated with this fence.
+    *
+    * It is constant for the life of the fence object.
+    */
+   unsigned int type;
+   /** Buffer manager context associated with this fence */
+   dri_bufmgr *bufmgr;
+};
+
+/**
+ * Context for a buffer manager instance.
+ *
+ * Contains public methods followed by private storage for the buffer manager.
+ */
+struct _dri_bufmgr {
+   /**
+    * Allocate a buffer object.
+    *
+    * Buffer objects are not necessarily initially mapped into CPU virtual
+    * address space or graphics device aperture.  They must be mapped using
+    * bo_map() to be used by the CPU, and validated for use using bo_validate()
+    * to be used from the graphics device.
+    */
+   dri_bo *(*bo_alloc)(dri_bufmgr *bufmgr_ctx, const char *name,
+		       unsigned long size, unsigned int alignment,
+		       uint64_t location_mask);
+
+   /**
+    * Allocates a buffer object for a static allocation.
+    *
+    * Static allocations are ones such as the front buffer that are offered by
+    * the X Server, which are never evicted and never moved.
+    */
+   dri_bo *(*bo_alloc_static)(dri_bufmgr *bufmgr_ctx, const char *name,
+			      unsigned long offset, unsigned long size,
+			      void *virtual, uint64_t location_mask);
+
+   /** Takes a reference on a buffer object */
+   void (*bo_reference)(dri_bo *bo);
+
+   /**
+    * Releases a reference on a buffer object, freeing the data if
+    * rerefences remain.
+    */
+   void (*bo_unreference)(dri_bo *bo);
+
+   /**
+    * Maps the buffer into userspace.
+    *
+    * This function will block waiting for any existing fence on the buffer to
+    * clear, first.  The resulting mapping is available at buf->virtual.
+\    */
+   int (*bo_map)(dri_bo *buf, int write_enable);
+
+   /** Reduces the refcount on the userspace mapping of the buffer object. */
+   int (*bo_unmap)(dri_bo *buf);
+
+   /** Takes a reference on a fence object */
+   void (*fence_reference)(dri_fence *fence);
+
+   /**
+    * Releases a reference on a fence object, freeing the data if
+    * rerefences remain.
+    */
+   void (*fence_unreference)(dri_fence *fence);
+
+   /**
+    * Blocks until the given fence is signaled.
+    */
+   void (*fence_wait)(dri_fence *fence);
+
+   /**
+    * Tears down the buffer manager instance.
+    */
+   void (*destroy)(dri_bufmgr *bufmgr);
+
+   /**
+    * Add relocation entry in reloc_buf, which will be updated with the
+    * target buffer's real offset on on command submission.
+    *
+    * Relocations remain in place for the lifetime of the buffer object.
+    *
+    * \param reloc_buf Buffer to write the relocation into.
+    * \param flags BO flags to be used in validating the target buffer.
+    *	     Applicable flags include:
+    *	     - DRM_BO_FLAG_READ: The buffer will be read in the process of
+    *	       command execution.
+    *	     - DRM_BO_FLAG_WRITE: The buffer will be written in the process of
+    *	       command execution.
+    *	     - DRM_BO_FLAG_MEM_TT: The buffer should be validated in TT memory.
+    *	     - DRM_BO_FLAG_MEM_VRAM: The buffer should be validated in video
+    *	       memory.
+    * \param delta Constant value to be added to the relocation target's offset.
+    * \param offset Byte offset within batch_buf of the relocated pointer.
+    * \param target Buffer whose offset should be written into the relocation
+    *	     entry.
+    */
+   int (*emit_reloc)(dri_bo *reloc_buf, uint64_t flags, uint32_t delta,
+		      uint32_t offset, dri_bo *target);
+
+   /**
+    * Processes the relocations, either in userland or by converting the list
+    * for use in batchbuffer submission.
+    *
+    * Kernel-based implementations will return a pointer to the arguments
+    * to be handed with batchbuffer submission to the kernel.  The userland
+    * implementation performs the buffer validation and emits relocations
+    * into them the appopriate order.
+    *
+    * \param batch_buf buffer at the root of the tree of relocations
+    * \param count returns the number of buffers validated.
+    * \return relocation record for use in command submission.
+    * */
+   void *(*process_relocs)(dri_bo *batch_buf, uint32_t *count);
+
+   void (*post_submit)(dri_bo *batch_buf, dri_fence **fence);
+
+   int (*check_aperture_space)(struct radeon_space_check *bos, int num_bo);
+
+   int (*pin)(dri_bo *bo, int domain);
+   void (*unpin)(dri_bo *bo);
+
+   uint32_t (*get_handle)(dri_bo *bo);
+   int debug; /**< Enables verbose debugging printouts */
+};
+
+dri_bo *dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size,
+		     unsigned int alignment, uint64_t location_mask);
+dri_bo *dri_bo_alloc_static(dri_bufmgr *bufmgr, const char *name,
+			    unsigned long offset, unsigned long size,
+			    void *virtual, uint64_t location_mask);
+void dri_bo_reference(dri_bo *bo);
+void dri_bo_unreference(dri_bo *bo);
+int dri_bo_map(dri_bo *buf, int write_enable);
+int dri_bo_unmap(dri_bo *buf);
+void dri_fence_wait(dri_fence *fence);
+void dri_fence_reference(dri_fence *fence);
+void dri_fence_unreference(dri_fence *fence);
+
+void dri_bo_subdata(dri_bo *bo, unsigned long offset,
+		    unsigned long size, const void *data);
+void dri_bo_get_subdata(dri_bo *bo, unsigned long offset,
+			unsigned long size, void *data);
+
+void dri_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr);
+dri_bufmgr *dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual,
+				 unsigned long size,
+				 unsigned int (*fence_emit)(void *private),
+				 int (*fence_wait)(void *private,
+						   unsigned int cookie),
+				 void *driver_priv);
+void dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug);
+void dri_bo_fake_disable_backing_store(dri_bo *bo,
+				       void (*invalidate_cb)(dri_bo *bo,
+							     void *ptr),
+				       void *ptr);
+void dri_bufmgr_destroy(dri_bufmgr *bufmgr);
+
+int dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, uint32_t delta,
+		   uint32_t offset, dri_bo *target_buf);
+void *dri_process_relocs(dri_bo *batch_buf, uint32_t *count);
+void dri_post_process_relocs(dri_bo *batch_buf);
+void dri_post_submit(dri_bo *batch_buf, dri_fence **last_fence);
+int dri_bufmgr_check_aperture_space(struct radeon_space_check *bos, int num_bo);
+
+int dri_bo_pin(dri_bo *bo, int domain);
+void dri_bo_unpin(dri_bo *bo);
+
+uint32_t dri_bo_get_handle(dri_bo *bo);
+
+#ifndef TTM_API
+/* reuse some TTM API */
+
+#define DRM_BO_MEM_LOCAL 0
+#define DRM_BO_MEM_TT 1
+#define DRM_BO_MEM_VRAM 2
+#define DRM_BO_MEM_PRIV0 3
+#define DRM_BO_MEM_PRIV1 4
+#define DRM_BO_MEM_PRIV2 5
+#define DRM_BO_MEM_PRIV3 6
+#define DRM_BO_MEM_PRIV4 7
+
+#define DRM_BO_FLAG_READ        (1ULL << 0)
+#define DRM_BO_FLAG_WRITE       (1ULL << 1)
+#define DRM_BO_FLAG_EXE         (1ULL << 2)
+#define DRM_BO_MASK_ACCESS	(DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE)
+#define DRM_BO_FLAG_NO_EVICT    (1ULL << 4)
+
+#define DRM_BO_FLAG_MAPPABLE    (1ULL << 5)
+#define DRM_BO_FLAG_SHAREABLE   (1ULL << 6)
+
+#define DRM_BO_FLAG_CACHED      (1ULL << 7)
+
+#define DRM_BO_FLAG_NO_MOVE     (1ULL << 8)
+#define DRM_BO_FLAG_CACHED_MAPPED    (1ULL << 19)
+#define DRM_BO_FLAG_FORCE_CACHING  (1ULL << 13)
+#define DRM_BO_FLAG_FORCE_MAPPABLE (1ULL << 14)
+#define DRM_BO_FLAG_TILE           (1ULL << 15)
+
+#define DRM_BO_FLAG_MEM_LOCAL  (1ULL << 24)
+#define DRM_BO_FLAG_MEM_TT     (1ULL << 25)
+#define DRM_BO_FLAG_MEM_VRAM   (1ULL << 26)
+
+#define DRM_BO_MASK_MEM         0x00000000FF000000ULL
+
+#define DRM_FENCE_TYPE_EXE                 0x00000001
+#endif
+
+#endif
diff -up xf86-video-ati-6.12.2/src/radeon_dri.c.modeset xf86-video-ati-6.12.2/src/radeon_dri.c
--- xf86-video-ati-6.12.2/src/radeon_dri.c.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_dri.c	2009-05-21 11:01:45.000000000 -0400
@@ -40,6 +40,8 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <errno.h>
+#include <sys/ioctl.h>
 
 				/* Driver data structures */
 #include "radeon.h"
@@ -53,6 +55,8 @@
 
 #include "atipciids.h"
 
+#include "radeon_drm.h"
+
 				/* X and server generic header files */
 #include "xf86.h"
 #include "xf86PciInfo.h"
@@ -70,16 +74,31 @@ static size_t radeon_drm_page_size;
 extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs,
 				void **configprivs);
 
+#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
+#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
+
 static void RADEONDRITransitionTo2d(ScreenPtr pScreen);
 static void RADEONDRITransitionTo3d(ScreenPtr pScreen);
 static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen);
 static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen);
 
+static Bool radeon_dri_gart_init(ScreenPtr pScreen);
+
 #ifdef DAMAGE
 static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, RegionPtr pReg);
 
-#if (DRIINFO_MAJOR_VERSION > 5 ||		\
-     (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1))
+#if DRI_SUPPORTS_CLIP_NOTIFY
 static void RADEONDRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num);
 #endif
 #endif
@@ -352,6 +371,81 @@ static void RADEONDestroyContext(ScreenP
 #endif
 }
 
+/* so we need to add a frontbuffer map no matter what */
+#define ROUND_TO(x, y)                 (((x) + (y) - 1) / (y) * (y))
+#define ROUND_TO_PAGE(x)               ROUND_TO((x), radeon_drm_page_size)
+
+static void
+radeon_update_screen_private(ScrnInfoPtr pScrn, drm_radeon_sarea_t * sarea)
+{
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    RADEONDRIPtr pRADEONDRI;
+
+    pRADEONDRI                    = (RADEONDRIPtr)info->dri->pDRIInfo->devPrivate;
+    info->dri->pDRIInfo->frameBufferPhysicalAddress = (char *) info->LinearAddr;
+    info->dri->pDRIInfo->frameBufferStride = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
+    info->dri->pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes);
+#if DRI_DRIVER_FRAMEBUFFER_MAP
+    info->dri->pDRIInfo->hFrameBuffer = info->fb_map_handle;
+#endif
+}
+
+static Bool
+radeon_update_dri_mappings(ScrnInfoPtr pScrn, drm_radeon_sarea_t * sarea)
+{
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    uint32_t fb_addr, fb_size;
+    int ret;
+
+    if (!info->drm_mm)
+	return TRUE;
+
+
+    fb_addr = info->mm.front_buffer->offset + info->LinearAddr;
+    fb_size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes);
+
+    if (info->fb_map_handle) {
+	drmRmMap(info->dri->drmFD, info->fb_map_handle);
+	info->fb_map_handle = 0;
+    }
+	
+    ret = drmAddMap(info->dri->drmFD, fb_addr, fb_size, DRM_FRAME_BUFFER, 0,
+		    &info->fb_map_handle);
+
+    ErrorF("adding fb map from %x for %x ret %d %x\n", fb_addr, fb_size, ret, info->fb_map_handle);
+
+    if (ret < 0)
+	return FALSE;
+
+    return TRUE;
+}
+
+Bool radeon_update_dri_buffers(ScreenPtr pScreen)
+{
+    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    Bool success;
+    drm_radeon_sarea_t *sarea;
+
+    if (info->ChipFamily >= CHIP_FAMILY_R600)
+	return TRUE;
+
+    if (!info->drm_mm)
+	return TRUE;
+
+    if (info->dri2.enabled)
+	return TRUE;
+
+    sarea = DRIGetSAREAPrivate(pScreen);
+    success = radeon_update_dri_mappings(pScrn, sarea);
+
+    if (!success)
+	return FALSE;
+
+    radeon_update_screen_private(pScrn, sarea);
+    return TRUE;
+}
+
 /* Called when the X server is woken up to allow the last client's
  * context to be saved and the X server's context to be loaded.  This is
  * not necessary for the Radeon since the client detects when it's
@@ -701,25 +795,35 @@ static void RADEONDRIInitGARTValues(RADE
 
     info->dri->gartOffset = 0;
 
-				/* Initialize the CP ring buffer data */
-    info->dri->ringStart       = info->dri->gartOffset;
-    info->dri->ringMapSize     = info->dri->ringSize*1024*1024 + radeon_drm_page_size;
-    info->dri->ringSizeLog2QW  = RADEONMinBits(info->dri->ringSize*1024*1024/8)-1;
-
-    info->dri->ringReadOffset  = info->dri->ringStart + info->dri->ringMapSize;
-    info->dri->ringReadMapSize = radeon_drm_page_size;
-
-				/* Reserve space for vertex/indirect buffers */
-    info->dri->bufStart        = info->dri->ringReadOffset + info->dri->ringReadMapSize;
-    info->dri->bufMapSize      = info->dri->bufSize*1024*1024;
-
-				/* Reserve the rest for GART textures */
-    info->dri->gartTexStart     = info->dri->bufStart + info->dri->bufMapSize;
-    s = (info->dri->gartSize*1024*1024 - info->dri->gartTexStart);
-    l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
-    if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
-    info->dri->gartTexMapSize   = (s >> l) << l;
-    info->dri->log2GARTTexGran  = l;
+    if (!info->drm_mm) {
+	/* Initialize the CP ring buffer data */
+	info->dri->ringStart       = info->dri->gartOffset;
+	info->dri->ringMapSize     = info->dri->ringSize*1024*1024 + radeon_drm_page_size;
+	info->dri->ringSizeLog2QW  = RADEONMinBits(info->dri->ringSize*1024*1024/8)-1;
+
+	info->dri->ringReadOffset  = info->dri->ringStart + info->dri->ringMapSize;
+	info->dri->ringReadMapSize = radeon_drm_page_size;
+
+	/* Reserve space for vertex/indirect buffers */
+	info->dri->bufStart        = info->dri->ringReadOffset + info->dri->ringReadMapSize;
+	info->dri->bufMapSize      = info->dri->bufSize*1024*1024;
+
+	/* Reserve the rest for GART textures */
+	info->dri->gartTexStart     = info->dri->bufStart + info->dri->bufMapSize;
+	s = (info->dri->gartSize*1024*1024 - info->dri->gartTexStart);
+	l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
+	if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
+	info->dri->gartTexMapSize   = (s >> l) << l;
+	info->dri->log2GARTTexGran  = l;
+    } else {
+      s = (8*1024*1024);
+      l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
+      l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
+      if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
+      info->dri->gartTexMapSize   = (s >> l) << l;
+      info->dri->log2GARTTexGran  = l;
+    }
+
 }
 
 /* AGP Mode Quirk List - Certain hostbridge/gfx-card combos don't work with
@@ -992,6 +1096,8 @@ static Bool RADEONDRIAgpInit(RADEONInfoP
 	       "[agp] ring handle = 0x%08x\n",
 	       (unsigned int)info->dri->ringHandle);
 
+
+#if 0
     if (drmMap(info->dri->drmFD, info->dri->ringHandle, info->dri->ringMapSize,
 	       &info->dri->ring) < 0) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n");
@@ -1000,9 +1106,10 @@ static Bool RADEONDRIAgpInit(RADEONInfoP
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[agp] Ring mapped at 0x%08lx\n",
 	       (unsigned long)info->dri->ring);
-
+#endif
     if (drmAddMap(info->dri->drmFD, info->dri->ringReadOffset, info->dri->ringReadMapSize,
 		  DRM_AGP, DRM_READ_ONLY, &info->dri->ringReadPtrHandle) < 0) {
+
 	xf86DrvMsg(pScreen->myNum, X_ERROR,
 		   "[agp] Could not add ring read ptr mapping\n");
 	return FALSE;
@@ -1011,6 +1118,8 @@ static Bool RADEONDRIAgpInit(RADEONInfoP
  	       "[agp] ring read ptr handle = 0x%08x\n",
 	       (unsigned int)info->dri->ringReadPtrHandle);
 
+
+#if 0
     if (drmMap(info->dri->drmFD, info->dri->ringReadPtrHandle, info->dri->ringReadMapSize,
 	       &info->dri->ringReadPtr) < 0) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -1020,6 +1129,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoP
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[agp] Ring read ptr mapped at 0x%08lx\n",
 	       (unsigned long)info->dri->ringReadPtr);
+#endif
 
     if (drmAddMap(info->dri->drmFD, info->dri->bufStart, info->dri->bufMapSize,
 		  DRM_AGP, 0, &info->dri->bufHandle) < 0) {
@@ -1097,6 +1207,7 @@ static Bool RADEONDRIPciInit(RADEONInfoP
 	       "[pci] ring handle = 0x%08x\n",
 	       (unsigned int)info->dri->ringHandle);
 
+#if 0
     if (drmMap(info->dri->drmFD, info->dri->ringHandle, info->dri->ringMapSize,
 	       &info->dri->ring) < 0) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n");
@@ -1108,6 +1219,7 @@ static Bool RADEONDRIPciInit(RADEONInfoP
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[pci] Ring contents 0x%08lx\n",
 	       *(unsigned long *)(pointer)info->dri->ring);
+#endif
 
     if (drmAddMap(info->dri->drmFD, info->dri->ringReadOffset, info->dri->ringReadMapSize,
 		  DRM_SCATTER_GATHER, flags, &info->dri->ringReadPtrHandle) < 0) {
@@ -1119,8 +1231,10 @@ static Bool RADEONDRIPciInit(RADEONInfoP
  	       "[pci] ring read ptr handle = 0x%08x\n",
 	       (unsigned int)info->dri->ringReadPtrHandle);
 
+#if 0
     if (drmMap(info->dri->drmFD, info->dri->ringReadPtrHandle, info->dri->ringReadMapSize,
 	       &info->dri->ringReadPtr) < 0) {
+
 	xf86DrvMsg(pScreen->myNum, X_ERROR,
 		   "[pci] Could not map ring read ptr\n");
 	return FALSE;
@@ -1131,6 +1245,7 @@ static Bool RADEONDRIPciInit(RADEONInfoP
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[pci] Ring read ptr contents 0x%08lx\n",
 	       *(unsigned long *)(pointer)info->dri->ringReadPtr);
+#endif
 
     if (drmAddMap(info->dri->drmFD, info->dri->bufStart, info->dri->bufMapSize,
 		  DRM_SCATTER_GATHER, 0, &info->dri->bufHandle) < 0) {
@@ -1183,6 +1298,9 @@ static Bool RADEONDRIPciInit(RADEONInfoP
  */
 static Bool RADEONDRIMapInit(RADEONInfoPtr info, ScreenPtr pScreen)
 {
+
+    if (info->drm_mm)
+    	return TRUE;
 				/* Map registers */
     info->dri->registerSize = info->MMIOSize;
     if (drmAddMap(info->dri->drmFD, info->MMIOAddr, info->dri->registerSize,
@@ -1223,20 +1341,23 @@ static int RADEONDRIKernelInit(RADEONInf
     drmInfo.fb_bpp              = info->CurrentLayout.pixel_code;
     drmInfo.depth_bpp           = (info->dri->depthBits - 8) * 2;
 
-    drmInfo.front_offset        = info->dri->frontOffset;
-    drmInfo.front_pitch         = info->dri->frontPitch * cpp;
-    drmInfo.back_offset         = info->dri->backOffset;
-    drmInfo.back_pitch          = info->dri->backPitch * cpp;
-    drmInfo.depth_offset        = info->dri->depthOffset;
-    drmInfo.depth_pitch         = info->dri->depthPitch * drmInfo.depth_bpp / 8;
-
-    drmInfo.fb_offset           = info->dri->fbHandle;
-    drmInfo.mmio_offset         = info->dri->registerHandle;
-    drmInfo.ring_offset         = info->dri->ringHandle;
-    drmInfo.ring_rptr_offset    = info->dri->ringReadPtrHandle;
-    drmInfo.buffers_offset      = info->dri->bufHandle;
-    drmInfo.gart_textures_offset= info->dri->gartTexHandle;
-
+    if (!info->drm_mm) {
+	drmInfo.front_offset        = info->dri->frontOffset;
+	drmInfo.front_pitch         = info->dri->frontPitch * cpp;
+	drmInfo.back_offset         = info->dri->backOffset;
+	drmInfo.back_pitch          = info->dri->backPitch * cpp;
+	drmInfo.depth_offset        = info->dri->depthOffset;
+	drmInfo.depth_pitch         = info->dri->depthPitch * drmInfo.depth_bpp / 8;
+
+	drmInfo.fb_offset           = info->dri->fbHandle;
+	drmInfo.mmio_offset         = info->dri->registerHandle;
+	drmInfo.ring_offset         = info->dri->ringHandle;
+	drmInfo.ring_rptr_offset    = info->dri->ringReadPtrHandle;
+	drmInfo.buffers_offset      = info->dri->bufHandle;
+	drmInfo.gart_textures_offset= info->dri->gartTexHandle;
+    } else {
+    }
+	
     if (drmCommandWrite(info->dri->drmFD, DRM_RADEON_CP_INIT,
 			&drmInfo, sizeof(drm_radeon_init_t)) < 0)
 	return FALSE;
@@ -1245,8 +1366,9 @@ static int RADEONDRIKernelInit(RADEONInf
      * registers back to their default values, so we need to restore
      * those engine register here.
      */
-    if (info->ChipFamily < CHIP_FAMILY_R600)
-	RADEONEngineRestore(pScrn);
+    if (!info->drm_mm)
+        if (info->ChipFamily < CHIP_FAMILY_R600)
+	    RADEONEngineRestore(pScrn);
 
     return TRUE;
 }
@@ -1444,12 +1566,11 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pSc
 
     /* Get DRM version & close DRM */
     info->dri->pKernelDRMVersion = drmGetVersion(fd);
-    drmClose(fd);
     if (info->dri->pKernelDRMVersion == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "[dri] RADEONDRIGetVersion failed to get the DRM version\n"
 		   "[dri] Disabling DRI.\n");
-	return FALSE;
+	goto fail;
     }
 
     /* Now check if we qualify */
@@ -1483,10 +1604,27 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pSc
 		   req_patch);
 	drmFreeVersion(info->dri->pKernelDRMVersion);
 	info->dri->pKernelDRMVersion = NULL;
-	return FALSE;
+	goto fail;
+    }
+
+    if (info->dri->pKernelDRMVersion->version_minor >= 30) {
+	    struct drm_radeon_gem_info mminfo;
+
+	    if (!drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
+	    {
+		    info->drm_mm = TRUE;
+		    info->mm.vram_size = mminfo.vram_size;
+		    info->mm.gart_size = mminfo.gart_size;
+		    ErrorF("initing %llx %llx\n",
+			   mminfo.gart_size, mminfo.vram_size);
+	    }
     }
 
+    drmClose(fd);
     return TRUE;
+fail:
+    drmClose(fd);
+    return FALSE;
 }
 
 Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on)
@@ -1495,6 +1633,9 @@ Bool RADEONDRISetVBlankInterrupt(ScrnInf
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int value = 0;
 
+    if (info->drm_mode_setting)
+	return TRUE;
+
     if (!info->want_vblank_interrupts)
         on = FALSE;
 
@@ -1514,6 +1655,50 @@ Bool RADEONDRISetVBlankInterrupt(ScrnInf
     return TRUE;
 }
 
+Bool RADEONDRIDoMappings(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr  info    = RADEONPTR(pScrn);
+    drm_radeon_sarea_t *  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+				/* DRIScreenInit doesn't add all the
+				 * common mappings.  Add additional
+				 * mappings here.
+				 */
+
+    if (info->ChipFamily >= CHIP_FAMILY_R600)
+	return TRUE;
+
+    if (info->dri2.enabled)
+	return TRUE;
+
+    pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+    if (!RADEONDRIMapInit(info, pScreen)) {
+	RADEONDRICloseScreen(pScreen);
+	return FALSE;
+    }
+    
+				/* DRIScreenInit adds the frame buffer
+				   map, but we need it as well */
+    {
+	void *scratch_ptr;
+        int scratch_int;
+
+	DRIGetDeviceInfo(pScreen, &info->dri->fbHandle,
+                         &scratch_int, &scratch_int,
+                         &scratch_int, &scratch_int,
+                         &scratch_ptr);
+    }
+
+				/* FIXME: When are these mappings unmapped? */
+
+    if (!RADEONInitVisualConfigs(pScreen)) {
+	RADEONDRICloseScreen(pScreen);
+	return FALSE;
+    }
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n");
+    return TRUE;
+
+}
 
 /* Initialize the screen-specific data structures for the DRI and the
  * Radeon.  This is the main entry point to the device-specific
@@ -1578,10 +1763,22 @@ Bool RADEONDRIScreenInit(ScreenPtr pScre
     pDRIInfo->ddxDriverMajorVersion      = info->allowColorTiling ? 5 : 4;
     pDRIInfo->ddxDriverMinorVersion      = 3;
     pDRIInfo->ddxDriverPatchVersion      = 0;
-    pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->dri->frontOffset;
-    pDRIInfo->frameBufferSize            = info->FbMapSize - info->FbSecureSize;
-    pDRIInfo->frameBufferStride          = (pScrn->displayWidth *
-					    info->CurrentLayout.pixel_bytes);
+
+#if DRI_DRIVER_FRAMEBUFFER_MAP
+    if (info->drm_mm) {
+	pDRIInfo->frameBufferPhysicalAddress = 0;
+	pDRIInfo->frameBufferSize = 0;
+	pDRIInfo->frameBufferStride = 0;
+	pDRIInfo->dontMapFrameBuffer = TRUE;
+    } else
+#endif
+    {
+	pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->dri->frontOffset;
+	pDRIInfo->frameBufferSize            = info->FbMapSize - info->FbSecureSize;
+	pDRIInfo->frameBufferStride          = (pScrn->displayWidth *
+						    info->CurrentLayout.pixel_bytes);
+    }
+
     pDRIInfo->ddxDrawableTableEntry      = RADEON_MAX_DRAWABLES;
     pDRIInfo->maxDrawableTableEntry      = (SAREA_MAX_DRAWABLES
 					    < RADEON_MAX_DRAWABLES
@@ -1634,9 +1831,7 @@ Bool RADEONDRIScreenInit(ScreenPtr pScre
     pDRIInfo->TransitionTo3d = RADEONDRITransitionTo3d;
     pDRIInfo->TransitionSingleToMulti3D = RADEONDRITransitionSingleToMulti3d;
     pDRIInfo->TransitionMultiToSingle3D = RADEONDRITransitionMultiToSingle3d;
-#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 ||	\
-			(DRIINFO_MAJOR_VERSION == 5 &&	\
-			 DRIINFO_MINOR_VERSION >= 1))
+#if DRI_SUPPORT_CLIP_NOTIFY
     pDRIInfo->ClipNotify     = RADEONDRIClipNotify;
 #endif
 
@@ -1668,57 +1863,60 @@ Bool RADEONDRIScreenInit(ScreenPtr pScre
 	pDRIInfo = NULL;
 	return FALSE;
     }
-				/* Initialize AGP */
-    if (info->cardType==CARD_AGP && !RADEONDRIAgpInit(info, pScreen)) {
-	xf86DrvMsg(pScreen->myNum, X_ERROR,
-		   "[agp] AGP failed to initialize. Disabling the DRI.\n" );
-	xf86DrvMsg(pScreen->myNum, X_INFO,
-		   "[agp] You may want to make sure the agpgart kernel "
-		   "module\nis loaded before the radeon kernel module.\n");
-	RADEONDRICloseScreen(pScreen);
-	return FALSE;
-    }
-
-				/* Initialize PCI */
-    if ((info->cardType!=CARD_AGP) && !RADEONDRIPciInit(info, pScreen)) {
-	xf86DrvMsg(pScreen->myNum, X_ERROR,
-		   "[pci] PCI failed to initialize. Disabling the DRI.\n" );
-	RADEONDRICloseScreen(pScreen);
-	return FALSE;
-    }
-
-				/* DRIScreenInit doesn't add all the
-				 * common mappings.  Add additional
-				 * mappings here.
-				 */
-    if (!RADEONDRIMapInit(info, pScreen)) {
-	RADEONDRICloseScreen(pScreen);
-	return FALSE;
-    }
 
-				/* DRIScreenInit adds the frame buffer
-				   map, but we need it as well */
-    {
-	void *scratch_ptr;
-        int scratch_int;
+    /* Now, nuke dri.c's dummy frontbuffer map setup if we did that. */
+    if (pDRIInfo->frameBufferSize != 0 && info->drm_mm) {
+	int tmp;
+	drm_handle_t fb_handle;
+	void *ptmp;
 
-	DRIGetDeviceInfo(pScreen, &info->dri->fbHandle,
-                         &scratch_int, &scratch_int,
-                         &scratch_int, &scratch_int,
-                         &scratch_ptr);
-    }
-
-				/* FIXME: When are these mappings unmapped? */
+	/* With the compat method, it will continue to report
+	 * the wrong map out of GetDeviceInfo, which will break AIGLX.
+	 */
+	DRIGetDeviceInfo(pScreen, &fb_handle, &tmp, &tmp, &tmp, &tmp, &ptmp);
+	drmRmMap(info->dri->drmFD, fb_handle);
 
-    if (!RADEONInitVisualConfigs(pScreen)) {
-	RADEONDRICloseScreen(pScreen);
-	return FALSE;
+	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");
+    }
+   
+    if (info->drm_mm) {
+	int ret;
+	ret = radeon_dri_gart_init(pScreen);
+	if (!ret) {
+	    xf86DrvMsg(pScreen->myNum, X_ERROR,
+		       "[gart] GART failed to initialize. Disabling the DRI.\n" );
+	    RADEONDRICloseScreen(pScreen);
+	    return FALSE;
+	}
+    } else {
+	if (info->cardType==CARD_AGP && !RADEONDRIAgpInit(info, pScreen)) {
+	    /* Initialize AGP */
+	    xf86DrvMsg(pScreen->myNum, X_ERROR,
+		       "[agp] AGP failed to initialize. Disabling the DRI.\n" );
+	    xf86DrvMsg(pScreen->myNum, X_INFO,
+		       "[agp] You may want to make sure the agpgart kernel "
+		       "module\nis loaded before the radeon kernel module.\n");
+	    RADEONDRICloseScreen(pScreen);
+	    return FALSE;
+	}
+	
+				/* Initialize PCI */
+	if ((info->cardType!=CARD_AGP) && !RADEONDRIPciInit(info, pScreen)) {
+	    xf86DrvMsg(pScreen->myNum, X_ERROR,
+		       "[pci] PCI failed to initialize. Disabling the DRI.\n" );
+	    RADEONDRICloseScreen(pScreen);
+	    return FALSE;
+	}
     }
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n");
 
     return TRUE;
 }
 
+
 static Bool RADEONDRIDoCloseScreen(int scrnIndex, ScreenPtr pScreen)
 {
     ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
@@ -1760,17 +1958,21 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr
 	return FALSE;
     }
 
-    /* Initialize the vertex buffers list */
-    if (!RADEONDRIBufInit(info, pScreen)) {
-	RADEONDRICloseScreen(pScreen);
-	return FALSE;
+    if (!info->drm_mm) {
+	/* Initialize the vertex buffers list */
+	if (!RADEONDRIBufInit(info, pScreen)) {
+	    RADEONDRICloseScreen(pScreen);
+	    return FALSE;
+	}
     }
 
-    /* Initialize IRQ */
-    RADEONDRIIrqInit(info, pScreen);
+    if (!info->drm_mode_setting) {
+	/* Initialize IRQ */
+	RADEONDRIIrqInit(info, pScreen);
+        /* Initialize kernel GART memory manager */
+        RADEONDRIGartHeapInit(info, pScreen);
+    }
 
-    /* Initialize kernel GART memory manager */
-    RADEONDRIGartHeapInit(info, pScreen);
 
     /* Initialize and start the CP if required */
     RADEONDRICPInit(pScrn);
@@ -1779,6 +1981,10 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr
     pSAREAPriv = (drm_radeon_sarea_t*)DRIGetSAREAPrivate(pScreen);
     memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
 
+    if (info->drm_mm) {
+	/* init the handles into the sarea */
+	
+    }
     pRADEONDRI                    = (RADEONDRIPtr)info->dri->pDRIInfo->devPrivate;
 
     pRADEONDRI->deviceID          = info->Chipset;
@@ -1936,6 +2142,8 @@ void RADEONDRICloseScreen(ScreenPtr pScr
 	drmUnmap(info->dri->buf, info->dri->bufMapSize);
 	info->dri->buf = NULL;
     }
+
+#if 0
     if (info->dri->ringReadPtr) {
 	drmUnmap(info->dri->ringReadPtr, info->dri->ringReadMapSize);
 	info->dri->ringReadPtr = NULL;
@@ -1944,6 +2152,7 @@ void RADEONDRICloseScreen(ScreenPtr pScr
 	drmUnmap(info->dri->ring, info->dri->ringMapSize);
 	info->dri->ring = NULL;
     }
+#endif
     if (info->dri->agpMemHandle != DRM_AGP_NO_HANDLE) {
 	drmAgpUnbind(info->dri->drmFD, info->dri->agpMemHandle);
 	drmAgpFree(info->dri->drmFD, info->dri->agpMemHandle);
@@ -2353,3 +2562,12 @@ int RADEONDRISetParam(ScrnInfoPtr pScrn,
 			  &radeonsetparam, sizeof(drm_radeon_setparam_t));
     return ret;
 }
+
+static Bool radeon_dri_gart_init(ScreenPtr pScreen)
+{
+    ScrnInfoPtr    pScrn   = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr  info    = RADEONPTR(pScrn);
+
+    RADEONDRIInitGARTValues(info);
+    return TRUE;
+}
diff -up xf86-video-ati-6.12.2/src/radeon_driver.c.modeset xf86-video-ati-6.12.2/src/radeon_driver.c
--- xf86-video-ati-6.12.2/src/radeon_driver.c.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_driver.c	2009-05-21 11:20:20.000000000 -0400
@@ -67,7 +67,7 @@
 
 #include <string.h>
 #include <stdio.h>
-
+#include <errno.h>
 				/* Driver data structures */
 #include "radeon.h"
 #include "radeon_reg.h"
@@ -229,7 +229,10 @@ radeonShadowWindow(ScreenPtr screen, CAR
     stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
     *size = stride;
 
-    return ((uint8_t *)info->FB + row * stride + offset);
+    if (info->drm_mm)
+        return ((uint8_t *)info->mm.front_buffer->virtual + row * stride + offset);
+    else
+        return ((uint8_t *)info->FB + row * stride + offset);
 }
 static Bool
 RADEONCreateScreenResources (ScreenPtr pScreen)
@@ -250,6 +253,13 @@ RADEONCreateScreenResources (ScreenPtr p
 		      radeonShadowWindow, 0, NULL))
 	   return FALSE;
    }
+
+   if (info->dri2.enabled) {
+       if (info->mm.front_buffer) {
+	   PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
+	   radeon_set_pixmap_bo(pPix, info->mm.front_buffer);
+       }
+   }
    return TRUE;
 }
 
@@ -1695,6 +1705,7 @@ static Bool RADEONPreInitVRAM(ScrnInfoPt
     }
 
     pScrn->videoRam  &= ~1023;
+
     info->FbMapSize  = pScrn->videoRam * 1024;
 
     /* if the card is PCI Express reserve the last 32k for the gart table */
@@ -1814,59 +1825,61 @@ static Bool RADEONPreInitChipType(ScrnIn
 	break;
     }
 
-    from               = X_PROBED;
-    info->LinearAddr   = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & ~0x1ffffffULL;
-    pScrn->memPhysBase = info->LinearAddr;
-    if (dev->MemBase) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Linear address override, using 0x%016lx instead of 0x%016llx\n",
-		   dev->MemBase,
-		   info->LinearAddr);
-	info->LinearAddr = dev->MemBase;
-	from             = X_CONFIG;
-    } else if (!info->LinearAddr) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "No valid linear framebuffer address\n");
-	return FALSE;
-    }
-    xf86DrvMsg(pScrn->scrnIndex, from,
-	       "Linear framebuffer at 0x%016llx\n", info->LinearAddr);
+    if (!info->drm_mode_setting) {
+	from               = X_PROBED;
+	info->LinearAddr   = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & ~0x1ffffffULL;
+	pScrn->memPhysBase = info->LinearAddr;
+	if (dev->MemBase) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Linear address override, using 0x%016lx instead of 0x%016llx\n",
+		       dev->MemBase,
+		       info->LinearAddr);
+	    info->LinearAddr = dev->MemBase;
+	    from             = X_CONFIG;
+	} else if (!info->LinearAddr) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "No valid linear framebuffer address\n");
+	    return FALSE;
+	}
+	xf86DrvMsg(pScrn->scrnIndex, from,
+		   "Linear framebuffer at 0x%016llx\n", info->LinearAddr);
 
 #ifndef XSERVER_LIBPCIACCESS
-				/* BIOS */
-    from              = X_PROBED;
-    info->BIOSAddr    = info->PciInfo->biosBase & 0xfffe0000;
-    if (dev->BiosBase) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "BIOS address override, using 0x%08lx instead of 0x%08lx\n",
-		   (unsigned long)dev->BiosBase,
-		   (unsigned long)info->BIOSAddr);
-	info->BIOSAddr = dev->BiosBase;
-	from           = X_CONFIG;
-    }
-    if (info->BIOSAddr) {
-	xf86DrvMsg(pScrn->scrnIndex, from,
-		   "BIOS at 0x%08lx\n", (unsigned long)info->BIOSAddr);
-    }
+				    /* BIOS */
+	from              = X_PROBED;
+	info->BIOSAddr    = info->PciInfo->biosBase & 0xfffe0000;
+	if (dev->BiosBase) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "BIOS address override, using 0x%08lx instead of 0x%08lx\n",
+		       (unsigned long)dev->BiosBase,
+		       (unsigned long)info->BIOSAddr);
+	    info->BIOSAddr = dev->BiosBase;
+	    from           = X_CONFIG;
+	}
+	if (info->BIOSAddr) {
+	    xf86DrvMsg(pScrn->scrnIndex, from,
+		       "BIOS at 0x%08lx\n", (unsigned long)info->BIOSAddr);
+	}
 #endif
 
-				/* Read registers used to determine options */
-    /* Check chip errata */
-    info->ChipErrata = 0;
+				    /* Read registers used to determine options */
+	/* Check chip errata */
+	info->ChipErrata = 0;
 
-    if (info->ChipFamily == CHIP_FAMILY_R300 &&
-	(INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK)
-	== RADEON_CFG_ATI_REV_A11)
-	    info->ChipErrata |= CHIP_ERRATA_R300_CG;
+	if (info->ChipFamily == CHIP_FAMILY_R300 &&
+	    (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK)
+	    == RADEON_CFG_ATI_REV_A11)
+		info->ChipErrata |= CHIP_ERRATA_R300_CG;
 
-    if (info->ChipFamily == CHIP_FAMILY_RV200 ||
-	info->ChipFamily == CHIP_FAMILY_RS200)
-	    info->ChipErrata |= CHIP_ERRATA_PLL_DUMMYREADS;
+	if (info->ChipFamily == CHIP_FAMILY_RV200 ||
+	    info->ChipFamily == CHIP_FAMILY_RS200)
+		info->ChipErrata |= CHIP_ERRATA_PLL_DUMMYREADS;
 
-    if (info->ChipFamily == CHIP_FAMILY_RV100 ||
-	info->ChipFamily == CHIP_FAMILY_RS100 ||
-	info->ChipFamily == CHIP_FAMILY_RS200)
-	    info->ChipErrata |= CHIP_ERRATA_PLL_DELAY;
+	if (info->ChipFamily == CHIP_FAMILY_RV100 ||
+	    info->ChipFamily == CHIP_FAMILY_RS100 ||
+	    info->ChipFamily == CHIP_FAMILY_RS200)
+		info->ChipErrata |= CHIP_ERRATA_PLL_DELAY;
+    }
 
 #ifdef XF86DRI
 				/* AGP/PCI */
@@ -2041,6 +2054,15 @@ static Bool RADEONPreInitAccel(ScrnInfoP
     }
     info->accel_state->fifo_slots                 = 0;
 
+    if (info->drm_mode_setting && info->ChipFamily >= CHIP_FAMILY_R600) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Using shadowfb for KMS on R600+\n");
+	info->r600_shadow_fb = TRUE;
+	if (!xf86LoadSubModule(pScrn, "shadow"))
+	    info->r600_shadow_fb = FALSE;
+	return TRUE;
+    }
+
     if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
 	(info->ChipFamily == CHIP_FAMILY_RS200) ||
 	(info->ChipFamily == CHIP_FAMILY_RS300) ||
@@ -2065,6 +2087,9 @@ static Bool RADEONPreInitAccel(ScrnInfoP
     if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
 	int errmaj = 0, errmin = 0;
 
+#if defined(USE_EXA)
+	info->useEXA = TRUE;
+#endif
 	from = X_DEFAULT;
 #if defined(USE_EXA)
 #if defined(USE_XAA)
@@ -2075,12 +2100,17 @@ static Bool RADEONPreInitAccel(ScrnInfoP
 		info->useEXA = TRUE;
 	    } else if (xf86NameCmp(optstr, "XAA") == 0) {
 		from = X_CONFIG;
+		info->useEXA = FALSE;
 	    }
 	}
 #else /* USE_XAA */
 	info->useEXA = TRUE;
 #endif /* !USE_XAA */
 #endif /* USE_EXA */
+	/* for drm_mm use EXA */
+	if (info->drm_mm && !info->r600_shadow_fb) {
+		info->useEXA = TRUE;
+	}
         if (info->ChipFamily < CHIP_FAMILY_R600)
 	    xf86DrvMsg(pScrn->scrnIndex, from,
 		       "Using %s acceleration architecture\n",
@@ -2179,15 +2209,9 @@ static Bool RADEONPreInitInt10(ScrnInfoP
     return TRUE;
 }
 
-#ifdef XF86DRI
-static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn)
+static Bool radeon_alloc_dri(ScrnInfoPtr pScrn)
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
-    MessageType    from;
-    char          *reason;
-
-    info->directRenderingEnabled = FALSE;
-    info->directRenderingInited = FALSE;
 
     if (!(info->dri = xcalloc(1, sizeof(struct radeon_dri)))) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Unable to allocate dri rec!\n");
@@ -2198,6 +2222,22 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Unable to allocate cp rec!\n");
 	return FALSE;
     }
+    return TRUE;
+}
+
+#ifdef XF86DRI
+static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    MessageType    from;
+    char          *reason;
+
+    info->directRenderingEnabled = FALSE;
+    info->directRenderingInited = FALSE;
+
+    if (!radeon_alloc_dri(pScrn))
+	return FALSE;
+
     info->cp->CPInUse = FALSE;
     info->cp->CPStarted = FALSE;
     info->cp->CPusecTimeout = RADEON_DEFAULT_CP_TIMEOUT;
@@ -2761,6 +2801,37 @@ static const xf86CrtcConfigFuncsRec RADE
     RADEONCRTCResize
 };
 
+#ifdef XF86DRM_MODE
+static Bool radeon_kernel_mode_enabled(ScrnInfoPtr pScrn)
+{
+#if XSERVER_LIBPCIACCESS
+    struct pci_device *PciInfo;
+#else
+    pciVideoPtr PciInfo;
+#endif
+    EntityInfoPtr pEnt;
+    char *busIdString;
+    int ret;
+
+    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+    PciInfo = xf86GetPciInfoForEntity(pEnt->index);
+
+    if (!xf86LoaderCheckSymbol("DRICreatePCIBusID"))
+	return FALSE;
+
+    busIdString = DRICreatePCIBusID(PciInfo);
+    ret = drmCheckModesettingSupported(busIdString);
+    xfree(busIdString);
+    if (ret)
+	return FALSE;
+
+    return TRUE;
+}
+#else
+#define radeon_kernel_mode_enabled(x) FALSE
+#endif
+
+
 Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
 {
     xf86CrtcConfigPtr   xf86_config;
@@ -2780,6 +2851,8 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, in
     info               = RADEONPTR(pScrn);
     info->MMIO         = NULL;
 
+    info->drm_mode_setting = radeon_kernel_mode_enabled(pScrn);
+
     info->IsSecondary  = FALSE;
     info->IsPrimary = FALSE;
 
@@ -2814,62 +2887,63 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, in
     }
 
     info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
-    info->PciTag  = pciTag(PCI_DEV_BUS(info->PciInfo),
-			   PCI_DEV_DEV(info->PciInfo),
-			   PCI_DEV_FUNC(info->PciInfo));
-    info->MMIOAddr = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & ~0xffULL;
-    info->MMIOSize = PCI_REGION_SIZE(info->PciInfo, 2);
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TOTO SAYS %016llx\n", 
-		(unsigned long long)PCI_REGION_BASE(info->PciInfo,
-		2, REGION_MEM));
-    if (info->pEnt->device->IOBase) {
-	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
-		   "MMIO address override, using 0x%08lx instead of 0x%016llx\n",
-		   info->pEnt->device->IOBase,
-		   info->MMIOAddr);
-	info->MMIOAddr = info->pEnt->device->IOBase;
-    } else if (!info->MMIOAddr) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n");
-	goto fail1;
-    }
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "MMIO registers at 0x%016llx: size %ldKB\n", info->MMIOAddr, info->MMIOSize / 1024);
 
-    if(!RADEONMapMMIO(pScrn)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Memory map the MMIO region failed\n");
-	goto fail1;
-    }
+    if (!info->drm_mode_setting) {
 
+	info->PciTag  = pciTag(PCI_DEV_BUS(info->PciInfo),
+			       PCI_DEV_DEV(info->PciInfo),
+			       PCI_DEV_FUNC(info->PciInfo));
+        info->MMIOAddr = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & ~0xffULL;
+	info->MMIOSize = PCI_REGION_SIZE(info->PciInfo, 2);
+	if (info->pEnt->device->IOBase) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+		       "MMIO address override, using 0x%08lx instead of 0x%016llx\n",
+		       info->pEnt->device->IOBase,
+		       info->MMIOAddr);
+	    info->MMIOAddr = info->pEnt->device->IOBase;
+	} else if (!info->MMIOAddr) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n");
+	    goto fail1;
+	}
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	           "MMIO registers at 0x%016llx: size %ldKB\n", info->MMIOAddr, info->MMIOSize / 1024);
+	
+	if(!RADEONMapMMIO(pScrn)) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Memory map the MMIO region failed\n");
+	    goto fail1;
+	}
+	
 #if !defined(__alpha__)
-    if (
+	if (
 #ifndef XSERVER_LIBPCIACCESS
-	xf86GetPciDomain(info->PciTag) ||
+	    xf86GetPciDomain(info->PciTag) ||
 #endif
-	!xf86IsPrimaryPci(info->PciInfo))
-	RADEONPreInt10Save(pScrn, &int10_save);
+	    !xf86IsPrimaryPci(info->PciInfo))
+	    RADEONPreInt10Save(pScrn, &int10_save);
 #else
-    /* [Alpha] On the primary, the console already ran the BIOS and we're
-     *         going to run it again - so make sure to "fix up" the card
-     *         so that (1) we can read the BIOS ROM and (2) the BIOS will
-     *         get the memory config right.
-     */
-    RADEONPreInt10Save(pScrn, &int10_save);
+	/* [Alpha] On the primary, the console already ran the BIOS and we're
+	 *         going to run it again - so make sure to "fix up" the card
+	 *         so that (1) we can read the BIOS ROM and (2) the BIOS will
+	 *         get the memory config right.
+	 */
+	RADEONPreInt10Save(pScrn, &int10_save);
 #endif
-
-    if (flags & PROBE_DETECT) {
-	RADEONProbeDDC(pScrn, info->pEnt->index);
-	RADEONPostInt10Check(pScrn, int10_save);
-	if(info->MMIO) RADEONUnmapMMIO(pScrn);
-	return TRUE;
-    }
+	
+	if (flags & PROBE_DETECT) {
+	    RADEONProbeDDC(pScrn, info->pEnt->index);
+	    RADEONPostInt10Check(pScrn, int10_save);
+	    if(info->MMIO) RADEONUnmapMMIO(pScrn);
+	    return TRUE;
+	}
 
 
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "PCI bus %d card %d func %d\n",
-	       PCI_DEV_BUS(info->PciInfo),
-	       PCI_DEV_DEV(info->PciInfo),
-	       PCI_DEV_FUNC(info->PciInfo));
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "PCI bus %d card %d func %d\n",
+		   PCI_DEV_BUS(info->PciInfo),
+		   PCI_DEV_DEV(info->PciInfo),
+		   PCI_DEV_FUNC(info->PciInfo));
+    }
 
     if (xf86RegisterResources(info->pEnt->index, 0, ResExclusive))
 	goto fail;
@@ -2879,10 +2953,12 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, in
     pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
     pScrn->monitor     = pScrn->confScreen->monitor;
 
-   /* Allocate an xf86CrtcConfig */
-    xf86CrtcConfigInit (pScrn, &RADEONCRTCResizeFuncs);
-    xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-
+    if (!info->drm_mode_setting) {
+	/* Allocate an xf86CrtcConfig */
+	xf86CrtcConfigInit (pScrn, &RADEONCRTCResizeFuncs);
+	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	
+    }
 
     if (!RADEONPreInitVisual(pScrn))
 	goto fail;
@@ -2897,125 +2973,189 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, in
     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
 
     /* By default, don't do VGA IOs on ppc/sparc */
+    if (!info->drm_mode_setting) {
 #if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW)
-    info->VGAAccess = FALSE;
+	info->VGAAccess = FALSE;
 #else
-    info->VGAAccess = TRUE;
+	info->VGAAccess = TRUE;
 #endif
 
 #ifdef WITH_VGAHW
-    xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess);
-    if (info->VGAAccess) {
-       if (!xf86LoadSubModule(pScrn, "vgahw"))
-           info->VGAAccess = FALSE;
-        else {
-            if (!vgaHWGetHWRec(pScrn))
-               info->VGAAccess = FALSE;
-       }
-       if (!info->VGAAccess)
-           xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed,"
-                      " trying to run without it\n");
-    } else
-           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE,"
-                      " VGA module load skipped\n");
-    if (info->VGAAccess)
-        vgaHWGetIOBase(VGAHWPTR(pScrn));
+	xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess);
+	if (info->VGAAccess) {
+	   if (!xf86LoadSubModule(pScrn, "vgahw"))
+	       info->VGAAccess = FALSE;
+	    else {
+		if (!vgaHWGetHWRec(pScrn))
+		   info->VGAAccess = FALSE;
+	   }
+	   if (!info->VGAAccess)
+	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed,"
+			  " trying to run without it\n");
+	} else
+	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE,"
+			  " VGA module load skipped\n");
+	if (info->VGAAccess)
+	    vgaHWGetIOBase(VGAHWPTR(pScrn));
 #endif
-
+    }
 
     if (!RADEONPreInitWeight(pScrn))
 	goto fail;
 
-    info->DispPriority = 1;
-    if ((s = xf86GetOptValString(info->Options, OPTION_DISP_PRIORITY))) {
-	if (strcmp(s, "AUTO") == 0) {
-	    info->DispPriority = 1;
-	} else if (strcmp(s, "BIOS") == 0) {
-	    info->DispPriority = 0;
-	} else if (strcmp(s, "HIGH") == 0) {
-	    info->DispPriority = 2;
-	} else
-	    info->DispPriority = 1;
-    }
-
     if (!RADEONPreInitChipType(pScrn))
 	goto fail;
 
-    if (!RADEONPreInitInt10(pScrn, &pInt10))
-	goto fail;
+    if (!info->drm_mode_setting) {
+	info->DispPriority = 1;
+	if ((s = xf86GetOptValString(info->Options, OPTION_DISP_PRIORITY))) {
+	    if (strcmp(s, "AUTO") == 0) {
+		info->DispPriority = 1;
+	    } else if (strcmp(s, "BIOS") == 0) {
+		info->DispPriority = 0;
+	    } else if (strcmp(s, "HIGH") == 0) {
+		info->DispPriority = 2;
+	    } else
+		info->DispPriority = 1;
+	}
 
-    RADEONPostInt10Check(pScrn, int10_save);
+	if (!RADEONPreInitInt10(pScrn, &pInt10))
+	    goto fail;
 
-    if (!RADEONPreInitBIOS(pScrn, pInt10))
-	goto fail;
+	RADEONPostInt10Check(pScrn, int10_save);
+
+	if (!RADEONPreInitBIOS(pScrn, pInt10))
+	    goto fail;
 
-    /* Save BIOS scratch registers */
-    RADEONSaveBIOSRegisters(pScrn, info->SavedReg);
+	/* Save BIOS scratch registers */
+	RADEONSaveBIOSRegisters(pScrn, info->SavedReg);
 
 #ifdef XF86DRI
-    /* PreInit DRI first of all since we need that for getting a proper
-     * memory map
-     */
-    info->directRenderingEnabled = RADEONPreInitDRI(pScrn);
+	/* PreInit DRI first of all since we need that for getting a proper
+	 * memory map
+	 */
+	info->directRenderingEnabled = RADEONPreInitDRI(pScrn);
 #endif
-    if (!info->directRenderingEnabled) {
-	if (info->ChipFamily >= CHIP_FAMILY_R600) {
-	    info->r600_shadow_fb = TRUE;
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "using shadow framebuffer\n");
-	    if (!xf86LoadSubModule(pScrn, "shadow"))
-		info->r600_shadow_fb = FALSE;
+	if (!info->directRenderingEnabled) {
+	    if (info->ChipFamily >= CHIP_FAMILY_R600) {
+		info->r600_shadow_fb = TRUE;
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			       "using shadow framebuffer\n");
+		if (!xf86LoadSubModule(pScrn, "shadow"))
+		    info->r600_shadow_fb = FALSE;
+	    }
 	}
-    }
 
-    if (!RADEONPreInitVRAM(pScrn))
-	goto fail;
+	if (!RADEONPreInitVRAM(pScrn))
+	    goto fail;
 
-    RADEONPreInitColorTiling(pScrn);
+	RADEONPreInitColorTiling(pScrn);
 
-    if (IS_AVIVO_VARIANT)
-	xf86CrtcSetSizeRange (pScrn, 320, 200, 8192, 8192);
-    else
-	xf86CrtcSetSizeRange (pScrn, 320, 200, 4096, 4096);
+	if (IS_AVIVO_VARIANT)
+	    xf86CrtcSetSizeRange (pScrn, 320, 200, 8192, 8192);
+	else
+	    xf86CrtcSetSizeRange (pScrn, 320, 200, 4096, 4096);
 
-    RADEONPreInitDDC(pScrn);
+	RADEONPreInitDDC(pScrn);
 
-    if (!RADEONPreInitControllers(pScrn))
-       goto fail;
+	if (!RADEONPreInitControllers(pScrn))
+	   goto fail;
 
 
-    ErrorF("before xf86InitialConfiguration\n");
+	ErrorF("before xf86InitialConfiguration\n");
 
-    if (!xf86InitialConfiguration (pScrn, FALSE))
-   {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
-      goto fail;
-   }
+	if (!xf86InitialConfiguration (pScrn, FALSE))
+       {
+	  xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
+	  goto fail;
+       }
 
-    /* fix up cloning on rn50 cards
-     * since they only have one crtc sometimes the xserver doesn't assign
-     * a crtc to one of the outputs even though both outputs have common modes
-     * which results in only one monitor being enabled.  Assign a crtc here so
-     * that both outputs light up.
-     */
-    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
-	int i;
+	/* fix up cloning on rn50 cards
+	 * since they only have one crtc sometimes the xserver doesn't assign
+	 * a crtc to one of the outputs even though both outputs have common modes
+	 * which results in only one monitor being enabled.  Assign a crtc here so
+	 * that both outputs light up.
+	 */
+	if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
+	    int i;
 
-	for (i = 0; i < xf86_config->num_output; i++) {
-	    xf86OutputPtr output = xf86_config->output[i];
+	    for (i = 0; i < xf86_config->num_output; i++) {
+		xf86OutputPtr output = xf86_config->output[i];
 
-	    /* XXX: double check crtc mode */
-	    if ((output->probed_modes != NULL) && (output->crtc == NULL))
-		output->crtc = xf86_config->crtc[0];
+		/* XXX: double check crtc mode */
+		if ((output->probed_modes != NULL) && (output->crtc == NULL))
+		    output->crtc = xf86_config->crtc[0];
+	    }
 	}
-    }
 
-    ErrorF("after xf86InitialConfiguration\n");
+	ErrorF("after xf86InitialConfiguration\n");
+    } else {
+#ifdef XF86DRM_MODE
+	char *bus_id;
+	int zaphod_mask;
+	if (!radeon_alloc_dri(pScrn))
+		return FALSE;
+
+	zaphod_mask = 0xf;
+	if (info->IsPrimary)
+		zaphod_mask = 0xd;
+	if (info->IsSecondary)
+		zaphod_mask = 0x2;
+
+	bus_id = DRICreatePCIBusID(info->PciInfo);
+	if (drmmode_pre_init(pScrn, &info->drmmode, bus_id, "radeon", pScrn->bitsPerPixel / 8, zaphod_mask) == FALSE) {
+	    xfree(bus_id);
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
+	    goto fail;
+	}
+
+	info->dri->drmFD = info->drmmode.fd;
+    info->dri2.drm_fd = info->drmmode.fd;
+    info->dri2.enabled = FALSE;
+	xfree(bus_id);
+	 
+        {
+	    struct drm_radeon_gem_info mminfo;
+
+	    if (!drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
+	    {
+		info->mm.vram_size = mminfo.vram_visible;
+		info->mm.gart_size = mminfo.gart_size;
+		ErrorF("initing gart:%llx vram: s:%llx v:%llx\n",
+		       mminfo.gart_size, mminfo.vram_size, mminfo.vram_visible);
+	    }
+	    {
+	        struct drm_radeon_getparam gp;
+		int value;
+
+		memset(&gp, 0, sizeof(gp));
+		gp.param = RADEON_PARAM_FB_LOCATION;
+		gp.value = &value;
+
+		if (drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GETPARAM, &gp,
+					sizeof(gp)) < 0) {
+		    goto fail;
+		}
+		if (info->ChipFamily >= CHIP_FAMILY_R600)
+	    		info->fbLocation = (value & 0xffff) << 24; 
+		else
+			info->fbLocation = (value & 0xffff) << 16;
+	    }
+        }
+	if (info->ChipFamily < CHIP_FAMILY_R600) {
+		info->useEXA = TRUE;
+		info->directRenderingEnabled = TRUE;
+	}
+	info->new_cs = TRUE;
+	info->drm_mm = TRUE;
+	//	info->directRenderingDisabled = FALSE;
+#endif
+    }
 
     RADEONSetPitch(pScrn);
 
-   /* Set display resolution */
-   xf86SetDpi(pScrn, 0, 0);
+    /* Set display resolution */
+    xf86SetDpi(pScrn, 0, 0);
 
 	/* Get ScreenInit function */
     if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
@@ -3030,10 +3170,12 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, in
 	if (!RADEONPreInitXv(pScrn))                 goto fail;
     }
 
-    if (!xf86RandR12PreInit (pScrn))
-    {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
-      goto fail;
+    if (!info->drm_mode_setting) {
+	if (!xf86RandR12PreInit (pScrn))
+	{
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
+		goto fail;
+	}
     }
 
     if (pScrn->modes == NULL) {
@@ -3186,6 +3328,9 @@ static void RADEONBlockHandler(int i, po
 
 #ifdef USE_EXA
     info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+    if (info->new_cs) {
+        RADEONCPReleaseIndirect(pScrn);
+    }
 #endif
 }
 
@@ -3274,7 +3419,7 @@ Bool RADEONScreenInit(int scrnIndex, Scr
     int            subPixelOrder = SubPixelUnknown;
     char*          s;
 #endif
-
+    void *front_ptr;
 
     info->accelOn      = FALSE;
 #ifdef USE_XAA
@@ -3294,58 +3439,61 @@ Bool RADEONScreenInit(int scrnIndex, Scr
 		   "RADEONScreenInit %lx %ld\n",
 		   pScrn->memPhysBase, pScrn->fbOffset);
 #endif
-    if (!RADEONMapMem(pScrn)) return FALSE;
+
+    if (!info->drm_mode_setting) {
+	if (!RADEONMapMem(pScrn)) return FALSE;
 
 #ifdef XF86DRI
-    info->dri->fbX = 0;
-    info->dri->fbY = 0;
+	info->dri->fbX = 0;
+	info->dri->fbY = 0;
 #endif
+	
+	info->PaletteSavedOnVT = FALSE;
 
-    info->PaletteSavedOnVT = FALSE;
+	info->crtc_on = FALSE;
+	info->crtc2_on = FALSE;
 
-    info->crtc_on = FALSE;
-    info->crtc2_on = FALSE;
+        /* save the real front buffer size
+         * it changes with randr, rotation, etc.
+         */
+        info->virtualX = pScrn->virtualX;
+        info->virtualY = pScrn->virtualY;
 
-    /* save the real front buffer size
-     * it changes with randr, rotation, etc.
-     */
-    info->virtualX = pScrn->virtualX;
-    info->virtualY = pScrn->virtualY;
+	RADEONSave(pScrn);
 
-    RADEONSave(pScrn);
+	/* set initial bios scratch reg state */
+	RADEONInitBIOSRegisters(pScrn);
 
-    /* set initial bios scratch reg state */
-    RADEONInitBIOSRegisters(pScrn);
+	/* blank the outputs/crtcs */
+	RADEONBlank(pScrn);
 
-    /* blank the outputs/crtcs */
-    RADEONBlank(pScrn);
+	if (info->IsMobility && !IS_AVIVO_VARIANT) {
+	    if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
+		RADEONSetDynamicClock(pScrn, 1);
+	    } else {
+		RADEONSetDynamicClock(pScrn, 0);
+	    }
+	} else if (IS_AVIVO_VARIANT) {
+	    if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
+		atombios_static_pwrmgt_setup(pScrn, 1);
+		atombios_dyn_clk_setup(pScrn, 1);
+	    }
+	}
+	
+	if (IS_R300_VARIANT || IS_RV100_VARIANT)
+	    RADEONForceSomeClocks(pScrn);
 
-    if (info->IsMobility && !IS_AVIVO_VARIANT) {
-	if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
-	    RADEONSetDynamicClock(pScrn, 1);
-	} else {
-	    RADEONSetDynamicClock(pScrn, 0);
+	if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Color tiling not supported with virtual x resolutions larger than %d, disabling\n",
+		       info->MaxSurfaceWidth);
+	    info->allowColorTiling = FALSE;
 	}
-    } else if (IS_AVIVO_VARIANT) {
-	if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
-	    atombios_static_pwrmgt_setup(pScrn, 1);
-	    atombios_dyn_clk_setup(pScrn, 1);
+	if (info->allowColorTiling) {
+	    info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
 	}
+	
     }
-
-    if (IS_R300_VARIANT || IS_RV100_VARIANT)
-	RADEONForceSomeClocks(pScrn);
-
-    if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Color tiling not supported with virtual x resolutions larger than %d, disabling\n",
-		    info->MaxSurfaceWidth);
-	info->allowColorTiling = FALSE;
-    }
-    if (info->allowColorTiling) {
-        info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
-    }
-
     /* Visual setup */
     miClearVisualTypes();
     if (!miSetVisualTypes(pScrn->depth,
@@ -3379,19 +3527,21 @@ Bool RADEONScreenInit(int scrnIndex, Scr
     hasDRI = info->directRenderingEnabled;
 #endif /* XF86DRI */
 
-    /* Initialize the memory map, this basically calculates the values
-     * we'll use later on for MC_FB_LOCATION & MC_AGP_LOCATION
-     */
-    RADEONInitMemoryMap(pScrn);
+    if (!info->drm_mode_setting) {
+	/* Initialize the memory map, this basically calculates the values
+	 * we'll use later on for MC_FB_LOCATION & MC_AGP_LOCATION
+	 */
+	RADEONInitMemoryMap(pScrn);
 
-    /* empty the surfaces */
-    if (info->ChipFamily < CHIP_FAMILY_R600) {
-	unsigned char *RADEONMMIO = info->MMIO;
-	unsigned int j;
-	for (j = 0; j < 8; j++) {
-	    OUTREG(RADEON_SURFACE0_INFO + 16 * j, 0);
-	    OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * j, 0);
-	    OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * j, 0);
+	/* empty the surfaces */
+	if (info->ChipFamily < CHIP_FAMILY_R600) {
+	    unsigned char *RADEONMMIO = info->MMIO;
+	    unsigned int j;
+	    for (j = 0; j < 8; j++) {
+		OUTREG(RADEON_SURFACE0_INFO + 16 * j, 0);
+		OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * j, 0);
+		OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * j, 0);
+	    }
 	}
     }
 
@@ -3428,7 +3578,7 @@ Bool RADEONScreenInit(int scrnIndex, Scr
 #ifdef XF86DRI
 	if (hasDRI) {
 	    info->accelDFS = xf86ReturnOptValBool(info->Options, OPTION_ACCEL_DFS,
-						  info->cardType != CARD_AGP);
+                                                  info->cardType != CARD_AGP);
 
 	    /* Reserve approx. half of offscreen memory for local textures by
 	     * default, can be overridden with Option "FBTexPercent".
@@ -3454,7 +3604,7 @@ Bool RADEONScreenInit(int scrnIndex, Scr
 #endif
 
 #if defined(XF86DRI) && defined(USE_XAA)
-    if (!info->useEXA && hasDRI) {
+    if (!info->useEXA && hasDRI && !info->drm_mm) {
 	info->dri->textureSize = -1;
 	if (xf86GetOptValInteger(info->Options, OPTION_FBTEX_PERCENT,
 				 &(info->dri->textureSize))) {
@@ -3472,7 +3622,7 @@ Bool RADEONScreenInit(int scrnIndex, Scr
 #endif
 
 #ifdef USE_XAA
-    if (!info->useEXA && !hasDRI && !RADEONSetupMemXAA(scrnIndex, pScreen))
+    if (!info->useEXA && !hasDRI && !info->drm_mm && !RADEONSetupMemXAA(scrnIndex, pScreen))
 	return FALSE;
 #endif
 
@@ -3493,7 +3643,7 @@ Bool RADEONScreenInit(int scrnIndex, Scr
 			    info->CurrentLayout.pixel_bytes);
 	int  maxy        = info->FbMapSize / width_bytes;
 
-	if (maxy <= pScrn->virtualY * 3) {
+	if (maxy <= pScrn->virtualY * 3 && !info->drm_mm) {
 	    xf86DrvMsg(scrnIndex, X_ERROR,
 		       "Static buffer allocation failed.  Disabling DRI.\n");
 	    xf86DrvMsg(scrnIndex, X_ERROR,
@@ -3503,19 +3653,52 @@ Bool RADEONScreenInit(int scrnIndex, Scr
 			info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024);
 	    info->directRenderingEnabled = FALSE;
 	} else {
-	    info->directRenderingEnabled = RADEONDRIScreenInit(pScreen);
+        info->directRenderingEnabled = FALSE;
+#ifdef DRI2
+        if (info->drm_mm) {
+            info->directRenderingEnabled = radeon_dri2_screen_init(pScreen);
+        }
+#endif
+        if (!info->directRenderingEnabled) {
+    	    info->directRenderingEnabled = RADEONDRIScreenInit(pScreen);
+        }
 	}
     }
 
-    /* Tell DRI about new memory map */
-    if (info->directRenderingEnabled && info->dri->newMemoryMap) {
-        if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) {
+    front_ptr = info->FB;
+    if (info->drm_mm) {
+	if (info->directRenderingEnabled && info->dri->newMemoryMap) {
+	    if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "[drm] failed to enable new memory map\n");
+		RADEONDRICloseScreen(pScreen);
+		info->directRenderingEnabled = FALSE;		
+	    }
+	}
+	info->bufmgr = radeon_bufmgr_gem_init(info->dri->drmFD);
+	drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr);
+
+	radeon_bufmgr_gem_set_limit(info->bufmgr, RADEON_GEM_DOMAIN_GTT, info->mm.gart_size - info->dri->gartTexMapSize);
+    
+	radeon_setup_kernel_mem(pScreen);
+	front_ptr = info->mm.front_buffer->virtual;
+	info->accel_state->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) << 22));
+    } else {
+
+	/* Tell DRI about new memory map */
+	if (info->directRenderingEnabled && info->dri->newMemoryMap) {
+	    if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) {
 		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 			   "[drm] failed to enable new memory map\n");
 		RADEONDRICloseScreen(pScreen);
 		info->directRenderingEnabled = FALSE;
+	    }
 	}
     }
+
+    if (info->directRenderingEnabled == TRUE && !info->dri2.enabled)
+        RADEONDRIDoMappings(pScreen);
+
 #endif
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "Initializing fb layer\n");
@@ -3539,7 +3722,7 @@ Bool RADEONScreenInit(int scrnIndex, Scr
 
     if (info->r600_shadow_fb == FALSE) {
 	/* Init fb layer */
-	if (!fbScreenInit(pScreen, info->FB,
+	if (!fbScreenInit(pScreen, front_ptr,
 			  pScrn->virtualX, pScrn->virtualY,
 			  pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
 			  pScrn->bitsPerPixel))
@@ -3581,8 +3764,10 @@ Bool RADEONScreenInit(int scrnIndex, Scr
     /* restore the memory map here otherwise we may get a hang when
      * initializing the drm below
      */
-    RADEONInitMemMapRegisters(pScrn, info->ModeReg, info);
-    RADEONRestoreMemMapRegisters(pScrn, info->ModeReg);
+    if (!info->drm_mode_setting) {
+    	RADEONInitMemMapRegisters(pScrn, info->ModeReg, info);
+    	RADEONRestoreMemMapRegisters(pScrn, info->ModeReg);
+    }
 
     /* Backing store setup */
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
@@ -3592,7 +3777,7 @@ Bool RADEONScreenInit(int scrnIndex, Scr
 
     /* DRI finalisation */
 #ifdef XF86DRI
-    if (info->directRenderingEnabled && info->cardType==CARD_PCIE &&
+    if (!info->drm_mm && info->directRenderingEnabled && info->cardType==CARD_PCIE &&
         info->dri->pKernelDRMVersion->version_minor >= 19)
     {
       if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_PCIGART_LOCATION, info->dri->pciGartOffset) < 0)
@@ -3608,14 +3793,24 @@ Bool RADEONScreenInit(int scrnIndex, Scr
     if (info->directRenderingEnabled) {
         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		       "DRI Finishing init !\n");
+    if (!info->dri2.enabled) {
 	info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen);
     }
+    }
     if (info->directRenderingEnabled) {
+
+	if (info->drm_mm)
+    if (!info->dri2.enabled) {
+	    radeon_update_dri_buffers(pScreen);
+    }
+    
 	/* DRI final init might have changed the memory map, we need to adjust
 	 * our local image to make sure we restore them properly on mode
 	 * changes or VT switches
 	 */
-	RADEONAdjustMemMapRegisters(pScrn, info->ModeReg);
+	if (!info->drm_mode_setting) {
+	    RADEONAdjustMemMapRegisters(pScrn, info->ModeReg);
+	}
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
 
@@ -3717,8 +3912,14 @@ Bool RADEONScreenInit(int scrnIndex, Scr
            pScrn->virtualY * pScrn->displayWidth * info->CurrentLayout.pixel_bytes);
 
     /* set the modes with desired rotation, etc. */
-    if (!xf86SetDesiredModes (pScrn))
+    pScrn->pScreen = pScreen;
+    if (info->drm_mode_setting) {
+      if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+	return FALSE;
+    } else {
+      if (!xf86SetDesiredModes (pScrn))
 	return FALSE;
+    }
 
     /* Provide SaveScreen & wrap BlockHandler and CloseScreen */
     /* Wrap CloseScreen */
@@ -3738,18 +3939,24 @@ Bool RADEONScreenInit(int scrnIndex, Scr
     pScrn->PointerMoved = RADEONPointerMoved;
 
     /* Colormap setup */
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
-                   "Initializing color map\n");
-    if (!miCreateDefColormap(pScreen)) return FALSE;
-    /* all radeons support 10 bit CLUTs */
-    if (!xf86HandleColormaps(pScreen, 256, 10,
-			     RADEONLoadPalette, NULL,
-			     CMAP_PALETTED_TRUECOLOR
+    if (!info->drm_mode_setting) {
+   	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+                       "Initializing color map\n");
+        if (!miCreateDefColormap(pScreen))
+            return FALSE;
+        /* all radeons support 10 bit CLUTs */
+        if (!xf86HandleColormaps(pScreen, 256, 10,
+			         RADEONLoadPalette, NULL,
+			         CMAP_PALETTED_TRUECOLOR
 #if 0 /* This option messes up text mode! (eich@suse.de) */
-			     | CMAP_LOAD_EVEN_IF_OFFSCREEN
+			         | CMAP_LOAD_EVEN_IF_OFFSCREEN
 #endif
-			     | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE;
-
+			         | CMAP_RELOAD_ON_MODE_SWITCH))
+            return FALSE;
+    } else {
+	if (!drmmode_setup_colormap(pScreen, pScrn))
+	    return FALSE;
+    }
     /* Note unused options */
     if (serverGeneration == 1)
 	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
@@ -5288,7 +5495,7 @@ Bool RADEONSwitchMode(int scrnIndex, Dis
 #ifdef XF86DRI
     Bool           CPStarted   = info->cp->CPStarted;
 
-    if (CPStarted) {
+    if (CPStarted && !info->drm_mode_setting) {
 	DRILock(pScrn->pScreen, 0);
 	RADEONCP_STOP(pScrn, info);
     }
@@ -5311,8 +5518,10 @@ Bool RADEONSwitchMode(int scrnIndex, Dis
 #endif
     }
 
-    if (info->accelOn)
-        RADEON_SYNC(info, pScrn);
+    if (!info->drm_mode_setting) {
+    	if (info->accelOn)
+       	    RADEON_SYNC(info, pScrn);
+    }
 
     ret = xf86SetSingleMode (pScrn, mode, RR_Rotate_0);
 
@@ -5324,16 +5533,19 @@ Bool RADEONSwitchMode(int scrnIndex, Dis
 	/* xf86SetRootClip would do, but can't access that here */
     }
 
-    if (info->accelOn) {
-        RADEON_SYNC(info, pScrn);
-	if (info->ChipFamily < CHIP_FAMILY_R600)
-	    RADEONEngineRestore(pScrn);
-    }
+    if (!info->drm_mode_setting)
+        if (info->accelOn) {
+           RADEON_SYNC(info, pScrn);
+	   if (info->ChipFamily < CHIP_FAMILY_R600)
+	       RADEONEngineRestore(pScrn);
+        }
 
 #ifdef XF86DRI
-    if (CPStarted) {
-	RADEONCP_START(pScrn, info);
-	DRIUnlock(pScrn->pScreen);
+    if (!info->drm_mode_setting) {
+    	if (CPStarted) {
+		RADEONCP_START(pScrn, info);
+		DRIUnlock(pScrn->pScreen);
+    	}
     }
 #endif
 
@@ -5531,6 +5743,11 @@ void RADEONAdjustFrame(int scrnIndex, in
     xf86OutputPtr  output = config->output[config->compat_output];
     xf86CrtcPtr	crtc = output->crtc;
 
+    if (info->drm_mode_setting) {
+	drmmode_adjust_frame(pScrn, &info->drmmode, x, y, flags);
+	return;
+    }
+
     /* not handled */
     if (IS_AVIVO_VARIANT)
 	return;
@@ -5570,80 +5787,104 @@ Bool RADEONEnterVT(int scrnIndex, int fl
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "RADEONEnterVT\n");
 
-    if (!radeon_card_posted(pScrn)) { /* Softboot V_BIOS */
-	if (info->IsAtomBios) {
-	    rhdAtomASICInit(info->atomBIOS);
-	} else {
-	    xf86Int10InfoPtr pInt;
-
-	    pInt = xf86InitInt10 (info->pEnt->index);
-	    if (pInt) {
-		pInt->num = 0xe6;
-		xf86ExecX86int10 (pInt);
-		xf86FreeInt10 (pInt);
+    if (!info->drm_mode_setting) {
+	if (!radeon_card_posted(pScrn)) { /* Softboot V_BIOS */
+	    if (info->IsAtomBios) {
+		rhdAtomASICInit(info->atomBIOS);
 	    } else {
-		RADEONGetBIOSInitTableOffsets(pScrn);
-		RADEONPostCardFromBIOSTables(pScrn);
+		xf86Int10InfoPtr pInt;
+
+		pInt = xf86InitInt10 (info->pEnt->index);
+		if (pInt) {
+		    pInt->num = 0xe6;
+		    xf86ExecX86int10 (pInt);
+		    xf86FreeInt10 (pInt);
+		} else {
+		    RADEONGetBIOSInitTableOffsets(pScrn);
+		    RADEONPostCardFromBIOSTables(pScrn);
+		}
 	    }
 	}
-    }
 
-    /* Makes sure the engine is idle before doing anything */
-    RADEONWaitForIdleMMIO(pScrn);
+	/* Makes sure the engine is idle before doing anything */
+	RADEONWaitForIdleMMIO(pScrn);
 
-    if (info->IsMobility && !IS_AVIVO_VARIANT) {
-	if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
-	    RADEONSetDynamicClock(pScrn, 1);
-	} else {
-	    RADEONSetDynamicClock(pScrn, 0);
-	}
-    } else if (IS_AVIVO_VARIANT) {
-	if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
-	    atombios_static_pwrmgt_setup(pScrn, 1);
-	    atombios_dyn_clk_setup(pScrn, 1);
+	if (info->IsMobility && !IS_AVIVO_VARIANT) {
+	    if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
+		RADEONSetDynamicClock(pScrn, 1);
+	    } else {
+		RADEONSetDynamicClock(pScrn, 0);
+	    }
+	} else if (IS_AVIVO_VARIANT) {
+	    if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
+		atombios_static_pwrmgt_setup(pScrn, 1);
+		atombios_dyn_clk_setup(pScrn, 1);
+	    }
 	}
+
+	if (IS_R300_VARIANT || IS_RV100_VARIANT)
+	    RADEONForceSomeClocks(pScrn);
+    } else {
+	int ret;
+	ret = ioctl(info->dri->drmFD, DRM_IOCTL_SET_MASTER, NULL);
+	if (ret == -EINVAL)
+		ErrorF("Unable to retrieve master\n");
     }
 
-    if (IS_R300_VARIANT || IS_RV100_VARIANT)
-	RADEONForceSomeClocks(pScrn);
+    if (info->drm_mm) {
+	info->accel_state->XInited3D = FALSE;
+	info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+    }
 
-    for (i = 0; i < config->num_crtc; i++)
-	radeon_crtc_modeset_ioctl(config->crtc[i], TRUE);
+    if (info->directRenderingEnabled)
+    	radeon_update_dri_buffers(pScrn->pScreen);
 
     pScrn->vtSema = TRUE;
 
-    /* Clear the framebuffer */
-    memset(info->FB + pScrn->fbOffset, 0,
-           pScrn->virtualY * pScrn->displayWidth * info->CurrentLayout.pixel_bytes);
+    if (!info->drm_mode_setting) {
+	for (i = 0; i < config->num_crtc; i++)
+	    radeon_crtc_modeset_ioctl(config->crtc[i], TRUE);
 
-    if (!xf86SetDesiredModes(pScrn))
+	/* Clear the framebuffer */
+	memset(info->FB + pScrn->fbOffset, 0,
+	       pScrn->virtualY * pScrn->displayWidth * info->CurrentLayout.pixel_bytes);
+    }
+
+    if (info->drm_mode_setting) {
+      if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+	return FALSE;
+    } else {
+      if (!xf86SetDesiredModes(pScrn))
 	return FALSE;
+    }
 
-    if (info->ChipFamily < CHIP_FAMILY_R600)
-        RADEONRestoreSurfaces(pScrn, info->ModeReg);
+    if (!info->drm_mode_setting) {
+	if (info->ChipFamily < CHIP_FAMILY_R600)
+	    RADEONRestoreSurfaces(pScrn, info->ModeReg);
 #ifdef XF86DRI
-    if (info->directRenderingEnabled) {
-    	if (info->cardType == CARD_PCIE &&
-	    info->dri->pKernelDRMVersion->version_minor >= 19 &&
-	    info->FbSecureSize) {
+	if (info->directRenderingEnabled) {
+	    if (info->cardType == CARD_PCIE &&
+		info->dri->pKernelDRMVersion->version_minor >= 19 &&
+		info->FbSecureSize) {
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	    unsigned char *RADEONMMIO = info->MMIO;
-	    unsigned int sctrl = INREG(RADEON_SURFACE_CNTL);
+		unsigned char *RADEONMMIO = info->MMIO;
+		unsigned int sctrl = INREG(RADEON_SURFACE_CNTL);
 
-	    /* we need to backup the PCIE GART TABLE from fb memory */
-	    OUTREG(RADEON_SURFACE_CNTL, 0);
+		/* we need to backup the PCIE GART TABLE from fb memory */
+		OUTREG(RADEON_SURFACE_CNTL, 0);
 #endif
-	    memcpy(info->FB + info->dri->pciGartOffset, info->dri->pciGartBackup, info->dri->pciGartSize);
+		memcpy(info->FB + info->dri->pciGartOffset, info->dri->pciGartBackup, info->dri->pciGartSize);
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	    OUTREG(RADEON_SURFACE_CNTL, sctrl);
+		OUTREG(RADEON_SURFACE_CNTL, sctrl);
 #endif
-    	}
+	    }
 
-	/* get the DRI back into shape after resume */
-	RADEONDRISetVBlankInterrupt (pScrn, TRUE);
-	RADEONDRIResume(pScrn->pScreen);
-	RADEONAdjustMemMapRegisters(pScrn, info->ModeReg);
+	    /* get the DRI back into shape after resume */
+	    RADEONDRISetVBlankInterrupt (pScrn, TRUE);
+	    RADEONDRIResume(pScrn->pScreen);
+	    RADEONAdjustMemMapRegisters(pScrn, info->ModeReg);
 
+	}
     }
 #endif
     /* this will get XVideo going again, but only if XVideo was initialised
@@ -5658,7 +5899,7 @@ Bool RADEONEnterVT(int scrnIndex, int fl
 	info->accel_state->XInited3D = FALSE;
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled) {
+    if (info->directRenderingEnabled && !info->drm_mode_setting) {
         if (info->ChipFamily >= CHIP_FAMILY_R600)
 		R600LoadShaders(pScrn);
 	RADEONCP_START(pScrn, info);
@@ -5682,27 +5923,29 @@ void RADEONLeaveVT(int scrnIndex, int fl
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "RADEONLeaveVT\n");
 #ifdef XF86DRI
-    if (RADEONPTR(pScrn)->directRenderingInited) {
-
-	RADEONDRISetVBlankInterrupt (pScrn, FALSE);
-	DRILock(pScrn->pScreen, 0);
-	RADEONCP_STOP(pScrn, info);
-
-        if (info->cardType == CARD_PCIE &&
-	    info->dri->pKernelDRMVersion->version_minor >= 19 &&
-	    info->FbSecureSize) {
+    if (info->directRenderingInited || info->dri2.enabled) {
+	if (!info->drm_mode_setting) {
+	    RADEONDRISetVBlankInterrupt (pScrn, FALSE);
+	    DRILock(pScrn->pScreen, 0);
+	    RADEONCP_STOP(pScrn, info);
+
+	    if (info->cardType == CARD_PCIE &&
+		info->dri->pKernelDRMVersion->version_minor >= 19 &&
+		info->FbSecureSize) {
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	    unsigned char *RADEONMMIO = info->MMIO;
-	    unsigned int sctrl = INREG(RADEON_SURFACE_CNTL);
+                unsigned char *RADEONMMIO = info->MMIO;
+	        unsigned int sctrl = INREG(RADEON_SURFACE_CNTL);
 
-            /* we need to backup the PCIE GART TABLE from fb memory */
-	    OUTREG(RADEON_SURFACE_CNTL, 0);
+                /* we need to backup the PCIE GART TABLE from fb memory */
+	        OUTREG(RADEON_SURFACE_CNTL, 0);
 #endif
-            memcpy(info->dri->pciGartBackup, (info->FB + info->dri->pciGartOffset), info->dri->pciGartSize);
+		/* we need to backup the PCIE GART TABLE from fb memory */
+		memcpy(info->dri->pciGartBackup, (info->FB + info->dri->pciGartOffset), info->dri->pciGartSize);
 #if X_BYTE_ORDER == X_BIG_ENDIAN
-	    OUTREG(RADEON_SURFACE_CNTL, sctrl);
+	        OUTREG(RADEON_SURFACE_CNTL, sctrl);
 #endif
-        }
+	    }
+	}
 
 	/* Make sure 3D clients will re-upload textures to video RAM */
 	if (info->dri->textureSize) {
@@ -5718,6 +5961,11 @@ void RADEONLeaveVT(int scrnIndex, int fl
 		i = list[i].next;
 	    } while (i != 0);
 	}
+
+	if (info->drm_mode_setting)
+		ioctl(info->dri->drmFD, DRM_IOCTL_DROP_MASTER, NULL);
+		
+	
     }
 #endif
 
@@ -5744,10 +5992,17 @@ void RADEONLeaveVT(int scrnIndex, int fl
 
     xf86_hide_cursors (pScrn);
 
-    RADEONRestore(pScrn);
+    if (info->drm_mm) {
+	info->accel_state->XInited3D = FALSE;
+	info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
+    }
+
+    if (!info->drm_mode_setting) {
+	RADEONRestore(pScrn);
 
-    for (i = 0; i < config->num_crtc; i++)
-	radeon_crtc_modeset_ioctl(config->crtc[i], FALSE);
+	for (i = 0; i < config->num_crtc; i++)
+	    radeon_crtc_modeset_ioctl(config->crtc[i], FALSE);
+    }
 
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "Ok, leaving now...\n");
@@ -5801,7 +6056,8 @@ static Bool RADEONCloseScreen(int scrnIn
 #endif /* USE_XAA */
 
     if (pScrn->vtSema) {
-	RADEONRestore(pScrn);
+        if (!info->drm_mode_setting)
+	    RADEONRestore(pScrn);
     }
 
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
@@ -5836,6 +6092,7 @@ static Bool RADEONCloseScreen(int scrnIn
     info->DGAModes = NULL;
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "Unmapping memory\n");
+
     RADEONUnmapMem(pScrn);
 
     pScrn->vtSema = FALSE;
diff -up xf86-video-ati-6.12.2/src/radeon_drm.h.modeset xf86-video-ati-6.12.2/src/radeon_drm.h
--- xf86-video-ati-6.12.2/src/radeon_drm.h.modeset	2008-12-01 17:20:59.000000000 -0500
+++ xf86-video-ati-6.12.2/src/radeon_drm.h	2009-05-21 11:01:45.000000000 -0400
@@ -303,7 +303,8 @@ typedef union {
 #define RADEON_INDEX_PRIM_OFFSET	20
 
 #define RADEON_SCRATCH_REG_OFFSET	32
-#define R600_SCRATCH_REG_OFFSET	        256
+
+#define R600_SCRATCH_REG_OFFSET         256
 
 #define RADEON_NR_SAREA_CLIPRECTS	12
 
@@ -493,6 +494,16 @@ typedef struct {
 #define DRM_RADEON_SETPARAM   0x19
 #define DRM_RADEON_SURF_ALLOC 0x1a
 #define DRM_RADEON_SURF_FREE  0x1b
+/* KMS ioctl */
+#define DRM_RADEON_GEM_INFO		0x1c
+#define DRM_RADEON_GEM_CREATE		0x1d
+#define DRM_RADEON_GEM_MMAP		0x1e
+#define DRM_RADEON_GEM_PREAD		0x21
+#define DRM_RADEON_GEM_PWRITE		0x22
+#define DRM_RADEON_GEM_SET_DOMAIN	0x23
+#define DRM_RADEON_GEM_WAIT_IDLE	0x24
+#define DRM_RADEON_CS			0x26
+#define DRM_RADEON_INFO			0x27
 
 #define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
 #define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
@@ -521,6 +532,17 @@ typedef struct {
 #define DRM_IOCTL_RADEON_SETPARAM   DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t)
 #define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
 #define DRM_IOCTL_RADEON_SURF_FREE  DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
+/* KMS */
+#define DRM_IOCTL_RADEON_GEM_INFO	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info)
+#define DRM_IOCTL_RADEON_GEM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create)
+#define DRM_IOCTL_RADEON_GEM_MMAP	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap)
+#define DRM_IOCTL_RADEON_GEM_PREAD	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread)
+#define DRM_IOCTL_RADEON_GEM_PWRITE	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite)
+#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN	DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain)
+#define DRM_IOCTL_RADEON_GEM_WAIT_IDLE	DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) 
+#define DRM_IOCTL_RADEON_CS		DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs)
+#define DRM_IOCTL_RADEON_INFO		DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info)
+
 
 typedef struct drm_radeon_init {
 	enum {
@@ -528,10 +550,10 @@ typedef struct drm_radeon_init {
 		RADEON_CLEANUP_CP = 0x02,
 		RADEON_INIT_R200_CP = 0x03,
 		RADEON_INIT_R300_CP = 0x04,
-		RADEON_INIT_R600_CP = 0x05,
+		RADEON_INIT_R600_CP = 0x05
 	} func;
 	unsigned long sarea_priv_offset;
-	int is_pci; /* for overriding only */
+	int is_pci;
 	int cp_mode;
 	int gart_size;
 	int ring_size;
@@ -543,9 +565,8 @@ typedef struct drm_radeon_init {
 	unsigned int depth_bpp;
 	unsigned int depth_offset, depth_pitch;
 
-	/* DEPRECATED commented out below to allow for -Werror build */
-	unsigned long fb_offset;	/* deprecated, driver asks hardware */
-	unsigned long mmio_offset;	/* deprecated, driver asks hardware */
+	unsigned long fb_offset;
+	unsigned long mmio_offset;
 	unsigned long ring_offset;
 	unsigned long ring_rptr_offset;
 	unsigned long buffers_offset;
@@ -581,7 +602,7 @@ typedef struct drm_radeon_clear {
 	unsigned int clear_depth;
 	unsigned int color_mask;
 	unsigned int depth_mask;	/* misnamed field:  should be stencil */
-	drm_radeon_clear_rect_t  *depth_boxes;
+	drm_radeon_clear_rect_t *depth_boxes;
 } drm_radeon_clear_t;
 
 typedef struct drm_radeon_vertex {
@@ -607,9 +628,9 @@ typedef struct drm_radeon_vertex2 {
 	int idx;		/* Index of vertex buffer */
 	int discard;		/* Client finished with buffer? */
 	int nr_states;
-	drm_radeon_state_t  *state;
+	drm_radeon_state_t *state;
 	int nr_prims;
-	drm_radeon_prim_t  *prim;
+	drm_radeon_prim_t *prim;
 } drm_radeon_vertex2_t;
 
 /* v1.3 - obsoletes drm_radeon_vertex2
@@ -624,15 +645,15 @@ typedef struct drm_radeon_vertex2 {
  */
 typedef struct drm_radeon_cmd_buffer {
 	int bufsz;
-	char  *buf;
+	char *buf;
 	int nbox;
-	struct drm_clip_rect  *boxes;
+	struct drm_clip_rect *boxes;
 } drm_radeon_cmd_buffer_t;
 
 typedef struct drm_radeon_tex_image {
 	unsigned int x, y;	/* Blit coordinates */
 	unsigned int width, height;
-	const void  *data;
+	const void *data;
 } drm_radeon_tex_image_t;
 
 typedef struct drm_radeon_texture {
@@ -641,11 +662,11 @@ typedef struct drm_radeon_texture {
 	int format;
 	int width;		/* Texture image coordinates */
 	int height;
-	drm_radeon_tex_image_t  *image;
+	drm_radeon_tex_image_t *image;
 } drm_radeon_texture_t;
 
 typedef struct drm_radeon_stipple {
-	unsigned int  *mask;
+	unsigned int *mask;
 } drm_radeon_stipple_t;
 
 typedef struct drm_radeon_indirect {
@@ -655,9 +676,6 @@ typedef struct drm_radeon_indirect {
 	int discard;
 } drm_radeon_indirect_t;
 
-#define RADEON_INDIRECT_DISCARD (1 << 0)
-#define RADEON_INDIRECT_NOFLUSH (1 << 1)
-
 /* enum for card type parameters */
 #define RADEON_CARD_PCI 0
 #define RADEON_CARD_AGP 1
@@ -683,10 +701,11 @@ typedef struct drm_radeon_indirect {
 #define RADEON_PARAM_VBLANK_CRTC           13   /* VBLANK CRTC */
 #define RADEON_PARAM_FB_LOCATION           14   /* FB location */
 #define RADEON_PARAM_NUM_GB_PIPES          15   /* num GB pipes */
+#define RADEON_PARAM_DEVICE_ID             16
 
 typedef struct drm_radeon_getparam {
 	int param;
-	void  *value;
+	void *value;
 } drm_radeon_getparam_t;
 
 /* 1.6: Set up a memory manager for regions of shared memory:
@@ -698,7 +717,7 @@ typedef struct drm_radeon_mem_alloc {
 	int region;
 	int alignment;
 	int size;
-	int  *region_offset;	/* offset from start of fb or GART */
+	int *region_offset;	/* offset from start of fb or GART */
 } drm_radeon_mem_alloc_t;
 
 typedef struct drm_radeon_mem_free {
@@ -715,7 +734,7 @@ typedef struct drm_radeon_mem_init_heap 
 /* 1.6: Userspace can request & wait on irq's:
  */
 typedef struct drm_radeon_irq_emit {
-	int  *irq_seq;
+	int *irq_seq;
 } drm_radeon_irq_emit_t;
 
 typedef struct drm_radeon_irq_wait {
@@ -734,7 +753,6 @@ typedef struct drm_radeon_setparam {
 #define RADEON_SETPARAM_FB_LOCATION    1	/* determined framebuffer location */
 #define RADEON_SETPARAM_SWITCH_TILING  2	/* enable/disable color tiling */
 #define RADEON_SETPARAM_PCIGART_LOCATION 3	/* PCI Gart Location */
-
 #define RADEON_SETPARAM_NEW_MEMMAP 4		/* Use new memory map */
 #define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5    /* PCI GART Table Size */
 #define RADEON_SETPARAM_VBLANK_CRTC 6           /* VBLANK CRTC */
@@ -753,4 +771,112 @@ typedef struct drm_radeon_surface_free {
 #define	DRM_RADEON_VBLANK_CRTC1		1
 #define	DRM_RADEON_VBLANK_CRTC2		2
 
+/*
+ * Kernel modesetting world below.
+ */
+#define RADEON_GEM_DOMAIN_CPU		0x1
+#define RADEON_GEM_DOMAIN_GTT		0x2
+#define RADEON_GEM_DOMAIN_VRAM		0x4
+
+struct drm_radeon_gem_info {
+	uint64_t	gart_size;
+	uint64_t	vram_size;
+	uint64_t	vram_visible;
+};
+
+#define RADEON_GEM_NO_BACKING_STORE 1
+
+struct drm_radeon_gem_create {
+	uint64_t	size;
+	uint64_t	alignment;
+	uint32_t	handle;
+	uint32_t	initial_domain;
+	uint32_t	flags;
+};
+
+struct drm_radeon_gem_mmap {
+	uint32_t	handle;
+	uint32_t	pad;
+	uint64_t	offset;
+	uint64_t	size;
+	uint64_t	addr_ptr;
+};
+
+struct drm_radeon_gem_set_domain {
+	uint32_t	handle;
+	uint32_t		read_domains;
+	uint32_t		write_domain;
+};
+
+struct drm_radeon_gem_wait_idle {
+	uint32_t	handle;
+	uint32_t	pad;
+};
+
+struct drm_radeon_gem_busy {
+	uint32_t	handle;
+	uint32_t	busy;
+};
+
+struct drm_radeon_gem_pread {
+	/** Handle for the object being read. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset into the object to read from */
+	uint64_t offset;
+	/** Length of data to read */
+	uint64_t size;
+	/** Pointer to write the data into. */
+	/* void *, but pointers are not 32/64 compatible */
+	uint64_t data_ptr;
+};
+
+struct drm_radeon_gem_pwrite {
+	/** Handle for the object being written to. */
+	uint32_t handle;
+	uint32_t pad;
+	/** Offset into the object to write to */
+	uint64_t offset;
+	/** Length of data to write */
+	uint64_t size;
+	/** Pointer to read the data from. */
+	/* void *, but pointers are not 32/64 compatible */
+	uint64_t data_ptr;
+};
+
+#define RADEON_CHUNK_ID_RELOCS	0x01
+#define RADEON_CHUNK_ID_IB	0x02
+
+struct drm_radeon_cs_chunk {
+	uint32_t		chunk_id;
+	uint32_t		length_dw;
+	uint64_t		chunk_data;
+};
+
+struct drm_radeon_cs_reloc {
+	uint32_t		handle;
+	uint32_t		read_domains;
+	uint32_t		write_domain;
+	uint32_t		flags;
+};
+
+struct drm_radeon_cs {
+	uint32_t		num_chunks;
+	uint32_t		cs_id;
+	/* this points to uint64_t * which point to cs chunks */
+	uint64_t		chunks;
+	/* updates to the limits after this CS ioctl */
+	uint64_t		gart_limit;
+	uint64_t		vram_limit;
+};
+
+#define RADEON_INFO_DEVICE_ID		0x00
+#define RADEON_INFO_NUM_GB_PIPES	0x01
+
+struct drm_radeon_info {
+	uint32_t		request;
+	uint32_t		pad;
+	uint64_t		value;
+};
+
 #endif
diff -up xf86-video-ati-6.12.2/src/radeon_exa.c.modeset xf86-video-ati-6.12.2/src/radeon_exa.c
--- xf86-video-ati-6.12.2/src/radeon_exa.c.modeset	2009-02-27 11:25:10.000000000 -0500
+++ xf86-video-ati-6.12.2/src/radeon_exa.c	2009-05-21 11:01:45.000000000 -0400
@@ -44,7 +44,7 @@
 #include "radeon_version.h"
 
 #include "xf86.h"
-
+#include "radeon_bufmgr_gem.h"
 
 /***********************************************************************/
 #define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn =  xf86Screens[pScr->myNum]; \
@@ -182,12 +182,25 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPt
 	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
 	uint32_t pitch, offset;
 	int bpp;
+	struct radeon_exa_pixmap_priv *driver_priv;
+
+    	driver_priv = exaGetPixmapDriverPrivate(pPix);
 
 	bpp = pPix->drawable.bitsPerPixel;
 	if (bpp == 24)
 		bpp = 8;
 
-	offset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+
+	/* validate the pixmap somewhere */
+	if (info->new_cs)
+	    offset = 0;
+	else { 
+	    if (driver_priv)
+		offset = driver_priv->bo->offset;
+	    else
+		offset = exaGetPixmapOffset(pPix);
+		offset += info->fbLocation + pScrn->fbOffset;
+	}
 	pitch = exaGetPixmapPitch(pPix);
 
 	return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
@@ -220,10 +233,27 @@ int RADEONBiggerCrtcArea(PixmapPtr pPix)
     return crtc_num;
 }
 
+Bool RADEONGetPixmapOffsetCS(PixmapPtr pPix, uint32_t *pitch_offset)
+{
+	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
+	uint32_t pitch, offset;
+	int bpp;
+
+	bpp = pPix->drawable.bitsPerPixel;
+	if (bpp == 24)
+		bpp = 8;
+
+	offset = exaGetPixmapOffset(pPix);
+	pitch = exaGetPixmapPitch(pPix);
+	return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
+}
+
 #if X_BYTE_ORDER == X_BIG_ENDIAN
 
 static unsigned long swapper_surfaces[6];
 
+#endif
+
 static Bool RADEONPrepareAccess(PixmapPtr pPix, int index)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
@@ -231,7 +261,31 @@ static Bool RADEONPrepareAccess(PixmapPt
     uint32_t offset = exaGetPixmapOffset(pPix);
     int bpp, soff;
     uint32_t size, flags;
+    struct radeon_exa_pixmap_priv *driver_priv;
+   
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    if (driver_priv) {
+
+	if (driver_priv->bo) {
+	    int ret;
+
+	    if (radeon_bufmgr_gem_has_references(driver_priv->bo))
+		RADEONCPFlushIndirect(pScrn, 0);
+
+	    radeon_bufmgr_gem_wait_rendering(driver_priv->bo);
+
+	    /* flush IB */
+	    ret = dri_bo_map(driver_priv->bo, 1);
+	    if (ret) {
+		FatalError("failed to map pixmap %d\n", ret);
+		return FALSE;
+	    }
+
+	    pPix->devPrivate.ptr = driver_priv->bo->virtual;
+	}
+    }
 
+#if X_BYTE_ORDER == X_BIG_ENDIAN
     /* Front buffer is always set with proper swappers */
     if (offset == 0)
         return TRUE;
@@ -287,6 +341,7 @@ static Bool RADEONPrepareAccess(PixmapPt
     OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset);
     OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1);
     swapper_surfaces[index] = offset;
+#endif
     return TRUE;
 }
 
@@ -296,7 +351,17 @@ static void RADEONFinishAccess(PixmapPtr
     unsigned char *RADEONMMIO = info->MMIO;
     uint32_t offset = exaGetPixmapOffset(pPix);
     int soff;
+    struct radeon_exa_pixmap_priv *driver_priv;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+    if (driver_priv) {
+	dri_bo_unmap(driver_priv->bo);
+    pPix->devPrivate.ptr = NULL;
+    }
+
 
+#if X_BYTE_ORDER == X_BIG_ENDIAN
     /* Front buffer is always set with proper swappers */
     if (offset == 0)
         return;
@@ -319,9 +384,92 @@ static void RADEONFinishAccess(PixmapPtr
     OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0);
     OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0);
     swapper_surfaces[index] = 0;
+#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
 }
 
-#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
+void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *new_priv;
+
+    new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv));
+    if (!new_priv)
+	return NULL;
+
+    if (size == 0)
+	return new_priv;
+
+    new_priv->bo = dri_bo_alloc(info->bufmgr, "exa pixmap", size,
+				align, 0);
+    if (!new_priv->bo) {
+	xfree(new_priv);
+	ErrorF("Failed to alloc memory\n");
+	return NULL;
+    }
+    
+    return new_priv;
+
+}
+
+static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
+    int ret;
+
+    dri_bo_unreference(driver_priv->bo);
+    xfree(driverPriv);
+}
+
+dri_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    
+#ifdef XF86DRM_MODE
+    struct radeon_exa_pixmap_priv *driver_priv;
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    if (driver_priv)
+	if (driver_priv->bo)
+ 	    return driver_priv->bo;
+#endif
+    return NULL;
+
+}
+
+void radeon_set_pixmap_bo(PixmapPtr pPix, dri_bo *bo)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+#ifdef XF86DRM_MODE
+    struct radeon_exa_pixmap_priv *driver_priv;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    if (driver_priv) {
+	if (driver_priv->bo)
+	    dri_bo_unreference(driver_priv->bo);
+
+	dri_bo_reference(bo);
+	driver_priv->bo = bo;
+    }
+#endif
+
+}
+
+static Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
+{
+    struct radeon_exa_pixmap_priv *driver_priv;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+    if (!driver_priv)
+       return FALSE;
+    if (driver_priv->bo)
+       return TRUE;
+    return FALSE;
+}
 
 #define ENTER_DRAW(x) TRACE
 #define LEAVE_DRAW(x) TRACE
@@ -332,6 +480,7 @@ static void RADEONFinishAccess(PixmapPtr
 #define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
 #define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
 #define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
+#define OUT_RELOC(x, read, write)            do {} while(0)
 #define FINISH_ACCEL()
 
 #ifdef RENDER
@@ -345,6 +494,7 @@ static void RADEONFinishAccess(PixmapPtr
 #undef OUT_ACCEL_REG
 #undef OUT_ACCEL_REG_F
 #undef FINISH_ACCEL
+#undef OUT_RELOC
 
 #ifdef XF86DRI
 
@@ -355,6 +505,7 @@ static void RADEONFinishAccess(PixmapPtr
 #define BEGIN_ACCEL(n)		BEGIN_RING(2*(n))
 #define OUT_ACCEL_REG(reg, val)	OUT_RING_REG(reg, val)
 #define FINISH_ACCEL()		ADVANCE_RING()
+#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write)
 
 #define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
 
@@ -393,122 +544,126 @@ Bool RADEONSetupMemEXA (ScreenPtr pScree
     if (info->accel_state->exa == NULL)
 	return FALSE;
 
-    /* Need to adjust screen size for 16 line tiles, and then make it align to.
-     * the buffer alignment requirement.
-     */
-    if (info->allowColorTiling)
-	screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride;
-    else
-	screen_size = pScrn->virtualY * byteStride;
-
-    info->accel_state->exa->memoryBase = info->FB;
-    info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize;
-    info->accel_state->exa->offScreenBase = screen_size;
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n",
-	       info->accel_state->exa->memorySize / 1024);
-
-    /* Reserve static area for hardware cursor */
-    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
-        int cursor_size = 64 * 4 * 64;
-        int align = IS_AVIVO_VARIANT ? 4096 : 256;
-        int c;
-
-        for (c = 0; c < xf86_config->num_crtc; c++) {
-            xf86CrtcPtr crtc = xf86_config->crtc[c];
-            RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
-
-            radeon_crtc->cursor_offset =
-                RADEON_ALIGN(info->accel_state->exa->offScreenBase, align);
-            info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size;
-
-            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-                       "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
-                       (cursor_size * xf86_config->num_crtc) / 1024,
-                       c,
-                       (unsigned int)radeon_crtc->cursor_offset);
-        }
-    }
-
-#if defined(XF86DRI)
-    if (info->directRenderingEnabled) {
-	int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size;
-
-	info->dri->frontOffset = 0;
-	info->dri->frontPitch = pScrn->displayWidth;
-
-        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Will use %d kb for front buffer at offset 0x%08x\n",
-	       screen_size / 1024, info->dri->frontOffset);
-	RADEONDRIAllocatePCIGARTTable(pScreen);
-	
-	if (info->cardType==CARD_PCIE)
-	  xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		     "Will use %d kb for PCI GART at offset 0x%08x\n",
-		     info->dri->pciGartSize / 1024,
-		     (int)info->dri->pciGartOffset);
-
-	/* Reserve a static area for the back buffer the same size as the
-	 * visible screen.  XXX: This would be better initialized in ati_dri.c
-	 * when GLX is set up, but the offscreen memory manager's allocations
-	 * don't last through VT switches, while the kernel's understanding of
-	 * offscreen locations does.
+    
+    if (info->drm_mm == FALSE) {
+	/* Need to adjust screen size for 16 line tiles, and then make it align to.
+	 * the buffer alignment requirement.
 	 */
-	info->dri->backPitch = pScrn->displayWidth;
-	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN);
-	if (!info->dri->noBackBuffer &&
-	    next + screen_size <= info->accel_state->exa->memorySize)
-	{
-	    info->dri->backOffset = next;
-	    info->accel_state->exa->offScreenBase = next + screen_size;
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Will use %d kb for back buffer at offset 0x%08x\n",
-		       screen_size / 1024, info->dri->backOffset);
+	if (info->allowColorTiling)
+	    screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride;
+	else
+	    screen_size = pScrn->virtualY * byteStride;
+
+	info->accel_state->exa->memoryBase = info->FB;
+	info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize;
+	info->accel_state->exa->offScreenBase = screen_size;
+
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n",
+		   info->accel_state->exa->memorySize / 1024);
+
+	/* Reserve static area for hardware cursor */
+	if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
+	    int cursor_size = 64 * 4 * 64;
+	    int align = IS_AVIVO_VARIANT ? 4096 : 256;
+	    int c;
+
+	    for (c = 0; c < xf86_config->num_crtc; c++) {
+		xf86CrtcPtr crtc = xf86_config->crtc[c];
+		RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+
+		radeon_crtc->cursor_offset =
+		    RADEON_ALIGN(info->accel_state->exa->offScreenBase, align);
+		info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size;
+		
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Will use %d kb for hardware cursor %d at offset 0x%08x\n",
+			   (cursor_size * xf86_config->num_crtc) / 1024,
+			   c,
+			   (unsigned int)radeon_crtc->cursor_offset);
+	    }
 	}
 
-	/* Reserve the static depth buffer, and adjust pitch and height to
-	 * handle tiling.
-	 */
-	info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
-	depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp;
-	next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN);
-	if (next + depth_size <= info->accel_state->exa->memorySize)
-	{
-	    info->dri->depthOffset = next;
-	    info->accel_state->exa->offScreenBase = next + depth_size;
+#if defined(XF86DRI)
+	if (info->directRenderingEnabled) {
+	    int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size;
+	    
+	    info->dri->frontOffset = 0;
+	    info->dri->frontPitch = pScrn->displayWidth;
+	    
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Will use %d kb for depth buffer at offset 0x%08x\n",
-		       depth_size / 1024, info->dri->depthOffset);
-	}
+		       "Will use %d kb for front buffer at offset 0x%08x\n",
+		       screen_size / 1024, info->dri->frontOffset);
+	    RADEONDRIAllocatePCIGARTTable(pScreen);
+
+	    if (info->cardType==CARD_PCIE)
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Will use %d kb for PCI GART at offset 0x%08x\n",
+			   info->dri->pciGartSize / 1024,
+			   (int)info->dri->pciGartOffset);
+
+	    /* Reserve a static area for the back buffer the same size as the
+	     * visible screen.  XXX: This would be better initialized in ati_dri.c
+	     * when GLX is set up, but the offscreen memory manager's allocations
+	     * don't last through VT switches, while the kernel's understanding of
+	     * offscreen locations does.
+	     */
+	    info->dri->backPitch = pScrn->displayWidth;
+	    next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN);
+	    if (!info->dri->noBackBuffer &&
+		next + screen_size <= info->accel_state->exa->memorySize)
+	    {
+		info->dri->backOffset = next;
+		info->accel_state->exa->offScreenBase = next + screen_size;
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Will use %d kb for back buffer at offset 0x%08x\n",
+			   screen_size / 1024, info->dri->backOffset);
+	    }
+
+	    /* Reserve the static depth buffer, and adjust pitch and height to
+	     * handle tiling.
+	     */
+	    info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
+	    depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp;
+	    next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN);
+	    if (next + depth_size <= info->accel_state->exa->memorySize)
+	    {
+		info->dri->depthOffset = next;
+		info->accel_state->exa->offScreenBase = next + depth_size;
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Will use %d kb for depth buffer at offset 0x%08x\n",
+			   depth_size / 1024, info->dri->depthOffset);
+	    }
 	
-	info->dri->textureSize *= (info->accel_state->exa->memorySize -
-				   info->accel_state->exa->offScreenBase) / 100;
+	    info->dri->textureSize *= (info->accel_state->exa->memorySize -
+				       info->accel_state->exa->offScreenBase) / 100;
 
-	l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS);
-	if (l < RADEON_LOG_TEX_GRANULARITY)
-	    l = RADEON_LOG_TEX_GRANULARITY;
-	info->dri->textureSize = (info->dri->textureSize >> l) << l;
-	if (info->dri->textureSize >= 512 * 1024) {
-	    info->dri->textureOffset = info->accel_state->exa->offScreenBase;
-	    info->accel_state->exa->offScreenBase += info->dri->textureSize;
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Will use %d kb for textures at offset 0x%08x\n",
-		       info->dri->textureSize / 1024, info->dri->textureOffset);
-	} else {
-	    /* Minimum texture size is for 2 256x256x32bpp textures */
-	    info->dri->textureSize = 0;
-	}
-    } else
+	    l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS);
+	    if (l < RADEON_LOG_TEX_GRANULARITY)
+		l = RADEON_LOG_TEX_GRANULARITY;
+	    info->dri->textureSize = (info->dri->textureSize >> l) << l;
+	    if (info->dri->textureSize >= 512 * 1024) {
+		info->dri->textureOffset = info->accel_state->exa->offScreenBase;
+		info->accel_state->exa->offScreenBase += info->dri->textureSize;
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Will use %d kb for textures at offset 0x%08x\n",
+			   info->dri->textureSize / 1024, info->dri->textureOffset);
+	    } else {
+		/* Minimum texture size is for 2 256x256x32bpp textures */
+		info->dri->textureSize = 0;
+	    }
+	} else
 #endif /* XF86DRI */
-    	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "Will use %d kb for front buffer at offset 0x%08x\n",
 		       screen_size / 1024, 0);
-
+	
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "Will use %ld kb for X Server offscreen at offset 0x%08lx\n",
 	       (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) /
 	       1024, info->accel_state->exa->offScreenBase);
 
+    }
+
     return TRUE;
 }
 
@@ -523,14 +678,23 @@ RADEONTexOffsetStart(PixmapPtr pPix)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
     unsigned long long offset;
-    exaMoveInPixmap(pPix);
-    ExaOffscreenMarkUsed(pPix);
+    struct radeon_exa_pixmap_priv *driver_priv;
 
-    offset = exaGetPixmapOffset(pPix);
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
 
-    if (offset > info->FbMapSize)
-	return ~0ULL;
-    else
-	return info->fbLocation + offset;
+    if (driver_priv) {
+        //offset = dri_bo_get_handle(driver_priv->bo);
+        offset = driver_priv->bo->offset;
+    } else {
+    	exaMoveInPixmap(pPix);
+        offset = exaGetPixmapOffset(pPix);
+    	if (offset > info->FbMapSize)
+		return ~0ULL;
+    	else
+    		offset += info->fbLocation;
+        ExaOffscreenMarkUsed(pPix);
+    }
+
+    return offset;
 }
 #endif
diff -up xf86-video-ati-6.12.2/src/radeon_exa_funcs.c.modeset xf86-video-ati-6.12.2/src/radeon_exa_funcs.c
--- xf86-video-ati-6.12.2/src/radeon_exa_funcs.c.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_exa_funcs.c	2009-05-21 11:01:45.000000000 -0400
@@ -74,21 +74,73 @@ FUNC_NAME(RADEONSync)(ScreenPtr pScreen,
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
+    if (info->new_cs)
+	    return;
+
     TRACE;
 
     if (info->accel_state->exaMarkerSynced != marker) {
-	FUNC_NAME(RADEONWaitForIdle)(pScrn);
+        FUNC_NAME(RADEONWaitForIdle)(pScrn);
 	info->accel_state->exaMarkerSynced = marker;
     }
 
     RADEONPTR(pScrn)->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
 }
 
+static void FUNC_NAME(Emit2DState)(ScrnInfoPtr pScrn, int op)
+{
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    uint32_t qwords;
+    int has_src;
+    ACCEL_PREAMBLE();
+
+    /* don't emit if no operation in progress */
+    if (info->state_2d.op == 0 && op == 0)
+	return;
+
+    has_src = info->state_2d.src_pitch_offset || (info->new_cs && info->state_2d.src_bo);
+
+    qwords = info->new_cs ? 10 : 9;
+    qwords += (has_src ? (info->new_cs ?  2 : 1) : 0);
+
+    BEGIN_ACCEL(qwords);
+    OUT_ACCEL_REG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right);
+    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl);
+    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr);
+    OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr);
+    OUT_ACCEL_REG(RADEON_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr);
+    OUT_ACCEL_REG(RADEON_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr);
+    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, info->state_2d.dp_write_mask);
+    OUT_ACCEL_REG(RADEON_DP_CNTL, info->state_2d.dp_cntl);
+
+    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
+    if (info->new_cs)
+	OUT_RELOC(info->state_2d.dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
+
+    if (has_src) {
+	    OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
+	    if (info->new_cs)
+		OUT_RELOC(info->state_2d.src_bo, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0);
+	    
+    }
+    FINISH_ACCEL();
+
+    if (op)
+	info->state_2d.op = op;
+    if (info->new_cs)
+	info->reemit_current2d = FUNC_NAME(Emit2DState);
+}
+
 static Bool
 FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
     uint32_t datatype, dst_pitch_offset;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int ret;
+    int retry_count = 0;
+    struct radeon_space_check bos[1];
+    int i;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -97,25 +149,58 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr 
 	RADEON_FALLBACK(("24bpp unsupported\n"));
     if (!RADEONGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype))
 	RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n"));
+
     if (!RADEONGetPixmapOffsetPitch(pPix, &dst_pitch_offset))
-	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n"));
+        RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n"));
+
+ retry:
+    if (info->new_cs) {
+      
+	i = 0;
+	driver_priv = exaGetPixmapDriverPrivate(pPix);
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = 0;
+	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;;
+	i++;
+
+	ret = dri_bufmgr_check_aperture_space(bos, i);
+	if (ret == BUFMGR_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == BUFMGR_SPACE_FLUSH) {
+	    RADEONCPFlushIndirect(pScrn, 1);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
 
     RADEON_SWITCH_TO_2D();
 
-    BEGIN_ACCEL(5);
-    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL,
-	    RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-	    RADEON_GMC_BRUSH_SOLID_COLOR |
-	    (datatype << 8) |
-	    RADEON_GMC_SRC_DATATYPE_COLOR |
-	    RADEON_ROP[alu].pattern |
-	    RADEON_GMC_CLR_CMP_CNTL_DIS);
-    OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg);
-    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, pm);
-    OUT_ACCEL_REG(RADEON_DP_CNTL,
-	(RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM));
-    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
-    FINISH_ACCEL();
+    info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX |
+					       RADEON_DEFAULT_SC_BOTTOM_MAX);
+    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
+    info->state_2d.dp_src_frgd_clr = 0xffffffff;
+    info->state_2d.dp_src_bkgd_clr = 0x00000000;
+    info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+					  RADEON_GMC_BRUSH_SOLID_COLOR |
+					  (datatype << 8) |
+					  RADEON_GMC_SRC_DATATYPE_COLOR |
+					  RADEON_ROP[alu].pattern |
+					  RADEON_GMC_CLR_CMP_CNTL_DIS);
+    info->state_2d.dp_brush_frgd_clr = fg;
+    info->state_2d.dp_cntl = (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM);
+    info->state_2d.dp_write_mask = pm;
+    info->state_2d.dst_pitch_offset = dst_pitch_offset;
+    info->state_2d.src_pitch_offset = 0;
+    info->state_2d.src_bo = NULL;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    if (driver_priv)
+      info->state_2d.dst_bo = driver_priv->bo;
+
+    FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID);
 
     return TRUE;
 }
@@ -146,6 +231,7 @@ FUNC_NAME(RADEONDoneSolid)(PixmapPtr pPi
 
     TRACE;
 
+    info->state_2d.op = 0;
     BEGIN_ACCEL(2);
     OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
     OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
@@ -153,6 +239,7 @@ FUNC_NAME(RADEONDoneSolid)(PixmapPtr pPi
     FINISH_ACCEL();
 }
 
+
 void
 FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
 			       uint32_t dst_pitch_offset, uint32_t datatype, int rop,
@@ -163,23 +250,28 @@ FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoP
 
     RADEON_SWITCH_TO_2D();
 
-    BEGIN_ACCEL(5);
-    OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL,
-	RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-	RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
-	RADEON_GMC_BRUSH_NONE |
-	(datatype << 8) |
-	RADEON_GMC_SRC_DATATYPE_COLOR |
-	RADEON_ROP[rop].rop |
-	RADEON_DP_SRC_SOURCE_MEMORY |
-	RADEON_GMC_CLR_CMP_CNTL_DIS);
-    OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask);
-    OUT_ACCEL_REG(RADEON_DP_CNTL,
-	((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
-	 (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)));
-    OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
-    OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset);
-    FINISH_ACCEL();
+    /* setup 2D state */
+    info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+					  RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+					  RADEON_GMC_BRUSH_NONE |
+					  (datatype << 8) |
+					  RADEON_GMC_SRC_DATATYPE_COLOR |
+					  RADEON_ROP[rop].rop |
+					  RADEON_DP_SRC_SOURCE_MEMORY |
+					  RADEON_GMC_CLR_CMP_CNTL_DIS);
+    info->state_2d.dp_cntl = ((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
+			       (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0));
+    info->state_2d.dp_brush_frgd_clr = 0xffffffff;
+    info->state_2d.dp_brush_bkgd_clr = 0x00000000;
+    info->state_2d.dp_src_frgd_clr = 0xffffffff;
+    info->state_2d.dp_src_bkgd_clr = 0x00000000;
+    info->state_2d.dp_write_mask = planemask;
+    info->state_2d.dst_pitch_offset = dst_pitch_offset;
+    info->state_2d.src_pitch_offset = src_pitch_offset;
+    info->state_2d.default_sc_bottom_right =  (RADEON_DEFAULT_SC_RIGHT_MAX
+						| RADEON_DEFAULT_SC_BOTTOM_MAX);
+
+    FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY);
 }
 
 static Bool
@@ -190,9 +282,46 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr p
 {
     RINFO_FROM_SCREEN(pDst->drawable.pScreen);
     uint32_t datatype, src_pitch_offset, dst_pitch_offset;
-
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int ret;
+    int retry_count = 0;
+    struct radeon_space_check bos[2];
+    int i;
     TRACE;
 
+retry:
+    if (info->new_cs) {
+      
+	i = 0;
+	driver_priv = exaGetPixmapDriverPrivate(pSrc);
+	info->state_2d.src_bo = driver_priv->bo;
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	bos[i].write_domain = 0;
+	i++;
+
+
+	driver_priv = exaGetPixmapDriverPrivate(pDst);
+	info->state_2d.dst_bo = driver_priv->bo;
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = 0;
+	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;;
+	i++;
+
+	ret = dri_bufmgr_check_aperture_space(bos, i);
+	if (ret == BUFMGR_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == BUFMGR_SPACE_FLUSH) {
+	    RADEONCPFlushIndirect(pScrn, 1);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
+
+
     info->accel_state->xdir = xdir;
     info->accel_state->ydir = ydir;
 
@@ -200,10 +329,11 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr p
 	RADEON_FALLBACK(("24bpp unsupported"));
     if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype))
 	RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n"));
+
     if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset))
-	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n"));
+        RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n"));
     if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset))
-	RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n"));
+        RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n"));
 
     FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset,
 				   datatype, rop, planemask);
@@ -251,6 +381,7 @@ FUNC_NAME(RADEONDoneCopy)(PixmapPtr pDst
 
     TRACE;
 
+    info->state_2d.op = 0;
     BEGIN_ACCEL(2);
     OUT_ACCEL_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
     OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
@@ -267,17 +398,27 @@ RADEONUploadToScreenCP(PixmapPtr pDst, i
 {
     RINFO_FROM_SCREEN(pDst->drawable.pScreen);
     unsigned int   bpp	     = pDst->drawable.bitsPerPixel;
+    int ret;
+    struct radeon_exa_pixmap_priv *driver_priv;
     unsigned int   hpass;
     uint32_t	   buf_pitch, dst_pitch_off;
 
     TRACE;
 
+    if (info->new_cs)
+	return FALSE;
+
     if (bpp < 8)
 	return FALSE;
 
-    if (info->directRenderingEnabled &&
-	RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off)) {
-	uint8_t *buf;
+    if (!info->directRenderingEnabled && !info->drm_mode_setting)
+        goto fallback;
+
+    if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off))
+        goto fallback;
+
+    {
+        uint8_t *buf;
 	int cpp = bpp / 8;
 	ACCEL_PREAMBLE();
 
@@ -297,20 +438,26 @@ RADEONUploadToScreenCP(PixmapPtr pDst, i
 	exaMarkSync(pDst->drawable.pScreen);
 	return TRUE;
     }
-
+fallback:
     return FALSE;
 }
 
 /* Emit blit with arbitrary source and destination offsets and pitches */
 static void
-RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, uint32_t src_pitch_offset,
+RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, dri_bo *src_bo, dri_bo *dst_bo,
+		uint32_t src_pitch_offset,
 		uint32_t dst_pitch_offset, int srcX, int srcY, int dstX, int dstY,
 		int w, int h)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
+    uint32_t qwords;
     ACCEL_PREAMBLE();
 
-    BEGIN_ACCEL(6);
+    qwords = 6;
+    if (src_bo && dst_bo)
+	qwords += 2;
+
+    BEGIN_ACCEL(qwords);
     OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL,
 		  RADEON_GMC_DST_PITCH_OFFSET_CNTL |
 		  RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
@@ -321,8 +468,14 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, uint3
 		  RADEON_DP_SRC_SOURCE_MEMORY |
 		  RADEON_GMC_CLR_CMP_CNTL_DIS |
 		  RADEON_GMC_WR_MSK_DIS);
+    
     OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset);
+    if (src_bo)
+	OUT_RELOC(src_bo, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0);
     OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
+    if (dst_bo)
+	OUT_RELOC(dst_bo, 0, RADEON_GEM_DOMAIN_GTT);
+
     OUT_ACCEL_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX);
     OUT_ACCEL_REG(RADEON_DST_Y_X, (dstY << 16) | dstX);
     OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
@@ -334,6 +487,174 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, uint3
     FINISH_ACCEL();
 }
 
+static Bool
+RADEON_DFS_CS2(PixmapPtr pSrc, int x, int y, int w, int h,
+		       char *dst, int dst_pitch)
+{
+    RINFO_FROM_SCREEN(pSrc->drawable.pScreen);
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int		   src_pitch = exaGetPixmapPitch(pSrc);
+    int		   bpp	     = pSrc->drawable.bitsPerPixel;
+    uint32_t src_offset;
+    /* force into GTT? */
+
+    if (!info->accelDFS)
+	return FALSE;
+	
+    driver_priv = exaGetPixmapDriverPrivate(pSrc);
+
+    radeon_bufmgr_gem_force_gtt(driver_priv->bo);
+    radeon_bufmgr_gem_wait_rendering(driver_priv->bo);
+
+    dri_bo_map(driver_priv->bo, 0);
+
+    src_offset = (x * bpp / 8) + (y * src_pitch);
+    w *= bpp / 8;
+
+    while (h--) {
+	    memcpy(dst, driver_priv->bo->virtual + src_offset, w);
+	    src_offset += src_pitch;
+	    dst += dst_pitch;
+    }
+    dri_bo_unmap(driver_priv->bo);
+    return TRUE;
+}
+
+static Bool
+RADEON_DFS_CS(PixmapPtr pSrc, int x, int y, int w, int h,
+		       char *dst, int dst_pitch)
+{
+    RINFO_FROM_SCREEN(pSrc->drawable.pScreen);
+    struct radeon_exa_pixmap_priv *driver_priv;
+    dri_bo *scratch_bo[2];
+    int i, ret;
+    uint32_t scratch_size = RADEON_BUFFER_SIZE / 2;
+    int		   bpp	     = pSrc->drawable.bitsPerPixel;
+    uint32_t scratch_pitch = (w * bpp/8 + 63) & ~63, scratch_off = 0;
+    uint32_t datatype;
+    int		   src_pitch = exaGetPixmapPitch(pSrc);
+    dri_bo *cur_scratch;
+    uint32_t src_pitch_offset;
+    struct radeon_space_check bos[3];
+    int retry_count;
+    
+    if (!info->accelDFS)
+	return FALSE;
+
+    driver_priv = exaGetPixmapDriverPrivate(pSrc);
+
+    if (radeon_bufmgr_gem_has_references(driver_priv->bo))
+	RADEONCPFlushIndirect(pScrn, 0);
+
+    /* if we haven't put this buffer in VRAM then just force gtt and memcpy from it */
+    if (!radeon_bufmgr_gem_in_vram(driver_priv->bo)) {
+	return RADEON_DFS_CS2(pSrc, x, y, w, h, dst, dst_pitch);
+    }
+    RADEONGetDatatypeBpp(bpp, &datatype);
+    scratch_bo[0] = scratch_bo[1] = NULL;
+    for (i = 0; i < 2; i++) {
+	scratch_bo[i] = dri_bo_alloc(info->bufmgr, "DFS scratch", scratch_size, 0, 0);
+	if (!scratch_bo[i])
+	    goto fail;
+    }
+
+retry:
+    i = 0;
+    bos[i].buf = driver_priv->bo;
+    bos[i].read_domains = RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM;
+    bos[i].write_domain = 0;
+    i++;
+    bos[i].buf = scratch_bo[0];
+    bos[i].read_domains = 0;
+    bos[i].write_domain = RADEON_GEM_DOMAIN_GTT;
+    i++;
+    bos[i].buf = scratch_bo[1];
+    bos[i].read_domains = 0;
+    bos[i].write_domain = RADEON_GEM_DOMAIN_GTT;
+    i++;
+
+    ret = dri_bufmgr_check_aperture_space(bos, i);
+    if (ret == BUFMGR_SPACE_OP_TO_BIG)
+	goto fail;
+    if (ret == BUFMGR_SPACE_FLUSH) {
+	RADEONCPFlushIndirect(pScrn, 1);
+	retry_count++;
+	if (retry_count == 2)
+	    goto fail;
+	goto retry;
+    }
+    
+    /* we want to blit from the BO to the scratch and memcpy out of the scratch */
+    {
+	int wpass = wpass = w * bpp / 8;
+	int hpass = min(h, scratch_size / scratch_pitch);
+	uint32_t pitch_offset = scratch_pitch << 16;
+
+	RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset);
+
+	ACCEL_PREAMBLE();
+	RADEON_SWITCH_TO_2D();
+
+	cur_scratch = scratch_bo[0];
+	RADEONBlitChunk(pScrn, datatype, driver_priv->bo, cur_scratch, src_pitch_offset,
+			  pitch_offset,
+			  x, y, 0, 0, w, hpass);
+
+	FLUSH_RING();
+
+	while (h) {
+	    int swap = RADEON_HOST_DATA_SWAP_NONE;
+	    int oldhpass = hpass, i = 0;
+	    dri_bo *old_scratch;
+	    uint8_t *src;
+
+	    old_scratch = cur_scratch;
+	    y += oldhpass;
+	    h -= oldhpass;
+	    hpass = min(h, scratch_size / scratch_pitch);
+	    if (hpass) {
+		if (cur_scratch == scratch_bo[0])
+		    cur_scratch = scratch_bo[1];
+		else
+		    cur_scratch = scratch_bo[0];
+
+		RADEONBlitChunk(pScrn, datatype, driver_priv->bo, cur_scratch, src_pitch_offset,
+				pitch_offset,
+				x, y, 0, 0, w, hpass);
+	    }
+
+	    radeon_bufmgr_gem_wait_rendering(old_scratch);
+	    ret = dri_bo_map(old_scratch, 0);
+	    
+	    if (hpass)
+		FLUSH_RING();
+
+	    src = old_scratch->virtual;
+
+	    if (wpass == scratch_pitch && wpass == dst_pitch) {
+		RADEONCopySwap((uint8_t*)dst, src, wpass * oldhpass, swap);
+		dst += dst_pitch * oldhpass;
+	    } else while (oldhpass--) {
+		RADEONCopySwap((uint8_t*)dst, src, wpass, swap);
+		src += scratch_pitch;
+		dst += dst_pitch;
+	    }
+	    dri_bo_unmap(old_scratch);
+	}
+
+	dri_bo_unreference(scratch_bo[0]);
+	dri_bo_unreference(scratch_bo[1]);
+	return TRUE;
+    }
+
+
+ fail:
+    if (scratch_bo[0])
+	dri_bo_unreference(scratch_bo[0]);
+    if (scratch_bo[1])
+	dri_bo_unreference(scratch_bo[1]);
+    return FALSE;
+}
 
 static Bool
 RADEONDownloadFromScreenCP(PixmapPtr pSrc, int x, int y, int w, int h,
@@ -347,12 +668,17 @@ RADEONDownloadFromScreenCP(PixmapPtr pSr
 
     TRACE;
 
+    if (info->new_cs) {
+	return RADEON_DFS_CS(pSrc, x, y, w, h, dst, dst_pitch);
+    }
+
     /*
      * Try to accelerate download. Use an indirect buffer as scratch space,
      * blitting the bits to one half while copying them out of the other one and
      * then swapping the halves.
      */
-    if (bpp != 24 && RADEONGetDatatypeBpp(bpp, &datatype) &&
+    if (!info->drm_mm && info->accelDFS && bpp != 24 &&
+	RADEONGetDatatypeBpp(bpp, &datatype) &&
 	RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset) &&
 	(scratch = RADEONCPGetBuffer(pScrn)))
     {
@@ -367,7 +693,8 @@ RADEONDownloadFromScreenCP(PixmapPtr pSr
 	RADEON_SWITCH_TO_2D();
 
 	/* Kick the first blit as early as possible */
-	RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset,
+	RADEONBlitChunk(pScrn, datatype, NULL, NULL,
+			src_pitch_offset, scratch_pitch_offset,
 			x, y, 0, 0, w, hpass);
 	FLUSH_RING();
 
@@ -394,7 +721,8 @@ RADEONDownloadFromScreenCP(PixmapPtr pSr
 	    /* Prepare next blit if anything's left */
 	    if (hpass) {
 		scratch_off = scratch->total/2 - scratch_off;
-		RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset + (scratch_off >> 10),
+		RADEONBlitChunk(pScrn, datatype, NULL, NULL,
+				src_pitch_offset, scratch_pitch_offset + (scratch_off >> 10),
 				x, y, 0, 0, w, hpass);
 	    }
 
@@ -473,10 +801,8 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr
 	info->accel_state->exa->DownloadFromScreen = RADEONDownloadFromScreenCP;
 #endif
 
-#if X_BYTE_ORDER == X_BIG_ENDIAN
     info->accel_state->exa->PrepareAccess = RADEONPrepareAccess;
     info->accel_state->exa->FinishAccess = RADEONFinishAccess;
-#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
 
     info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS;
 #ifdef EXA_SUPPORTS_PREPARE_AUX
@@ -485,6 +811,11 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr
     info->accel_state->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1;
     info->accel_state->exa->pixmapPitchAlign = 64;
 
+    if (info->drm_mm) {
+      info->accel_state->exa->flags |= EXA_HANDLES_PIXMAPS;
+    } else {
+    }
+
 #ifdef RENDER
     if (info->RenderAccel) {
 	if (info->ChipFamily >= CHIP_FAMILY_R600)
@@ -493,7 +824,7 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr
 	else if (IS_R300_3D || IS_R500_3D) {
 	    if ((info->ChipFamily < CHIP_FAMILY_RS400)
 #ifdef XF86DRI
-		|| (info->directRenderingEnabled)
+		|| (info->directRenderingEnabled || info->drm_mode_setting)
 #endif
 		) {
 		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration "
@@ -528,6 +859,15 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr
     }
 #endif
 
+#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4)
+    if (info->drm_mm) {
+        info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap;
+        info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap;
+        info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen;
+    }
+#endif
+
+
 #if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting EXA maxPitchBytes\n");
 
diff -up xf86-video-ati-6.12.2/src/radeon_exa_render.c.modeset xf86-video-ati-6.12.2/src/radeon_exa_render.c
--- xf86-video-ati-6.12.2/src/radeon_exa_render.c.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_exa_render.c	2009-05-21 11:01:45.000000000 -0400
@@ -54,6 +54,10 @@
 #define ONLY_ONCE
 #endif
 
+#define VTX_COUNT_MASK 6
+#define VTX_COUNT 4
+
+
 /* Only include the following (generic) bits once. */
 #ifdef ONLY_ONCE
 
@@ -365,12 +369,14 @@ static Bool FUNC_NAME(R100TextureSetup)(
     Bool repeat = pPict->repeat && pPict->repeatType != RepeatPad &&
 	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
     int i;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int qwords;
     ACCEL_PREAMBLE();
 
     txpitch = exaGetPixmapPitch(pPix);
-    txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+    txoffset = exaGetPixmapOffset(pPix);
 
-    if ((txoffset & 0x1f) != 0)
+    if (!info->new_cs && ((txoffset & 0x1f) != 0))
 	RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset));
     if ((txpitch & 0x1f) != 0)
 	RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch));
@@ -426,23 +432,43 @@ static Bool FUNC_NAME(R100TextureSetup)(
 	}
     }
 
-    BEGIN_ACCEL(5);
+    qwords = info->new_cs ? 6 : 5;
+    BEGIN_ACCEL(qwords);
     if (unit == 0) {
 	OUT_ACCEL_REG(RADEON_PP_TXFILTER_0, txfilter);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat);
-	OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, txoffset);
 	OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_0,
 	    (pPix->drawable.width - 1) |
 	    ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_0, txpitch - 32);
+
+	if (info->new_cs) {
+	    driver_priv = exaGetPixmapDriverPrivate(pPix); 
+	    OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, 0);
+	    OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0);
+	} else {
+	    txoffset += info->fbLocation + pScrn->fbOffset;
+	    OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, txoffset);
+	}
+	/* emit a texture relocation */
     } else {
 	OUT_ACCEL_REG(RADEON_PP_TXFILTER_1, txfilter);
 	OUT_ACCEL_REG(RADEON_PP_TXFORMAT_1, txformat);
-	OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, txoffset);
+
 	OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_1,
 	    (pPix->drawable.width - 1) |
 	    ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_1, txpitch - 32);
+	if (info->new_cs) {
+	    driver_priv = exaGetPixmapDriverPrivate(pPix); 
+	    OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, 0);
+	    OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0);
+	} else {
+	    txoffset += info->fbLocation + pScrn->fbOffset;
+	    OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, txoffset);
+	}
+	    
+	/* emit a texture relocation */
     }
     FINISH_ACCEL();
 
@@ -551,10 +577,52 @@ static Bool FUNC_NAME(R100PrepareComposi
     uint32_t dst_format, dst_offset, dst_pitch, colorpitch;
     uint32_t pp_cntl, blendcntl, cblend, ablend;
     int pixel_shift;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int qwords;
+    int retry_count = 0;
+    struct radeon_space_check bos[3];
+    int i, ret;
     ACCEL_PREAMBLE();
 
     TRACE;
 
+ retry:
+    if (info->new_cs) {
+      
+	i = 0;
+	driver_priv = exaGetPixmapDriverPrivate(pSrc);
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	bos[i].write_domain = 0;
+	i++;
+
+	if (pMask) {
+	    driver_priv = exaGetPixmapDriverPrivate(pMask);
+	    bos[i].buf = driver_priv->bo;
+	    bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	    bos[i].write_domain = 0;
+	    i++;
+	}
+
+	driver_priv = exaGetPixmapDriverPrivate(pDst);
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = 0;
+	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;;
+	i++;
+
+	ret = dri_bufmgr_check_aperture_space(bos, i);
+	if (ret == BUFMGR_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == BUFMGR_SPACE_FLUSH) {
+	    RADEONCPFlushIndirect(pScrn, 1);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
+
     if (!RADEONGetDestFormat(pDstPicture, &dst_format))
 	return FALSE;
 
@@ -568,19 +636,18 @@ static Bool FUNC_NAME(R100PrepareComposi
 
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
-    dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+    dst_offset = exaGetPixmapOffset(pDst);
     dst_pitch = exaGetPixmapPitch(pDst);
     colorpitch = dst_pitch >> pixel_shift;
     if (RADEONPixmapIsColortiled(pDst))
 	colorpitch |= RADEON_COLOR_TILE_ENABLE;
 
-    dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
-    dst_pitch = exaGetPixmapPitch(pDst);
-    if ((dst_offset & 0x0f) != 0)
+    if (!info->new_cs && (dst_offset & 0x0f) != 0)
 	RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset));
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
 
+
     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
 	return FALSE;
 
@@ -598,10 +665,18 @@ static Bool FUNC_NAME(R100PrepareComposi
 	info->accel_state->is_transform[1] = FALSE;
     }
 
-    BEGIN_ACCEL(8);
+    qwords = info->new_cs ? 9 : 8;
+    BEGIN_ACCEL(qwords);
     OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl);
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE);
-    OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+    if (info->new_cs) {
+      	driver_priv = exaGetPixmapDriverPrivate(pDst);
+        OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, 0);
+	OUT_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+    } else {
+        dst_offset += info->fbLocation + pScrn->fbOffset;
+	OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+    }
     OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch);
 
     /* IN operator: Multiply src by mask components or mask alpha.
@@ -701,13 +776,17 @@ static Bool FUNC_NAME(R200TextureSetup)(
     Bool repeat = pPict->repeat && pPict->repeatType != RepeatPad &&
 	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
     int i;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int qwords;
     ACCEL_PREAMBLE();
 
     txpitch = exaGetPixmapPitch(pPix);
-    txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+    txoffset = exaGetPixmapOffset(pPix);
 
-    if ((txoffset & 0x1f) != 0)
-	RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset));
+    if (!info->new_cs) {
+	if ((txoffset & 0x1f) != 0)
+	    RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset));
+    }
     if ((txpitch & 0x1f) != 0)
 	RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch));
 
@@ -764,7 +843,8 @@ static Bool FUNC_NAME(R200TextureSetup)(
 	}
     }
 
-    BEGIN_ACCEL(6);
+    qwords = info->new_cs ? 7 : 6;
+    BEGIN_ACCEL(qwords);
     if (unit == 0) {
 	OUT_ACCEL_REG(R200_PP_TXFILTER_0, txfilter);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_0, txformat);
@@ -772,7 +852,15 @@ static Bool FUNC_NAME(R200TextureSetup)(
 	OUT_ACCEL_REG(R200_PP_TXSIZE_0, (pPix->drawable.width - 1) |
 		      ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(R200_PP_TXPITCH_0, txpitch - 32);
-	OUT_ACCEL_REG(R200_PP_TXOFFSET_0, txoffset);
+	if (info->new_cs) {
+	    driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+	    OUT_ACCEL_REG(R200_PP_TXOFFSET_0, driver_priv ? 0 : txoffset);
+	    OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0);
+	} else {
+	    txoffset += info->fbLocation + pScrn->fbOffset;
+	    OUT_ACCEL_REG(R200_PP_TXOFFSET_0, txoffset);
+	}
     } else {
 	OUT_ACCEL_REG(R200_PP_TXFILTER_1, txfilter);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_1, txformat);
@@ -780,7 +868,17 @@ static Bool FUNC_NAME(R200TextureSetup)(
 	OUT_ACCEL_REG(R200_PP_TXSIZE_1, (pPix->drawable.width - 1) |
 		      ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT));
 	OUT_ACCEL_REG(R200_PP_TXPITCH_1, txpitch - 32);
-	OUT_ACCEL_REG(R200_PP_TXOFFSET_1, txoffset);
+	if (info->new_cs) {
+	    uint32_t handle = 0;
+	    driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+	    OUT_ACCEL_REG(R200_PP_TXOFFSET_1, driver_priv ? 0 : txoffset);
+	    OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0);
+	} else {
+	    txoffset += info->fbLocation + pScrn->fbOffset;
+	    OUT_ACCEL_REG(R200_PP_TXOFFSET_1, txoffset);
+	}
+	/* emit a texture relocation */
     }
     FINISH_ACCEL();
 
@@ -873,10 +971,52 @@ static Bool FUNC_NAME(R200PrepareComposi
     uint32_t dst_format, dst_offset, dst_pitch;
     uint32_t pp_cntl, blendcntl, cblend, ablend, colorpitch;
     int pixel_shift;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int qwords;
+    int retry_count = 0;
+    struct radeon_space_check bos[3];
+    int i, ret;
     ACCEL_PREAMBLE();
 
     TRACE;
 
+ retry:
+    if (info->new_cs) {
+      
+	i = 0;
+	driver_priv = exaGetPixmapDriverPrivate(pSrc);
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	bos[i].write_domain = 0;
+	i++;
+
+	if (pMask) {
+	    driver_priv = exaGetPixmapDriverPrivate(pMask);
+	    bos[i].buf = driver_priv->bo;
+	    bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	    bos[i].write_domain = 0;
+	    i++;
+	}
+
+	driver_priv = exaGetPixmapDriverPrivate(pDst);
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = 0;
+	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;;
+	i++;
+
+	ret = dri_bufmgr_check_aperture_space(bos, i);
+	if (ret == BUFMGR_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == BUFMGR_SPACE_FLUSH) {
+	    RADEONCPFlushIndirect(pScrn, 1);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM for src\n"));
+	    goto retry;
+	}
+    }
+
     if (!RADEONGetDestFormat(pDstPicture, &dst_format))
 	return FALSE;
 
@@ -890,13 +1030,13 @@ static Bool FUNC_NAME(R200PrepareComposi
 
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
-    dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+    dst_offset = exaGetPixmapOffset(pDst);
     dst_pitch = exaGetPixmapPitch(pDst);
     colorpitch = dst_pitch >> pixel_shift;
     if (RADEONPixmapIsColortiled(pDst))
 	colorpitch |= RADEON_COLOR_TILE_ENABLE;
 
-    if ((dst_offset & 0x0f) != 0)
+    if (!info->new_cs && (dst_offset & 0x0f) != 0)
 	RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset));
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
@@ -918,11 +1058,22 @@ static Bool FUNC_NAME(R200PrepareComposi
 	info->accel_state->is_transform[1] = FALSE;
     }
 
-    BEGIN_ACCEL(11);
+    qwords = info->new_cs ? 12 : 11;
+    BEGIN_ACCEL(qwords);
 
     OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl);
     OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE);
-    OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+
+    if (info->new_cs) {
+	driver_priv = exaGetPixmapDriverPrivate(pDst);
+	assert(driver_priv);
+
+        OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, 0);
+	OUT_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+    } else {
+        dst_offset += info->fbLocation + pScrn->fbOffset;
+	OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+    }
 
     OUT_ACCEL_REG(R200_SE_VTX_FMT_0, R200_VTX_XY);
     if (pMask)
@@ -991,6 +1142,10 @@ static Bool R300CheckCompositeTexture(Pi
 				      int unit,
 				      Bool is_r500)
 {
+    ScreenPtr pScreen = pDstPict->pDrawable->pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i;
@@ -1016,8 +1171,17 @@ static Bool R300CheckCompositeTexture(Pi
 	RADEON_FALLBACK(("Unsupported picture format 0x%x\n",
 			 (int)pPict->format));
 
-    if (!RADEONCheckTexturePOT(pPict, unit == 0))
+    if (!RADEONCheckTexturePOT(pPict, unit == 0)) {
+	if (info->new_cs) {
+    		struct radeon_exa_pixmap_priv *driver_priv;
+		PixmapPtr pPix;
+
+    		pPix = RADEONGetDrawablePixmap(pPict->pDrawable);
+		driver_priv = exaGetPixmapDriverPrivate(pPix);
+		radeon_bufmgr_gem_force_gtt(driver_priv->bo);
+	}
 	return FALSE;
+    }
 
     if (pPict->filter != PictFilterNearest &&
 	pPict->filter != PictFilterBilinear)
@@ -1049,15 +1213,19 @@ static Bool FUNC_NAME(R300TextureSetup)(
     int w = pPict->pDrawable->width;
     int h = pPict->pDrawable->height;
     int i, pixel_shift;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    int qwords;
     ACCEL_PREAMBLE();
 
     TRACE;
 
     txpitch = exaGetPixmapPitch(pPix);
-    txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+    txoffset = exaGetPixmapOffset(pPix);
 
-    if ((txoffset & 0x1f) != 0)
-	RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset));
+    if (!info->new_cs) {
+    	if ((txoffset & 0x1f) != 0)
+		RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset));
+    }
     if ((txpitch & 0x1f) != 0)
 	RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch));
 
@@ -1139,13 +1307,26 @@ static Bool FUNC_NAME(R300TextureSetup)(
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
-    BEGIN_ACCEL(pPict->repeat ? 6 : 7);
+    qwords = pPict->repeat ? 6 : 7;
+    qwords += info->new_cs ? 1 : 0;
+
+    BEGIN_ACCEL(qwords);
     OUT_ACCEL_REG(R300_TX_FILTER0_0 + (unit * 4), txfilter);
     OUT_ACCEL_REG(R300_TX_FILTER1_0 + (unit * 4), 0);
     OUT_ACCEL_REG(R300_TX_FORMAT0_0 + (unit * 4), txformat0);
     OUT_ACCEL_REG(R300_TX_FORMAT1_0 + (unit * 4), txformat1);
     OUT_ACCEL_REG(R300_TX_FORMAT2_0 + (unit * 4), txpitch);
-    OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), txoffset);
+
+    if (info->new_cs) {
+        uint32_t handle = 0;
+	driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+        OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), driver_priv ? 0 : txoffset);
+	OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0);
+    } else {
+        txoffset += info->fbLocation + pScrn->fbOffset;
+        OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), txoffset);
+    }
     if (!pPict->repeat)
 	OUT_ACCEL_REG(R300_TX_BORDER_COLOR_0 + (unit * 4), 0);
     FINISH_ACCEL();
@@ -1244,6 +1425,7 @@ static Bool R300CheckComposite(int op, P
     return TRUE;
 
 }
+
 #endif /* ONLY_ONCE */
 
 static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
@@ -1255,10 +1437,51 @@ static Bool FUNC_NAME(R300PrepareComposi
     uint32_t txenable, colorpitch;
     uint32_t blendcntl;
     int pixel_shift;
+    int qwords, ret;
+    int retry_count = 0;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_space_check bos[3];
+    int i;
     ACCEL_PREAMBLE();
-
     TRACE;
 
+ retry:
+    if (info->new_cs) {
+      
+	i = 0;
+	driver_priv = exaGetPixmapDriverPrivate(pSrc);
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	bos[i].write_domain = 0;
+	i++;
+
+	if (pMask) {
+	    driver_priv = exaGetPixmapDriverPrivate(pMask);
+	    bos[i].buf = driver_priv->bo;
+	    bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	    bos[i].write_domain = 0;
+	    i++;
+	}
+
+	driver_priv = exaGetPixmapDriverPrivate(pDst);
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = 0;
+	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;;
+	i++;
+
+	ret = dri_bufmgr_check_aperture_space(bos, i);
+	if (ret == BUFMGR_SPACE_OP_TO_BIG) {
+	    RADEON_FALLBACK(("Not enough RAM to hw accel composite operation\n"));
+	}
+	if (ret == BUFMGR_SPACE_FLUSH) {
+	    RADEONCPFlushIndirect(pScrn, 1);
+	    retry_count++;
+	    if (retry_count == 2)
+	        RADEON_FALLBACK(("Not enough Video RAM - this really shouldn't happen\nm"));
+	    goto retry;
+	}
+    }
+
     if (!R300GetDestFormat(pDstPicture, &dst_format))
 	return FALSE;
 
@@ -1269,7 +1492,7 @@ static Bool FUNC_NAME(R300PrepareComposi
 
     pixel_shift = pDst->drawable.bitsPerPixel >> 4;
 
-    dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset;
+    dst_offset = exaGetPixmapOffset(pDst);
     dst_pitch = exaGetPixmapPitch(pDst);
     colorpitch = dst_pitch >> pixel_shift;
 
@@ -1278,7 +1501,7 @@ static Bool FUNC_NAME(R300PrepareComposi
 
     colorpitch |= dst_format;
 
-    if ((dst_offset & 0x0f) != 0)
+    if (!info->new_cs && ((dst_offset & 0x0f) != 0))
 	RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset));
     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
@@ -1287,6 +1510,9 @@ static Bool FUNC_NAME(R300PrepareComposi
 	return FALSE;
 
     RADEON_SWITCH_TO_3D();
+    BEGIN_ACCEL(1);
+    OUT_ACCEL_REG(R300_TX_INVALTAGS, 0x0);
+    FINISH_ACCEL();
 
     if (!FUNC_NAME(R300TextureSetup)(pSrcPicture, pSrc, 0))
 	return FALSE;
@@ -1943,9 +2169,18 @@ static Bool FUNC_NAME(R300PrepareComposi
 				     (8191 << R300_SCISSOR_Y_SHIFT)));
     FINISH_ACCEL();
 
-    BEGIN_ACCEL(3);
+    qwords = info->new_cs ? 4 : 3;
+    BEGIN_ACCEL(qwords);
+    if (info->new_cs) {
+        driver_priv = exaGetPixmapDriverPrivate(pDst);
+	assert(driver_priv);
 
-    OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+        OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, 0);
+	OUT_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM);
+    } else {
+        dst_offset += info->fbLocation + pScrn->fbOffset;
+        OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+    }
     OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch);
 
     blendcntl = RADEONGetBlendCntl(op, pMaskPicture, pDstPicture->format);
@@ -1963,7 +2198,6 @@ static Bool FUNC_NAME(R300PrepareComposi
     return TRUE;
 }
 
-
 #ifdef ACCEL_CP
 
 #define VTX_OUT_MASK(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY)	\
@@ -2249,14 +2483,23 @@ static void FUNC_NAME(RadeonDoneComposit
 
     if (IS_R300_3D || IS_R500_3D) {
 	BEGIN_ACCEL(3);
-	OUT_ACCEL_REG(R300_SC_CLIP_RULE, 0xAAAA);
 	OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_RB3D_DC_FLUSH_ALL);
+	OUT_ACCEL_REG(R300_SC_CLIP_RULE, 0xaaaa);
     } else
 	BEGIN_ACCEL(1);
     OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
     FINISH_ACCEL();
 
     LEAVE_DRAW(0);
+
+#if 0
+    /* workaround hang on RS4xx and RS6xx chips */
+    if(info->ChipFamily == CHIP_FAMILY_RS400 ||
+       info->ChipFamily == CHIP_FAMILY_RS480 ||
+       info->ChipFamily == CHIP_FAMILY_RS600 ||
+       info->ChipFamily == CHIP_FAMILY_RS690)
+	RADEONCPFlushIndirect(pScrn, 1);
+#endif
 }
 
 #undef ONLY_ONCE
diff -up xf86-video-ati-6.12.2/src/radeon.h.modeset xf86-video-ati-6.12.2/src/radeon.h
--- xf86-video-ati-6.12.2/src/radeon.h.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon.h	2009-05-21 11:01:45.000000000 -0400
@@ -46,6 +46,8 @@
 #include "compiler.h"
 #include "xf86fbman.h"
 
+#include "drmmode_display.h"
+
 				/* PCI support */
 #include "xf86Pci.h"
 
@@ -75,6 +77,7 @@
 #include "dri.h"
 #include "GL/glxint.h"
 #include "xf86drm.h"
+#include "radeon_dri2.h"
 
 #ifdef DAMAGE
 #include "damage.h"
@@ -85,6 +88,7 @@
 #include "xf86Crtc.h"
 #include "X11/Xatom.h"
 
+#include "radeon_bufmgr.h"
 				/* Render support */
 #ifdef RENDER
 #include "picturestr.h"
@@ -413,6 +417,11 @@ typedef enum {
 
 typedef struct _atomBiosHandle *atomBiosHandlePtr;
 
+struct radeon_exa_pixmap_priv {
+    dri_bo *bo;
+    int flags;
+};
+    
 typedef struct {
     uint32_t pci_device_id;
     RADEONChipFamily chip_family;
@@ -423,7 +432,27 @@ typedef struct {
     int singledac;
 } RADEONCardInfo;
 
+#define RADEON_2D_EXA_COPY 1
+#define RADEON_2D_EXA_SOLID 2
+
+struct radeon_2d_state {
+    int op; //
+    uint32_t dst_pitch_offset;
+    uint32_t src_pitch_offset;
+    uint32_t dp_gui_master_cntl;
+    uint32_t dp_cntl;
+    uint32_t dp_write_mask;
+    uint32_t dp_brush_frgd_clr;
+    uint32_t dp_brush_bkgd_clr;
+    uint32_t dp_src_frgd_clr;
+    uint32_t dp_src_bkgd_clr;
+    uint32_t default_sc_bottom_right;
+    dri_bo *dst_bo;
+    dri_bo *src_bo;
+};
+    
 #ifdef XF86DRI
+
 struct radeon_cp {
     Bool              CPRuns;           /* CP is running */
     Bool              CPInUse;          /* CP has been used by X server */
@@ -437,6 +466,10 @@ struct radeon_cp {
     drmBufPtr         indirectBuffer;
     int               indirectStart;
 
+    drmBuf         ib_gem_fake;
+    void *ib_ptr;
+  
+    struct radeon_relocs_info relocs;
     /* Debugging info for BEGIN_RING/ADVANCE_RING pairs. */
     int               dma_begin_count;
     char              *dma_debug_func;
@@ -503,13 +536,13 @@ struct radeon_dri {
     drm_handle_t      ringHandle;       /* Handle from drmAddMap */
     drmSize           ringMapSize;      /* Size of map */
     int               ringSize;         /* Size of ring (in MB) */
-    drmAddress        ring;             /* Map */
+  //    drmAddress        ring;             /* Map */
     int               ringSizeLog2QW;
 
     unsigned long     ringReadOffset;   /* Offset into GART space */
     drm_handle_t      ringReadPtrHandle; /* Handle from drmAddMap */
     drmSize           ringReadMapSize;  /* Size of map */
-    drmAddress        ringReadPtr;      /* Map */
+  //    drmAddress        ringReadPtr;      /* Map */
 
     /* CP vertex/indirect buffer data */
     unsigned long     bufStart;         /* Offset into GART space */
@@ -528,7 +561,6 @@ struct radeon_dri {
     drmAddress        gartTex;           /* Map */
     int               log2GARTTexGran;
 
-    /* DRI screen private data */
     int               fbX;
     int               fbY;
     int               backX;
@@ -788,6 +820,7 @@ typedef struct {
     RADEONCardType    cardType;            /* Current card is a PCI card */
     struct radeon_cp  *cp;
     struct radeon_dri  *dri;
+    struct radeon_dri2 dri2;
 #ifdef USE_EXA
     Bool              accelDFS;
 #endif
@@ -891,6 +924,27 @@ typedef struct {
 
     Bool              r4xx_atom;
 
+    Bool new_cs; // new command submission routine
+    struct radeon_2d_state state_2d;
+    void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB 
+    Bool cs_used_depth;
+    Bool drm_mm; // the drm memory manager exists and is initialised 
+    struct {
+      uint64_t vram_size;
+      uint64_t gart_size;
+
+      dri_bo *front_buffer;
+      dri_bo *cursor[2];
+    } mm;
+
+    drm_handle_t fb_map_handle;
+    Bool drm_mode_setting;
+#ifdef XF86DRM_MODE
+    drmmode_rec drmmode;
+#endif
+
+    int can_resize;
+    dri_bufmgr *bufmgr;
 } RADEONInfoRec, *RADEONInfoPtr;
 
 #define RADEONWaitForFifo(pScrn, entries)				\
@@ -1146,6 +1200,13 @@ extern void
 radeon_legacy_free_memory(ScrnInfoPtr pScrn,
 		          void *mem_struct);
 
+/* radeon_memory.c */
+Bool radeon_setup_kernel_mem(ScreenPtr pScreen);
+Bool RADEONDRIDoMappings(ScreenPtr pScreen);
+Bool radeon_update_dri_buffers(ScreenPtr pScreen);
+
+dri_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
+void radeon_set_pixmap_bo(PixmapPtr pPix, dri_bo *bo);
 #ifdef XF86DRI
 #  ifdef USE_XAA
 /* radeon_accelfuncs.c */
@@ -1164,7 +1225,9 @@ do {									\
 
 #define RADEONCP_RELEASE(pScrn, info)					\
 do {									\
-    if (info->cp->CPInUse) {						\
+    if (info->new_cs) {							\
+	RADEONCPReleaseIndirect(pScrn);					\
+    } else if (info->cp->CPInUse) {						\
 	RADEON_PURGE_CACHE();						\
 	RADEON_WAIT_UNTIL_IDLE();					\
 	RADEONCPReleaseIndirect(pScrn);					\
@@ -1199,7 +1262,7 @@ do {									\
 
 #define RADEONCP_REFRESH(pScrn, info)					\
 do {									\
-    if (!info->cp->CPInUse) {						\
+    if (!info->cp->CPInUse && !info->new_cs) {				\
 	if (info->cp->needCacheFlush) {					\
 	    RADEON_PURGE_CACHE();					\
 	    RADEON_PURGE_ZCACHE();					\
@@ -1226,6 +1289,13 @@ do {									\
 #define RING_LOCALS	uint32_t *__head = NULL; int __expected; int __count = 0
 
 #define BEGIN_RING(n) do {						\
+    if (!info->cp->indirectBuffer) {					\
+	info->cp->indirectBuffer = RADEONCPGetBuffer(pScrn);		\
+	info->cp->indirectStart = 0;					\
+    } else if (info->cp->indirectBuffer->used + (n) * (int)sizeof(uint32_t) >	\
+	       info->cp->indirectBuffer->total) {				\
+	RADEONCPFlushIndirect(pScrn, 1);				\
+    }									\
     if (RADEON_VERBOSE) {						\
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,				\
 		   "BEGIN_RING(%d) in %s\n", (unsigned int)n, __FUNCTION__);\
@@ -1238,13 +1308,6 @@ do {									\
     }									\
     info->cp->dma_debug_func = __FILE__;				\
     info->cp->dma_debug_lineno = __LINE__;				\
-    if (!info->cp->indirectBuffer) {					\
-	info->cp->indirectBuffer = RADEONCPGetBuffer(pScrn);		\
-	info->cp->indirectStart = 0;					\
-    } else if (info->cp->indirectBuffer->used + (n) * (int)sizeof(uint32_t) >	\
-	       info->cp->indirectBuffer->total) {		        \
-	RADEONCPFlushIndirect(pScrn, 1);				\
-    }									\
     __expected = n;							\
     __head = (pointer)((char *)info->cp->indirectBuffer->address +	\
 		       info->cp->indirectBuffer->used);			\
@@ -1287,6 +1350,14 @@ do {									\
     OUT_RING(val);							\
 } while (0)
 
+/* TODO - VRAM is wrong in general but true for now - all EXA stuff
+ is in VRAM */
+#define OUT_RING_RELOC(x, read_domains, write_domains)			\
+  do {									\
+    radeon_bufmgr_emit_reloc(x, &info->cp->relocs, __head, &__count, read_domains, write_domains); \
+  } while(0)
+
+
 #define FLUSH_RING()							\
 do {									\
     if (RADEON_VERBOSE)							\
diff -up xf86-video-ati-6.12.2/src/radeon_legacy_memory.c.modeset xf86-video-ati-6.12.2/src/radeon_legacy_memory.c
--- xf86-video-ati-6.12.2/src/radeon_legacy_memory.c.modeset	2009-02-24 09:45:07.000000000 -0500
+++ xf86-video-ati-6.12.2/src/radeon_legacy_memory.c	2009-05-21 11:01:45.000000000 -0400
@@ -21,6 +21,19 @@ radeon_legacy_allocate_memory(ScrnInfoPt
     RADEONInfoPtr info = RADEONPTR(pScrn);
     uint32_t offset = 0;
 
+    if (info->new_cs) {
+	dri_bo *video_bo;
+
+	video_bo = dri_bo_alloc(info->bufmgr, "xv pixmap", size, 4096, 0);
+
+	*mem_struct = video_bo;
+
+	if (!video_bo)
+	    return 0;
+	
+	return (uint32_t)-1;
+
+    }
 #ifdef USE_EXA
     if (info->useEXA) {
 	ExaOffscreenArea *area = *mem_struct;
@@ -94,6 +107,12 @@ radeon_legacy_free_memory(ScrnInfoPtr pS
 		   void *mem_struct)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
+
+    if (info->new_cs) {
+        dri_bo *bo = mem_struct;
+	dri_bo_unreference(bo);
+	return;
+    }
 #ifdef USE_EXA
     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
 
diff -up /dev/null xf86-video-ati-6.12.2/src/radeon_memory.c
--- /dev/null	2009-05-05 09:44:49.704001696 -0400
+++ xf86-video-ati-6.12.2/src/radeon_memory.c	2009-05-21 11:01:45.000000000 -0400
@@ -0,0 +1,71 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "radeon.h"
+#include "radeon_drm.h"
+#include "radeon_bufmgr_gem.h"
+
+Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int cpp = info->CurrentLayout.pixel_bytes;
+    int screen_size;
+    int stride = pScrn->displayWidth * cpp;
+    int total_size_bytes = 0, remain_size_bytes;
+    int pagesize = 4096;
+    
+    screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * stride;
+    {
+	int cursor_size = 64 * 4 * 64;
+	int c;
+
+    	cursor_size = RADEON_ALIGN(cursor_size, pagesize);
+	for (c = 0; c < xf86_config->num_crtc; c++) {
+	    /* cursor objects */
+	    info->mm.cursor[c] = dri_bo_alloc(info->bufmgr, "front", cursor_size,
+					      0, RADEON_GEM_DOMAIN_VRAM);
+	    if (!info->mm.cursor[c]) {
+		return FALSE;
+	    }
+
+	    if (dri_bo_map(info->mm.cursor[c], 1)) {
+	      ErrorF("Failed to map cursor buffer memory\n");
+	    }
+	    
+	    drmmode_set_cursor(pScrn, &info->drmmode, c, info->mm.cursor[c]);
+	    total_size_bytes += cursor_size;
+	}
+    }
+
+    screen_size = RADEON_ALIGN(screen_size, pagesize);
+    /* keep area front front buffer - but don't allocate it yet */
+    total_size_bytes += screen_size;
+
+    /* work out from the mm size what the exa / tex sizes need to be */
+    remain_size_bytes = info->mm.vram_size - total_size_bytes;
+
+    info->dri->textureSize = 0;
+
+    info->mm.front_buffer = dri_bo_alloc(info->bufmgr, "front", screen_size,
+					 0, RADEON_GEM_DOMAIN_VRAM);
+
+    //    drmmode_set_fb(pScrn, &info->drmmode, pScrn->virtualX, RADEON_ALIGN(pScrn->virtualY, 16), stride, info->mm.front_buffer);
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->mm.front_buffer->size/1024);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Remaining VRAM size (used for pixmaps): %dK\n", remain_size_bytes/1024);
+
+    /* set the emit limit at 90% of VRAM */
+    remain_size_bytes = (remain_size_bytes / 10) * 9;
+
+    radeon_bufmgr_gem_set_limit(info->bufmgr, RADEON_GEM_DOMAIN_VRAM, remain_size_bytes);
+    return TRUE;
+}
+
+
diff -up xf86-video-ati-6.12.2/src/radeon_probe.h.modeset xf86-video-ati-6.12.2/src/radeon_probe.h
--- xf86-video-ati-6.12.2/src/radeon_probe.h.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_probe.h	2009-05-21 11:01:45.000000000 -0400
@@ -50,6 +50,7 @@
 #include "xaa.h"
 #endif
 
+#include "radeon_dri_bufmgr.h"
 extern DriverRec RADEON;
 
 #define RADEON_MAX_CRTC 2
@@ -159,6 +160,7 @@ typedef struct _RADEONCrtcPrivateRec {
     int can_tile;
     Bool enabled;
     Bool initialized;
+
 } RADEONCrtcPrivateRec, *RADEONCrtcPrivatePtr;
 
 typedef struct _radeon_encoder {
@@ -612,6 +614,7 @@ typedef struct
     RADEONSaveRec     SavedReg;         /* Original (text) mode              */
 
     void              *MMIO;            /* Map of MMIO region                */
+    int fd;
 } RADEONEntRec, *RADEONEntPtr;
 
 /* radeon_probe.c */
diff -up xf86-video-ati-6.12.2/src/radeon_textured_video.c.modeset xf86-video-ati-6.12.2/src/radeon_textured_video.c
--- xf86-video-ati-6.12.2/src/radeon_textured_video.c.modeset	2009-03-27 01:13:04.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_textured_video.c	2009-05-21 11:01:45.000000000 -0400
@@ -40,6 +40,7 @@
 #include "radeon_macros.h"
 #include "radeon_probe.h"
 #include "radeon_video.h"
+#include "radeon_drm.h"
 
 #include <X11/extensions/Xv.h>
 #include "fourcc.h"
@@ -133,6 +134,7 @@ static __inline__ uint32_t float4touint(
 #define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
 #define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
 #define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
+#define OUT_RELOC(x, read, write) do {} while(0)
 #define FINISH_ACCEL()
 
 #include "radeon_textured_videofuncs.c"
@@ -142,6 +144,7 @@ static __inline__ uint32_t float4touint(
 #undef BEGIN_ACCEL
 #undef OUT_ACCEL_REG
 #undef OUT_ACCEL_REG_F
+#undef OUT_RELOC
 #undef FINISH_ACCEL
 
 #ifdef XF86DRI
@@ -155,6 +158,7 @@ static __inline__ uint32_t float4touint(
 #define OUT_ACCEL_REG_F(reg, val)	OUT_ACCEL_REG(reg, F_TO_DW(val))
 #define FINISH_ACCEL()		ADVANCE_RING()
 #define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
+#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write)
 
 #include "radeon_textured_videofuncs.c"
 
@@ -412,6 +416,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn
 								size * 2, 64);
 	if (pPriv->video_offset == 0)
 	    return BadAlloc;
+
+	if (info->new_cs)
+	    pPriv->src_bo = pPriv->video_memory;
     }
 
     /* Bicubic filter loading */
@@ -422,6 +429,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn
 	pPriv->bicubic_src_offset = pPriv->bicubic_offset + info->fbLocation + pScrn->fbOffset;
 	if (pPriv->bicubic_offset == 0)
 		pPriv->bicubic_enabled = FALSE;
+
+	if (info->new_cs)
+	    pPriv->bicubic_bo = pPriv->bicubic_memory;
     }
 
     if (pDraw->type == DRAWABLE_WINDOW)
@@ -451,11 +461,21 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn
     left = (x1 >> 16) & ~1;
     npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
 
-    pPriv->src_offset = pPriv->video_offset + info->fbLocation + pScrn->fbOffset;
-    if (info->ChipFamily >= CHIP_FAMILY_R600)
-	pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset);
-    else
-	pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch));
+    pPriv->src_offset = pPriv->video_offset;
+    if (info->new_cs) {
+	int ret;
+	radeon_bufmgr_gem_wait_rendering(pPriv->src_bo);
+	ret = dri_bo_map(pPriv->src_bo, 1);
+	if (ret) 
+	    return BadAlloc;
+      
+	pPriv->src_addr = pPriv->src_bo->virtual;
+    } else {
+        if (info->ChipFamily >= CHIP_FAMILY_R600)
+            pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset);
+	else
+            pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch));
+    }
     pPriv->src_pitch = dstPitch;
     pPriv->planeu_offset = dstPitch * dst_height;
     pPriv->planev_offset = pPriv->planeu_offset + dstPitch2 * ((dst_height + 1) >> 1);
@@ -481,12 +501,12 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn
 	    if (info->DMAForXv) {
 		if (id == FOURCC_YV12)
 		    R600CopyPlanarHW(pScrn, buf, buf + s3offset, buf + s2offset,
-				     pPriv->src_offset,
+				     pPriv->src_offset + info->fbLocation + pScrn->fbOffset,
 				     srcPitch, srcPitch2, pPriv->src_pitch,
 				     width, height);
 		else
 		    R600CopyPlanarHW(pScrn, buf, buf + s2offset, buf + s3offset,
-				     pPriv->src_offset,
+				     pPriv->src_offset + info->fbLocation + pScrn->fbOffset,
 				     srcPitch, srcPitch2, pPriv->src_pitch,
 				     width, height);
 	    } else {
@@ -548,7 +568,7 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn
     default:
 	if (info->ChipFamily >= CHIP_FAMILY_R600) {
 	    if (info->DMAForXv)
-		R600CopyPackedHW(pScrn, buf, pPriv->src_offset,
+		R600CopyPackedHW(pScrn, buf, pPriv->src_offset + info->fbLocation + pScrn->fbOffset,
 				 2 * width, pPriv->src_pitch,
 				 width, height);
 	    else
@@ -566,9 +586,25 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn
 
     /* Upload bicubic filter tex */
     if (pPriv->bicubic_enabled) {
-	if (info->ChipFamily < CHIP_FAMILY_R600)
-	    RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512,
-			   (uint8_t *)(info->FB + pPriv->bicubic_offset), 1024, 1024, 1, 512, 2);
+       if (info->ChipFamily < CHIP_FAMILY_R600) {
+	   uint8_t *bicubic_addr;
+	   int ret;
+
+	   if (info->new_cs) {
+	       radeon_bufmgr_gem_wait_rendering(pPriv->bicubic_bo);
+	       ret = dri_bo_map(pPriv->bicubic_bo, 1);
+	       if (ret)
+		   return BadAlloc;
+
+	       bicubic_addr = pPriv->bicubic_bo->virtual;
+	   } else
+	       bicubic_addr = (uint8_t *)(info->FB + pPriv->bicubic_offset);
+	
+	   RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, bicubic_addr, 1024, 1024, 1, 512, 2);
+	   
+	   if (info->new_cs)
+	       dri_bo_unmap(pPriv->bicubic_bo);
+       }
     }
 
     /* update cliplist */
@@ -586,10 +622,12 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn
     pPriv->w = width;
     pPriv->h = height;
 
+    if (info->new_cs)
+	dri_bo_unmap(pPriv->src_bo);
 #ifdef XF86DRI
     if (IS_R600_3D)
 	R600DisplayTexturedVideo(pScrn, pPriv);
-    else if (info->directRenderingEnabled)
+    else if (info->directRenderingEnabled || info->drm_mode_setting)
 	RADEONDisplayTexturedVideoCP(pScrn, pPriv);
     else
 #endif
diff -up xf86-video-ati-6.12.2/src/radeon_textured_videofuncs.c.modeset xf86-video-ati-6.12.2/src/radeon_textured_videofuncs.c
--- xf86-video-ati-6.12.2/src/radeon_textured_videofuncs.c.modeset	2009-05-21 11:01:45.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_textured_videofuncs.c	2009-05-21 11:01:45.000000000 -0400
@@ -87,11 +87,25 @@ do {								\
 
 #endif /* !ACCEL_CP */
 
+#define OUT_TEXTURE_REG(reg, offset, bo) do {	\
+	if (info->new_cs) {		  \
+	    OUT_ACCEL_REG((reg), (offset));				\
+	    OUT_RELOC((bo), RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); \
+	} else { \
+	    OUT_ACCEL_REG((reg), (offset) + info->fbLocation + pScrn->fbOffset);} \
+    } while(0)
+
+
 static void
 FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     PixmapPtr pPixmap = pPriv->pPixmap;
+    struct radeon_exa_pixmap_priv *driver_priv;
+    struct radeon_space_check bos[2];
+    int i, ret;
+    int retry_count = 0;
+    dri_bo *dst_bo;
     uint32_t txformat;
     uint32_t txfilter, txformat0, txformat1, txoffset, txpitch;
     uint32_t dst_offset, dst_pitch, dst_format;
@@ -101,19 +115,57 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
     int dstxoff, dstyoff, pixel_shift, vtx_count;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    int qwords;
     ACCEL_PREAMBLE();
 
+ retry:
+    if (info->new_cs) {
+      
+	i = 0;
+	bos[i].buf = pPriv->src_bo;
+	bos[i].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	bos[i].write_domain = 0;
+	i++;
+
+	driver_priv = exaGetPixmapDriverPrivate(pPixmap);
+	dst_bo = driver_priv->bo;
+	bos[i].buf = driver_priv->bo;
+	bos[i].read_domains = 0;
+	bos[i].write_domain = RADEON_GEM_DOMAIN_VRAM;;
+	i++;
+
+	ret = dri_bufmgr_check_aperture_space(bos, i);
+	if (ret == BUFMGR_SPACE_OP_TO_BIG) {
+	    ErrorF("Not enough RAM to hw accel composite operation\n");
+	    return;
+	}
+	if (ret == BUFMGR_SPACE_FLUSH) {
+	    RADEONCPFlushIndirect(pScrn, 1);
+	    retry_count++;
+	    if (retry_count == 2) {
+	        ErrorF("Not enough RAM to hw accel composite operation\n");
+	        return;
+	    }
+	    goto retry;
+	}
+    }
+
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
 #ifdef USE_EXA
     if (info->useEXA) {
-	dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
+	if (info->new_cs) {
+	    driver_priv = exaGetPixmapDriverPrivate(pPixmap);
+	    if (driver_priv)
+		dst_bo = driver_priv->bo;
+	} else {
+	    dst_offset = exaGetPixmapOffset(pPixmap);
+	}
 	dst_pitch = exaGetPixmapPitch(pPixmap);
     } else
 #endif
 	{
-	    dst_offset = (pPixmap->devPrivate.ptr - info->FB) +
-		info->fbLocation + pScrn->fbOffset;
+	    dst_offset = (pPixmap->devPrivate.ptr - info->FB);
 	    dst_pitch = pPixmap->devKind;
 	}
 
@@ -144,7 +196,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 			  RADEON_WAIT_DMA_GUI_IDLE);
 	    FINISH_ACCEL();
 
-	    if (!info->accel_state->XInited3D)
+	    if (!info->accel_state->XInited3D && !info->drm_mm)
 		RADEONInit3DEngine(pScrn);
 	}
 
@@ -222,15 +274,19 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 	if (IS_R500_3D && ((pPriv->h - 1) & 0x800))
 	    txpitch |= R500_TXHEIGHT_11;
 
-	txoffset = pPriv->src_offset;
+	if (info->new_cs)
+		txoffset = 0;
+	else
+		txoffset = pPriv->src_offset;
 
-	BEGIN_ACCEL(6);
+	qwords = info->new_cs ? 7 : 6;
+	BEGIN_ACCEL(qwords);
 	OUT_ACCEL_REG(R300_TX_FILTER0_0, txfilter);
 	OUT_ACCEL_REG(R300_TX_FILTER1_0, 0);
 	OUT_ACCEL_REG(R300_TX_FORMAT0_0, txformat0);
 	OUT_ACCEL_REG(R300_TX_FORMAT1_0, txformat1);
 	OUT_ACCEL_REG(R300_TX_FORMAT2_0, txpitch);
-	OUT_ACCEL_REG(R300_TX_OFFSET_0, txoffset);
+	OUT_TEXTURE_REG(R300_TX_OFFSET_0, txoffset, pPriv->src_bo);
 	FINISH_ACCEL();
 
 	txenable = R300_TEX_0_ENABLE;
@@ -246,19 +302,22 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 			R300_TX_MIN_FILTER_LINEAR |
 			R300_TX_MAG_FILTER_LINEAR);
 
-		BEGIN_ACCEL(12);
+		qwords = info->new_cs ? 14 : 12;
+		BEGIN_ACCEL(qwords);
 		OUT_ACCEL_REG(R300_TX_FILTER0_1, txfilter | (1 << R300_TX_ID_SHIFT));
 		OUT_ACCEL_REG(R300_TX_FILTER1_1, 0);
 		OUT_ACCEL_REG(R300_TX_FORMAT0_1, txformat0);
 		OUT_ACCEL_REG(R300_TX_FORMAT1_1, R300_TX_FORMAT_X8 | R300_TX_FORMAT_CACHE_FOURTH_REGION_2);
 		OUT_ACCEL_REG(R300_TX_FORMAT2_1, txpitch);
-		OUT_ACCEL_REG(R300_TX_OFFSET_1, txoffset + pPriv->planeu_offset);
+		OUT_TEXTURE_REG(R300_TX_OFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
+
 		OUT_ACCEL_REG(R300_TX_FILTER0_2, txfilter | (2 << R300_TX_ID_SHIFT));
 		OUT_ACCEL_REG(R300_TX_FILTER1_2, 0);
 		OUT_ACCEL_REG(R300_TX_FORMAT0_2, txformat0);
 		OUT_ACCEL_REG(R300_TX_FORMAT1_2, R300_TX_FORMAT_X8 | R300_TX_FORMAT_CACHE_FOURTH_REGION_3);
 		OUT_ACCEL_REG(R300_TX_FORMAT2_2, txpitch);
-		OUT_ACCEL_REG(R300_TX_OFFSET_2, txoffset + pPriv->planev_offset);
+		OUT_TEXTURE_REG(R300_TX_OFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
+
 		FINISH_ACCEL();
 		txenable |= R300_TEX_1_ENABLE | R300_TEX_2_ENABLE;
 	}
@@ -279,13 +338,19 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 			    R300_TX_MAG_FILTER_NEAREST |
 			    (1 << R300_TX_ID_SHIFT));
 
-		BEGIN_ACCEL(6);
+		qwords = info->new_cs ? 7 : 6;
+		BEGIN_ACCEL(qwords);
 		OUT_ACCEL_REG(R300_TX_FILTER0_1, txfilter);
 		OUT_ACCEL_REG(R300_TX_FILTER1_1, 0);
 		OUT_ACCEL_REG(R300_TX_FORMAT0_1, txformat0);
 		OUT_ACCEL_REG(R300_TX_FORMAT1_1, txformat1);
 		OUT_ACCEL_REG(R300_TX_FORMAT2_1, txpitch);
-		OUT_ACCEL_REG(R300_TX_OFFSET_1, pPriv->bicubic_src_offset);
+		if (info->new_cs) {
+		    OUT_ACCEL_REG(R300_TX_OFFSET_1, 0);
+		    OUT_RELOC(pPriv->bicubic_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0);
+		} else {
+		    OUT_ACCEL_REG(R300_TX_OFFSET_1, pPriv->bicubic_src_offset);
+		}
 		FINISH_ACCEL();
 
 		/* Enable tex 1 */
@@ -1536,11 +1601,18 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 	    }
 	}
 
-	BEGIN_ACCEL(6);
+	qwords = info->new_cs ? 8 : 6;
+	BEGIN_ACCEL(qwords);
 	OUT_ACCEL_REG(R300_TX_INVALTAGS, 0);
 	OUT_ACCEL_REG(R300_TX_ENABLE, txenable);
 
-	OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+	if (info->new_cs) {
+	    OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, 0);
+	    OUT_RELOC(dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
+	} else {
+	    dst_offset += info->fbLocation + pScrn->fbOffset;
+	    OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+	}
 	OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch);
 
 	blendcntl = RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO;
@@ -1587,11 +1659,19 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 	if (RADEONTilingEnabled(pScrn, pPixmap))
 	    colorpitch |= RADEON_COLOR_TILE_ENABLE;
 
-	BEGIN_ACCEL(4);
+	qwords = info->new_cs ? 5 : 4;
+	BEGIN_ACCEL(qwords);
 
 	OUT_ACCEL_REG(RADEON_RB3D_CNTL,
 		      dst_format /*| RADEON_ALPHA_BLEND_ENABLE*/);
-	OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+
+	if (info->new_cs) {
+	    OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, 0);
+	    OUT_RELOC(dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
+	} else {
+	    dst_offset += info->fbLocation + pScrn->fbOffset;
+	    OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
+	}
 
 	OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch);
 
@@ -1630,7 +1710,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 			    R200_CLAMP_S_CLAMP_LAST |
 			    R200_CLAMP_T_CLAMP_LAST;
 
-		BEGIN_ACCEL(36);
+		qwords = info->new_cs ? 39 : 36;
+		BEGIN_ACCEL(qwords);
 
 		OUT_ACCEL_REG(RADEON_PP_CNTL,
 			      RADEON_TEX_0_ENABLE | RADEON_TEX_1_ENABLE | RADEON_TEX_2_ENABLE |
@@ -1649,21 +1730,22 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 			      (pPriv->w - 1) |
 			      ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 		OUT_ACCEL_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
-		OUT_ACCEL_REG(R200_PP_TXOFFSET_0, pPriv->src_offset);
+		OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
 
 		OUT_ACCEL_REG(R200_PP_TXFILTER_1, txfilter);
 		OUT_ACCEL_REG(R200_PP_TXFORMAT_1, txformat | R200_TXFORMAT_ST_ROUTE_STQ1);
 		OUT_ACCEL_REG(R200_PP_TXFORMAT_X_1, 0);
 		OUT_ACCEL_REG(R200_PP_TXSIZE_1, txformat0);
 		OUT_ACCEL_REG(R200_PP_TXPITCH_1, txpitch);
-		OUT_ACCEL_REG(R200_PP_TXOFFSET_1, pPriv->src_offset + pPriv->planeu_offset);
+		OUT_TEXTURE_REG(R200_PP_TXOFFSET_1, txoffset + pPriv->planeu_offset, pPriv->src_bo);
 
 		OUT_ACCEL_REG(R200_PP_TXFILTER_2, txfilter);
 		OUT_ACCEL_REG(R200_PP_TXFORMAT_2, txformat | R200_TXFORMAT_ST_ROUTE_STQ1);
 		OUT_ACCEL_REG(R200_PP_TXFORMAT_X_2, 0);
 		OUT_ACCEL_REG(R200_PP_TXSIZE_2, txformat0);
 		OUT_ACCEL_REG(R200_PP_TXPITCH_2, txpitch);
-		OUT_ACCEL_REG(R200_PP_TXOFFSET_2, pPriv->src_offset + pPriv->planev_offset);
+
+		OUT_TEXTURE_REG(R200_PP_TXOFFSET_2, txoffset + pPriv->planev_offset, pPriv->src_bo);
 
 		/* similar to r300 code. Note the big problem is that hardware constants
 		 * are 8 bits only, representing 0.0-1.0. We can get that up (using bias
@@ -1799,7 +1881,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 			    R200_CLAMP_S_CLAMP_LAST |
 			    R200_CLAMP_T_CLAMP_LAST;
 
-		BEGIN_ACCEL(24);
+		qwords = info->new_cs ? 25 : 24;
+		BEGIN_ACCEL(qwords);
 
 		OUT_ACCEL_REG(RADEON_PP_CNTL,
 			      RADEON_TEX_0_ENABLE |
@@ -1817,7 +1900,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 			      (pPriv->w - 1) |
 			      ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 		OUT_ACCEL_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
-		OUT_ACCEL_REG(R200_PP_TXOFFSET_0, pPriv->src_offset);
+		OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
 
 		/* MAD temp1 / 2, const0.a * 2, temp0.ggg, -const0.rgb */
 		OUT_ACCEL_REG(R200_PP_TXCBLEND_0,
@@ -1901,7 +1984,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 		FINISH_ACCEL();
 	    }
 	    else {
-		BEGIN_ACCEL(13);
+		qwords = info->new_cs ? 14 : 13;
+		BEGIN_ACCEL(qwords);
 		OUT_ACCEL_REG(RADEON_PP_CNTL,
 			      RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
 
@@ -1922,7 +2006,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 			      ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 		OUT_ACCEL_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
 
-		OUT_ACCEL_REG(R200_PP_TXOFFSET_0, pPriv->src_offset);
+		OUT_TEXTURE_REG(R200_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
 
 		OUT_ACCEL_REG(R200_PP_TXCBLEND_0,
 			      R200_TXC_ARG_A_ZERO |
@@ -1945,7 +2029,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 	    info->accel_state->texW[0] = 1;
 	    info->accel_state->texH[0] = 1;
 
-	    BEGIN_ACCEL(9);
+	    qwords = info->new_cs ? 10 : 9;
+	    BEGIN_ACCEL(qwords);
 
 	    OUT_ACCEL_REG(RADEON_PP_CNTL,
 			  RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
@@ -1959,8 +2044,9 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(Sc
 			  RADEON_CLAMP_S_CLAMP_LAST |
 			  RADEON_CLAMP_T_CLAMP_LAST |
 			  RADEON_YUV_TO_RGB);
+
 	    OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat);
-	    OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset);
+	    OUT_TEXTURE_REG(RADEON_PP_TXOFFSET_0, txoffset, pPriv->src_bo);
 	    OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0,
 			  RADEON_COLOR_ARG_A_ZERO |
 			  RADEON_COLOR_ARG_B_ZERO |
diff -up xf86-video-ati-6.12.2/src/radeon_video.c.modeset xf86-video-ati-6.12.2/src/radeon_video.c
--- xf86-video-ati-6.12.2/src/radeon_video.c.modeset	2009-04-07 11:31:32.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_video.c	2009-05-21 11:01:45.000000000 -0400
@@ -284,7 +284,7 @@ void RADEONInitVideo(ScreenPtr pScreen)
     memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
     adaptors = newAdaptors;
 
-    if (!IS_AVIVO_VARIANT) {
+    if (!IS_AVIVO_VARIANT && !info->drm_mode_setting) {
 	overlayAdaptor = RADEONSetupImageVideo(pScreen);
 	if (overlayAdaptor != NULL) {
 	    adaptors[num_adaptors++] = overlayAdaptor;
@@ -294,9 +294,12 @@ void RADEONInitVideo(ScreenPtr pScreen)
 	RADEONInitOffscreenImages(pScreen);
     }
 
-    if ((info->ChipFamily < CHIP_FAMILY_RS400)
+    if (info->ChipFamily >= CHIP_FAMILY_R600 && info->drm_mode_setting) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Disabling textured video for KMS On R600+\n");
+    } else if ((info->ChipFamily < CHIP_FAMILY_RS400)
 #ifdef XF86DRI
-	|| (info->directRenderingEnabled)
+	|| (info->directRenderingEnabled || info->drm_mode_setting)
 #endif
 	) {
 	texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen);
@@ -2197,7 +2200,7 @@ RADEONCopyData(
 
 #ifdef XF86DRI
 
-    if ( info->directRenderingEnabled && info->DMAForXv )
+    if ( info->directRenderingEnabled && info->DMAForXv && !info->new_cs )
     {
 	uint8_t *buf;
 	uint32_t bufPitch, dstPitchOff;
diff -up xf86-video-ati-6.12.2/src/radeon_video.h.modeset xf86-video-ati-6.12.2/src/radeon_video.h
--- xf86-video-ati-6.12.2/src/radeon_video.h.modeset	2009-04-07 11:31:53.000000000 -0400
+++ xf86-video-ati-6.12.2/src/radeon_video.h	2009-05-21 11:01:45.000000000 -0400
@@ -121,6 +121,9 @@ typedef struct {
     int w, h;
     int drw_x, drw_y;
     int vsync;
+
+    dri_bo *src_bo;
+    dri_bo *bicubic_bo;
 } RADEONPortPrivRec, *RADEONPortPrivPtr;
 
 xf86CrtcPtr