Dear list,

Attached please find a patch to the DRI CVS that enables suspending to and
resuming from disc with running DRI clients (3D Windows, ao).  This is
different from the reinit solution that Michel D�nzer and I have proposed
and which Michel has refined: it allows suspending/resuming with active 3D
windows.  I have tested this with the venerable glxgears at 1000 FPS (24bpp
display depth, no page flipping).

This patch simply (ha ha) tries to re-initialise the only the Radeon
hardware after a resume.  At the moment, I invoke the new code from
RADEONEnterVT() as it's idempotent during normal operation (I think).

I would appreciate your review.  I'm going to do more testing and
refinement as soon as I have more time.  This week is filled with
RealLife(tm).

Thanks,
Charl

-- 
charl p. botha http://cpbotha.net/ http://visualisation.tudelft.nl/
Index: drivers/ati/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
--- drivers/ati/radeon.h        16 Jun 2002 20:34:13 -0000      1.22
+++ drivers/ati/radeon.h        19 Aug 2002 22:30:11 -0000
@@ -502,6 +502,7 @@
 #ifdef XF86DRI
 extern Bool        RADEONDRIScreenInit(ScreenPtr pScreen);
 extern void        RADEONDRICloseScreen(ScreenPtr pScreen);
+extern void        RADEONDRIResume(ScreenPtr pScreen);
 extern Bool        RADEONDRIFinishScreenInit(ScreenPtr pScreen);
 
 extern drmBufPtr   RADEONCPGetBuffer(ScrnInfoPtr pScrn);
@@ -539,6 +540,17 @@
        }                                                               \
     }                                                                  \
 } while (0)
+
+/* added by Charl P. Botha <http://cpbotha.net/> */
+#define RADEONCP_RESUME(pScrn, info)                                   \
+do {                                                                   \
+    int _ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_RESUME);      \
+    if (_ret) {                                                        \
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,                   \
+                  "%s: CP resume %d\n", __FUNCTION__, _ret);   \
+    }                                                          \
+} while (0)
+
 
 #define RADEONCP_REFRESH(pScrn, info)                                  \
 do {                                                                   \
Index: drivers/ati/radeon_common.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v
retrieving revision 1.4
diff -u -r1.4 radeon_common.h
--- drivers/ati/radeon_common.h 11 Jul 2002 20:31:11 -0000      1.4
+++ drivers/ati/radeon_common.h 19 Aug 2002 22:30:12 -0000
@@ -65,6 +65,7 @@
 #define DRM_RADEON_CMDBUF                 0x10
 #define DRM_RADEON_GETPARAM               0x11
 #define DRM_RADEON_FLIP                   0x12
+#define DRM_RADEON_CP_RESUME              0x13
 #define DRM_RADEON_MAX_DRM_COMMAND_INDEX  0x39
 
 
Index: drivers/ati/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
--- drivers/ati/radeon_dri.c    24 Jun 2002 18:47:57 -0000      1.27
+++ drivers/ati/radeon_dri.c    19 Aug 2002 22:30:13 -0000
@@ -1574,6 +1574,77 @@
     return TRUE;
 }
 
+/**
+ * This function will attempt to get the Radeon hardware back into shape
+ * after a resume from disc.  Basically, it's an extract of all hardware-
+ * affecting code from RADEONDRIScreenInit() and RADEONDRIFinishScreenInit()
+ * including a new ioctl in the radeon DRM that in its turn is an extraction
+ * of the hardware-affecting bits from radeon_do_init_cp() (see radeon_cp.c)
+ *
+ * Charl P. Botha <http://cpbotha.net>
+ */
+void RADEONDRIResume(ScreenPtr pScreen)
+{
+    unsigned long mode;
+    ScrnInfoPtr   pScrn   = xf86Screens[pScreen->myNum];
+    RADEONInfoPtr info    = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    xf86DrvMsg(pScreen->myNum, X_INFO,
+              "[RESUME] Attempting to re-init Radeon hardware.\n");
+    
+    
+    /* Following bits from RADEONDRIAgpInit() */
+    /* -------------------------------------- */
+
+    mode   = drmAgpGetMode(info->drmFD);       /* Default mode */
+
+    mode &= ~RADEON_AGP_MODE_MASK;
+    switch (info->agpMode) {
+    case 4:          mode |= RADEON_AGP_4X_MODE;
+    case 2:          mode |= RADEON_AGP_2X_MODE;
+    case 1: default: mode |= RADEON_AGP_1X_MODE;
+    }
+
+    xf86DrvMsg(pScreen->myNum, X_INFO,
+               "[agp] Mode 0x%08lx [Card 0x%04x/0x%04x]\n",
+               mode,
+               info->PciInfo->vendor,
+               info->PciInfo->chipType);
+
+    if (drmAgpEnable(info->drmFD, mode) < 0) {
+       xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n");
+       drmAgpRelease(info->drmFD);
+       return;
+    }
+
+    /* Ring buffer is at AGP offset 0 - from RADEONAgpInit() */
+    OUTREG(RADEON_AGP_BASE, info->ringHandle);
+
+    /* enable bus-mastering - we do this here bacause RADEONAgpInit() does it.
+     * The bus-mastering fix does this in RADEONEnterVT() as well, leave that!
+     */
+    xf86EnablePciBusMaster(info->PciInfo, TRUE);
+
+    /* Following bits from RADEONDRIFinishScreenInit() */
+    /* ----------------------------------------------- */
+    
+    /* this will make the IOCTL call we've added to try and re-tickle the 
+     * radeon chip in all the right places - similar to what the 
+     * DRM_RADEON_CP_INIT ioctl does in RADEONDRIKernelInit()
+     */
+    RADEONCP_RESUME(pScrn, info);
+
+    /* DRM_RADEON_CP_RESUME does an engine reset, which resets some engine
+       registers back to their default values, so we need to restore
+       those engine register here. - from RADEONDRIKernelInit() that's called by
+       RADEONDRIFinishScreenInit() */
+    RADEONEngineRestore(pScrn);
+
+    /* Initialize and start the CP if required - from RADEONDRIFinishScreenInit() */
+    RADEONDRICPInit(pScrn);
+}
+
 /* The screen is being closed, so clean up any state and free any
    resources used by the DRI. */
 void RADEONDRICloseScreen(ScreenPtr pScreen)
Index: drivers/ati/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
--- drivers/ati/radeon_driver.c 23 Jul 2002 17:49:34 -0000      1.23
+++ drivers/ati/radeon_driver.c 19 Aug 2002 22:30:16 -0000
@@ -4443,6 +4443,13 @@
     } else
         if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
 
+#ifdef XF86DRI
+    if (info->directRenderingEnabled) {
+       /* test the resume code here, he he he */
+       RADEONDRIResume(pScrn->pScreen);
+    }
+#endif
+
     if (info->accelOn)
        RADEONEngineRestore(pScrn);
 
Index: os-support/shared/drm/kernel/radeon.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon.h,v
retrieving revision 1.3
diff -u -r1.3 radeon.h
--- os-support/shared/drm/kernel/radeon.h       14 Jul 2002 20:26:52 -0000      1.3
+++ os-support/shared/drm/kernel/radeon.h       19 Aug 2002 22:30:17 -0000
@@ -71,6 +71,7 @@
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)]    = { radeon_cp_stop,     1, 1 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)]   = { radeon_cp_reset,    1, 1 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)]    = { radeon_cp_idle,     1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESUME)]  = { radeon_cp_resume,   1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)]    = { radeon_engine_reset,  1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen,  1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)]       = { radeon_cp_swap,     1, 0 }, \
Index: os-support/shared/drm/kernel/radeon_cp.c
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_cp.c,v
retrieving revision 1.4
diff -u -r1.4 radeon_cp.c
--- os-support/shared/drm/kernel/radeon_cp.c    11 Aug 2002 15:56:43 -0000      1.4
+++ os-support/shared/drm/kernel/radeon_cp.c    19 Aug 2002 22:30:18 -0000
@@ -695,6 +695,135 @@
                       RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
 }
 
+/* This is called by radeon_do_resume_cp and is based on radeon_cp_init_ring_buffer()
+ * Err, so far, this hasn't changed much from radeon_cp_resume_ring_buffer.
+ *
+ * Charl P. Botha <http://cpbotha.net>
+ */
+static void radeon_cp_resume_ring_buffer( drm_device_t *dev,
+                                       drm_radeon_private_t *dev_priv )
+{
+       u32 ring_start, cur_read_ptr;
+       u32 tmp;
+
+       /* Initialize the memory controller */
+       RADEON_WRITE( RADEON_MC_FB_LOCATION,
+                     (dev_priv->agp_vm_start - 1) & 0xffff0000 );
+
+       if ( !dev_priv->is_pci ) {
+               RADEON_WRITE( RADEON_MC_AGP_LOCATION,
+                             (((dev_priv->agp_vm_start - 1 +
+                                dev_priv->agp_size) & 0xffff0000) |
+                              (dev_priv->agp_vm_start >> 16)) );
+       }
+
+#if __REALLY_HAVE_AGP
+       if ( !dev_priv->is_pci )
+               ring_start = (dev_priv->cp_ring->offset
+                             - dev->agp->base
+                             + dev_priv->agp_vm_start);
+       else
+#endif
+               ring_start = (dev_priv->cp_ring->offset
+                             - dev->sg->handle
+                             + dev_priv->agp_vm_start);
+
+       RADEON_WRITE( RADEON_CP_RB_BASE, ring_start );
+
+       /* Set the write pointer delay */
+       RADEON_WRITE( RADEON_CP_RB_WPTR_DELAY, 0 );
+
+       /* Initialize the ring buffer's read and write pointers */
+       cur_read_ptr = RADEON_READ( RADEON_CP_RB_RPTR );
+       RADEON_WRITE( RADEON_CP_RB_WPTR, cur_read_ptr );
+       *dev_priv->ring.head = cur_read_ptr;
+       dev_priv->ring.tail = cur_read_ptr;
+
+       if ( !dev_priv->is_pci ) {
+               RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+                             dev_priv->ring_rptr->offset );
+       } else {
+               drm_sg_mem_t *entry = dev->sg;
+               unsigned long tmp_ofs, page_ofs;
+
+               tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
+               page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+               RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+                            entry->busaddr[page_ofs]);
+               DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
+                          entry->busaddr[page_ofs],
+                          entry->handle + tmp_ofs );
+       }
+
+       /* Initialize the scratch register pointer.  This will cause
+        * the scratch register values to be written out to memory
+        * whenever they are updated.
+        *
+        * We simply put this behind the ring read pointer, this works
+        * with PCI GART as well as (whatever kind of) AGP GART
+        */
+       RADEON_WRITE( RADEON_SCRATCH_ADDR, RADEON_READ( RADEON_CP_RB_RPTR_ADDR )
+                                        + RADEON_SCRATCH_REG_OFFSET );
+
+       dev_priv->scratch = ((__volatile__ u32 *)
+                            dev_priv->ring.head +
+                            (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+
+       RADEON_WRITE( RADEON_SCRATCH_UMSK, 0x7 );
+
+       /* Writeback doesn't seem to work everywhere, test it first */
+       DRM_WRITE32( &dev_priv->scratch[1], 0 );
+       RADEON_WRITE( RADEON_SCRATCH_REG1, 0xdeadbeef );
+
+       for ( tmp = 0 ; tmp < dev_priv->usec_timeout ; tmp++ ) {
+               if ( DRM_READ32( &dev_priv->scratch[1] ) == 0xdeadbeef )
+                       break;
+               DRM_UDELAY( 1 );
+       }
+
+       if ( tmp < dev_priv->usec_timeout ) {
+               dev_priv->writeback_works = TRUE;
+               DRM_DEBUG( "writeback test succeeded, tmp=%d\n", tmp );
+       } else {
+               dev_priv->writeback_works = FALSE;
+               DRM_DEBUG( "writeback test failed\n" );
+       }
+
+       dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
+       RADEON_WRITE( RADEON_LAST_FRAME_REG,
+                     dev_priv->sarea_priv->last_frame );
+
+       dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
+       RADEON_WRITE( RADEON_LAST_DISPATCH_REG,
+                     dev_priv->sarea_priv->last_dispatch );
+
+       dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
+       RADEON_WRITE( RADEON_LAST_CLEAR_REG,
+                     dev_priv->sarea_priv->last_clear );
+
+       /* Set ring buffer size */
+#ifdef __BIG_ENDIAN
+       RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw | 
+RADEON_BUF_SWAP_32BIT );
+#else
+       RADEON_WRITE( RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw );
+#endif
+
+       radeon_do_wait_for_idle( dev_priv );
+
+       /* Turn on bus mastering */
+       tmp = RADEON_READ( RADEON_BUS_CNTL ) & ~RADEON_BUS_MASTER_DIS;
+       RADEON_WRITE( RADEON_BUS_CNTL, tmp );
+
+       /* Sync everything up */
+       RADEON_WRITE( RADEON_ISYNC_CNTL,
+                     (RADEON_ISYNC_ANY2D_IDLE3D |
+                      RADEON_ISYNC_ANY3D_IDLE2D |
+                      RADEON_ISYNC_WAIT_IDLEGUI |
+                      RADEON_ISYNC_CPSCRATCH_IDLEGUI) );
+}
+
+
 static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 {
        drm_radeon_private_t *dev_priv;
@@ -1019,6 +1148,198 @@
        return 0;
 }
 
+/* This code will reinit the Radeon CP hardware after a resume from disc.  
+ * AFAIK, it would be very difficult to pickle the state at suspend time, so 
+ * here we make sure that all Radeon hardware initialisation is re-done without
+ * affecting running applications.  This function is called radeon_do_resume_cp()
+ * as it was derived from radeon_init_cp, where most of the initialisation takes
+ * place during DRI init.
+ *
+ * This patch is NOT to be confused with my and Michel Daenzer's earlier DRI
+ * reinit work, which de- and re-initialised the complete DRI at every VT
+ * switch.
+ *
+ * Charl P. Botha <http://cpbotha.net>
+ */
+static int radeon_do_resume_cp( drm_device_t *dev)
+{
+       drm_radeon_private_t *dev_priv;
+       u32 tmp;
+       DRM_DEBUG( "\n" );
+       
+       DRM_DEBUG("Starting radeon_do_resume_cp()\n");
+
+       /* get the existing dev_private */
+       dev_priv = dev->dev_private;
+
+#if !defined(PCIGART_ENABLED)
+       /* PCI support is not 100% working, so we disable it here.
+        */
+       if ( dev_priv->is_pci ) {
+               DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
+               radeon_do_cleanup_cp(dev);
+               return DRM_ERR(EINVAL);
+       }
+#endif
+
+       if ( dev_priv->is_pci && !dev->sg ) {
+               DRM_ERROR( "PCI GART memory not allocated!\n" );
+               radeon_do_cleanup_cp(dev);
+               return DRM_ERR(EINVAL);
+       }
+
+       if ( dev_priv->usec_timeout < 1 ||
+            dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
+               DRM_DEBUG( "TIMEOUT problem!\n" );
+               radeon_do_cleanup_cp(dev);
+               return DRM_ERR(EINVAL);
+       }
+
+       /* Simple idle check.
+        */
+       /*atomic_set( &dev_priv->idle_count, 0 ); */
+
+       if(!dev_priv->sarea) {
+               DRM_ERROR("could not find sarea!\n");
+               radeon_do_cleanup_cp(dev);
+               return DRM_ERR(EINVAL);
+       }
+
+       if(!dev_priv->fb) {
+               DRM_ERROR("could not find framebuffer!\n");
+               radeon_do_cleanup_cp(dev);
+               return DRM_ERR(EINVAL);
+       }
+
+       if(!dev_priv->mmio) {
+               DRM_ERROR("could not find mmio region!\n");
+               radeon_do_cleanup_cp(dev);
+               return DRM_ERR(EINVAL);
+       }
+
+       if(!dev_priv->cp_ring) {
+               DRM_ERROR("could not find cp ring region!\n");
+               radeon_do_cleanup_cp(dev);
+               return DRM_ERR(EINVAL);
+       }
+
+       if(!dev_priv->ring_rptr) {
+               DRM_ERROR("could not find ring read pointer!\n");
+               radeon_do_cleanup_cp(dev);
+               return DRM_ERR(EINVAL);
+       }
+
+       if(!dev_priv->buffers) {
+               DRM_ERROR("could not find dma buffer region!\n");
+               radeon_do_cleanup_cp(dev);
+               return DRM_ERR(EINVAL);
+       }
+
+       if ( !dev_priv->is_pci ) {
+               if(!dev_priv->agp_textures) {
+                       DRM_ERROR("could not find agp texture region!\n");
+                       radeon_do_cleanup_cp(dev);
+                       return DRM_ERR(EINVAL);
+               }
+       }
+
+       if ( !dev_priv->is_pci ) {
+/*             DRM_IOREMAP( dev_priv->cp_ring );
+               DRM_IOREMAP( dev_priv->ring_rptr );
+               DRM_IOREMAP( dev_priv->buffers ); */
+               if(!dev_priv->cp_ring->handle ||
+                  !dev_priv->ring_rptr->handle ||
+                  !dev_priv->buffers->handle) {
+                       DRM_ERROR("could not find ioremap agp regions!\n");
+                       radeon_do_cleanup_cp(dev);
+                       return DRM_ERR(EINVAL);
+               }
+       } else {
+/*             dev_priv->cp_ring->handle =
+                       (void *)dev_priv->cp_ring->offset;
+               dev_priv->ring_rptr->handle =
+                       (void *)dev_priv->ring_rptr->offset;
+               dev_priv->buffers->handle = (void *)dev_priv->buffers->offset; */
+
+               DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
+                          dev_priv->cp_ring->handle );
+               DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
+                          dev_priv->ring_rptr->handle );
+               DRM_DEBUG( "dev_priv->buffers->handle %p\n",
+                          dev_priv->buffers->handle );
+       }
+
+
+/*         dev_priv->agp_vm_start = RADEON_READ( RADEON_CONFIG_APER_SIZE );   */
+/* #if __REALLY_HAVE_AGP                                                      */
+/*         if ( !dev_priv->is_pci )                                           */
+/*                 dev_priv->agp_buffers_offset = (dev_priv->buffers->offset  */
+/*                                                 - dev->agp->base           */
+/*                                                 + dev_priv->agp_vm_start); */
+/*         else                                                               */
+/* #endif                                                                     */
+/*                 dev_priv->agp_buffers_offset = (dev_priv->buffers->offset  */
+/*                                                 - dev->sg->handle          */
+/*                                                 + dev_priv->agp_vm_start); */
+/*                                                                            */
+       DRM_DEBUG( "dev_priv->agp_size %d\n",
+                  dev_priv->agp_size );
+       DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n",
+                  dev_priv->agp_vm_start );
+       DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n",
+                  dev_priv->agp_buffers_offset );
+
+#if __REALLY_HAVE_SG
+       if ( dev_priv->is_pci ) {
+           /* I'm not so sure about this ati_picgart_init after at resume-time... */
+/*                 if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart, */
+/*                                             &dev_priv->bus_pci_gart)) {    */
+/*                         DRM_ERROR( "failed to init PCI GART!\n" );         */
+/*                         dev->dev_private = (void *)dev_priv;               */
+/*                         radeon_do_cleanup_cp(dev);                         */
+/*                         return DRM_ERR(ENOMEM);                            */
+/*                 }                                                          */
+
+               tmp = RADEON_READ( RADEON_AIC_CNTL )
+                     | RADEON_PCIGART_TRANSLATE_EN;
+               RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+
+               /* set PCI GART page-table base address
+                */
+               RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
+
+               /* set address range for PCI address translate
+                */
+               RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start );
+               RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start
+                                                 + dev_priv->agp_size - 1);
+
+               /* Turn off AGP aperture -- is this required for PCIGART?
+                */
+               RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
+               RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
+       } else {
+#endif /* __REALLY_HAVE_SG */
+               /* Turn off PCI GART
+                */
+               tmp = RADEON_READ( RADEON_AIC_CNTL )
+                     & ~RADEON_PCIGART_TRANSLATE_EN;
+               RADEON_WRITE( RADEON_AIC_CNTL, tmp );
+#if __REALLY_HAVE_SG
+       }
+#endif /* __REALLY_HAVE_SG */
+
+       radeon_cp_load_microcode( dev_priv );
+       radeon_cp_resume_ring_buffer( dev, dev_priv );
+
+       dev_priv->last_buf = 0;
+
+       radeon_do_engine_reset( dev );
+
+       return 0;
+}
+
+
 int radeon_cp_init( DRM_IOCTL_ARGS )
 {
        DRM_DEVICE;
@@ -1134,6 +1455,16 @@
 
        return radeon_do_cp_idle( dev_priv );
 }
+
+/* Added by Charl P. Botha to call radeon_do_resume_cp().
+ */
+int radeon_cp_resume( DRM_IOCTL_ARGS )
+{
+       DRM_DEVICE;
+
+       return radeon_do_resume_cp(dev);
+}
+
 
 int radeon_engine_reset( DRM_IOCTL_ARGS )
 {
Index: os-support/shared/drm/kernel/radeon_drm.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h,v
retrieving revision 1.3
diff -u -r1.3 radeon_drm.h
--- os-support/shared/drm/kernel/radeon_drm.h   11 Jul 2002 20:31:12 -0000      1.3
+++ os-support/shared/drm/kernel/radeon_drm.h   19 Aug 2002 22:30:19 -0000
@@ -323,6 +323,8 @@
 #define DRM_IOCTL_RADEON_CMDBUF     DRM_IOW( 0x50, drm_radeon_cmd_buffer_t)
 #define DRM_IOCTL_RADEON_GETPARAM   DRM_IOWR(0x51, drm_radeon_getparam_t)
 #define DRM_IOCTL_RADEON_FLIP      DRM_IO(  0x52)
+/* added by Charl P. Botha - see radeon_cp.c for details */
+#define DRM_IOCTL_RADEON_CP_RESUME  DRM_IO(0x53)
 
 typedef struct drm_radeon_init {
        enum {
Index: os-support/shared/drm/kernel/radeon_drv.h
===================================================================
RCS file: 
/cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h,v
retrieving revision 1.3
diff -u -r1.3 radeon_drv.h
--- os-support/shared/drm/kernel/radeon_drv.h   11 Aug 2002 15:56:43 -0000      1.3
+++ os-support/shared/drm/kernel/radeon_drv.h   19 Aug 2002 22:30:19 -0000
@@ -125,6 +125,7 @@
 extern int radeon_cp_stop( DRM_IOCTL_ARGS );
 extern int radeon_cp_reset( DRM_IOCTL_ARGS );
 extern int radeon_cp_idle( DRM_IOCTL_ARGS );
+extern int radeon_cp_resume( DRM_IOCTL_ARGS );
 extern int radeon_engine_reset( DRM_IOCTL_ARGS );
 extern int radeon_fullscreen( DRM_IOCTL_ARGS );
 extern int radeon_cp_buffers( DRM_IOCTL_ARGS );

Reply via email to