Index: radeon.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v
retrieving revision 1.22
diff -u -r1.22 radeon.h
--- radeon.h	16 Jun 2002 20:34:13 -0000	1.22
+++ radeon.h	25 Jul 2002 20:33:17 -0000
@@ -381,6 +381,17 @@
     Bool              allowPageFlip;    /* Enable 3d page flipping */
     Bool              have3DWindows;    /* Are there any 3d clients? */
     int               drmMinor;
+   
+    Bool              driReInitKludge;  /* This enables the hack that allows
+					   DRI to terminate and re-init across
+					   VT changes.  This is temporary so
+					   that suspend to disc WITH dri/agp
+					   can work. */
+    Bool              driReInit;        /* We use this variable to indicate to
+                                           DRI init functions that we're busy
+					   with a RE-initialisation.  This
+					   variable is only honoured if
+					   driReInitKludge is TRUE. */
 
     drmSize           agpSize;
     drmHandle         agpMemHandle;     /* Handle from drmAgpAlloc */
Index: radeon_dri.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v
retrieving revision 1.27
diff -u -r1.27 radeon_dri.c
--- radeon_dri.c	24 Jun 2002 18:47:57 -0000	1.27
+++ radeon_dri.c	25 Jul 2002 20:33:19 -0000
@@ -689,8 +689,6 @@
 }
 
 
-
-
 /* Initialize the AGP state.  Request memory for use in AGP space, and
    initialize the Radeon registers to point to that memory. */
 static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen)
@@ -1565,8 +1563,16 @@
    /* Have shadow run only while there is 3d active.
     */
     if (info->allowPageFlip /*  && info->drmMinor >= 3 */) {
-       shadowSetup (pScreen);   
-       shadowAdd( pScreen, 0, RADEONDRIShadowUpdate, 0, 0, 0 );
+      /* We only do the shadow setup if this is not a DRI re-init;
+	 i.e. this is not server startup, but rather a resume from
+	 suspend to disc.  Also, if info->driReInitKludge is FALSE,
+         we don't honour info->driReInit at all; the shadow init
+         always happens. */
+      if ((!info->driReInitKludge) || (!info->driReInit))
+	{
+	  shadowSetup (pScreen);   
+	  shadowAdd( pScreen, 0, RADEONDRIShadowUpdate, 0, 0, 0 );
+	}
     }
     else
        info->allowPageFlip = 0;
Index: radeon_driver.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v
retrieving revision 1.23
diff -u -r1.23 radeon_driver.c
--- radeon_driver.c	23 Jul 2002 17:49:34 -0000	1.23
+++ radeon_driver.c	25 Jul 2002 20:33:21 -0000
@@ -68,6 +68,7 @@
 #define _XF86DRI_SERVER_
 #include "radeon_dri.h"
 #include "radeon_sarea.h"
+
 #endif
 
 #define USE_FB                  /* not until overlays */
@@ -115,6 +116,7 @@
 					    int PowerManagementMode,
 					    int flags);
 
+
 typedef enum {
     OPTION_NOACCEL,
     OPTION_SW_CURSOR,
@@ -131,6 +133,7 @@
     OPTION_BUFFER_SIZE,
     OPTION_DEPTH_MOVE,
     OPTION_PAGE_FLIP,
+    OPTION_DRI_REINIT_KLUDGE,
 #endif
     OPTION_CRT_SCREEN,
     OPTION_PANEL_SIZE,
@@ -152,6 +155,7 @@
     { OPTION_BUFFER_SIZE,  "BufferSize",       OPTV_INTEGER, {0}, FALSE },
     { OPTION_DEPTH_MOVE,   "EnableDepthMoves", OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_PAGE_FLIP, "EnablePageFlip",  OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_DRI_REINIT_KLUDGE, "driReInitKludge", OPTV_BOOLEAN, {0}, FALSE },
 #endif
     { OPTION_CRT_SCREEN,   "CrtScreen",        OPTV_BOOLEAN, {0}, FALSE},
     { OPTION_PANEL_SIZE,   "PanelSize",        OPTV_ANYSTR,  {0}, FALSE },
@@ -2001,6 +2005,21 @@
        }
     }
 
+    if ((info->driReInitKludge = xf86ReturnOptValBool(info->Options,
+						      OPTION_DRI_REINIT_KLUDGE,
+						      FALSE))) {
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "driReInitKludge enabled [EXPERIMENTAL, DANGEROUS]\n");
+    } else {
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "driReInitKludge not enabled\n");
+    }
+
+    /* this gets called before RADEONDRIScreenInit and RADEONDRIFinishScreenInit
+       get called the first time; so we can set info->driReInit and the functions
+       will know that they don't have to be careful with the shadow init.  When
+       EnterVT is called, info->driReinit will be set to TRUE.  This variable is
+       ignored throughout if driReInitKludge is FALSE (default). */
+    info->driReInit = FALSE;
+
 
     return TRUE;
 }
@@ -4435,6 +4454,33 @@
 
     RADEONTRACE(("RADEONEnterVT\n"));
 
+#ifdef XF86DRI
+    if (info->directRenderingEnabled && 
+	info->driReInitKludge && (!info->have3DWindows)) {
+      /* we only do this kludge if direct rendering is on, the kludge has
+	 been explicitly activated, and we've come back from a VT switch
+	 that had NO 3d clients */
+
+      /* this is so that the following two init functions know this is a
+	 re-init */
+      info->driReInit = TRUE;
+
+      if (RADEONDRIScreenInit(pScrn->pScreen) &&
+	  RADEONDRIFinishScreenInit(pScrn->pScreen))
+	{
+	  xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+		     "Direct rendering enabled after VT switch\n");
+	}
+      else
+	{
+	  xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+		     "Direct rendering disabled after VT switch.  DANGER!\n");
+	}
+
+      info->driReInit = FALSE;
+    }
+#endif
+
     if (info->FBDev) {
 	unsigned char *RADEONMMIO = info->MMIO;
         if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE;
@@ -4444,19 +4490,26 @@
         if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
 
     if (info->accelOn)
-	RADEONEngineRestore(pScrn);
+      RADEONEngineRestore(pScrn);
 
 #ifdef XF86DRI
-    if (info->directRenderingEnabled) {
-	/* This seems to fix that !@#$ irritating switch to VT and back X-freeze
-	 * that has been plaguing some DRI users.  It seems that bus mastering
-	 * is turned off on the video card when one switches to a VT and this
-	 * needs to be reactivated when we get back, else things just stop. :)
-	 * Charl P. Botha <http://cpbotha.net/> */
-	xf86EnablePciBusMaster(info->PciInfo, TRUE);
+    if (info->directRenderingEnabled && 
+	(info->have3DWindows || (!info->driReInitKludge))) {
+      /* We do the normal DRI restart if direct rendering is enabled and
+	 (we're not kludging OR we had 3d windows when we switched to VT),
+	 i.e. even if a kludge has been requested and there were 3d windows
+	 running at the time of the VT switch, we could NOT perform the kludge.
+      */
+
+      /* This seems to fix that !@#$ irritating switch to VT and back X-freeze
+       * that has been plaguing some DRI users.  It seems that bus mastering
+       * is turned off on the video card when one switches to a VT and this
+       * needs to be reactivated when we get back, else things just stop. :)
+       * Charl P. Botha <http://cpbotha.net/> */
+      xf86EnablePciBusMaster(info->PciInfo, TRUE);
 
-	RADEONCP_START(pScrn, info);
-	DRIUnlock(pScrn->pScreen);
+      RADEONCP_START(pScrn, info);
+      DRIUnlock(pScrn->pScreen);
     }
 #endif
 
@@ -4474,9 +4527,16 @@
 
     RADEONTRACE(("RADEONLeaveVT\n"));
 #ifdef XF86DRI
-    if (RADEONPTR(pScrn)->directRenderingEnabled) {
-	DRILock(pScrn->pScreen, 0);
-	RADEONCP_STOP(pScrn, info);
+    if (info->directRenderingEnabled) {
+      if (info->driReInitKludge && (!info->have3DWindows))
+	{
+	  RADEONDRICloseScreen(pScrn->pScreen);
+	}
+      else
+	{
+	  DRILock(pScrn->pScreen, 0);
+	  RADEONCP_STOP(pScrn, info);
+	}
     }
 #endif
 
