#! /bin/sh -e

if [ $# -eq 3 -a "$2" = '-d' ]; then
    pdir="-d $3"
elif [ $# -ne 1 ]; then
    echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
    exit 1
fi
case "$1" in
    -patch) patch $pdir -f --no-backup-if-mismatch -p1 < $0;;
    -unpatch) patch $pdir -f --no-backup-if-mismatch -R -p1 < $0;;
    *)
	echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
	exit 1
esac
exit 0

--- xc/programs/Xserver/hw/xfree86/drivers/ati/aticonsole.c
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/aticonsole.c
@@ -26,6 +26,7 @@
  */
 
 #include "ati.h"
+#include "atidri.h"
 #include "atiadapter.h"
 #include "aticonsole.h"
 #include "aticrtc.h"
@@ -307,6 +308,8 @@
 
         if (pATI->directRenderingEnabled) 
         {
+            /* get the Mach64 back into shape after resume */
+            ATIDRIResume(pScreen);
             DRIUnlock(pScreen);
         }
 
@@ -342,6 +345,8 @@
 
     if (pATI->directRenderingEnabled) 
     {
+        /* get the Mach64 back into shape after resume */
+        ATIDRIResume(pScreen);
         DRIUnlock(pScreen);
     }
 
--- xc/programs/Xserver/hw/xfree86/drivers/ati/atidri.c
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/atidri.c
@@ -634,34 +634,15 @@
     return bits;
 }
 
-/* Initialize the AGP state.  Request memory for use in AGP space, and
- * initialize the Rage Pro registers to point to that memory.
- */
-static Bool ATIDRIAgpInit( ScreenPtr pScreen )
+static Bool ATIDRISetAgpMode( ScreenPtr pScreen )
 {
    ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
    ATIPtr pATI = ATIPTR(pScreenInfo);
    ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
 
-   unsigned long mode;
-   unsigned int  vendor, device;
-   int ret;
-   unsigned long cntl;
-   int s, l;
-
-   pATIDRIServer->agpSize = ATI_DEFAULT_AGP_SIZE;
-   pATIDRIServer->agpMode = ATI_DEFAULT_AGP_MODE;
-   pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
-   pATIDRIServer->ringSize = 16; /* 16 kB ring */
-
-   if ( drmAgpAcquire( pATI->drmFD ) < 0 ) {
-      xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP not available\n" );
-      return FALSE;
-   }
-
-   mode   = drmAgpGetMode( pATI->drmFD );        /* Default mode */
-   vendor = drmAgpVendorId( pATI->drmFD );
-   device = drmAgpDeviceId( pATI->drmFD );
+   unsigned long mode   = drmAgpGetMode( pATI->drmFD );        /* Default mode */
+   unsigned int vendor = drmAgpVendorId( pATI->drmFD );
+   unsigned int device = drmAgpDeviceId( pATI->drmFD );
 
    if (pATI->OptionAGPMode > 0 && pATI->OptionAGPMode <= ATI_AGP_MAX_MODE) {
       pATIDRIServer->agpMode = pATI->OptionAGPMode;
@@ -723,6 +704,35 @@
       return FALSE;
    }
 
+   return TRUE;
+}
+
+/* Initialize the AGP state.  Request memory for use in AGP space, and
+ * initialize the Rage Pro registers to point to that memory.
+ */
+static Bool ATIDRIAgpInit( ScreenPtr pScreen )
+{
+   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+   ATIPtr pATI = ATIPTR(pScreenInfo);
+   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
+
+   int ret;
+   unsigned long cntl;
+   int s, l;
+
+   pATIDRIServer->agpSize = ATI_DEFAULT_AGP_SIZE;
+   pATIDRIServer->agpMode = ATI_DEFAULT_AGP_MODE;
+   pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
+   pATIDRIServer->ringSize = 16; /* 16 kB ring */
+
+   if ( drmAgpAcquire( pATI->drmFD ) < 0 ) {
+      xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP not available\n" );
+      return FALSE;
+   }
+
+   if (!ATIDRISetAgpMode( pScreen ))
+      return FALSE;
+
    pATIDRIServer->agpOffset = 0;
 
    ret = drmAgpAlloc( pATI->drmFD, pATIDRIServer->agpSize*1024*1024,
@@ -1423,6 +1433,35 @@
    return TRUE;
 }
 
+/*
+ * This function will attempt to get the Mach64 hardware back into shape
+ * after a resume from disc. Its an extract from ATIDRIAgpInit and ATIDRIFinishScreenInit
+ * This also calls a new ioctl in the mach64 DRM that in its turn is
+ * an extraction of the hardware-affecting bits from mach64_do_init_drm()
+ * (see atidrm.c)
+ * I am assuming here that pATI->pDRIServerInfo doesn't change
+ * elsewhere in incomaptible ways.
+ * How will this code react to resuming after a failed resumeor pci based dri ?
+ */
+void ATIDRIResume( ScreenPtr pScreen )
+{
+   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+   ATIPtr pATI = ATIPTR(pScreenInfo);
+   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
+
+   int ret;
+
+   xf86DrvMsg( pScreen->myNum, X_INFO,
+		 "[RESUME] Attempting to re-init Mach64 hardware.\n");
+
+   if (!pATIDRIServer->IsPCI) {
+      if (!ATIDRISetAgpMode(pScreen))
+      return;
+
+      outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
+   }
+}
+
 /* The screen is being closed, so clean up any state and free any
  * resources used by the DRI.
  */
--- xc/programs/Xserver/hw/xfree86/drivers/ati/atidri.h
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/atidri.h
@@ -40,6 +40,11 @@
 
 #define ATI_AGP_MAX_MODE	 2
 
+/* Imported from the radeon suspend code writen by cpbotha@ieee.org
+ * to enable suspend/resume support for the mach64 card.
+ */
+extern void ATIDRIResume           FunctionPrototype((ScreenPtr pScreen));
+
 extern Bool ATIDRIScreenInit       FunctionPrototype((ScreenPtr));
 extern Bool ATIDRIFinishScreenInit FunctionPrototype((ScreenPtr));
 extern void ATIDRICloseScreen      FunctionPrototype((ScreenPtr));
