Blob Blame History Raw
diff --git a/configure.ac b/configure.ac
index b8c18a6..a7e954d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -115,6 +115,15 @@ 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
 
 save_CFLAGS="$CFLAGS"
diff --git a/src/Makefile.am b/src/Makefile.am
index 97c686b..d32e74a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -90,12 +90,13 @@ radeon_drv_ladir = @moduledir@/drivers
 radeon_drv_la_SOURCES = \
 	radeon_accel.c radeon_cursor.c radeon_dga.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_exa.c radeon_bufmgr_gem.c
 
 if XMODES
 radeon_drv_la_SOURCES += \
@@ -160,4 +161,5 @@ 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
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
new file mode 100644
index 0000000..97762ce
--- /dev/null
+++ b/src/drmmode_display.c
@@ -0,0 +1,681 @@
+/*
+ * 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 "radeon.h"
+#include "sarea.h"
+
+static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height);
+
+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;
+	Bool ret;
+
+	ErrorF("resize called %d %d\n", width, height);
+	ret = drmmode_resize_fb(scrn, drmmode, width, height);
+	scrn->virtualX = width;
+	scrn->virtualY = height;
+	return ret;
+}
+
+static void
+drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
+		     struct drm_mode_modeinfo *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,
+		     struct drm_mode_modeinfo *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 const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
+	drmmode_xf86crtc_resize
+};
+
+static void
+drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
+{
+
+}
+
+static Bool
+drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+		     Rotation rotation, int x, int y)
+{
+	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;
+	int ret = TRUE;
+	int i;
+	int fb_id;
+	struct drm_mode_modeinfo kmode;
+
+	saved_mode = crtc->mode;
+	saved_x = crtc->x;
+	saved_y = crtc->y;
+	saved_rotation = crtc->rotation;
+
+	crtc->mode = *mode;
+	crtc->x = x;
+	crtc->y = y;
+	crtc->rotation = rotation;
+
+	output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output);
+	if (!output_ids) {
+		ret = FALSE;
+		goto done;
+	}
+
+	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, mode, rotation)) {
+		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;
+	ErrorF("fb id is %d\n", fb_id);
+	drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+		       fb_id, x, y, output_ids, output_count, &kmode);
+
+
+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_map;
+
+	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;
+
+	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, drmmode_crtc->cursor_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;
+	unsigned long rotate_pitch;
+	dri_bo *rotate_bo;
+	int ret;
+	rotate_pitch = crtc->scrn->displayWidth * drmmode->cpp;
+	size = rotate_pitch * height;
+
+	rotate_bo = dri_bo_alloc(drmmode->bufmgr, "rotate", size, 0);
+	if (rotate_bo == NULL)
+		return NULL;
+
+	radeon_bufmgr_pin(rotate_bo);
+	dri_bo_map(rotate_bo, 1);
+
+	ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
+			   crtc->scrn->bitsPerPixel, rotate_pitch, radeon_bufmgr_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 = pScrn->displayWidth * 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");
+	}
+	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_unreference(drmmode_crtc->rotate_bo);
+		drmmode_crtc->rotate_bo = NULL;
+	}
+
+}
+
+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,
+
+    .shadow_create = drmmode_crtc_shadow_create,
+    .shadow_allocate = drmmode_crtc_shadow_allocate,
+    .shadow_destroy = drmmode_crtc_shadow_destroy,
+#if 0
+    .gamma_set = i830_crtc_gamma_set,
+#endif
+    .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)
+{
+	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;
+	char name[32];
+
+	koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
+	if (!koutput)
+		return;
+
+	kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
+	if (!kencoder) {
+		drmModeFreeConnector(koutput);
+		return;
+	}
+
+	snprintf(name, 32, "%s%d", output_names[koutput->connector_type], koutput->connector_type_id);
+
+	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;
+	return;
+}
+
+Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp)
+{
+	xf86CrtcConfigPtr   xf86_config;
+	int i;
+	Bool ret;
+
+	/* Create a bus Id */
+	/* Low level DRM open */
+	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);
+
+	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++)
+		drmmode_crtc_init(pScrn, drmmode, i);
+
+	for (i = 0; i < drmmode->mode_res->count_connectors; i++)
+		drmmode_output_init(pScrn, drmmode, i);
+
+	xf86InitialConfiguration(pScrn, FALSE);
+
+	return TRUE;
+}
+
+Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, dri_bufmgr *bufmgr)
+{
+	drmmode->bufmgr = bufmgr;
+	return TRUE;
+}
+
+void drmmode_set_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height, int pitch, uint32_t handle)
+{
+	int ret;
+
+	ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
+			   scrn->bitsPerPixel, pitch, handle,
+			   &drmmode->fb_id);
+
+	if (ret) {
+		ErrorF("Failed to add fb\n");
+	}
+
+	drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id);
+	if (!drmmode->mode_fb)
+		return;
+
+
+	ErrorF("Add fb id %d %d %d\n", drmmode->fb_id, width, height);
+}
+
+void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, void *ptr, uint32_t handle)
+{
+  	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_handle = handle;
+	drmmode_crtc->cursor_map = ptr;
+}
+
+Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo)
+{
+	xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (pScrn);
+	int i;
+
+	if (pPixData == NULL)
+		return FALSE;
+
+	for (i = 0; i < config->num_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+		if (!drmmode_crtc->rotate_bo)
+			continue;
+
+		if (drmmode_crtc->rotate_bo->virtual == pPixData) {
+			*bo = drmmode_crtc->rotate_bo;
+			return TRUE;
+		}
+	}
+	return FALSE;
+
+}
+
+static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height)
+{
+	uint32_t handle;
+	int pitch;
+	int ret;
+
+	return FALSE;
+
+	if (drmmode->mode_fb->width == width && drmmode->mode_fb->height == height)
+		return TRUE;
+
+	if (!drmmode->create_new_fb)
+		return FALSE;
+
+	handle = drmmode->create_new_fb(scrn, width, height, &pitch);
+	if (handle == 0)
+		return FALSE;
+
+	ret = drmModeReplaceFB(drmmode->fd, drmmode->fb_id, 
+			       width, height,
+			       scrn->depth, scrn->bitsPerPixel, pitch,
+			       handle);
+
+	if (ret)
+		return FALSE;
+
+	drmModeFreeFB(drmmode->mode_fb);
+	drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id);
+	if (!drmmode->mode_fb)
+		return FALSE;
+	
+	return TRUE;
+}
+
+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);
+	}
+}
+
+#endif
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
new file mode 100644
index 0000000..691d62e
--- /dev/null
+++ b/src/drmmode_display.h
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+  uint32_t (*create_new_fb)(ScrnInfoPtr pScrn, int width, int height, int *pitch);
+} drmmode_rec, *drmmode_ptr;
+
+typedef struct {
+
+    drmmode_ptr drmmode;
+    drmModeCrtcPtr mode_crtc;
+    uint32_t cursor_handle;
+    void *cursor_map;
+    dri_bo *rotate_bo;
+    int rotate_fb_id;
+} 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;
+} 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);
+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, uint32_t handle);
+extern Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo);
+extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, void *ptr, uint32_t handle);
+void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags);
+#endif
+#endif
diff --git a/src/radeon.h b/src/radeon.h
index 2348e7c..32bfa4e 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -46,6 +46,8 @@
 #include "compiler.h"
 #include "xf86fbman.h"
 
+#include "drmmode_display.h"
+
 				/* PCI support */
 #include "xf86Pci.h"
 
@@ -84,6 +86,7 @@
 #include "xf86Crtc.h"
 #include "X11/Xatom.h"
 
+#include "radeon_bufmgr.h"
 				/* Render support */
 #ifdef RENDER
 #include "picturestr.h"
@@ -403,6 +406,9 @@ typedef enum {
 
 typedef struct _atomBiosHandle *atomBiosHandlePtr;
 
+#define RADEON_POOL_GART 0
+#define RADEON_POOL_VRAM 1
+    
 typedef struct {
     uint32_t pci_device_id;
     RADEONChipFamily chip_family;
@@ -413,6 +419,25 @@ 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;
+};
+    
 typedef struct {
     EntityInfoPtr     pEnt;
     pciVideoPtr       PciInfo;
@@ -612,13 +637,13 @@ typedef struct {
     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 */
@@ -641,6 +666,9 @@ typedef struct {
     drmBufPtr         indirectBuffer;
     int               indirectStart;
 
+    drmBuf         ib_gem_fake;
+    void *ib_ptr;
+
 				/* DRI screen private data */
     int               fbX;
     int               fbY;
@@ -798,6 +826,45 @@ typedef struct {
 
     int num_gb_pipes;
     Bool has_tcl;
+
+    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_start;
+      uint64_t vram_size;
+      uint64_t gart_start;
+      uint64_t gart_size;
+
+      struct radeon_memory *bo_list[2];
+      struct radeon_memory *front_buffer;
+      struct radeon_memory *back_buffer;
+      struct radeon_memory *depth_buffer;
+
+#if 0
+      struct radeon_memory *exa_buffer;
+#endif
+      struct radeon_memory *texture_buffer;
+
+      struct radeon_memory *dma_buffer;
+      struct radeon_memory *gart_texture_buffer;
+      struct radeon_memory *rotate_buffer;
+      struct radeon_memory *cursor[2];
+
+      /* indirect buffer for accel */
+      struct radeon_memory *gem_ib_memory;
+      
+    } mm;
+
+    drm_handle_t fb_map_handle;
+    Bool drm_mode_setting;
+#ifdef XF86DRM_MODE
+    drmmode_rec drmmode;
+#endif
+
+    dri_bufmgr *bufmgr;
 } RADEONInfoRec, *RADEONInfoPtr;
 
 #define RADEONWaitForFifo(pScrn, entries)				\
@@ -1030,6 +1097,23 @@ extern void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode);
 extern void RADEONInitVideo(ScreenPtr pScreen);
 extern void RADEONResetVideo(ScrnInfoPtr pScrn);
 
+/* radeon_memory.c */
+extern uint32_t radeon_name_buffer(ScrnInfoPtr pScrn, struct radeon_memory *mem);
+extern Bool radeon_bind_all_memory(ScrnInfoPtr pScrn);
+extern Bool radeon_unbind_all_memory(ScrnInfoPtr pScrn);
+extern struct radeon_memory *radeon_allocate_memory(ScrnInfoPtr pScrn, int pool, int size, int alignment, Bool no_backing_store, char *name, 
+						    int need_bind);
+uint32_t radeon_create_new_fb(ScrnInfoPtr pScrn, int width, int height, int *pitch);
+int radeon_map_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem);
+void radeon_unmap_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem);
+void radeon_free_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem);
+Bool radeon_bind_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem);
+Bool radeon_free_all_memory(ScrnInfoPtr pScrn);
+Bool radeon_setup_kernel_mem(ScreenPtr pScreen);
+Bool RADEONDRIDoMappings(ScreenPtr pScreen);
+Bool radeon_update_dri_buffers(ScrnInfoPtr pScrn);
+Bool radeon_setup_gart_mem(ScreenPtr pScreen);
+
 #ifdef XF86DRI
 #  ifdef USE_XAA
 /* radeon_accelfuncs.c */
@@ -1048,7 +1132,9 @@ do {									\
 
 #define RADEONCP_RELEASE(pScrn, info)					\
 do {									\
-    if (info->CPInUse) {						\
+    if (info->new_cs) {							\
+	RADEONCPReleaseIndirect(pScrn);					\
+    } else if (info->CPInUse) {						\
 	RADEON_PURGE_CACHE();						\
 	RADEON_WAIT_UNTIL_IDLE();					\
 	RADEONCPReleaseIndirect(pScrn);					\
@@ -1082,7 +1168,7 @@ do {									\
 
 #define RADEONCP_REFRESH(pScrn, info)					\
 do {									\
-    if (!info->CPInUse) {						\
+    if (!info->CPInUse && !info->new_cs) {				\
 	if (info->needCacheFlush) {					\
 	    RADEON_PURGE_CACHE();					\
 	    RADEON_PURGE_ZCACHE();					\
@@ -1109,6 +1195,13 @@ do {									\
 #define RING_LOCALS	uint32_t *__head = NULL; int __expected; int __count = 0
 
 #define BEGIN_RING(n) do {						\
+    if (!info->indirectBuffer) {					\
+	info->indirectBuffer = RADEONCPGetBuffer(pScrn);		\
+	info->indirectStart = 0;					\
+    } else if (info->indirectBuffer->used + (n) * (int)sizeof(uint32_t) >	\
+	       info->indirectBuffer->total) {				\
+	RADEONCPFlushIndirect(pScrn, 1);				\
+    }									\
     if (RADEON_VERBOSE) {						\
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,				\
 		   "BEGIN_RING(%d) in %s\n", (unsigned int)n, __FUNCTION__);\
@@ -1121,13 +1214,6 @@ do {									\
     }									\
     info->dma_debug_func = __FILE__;					\
     info->dma_debug_lineno = __LINE__;					\
-    if (!info->indirectBuffer) {					\
-	info->indirectBuffer = RADEONCPGetBuffer(pScrn);		\
-	info->indirectStart = 0;					\
-    } else if (info->indirectBuffer->used + (n) * (int)sizeof(uint32_t) >	\
-	       info->indirectBuffer->total) {				\
-	RADEONCPFlushIndirect(pScrn, 1);				\
-    }									\
     __expected = n;							\
     __head = (pointer)((char *)info->indirectBuffer->address +		\
 		       info->indirectBuffer->used);			\
@@ -1170,6 +1256,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, __head, &__count, read_domains, write_domains); \
+  } while(0)
+
+
 #define FLUSH_RING()							\
 do {									\
     if (RADEON_VERBOSE)							\
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index e617fd5..09aa7f6 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -313,6 +313,9 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn)
     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,
@@ -371,7 +374,7 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
 		   info->CurrentLayout.bitsPerPixel);
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled && (IS_R300_3D || IS_R500_3D)) {
+    if ((info->directRenderingEnabled || info->drm_mode_setting) && (IS_R300_3D || IS_R500_3D)) {
 	drmRadeonGetParam np;
 	int num_pipes;
 
@@ -391,60 +394,62 @@ 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->num_gb_pipes == 0) {
-	    uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT);
-
-	    info->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->num_gb_pipes == 0) {
-	    if ((info->ChipFamily == CHIP_FAMILY_R300) ||
-		(info->ChipFamily == CHIP_FAMILY_R350)) {
-		/* R3xx chips */
-		info->num_gb_pipes = 2;
-	    } else {
-		/* RV3xx chips */
-		info->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->num_gb_pipes == 0) {
+		uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT);
+		
+		info->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->num_gb_pipes == 0) {
+		if ((info->ChipFamily == CHIP_FAMILY_R300) ||
+		    (info->ChipFamily == CHIP_FAMILY_R350)) {
+		    /* R3xx chips */
+		    info->num_gb_pipes = 2;
+		} else {
+		    /* RV3xx chips */
+		    info->num_gb_pipes = 1;
+		}
 	    }
 	}
+	
+	if (IS_R300_3D || IS_R500_3D)
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "num pipes is %d\n", info->num_gb_pipes);
+	
+	if (IS_R300_3D || IS_R500_3D) {
+	    uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 | R300_SUBPIXEL_1_16);
+	    
+	    switch(info->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);
     }
 
-    if (IS_R300_3D || IS_R500_3D)
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "num pipes is %d\n", info->num_gb_pipes);
-
-    if (IS_R300_3D || IS_R500_3D) {
-	uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 | R300_SUBPIXEL_1_16);
-
-	switch(info->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);
-
     switch (info->CurrentLayout.pixel_code) {
     case 8:  info->datatype = 2; break;
     case 15: info->datatype = 3; break;
@@ -556,6 +561,149 @@ int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info)
     }
 }
 
+drmBufPtr RADEONCSGetBuffer(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+
+    info->ib_gem_fake.address = xcalloc(1, RADEON_BUFFER_SIZE);
+    if (!info->ib_gem_fake.address)
+        return NULL;
+
+    info->ib_gem_fake.used = 0;
+    info->ib_gem_fake.total = RADEON_BUFFER_SIZE - (16*4); // reserve 16 dwords
+    return &info->ib_gem_fake;
+}
+
+void RADEONCSFlushIndirect(ScrnInfoPtr pScrn, int discard)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    struct drm_radeon_cs args;
+    int ret;
+    RING_LOCALS;
+
+    /* always add the cache flushes to the end of the IB */
+    info->indirectBuffer->total += 16 * 4;
+    
+    /* end of IB purge caches */
+    if (info->cs_used_depth) {
+	RADEON_PURGE_ZCACHE();
+	info->cs_used_depth = 0;
+    }
+
+    RADEON_PURGE_CACHE();
+    RADEON_WAIT_UNTIL_IDLE();
+
+    args.packets = (unsigned long)info->ib_gem_fake.address;
+    args.dwords = info->indirectBuffer->used / sizeof(uint32_t);
+
+    ret = drmCommandWriteRead(info->drmFD, DRM_RADEON_CS,
+			      &args, sizeof(args));
+
+    if (ret) {
+      FatalError("DRM Command submission failure %d\n", ret);
+      return;
+    }
+
+
+    info->indirectStart = 0;
+    info->indirectBuffer->used = 0;
+    info->indirectBuffer->total -= 16*4;
+
+    if (info->bufmgr)
+      radeon_gem_bufmgr_post_submit(info->bufmgr);
+
+    /* 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);
+}
+
+void RADEONCSReleaseIndirect(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+
+    if (!info->indirectBuffer) return;
+    RADEONCSFlushIndirect(pScrn, 0);
+    xfree(info->ib_gem_fake.address);
+    info->ib_gem_fake.address = NULL;
+    info->indirectBuffer = NULL;
+
+}
+
+drmBufPtr RADEONGEMGetBuffer(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    int ret;
+
+    info->mm.gem_ib_memory = radeon_allocate_memory(pScrn, RADEON_POOL_GART, RADEON_BUFFER_SIZE,
+						    0, 0, "Accel IB", 0);
+
+    if (!info->mm.gem_ib_memory) {
+	ErrorF("Unable to map allocate IB\n");
+	return NULL;
+    }
+
+    radeon_bind_memory(pScrn, info->mm.gem_ib_memory);
+    ret = radeon_map_memory(pScrn, info->mm.gem_ib_memory);
+    if (ret) {
+	ErrorF("Unable to map IB\n");
+	radeon_free_memory(pScrn, info->mm.gem_ib_memory);
+	return NULL;
+    }
+    info->ib_gem_fake.address = info->mm.gem_ib_memory->map;
+    info->ib_gem_fake.used = 0;
+    info->ib_gem_fake.total = RADEON_BUFFER_SIZE;
+    
+    return &info->ib_gem_fake;
+}
+
+void RADEONGEMFlushIndirect(ScrnInfoPtr pScrn, int discard)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+    struct drm_radeon_gem_indirect args;
+    struct drm_radeon_gem_set_domain dom_args;
+
+    if (RADEON_VERBOSE) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing IB\n");
+    }
+
+    args.handle = info->mm.gem_ib_memory->kernel_bo_handle;
+    args.used = info->indirectBuffer->used;
+
+
+    drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_INDIRECT,
+			&args, sizeof(args));
+
+    /* for now just wait for the buffer to come around again */
+
+    dom_args.handle = info->mm.gem_ib_memory->kernel_bo_handle;
+    dom_args.read_domains = RADEON_GEM_DOMAIN_GTT;
+    dom_args.write_domain = 0;
+
+    drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_SET_DOMAIN,
+			&dom_args, sizeof(dom_args));
+
+    info->indirectStart = 0;
+    info->indirectBuffer->used = 0;
+}
+
+void RADEONGEMReleaseIndirect(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info = RADEONPTR(pScrn);
+
+    if (RADEON_VERBOSE) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing IB\n");
+    }
+
+    if (!info->indirectBuffer) return;
+
+    RADEONGEMFlushIndirect(pScrn, 0);
+
+    radeon_free_memory(pScrn, info->mm.gem_ib_memory);
+    info->mm.gem_ib_memory = NULL;
+    info->indirectBuffer = NULL;
+}
+
 /* Get an indirect buffer for the CP 2D acceleration commands  */
 drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn)
 {
@@ -566,6 +714,9 @@ drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn)
     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
@@ -631,6 +782,11 @@ void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard)
     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);
@@ -665,10 +821,17 @@ void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn)
     int                start  = info->indirectStart;
     drmRadeonIndirect  indirect;
 
+
+    if (info->new_cs) {
+      RADEONCSReleaseIndirect(pScrn);
+      return;
+    }
+
     info->indirectBuffer = NULL;
     info->indirectStart  = 0;
 
     if (!buffer) return;
+      
 
     if (RADEON_VERBOSE) {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing buffer %d\n",
@@ -795,6 +958,7 @@ RADEONHostDataBlit(
     ret = ( uint8_t* )&__head[__count];
 
     __count += dwords;
+
     ADVANCE_RING();
 
     *y += *hpass;
@@ -932,7 +1096,7 @@ Bool RADEONAccelInit(ScreenPtr pScreen)
 #ifdef USE_EXA
     if (info->useEXA) {
 # ifdef XF86DRI
-	if (info->directRenderingEnabled) {
+	if (info->directRenderingEnabled || info->drm_mode_setting) {
 	    if (!RADEONDrawInitCP(pScreen))
 		return FALSE;
 	} else
@@ -953,7 +1117,7 @@ Bool RADEONAccelInit(ScreenPtr pScreen)
 	}
 
 #ifdef XF86DRI
-	if (info->directRenderingEnabled)
+	if (info->directRenderingEnabled || info->drm_mode_setting)
 	    RADEONAccelInitCP(pScreen, a);
 	else
 #endif /* XF86DRI */
@@ -975,11 +1139,13 @@ void RADEONInit3DEngine(ScrnInfoPtr pScrn)
     RADEONInfoPtr info = RADEONPTR (pScrn);
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled) {
-	RADEONSAREAPrivPtr pSAREAPriv;
-
-	pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-	pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
+    if (info->directRenderingEnabled || info->drm_mode_setting) {
+	if (info->directRenderingEnabled) {
+	    RADEONSAREAPrivPtr pSAREAPriv;
+	    
+	    pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+	    pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen);
+	}
 	RADEONInit3DEngineCP(pScrn);
     } else
 #endif
diff --git a/src/radeon_bufmgr.h b/src/radeon_bufmgr.h
new file mode 100644
index 0000000..a16ad9a
--- /dev/null
+++ b/src/radeon_bufmgr.h
@@ -0,0 +1,30 @@
+/**
+ * @file intel_bufmgr.h
+ *
+ * Public definitions of Intel-specific bufmgr functions.
+ */
+
+#ifndef RADEON_BUFMGR_H
+#define RADEON_BUFMGR_H
+
+#include "dri_bufmgr.h"
+
+struct radeon_bufmgr {
+  void (*emit_reloc)(dri_bo *buf, 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);
+
+void radeon_bufmgr_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain);
+
+dri_bufmgr *radeon_bufmgr_exa_init(ScrnInfoPtr pScrn);
+extern void radeon_bufmgr_exa_wait_rendering(dri_bo *bo);
+extern dri_bo *radeon_bufmgr_exa_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem);
+void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr);
+void radeon_bufmgr_pin(dri_bo *buf);
+void radeon_bufmgr_unpin(dri_bo *buf);
+uint32_t radeon_bufmgr_get_handle(dri_bo *buf);
+void radeon_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr);
+#endif
diff --git a/src/radeon_bufmgr_exa.c b/src/radeon_bufmgr_exa.c
new file mode 100644
index 0000000..64537a6
--- /dev/null
+++ b/src/radeon_bufmgr_exa.c
@@ -0,0 +1,324 @@
+/**************************************************************************
+ *
+ * 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 "xf86.h"
+#include "errno.h"
+#include "dri_bufmgr.h"
+#include "string.h"
+
+#include "radeon_reg.h"
+#include "radeon_probe.h"
+#include "radeon.h"
+#include "radeon_bufmgr.h"
+
+
+typedef struct _dri_bo_exa {
+	dri_bo bo;
+	struct radeon_memory *mem;
+	int refcount;
+	int reloc_count;
+	int map_count;
+	/* reloc list - add to list for relocs */
+	struct _dri_bo_exa *next;
+} dri_bo_exa;
+
+typedef struct _dri_bufmgr_exa {
+	dri_bufmgr bufmgr;
+	struct radeon_bufmgr radeon_bufmgr;
+	ScrnInfoPtr pScrn;
+	struct _dri_bo_exa *reloc_head;
+} dri_bufmgr_exa;
+
+static dri_bo *
+dri_exa_alloc(dri_bufmgr *bufmgr, const char *name,
+	      unsigned long size, unsigned int alignment)
+
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)bufmgr;
+	RADEONInfoPtr info = RADEONPTR(bufmgr_exa->pScrn);
+	dri_bo_exa *exa_buf;
+
+	exa_buf = malloc(sizeof(*exa_buf));
+	if (!exa_buf)
+		return NULL;
+
+	exa_buf->refcount = 1;
+	exa_buf->mem = radeon_allocate_memory(bufmgr_exa->pScrn, RADEON_POOL_GART,
+					      size, alignment, 0, name, 0);
+
+	exa_buf->bo.size = exa_buf->mem->size;
+	exa_buf->bo.offset = exa_buf->mem->offset;
+	exa_buf->bo.bufmgr = bufmgr;
+	exa_buf->next = NULL;
+	exa_buf->reloc_count = 0;
+	exa_buf->map_count = 0;
+
+	return &exa_buf->bo;
+}
+
+static void
+dri_exa_bo_reference(dri_bo *buf)
+{
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+	exa_buf->refcount++;
+}
+
+static void
+dri_exa_bo_unreference(dri_bo *buf)
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr;
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+
+	if (!buf)
+		return;
+
+	if (--exa_buf->refcount == 0)
+		radeon_free_memory(bufmgr_exa->pScrn, exa_buf->mem);
+}
+
+static int
+dri_exa_bo_map(dri_bo *buf, int write_enable)
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr;
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+
+	if (exa_buf->map_count++ != 0)
+		return 0;
+	
+	radeon_map_memory(bufmgr_exa->pScrn, exa_buf->mem);
+	exa_buf->bo.virtual = exa_buf->mem->map;
+	return 0;
+}
+
+static int
+dri_exa_bo_unmap(dri_bo *buf)
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr;
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+
+	if (--exa_buf->map_count > 0)
+		return 0;
+
+	radeon_unmap_memory(bufmgr_exa->pScrn, exa_buf->mem);
+	exa_buf->bo.virtual = 0;
+	return 0;
+}
+
+static void
+dri_bufmgr_exa_destroy(dri_bufmgr *bufmgr)
+{
+	free(bufmgr);
+}
+
+void radeon_bufmgr_exa_wait_rendering(dri_bo *buf)
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr;
+	RADEONInfoPtr info = RADEONPTR(bufmgr_exa->pScrn);
+	struct drm_radeon_gem_set_domain dom_args;
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+	int ret;
+
+	dom_args.handle = exa_buf->mem->kernel_bo_handle;
+	dom_args.read_domains = RADEON_GEM_DOMAIN_GTT;
+	dom_args.write_domain = 0;
+	ret = drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_SET_DOMAIN,
+				  &dom_args, sizeof(dom_args));
+
+	return;
+}
+
+int radeon_bufmgr_subdata(dri_bo *buf, unsigned long offset,
+			  unsigned long size, const void *data)
+{
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr;
+	RADEONInfoPtr info = RADEONPTR(bufmgr_exa->pScrn);
+	int ret;
+	/* go to pwrite */
+	struct drm_radeon_gem_pwrite pwrite;
+
+	pwrite.handle = exa_buf->mem->kernel_bo_handle;
+	pwrite.offset = offset;
+	pwrite.size = size;
+	pwrite.data_ptr = (uint64_t)(uintptr_t)data;
+
+	do {
+		ret = drmCommandWriteRead(info->drmFD, DRM_IOCTL_RADEON_GEM_PWRITE,
+					  &pwrite, sizeof(pwrite));
+	} while (ret == -1 && errno == EINTR);
+
+	if (ret != 0) {
+		fprintf(stderr,"Pwrite %lx at %lx failed\n", size, offset);
+		return -1;
+	}
+	return 0;
+}
+
+
+dri_bo *
+radeon_bufmgr_exa_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem)
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)bufmgr;
+	dri_bo_exa *exa_buf;
+
+	exa_buf = malloc(sizeof(*exa_buf));
+	if (!exa_buf)
+		return NULL;
+	exa_buf->refcount = 1;
+	exa_buf->mem =  mem;
+	exa_buf->bo.size = exa_buf->mem->size;
+	exa_buf->bo.offset = exa_buf->mem->offset;
+	exa_buf->bo.bufmgr = bufmgr;
+	exa_buf->bo.virtual = exa_buf->mem->map;
+	exa_buf->next = NULL;
+	exa_buf->reloc_count = 0;
+	/* get map count right */
+	exa_buf->map_count = 1;
+
+	return &exa_buf->bo;
+}
+
+static void radeon_bufmgr_exa_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain)
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr;
+	ScrnInfoPtr pScrn = bufmgr_exa->pScrn;
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+	uint32_t *__head = head;
+	uint32_t __count = *count_p;
+	dri_bo_exa *trav;
+
+	if (exa_buf->reloc_count == 0) {
+		dri_bo_reference(buf);
+
+		if (bufmgr_exa->reloc_head == NULL)
+			bufmgr_exa->reloc_head = exa_buf;
+		else {
+			trav = bufmgr_exa->reloc_head;
+			while (trav->next != NULL)
+				trav = trav->next;
+			trav->next = exa_buf;
+		}
+	}
+	exa_buf->reloc_count++;
+	OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 2));
+	OUT_RING(exa_buf->mem->kernel_bo_handle);
+	OUT_RING(read_domains);
+	OUT_RING(write_domain);
+	*count_p = __count;
+}
+
+/**
+ * Initializes the EXA buffer manager, which is just a thin wrapper
+ * around the EXA 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_exa_init(ScrnInfoPtr pScrn)
+{
+	dri_bufmgr_exa *bufmgr_exa;
+
+	bufmgr_exa = calloc(1, sizeof(*bufmgr_exa));
+	bufmgr_exa->pScrn = pScrn;
+
+	bufmgr_exa->bufmgr.bo_alloc = dri_exa_alloc;
+	bufmgr_exa->bufmgr.bo_reference = dri_exa_bo_reference;
+	bufmgr_exa->bufmgr.bo_unreference = dri_exa_bo_unreference;
+	bufmgr_exa->bufmgr.bo_map = dri_exa_bo_map;
+	bufmgr_exa->bufmgr.bo_unmap = dri_exa_bo_unmap;
+	bufmgr_exa->bufmgr.destroy = dri_bufmgr_exa_destroy;
+	bufmgr_exa->bufmgr.bo_wait_rendering = radeon_bufmgr_exa_wait_rendering;
+	bufmgr_exa->radeon_bufmgr.emit_reloc = radeon_bufmgr_exa_emit_reloc;
+	return &bufmgr_exa->bufmgr;
+}
+
+void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr)
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)bufmgr;
+	struct _dri_bo_exa *trav, *prev;
+
+	if (!bufmgr_exa->reloc_head)
+		return;
+
+	trav = bufmgr_exa->reloc_head;
+	while (trav) {
+		prev = trav;
+		trav = trav->next;
+		
+		prev->reloc_count = 0;
+		prev->next = NULL;
+		dri_bo_unreference(&prev->bo);
+	}
+	bufmgr_exa->reloc_head = NULL;
+
+}
+
+void radeon_bufmgr_pin(dri_bo *buf)
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr;
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+
+	radeon_bind_memory(bufmgr_exa->pScrn, exa_buf->mem);
+}
+
+void radeon_bufmgr_unpin(dri_bo *buf)
+{
+	dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr;
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+
+	radeon_unbind_memory(bufmgr_exa->pScrn, exa_buf->mem);
+}
+
+uint32_t radeon_bufmgr_get_handle(dri_bo *buf)
+{
+	dri_bo_exa *exa_buf = (dri_bo_exa *)buf;
+	
+	return exa_buf->mem->kernel_bo_handle;
+}
diff --git a/src/radeon_bufmgr_exa.h b/src/radeon_bufmgr_exa.h
new file mode 100644
index 0000000..260322c
--- /dev/null
+++ b/src/radeon_bufmgr_exa.h
@@ -0,0 +1,14 @@
+#ifndef RADEON_BUFMGR_EXA_H
+#define RADEON_BUFMGR_EXA_H
+
+#include "dri_bufmgr.h"
+
+dri_bufmgr *radeon_bufmgr_exa_init(ScrnInfoPtr pScrn);
+extern void radeon_bufmgr_exa_wait_rendering(dri_bo *bo);
+extern dri_bo *radeon_bufmgr_exa_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem);
+void radeon_bufmgr_exa_emit_reloc(dri_bo *bo, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain);
+void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr);
+void radeon_bufmgr_pin(dri_bo *buf);
+void radeon_bufmgr_unpin(dri_bo *buf);
+uint32_t radeon_bufmgr_get_handle(dri_bo *buf);
+#endif
diff --git a/src/radeon_bufmgr_gem.c b/src/radeon_bufmgr_gem.c
new file mode 100644
index 0000000..db28edc
--- /dev/null
+++ b/src/radeon_bufmgr_gem.c
@@ -0,0 +1,530 @@
+/**************************************************************************
+ *
+ * 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 "dri_bufmgr.h"
+#include "string.h"
+
+#include "radeon_reg.h"
+#include "radeon_probe.h"
+#include "radeon.h"
+#include "radeon_bufmgr.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;
+	struct _dri_bo_gem *reloc_next;
+	int in_vram; /* have we migrated this bo to VRAM ever */
+} dri_bo_gem;
+
+struct dri_gem_bo_bucket {
+   dri_bo_gem *head, **tail;
+   /**
+    * Limit on the number of entries in this bucket.
+    *
+    * 0 means that this caching at this bucket size is disabled.
+    * -1 means that there is no limit to caching at this size.
+    */
+   int max_entries;
+   int num_entries;
+};
+
+/* Arbitrarily chosen, 16 means that the maximum size we'll cache for reuse
+ * is 1 << 16 pages, or 256MB.
+ */
+#define RADEON_GEM_BO_BUCKETS	16
+
+typedef struct _dri_bufmgr_gem {
+	dri_bufmgr bufmgr;
+	struct radeon_bufmgr radeon_bufmgr;
+	int fd;
+	struct _dri_bo_gem *reloc_head;
+	
+	/** Array of lists of cached gem objects of power-of-two sizes */
+	struct dri_gem_bo_bucket cache_bucket[RADEON_GEM_BO_BUCKETS];
+} dri_bufmgr_gem;
+
+static int
+logbase2(int n)
+{
+   int i = 1;
+   int log2 = 0;
+
+   while (n > i) {
+      i *= 2;
+      log2++;
+   }
+
+   return log2;
+}
+
+static struct dri_gem_bo_bucket *
+dri_gem_bo_bucket_for_size(dri_bufmgr_gem *bufmgr_gem, unsigned long size)
+{
+    int i;
+
+    /* We only do buckets in power of two increments */
+    if ((size & (size - 1)) != 0)
+	return NULL;
+
+    /* We should only see sizes rounded to pages. */
+    assert((size % 4096) == 0);
+
+    /* We always allocate in units of pages */
+    i = ffs(size / 4096) - 1;
+    if (i >= RADEON_GEM_BO_BUCKETS)
+	return NULL;
+
+    return &bufmgr_gem->cache_bucket[i];
+}
+
+
+static dri_bo *
+dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
+		 unsigned long size, unsigned int alignment)
+
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
+	struct drm_radeon_gem_create args;
+	int ret;
+	unsigned int page_size = getpagesize();
+	dri_bo_gem *gem_bo;
+	struct dri_gem_bo_bucket *bucket;
+	int alloc_from_cache = 0;
+	unsigned long bo_size;
+
+	/* Round the allocated size up to a power of two number of pages. */
+	bo_size = 1 << logbase2(size);
+	if (bo_size < page_size)
+		bo_size = page_size;
+	bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_size);
+    
+	/* If we don't have caching at this size, don't actually round the
+	 * allocation up.
+	 */
+	if (bucket == NULL || bucket->max_entries == 0) {
+		bo_size = size;
+		if (bo_size < page_size)
+			bo_size = page_size;
+	}
+
+	/* Get a buffer out of the cache if available */
+	if (bucket != NULL && bucket->num_entries > 0) {
+		struct drm_radeon_gem_set_domain args;
+
+		gem_bo = bucket->head;
+		args.handle = gem_bo->gem_handle;
+		args.read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+		args.write_domain = 0;
+		ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_RADEON_GEM_SET_DOMAIN, &args);
+		alloc_from_cache = (ret == 0);
+
+		if (alloc_from_cache) {
+			bucket->head = gem_bo->next;
+			if (gem_bo->next == NULL)
+				bucket->tail = &bucket->head;
+			bucket->num_entries--;
+		}
+	}
+
+	if (!alloc_from_cache) {
+
+		gem_bo = calloc(1, sizeof(*gem_bo));
+		if (!gem_bo)
+			return NULL;
+
+		gem_bo->bo.size = bo_size;
+		args.size = bo_size;
+		args.alignment = alignment;
+		args.initial_domain = RADEON_GEM_DOMAIN_CPU;
+		args.no_backing_store = 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 = name;
+
+	DBG("bo_create: buf %d (%s) %ldb: %d\n",
+	    gem_bo->gem_handle, gem_bo->name, size, alloc_from_cache);
+
+	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;
+	struct drm_gem_close args;
+
+	if (gem_bo->map_count)
+		munmap(gem_bo->bo.virtual, gem_bo->bo.size);
+
+	/* close object */
+	args.handle = gem_bo->gem_handle;
+	ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &args);
+	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) {
+		struct dri_gem_bo_bucket *bucket;
+		
+
+		bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
+		/* Put the buffer into our internal cache for reuse if we can. */
+		if ((gem_bo->in_vram == 0) && (bucket != NULL &&
+		    (bucket->max_entries == -1 ||
+		     (bucket->max_entries > 0 &&
+		      bucket->num_entries < bucket->max_entries))))
+		{
+			DBG("bo_unreference final: %d (%s) 1\n",
+			    gem_bo->gem_handle, gem_bo->name);
+		
+			gem_bo->name = 0;
+			
+			gem_bo->next = NULL;
+			*bucket->tail = gem_bo;
+			bucket->tail = &gem_bo->next;
+			bucket->num_entries++;
+		} else {
+			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;
+
+	if (gem_bo->map_count++ != 0)
+		return 0;
+	
+	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)
+		gem_bo->bo.virtual = (void *)(unsigned long)args.addr_ptr;
+
+	return ret;
+}
+
+static int
+dri_gem_bo_unmap(dri_bo *buf)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr;
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+
+	if (--gem_bo->map_count > 0)
+		return 0;
+
+        munmap(gem_bo->bo.virtual, gem_bo->bo.size);
+	gem_bo->bo.virtual = 0;
+	return 0;
+}
+
+static void
+dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
+	int i;
+
+	/* Free any cached buffer objects we were going to reuse */
+	for (i = 0; i < RADEON_GEM_BO_BUCKETS; i++) {
+		struct dri_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i];
+		dri_bo_gem *bo_gem;
+
+		while ((bo_gem = bucket->head) != NULL) {
+			bucket->head = bo_gem->next;
+			if (bo_gem->next == NULL)
+				bucket->tail = &bucket->head;
+			bucket->num_entries--;
+			
+			dri_gem_bo_free(&bo_gem->bo);
+		}
+	}
+	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_set_domain dom_args;
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+	int ret;
+
+	dom_args.handle = gem_bo->gem_handle;
+	dom_args.read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
+	dom_args.write_domain = 0;
+	ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_SET_DOMAIN,
+				  &dom_args, sizeof(dom_args));
+	return;
+}
+
+/**
+ * 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;
+    dri_bo_gem *bo_gem;
+    int ret;
+    struct drm_gem_open open_arg;
+
+    bo_gem = calloc(1, sizeof(*bo_gem));
+    if (!bo_gem)
+	return NULL;
+
+    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));
+	free(bo_gem);
+	return NULL;
+    }
+    bo_gem->bo.size = open_arg.size;
+    bo_gem->bo.offset = 0;
+    bo_gem->bo.virtual = NULL;
+    bo_gem->bo.bufmgr = bufmgr;
+    bo_gem->name = name;
+    bo_gem->refcount = 1;
+    bo_gem->gem_handle = open_arg.handle;
+
+    return &bo_gem->bo;
+}
+
+#define BUF_OUT_RING(x)	 do {			\
+		__head[__count++] = (x);				\
+	} while (0)
+
+void radeon_bufmgr_gem_emit_reloc(dri_bo *buf, 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;
+	dri_bo_gem *trav;
+	
+	if (gem_bo->reloc_count == 0) {
+		dri_bo_reference(buf);
+
+		if (bufmgr_gem->reloc_head == NULL)
+			bufmgr_gem->reloc_head = gem_bo;
+		else {
+			trav = bufmgr_gem->reloc_head;
+			while (trav->reloc_next != NULL)
+				trav = trav->reloc_next;
+			trav->reloc_next = gem_bo;
+		}
+	}
+
+	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;
+	}
+
+	gem_bo->reloc_count++;
+	BUF_OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 2));
+	BUF_OUT_RING(gem_bo->gem_handle);
+	BUF_OUT_RING(read_domains);
+	BUF_OUT_RING(write_domain);
+	*count_p = __count;
+}
+
+/**
+ * Enables unlimited caching of buffer objects for reuse.
+ *
+ * This is potentially very memory expensive, as the cache at each bucket
+ * size is only bounded by how many buffers of that size we've managed to have
+ * in flight at once.
+ */
+void
+radeon_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr)
+{
+    dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
+    int i;
+
+    for (i = 0; i < RADEON_GEM_BO_BUCKETS; i++) {
+	bufmgr_gem->cache_bucket[i].max_entries = -1;
+    }
+}
+
+/**
+ * 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;
+	int i;
+
+	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;
+	/* Initialize the linked lists for BO reuse cache. */
+	for (i = 0; i < RADEON_GEM_BO_BUCKETS; i++)
+		bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head;
+	bufmgr_gem->bufmgr.debug = 0;
+	return &bufmgr_gem->bufmgr;
+}
+
+
+void radeon_gem_bufmgr_post_submit(dri_bufmgr *bufmgr)
+{
+	dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
+	struct _dri_bo_gem *trav, *prev;
+
+	if (!bufmgr_gem->reloc_head)
+		return;
+
+	trav = bufmgr_gem->reloc_head;
+	while (trav) {
+		prev = trav;
+		trav = trav->reloc_next;
+		
+		prev->reloc_count = 0;
+		prev->reloc_next = NULL;
+		dri_bo_unreference(&prev->bo);
+	}
+	bufmgr_gem->reloc_head = NULL;
+
+}
+
+void radeon_gem_bufmgr_pin(dri_bo *buf)
+{
+}
+
+void radeon_gem_bufmgr_unpin(dri_bo *buf)
+{
+}
+
+uint32_t radeon_gem_bufmgr_get_handle(dri_bo *buf)
+{
+	dri_bo_gem *gem_bo = (dri_bo_gem *)buf;
+	
+	return gem_bo->gem_handle;
+}
+
+void radeon_bufmgr_emit_reloc(dri_bo *buf, 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, head, count_p, read_domains, write_domain);
+}
diff --git a/src/radeon_bufmgr_gem.h b/src/radeon_bufmgr_gem.h
new file mode 100644
index 0000000..e2f1ca6
--- /dev/null
+++ b/src/radeon_bufmgr_gem.h
@@ -0,0 +1,14 @@
+#ifndef RADEON_BUFMGR_GEM_H
+#define RADEON_BUFMGR_GEM_H
+
+#include "dri_bufmgr.h"
+
+dri_bufmgr *radeon_bufmgr_gem_init(ScrnInfoPtr pScrn);
+extern void radeon_bufmgr_gem_wait_rendering(dri_bo *bo);
+extern dri_bo *radeon_bufmgr_gem_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem);
+void radeon_bufmgr_gem_emit_reloc(dri_bo *bo, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain);
+void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr);
+void radeon_bufmgr_pin(dri_bo *buf);
+void radeon_bufmgr_unpin(dri_bo *buf);
+uint32_t radeon_bufmgr_get_handle(dri_bo *buf);
+#endif
diff --git a/src/radeon_common.h b/src/radeon_common.h
index 193c1f9..c3b7e3b 100644
--- a/src/radeon_common.h
+++ b/src/radeon_common.h
@@ -39,6 +39,9 @@
 #include <inttypes.h>
 #include "xf86drm.h"
 
+#include "radeon_drm.h"
+
+#if 0
 /* WARNING: If you change any of these defines, make sure to change
  * the kernel include file as well (radeon_drm.h)
  */
@@ -494,3 +497,13 @@ typedef struct drm_radeon_surface_free {
 #define	DRM_RADEON_VBLANK_CRTC2 	2
 
 #endif
+
+typedef drm_radeon_indirect_t drmRadeonIndirect;
+typedef drm_radeon_getparam_t drmRadeonGetParam;
+typedef drm_radeon_cp_stop_t drmRadeonCPStop;
+typedef drm_radeon_surface_alloc_t drmRadeonSurfaceAlloc;
+typedef drm_radeon_surface_free_t drmRadeonSurfaceFree;
+typedef drm_radeon_init_t drmRadeonInit;
+typedef drm_radeon_mem_init_heap_t drmRadeonMemInitHeap;
+typedef drm_radeon_setparam_t drmRadeonSetParam;
+#endif
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index d0c5229..15a3beb 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -62,11 +62,13 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
 
     if (IS_R300_3D || IS_R500_3D) {
 
-	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 | R300_SUBPIXEL_1_16);
 
@@ -688,7 +690,7 @@ void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn)
 
 #ifdef ACCEL_CP
     /* Make sure the CP is idle first */
-    if (info->CPStarted) {
+    if (info->CPStarted || info->drm_mode_setting) {
 	int  ret;
 
 	FLUSH_RING();
diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c
index 13c2b9c..1e1835a 100644
--- a/src/radeon_cursor.c
+++ b/src/radeon_cursor.c
@@ -96,12 +96,19 @@ avivo_setup_cursor(xf86CrtcPtr crtc, Bool enable)
     RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
     RADEONInfoPtr  info = RADEONPTR(crtc->scrn);
     unsigned char     *RADEONMMIO = info->MMIO;
-
+    uint32_t location;
+    
     OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 0);
 
     if (enable) {
+
+	if (info->drm_mm)
+	    location = info->fbLocation + radeon_crtc->cursor->offset;
+	else
+	    location = info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset;
+
 	OUTREG(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
-	       info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset);
+	       location);
 	OUTREG(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
 	       ((CURSOR_WIDTH - 1) << 16) | (CURSOR_HEIGHT - 1));
 	OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
@@ -203,6 +210,7 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
     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;
@@ -235,8 +243,12 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 					       | (yorigin ? 0 : y)));
 	    RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n",
 			  radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp));
+	    if (info->drm_mm)
+		offset = radeon_crtc->cursor->offset;
+	    else
+		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)
@@ -246,8 +258,12 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 						| (yorigin ? 0 : y)));
 	    RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n",
 			  radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp));
+	    if (info->drm_mm)
+		offset = radeon_crtc->cursor->offset;
+	    else
+		offset = radeon_crtc->cursor_offset + pScrn->fbOffset;
 	    OUTREG(RADEON_CUR2_OFFSET,
-		   radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride);
+		   offset + yorigin * stride);
 	}
     }
 }
@@ -301,10 +317,15 @@ radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
     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"));
 
+    if (info->drm_mm) 
+      d = (uint32_t *)radeon_crtc->cursor->map;
+    else
+      d = (uint32_t *)(pointer)(info->FB + radeon_crtc->cursor_offset);
+
     info->cursor_argb = TRUE;
 
     CURSOR_SWAPPING_START();
@@ -336,7 +357,7 @@ Bool RADEONCursorInit(ScreenPtr pScreen)
     height      = ((size_bytes * xf86_config->num_crtc) + width_bytes - 1) / width_bytes;
 
 #ifdef USE_XAA
-    if (!info->useEXA) {
+    if (!info->useEXA && !info->drm_mm) {
 	int align = IS_AVIVO_VARIANT ? 4096 : 256;
 	FBAreaPtr          fbarea;
 
diff --git a/src/radeon_dri.c b/src/radeon_dri.c
index a192811..9fa0add 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -40,6 +40,8 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <errno.h>
+#include <sys/ioctl.h>
 
 				/* Driver data structures */
 #include "radeon.h"
@@ -49,6 +51,8 @@
 #include "radeon_dri.h"
 #include "radeon_version.h"
 
+#include "radeon_drm.h"
+
 				/* X and server generic header files */
 #include "xf86.h"
 #include "xf86PciInfo.h"
@@ -62,17 +66,31 @@
 
 static size_t radeon_drm_page_size;
 
+#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
@@ -345,6 +363,120 @@ static void RADEONDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
 #endif
 }
 
+
+uint32_t radeon_name_buffer(ScrnInfoPtr pScrn, struct radeon_memory *mem)
+{
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    struct drm_gem_flink flink;
+    int ret;
+	
+    if (mem && mem->kernel_bo_handle) {
+	if (!mem->kernel_name) {
+	    flink.handle = mem->kernel_bo_handle;
+	    ret = ioctl(info->drmFD, DRM_IOCTL_GEM_FLINK, &flink);
+	    if (ret != 0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "[drm] failed to name buffer %d\n", -errno);
+		return -1;
+	    }
+	    mem->kernel_name = flink.name;
+	}
+	return mem->kernel_name;
+    }
+    return -1;
+}
+
+static void radeon_update_sarea(ScrnInfoPtr pScrn, RADEONSAREAPrivPtr sarea)
+{
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    int cpp = info->CurrentLayout.pixel_bytes;
+    sarea->front_handle = -1;
+    sarea->back_handle = -1;
+    sarea->depth_handle = -1;
+   
+    if (info->drm_mm){
+	/* get handles and use them */
+	sarea->front_handle = radeon_name_buffer(pScrn, info->mm.front_buffer);
+
+	sarea->front_pitch         = info->frontPitch * cpp;
+	sarea->back_pitch         = info->backPitch * cpp;
+	sarea->depth_pitch         = info->depthPitch * cpp;
+	ErrorF("front handle is %x\n", sarea->front_handle);
+	sarea->back_handle = radeon_name_buffer(pScrn, info->mm.back_buffer);
+	sarea->depth_handle = radeon_name_buffer(pScrn, info->mm.depth_buffer);
+
+    }
+}
+
+/* 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, RADEONSAREAPrivPtr sarea)
+{
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    RADEONDRIPtr pRADEONDRI;
+
+    pRADEONDRI                    = (RADEONDRIPtr)info->pDRIInfo->devPrivate;
+    info->pDRIInfo->frameBufferPhysicalAddress = (char *) info->LinearAddr;
+    info->pDRIInfo->frameBufferStride = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
+    info->pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes);
+#if DRI_DRIVER_FRAMEBUFFER_MAP
+    info->pDRIInfo->hFrameBuffer = info->fb_map_handle;
+#endif
+    /* overload these */
+    pRADEONDRI->gartTexHandle = radeon_name_buffer(pScrn, info->mm.gart_texture_buffer);
+    pRADEONDRI->textureOffset = radeon_name_buffer(pScrn, info->mm.texture_buffer);
+    pRADEONDRI->frontOffset = radeon_name_buffer(pScrn, info->mm.front_buffer);
+    pRADEONDRI->backOffset = radeon_name_buffer(pScrn, info->mm.back_buffer);
+    pRADEONDRI->depthOffset = radeon_name_buffer(pScrn, info->mm.depth_buffer);
+}
+
+static Bool
+radeon_update_dri_mappings(ScrnInfoPtr pScrn, RADEONSAREAPrivPtr 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->drmFD, info->fb_map_handle);
+	info->fb_map_handle = 0;
+    }
+	
+    ret = drmAddMap(info->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(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    Bool success;
+    RADEONSAREAPrivPtr sarea = DRIGetSAREAPrivate(pScrn->pScreen);
+    success = radeon_update_dri_mappings(pScrn, sarea);
+
+    if (!success)
+	return FALSE;
+
+    radeon_update_sarea(pScrn, sarea);
+    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
@@ -362,7 +494,7 @@ static void RADEONEnterServer(ScreenPtr pScreen)
     RADEON_MARK_SYNC(info, pScrn);
 
     pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-    if (pSAREAPriv->ctxOwner != DRIGetContext(pScrn->pScreen)) {
+    if (pSAREAPriv->ctx_owner != DRIGetContext(pScrn->pScreen)) {
 	info->XInited3D = FALSE;
 	info->needCacheFlush = (info->ChipFamily >= CHIP_FAMILY_R300);
     }
@@ -694,25 +826,37 @@ static void RADEONDRIInitGARTValues(RADEONInfoPtr info)
 
     info->gartOffset = 0;
 
-				/* Initialize the CP ring buffer data */
-    info->ringStart       = info->gartOffset;
-    info->ringMapSize     = info->ringSize*1024*1024 + radeon_drm_page_size;
-    info->ringSizeLog2QW  = RADEONMinBits(info->ringSize*1024*1024/8)-1;
+    if (!info->drm_mm) {
+      /* Initialize the CP ring buffer data */
+      info->ringStart       = info->gartOffset;
+      info->ringMapSize     = info->ringSize*1024*1024 + radeon_drm_page_size;
+      info->ringSizeLog2QW  = RADEONMinBits(info->ringSize*1024*1024/8)-1;
 
-    info->ringReadOffset  = info->ringStart + info->ringMapSize;
-    info->ringReadMapSize = radeon_drm_page_size;
+      info->ringReadOffset  = info->ringStart + info->ringMapSize;
+      info->ringReadMapSize = radeon_drm_page_size;
 
 				/* Reserve space for vertex/indirect buffers */
-    info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
-    info->bufMapSize      = info->bufSize*1024*1024;
-
-				/* Reserve the rest for GART textures */
-    info->gartTexStart     = info->bufStart + info->bufMapSize;
-    s = (info->gartSize*1024*1024 - info->gartTexStart);
-    l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
-    if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
-    info->gartTexMapSize   = (s >> l) << l;
-    info->log2GARTTexGran  = l;
+      info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
+      info->bufMapSize      = info->bufSize*1024*1024;
+
+      /* Reserve the rest for GART textures */
+      info->gartTexStart     = info->bufStart + info->bufMapSize;
+      s = (info->gartSize*1024*1024 - info->gartTexStart);
+      l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS);
+      if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY;
+      info->gartTexMapSize   = (s >> l) << l;
+      info->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->gartTexMapSize   = (s >> l) << l;
+      info->log2GARTTexGran  = l;
+    }
+    
+
 }
 
 /* Set AGP transfer mode according to requests and constraints */
@@ -884,6 +1028,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen)
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[agp] ring handle = 0x%08x\n", info->ringHandle);
 
+#if 0
     if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
 	       &info->ring) < 0) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n");
@@ -892,7 +1037,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen)
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[agp] Ring mapped at 0x%08lx\n",
 	       (unsigned long)info->ring);
-
+#endif
     if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
 		  DRM_AGP, DRM_READ_ONLY, &info->ringReadPtrHandle) < 0) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -903,6 +1048,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen)
  	       "[agp] ring read ptr handle = 0x%08x\n",
 	       info->ringReadPtrHandle);
 
+#if 0
     if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
 	       &info->ringReadPtr) < 0) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -912,7 +1058,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen)
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[agp] Ring read ptr mapped at 0x%08lx\n",
 	       (unsigned long)info->ringReadPtr);
-
+#endif
     if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
 		  DRM_AGP, 0, &info->bufHandle) < 0) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -986,7 +1132,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen)
     }
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[pci] ring handle = 0x%08x\n", info->ringHandle);
-
+#if 0
     if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
 	       &info->ring) < 0) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n");
@@ -998,6 +1144,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen)
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[pci] Ring contents 0x%08lx\n",
 	       *(unsigned long *)(pointer)info->ring);
+#endif
 
     if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
 		  DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
@@ -1008,7 +1155,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen)
     xf86DrvMsg(pScreen->myNum, X_INFO,
  	       "[pci] ring read ptr handle = 0x%08x\n",
 	       info->ringReadPtrHandle);
-
+#if 0
     if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
 	       &info->ringReadPtr) < 0) {
 	xf86DrvMsg(pScreen->myNum, X_ERROR,
@@ -1021,6 +1168,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen)
     xf86DrvMsg(pScreen->myNum, X_INFO,
 	       "[pci] Ring read ptr contents 0x%08lx\n",
 	       *(unsigned long *)(pointer)info->ringReadPtr);
+#endif
 
     if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
 		  DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
@@ -1073,6 +1221,9 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen)
  */
 static Bool RADEONDRIMapInit(RADEONInfoPtr info, ScreenPtr pScreen)
 {
+
+    if (info->drm_mm)
+    return TRUE;
 				/* Map registers */
     info->registerSize = info->MMIOSize;
     if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize,
@@ -1094,12 +1245,12 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen)
 
     memset(&drmInfo, 0, sizeof(drmRadeonInit));
     if ( info->ChipFamily >= CHIP_FAMILY_R300 )
-       drmInfo.func             = DRM_RADEON_INIT_R300_CP;
+       drmInfo.func             = RADEON_INIT_R300_CP;
     else
     if ( info->ChipFamily >= CHIP_FAMILY_R200 )
-       drmInfo.func		= DRM_RADEON_INIT_R200_CP;
+       drmInfo.func		= RADEON_INIT_R200_CP;
     else
-       drmInfo.func		= DRM_RADEON_INIT_CP;
+       drmInfo.func		= RADEON_INIT_CP;
 
     drmInfo.sarea_priv_offset   = sizeof(XF86DRISAREARec);
     drmInfo.is_pci              = (info->cardType!=CARD_AGP);
@@ -1111,19 +1262,22 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen)
     drmInfo.fb_bpp              = info->CurrentLayout.pixel_code;
     drmInfo.depth_bpp           = (info->depthBits - 8) * 2;
 
-    drmInfo.front_offset        = info->frontOffset;
-    drmInfo.front_pitch         = info->frontPitch * cpp;
-    drmInfo.back_offset         = info->backOffset;
-    drmInfo.back_pitch          = info->backPitch * cpp;
-    drmInfo.depth_offset        = info->depthOffset;
-    drmInfo.depth_pitch         = info->depthPitch * drmInfo.depth_bpp / 8;
-
-    drmInfo.fb_offset           = info->fbHandle;
-    drmInfo.mmio_offset         = info->registerHandle;
-    drmInfo.ring_offset         = info->ringHandle;
-    drmInfo.ring_rptr_offset    = info->ringReadPtrHandle;
-    drmInfo.buffers_offset      = info->bufHandle;
-    drmInfo.gart_textures_offset= info->gartTexHandle;
+    if (!info->drm_mm) {
+        drmInfo.front_offset        = info->frontOffset;
+	drmInfo.front_pitch         = info->frontPitch * cpp;
+	drmInfo.back_offset         = info->backOffset;
+	drmInfo.back_pitch          = info->backPitch * cpp;
+	drmInfo.depth_offset        = info->depthOffset;
+	drmInfo.depth_pitch         = info->depthPitch * drmInfo.depth_bpp / 8;
+
+	drmInfo.fb_offset           = info->fbHandle;
+	drmInfo.mmio_offset         = info->registerHandle;
+	drmInfo.ring_offset         = info->ringHandle;
+	drmInfo.ring_rptr_offset    = info->ringReadPtrHandle;
+	drmInfo.buffers_offset      = info->bufHandle;
+	drmInfo.gart_textures_offset= info->gartTexHandle;
+    } else {
+    }
 
     if (drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT,
 			&drmInfo, sizeof(drmRadeonInit)) < 0)
@@ -1133,7 +1287,8 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen)
      * registers back to their default values, so we need to restore
      * those engine register here.
      */
-    RADEONEngineRestore(pScrn);
+    if (!info->drm_mm)
+      RADEONEngineRestore(pScrn);
 
     return TRUE;
 }
@@ -1329,12 +1484,11 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn)
 
     /* Get DRM version & close DRM */
     info->pKernelDRMVersion = drmGetVersion(fd);
-    drmClose(fd);
     if (info->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 */
@@ -1368,10 +1522,29 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn)
 		   req_patch);
 	drmFreeVersion(info->pKernelDRMVersion);
 	info->pKernelDRMVersion = NULL;
-	return FALSE;
+	goto fail;
+    }
+
+    if (info->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_start = mminfo.vram_start;
+		    info->mm.vram_size = mminfo.vram_size;
+		    info->mm.gart_start = mminfo.vram_start;
+		    info->mm.gart_size = mminfo.gart_size;
+		    ErrorF("initing %llx %llx %llx %llx\n", mminfo.gart_start,
+			   mminfo.gart_size, mminfo.vram_start, mminfo.vram_size);
+	    }
     }
 
+    drmClose(fd);
     return TRUE;
+fail:
+    drmClose(fd);
+    return FALSE;
 }
 
 Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on)
@@ -1380,6 +1553,9 @@ Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on)
     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;
 
@@ -1399,6 +1575,44 @@ Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on)
     return TRUE;
 }
 
+Bool RADEONDRIDoMappings(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr  info    = RADEONPTR(pScrn);
+    RADEONSAREAPrivPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
+				/* DRIScreenInit doesn't add all the
+				 * common mappings.  Add additional
+				 * mappings here.
+				 */
+    if (!RADEONDRIMapInit(info, pScreen)) {
+	RADEONDRICloseScreen(pScreen);
+	return FALSE;
+    }
+    
+    radeon_update_sarea(pScrn, pSAREAPriv);
+    
+				/* DRIScreenInit adds the frame buffer
+				   map, but we need it as well */
+    {
+	void *scratch_ptr;
+        int scratch_int;
+
+	DRIGetDeviceInfo(pScreen, &info->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
@@ -1462,10 +1676,23 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen)
     pDRIInfo->ddxDriverMajorVersion      = info->allowColorTiling ? 5 : 4;
     pDRIInfo->ddxDriverMinorVersion      = 3;
     pDRIInfo->ddxDriverPatchVersion      = 0;
-    pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->frontOffset;
-    pDRIInfo->frameBufferSize            = info->FbMapSize - info->FbSecureSize;
-    pDRIInfo->frameBufferStride          = (pScrn->displayWidth *
-					    info->CurrentLayout.pixel_bytes);
+
+#if DRI_DRIVER_FRAMEBUFFER_MAP
+    /* only map the fb ourselves if we have the memory manager in place */
+    if (info->drm_mm) {
+	pDRIInfo->frameBufferPhysicalAddress = 0;
+	pDRIInfo->frameBufferSize = 0;
+	pDRIInfo->frameBufferStride = 0;
+	pDRIInfo->dontMapFrameBuffer = TRUE;
+    } else
+#endif
+     {
+	pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->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
@@ -1518,9 +1745,7 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen)
     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
 
@@ -1552,57 +1777,61 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen)
 	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->fbHandle,
-                         &scratch_int, &scratch_int,
-                         &scratch_int, &scratch_int,
-                         &scratch_ptr);
+	/* 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->drmFD, fb_handle);
+
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Removed DRI frontbuffer mapping in compatibility mode.\n");
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "DRIGetDeviceInfo will report incorrect frontbuffer "
+		   "handle.\n");
+    }
+   
+    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;
+	}
     }
 
-				/* 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;
 }
 
+
 static Bool RADEONDRIDoCloseScreen(int scrnIndex, ScreenPtr pScreen)
 {
     ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
@@ -1644,14 +1873,18 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen)
 	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);
@@ -1663,6 +1896,10 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen)
     pSAREAPriv = (RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
     memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
 
+    if (info->drm_mm) {
+	/* init the handles into the sarea */
+	
+    }
     pRADEONDRI                    = (RADEONDRIPtr)info->pDRIInfo->devPrivate;
 
     pRADEONDRI->deviceID          = info->Chipset;
@@ -1806,7 +2043,7 @@ void RADEONDRICloseScreen(ScreenPtr pScreen)
 
     /* De-allocate all kernel resources */
     memset(&drmInfo, 0, sizeof(drmRadeonInit));
-    drmInfo.func = DRM_RADEON_CLEANUP_CP;
+    drmInfo.func = RADEON_CLEANUP_CP;
     drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT,
 		    &drmInfo, sizeof(drmRadeonInit));
 
@@ -1819,6 +2056,7 @@ void RADEONDRICloseScreen(ScreenPtr pScreen)
 	drmUnmap(info->buf, info->bufMapSize);
 	info->buf = NULL;
     }
+#if 0
     if (info->ringReadPtr) {
 	drmUnmap(info->ringReadPtr, info->ringReadMapSize);
 	info->ringReadPtr = NULL;
@@ -1827,6 +2065,7 @@ void RADEONDRICloseScreen(ScreenPtr pScreen)
 	drmUnmap(info->ring, info->ringMapSize);
 	info->ring = NULL;
     }
+#endif
     if (info->agpMemHandle != DRM_AGP_NO_HANDLE) {
 	drmAgpUnbind(info->drmFD, info->agpMemHandle);
 	drmAgpFree(info->drmFD, info->agpMemHandle);
@@ -1903,7 +2142,7 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, RegionPtr pReg)
     /* Don't want to do this when no 3d is active and pages are
      * right-way-round
      */
-    if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0)
+    if (!pSAREAPriv->pfState && pSAREAPriv->pfCurrentPage == 0)
 	return;
 
     REGION_NULL(pScreen, &region);
@@ -1992,7 +2231,7 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen)
 		       .y2 = pScrn->virtualY - 1 };
 	RegionPtr pReg = REGION_CREATE(pScreen, &box, 1);
 
-	pSAREAPriv->pfAllowPageFlip = 1;
+	pSAREAPriv->pfState = 1;
 	RADEONDRIRefreshArea(pScrn, pReg);
 	REGION_DESTROY(pScreen, pReg);
     }
@@ -2007,7 +2246,7 @@ static void RADEONDisablePageFlip(ScreenPtr pScreen)
      */
     RADEONSAREAPrivPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
 
-    pSAREAPriv->pfAllowPageFlip = 0;
+    pSAREAPriv->pfState = 0;
 }
 
 static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen)
@@ -2232,3 +2471,16 @@ int RADEONDRISetParam(ScrnInfoPtr pScrn, unsigned int param, int64_t value)
 			  &radeonsetparam, sizeof(drmRadeonSetParam));
     return ret;
 }
+
+static Bool radeon_dri_gart_init(ScreenPtr pScreen)
+{
+    ScrnInfoPtr    pScrn   = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr  info    = RADEONPTR(pScrn);
+
+    RADEONDRIInitGARTValues(info);
+
+    /* so we want to allocate the buffers/gart texmap */
+    /* ignore ring stuff */
+    return radeon_setup_gart_mem(pScreen);
+
+}
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 45d2c2f..8fa32ab 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1621,6 +1621,7 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn)
     }
 
     pScrn->videoRam  &= ~1023;
+
     info->FbMapSize  = pScrn->videoRam * 1024;
 
     /* if the card is PCI Express reserve the last 32k for the gart table */
@@ -1748,56 +1749,62 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn)
     from               = X_PROBED;
     info->LinearAddr   = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & ~0x1ffffffUL;
     pScrn->memPhysBase = info->LinearAddr;
-    if (dev->MemBase) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Linear address override, using 0x%016lx instead of 0x%016lx\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%016lx\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",
-		   dev->BiosBase,
-		   info->BIOSAddr);
-	info->BIOSAddr = dev->BiosBase;
-	from           = X_CONFIG;
-    }
-    if (info->BIOSAddr) {
+    if (!info->drm_mode_setting) {
+	from               = X_PROBED;
+	info->LinearAddr   = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & ~0x1ffffffUL;
+	pScrn->memPhysBase = info->LinearAddr;
+	if (dev->MemBase) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Linear address override, using 0x%016lx instead of 0x%016lx\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,
-		   "BIOS at 0x%08lx\n", info->BIOSAddr);
-    }
+		   "Linear framebuffer at 0x%016lx\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",
+		       dev->BiosBase,
+		       info->BIOSAddr);
+	    info->BIOSAddr = dev->BiosBase;
+	    from           = X_CONFIG;
+	}
+	if (info->BIOSAddr) {
+	    xf86DrvMsg(pScrn->scrnIndex, from,
+		       "BIOS at 0x%08lx\n", 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)
+	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)
+	
+	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)
+	
+	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 */
@@ -1985,6 +1992,9 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn)
     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)
@@ -1995,6 +2005,7 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn)
 		info->useEXA = TRUE;
 	    } else if (xf86NameCmp(optstr, "XAA") == 0) {
 		from = X_CONFIG;
+		info->useEXA = FALSE;
 	    }
 	}
 #else /* USE_XAA */
@@ -2664,6 +2675,37 @@ static const xf86CrtcConfigFuncsRec RADEONCRTCResizeFuncs = {
     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;
@@ -2684,6 +2726,8 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
     info               = RADEONPTR(pScrn);
     info->MMIO         = NULL;
 
+    info->drm_mode_setting = radeon_kernel_mode_enabled(pScrn);
+
     info->IsSecondary  = FALSE;
     info->IsPrimary = FALSE;
 
@@ -2718,59 +2762,63 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
     }
 
     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) & ~0xffUL;
-    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%08lx\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%016lx: 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) & ~0xffUL;
+	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%08lx\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%016lx: 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;
@@ -2780,10 +2828,12 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
     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;
@@ -2797,136 +2847,192 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
     memcpy(info->Options, RADEONOptions, sizeof(RADEONOptions));
     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
 
-    /* By default, don't do VGA IOs on ppc/sparc */
+    if (!info->drm_mode_setting) {
+	/* By default, don't do VGA IOs on ppc/sparc */
 #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;
-
-    RADEONPostInt10Check(pScrn, int10_save);
-
-    if (!RADEONPreInitBIOS(pScrn, pInt10))
-	goto fail;
+        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;
+	}
+	
+	
+	if (!RADEONPreInitInt10(pScrn, &pInt10))
+	    goto fail;
+	
+	RADEONPostInt10Check(pScrn, int10_save);
 
+	if (!RADEONPreInitBIOS(pScrn, pInt10))
+	    goto fail;
 #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 (!RADEONPreInitVRAM(pScrn))
-	goto fail;
-
-    RADEONPreInitColorTiling(pScrn);
-
-    /* we really need an FB manager... */
-    if (pScrn->display->virtualX) {
-	crtc_max_X = pScrn->display->virtualX;
-	crtc_max_Y = pScrn->display->virtualY;
-	if (info->allowColorTiling) {
-	    if (crtc_max_X > info->MaxSurfaceWidth ||
-		crtc_max_Y > info->MaxLines) {
-		info->allowColorTiling = FALSE;
-		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-			   "Requested desktop size exceeds surface limts for tiling, ColorTiling disabled\n");
+	
+	if (!RADEONPreInitVRAM(pScrn))
+	    goto fail;
+	
+	RADEONPreInitColorTiling(pScrn);
+	
+	/* we really need an FB manager... */
+	if (pScrn->display->virtualX) {
+	    crtc_max_X = pScrn->display->virtualX;
+	    crtc_max_Y = pScrn->display->virtualY;
+	    if (info->allowColorTiling) {
+		if (crtc_max_X > info->MaxSurfaceWidth ||
+		    crtc_max_Y > info->MaxLines) {
+		    info->allowColorTiling = FALSE;
+		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			       "Requested desktop size exceeds surface limts for tiling, ColorTiling disabled\n");
+		}
 	    }
-	}
-	if (crtc_max_X > 8192)
-	    crtc_max_X = 8192;
-	if (crtc_max_Y > 8192)
-	    crtc_max_Y = 8192;
-    } else {
-	/*
-	 * note that these aren't really the CRTC limits, they're just
-	 * heuristics until we have a better memory manager.
-	 */
-	if (pScrn->videoRam <= 16384) {
-	    crtc_max_X = 1600;
-	    crtc_max_Y = 1200;
-	} else if (IS_R300_VARIANT) {
-	    crtc_max_X = 2560;
-	    crtc_max_Y = 1200;
-	} else if (IS_AVIVO_VARIANT) {
-	    crtc_max_X = 2560;
-	    crtc_max_Y = 1600;
+	    if (crtc_max_X > 8192)
+		crtc_max_X = 8192;
+	    if (crtc_max_Y > 8192)
+		crtc_max_Y = 8192;
 	} else {
-	    crtc_max_X = 2048;
-	    crtc_max_Y = 1200;
+	    /*
+	     * note that these aren't really the CRTC limits, they're just
+	     * heuristics until we have a better memory manager.
+	     */
+	    if (pScrn->videoRam <= 16384) {
+		crtc_max_X = 1600;
+		crtc_max_Y = 1200;
+	    } else if (IS_R300_VARIANT) {
+		crtc_max_X = 2560;
+		crtc_max_Y = 1200;
+	    } else if (IS_AVIVO_VARIANT) {
+		crtc_max_X = 2560;
+		crtc_max_Y = 1600;
+	    } else {
+		crtc_max_X = 2048;
+		crtc_max_Y = 1200;
 	}
-    }
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Max desktop size set to %dx%d\n",
-	       crtc_max_X, crtc_max_Y);
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "For a larger or smaller max desktop size, add a Virtual line to your xorg.conf\n");
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "If you are having trouble with 3D, "
-	       "reduce the desktop size by adjusting the Virtual line to your xorg.conf\n");
-
+	}
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Max desktop size set to %dx%d\n",
+		   crtc_max_X, crtc_max_Y);
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "For a larger or smaller max desktop size, add a Virtual line to your xorg.conf\n");
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "If you are having trouble with 3D, "
+		   "reduce the desktop size by adjusting the Virtual line to your xorg.conf\n");
+	
     /*xf86CrtcSetSizeRange (pScrn, 320, 200, info->MaxSurfaceWidth, info->MaxLines);*/
-    xf86CrtcSetSizeRange (pScrn, 320, 200, crtc_max_X, crtc_max_Y);
+	xf86CrtcSetSizeRange (pScrn, 320, 200, crtc_max_X, crtc_max_Y);
+	
+	RADEONPreInitDDC(pScrn);
 
-    RADEONPreInitDDC(pScrn);
+	if (!RADEONPreInitControllers(pScrn))
+	    goto fail;
 
-    if (!RADEONPreInitControllers(pScrn))
-       goto fail;
 
+	ErrorF("before xf86InitialConfiguration\n");
+	
+	if (!xf86InitialConfiguration (pScrn, FALSE))
+	{
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
+		goto fail;
+	}
+	
+	ErrorF("after xf86InitialConfiguration\n");
+
+    } else {
+#ifdef XF86DRM_MODE
+	char *bus_id;
+	bus_id = DRICreatePCIBusID(info->PciInfo);
+	if (drmmode_pre_init(pScrn, &info->drmmode, bus_id, "radeon", pScrn->bitsPerPixel / 8) == FALSE) {
+	    xfree(bus_id);
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
+	    goto fail;
+	}
 
-    ErrorF("before xf86InitialConfiguration\n");
+	info->drmmode.create_new_fb = radeon_create_new_fb;
+	info->drmFD = info->drmmode.fd;
+	xfree(bus_id);
+	 
+        {
+	    struct drm_radeon_gem_info mminfo;
+
+	    if (!drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
+	    {
+		info->mm.vram_start = mminfo.vram_start;
+		info->mm.vram_size = mminfo.vram_visible;
+		info->mm.gart_start = mminfo.gart_start;
+		info->mm.gart_size = mminfo.gart_size;
+		ErrorF("initing %llx %llx %llx %llx %llx\n", mminfo.gart_start,
+		       mminfo.gart_size, mminfo.vram_start, mminfo.vram_size, mminfo.vram_visible);
+	    }
+	    {
+		drmRadeonGetParam gp;
+		int value;
 
-    if (!xf86InitialConfiguration (pScrn, FALSE))
-   {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
-      goto fail;
-   }
+		memset(&gp, 0, sizeof(gp));
+		gp.param = RADEON_PARAM_FB_LOCATION;
+		gp.value = &value;
 
-    ErrorF("after xf86InitialConfiguration\n");
+		if (drmCommandWriteRead(info->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;
+	    }
+        }
+	info->useEXA = TRUE;
+	info->drm_mm = TRUE;
+	info->directRenderingEnabled = TRUE;
+	info->new_cs = 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;
@@ -2941,10 +3047,12 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
 	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) {
@@ -3185,7 +3293,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
     int            subPixelOrder = SubPixelUnknown;
     char*          s;
 #endif
-
+    void *front_ptr;
 
     info->accelOn      = FALSE;
 #ifdef USE_XAA
@@ -3205,52 +3313,55 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
 		   "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->fbX = 0;
-    info->fbY = 0;
+	info->fbX = 0;
+	info->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;
+	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,
@@ -3284,19 +3395,21 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
     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 */
-    {
-	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 */
+	{
+	    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);
+	    }
 	}
     }
 
@@ -3341,6 +3454,9 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
 		from = X_CONFIG;
 	    }
 
+	    if (info->drm_mm)
+	      info->accelDFS = FALSE;
+
 	    /* Reserve approx. half of offscreen memory for local textures by
 	     * default, can be overridden with Option "FBTexPercent".
 	     * Round down to a whole number of texture regions.
@@ -3407,7 +3523,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
 			    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,
@@ -3421,15 +3537,39 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
 	}
     }
 
-    /* Tell DRI about new memory map */
-    if (info->directRenderingEnabled && info->newMemoryMap) {
-        if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) {
+    front_ptr = info->FB;
+    if (info->drm_mm) {
+	if (info->directRenderingEnabled && info->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->drmFD);
+	drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr);
+	//radeon_bufmgr_gem_enable_reuse(info->bufmgr);
+	radeon_setup_kernel_mem(pScreen);
+	front_ptr = info->mm.front_buffer->map;
+	pScrn->fbOffset = info->mm.front_buffer->offset;
+	info->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64)
+				   << 22) | ((info->fbLocation + pScrn->fbOffset) >> 10));
+    } else {
+	
+	/* Tell DRI about new memory map */
+	if (info->directRenderingEnabled && info->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;		
+	    }
 	}
     }
+
+    RADEONDRIDoMappings(pScreen);
+
 #endif
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "Initializing fb layer\n");
@@ -3453,7 +3593,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
 
     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))
@@ -3508,7 +3648,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
 
     /* DRI finalisation */
 #ifdef XF86DRI
-    if (info->directRenderingEnabled && info->cardType==CARD_PCIE &&
+    if (!info->drm_mm && info->directRenderingEnabled && info->cardType==CARD_PCIE &&
         info->pKernelDRMVersion->version_minor >= 19)
     {
       if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_PCIGART_LOCATION, info->pciGartOffset) < 0)
@@ -3527,15 +3667,21 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
 	info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen);
     }
     if (info->directRenderingEnabled) {
+
+	if (info->drm_mm)
+	    radeon_update_dri_buffers(pScrn);
+    
 	/* 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);
 
-	if ((info->DispPriority == 1) && (info->cardType==CARD_AGP)) {
-	    /* we need to re-calculate bandwidth because of AGPMode difference. */ 
-	    RADEONInitDispBandwidth(pScrn);
+	    if ((info->DispPriority == 1) && (info->cardType==CARD_AGP)) {
+		/* we need to re-calculate bandwidth because of AGPMode difference. */ 
+		RADEONInitDispBandwidth(pScrn);
+	    }
 	}
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
 
@@ -5355,6 +5501,11 @@ void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags)
     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;
+    }
+
 #ifdef XF86DRI
     if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0);
 #endif
@@ -5390,67 +5541,76 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
     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);
+
     }
 
-    if (IS_R300_VARIANT || IS_RV100_VARIANT)
-	RADEONForceSomeClocks(pScrn);
+    if (info->drm_mm)
+	radeon_bind_all_memory(pScrn);
 
-    for (i = 0; i < config->num_crtc; i++)
-	radeon_crtc_modeset_ioctl(config->crtc[i], TRUE);
+    radeon_update_dri_buffers(pScrn);
 
     pScrn->vtSema = TRUE;
 
+    if (!info->drm_mode_setting)
+	for (i = 0; i < config->num_crtc; i++)
+	    radeon_crtc_modeset_ioctl(config->crtc[i], TRUE);
+
     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->pKernelDRMVersion->version_minor >= 19 &&
-	    info->FbSecureSize) {
-	    /* we need to backup the PCIE GART TABLE from fb memory */
-	    memcpy(info->FB + info->pciGartOffset, info->pciGartBackup, info->pciGartSize);
-    	}
-
-	/* get the DRI back into shape after resume */
-	RADEONDRISetVBlankInterrupt (pScrn, TRUE);
-	RADEONDRIResume(pScrn->pScreen);
-	RADEONAdjustMemMapRegisters(pScrn, info->ModeReg);
-
+	if (info->directRenderingEnabled) {
+	    if (info->cardType == CARD_PCIE &&
+		info->pKernelDRMVersion->version_minor >= 19 &&
+		info->FbSecureSize) {
+		/* we need to backup the PCIE GART TABLE from fb memory */
+		memcpy(info->FB + info->pciGartOffset, info->pciGartBackup, info->pciGartSize);
+	    }
+	    
+	    /* 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
@@ -5462,7 +5622,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
 	RADEONEngineRestore(pScrn);
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled) {
+    if (info->directRenderingEnabled && !info->drm_mode_setting) {
 	RADEONCP_START(pScrn, info);
 	DRIUnlock(pScrn->pScreen);
     }
@@ -5485,24 +5645,26 @@ void RADEONLeaveVT(int scrnIndex, int flags)
 		   "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->pKernelDRMVersion->version_minor >= 19 &&
-	    info->FbSecureSize) {
-            /* we need to backup the PCIE GART TABLE from fb memory */
-            memcpy(info->pciGartBackup, (info->FB + info->pciGartOffset), info->pciGartSize);
-        }
+	
+	if (!info->drm_mode_setting) {
+	    RADEONDRISetVBlankInterrupt (pScrn, FALSE);
+	    DRILock(pScrn->pScreen, 0);
+	    RADEONCP_STOP(pScrn, info);
+
+	    if (info->cardType == CARD_PCIE &&
+		info->pKernelDRMVersion->version_minor >= 19 &&
+		info->FbSecureSize) {
+		/* we need to backup the PCIE GART TABLE from fb memory */
+		memcpy(info->pciGartBackup, (info->FB + info->pciGartOffset), info->pciGartSize);
+	    }
+	}
 
 	/* Make sure 3D clients will re-upload textures to video RAM */
 	if (info->textureSize) {
 	    RADEONSAREAPrivPtr pSAREAPriv =
 		(RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScrn->pScreen);
-	    drmTextureRegionPtr list = pSAREAPriv->texList[0];
-	    int age = ++pSAREAPriv->texAge[0];
+	    drmTextureRegionPtr list = pSAREAPriv->tex_list[0];
+	    int age = ++pSAREAPriv->tex_age[0];
 
 	    i = 0;
 
@@ -5531,10 +5693,15 @@ void RADEONLeaveVT(int scrnIndex, int flags)
 
     xf86_hide_cursors (pScrn);
 
-    RADEONRestore(pScrn);
+    if (info->drm_mm)
+	radeon_unbind_all_memory(pScrn);
 
-    for (i = 0; i < config->num_crtc; i++)
-	radeon_crtc_modeset_ioctl(config->crtc[i], FALSE);
+    if (!info->drm_mode_setting) {
+	RADEONRestore(pScrn);
+
+	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");
@@ -5579,7 +5746,8 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen)
 #endif /* USE_XAA */
 
     if (pScrn->vtSema) {
-	RADEONRestore(pScrn);
+        if (!info->drm_mode_setting)
+	    RADEONRestore(pScrn);
     }
 
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
@@ -5614,6 +5782,12 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen)
     info->DGAModes = NULL;
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "Unmapping memory\n");
+
+    if (info->drm_mm) {
+	radeon_unbind_all_memory(pScrn);
+	radeon_free_all_memory(pScrn);
+    }
+
     RADEONUnmapMem(pScrn);
 
     pScrn->vtSema = FALSE;
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 02fd4fc..555ae16 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -47,6 +47,13 @@
 
 #include "xf86.h"
 
+#define RADEON_PIXMAP_IS_FRONTBUFFER 1
+
+/* quick hacks lolz */
+struct radeon_exa_pixmap_priv {
+    dri_bo *bo;
+    int flags;
+};
 
 /***********************************************************************/
 #define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn =  xf86Screens[pScr->myNum]; \
@@ -184,14 +191,26 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
 	RINFO_FROM_SCREEN(pPix->drawable.pScreen);
 	uint32_t pitch, offset;
 	int bpp;
+	struct radeon_exa_pixmap_priv *driver_priv;
 
 	bpp = pPix->drawable.bitsPerPixel;
 	if (bpp == 24)
 		bpp = 8;
 
-	offset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset;
+	driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+	/* 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);
 }
 
@@ -199,6 +218,8 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
 
 static unsigned long swapper_surfaces[3];
 
+#endif
+
 static Bool RADEONPrepareAccess(PixmapPtr pPix, int index)
 {
     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
@@ -206,7 +227,30 @@ static Bool RADEONPrepareAccess(PixmapPtr pPix, int index)
     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;
+
+	    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;
@@ -262,6 +306,7 @@ static Bool RADEONPrepareAccess(PixmapPtr pPix, int index)
     OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset);
     OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1);
     swapper_surfaces[index] = offset;
+#endif
     return TRUE;
 }
 
@@ -271,7 +316,16 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index)
     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;
@@ -294,13 +348,100 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index)
     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);
+    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);
+}
+
+static Bool RADEONEXAModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
+					int depth, int bitsPerPixel, int devKind,
+					pointer pPixData)
+{
+    ScreenPtr   pScreen = pPixmap->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    struct radeon_exa_pixmap_priv *driver_priv;
+
+    driver_priv = exaGetPixmapDriverPrivate(pPixmap);
+    if (!driver_priv)
+	return FALSE;
+
+
+    if (info->drm_mode_setting && drmmode_is_rotate_pixmap(pScrn, pPixData, &driver_priv->bo)){
+	dri_bo_unmap(driver_priv->bo);
+	dri_bo_reference(driver_priv->bo);
+	miModifyPixmapHeader(pPixmap, width, height, depth,
+                             bitsPerPixel, devKind, NULL);
+
+    	return TRUE;
+    }
+
+    if (pPixData == info->mm.front_buffer->map) {
+	driver_priv->flags |= RADEON_PIXMAP_IS_FRONTBUFFER;
+
+	if (info->new_cs)
+	  driver_priv->bo = radeon_bo_gem_create_from_name(info->bufmgr, "front",
+							   radeon_name_buffer(pScrn, info->mm.front_buffer));
+	else
+	  driver_priv->bo = radeon_bufmgr_exa_create_bo(info->bufmgr, info->mm.front_buffer);
+
+	miModifyPixmapHeader(pPixmap, width, height, depth,
+                             bitsPerPixel, devKind, NULL);
+	return TRUE;
+    }
+    return FALSE;
+}
+
+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 RADEON_SWITCH_TO_2D()						\
 do {									\
-	uint32_t wait_until = 0;			\
+        uint32_t wait_until = 0;				       	\
 	BEGIN_ACCEL(1);							\
 	switch (info->engineMode) {					\
 	case EXA_ENGINEMODE_UNKNOWN:					\
@@ -317,7 +458,7 @@ do {									\
 
 #define RADEON_SWITCH_TO_3D()						\
 do {									\
-	uint32_t wait_until = 0;			\
+         uint32_t wait_until = 0;					\
 	BEGIN_ACCEL(1);							\
 	switch (info->engineMode) {					\
 	case EXA_ENGINEMODE_UNKNOWN:					\
@@ -341,6 +482,7 @@ do {									\
 #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
@@ -353,6 +495,7 @@ do {									\
 #undef BEGIN_ACCEL
 #undef OUT_ACCEL_REG
 #undef FINISH_ACCEL
+#undef OUT_RELOC
 
 #ifdef XF86DRI
 
@@ -363,6 +506,7 @@ do {									\
 #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))
 
@@ -373,6 +517,8 @@ do {									\
 
 #endif /* XF86DRI */
 
+
+
 /*
  * Once screen->off_screen_base is set, this function
  * allocates the remaining memory appropriately
@@ -394,125 +540,124 @@ Bool RADEONSetupMemEXA (ScreenPtr pScreen)
     if (info->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->exa->memoryBase = info->FB;
-    info->exa->memorySize = info->FbMapSize - info->FbSecureSize;
-    info->exa->offScreenBase = screen_size;
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n",
-	       info->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->exa->offScreenBase, align);
-	    info->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->depthBits - 8) / 4, l, next, depth_size;
-
-	info->frontOffset = 0;
-	info->frontPitch = pScrn->displayWidth;
-
-        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "Will use %d kb for front buffer at offset 0x%08x\n",
-	       screen_size / 1024, info->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->pciGartSize / 1024,
-		     (int)info->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->backPitch = pScrn->displayWidth;
-	next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN);
-	if (!info->noBackBuffer &&
-	    next + screen_size <= info->exa->memorySize)
-	{
-	    info->backOffset = next;
-	    info->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->backOffset);
-	}
-
-	/* Reserve the static depth buffer, and adjust pitch and height to
-	 * handle tiling.
+    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->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
-	depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->depthPitch * depthCpp;
-	next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN);
-	if (next + depth_size <= info->exa->memorySize)
-	{
-	    info->depthOffset = next;
-	    info->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->depthOffset);
+	if (info->allowColorTiling)
+	    screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride;
+	else
+	    screen_size = pScrn->virtualY * byteStride;
+
+	info->exa->memoryBase = info->FB;
+	info->exa->memorySize = info->FbMapSize - info->FbSecureSize;
+	info->exa->offScreenBase = screen_size;
+
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n",
+		   info->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->exa->offScreenBase, align);
+	        info->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);
+	    }
 	}
 	
-	info->textureSize *= (info->exa->memorySize -
-			      info->exa->offScreenBase) / 100;
-
-	l = RADEONLog2(info->textureSize / RADEON_NR_TEX_REGIONS);
-	if (l < RADEON_LOG_TEX_GRANULARITY)
-	    l = RADEON_LOG_TEX_GRANULARITY;
-	info->textureSize = (info->textureSize >> l) << l;
-	if (info->textureSize >= 512 * 1024) {
-	    info->textureOffset = info->exa->offScreenBase;
-	    info->exa->offScreenBase += info->textureSize;
+#if defined(XF86DRI)
+	if (info->directRenderingEnabled) {
+	    int depthCpp = (info->depthBits - 8) / 4, l, next, depth_size;
+	    
+	    info->frontOffset = 0;
+	    info->frontPitch = pScrn->displayWidth;
+	    
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Will use %d kb for textures at offset 0x%08x\n",
-		       info->textureSize / 1024, info->textureOffset);
-	} else {
-	    /* Minimum texture size is for 2 256x256x32bpp textures */
-	    info->textureSize = 0;
-	}
-    } else
+		       "Will use %d kb for front buffer at offset 0x%08x\n",
+		       screen_size / 1024, info->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->pciGartSize / 1024,
+			   (int)info->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->backPitch = pScrn->displayWidth;
+	    next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN);
+	    if (!info->noBackBuffer &&
+		next + screen_size <= info->exa->memorySize)
+		{
+		    info->backOffset = next;
+		    info->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->backOffset);
+		}
+	    
+	    /* Reserve the static depth buffer, and adjust pitch and height to
+	     * handle tiling.
+	     */
+	    info->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
+	    depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->depthPitch * depthCpp;
+	    next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN);
+	    if (next + depth_size <= info->exa->memorySize)
+		{
+		    info->depthOffset = next;
+		    info->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->depthOffset);
+		}
+	    
+	    info->textureSize *= (info->exa->memorySize -
+				  info->exa->offScreenBase) / 100;
+	    
+	    l = RADEONLog2(info->textureSize / RADEON_NR_TEX_REGIONS);
+	    if (l < RADEON_LOG_TEX_GRANULARITY)
+		l = RADEON_LOG_TEX_GRANULARITY;
+	    info->textureSize = (info->textureSize >> l) << l;
+	    if (info->textureSize >= 512 * 1024) {
+		info->textureOffset = info->exa->offScreenBase;
+		info->exa->offScreenBase += info->textureSize;
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "Will use %d kb for textures at offset 0x%08x\n",
+			   info->textureSize / 1024, info->textureOffset);
+	    } else {
+		/* Minimum texture size is for 2 256x256x32bpp textures */
+		info->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->exa->memorySize - info->exa->offScreenBase) /
 	       1024, info->exa->offScreenBase);
-
+    }
     return TRUE;
 }
 
@@ -525,10 +670,21 @@ extern void ExaOffscreenMarkUsed(PixmapPtr);
 unsigned long long
 RADEONTexOffsetStart(PixmapPtr pPix)
 {
+    struct radeon_exa_pixmap_priv *driver_priv;
+    uint32_t offset;
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+
+    if (driver_priv) {
+        offset = driver_priv->bo->offset;
+	
+    } else {
+        offset = exaGetPixmapOffset(pPix);
+    	offset += RADEONPTR(xf86Screens[pPix->drawable.pScreen->myNum])->fbLocation;
+    }
     exaMoveInPixmap(pPix);
     ExaOffscreenMarkUsed(pPix);
+    
 
-    return RADEONPTR(xf86Screens[pPix->drawable.pScreen->myNum])->fbLocation +
-	exaGetPixmapOffset(pPix);
+    return offset;
 }
 #endif
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 56de23e..628d2c7 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -74,21 +74,69 @@ FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker)
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     RADEONInfoPtr info = RADEONPTR(pScrn);
 
+    if (info->new_cs)
+	    return;
+
     TRACE;
 
     if (info->exaMarkerSynced != marker) {
-	FUNC_NAME(RADEONWaitForIdle)(pScrn);
+        FUNC_NAME(RADEONWaitForIdle)(pScrn);
 	info->exaMarkerSynced = marker;
     }
 
     RADEONPTR(pScrn)->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 ? 11 : 9;
+    qwords += (has_src ? (info->new_cs ?  3 : 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;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -97,25 +145,35 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
 	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"));
 
     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;
 }
@@ -148,8 +206,10 @@ FUNC_NAME(RADEONDoneSolid)(PixmapPtr pPix)
     OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
                   RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
     FINISH_ACCEL();
+    info->state_2d.op = 0;
 }
 
+
 void
 FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
 			       uint32_t dst_pitch_offset, uint32_t datatype, int rop,
@@ -160,23 +220,28 @@ FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset,
 
     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->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
-	 (info->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->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
+			       (info->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
@@ -187,7 +252,7 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
 {
     RINFO_FROM_SCREEN(pDst->drawable.pScreen);
     uint32_t datatype, src_pitch_offset, dst_pitch_offset;
-
+    struct radeon_exa_pixmap_priv *driver_priv;
     TRACE;
 
     info->xdir = xdir;
@@ -197,10 +262,19 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc,   PixmapPtr pDst,
 	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"));
+
+    driver_priv = exaGetPixmapDriverPrivate(pSrc);
+    if (driver_priv)
+      info->state_2d.src_bo = driver_priv->bo;
+
+    driver_priv = exaGetPixmapDriverPrivate(pDst);
+    if (driver_priv)
+      info->state_2d.dst_bo = driver_priv->bo;
 
     FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset,
 				   datatype, rop, planemask);
@@ -250,6 +324,8 @@ FUNC_NAME(RADEONDoneCopy)(PixmapPtr pDst)
     OUT_ACCEL_REG(RADEON_WAIT_UNTIL,
                   RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
     FINISH_ACCEL();
+
+    info->state_2d.op = 0;
 }
 
 static Bool
@@ -260,6 +336,8 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h,
     uint8_t	   *dst	     = info->FB + exaGetPixmapOffset(pDst);
     unsigned int   dst_pitch = exaGetPixmapPitch(pDst);
     unsigned int   bpp	     = pDst->drawable.bitsPerPixel;
+    int ret;
+    struct radeon_exa_pixmap_priv *driver_priv;
 #ifdef ACCEL_CP
     unsigned int   hpass;
     uint32_t	   buf_pitch, dst_pitch_off;
@@ -276,10 +354,47 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h,
     if (bpp < 8)
 	return FALSE;
 
+    if (info->new_cs)
+	dst = info->mm.front_buffer->map + exaGetPixmapOffset(pDst);
+
 #ifdef ACCEL_CP
-    if (info->directRenderingEnabled &&
-	RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off)) {
-	uint8_t *buf;
+
+    if (info->new_cs){
+
+	if (info->drm_mm) {
+	    uint32_t offset, bo_width, bo_height = h;
+
+	    driver_priv = exaGetPixmapDriverPrivate(pDst);
+	    if (!driver_priv)
+		return FALSE;
+
+
+	    /* use pwrites - maybe require some sort of fallback */
+	    bo_width = w * (bpp / 8);
+	    offset = (x * bpp / 8) + (y * dst_pitch);
+
+	    while (bo_height--) {
+		ret = dri_bo_subdata(driver_priv->bo, offset, bo_width,
+				     src);
+		if (ret == -1)
+		    return FALSE;
+		    
+		src += src_pitch;
+		offset += dst_pitch;
+	    }
+
+	    return TRUE;
+	}
+    }
+    if (!info->directRenderingEnabled && !info->drm_mode_setting)
+        goto fallback;
+
+    if (RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off))
+        goto fallback;
+
+    if (!info->new_cs)
+    {
+        uint8_t *buf;
 	int cpp = bpp / 8;
 	ACCEL_PREAMBLE();
 
@@ -294,9 +409,10 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h,
 
 	exaMarkSync(pDst->drawable.pScreen);
 	return TRUE;
-  }
-#endif
+    }
 
+ fallback:
+#endif
     /* Do we need that sync here ? probably not .... */
     exaWaitSync(pDst->drawable.pScreen);
 
@@ -388,13 +504,17 @@ FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h,
 
     TRACE;
 
+    if (info->drm_mode_setting)
+      src = info->mm.front_buffer->map + exaGetPixmapOffset(pSrc);
+
 #ifdef ACCEL_CP
     /*
      * 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 (info->accelDFS && bpp != 24 && RADEONGetDatatypeBpp(bpp, &datatype) &&
+    if (!info->drm_mm && info->accelDFS && bpp != 24 &&
+	RADEONGetDatatypeBpp(bpp, &datatype) &&
 	RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset) &&
 	(scratch = RADEONCPGetBuffer(pScrn)))
     {
@@ -540,17 +660,23 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
 
     info->exa->MarkSync = FUNC_NAME(RADEONMarkSync);
     info->exa->WaitMarker = FUNC_NAME(RADEONSync);
+
     info->exa->UploadToScreen = FUNC_NAME(RADEONUploadToScreen);
-    info->exa->DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen);
+    if (!info->drm_mm) {
+      info->exa->DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen);
+    }
 
-#if X_BYTE_ORDER == X_BIG_ENDIAN
     info->exa->PrepareAccess = RADEONPrepareAccess;
     info->exa->FinishAccess = RADEONFinishAccess;
-#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
 
     info->exa->flags = EXA_OFFSCREEN_PIXMAPS;
-    info->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1;
     info->exa->pixmapPitchAlign = 64;
+    info->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1;
+
+    if (info->drm_mm) {
+      info->exa->flags |= EXA_HANDLES_PIXMAPS;
+    } else {
+    }
 
 #ifdef RENDER
     if (info->RenderAccel) {
@@ -560,7 +686,7 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
 	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 "
@@ -595,6 +721,16 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen)
     }
 #endif
 
+#if EXA_VERSION_MINOR >= 4
+    if (info->drm_mm) {
+        info->exa->CreatePixmap = RADEONEXACreatePixmap;
+        info->exa->DestroyPixmap = RADEONEXADestroyPixmap;
+        info->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen;
+        info->exa->ModifyPixmapHeader = RADEONEXAModifyPixmapHeader;
+    }
+#endif
+
+
 #if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting EXA maxPitchBytes\n");
 
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index 5d28d80..6426736 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -410,19 +410,22 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     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);
+	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);
+	OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, txoffset);
+	/* emit a texture relocation */
     }
     FINISH_ACCEL();
 
@@ -730,6 +733,7 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 		      ((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);
+	/* emit a texture relocation */
     } else {
 	OUT_ACCEL_REG(R200_PP_TXFILTER_1, txfilter);
 	OUT_ACCEL_REG(R200_PP_TXFORMAT_1, txformat);
@@ -738,6 +742,7 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 		      ((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);
+	/* emit a texture relocation */
     }
     FINISH_ACCEL();
 
@@ -1002,12 +1007,14 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
     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));
@@ -1071,13 +1078,25 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
 	RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter));
     }
 
-    BEGIN_ACCEL(pPict->repeat ? 6 : 7);
+    qwords = pPict->repeat ? 6 : 7;
+    qwords += info->new_cs ? 2 : 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);
+
+    driver_priv = exaGetPixmapDriverPrivate(pPix);
+    if (info->new_cs) {
+        uint32_t handle = 0;
+        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();
@@ -1187,6 +1206,8 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
     uint32_t txenable, colorpitch;
     uint32_t blendcntl;
     int pixel_shift;
+    int qwords;
+    struct radeon_exa_pixmap_priv *driver_priv;
     ACCEL_PREAMBLE();
 
     TRACE;
@@ -1204,7 +1225,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 
     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;
 
@@ -1830,9 +1851,18 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
 	FINISH_ACCEL();
     }
 
-    BEGIN_ACCEL(3);
+    qwords = info->new_cs ? 5 : 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);
diff --git a/src/radeon_memory.c b/src/radeon_memory.c
new file mode 100644
index 0000000..ccc3bb8
--- /dev/null
+++ b/src/radeon_memory.c
@@ -0,0 +1,424 @@
+
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "radeon.h"
+#include "radeon_drm.h"
+
+Bool
+radeon_bind_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem)
+{
+	RADEONInfoPtr info = RADEONPTR(pScrn);	
+  
+	if (mem == NULL || mem->bound)
+		return TRUE;
+
+	if (!info->drm_mm)
+		return FALSE;
+
+	if (mem->kernel_bo_handle) {
+		struct drm_radeon_gem_pin pin;
+
+		int ret;
+
+		pin.handle = mem->kernel_bo_handle;
+		pin.alignment = mem->alignment;
+
+		ret = ioctl(info->drmFD, DRM_IOCTL_RADEON_GEM_PIN, &pin);
+		if (ret != 0) {
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				   "Failed to pin %s: %s\n", mem->name, strerror(errno));
+			return FALSE;
+		}
+
+		mem->bound = TRUE;
+		mem->offset = pin.offset;
+		//		ErrorF("pin returned 0x%llx\n", pin.offset);
+		mem->end = mem->offset + mem->size;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static Bool
+radeon_unbind_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem)
+{
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+	int ret;
+
+	if (mem == NULL || !mem->bound)
+		return TRUE;
+
+	if (!info->drm_mm)
+		return FALSE;
+
+
+	if (mem->kernel_bo_handle) {
+		struct drm_radeon_gem_unpin unpin;
+
+		unpin.handle = mem->kernel_bo_handle;
+		ret = ioctl(info->drmFD, DRM_IOCTL_RADEON_GEM_UNPIN, &unpin);
+
+		if (ret == 0) {
+			mem->bound = FALSE;
+			mem->offset = -1;
+			mem->end = -1;
+			return TRUE;
+		} else {
+			return FALSE;
+		}
+	}
+	return FALSE;
+}
+
+void radeon_free_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem)
+{
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+
+	if (mem == NULL)
+		return;
+
+	if (mem->map)
+	    radeon_unmap_memory(pScrn, mem);
+	    
+	radeon_unbind_memory(pScrn, mem);
+
+	if (mem->kernel_bo_handle) {
+		struct drm_gem_close close;
+
+		close.handle = mem->kernel_bo_handle;
+		ioctl(info->drmFD, DRM_IOCTL_GEM_CLOSE, &close);
+	}
+
+	if (info->mm.bo_list[mem->pool] == mem) {
+	  info->mm.bo_list[mem->pool] = mem->next;
+	  if (mem->next)
+	    mem->next->prev = NULL;
+	} else {
+	  if (mem->prev)
+	    mem->prev->next = mem->next;
+	  if (mem->next)
+	    mem->next->prev = mem->prev;
+	}
+	xfree(mem->name);
+	xfree(mem);
+	return;
+}
+
+struct radeon_memory *radeon_allocate_memory(ScrnInfoPtr pScrn, int pool, int size, int alignment, Bool no_backing_store, char *name,
+					     int static_alloc)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);	
+    struct drm_radeon_gem_create args;
+    struct radeon_memory *mem;
+    int ret;
+
+    mem = xcalloc(1, sizeof(*mem));
+    if (!mem)
+	return NULL;
+    
+    mem->name = xstrdup(name); 
+    if (!mem->name) {
+	xfree(mem);
+	return NULL;
+    }
+
+    mem->size = size;
+    mem->pool = pool;
+    mem->next = mem->prev = NULL;
+    mem->vt_bind = static_alloc;
+    args.size = size;
+    args.alignment = alignment;
+    if (pool == RADEON_POOL_VRAM)
+      args.initial_domain = RADEON_GEM_DOMAIN_VRAM;
+    else
+      args.initial_domain = RADEON_GEM_DOMAIN_GTT;
+    args.no_backing_store = no_backing_store;
+
+    ret = drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_CREATE, &args, sizeof(args));
+    if (ret) {
+	ErrorF("Failed to allocate %s\n", mem->name);
+	xfree(mem);
+	return NULL;
+    }
+
+    mem->kernel_bo_handle = args.handle;
+    //    xf86DrvMsg(pScrn->scrnIndex, X_INFO,	
+    //	       "%s allocated %d with handle %x\n", mem->name, mem->size, mem->kernel_bo_handle);
+
+    /* add to VRAM linked list for now */
+
+    mem->prev = NULL;
+    mem->next = info->mm.bo_list[pool];
+    if (info->mm.bo_list[pool] != NULL)
+	info->mm.bo_list[pool]->prev = mem;
+    info->mm.bo_list[pool] = mem;
+    return mem;
+}
+
+Bool radeon_bind_all_memory(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);	
+    struct radeon_memory *mem;
+    int i;
+
+    for (i = 0; i < 2; i++) {
+	for (mem = info->mm.bo_list[i]; mem != NULL;
+	     mem = mem->next) {
+	    if (mem->vt_bind)
+		if (!radeon_bind_memory(pScrn, mem)) {
+		    FatalError("Couldn't bind %s\n", mem->name);
+		}
+	}
+    }
+    return TRUE;
+}
+	    
+Bool radeon_unbind_all_memory(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);	
+    struct radeon_memory *mem;
+    int i;
+
+    for (i = 0; i < 2; i++) {
+	for (mem = info->mm.bo_list[i]; mem != NULL;
+	     mem = mem->next) {
+	    if (mem->vt_bind)
+		radeon_unbind_memory(pScrn, mem);
+	}
+    }
+    return TRUE;
+}
+
+Bool radeon_free_all_memory(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);	
+    struct radeon_memory *mem;
+    int i;
+
+    for (i = 0; i < 2; i++) {
+	for (mem = info->mm.bo_list[i]; mem != NULL;
+	     mem = mem->next) {
+	    radeon_free_memory(pScrn, mem);
+	}
+    }
+    return TRUE;
+}
+
+int radeon_map_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem)
+{
+    struct drm_radeon_gem_mmap args;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    int ret;
+
+    assert(!mem->map);
+
+
+    args.handle = mem->kernel_bo_handle;
+    args.size = mem->size;
+    ret = drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_MMAP, &args, sizeof(args));
+
+    if (!ret)
+	mem->map = (void *)(unsigned long)args.addr_ptr;
+    //    ErrorF("Mapped %s size %ld at %x %p\n", mem->name, mem->size, mem->offset, mem->map);
+    return ret;
+}
+
+void radeon_unmap_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem)
+{
+    assert(mem->map);
+    if (mem->map) {
+        munmap(mem->map, mem->size);
+        mem->map = NULL;
+    }
+}
+
+/* Okay radeon
+   2D allocations 
+   - Front buffer
+   - cursors
+   - EXA space
+
+   3D related:
+   - Backbuffer
+   - Depth buffer
+   - textures
+*/
+
+
+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 = (20*1024*1024)+32*1024, remain_size_bytes;
+    int fb_size_bytes;
+
+    screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * stride;
+
+    ErrorF("%d x %d x %d = %dK\n", pScrn->displayWidth, pScrn->virtualY, cpp, screen_size / 1024);
+
+    {
+	int cursor_size = 64 * 4 * 64;
+	int c;
+
+	for (c = 0; c < xf86_config->num_crtc; c++) {
+	    /* cursor objects */
+	    info->mm.cursor[c] = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, cursor_size, 0, 1, "Cursor", 1);
+	    if (!info->mm.cursor[c]) {
+		return FALSE;
+	    }
+
+	    radeon_bind_memory(pScrn, info->mm.cursor[c]);
+
+	    if (radeon_map_memory(pScrn, info->mm.cursor[c])) {
+		ErrorF("Failed to map front buffer memory\n");
+	    }
+	    
+	    if (!info->drm_mode_setting) {
+		xf86CrtcPtr crtc = xf86_config->crtc[c];
+		RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;
+		radeon_crtc->cursor = info->mm.cursor[c];
+	    } else {
+		drmmode_set_cursor(pScrn, &info->drmmode, c, (void *)info->mm.cursor[c]->map, info->mm.cursor[c]->kernel_bo_handle);
+	    }
+	    total_size_bytes += cursor_size;
+	}
+    }
+
+#if 0
+    info->mm.front_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, screen_size, 0, 1, "Front Buffer");
+    if (!info->mm.front_buffer) {
+	return FALSE;
+    }
+
+    radeon_bind_memory(pScrn, info->mm.front_buffer);
+
+    if (radeon_map_memory(pScrn, info->mm.front_buffer)) {
+	ErrorF("Failed to map front buffer memory\n");
+    }
+#endif
+    /* keep area front front buffer - but don't allocate it yet */
+    total_size_bytes += screen_size;
+
+    if (info->directRenderingEnabled) {
+	info->backPitch = pScrn->displayWidth;
+	info->mm.back_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, screen_size, 0, 1, "Back Buffer", 1);
+	if (!info->mm.back_buffer) {
+	    return FALSE;
+	}
+	radeon_bind_memory(pScrn, info->mm.back_buffer);
+	total_size_bytes += screen_size;
+	
+	info->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32);
+	{
+	    int depthCpp = (info->depthBits - 8) / 4;
+	    int depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->depthPitch * depthCpp;
+	    info->mm.depth_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, depth_size, 0, 1, "Depth Buffer", 1);
+	    if (!info->mm.depth_buffer) {
+		return FALSE;
+	    }
+	    radeon_bind_memory(pScrn, info->mm.depth_buffer);
+	    total_size_bytes += depth_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->textureSize = remain_size_bytes / 2;
+
+    ErrorF("texture size is %dK, exa is %dK\n", info->textureSize / 1024, (remain_size_bytes - info->textureSize)/1024);
+
+    /* allocate an object for all the EXA bits */
+    /* shove EXA + frontbuffer together until we have EXA pixmap hooks */
+    fb_size_bytes = screen_size + (remain_size_bytes - info->textureSize);
+
+    if (info->new_cs)
+        fb_size_bytes = screen_size;
+    ErrorF("fb size is %dK %dK\n", fb_size_bytes / 1024, total_size_bytes / 1024);
+
+    info->mm.front_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, fb_size_bytes, 0, 1, "Front Buffer + EXA", 1);
+    if (!info->mm.front_buffer) {
+	return FALSE;
+    }
+
+    radeon_bind_memory(pScrn, info->mm.front_buffer);
+    if (radeon_map_memory(pScrn, info->mm.front_buffer)) {
+	ErrorF("Failed to map front buffer memory\n");
+    }
+    info->frontPitch = pScrn->displayWidth;
+#if 0
+    info->mm.exa_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, remain_size_bytes - info->textureSize, 0, 1, "EXA Memory Buffer");
+    if (!info->mm.exa_buffer) {
+	return FALSE;
+    }
+    radeon_bind_memory(pScrn, info->mm.exa_buffer);
+    if (radeon_map_memory(pScrn, info->mm.exa_buffer)) {
+	ErrorF("Failed to map front buffer memory\n");
+    }
+#endif
+
+    if (!info->new_cs) {
+        info->exa->memoryBase = info->mm.front_buffer->map;
+        info->exa->offScreenBase = screen_size;
+        info->exa->memorySize = fb_size_bytes;
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Will use %ld kb for X Server offscreen at offset 0x%08lx\n",
+		   (info->exa->memorySize - info->exa->offScreenBase) /
+		   1024, info->exa->offScreenBase);
+    }
+
+    if (info->directRenderingEnabled) {
+	info->textureSize /= 2;
+	info->mm.texture_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, info->textureSize, 0, 1, "Texture Buffer", 1);
+	if (!info->mm.texture_buffer) {
+	    return FALSE;
+	}
+	radeon_bind_memory(pScrn, info->mm.texture_buffer);
+    }
+	
+    if (info->drm_mode_setting) {
+	drmmode_set_fb(pScrn, &info->drmmode, pScrn->virtualX, RADEON_ALIGN(pScrn->virtualY, 16), stride, info->mm.front_buffer->kernel_bo_handle);
+    }
+    return TRUE;
+}
+
+Bool radeon_setup_gart_mem(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+
+
+    info->mm.gart_texture_buffer =
+	radeon_allocate_memory(pScrn, RADEON_POOL_GART,
+			       info->gartTexMapSize,
+			       0, 1, "GART texture buffers", 1);
+    
+    if (!info->mm.gart_texture_buffer) {
+	return FALSE;
+    }
+
+    radeon_bind_memory(pScrn, info->mm.gart_texture_buffer);
+    return TRUE;
+}
+
+uint32_t radeon_create_new_fb(ScrnInfoPtr pScrn, int width, int height, int *pitch)
+{
+    return 0;
+}
+
+
+dri_bo *radeon_create_rotate_bo(ScrnInfoPtr pScrn, int size)
+{
+	RADEONInfoPtr info = RADEONPTR(pScrn);
+	dri_bo *bo;
+
+	bo = dri_bo_alloc(info->bufmgr, "rotate", size, 0);
+
+	radeon_bufmgr_pin(bo);
+	return bo;
+}
+
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 3770abf..e8505b7 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -182,6 +182,27 @@ typedef struct
     uint32_t a_data_mask;
 } RADEONI2CBusRec, *RADEONI2CBusPtr;
 
+struct radeon_memory {
+    int pool; // memory is VRAM vs GART
+    unsigned long offset;
+    unsigned long end;
+
+    unsigned long size;
+    unsigned long allocated_size;
+    void *map;
+    int key;
+
+    Bool bound;
+    unsigned long agp_offset;
+    unsigned int pitch;
+    char *name;
+    struct radeon_memory *next, *prev;
+    uint32_t alignment;
+    uint32_t kernel_bo_handle;
+    uint32_t kernel_name;
+    Bool vt_bind;
+};
+
 typedef struct _RADEONCrtcPrivateRec {
 #ifdef USE_XAA
     FBLinearPtr rotate_mem_xaa;
@@ -198,6 +219,8 @@ typedef struct _RADEONCrtcPrivateRec {
     uint32_t crtc_offset;
     int can_tile;
     Bool enabled;
+    struct radeon_memory *cursor;
+
 } RADEONCrtcPrivateRec, *RADEONCrtcPrivatePtr;
 
 typedef struct {
diff --git a/src/radeon_sarea.h b/src/radeon_sarea.h
index 80333a4..c33632b 100644
--- a/src/radeon_sarea.h
+++ b/src/radeon_sarea.h
@@ -36,6 +36,7 @@
 #ifndef _RADEON_SAREA_H_
 #define _RADEON_SAREA_H_
 
+#if 0
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the kernel file (radeon_drm.h)
  */
@@ -229,3 +230,6 @@ typedef struct {
  } RADEONSAREAPriv, *RADEONSAREAPrivPtr;
 
 #endif
+
+typedef drm_radeon_sarea_t RADEONSAREAPriv, *RADEONSAREAPrivPtr;
+#endif
diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c
index cfa349d..ef05c72 100644
--- a/src/radeon_textured_video.c
+++ b/src/radeon_textured_video.c
@@ -85,6 +85,7 @@ static __inline__ uint32_t F_TO_DW(float val)
 #define BEGIN_VIDEO(n)		RADEONWaitForFifo(pScrn, (n))
 #define OUT_VIDEO_REG(reg, val)	OUTREG(reg, val)
 #define OUT_VIDEO_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
+#define OUT_RELOC(x, read, write) do {} while(0)
 #define FINISH_VIDEO()
 
 #include "radeon_textured_videofuncs.c"
@@ -93,6 +94,7 @@ static __inline__ uint32_t F_TO_DW(float val)
 #undef VIDEO_PREAMBLE
 #undef BEGIN_VIDEO
 #undef OUT_VIDEO_REG
+#undef OUT_RELOC
 #undef FINISH_VIDEO
 
 #ifdef XF86DRI
@@ -105,6 +107,7 @@ static __inline__ uint32_t F_TO_DW(float val)
 #define OUT_VIDEO_REG(reg, val)	OUT_RING_REG(reg, val)
 #define FINISH_VIDEO()		ADVANCE_RING()
 #define OUT_VIDEO_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"
 
@@ -179,7 +182,8 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
     }
 
 #ifdef XF86DRI
-   if (info->directRenderingEnabled && info->DMAForXv)
+    if ((info->directRenderingEnabled || info->drm_mode_setting)
+	&& info->DMAForXv )
        /* The upload blit only supports multiples of 64 bytes */
        dstPitch = (dstPitch + 63) & ~63;
    else
@@ -226,8 +230,12 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
     left = (x1 >> 16) & ~1;
     npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
 
-    pPriv->src_offset = pPriv->video_offset + info->fbLocation + pScrn->fbOffset;
-    pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch));
+    pPriv->src_offset = pPriv->video_offset;
+    if (info->drm_mm) {
+        pPriv->src_addr = (uint8_t *)(info->mm.front_buffer->map + pPriv->video_offset + (top * dstPitch));
+    } else {
+        pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch));
+    }
     pPriv->src_pitch = dstPitch;
     pPriv->size = size;
     pPriv->pDraw = pDraw;
@@ -283,7 +291,7 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn,
     pPriv->h = height;
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled)
+    if (info->directRenderingEnabled || info->drm_mode_setting)
 	RADEONDisplayTexturedVideoCP(pScrn, pPriv);
     else
 #endif
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index d39f74d..56d71b1 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -82,19 +82,19 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
     int dstxoff, dstyoff, pixel_shift;
     BoxPtr pBox = REGION_RECTS(&pPriv->clip);
     int nBox = REGION_NUM_RECTS(&pPriv->clip);
+    int qwords;
     VIDEO_PREAMBLE();
 
     pixel_shift = pPixmap->drawable.bitsPerPixel >> 4;
 
 #ifdef USE_EXA
     if (info->useEXA) {
-	dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset;
+	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;
 	}
 
@@ -183,13 +183,21 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 
 	txoffset = pPriv->src_offset;
 
-	BEGIN_VIDEO(6);
+	qwords = info->new_cs ? 8 : 6;
+	BEGIN_VIDEO(qwords);
 	OUT_VIDEO_REG(R300_TX_FILTER0_0, txfilter);
 	OUT_VIDEO_REG(R300_TX_FILTER1_0, 0);
 	OUT_VIDEO_REG(R300_TX_FORMAT0_0, txformat0);
 	OUT_VIDEO_REG(R300_TX_FORMAT1_0, txformat1);
 	OUT_VIDEO_REG(R300_TX_FORMAT2_0, txpitch);
-	OUT_VIDEO_REG(R300_TX_OFFSET_0, txoffset);
+
+	if (info->new_cs) {
+	    OUT_VIDEO_REG(R300_TX_OFFSET_0, txoffset);
+	    OUT_RELOC(info->mm.front_buffer->kernel_bo_handle, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0);
+	} else {
+	    txoffset += info->fbLocation + pScrn->fbOffset;
+	    OUT_VIDEO_REG(R300_TX_OFFSET_0, txoffset);
+	}
 	FINISH_VIDEO();
 
 	txenable = R300_TEX_0_ENABLE;
@@ -408,11 +416,18 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 	    FINISH_VIDEO();
 	}
 
-	BEGIN_VIDEO(5);
+	qwords = info->new_cs ? 7 : 5;
+	BEGIN_VIDEO(qwords);
 	OUT_VIDEO_REG(R300_TX_INVALTAGS, 0);
 	OUT_VIDEO_REG(R300_TX_ENABLE, txenable);
 
-	OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+	if (info->new_cs) {
+	    OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+	    OUT_RELOC(info->mm.front_buffer->kernel_bo_handle, 0, RADEON_GEM_DOMAIN_VRAM);
+	} else {
+	    dst_offset += info->fbLocation + pScrn->fbOffset;
+	    OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset);
+	}
 	OUT_VIDEO_REG(R300_RB3D_COLORPITCH0, colorpitch);
 
 	blendcntl = RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO;
@@ -459,6 +474,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 		    RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE);
 	OUT_VIDEO_REG(RADEON_RB3D_CNTL,
 		    dst_format | RADEON_ALPHA_BLEND_ENABLE);
+	dst_offset += info->fbLocation + pScrn->fbOffset;
 	OUT_VIDEO_REG(RADEON_RB3D_COLOROFFSET, dst_offset);
 
 	OUT_VIDEO_REG(RADEON_RB3D_COLORPITCH, colorpitch);
@@ -496,7 +512,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 			((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT));
 	    OUT_VIDEO_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32);
 
-	    OUT_VIDEO_REG(R200_PP_TXOFFSET_0, pPriv->src_offset);
+	    OUT_VIDEO_REG(R200_PP_TXOFFSET_0, pPriv->src_offset +
+			  info->fbLocation + pScrn->fbOffset);
 
 	    OUT_VIDEO_REG(R200_PP_TXCBLEND_0,
 			R200_TXC_ARG_A_ZERO |
@@ -530,7 +547,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
 			RADEON_CLAMP_T_CLAMP_LAST |
 			RADEON_YUV_TO_RGB);
 	    OUT_VIDEO_REG(RADEON_PP_TXFORMAT_0, txformat);
-	    OUT_VIDEO_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset);
+	    OUT_VIDEO_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset +
+			  info->fbLocation + pScrn->fbOffset);
 	    OUT_VIDEO_REG(RADEON_PP_TXCBLEND_0,
 			RADEON_COLOR_ARG_A_ZERO |
 			RADEON_COLOR_ARG_B_ZERO |
diff --git a/src/radeon_video.c b/src/radeon_video.c
index 57dcd8a..ecd34a1 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -275,7 +275,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;
@@ -288,7 +288,7 @@ void RADEONInitVideo(ScreenPtr pScreen)
     if (info->ChipFamily != CHIP_FAMILY_RV250) {
 	if ((info->ChipFamily < CHIP_FAMILY_RS400)
 #ifdef XF86DRI
-	    || (info->directRenderingEnabled)
+	    || (info->directRenderingEnabled || info->drm_mode_setting)
 #endif
 	    ) {
 	    texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen);