diff -urN xf86-video-ati.orig/src/radeon.h xf86-video-ati/src/radeon.h
--- xf86-video-ati.orig/src/radeon.h	2006-01-09 06:02:16.000000000 +1100
+++ xf86-video-ati/src/radeon.h	2006-01-25 23:27:05.000000000 +1100
@@ -102,7 +102,7 @@
 
 /* ------------------------------------- */
 
-#define RADEON_DEBUG            0 /* Turn off debugging output               */
+#define RADEON_DEBUG            1 /* Turn off debugging output               */
 #define RADEON_IDLE_RETRY      16 /* Fall out of idle loops after this count */
 #define RADEON_TIMEOUT    2000000 /* Fall out of wait loops after this count */
 #define RADEON_MMIOSIZE   0x80000
@@ -116,13 +116,13 @@
 				   */
 
 #if RADEON_DEBUG
-#define RADEONTRACE(x)							\
+#define RADEONTRACE(x)						\
 do {									\
     ErrorF("(**) %s(%d): ", RADEON_NAME, pScrn->scrnIndex);		\
     ErrorF x;								\
-} while (0);
+} while(0)
 #else
-#define RADEONTRACE(x)
+#define RADEONTRACE(x) do { } while(0)
 #endif
 
 
@@ -147,10 +147,16 @@
     CARD32            cap0_trig_cntl;
     CARD32            cap1_trig_cntl;
     CARD32            bus_cntl;
-    CARD32            surface_cntl;
     CARD32            bios_4_scratch;
     CARD32            bios_5_scratch;
     CARD32            bios_6_scratch;
+    CARD32            surface_cntl;
+    CARD32            surfaces[8][3];
+    CARD32            mc_agp_location;
+    CARD32            mc_fb_location;
+    CARD32            display_base_addr;
+    CARD32            display2_base_addr;
+    CARD32            ov0_base_addr;
 
 				/* Other registers to save for VT switches */
     CARD32            dp_datatype;
@@ -158,8 +164,6 @@
     CARD32            clock_cntl_index;
     CARD32            amcgpio_en_reg;
     CARD32            amcgpio_mask;
-    
-    CARD32            surfaces[8][3];
 
 				/* CRTC registers */
     CARD32            crtc_gen_cntl;
@@ -326,6 +330,8 @@
     unsigned long     MMIOAddr;         /* MMIO region physical address      */
     unsigned long     BIOSAddr;         /* BIOS physical address             */
     unsigned int      fbLocation;
+    CARD32            mc_fb_location;
+    CARD32            mc_agp_location;
 
     unsigned char     *MMIO;            /* Map of MMIO region                */
     unsigned char     *FB;              /* Map of frame buffer               */
@@ -482,6 +488,7 @@
 #ifdef XF86DRI
     Bool              noBackBuffer;
     Bool              directRenderingEnabled;
+    Bool              directRenderingInited;
     DRIInfoPtr        pDRIInfo;
     int               drmFD;
     int               numVisualConfigs;
diff -urN xf86-video-ati.orig/src/radeon_common.h xf86-video-ati/src/radeon_common.h
--- xf86-video-ati.orig/src/radeon_common.h	2005-09-11 18:51:38.000000000 +1000
+++ xf86-video-ati/src/radeon_common.h	2006-01-25 19:37:41.000000000 +1100
@@ -474,6 +474,7 @@
 #define RADEON_SETPARAM_FB_LOCATION     1
 #define RADEON_SETPARAM_SWITCH_TILING   2
 #define RADEON_SETPARAM_PCIGART_LOCATION 3
+#define RADEON_SETPARAM_NEW_MEMMAP 4
 
 /* 1.14: Clients can allocate/free a surface
  */
diff -urN xf86-video-ati.orig/src/radeon_commonfuncs.c xf86-video-ati/src/radeon_commonfuncs.c
--- xf86-video-ati.orig/src/radeon_commonfuncs.c	2005-09-12 06:58:53.000000000 +1000
+++ xf86-video-ati/src/radeon_commonfuncs.c	2006-01-25 22:50:36.000000000 +1100
@@ -155,9 +155,11 @@
     }
 #endif
 
+#if 0
     RADEONTRACE(("WaitForIdle (entering): %d entries, stat=0x%08x\n",
 		     INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
 		     INREG(RADEON_RBBM_STATUS)));
+#endif
 
     /* Wait for the engine to go idle */
     RADEONWaitForFifoFunction(pScrn, 64);
diff -urN xf86-video-ati.orig/src/radeon_cursor.c xf86-video-ati/src/radeon_cursor.c
--- xf86-video-ati.orig/src/radeon_cursor.c	2005-11-08 20:44:41.000000000 +1100
+++ xf86-video-ati/src/radeon_cursor.c	2006-01-26 10:35:37.000000000 +1100
@@ -31,6 +31,9 @@
 #include "config.h"
 #endif
 
+#define RADEONCTRACE(x)
+//#define RADEONCTRACE(x) RADEONTRACE(x)
+
 /*
  * Authors:
  *   Kevin E. Martin <martin@xfree86.org>
@@ -50,6 +53,7 @@
 
 				/* Driver data structures */
 #include "radeon.h"
+#include "radeon_version.h"
 #include "radeon_reg.h"
 #include "radeon_macros.h"
 #include "radeon_mergedfb.h"
@@ -81,11 +85,11 @@
 #define CURSOR_SWAPPING_DECL_MMIO   unsigned char *RADEONMMIO = info->MMIO;
 #define CURSOR_SWAPPING_START() \
   do { \
+    COMMON_CURSOR_SWAPPING_START(); \
     OUTREG(RADEON_SURFACE_CNTL, \
 	   (info->ModeReg.surface_cntl | \
-	    RADEON_NONSURF_AP0_SWP_32BPP) & \
-	   ~RADEON_NONSURF_AP0_SWP_16BPP); \
-    COMMON_CURSOR_SWAPPING_START(); \
+	     RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP) & \
+	   ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP)); \
   } while (0)
 #define CURSOR_SWAPPING_END()	(OUTREG(RADEON_SURFACE_CNTL, \
 					info->ModeReg.surface_cntl))
@@ -133,9 +137,9 @@
 		   "Using hardware cursor\n",
 		   info->cursor_offset = info->cursorArea->offset);
 
-	RADEONTRACE(("%s (0x%08x-0x%08x)\n", __func__,
-		     info->cursor_offset,
-		     info->cursor_offset + info->cursorArea->size));
+	RADEONCTRACE(("%s (0x%08x-0x%08x)\n", __func__,
+		      info->cursor_offset,
+		      info->cursor_offset + info->cursorArea->size));
     }
 }
 #endif
@@ -149,6 +153,11 @@
     int            pixel, i;
     CURSOR_SWAPPING_DECL_MMIO
 
+    RADEONCTRACE(("RADEONSetCursorColors\n"));
+
+    if (info->cursor_offset == 0)
+	return;
+
 #ifdef ARGB_CURSOR
     /* Don't recolour cursors set with SetCursorARGB. */
     if (info->cursor_argb)
@@ -191,11 +200,17 @@
     int                total_y    = pScrn->frameY1 - pScrn->frameY0;
     int		       stride     = 256;
 
+    if (info->cursor_offset == 0)
+	return;
+
     if(info->MergedFB) {
+       RADEONCTRACE(("RADEONSetCursorPositionMerged\n"));
        RADEONSetCursorPositionMerged(pScrn, x, y);
        return;
     }
 
+    RADEONCTRACE(("RADEONSetCursorPosition\n"));
+
     if (x < 0)                        xorigin = -x+1;
     if (y < 0)                        yorigin = -y+1;
     if (y > total_y)                  y       = total_y;
@@ -210,6 +225,8 @@
 	OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK
 					   | ((xorigin ? 0 : x) << 16)
 					   | (yorigin ? 0 : y)));
+	RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d\n",
+		     info->cursor_offset, yorigin, stride));
 	OUTREG(RADEON_CUR_OFFSET, info->cursor_offset + yorigin * stride);
     } else {
 	OUTREG(RADEON_CUR2_HORZ_VERT_OFF,  (RADEON_CUR2_LOCK
@@ -238,6 +255,11 @@
     CARD8	   chunk;
     CARD32         i, j;
 
+    if (info->cursor_offset == 0)
+	return;
+
+    RADEONCTRACE(("RADEONLoadCursorImage (at %x)\n", info->cursor_offset));
+
     if (!info->IsSecondary) {
 	save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20);
 	save1 |= (CARD32) (2 << 20);
@@ -264,7 +286,7 @@
      */
     CURSOR_SWAPPING_START();
 #define ARGB_PER_CHUNK	(8 * sizeof (chunk) / 2)
-    for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT / ARGB_PER_CHUNK; i++) {
+    for (i = 0; i < (CURSOR_WIDTH * CURSOR_HEIGHT / ARGB_PER_CHUNK); i++) {
         chunk = *s++;
 	for (j = 0; j < ARGB_PER_CHUNK; j++, chunk >>= 2)
 	    *d++ = mono_cursor_color[chunk & 3];
@@ -288,6 +310,8 @@
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
 
+    RADEONCTRACE(("RADEONHideCursor\n"));
+
     if (info->IsSecondary || info->MergedFB)
 	OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN);
 
@@ -301,6 +325,8 @@
     RADEONInfoPtr  info       = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
 
+    RADEONCTRACE(("RADEONShowCursor\n"));
+
     if (info->IsSecondary || info->MergedFB)
 	OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN,
 		~RADEON_CRTC2_CUR_EN);
@@ -351,8 +377,10 @@
     CARD32	  *image = pCurs->bits->argb;
     CARD32	  *i;
 
-    if (!image)
-	return;	/* XXX can't happen */
+    RADEONCTRACE(("RADEONLoadCursorARGB\n"));
+
+    if (info->cursor_offset == 0)
+	return;
 
     if (!info->IsSecondary) {
 	save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20);
@@ -473,7 +501,7 @@
 						256);
 	    info->cursor_end = info->cursor_offset + size_bytes;
 	}
-	RADEONTRACE(("RADEONCursorInit (0x%08x-0x%08x)\n",
+	RADEONCTRACE(("RADEONCursorInit (0x%08x-0x%08x)\n",
 		    info->cursor_offset, info->cursor_end));
     }
 #endif
diff -urN xf86-video-ati.orig/src/radeon_dri.c xf86-video-ati/src/radeon_dri.c
--- xf86-video-ati.orig/src/radeon_dri.c	2005-10-22 04:40:18.000000000 +1000
+++ xf86-video-ati/src/radeon_dri.c	2006-01-25 15:49:05.000000000 +1100
@@ -1456,10 +1456,6 @@
 		       version->version_patchlevel);
 	   info->allowColorTiling = FALSE;
 	   info->tilingEnabled = FALSE;
-	   /* try to fix up already set mode, crt pitch, ddx major (hope that's ok to do here) */
-	   /* is this correct scrnIndex? flags? */
-	   RADEONSwitchMode(pScrn->scrnIndex, pScrn->currentMode, 0);
-	   pScrn->AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
 	   pDRIInfo->ddxDriverMajorVersion = RADEON_VERSION_MAJOR;
 	}
 	drmFreeVersion(version);
@@ -1611,6 +1607,8 @@
        info->allowPageFlip = 0;
     }
 
+    info->directRenderingInited = TRUE;
+
     return TRUE;
 }
 
@@ -1665,7 +1663,9 @@
     drmRadeonInit  drmInfo;
     RING_LOCALS;
 
-				/* Stop the CP */
+    RADEONTRACE(("RADEONDRICloseScreen\n"));
+    
+    /* Stop the CP */
     if (info->directRenderingEnabled) {
 	/* If we've generated any CP commands, we must flush them to the
 	 * kernel module now.
@@ -1775,6 +1775,9 @@
     int                 i;
     RADEONSAREAPrivPtr  pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
 
+    if (!info->directRenderingInited)
+	return;
+
     /* Don't want to do this when no 3d is active and pages are
      * right-way-round
      */
@@ -1784,6 +1787,10 @@
 #ifdef USE_XAA
     /* XXX: implement for EXA */
     /* pretty much a hack. */
+
+    /* Make sure accel has been properly inited */
+    if (info->accel == NULL || info->accel->SetupForScreenToScreenCopy == NULL)
+	return;
     if (info->tilingEnabled)
        info->dst_pitch_offset |= RADEON_DST_TILE_MACRO;
     (*info->accel->SetupForScreenToScreenCopy)(pScrn,
diff -urN xf86-video-ati.orig/src/radeon_driver.c xf86-video-ati/src/radeon_driver.c
--- xf86-video-ati.orig/src/radeon_driver.c	2006-01-25 11:04:45.000000000 +1100
+++ xf86-video-ati/src/radeon_driver.c	2006-01-26 10:27:08.000000000 +1100
@@ -130,6 +130,8 @@
 static int RADEONValidateMergeModes(ScrnInfoPtr pScrn);
 static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode);
 static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn);
+static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
+static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
 
 /* psuedo xinerama support */
 
@@ -733,6 +735,7 @@
     if (info->FBDev) {
 	info->FB = fbdevHWMapVidmem(pScrn);
     } else {
+	RADEONTRACE(("Map: 0x%08x, 0x%08x\n", info->LinearAddr, info->FbMapSize));
 	info->FB = xf86MapPciMem(pScrn->scrnIndex,
 				 VIDMEM_FRAMEBUFFER,
 				 info->PciTag,
@@ -2253,83 +2256,80 @@
     return TRUE;
 }
 
-/* Set up MC_FB_LOCATION and related registers */
-static void
-RADEONSetFBLocation(ScrnInfoPtr pScrn)
+static void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
+				      RADEONInfoPtr info)
 {
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+    save->mc_fb_location = info->mc_fb_location;
+    save->mc_agp_location = info->mc_agp_location;
+    save->display_base_addr = info->fbLocation;
+    save->display2_base_addr = info->fbLocation;
+    save->ov0_base_addr = info->fbLocation;
+}
+
+static void RADEONInitMemoryMap(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 mc_fb_location;
-    CARD32 mc_agp_location = INREG(RADEON_MC_AGP_LOCATION);
-    CARD32 bus_cntl = INREG(RADEON_BUS_CNTL);
-    
-    OUTREG (RADEON_BUS_CNTL, bus_cntl | RADEON_BUS_MASTER_DIS);
-    RADEONWaitForIdleMMIO(pScrn);
+    unsigned long agp_size, agp_base, mem_size;
 
-    /* This function has many problems with newer cards.
-     * Even with older cards, all registers changed here are not
-     * restored properly when X quits, this will also cause 
-     * various problems, especially with radeonfb.
-     * Since we don't have DRI support for R300 and above cards, 
-     * we just hardcode these values for now.
-     * Need to revisit this whole function!!!
-     */
+    /* Default to existing values */
+    info->mc_fb_location = INREG(RADEON_MC_FB_LOCATION);
+    info->mc_agp_location = INREG(RADEON_MC_AGP_LOCATION);
 
-    if (info->IsIGP) {
-	mc_fb_location = INREG(RADEON_NB_TOM);
+    /* We shouldn't use info->videoRam here which might have been clipped
+     * but the real video RAM instead
+     */
+    mem_size = INREG(RADEON_CONFIG_MEMSIZE);
+    if (mem_size == 0)
+	    mem_size = 0x800000;
 
-	OUTREG(RADEON_GRPH2_BUFFER_CNTL,
-	       INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000);
 
-    } else
+    /* We won't try to change MC_FB_LOCATION when using fbdev */
+    if (!info->FBDev) {
+	if (info->IsIGP)
+	    info->mc_fb_location = INREG(RADEON_NB_TOM);
+	else
 #ifdef XF86DRI
-    if ( info->directRenderingEnabled && info->drmMinor < 10 ) {
-	mc_fb_location = (INREG(RADEON_CONFIG_APER_SIZE) - 1) & 0xffff0000U;
-    } else
+  /* Old DRI has restrictions on the memory map */
+	if ( info->directRenderingEnabled && info->drmMinor < 10 )
+	    info->mc_fb_location = (mem_size - 1) & 0xffff0000U;
+	else
 #endif
-    {
-	CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE);
-
-	mc_fb_location = (aper0_base >> 16)
-		       | ((aper0_base + (INREG(RADEON_CONFIG_APER_SIZE) - 1)
-			   ) & 0xffff0000U);
-    }
-
-    info->fbLocation = (mc_fb_location & 0xffff) << 16;
+	{
+	    CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE);
 
-    if (((mc_agp_location & 0xffff) << 16) !=
-	((mc_fb_location & 0xffff0000U) + 0x10000)) {
-	mc_agp_location = mc_fb_location & 0xffff0000U;
-	mc_agp_location |= (mc_agp_location + 0x10000) >> 16;
+	    info->mc_fb_location = (aper0_base >> 16) |
+		    ((aper0_base + mem_size - 1) & 0xffff0000U);
+	}
     }
+    info->fbLocation = (info->mc_fb_location & 0xffff) << 16;
 
-    RADEONWaitForIdleMMIO(pScrn);
+    /* Calculate AGP aperture location */
+    agp_size = ((info->mc_agp_location >> 16) -
+		(info->mc_agp_location & 0xffff) + 1) << 16;
+    agp_base = info->fbLocation + mem_size;
 
-    OUTREG(RADEON_MC_FB_LOCATION, mc_fb_location);
-    OUTREG(RADEON_MC_AGP_LOCATION, mc_agp_location);
-    OUTREG(RADEON_DISPLAY_BASE_ADDR, info->fbLocation);
-    if (info->HasCRTC2)
-	OUTREG(RADEON_DISPLAY2_BASE_ADDR, info->fbLocation);
-    OUTREG(RADEON_OV0_BASE_ADDR, info->fbLocation);
+    /* Make sure AGP size is at least 4Mb for the sake of the memory mapping
+     * (even if we don't actually use it, to avoid leaving a dangling map
+     * or invalid setting in MC_AGP_LOCATION
+     */
+    if (agp_size < 0x400000)
+	    agp_size = 0x400000;
 
-    OUTREG (RADEON_BUS_CNTL, bus_cntl);
-    RADEONWaitForIdleMMIO(pScrn);
+    /* If there is no room up there put AGP just below the fb */
+    if (((agp_base + agp_size) & 0xfffffffful) < agp_base)
+	    agp_base = info->fbLocation - agp_size;
 
-    /* Set display0/1 priority up on r3/4xx in the memory controller for 
-     * high res modes if the user specifies HIGH for displaypriority 
-     * option.
-     */
-    if ((info->DispPriority == 2) && IS_R300_VARIANT) {
-        CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER);
-	if (info->MergedFB || pRADEONEnt->HasSecondary) {
-	    mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */
-	} else {
-	    mc_init_misc_lat_timer |= 0x0100; /* display 0 only */
-	}
-	OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
-    }
+    /* Ok, now set our various bits & pieces */
+    info->mc_agp_location = (agp_base >> 16) |
+	    ((agp_base + agp_size - 1) & 0xffff0000U);
 
+    RADEONTRACE(("RADEONInitMemoryMap() : \n"));
+    RADEONTRACE(("  mem_size         : 0x%08lx\n", mem_size));
+    RADEONTRACE(("  agp_size         : 0x%08lx\n", agp_size));
+    RADEONTRACE(("  agp_base         : 0x%08lx\n", agp_base));
+    RADEONTRACE(("  MC_FB_LOCATION   : 0x%08lx\n", info->mc_fb_location));
+    RADEONTRACE(("  MC_AGP_LOCATION  : 0x%08lx\n", info->mc_agp_location));
 }
 
 static void RADEONGetVRamType(ScrnInfoPtr pScrn)
@@ -2705,22 +2705,48 @@
 
 	OUTREG(RADEON_CONFIG_MEMSIZE, pScrn->videoRam * 1024);
     } else {
-        /* There are different HDP mapping schemes depending on single/multi funciton setting,
-         * chip family, HDP mode, and the generation of HDP mapping scheme.
-         * To make things simple, we only allow maximum 128M addressable FB. Anything more than
-         * 128M is configured as invisible FB to CPU that can only be accessed from chip side.
-         */
+	CARD32 accessible_mem = INREG(RADEON_CONFIG_APER_SIZE) / 1024;
+
+        /* There are different HDP mapping schemes depending on single/multi
+	 * funciton setting, chip family, HDP mode, and the generation of HDP
+	 * mapping scheme. To make things simple, we only allow maximum 128M
+	 * addressable FB. Anything more than 128M is configured as invisible
+	 * FB to CPU that can only be accessed from chip side.
+	 *
+	 * The above doesn't necessarily work. For example, I've seen machines
+	 * with 128Mb configured as 2x64Mb apertures. However, if I always set
+	 * HDP_APER_CNTL, it seems PCI access stops working on some cards :(
+	 * Let's just read the setting and check how much we can access...
+	 */
         pScrn->videoRam      = INREG(RADEON_CONFIG_MEMSIZE) / 1024;
-        if (pScrn->videoRam > 128*1024) pScrn->videoRam = 128*1024;
+
+	/* We used to limit to 128M ... let's keep that for now until I have
+	 * verified that my new code might lift that limitation
+	 */
+        if (pScrn->videoRam > 128*1024)
+	    pScrn->videoRam = 128*1024;
+
+	/* Now, set HDP_APER_CNTL only on some cards as Hui original code does */
         if ((info->ChipFamily == CHIP_FAMILY_RV350) ||
             (info->ChipFamily == CHIP_FAMILY_RV380) ||
-            (info->ChipFamily == CHIP_FAMILY_R420)) {
-	    OUTREGP (RADEON_HOST_PATH_CNTL, (1<<23), ~(1<<23));
-        }
+            (info->ChipFamily == CHIP_FAMILY_R420))
+	    OUTREGP (RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL,
+		     ~RADEON_HDP_APER_CNTL);
+	
+	/* Now, read that bit. If it's set, double the accessible memory */
+	if (INREG(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL)
+	    accessible_mem *= 2;
+
+	/* Now trim videoRam if necessary */
+	if (pScrn->videoRam > accessible_mem)
+	     pScrn->videoRam = accessible_mem;
     }
 
     /* Some production boards of m6 will return 0 if it's 8 MB */
-    if (pScrn->videoRam == 0) pScrn->videoRam = 8192;
+    if (pScrn->videoRam == 0) {
+	pScrn->videoRam = 8192;
+	OUTREG(RADEON_CONFIG_MEMSIZE, 0x800000);
+    }
 
     /* Check chip errata */
     info->ChipErrata = 0;
@@ -5097,7 +5123,7 @@
     RADEONInfoPtr  info    = RADEONPTR(pScrn);
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled) {
+    if (info->directRenderingInited) {
 	FLUSH_RING();
     }
 #endif
@@ -5455,8 +5481,10 @@
     info->CPInUse      = FALSE;
     info->CPStarted    = FALSE;
     info->directRenderingEnabled = FALSE;
+    info->directRenderingInited = FALSE;
 #endif
     info->accelOn      = FALSE;
+    info->accel        = NULL;
     pScrn->fbOffset    = 0;
     if (info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024;
     if (!RADEONMapMem(pScrn)) return FALSE;
@@ -5504,31 +5532,6 @@
             info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
 	}
     }
-
-    if (!info->IsSecondary) {
-	/* empty the surfaces */
-	unsigned char *RADEONMMIO = info->MMIO;
-	unsigned int i;
-	for (i = 0; i < 8; i++) {
-	    OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0);
-	    OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0);
-	    OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0);
-	}
-    }
-
-    if (info->FBDev) {
-	unsigned char *RADEONMMIO = info->MMIO;
-
-	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
-	info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL);
-    } else {
-	if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
-    }
-
-    RADEONSaveScreen(pScreen, SCREEN_SAVER_ON);
-
-    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
-
 				/* Visual setup */
     miClearVisualTypes();
     if (!miSetVisualTypes(pScrn->depth,
@@ -5590,6 +5593,41 @@
 	}
     }
 
+    hasDRI = info->directRenderingEnabled;
+#endif
+
+    /* 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->IsSecondary) {
+	/* empty the surfaces */
+	unsigned char *RADEONMMIO = info->MMIO;
+	unsigned int i;
+	for (i = 0; i < 8; i++) {
+	    OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0);
+	    OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0);
+	    OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0);
+	}
+    }
+
+    if (info->FBDev) {
+	unsigned char *RADEONMMIO = info->MMIO;
+
+	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
+	RADEONSaveMemMapRegisters(pScrn, &info->ModeReg);
+	info->fbLocation = (info->ModeReg.mc_fb_location & 0xffff) << 16;
+	info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL);
+	info->ModeReg.surface_cntl &= ~RADEON_SURF_TRANSLATION_DIS;
+    } else {
+	if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
+    }
+
+    RADEONSaveScreen(pScreen, SCREEN_SAVER_ON);
+
+    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
     /* Depth moves are disabled by default since they are extremely slow */
     info->depthMoves = xf86ReturnOptValBool(info->Options,
 						 OPTION_DEPTH_MOVE, FALSE);
@@ -5604,11 +5642,15 @@
 		   "Depth moves disabled by default\n");
     }
 
-    hasDRI = info->directRenderingEnabled;
-#endif
+    /* Initial setup of surfaces */
+    if (!info->IsSecondary) {
+	RADEONTRACE(("Setting up initial surfaces\n"));
+	RADEONChangeSurfaces(pScrn);
+    }
 
-    RADEONSetFBLocation(pScrn);
+    RADEONTRACE(("Initializing fb layer\n"));
 
+    /* Init fb layer */
     if (!fbScreenInit(pScreen, info->FB,
 		      pScrn->virtualX, pScrn->virtualY,
 		      pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
@@ -5655,6 +5697,9 @@
     }
 #endif
 				/* Memory manager setup */
+
+    RADEONTRACE(("Setting up accel memmap\n"));
+
 #ifdef USE_EXA
     if (info->useEXA && !RADEONSetupMemEXA(pScreen))
 	return FALSE;
@@ -5673,8 +5718,97 @@
     info->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64)
 			       << 22) | ((info->fbLocation + pScrn->fbOffset) >> 10));
 
-    /* Acceleration setup */
+    /* Backing store setup */
+    RADEONTRACE(("Initializing backing store\n"));
+    miInitializeBackingStore(pScreen);
+    xf86SetBackingStore(pScreen);
+
+    /* Colormap setup */
+    RADEONTRACE(("Initializing color map\n"));
+    if (!miCreateDefColormap(pScreen)) return FALSE;
+    if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
+			     RADEONLoadPalette, NULL,
+			     CMAP_PALETTED_TRUECOLOR
+#if 0 /* This option messes up text mode! (eich@suse.de) */
+			     | CMAP_LOAD_EVEN_IF_OFFSCREEN
+#endif
+			     | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE;
+
+				/* DPMS setup */
+    /* DRI finalisation */
+#ifdef XF86DRI
+    /* Tell DRI about new memory map */
+    if (info->directRenderingEnabled) {
+	drmRadeonSetParam  radeonsetparam;
+	RADEONTRACE(("DRI New memory map param\n"));
+	memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam));
+	radeonsetparam.param = RADEON_SETPARAM_NEW_MEMMAP;
+	radeonsetparam.value = 1;
+	if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM,
+			    &radeonsetparam, sizeof(drmRadeonSetParam)) < 0)
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			   "[drm] failed to enable new memory map\n");
+    }
+
+    if (info->cardType==CARD_PCIE && info->pciGartOffset && info->drmMinor>=19)
+    {
+      drmRadeonSetParam  radeonsetparam;
+      RADEONTRACE(("DRI PCIGART param\n"));
+      memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam));
+      radeonsetparam.param = RADEON_SETPARAM_PCIGART_LOCATION;
+      radeonsetparam.value = info->pciGartOffset;
+      if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM,
+			  &radeonsetparam, sizeof(drmRadeonSetParam)) < 0)
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "[drm] failed set pci gart location\n");
+    }
+    if (info->directRenderingEnabled) {
+        RADEONTRACE(("DRI Finishing init !\n"));
+	info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen);
+    }
+    if (info->directRenderingEnabled) {
+	/* 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->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");
+
+	/* we might already be in tiled mode, tell drm about it */
+	if (info->directRenderingEnabled && info->tilingEnabled) {
+	    drmRadeonSetParam  radeonsetparam;
+	    memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam));
+	    radeonsetparam.param = RADEON_SETPARAM_SWITCH_TILING;
+	    radeonsetparam.value = info->tilingEnabled ? 1 : 0; 
+	    if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM,
+		&radeonsetparam, sizeof(drmRadeonSetParam)) < 0)
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "[drm] failed changing tiling status\n");
+	}
+    } else {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 
+		   "Direct rendering disabled\n");
+    }
+#endif
+
+    /* Make sure surfaces are allright since DRI setup may have changed them */
+    if (!info->IsSecondary) {
+	RADEONTRACE(("Setting up final surfaces\n"));
+	RADEONChangeSurfaces(pScrn);
+    }
+
+    if(info->MergedFB)
+	/* need this here to fix up sarea values */
+	RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+    /* Enable aceleration */
     if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
+	 RADEONTRACE(("Initializing Acceleration\n"));
 	if (RADEONAccelInit(pScreen)) {
 	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
 	    info->accelOn = TRUE;
@@ -5689,12 +5823,28 @@
 	info->accelOn = FALSE;
     }
 
+    /* Init DPMS */
+    RADEONTRACE(("Initializing DPMS\n"));
+    xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0);
+
     /* DGA setup */
+    RADEONTRACE(("Initializing DGA\n"));
     RADEONDGAInit(pScreen);
 
-    /* Backing store setup */
-    miInitializeBackingStore(pScreen);
-    xf86SetBackingStore(pScreen);
+    /* Wrap some funcs for MergedFB */
+    if(info->MergedFB) {
+       info->PointerMoved = pScrn->PointerMoved;
+       pScrn->PointerMoved = RADEONMergePointerMoved;
+       /* Psuedo xinerama */
+       if(info->UseRADEONXinerama) {
+          RADEONnoPanoramiXExtension = FALSE;
+          RADEONXineramaExtensionInit(pScrn);
+       } else {
+	  info->MouseRestrictions = FALSE;
+       }
+    }
+
+    RADEONTRACE(("Initializing Cursor\n"));
 
     /* Set Silken Mouse */
     xf86SetSilkenMouse(pScreen);
@@ -5731,115 +5881,117 @@
 	xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n");
     }
 
-				/* Colormap setup */
-    if (!miCreateDefColormap(pScreen)) return FALSE;
-    if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
-			     RADEONLoadPalette, NULL,
-			     CMAP_PALETTED_TRUECOLOR
-#if 0 /* This option messes up text mode! (eich@suse.de) */
-			     | CMAP_LOAD_EVEN_IF_OFFSCREEN
-#endif
-			     | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE;
-
-				/* DPMS setup */
-    xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0);
-
+    /* Init Xv */
+    RADEONTRACE(("Initializing Xv\n"));
     RADEONInitVideo(pScreen);
 
-				/* Provide SaveScreen */
-    pScreen->SaveScreen  = RADEONSaveScreen;
-
-				/* Wrap CloseScreen */
+    /* Provide SaveScreen & wrap BlockHandler and CloseScreen */
+    /* Wrap CloseScreen */
     info->CloseScreen    = pScreen->CloseScreen;
     pScreen->CloseScreen = RADEONCloseScreen;
+    pScreen->SaveScreen  = RADEONSaveScreen;
+    info->BlockHandler = pScreen->BlockHandler;
+    pScreen->BlockHandler = RADEONBlockHandler;
 
-    /* Wrap some funcs for MergedFB */
-    if(info->MergedFB) {
-       info->PointerMoved = pScrn->PointerMoved;
-       pScrn->PointerMoved = RADEONMergePointerMoved;
-       /* Psuedo xinerama */
-       if(info->UseRADEONXinerama) {
-          RADEONnoPanoramiXExtension = FALSE;
-          RADEONXineramaExtensionInit(pScrn);
-       } else {
-	  info->MouseRestrictions = FALSE;
-       }
-    }
-
-				/* Note unused options */
+    /* Note unused options */
     if (serverGeneration == 1)
 	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
 
-#ifdef XF86DRI
-    if (info->cardType==CARD_PCIE && info->pciGartOffset && info->drmMinor>=19)
-    {
-      drmRadeonSetParam  radeonsetparam;
-      memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam));
-      radeonsetparam.param = RADEON_SETPARAM_PCIGART_LOCATION;
-      radeonsetparam.value = info->pciGartOffset;
-      if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM,
-			  &radeonsetparam, sizeof(drmRadeonSetParam)) < 0)
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "[drm] failed set pci gart location\n");
-    }
+    RADEONTRACE(("RADEONScreenInit finished\n"));
 
-      /* DRI finalization */
-    if (info->directRenderingEnabled) {
-				/* Now that mi, fb, drm and others have
-				   done their thing, complete the DRI
-				   setup. */
-	if (!(info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen))) {
-#ifdef USE_EXA
-	    if (info->useEXA) {
-		RADEONDrawInitMMIO(pScreen);
-	    }
-#endif /* USE_EXA */
-#ifdef USE_XAA
-	    if (!info->useEXA)
-		RADEONAccelInitMMIO(pScreen, info->accel);
-#endif /* USE_XAA */
-	}
-    }
-    if (info->directRenderingEnabled) {
-	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");
+    return TRUE;
+}
 
-	/* we might already be in tiled mode, tell drm about it */
-	if (info->directRenderingEnabled && info->tilingEnabled) {
-	    drmRadeonSetParam  radeonsetparam;
-	    memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam));
-	    radeonsetparam.param = RADEON_SETPARAM_SWITCH_TILING;
-	    radeonsetparam.value = info->tilingEnabled ? 1 : 0; 
-	    if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM,
-		&radeonsetparam, sizeof(drmRadeonSetParam)) < 0)
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "[drm] failed changing tiling status\n");
-	}
+/* Write memory mapping registers */
+static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn,
+					 RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    int i;
 
-    } else {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 
-		   "Direct rendering disabled\n");
-    }
-#endif
+    RADEONTRACE(("RADEONRestoreMemMapRegisters() : \n"));
+    RADEONTRACE(("  MC_FB_LOCATION   : 0x%08lx\n", restore->mc_fb_location));
+    RADEONTRACE(("  MC_AGP_LOCATION  : 0x%08lx\n", restore->mc_agp_location));
+
+    /* Write memory mapping registers only if their value change
+     * since we must ensure no access is done while they are
+     * reprogrammed
+     */
+    if (INREG(RADEON_MC_FB_LOCATION) != restore->mc_fb_location ||
+	INREG(RADEON_MC_AGP_LOCATION) != restore->mc_agp_location) {
+	CARD32 tmp;
 
-    if (!info->IsSecondary)
-	RADEONChangeSurfaces(pScrn);
+	RADEONTRACE(("  Map Changed ! Applying ...\n"));
 
-    if(info->MergedFB) {
-	/* need this here to fix up sarea values */
-	RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+	/* Make sure engine is idle. We assume the CCE is stopped
+	 * at this point
+	 */
+	RADEONWaitForIdleMMIO(pScrn);
+
+	/* Stop display & memory access */
+	tmp = INREG(RADEON_CRTC_EXT_CNTL);
+	OUTREG(RADEON_CRTC_EXT_CNTL, tmp | RADEON_CRTC_DISPLAY_DIS);
+	tmp = INREG(RADEON_CRTC_GEN_CNTL);
+	tmp &= ~RADEON_CRTC_CUR_EN;
+	tmp |= RADEON_CRTC_DISP_REQ_EN_B;
+	OUTREG(RADEON_CRTC_GEN_CNTL, tmp);
+	if (info->HasCRTC2) {
+		tmp = INREG(RADEON_CRTC2_GEN_CNTL);
+		tmp &= ~RADEON_CRTC2_CUR_EN;
+		tmp |= RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_DISP_REQ_EN_B;
+		OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
+	}
+	tmp = INREG(RADEON_OV0_SCALE_CNTL);
+	tmp &= ~RADEON_SCALER_ENABLE;
+
+	/* Make sure the chip settles down and set new map*/ 
+	usleep(100000);
+	OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location);
+ 	OUTREG(RADEON_MC_AGP_LOCATION, restore->mc_agp_location);
+	/* Make sure map fully reached the chip */
+	(void)INREG(RADEON_MC_FB_LOCATION);
     }
+    
+    /* Restore base addresses */
+    OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr);
+    OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr);
+    OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr);
+}
 
-    info->BlockHandler = pScreen->BlockHandler;
-    pScreen->BlockHandler = RADEONBlockHandler;
+static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 fb, agp;
+    int fb_loc_changed;
 
-    return TRUE;
+    fb = INREG(RADEON_MC_FB_LOCATION);
+    agp = INREG(RADEON_MC_AGP_LOCATION);
+    fb_loc_changed = (fb != info->mc_fb_location);
+
+    if (fb_loc_changed || agp != info->mc_agp_location) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "DRI init changed memory map, adjusting ...\n");
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "  MC_FB_LOCATION  was: 0x%08lx is: 0x%08lx\n",
+		       info->mc_fb_location, fb);
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "  MC_AGP_LOCATION was: 0x%08lx is: 0x%08lx\n",
+		       info->mc_agp_location, agp);
+	    info->mc_fb_location = fb;
+	    info->mc_agp_location = agp;
+	    info->fbLocation = (save->mc_fb_location & 0xffff) << 16;
+
+	    RADEONInitMemMapRegisters(pScrn, save, info);
+
+	    /* If MC_FB_LOCATION was changed, adjust the various offsets */
+	    if (fb_loc_changed)
+		    RADEONRestoreMemMapRegisters(pScrn, save);
+    }
 }
 
-/* Write common registers (initialized to 0) */
+/* Write common registers */
 static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn,
 					 RADEONSavePtr restore)
 {
@@ -6002,13 +6154,6 @@
     OUTREG(RADEON_FP_VERT_STRETCH,      restore->fp_vert_stretch);
     OUTREG(RADEON_FP_GEN_CNTL,          restore->fp_gen_cntl);
 
-    /* old AIW Radeon has some BIOS initialization problem
-     * with display buffer underflow, only occurs to DFP
-     */
-    if (!info->HasCRTC2)
-	OUTREG(RADEON_GRPH_BUFFER_CNTL,
-	       INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000);
-
     if (info->IsMobility) {
 	OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch);
 	OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch);
@@ -6257,6 +6402,35 @@
 	    ~(RADEON_PIX2CLK_SRC_SEL_MASK));
 }
 
+
+/* restore original surface info (for fb console). */
+static void RADEONRestoreSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr restore)
+{
+    RADEONInfoPtr      info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    unsigned int surfnr;
+    
+    for ( surfnr = 0; surfnr < 8; surfnr++ ) {
+	OUTREG(RADEON_SURFACE0_INFO + 16 * surfnr, restore->surfaces[surfnr][0]);
+	OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * surfnr, restore->surfaces[surfnr][1]);
+	OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * surfnr, restore->surfaces[surfnr][2]);
+    }
+}
+
+/* save original surface info (for fb console). */
+static void RADEONSaveSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr      info = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    unsigned int surfnr;
+    
+    for ( surfnr = 0; surfnr < 8; surfnr++ ) {
+	save->surfaces[surfnr][0] = INREG(RADEON_SURFACE0_INFO + 16 * surfnr);
+	save->surfaces[surfnr][1] = INREG(RADEON_SURFACE0_LOWER_BOUND + 16 * surfnr);
+	save->surfaces[surfnr][2] = INREG(RADEON_SURFACE0_UPPER_BOUND + 16 * surfnr);
+    }
+}
+
 void RADEONChangeSurfaces(ScrnInfoPtr pScrn)
 {
    /* the idea here is to only set up front buffer as tiled, and back/depth buffer when needed.
@@ -6275,6 +6449,9 @@
         + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN);
     unsigned int depth_pattern, color_pattern, swap_pattern;
 
+    if (!info->allowColorTiling)
+	return;
+
     swap_pattern = 0;
 #if X_BYTE_ORDER == X_BIG_ENDIAN
     switch (pScrn->bitsPerPixel) {
@@ -6307,8 +6484,9 @@
 	    depth_pattern = R200_SURF_TILE_DEPTH_32BPP;
     }   
 #ifdef XF86DRI
-    if (info->directRenderingEnabled && info->allowColorTiling) {
+    if (info->directRenderingInited) {
 	drmRadeonSurfaceFree drmsurffree;
+	drmRadeonSurfaceAlloc drmsurfalloc;
 	int retvalue;
 
 	drmsurffree.address = info->frontOffset;
@@ -6329,31 +6507,31 @@
 		&drmsurffree, sizeof(drmsurffree));
 	}
 
-	if (info->tilingEnabled) {
-	    drmRadeonSurfaceAlloc drmsurfalloc;
-	    drmsurfalloc.size = bufferSize;
-	    drmsurfalloc.address = info->frontOffset;
+	drmsurfalloc.size = bufferSize;
+	drmsurfalloc.address = info->frontOffset;
+	drmsurfalloc.flags = swap_pattern;
 
+	if (info->tilingEnabled) {
 	    if (IS_R300_VARIANT)
-		drmsurfalloc.flags = swap_pattern | (width_bytes / 8) | color_pattern;
+		drmsurfalloc.flags |= (width_bytes / 8) | color_pattern;
 	    else
-		drmsurfalloc.flags = swap_pattern | (width_bytes / 16) | color_pattern;
-
+		drmsurfalloc.flags |= (width_bytes / 16) | color_pattern;
+	}
+	retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC,
+				   &drmsurfalloc, sizeof(drmsurfalloc));
+	if (retvalue < 0)
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "drm: could not allocate surface for front buffer!\n");
+	
+	if ((info->have3DWindows) && (!info->noBackBuffer)) {
+	    drmsurfalloc.address = info->backOffset;
 	    retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC,
-		&drmsurfalloc, sizeof(drmsurfalloc));
+				       &drmsurfalloc, sizeof(drmsurfalloc));
 	    if (retvalue < 0)
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		    "drm: could not allocate surface for front buffer!\n");
-
-	    if ((info->have3DWindows) && (!info->noBackBuffer)) {
-		drmsurfalloc.address = info->backOffset;
-		retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC,
-		    &drmsurfalloc, sizeof(drmsurfalloc));
-		if (retvalue < 0)
-		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			"drm: could not allocate surface for back buffer!\n");
-	    }
+			   "drm: could not allocate surface for back buffer!\n");
 	}
+
 	/* rv100 and probably the derivative igps don't have depth tiling on all the time? */
 	if (info->have3DWindows && ((info->ChipFamily != CHIP_FAMILY_RV100) || 
 	    (info->ChipFamily != CHIP_FAMILY_RS100) ||
@@ -6374,16 +6552,16 @@
     }
     else
 #endif
-    if (info->allowColorTiling) {
-	unsigned int surf_info = 0;
+    {
+	unsigned int surf_info = swap_pattern;
 	unsigned char *RADEONMMIO = info->MMIO;
 	/* we don't need anything like WaitForFifo, no? */
 	if (!info->IsSecondary) {
 	    if (info->tilingEnabled) {
 		if (IS_R300_VARIANT)
-		   surf_info = swap_pattern | (width_bytes / 8) | color_pattern;
+		   surf_info |= (width_bytes / 8) | color_pattern;
 		else
-		   surf_info = swap_pattern | (width_bytes / 16) | color_pattern;
+		   surf_info |= (width_bytes / 16) | color_pattern;
 	    }
 	    OUTREG(RADEON_SURFACE0_INFO, surf_info);
 	    OUTREG(RADEON_SURFACE0_LOWER_BOUND, 0);
@@ -6393,6 +6571,9 @@
 		surf_info, 0, bufferSize - 1024);*/
 	}
     }
+
+    /* Update surface images */
+    RADEONSaveSurfaces(pScrn, &info->ModeReg);
 }
 
 #if 0
@@ -6421,35 +6602,6 @@
 }
 #endif
 
-/* restore original surface info (for fb console). */
-static void RADEONRestoreSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr restore)
-{
-    RADEONInfoPtr      info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    unsigned int surfnr;
-    
-    for ( surfnr = 0; surfnr < 8; surfnr++ ) {
-	OUTREG(RADEON_SURFACE0_INFO + 16 * surfnr, restore->surfaces[surfnr][0]);
-	OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * surfnr, restore->surfaces[surfnr][1]);
-	OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * surfnr, restore->surfaces[surfnr][2]);
-    }
-}
-
-/* save original surface info (for fb console). */
-static void RADEONSaveSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr save)
-{
-    RADEONInfoPtr      info = RADEONPTR(pScrn);
-    unsigned char *RADEONMMIO = info->MMIO;
-    unsigned int surfnr;
-    
-    for ( surfnr = 0; surfnr < 8; surfnr++ ) {
-	save->surfaces[surfnr][0] = INREG(RADEON_SURFACE0_INFO + 16 * surfnr);
-	save->surfaces[surfnr][1] = INREG(RADEON_SURFACE0_LOWER_BOUND + 16 * surfnr);
-	save->surfaces[surfnr][2] = INREG(RADEON_SURFACE0_UPPER_BOUND + 16 * surfnr);
-    }
-}
-
-
 /* Write out state to define a new video mode */
 static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore)
 {
@@ -6457,8 +6609,11 @@
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
     static RADEONSaveRec  restore0;
 
+    RADEONTRACE(("RADEONRestoreMode()\n"));
+
     /* For Non-dual head card, we don't have private field in the Entity */
     if (!info->HasCRTC2) {
+	RADEONRestoreMemMapRegisters(pScrn, restore);
 	RADEONRestoreCommonRegisters(pScrn, restore);
 	RADEONRestoreCrtcRegisters(pScrn, restore);
 	RADEONRestoreFPRegisters(pScrn, restore);
@@ -6476,10 +6631,12 @@
      * order. Regardless the order of X server issuing the calls, we
      * have to ensure we set registers in the right order!!!  Otherwise
      * we may get a blank screen.
+     *
+     * We always restore MemMap first, the saverec should be up to date
+     * in all cases
      */
     if (info->IsSecondary) {
-	if (!pRADEONEnt->RestorePrimary  && !info->IsSwitching)
-	    RADEONRestoreCommonRegisters(pScrn, restore);
+	RADEONRestoreMemMapRegisters(pScrn, restore);
 	RADEONRestoreCrtc2Registers(pScrn, restore);
 	RADEONRestorePLL2Registers(pScrn, restore);
 
@@ -6490,15 +6647,14 @@
 	if (pRADEONEnt->RestorePrimary) {
 	    pRADEONEnt->RestorePrimary = FALSE;
 
+	    RADEONRestoreCommonRegisters(pScrn, &restore0);
 	    RADEONRestoreCrtcRegisters(pScrn, &restore0);
 	    RADEONRestoreFPRegisters(pScrn, &restore0);
 	    RADEONRestorePLLRegisters(pScrn, &restore0);
 	    pRADEONEnt->IsSecondaryRestored = FALSE;
 	}
     } else {
-	if (!pRADEONEnt->IsSecondaryRestored)
-	    RADEONRestoreCommonRegisters(pScrn, restore);
-
+	RADEONRestoreMemMapRegisters(pScrn, restore);
 	if (info->MergedFB) {
 	    RADEONRestoreCrtc2Registers(pScrn, restore);
 	    RADEONRestorePLL2Registers(pScrn, restore);
@@ -6508,6 +6664,7 @@
 	    info->IsSwitching) {
 	    pRADEONEnt->IsSecondaryRestored = FALSE;
 
+	    RADEONRestoreCommonRegisters(pScrn, restore);
 	    RADEONRestoreCrtcRegisters(pScrn, restore);
 	    RADEONRestoreFPRegisters(pScrn, restore);
 	    RADEONRestorePLLRegisters(pScrn, restore);
@@ -6522,6 +6679,19 @@
 #endif
 }
 
+/* Read memory map */
+static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    save->mc_fb_location     = INREG(RADEON_MC_FB_LOCATION);
+    save->mc_agp_location    = INREG(RADEON_MC_AGP_LOCATION);
+    save->display_base_addr  = INREG(RADEON_DISPLAY_BASE_ADDR);
+    save->display2_base_addr = INREG(RADEON_DISPLAY2_BASE_ADDR);
+    save->ov0_base_addr      = INREG(RADEON_OV0_BASE_ADDR);
+}
+
 /* Read common registers */
 static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
 {
@@ -6705,6 +6875,7 @@
     RADEONInfoPtr  info = RADEONPTR(pScrn);
 
     RADEONTRACE(("RADEONSaveMode(%p)\n", save));
+    RADEONSaveMemMapRegisters(pScrn, save);
     RADEONSaveCommonRegisters(pScrn, save);
     if (info->IsSecondary) {
 	RADEONSaveCrtc2Registers(pScrn, save);
@@ -6733,6 +6904,7 @@
 
     RADEONTRACE(("RADEONSave\n"));
     if (info->FBDev) {
+	RADEONSaveMemMapRegisters(pScrn, save);
 	fbdevHWSave(pScrn);
 	return;
     }
@@ -6916,6 +7088,22 @@
     int stop_req, max_stop_req;
     float read_return_rate, time_disp1_drop_priority;
 
+    /* 
+     * Set display0/1 priority up on r3/4xx in the memory controller for 
+     * high res modes if the user specifies HIGH for displaypriority 
+     * option.
+     */
+    if ((info->DispPriority == 2) && IS_R300_VARIANT) {
+        CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER);
+	if (info->MergedFB || pRADEONEnt->HasSecondary) {
+	    mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */
+	} else {
+	    mc_init_misc_lat_timer |= 0x0100; /* display 0 only */
+	}
+	OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
+    }
+
+
     /* R420 family not supported yet */
     if (info->ChipFamily == CHIP_FAMILY_R420) return; 
 
@@ -7824,8 +8012,9 @@
 }
 
 /* Define PLL registers for requested video mode */
-static void RADEONInitPLLRegisters(RADEONInfoPtr info, RADEONSavePtr save,
-                                  RADEONPLLPtr pll, double dot_clock)
+static void RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info,
+				   RADEONSavePtr save, RADEONPLLPtr pll,
+				   double dot_clock)
 {
     unsigned long  freq = dot_clock * 100;
 
@@ -7889,8 +8078,9 @@
 }
 
 /* Define PLL2 registers for requested video mode */
-static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll,
-                                   double dot_clock, int no_odd_postdiv)
+static void RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
+				    RADEONPLLPtr pll, double dot_clock,
+				    int no_odd_postdiv)
 {
     unsigned long  freq = dot_clock * 100;
 
@@ -8018,11 +8208,12 @@
 
     info->Flags = mode->Flags;
 
+    RADEONInitMemMapRegisters(pScrn, save, info);
     RADEONInitCommonRegisters(save, info);
     if (info->IsSecondary) {
 	if (!RADEONInitCrtc2Registers(pScrn, save, mode, info))
 	    return FALSE;
-       RADEONInitPLL2Registers(save, &info->pll, dot_clock, info->DisplayType != MT_CRT);
+	RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->DisplayType != MT_CRT);
     } else if (info->MergedFB) {
         RADEONInitCommonRegisters(save, info);
         if (!RADEONInitCrtcRegisters(pScrn, save, 
@@ -8030,7 +8221,7 @@
             return FALSE;
         dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT1)->Clock / 1000.0;
         if (dot_clock) {
-            RADEONInitPLLRegisters(info, save, &info->pll, dot_clock);
+		RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock);
         } else {
             save->ppll_ref_div = info->SavedReg.ppll_ref_div;
             save->ppll_div_3   = info->SavedReg.ppll_div_3;
@@ -8039,13 +8230,13 @@
         RADEONInitCrtc2Registers(pScrn, save, 
 			((RADEONMergedDisplayModePtr)mode->Private)->CRT2, info);
         dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT2)->Clock / 1000.0;
-        RADEONInitPLL2Registers(save, &info->pll, dot_clock, info->MergeType != MT_CRT);
+        RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->MergeType != MT_CRT);
     } else {
 	if (!RADEONInitCrtcRegisters(pScrn, save, mode, info))
 	    return FALSE;
 	dot_clock = mode->Clock/1000.0;
 	if (dot_clock) {
-           RADEONInitPLLRegisters(info, save, &info->pll, dot_clock);
+		RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock);
 	} else {
 	    save->ppll_ref_div = info->SavedReg.ppll_ref_div;
 	    save->ppll_div_3   = info->SavedReg.ppll_div_3;
@@ -8081,6 +8272,8 @@
 {
     RADEONInfoPtr  info = RADEONPTR(pScrn);
 
+    RADEONTRACE(("RADEONModeInit()\n"));
+
     if (!RADEONInit(pScrn, mode, &info->ModeReg)) return FALSE;
 
     pScrn->vtSema = TRUE;
@@ -8101,6 +8294,8 @@
     ScrnInfoPtr  pScrn = xf86Screens[pScreen->myNum];
     Bool         unblank;
 
+    RADEONTRACE(("RADEONSaveScreen(%d)\n", mode));
+
     unblank = xf86IsUnblank(mode);
     if (unblank) SetTimeSinceLastInputEvent();
 
@@ -8126,6 +8321,8 @@
     }
 #endif
 
+    RADEONTRACE(("RADEONSwitchMode() !n"));
+
     if (info->allowColorTiling) {
 	if (info->MergedFB) {
 	    if ((((RADEONMergedDisplayModePtr)mode->Private)->CRT1->Flags &
@@ -8239,6 +8436,8 @@
     XF86DRISAREAPtr pSAREA;
 #endif
 
+    RADEONTRACE(("RADEONDoAdjustFrame(%d,%d,%d)\n", x, y, clone));
+
     if (info->showCache && y) {
 	        int lastline = info->FbMapSize /
 		    ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
@@ -8302,7 +8501,7 @@
     Base &= ~7;                 /* 3 lower bits are always 0 */
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled) {
+    if (info->directRenderingInited) {
 	/* note cannot use pScrn->pScreen since this is unitialized when called from
 	   RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */
         /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for
@@ -8330,11 +8529,15 @@
     }
 #endif
 
+    RADEONTRACE((" -> reg     : 0x%04x = 0x%08x\n", reg, Base));
+
     OUTREG(reg, Base);
 
     if (IS_R300_VARIANT) {
+	RADEONTRACE(("    regcntl : 0x%04x = 0x%08x\n", xytilereg, crtcxytile));
         OUTREG(xytilereg, crtcxytile);
     } else {
+	RADEONTRACE(("    regcntl : 0x%04x = 0x%08x\n", regcntl, crtcoffsetcntl));
         OUTREG(regcntl, crtcoffsetcntl);
     }
 
@@ -8398,13 +8601,13 @@
     } else
 	if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
 
-    RADEONSetFBLocation(pScrn);
     if (!info->IsSecondary)
 	RADEONRestoreSurfaces(pScrn, &info->ModeReg);
 #ifdef XF86DRI
     if (info->directRenderingEnabled) {
 	/* get the Radeon back into shape after resume */
 	RADEONDRIResume(pScrn->pScreen);
+	RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg);
     }
 #endif
     /* this will get XVideo going again, but only if XVideo was initialised
@@ -8438,7 +8641,7 @@
 
     RADEONTRACE(("RADEONLeaveVT\n"));
 #ifdef XF86DRI
-    if (RADEONPTR(pScrn)->directRenderingEnabled) {
+    if (RADEONPTR(pScrn)->directRenderingInited) {
 	DRILock(pScrn->pScreen, 0);
 	RADEONCP_STOP(pScrn, info);
     }
@@ -8453,9 +8656,9 @@
 	fbdevHWLeaveVT(scrnIndex,flags);
     }
 
-    if (!info->IsSecondary)
-	RADEONSaveSurfaces(pScrn, save);
     RADEONRestore(pScrn);
+
+    RADEONTRACE(("Ok, leaving now...\n"));
 }
 
 /* Called at the end of each server generation.  Restore the original
@@ -8469,11 +8672,17 @@
 
     RADEONTRACE(("RADEONCloseScreen\n"));
 
+    /* Mark acceleration as stopped or we might try to access the engine at
+     * wrong times, especially if we had DRI, after DRI has been stopped
+     */
+    info->accelOn = FALSE;
+
 #ifdef XF86DRI
-				/* Disable direct rendering */
+    /* Disable direct rendering */
     if (info->directRenderingEnabled) {
 	RADEONDRICloseScreen(pScreen);
 	info->directRenderingEnabled = FALSE;
+	info->directRenderingInited = FALSE;
     }
 #endif
 
@@ -8488,8 +8697,8 @@
 	RADEONDisplayPowerManagementSet(pScrn, DPMSModeOn, 0);
 	RADEONRestore(pScrn);
     }
-    RADEONUnmapMem(pScrn);
 
+    RADEONTRACE(("Disposing accel...\n"));
 #ifdef USE_EXA
     if (info->useEXA && info->accelOn)
 	exaDriverFini(pScreen);
@@ -8506,12 +8715,17 @@
     }
 #endif /* USE_XAA */
 
+    RADEONTRACE(("Disposing cusor info\n"));
     if (info->cursor) xf86DestroyCursorInfoRec(info->cursor);
     info->cursor = NULL;
 
+    RADEONTRACE(("Disposing DGA\n"));
     if (info->DGAModes) xfree(info->DGAModes);
     info->DGAModes = NULL;
 
+    RADEONTRACE(("Unmapping memory\n"));
+    RADEONUnmapMem(pScrn);
+
     pScrn->vtSema = FALSE;
 
     xf86ClearPrimInitDone(info->pEnt->index);
@@ -8649,6 +8863,8 @@
 
     if (!pScrn->vtSema) return;
 
+    RADEONTRACE(("RADEONDisplayPowerManagementSet(%d,0x%x)\n", PowerManagementMode, flags));
+
 #ifdef XF86DRI
     if (info->CPStarted) DRILock(pScrn->pScreen, 0);
 #endif
diff -urN xf86-video-ati.orig/src/radeon_reg.h xf86-video-ati/src/radeon_reg.h
--- xf86-video-ati.orig/src/radeon_reg.h	2005-09-17 17:47:51.000000000 +1000
+++ xf86-video-ati/src/radeon_reg.h	2006-01-10 17:17:06.000000000 +1100
@@ -812,6 +812,7 @@
 #define RADEON_HOST_DATA_LAST               0x17e0
 #define RADEON_HOST_PATH_CNTL               0x0130
 #       define RADEON_HDP_SOFT_RESET        (1 << 26)
+#       define RADEON_HDP_APER_CNTL         (1 << 23)
 #define RADEON_HTOTAL_CNTL                  0x0009 /* PLL */
 #define RADEON_HTOTAL2_CNTL                 0x002e /* PLL */
 
diff -urN xf86-video-ati.orig/src/radeon_render.c xf86-video-ati/src/radeon_render.c
--- xf86-video-ati.orig/src/radeon_render.c	2005-12-10 05:15:31.000000000 +1100
+++ xf86-video-ati/src/radeon_render.c	2006-01-26 00:19:45.000000000 +1100
@@ -315,29 +315,27 @@
 {
     RADEONInfoPtr info = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 swapper = info->ModeReg.surface_cntl;
+
+    swapper &= ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP |
+		 RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP);
 
     /* Set up byte swapping for the framebuffer aperture as needed */
     switch (tex_bytepp) {
     case 1:
-	OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl &
-				    ~(RADEON_NONSURF_AP0_SWP_32BPP
-				    | RADEON_NONSURF_AP0_SWP_16BPP));
 	break;
     case 2:
-	OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg.surface_cntl &
-				     ~RADEON_NONSURF_AP0_SWP_32BPP)
-				   | RADEON_NONSURF_AP0_SWP_16BPP);
+	swapper |= RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP;
 	break;
     case 4:
-	OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg.surface_cntl &
-				     ~RADEON_NONSURF_AP0_SWP_16BPP)
-				   | RADEON_NONSURF_AP0_SWP_32BPP);
+	swapper |= RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP;
 	break;
     default:
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Don't know what to do for "
 		   "tex_bytepp == %d!\n", __func__, tex_bytepp);
 	return FALSE;
     }
+    OUTREG(RADEON_SURFACE_CNTL, swapper);
     return TRUE;
 }
 
