On Sat, 2002-09-21 at 07:21, Michel Dänzer wrote:
> On Fre, 2002-09-20 at 17:30, Andreas Stenglein wrote: 
> > I tried to port Andreas Ehliar's mga-stereo-patch
> > (http://www.lysator.liu.se/~ehliar/3d/)
> > to current DRI-CVS.
> > 
> > I think its almost done, but now the big problem for me
> > (as a "non-dri-developer")
> > is to get the vblank-irq and the pageflipping working
> > without locking up the machine. (file mga_dma.c)
> > The old mga-drm-driver was irq-driven and so the
> > additional vblank-irq-handling has been hooked
> > into the main irq-handler.
> > But this infrastructure isnt there anymore.
> 
> You may want to look at the radeon IRQ code on r200-0-2-branch and
> 
> http://penguinppc.org/~daenzer/DRI/radeon-vblank.diff
> 
> Let me know what you think about the interface in that patch, would be
> great if we could make this a template.

Here's the patch with FreeBSD and r200 added (partially).  I've removed
the bottom half from the irq handler in the FreeBSD case -- wakeups and
a lot more can go in the top half in BSD just fine from what I've been
told.  Would anything else ever get added to the handler (for vbl or
other irq)?  The r200 client lib doesn't check for the irq number, but I
couldn't figure out what exactly that was being checked for.  Also, it
seems the driver init macros should be functions.  Is there any reason
why they aren't?

375 frames in 5.0 seconds = 75.000 FPS
375 frames in 5.0 seconds = 75.000 FPS
375 frames in 5.0 seconds = 75.000 FPS

  PID USERNAME PRI NICE  SIZE    RES STATE  C   TIME   WCPU    CPU COMMAND
  269 root      22   0 80040K  5584K rdnvbl 0   0:54  4.93%  4.93% glxgears

-- 
Eric Anholt <[EMAIL PROTECTED]>
http://people.freebsd.org/~anholt/dri/

Index: lib/GL/mesa/src/drv/r200/r200_context.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r200/r200_context.c,v
retrieving revision 1.2.2.5
diff -u -r1.2.2.5 r200_context.c
--- lib/GL/mesa/src/drv/r200/r200_context.c	19 Sep 2002 10:05:37 -0000	1.2.2.5
+++ lib/GL/mesa/src/drv/r200/r200_context.c	23 Sep 2002 03:20:40 -0000
@@ -373,6 +373,10 @@
    ctx->Const.MaxLineWidthAA = 10.0;
    ctx->Const.LineWidthGranularity = 0.0625;
 
+   if (getenv("R200_THROTTLE_REFRESH"))
+      rmesa->vblwait_enabled = 1;
+   else
+      rmesa->vblwait_enabled = 0;
 
    /* Initialize the software rasterizer and helper modules.
     */
@@ -529,6 +533,9 @@
       ctx = rmesa->glCtx;
       if (ctx->Visual.doubleBufferMode) {
          _mesa_swapbuffers( ctx );  /* flush pending rendering comands */
+	 if ( /* rmesa->r200Screen->irq && */ rmesa->vblwait_enabled ) {
+            r200WaitForVBlank( rmesa );
+	 }
          if ( rmesa->doPageFlip ) {
             r200PageFlip( dPriv );
          }
Index: lib/GL/mesa/src/drv/r200/r200_context.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r200/r200_context.h,v
retrieving revision 1.2.2.2
diff -u -r1.2.2.2 r200_context.h
--- lib/GL/mesa/src/drv/r200/r200_context.h	30 Aug 2002 11:05:42 -0000	1.2.2.2
+++ lib/GL/mesa/src/drv/r200/r200_context.h	23 Sep 2002 03:20:41 -0000
@@ -825,6 +825,11 @@
    GLuint TexGenCompSel;
    GLmatrix tmpmat;
 
+   /* VBlank sequence number
+    */
+   unsigned int vbl_seq;
+   int vblwait_enabled; 
+
    /* r200_tcl.c
     */
    struct r200_tcl_info tcl;
Index: lib/GL/mesa/src/drv/r200/r200_ioctl.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r200/r200_ioctl.c,v
retrieving revision 1.2.2.5
diff -u -r1.2.2.5 r200_ioctl.c
--- lib/GL/mesa/src/drv/r200/r200_ioctl.c	20 Sep 2002 21:39:00 -0000	1.2.2.5
+++ lib/GL/mesa/src/drv/r200/r200_ioctl.c	23 Sep 2002 03:20:42 -0000
@@ -680,6 +680,28 @@
     UNLOCK_HARDWARE(rmesa);
 }
 
+void r200WaitForVBlank( r200ContextPtr rmesa )
+{
+    int fd = rmesa->dri.fd, ret;
+    drmRadeonWaitVBlank vbl;
+
+    /*if ( !rmesa->r200Screen->irq ) {
+	fprintf(stderr, "%s called without active IRQ, returning immediately\n", __FUNCTION__);
+	return;
+    }*/
+
+    vbl.type = RADEON_VBL_ABSOLUTE;
+    vbl.sequence = rmesa->vbl_seq + 1;
+
+    do {
+	ret = drmCommandWriteRead( fd, DRM_RADEON_WAIT_VBLANK, &vbl, sizeof(vbl) );
+	if (R200_DEBUG & DEBUG_IOCTL)
+	    fprintf(stderr, "%s: DRM_RADEON_WAIT_VBLANK ioctl returned %d\n", __FUNCTION__, ret);
+    } while ( ret && errno == EINTR );
+
+    rmesa->vbl_seq = vbl.sequence;
+}
+
 
 void r200Flush( GLcontext *ctx )
 {
Index: lib/GL/mesa/src/drv/r200/r200_ioctl.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r200/r200_ioctl.h,v
retrieving revision 1.2.2.3
diff -u -r1.2.2.3 r200_ioctl.h
--- lib/GL/mesa/src/drv/r200/r200_ioctl.h	20 Sep 2002 18:14:22 -0000	1.2.2.3
+++ lib/GL/mesa/src/drv/r200/r200_ioctl.h	23 Sep 2002 03:20:43 -0000
@@ -99,6 +99,7 @@
 extern void r200Flush( GLcontext *ctx );
 extern void r200Finish( GLcontext *ctx );
 extern void r200WaitForIdleLocked( r200ContextPtr rmesa );
+extern void r200WaitForVBlank( r200ContextPtr rmesa );
 extern void r200InitIoctlFuncs( GLcontext *ctx );
 
 extern void *r200AllocateMemoryNV( GLsizei size, GLfloat readfreq,
Index: lib/GL/mesa/src/drv/r200/r200_screen.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/r200/r200_screen.h,v
retrieving revision 1.2.2.1
diff -u -r1.2.2.1 r200_screen.h
--- lib/GL/mesa/src/drv/r200/r200_screen.h	28 Aug 2002 17:49:38 -0000	1.2.2.1
+++ lib/GL/mesa/src/drv/r200/r200_screen.h	23 Sep 2002 03:20:43 -0000
@@ -61,6 +61,7 @@
    int cpp;
    int IsPCI;				/* Current card is a PCI card */
    int AGPMode;
+   unsigned int irq;
 
    unsigned int frontOffset;
    unsigned int frontPitch;
Index: lib/GL/mesa/src/drv/radeon/radeon_context.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v
retrieving revision 1.15
diff -u -r1.15 radeon_context.c
--- lib/GL/mesa/src/drv/radeon/radeon_context.c	16 Aug 2002 22:02:43 -0000	1.15
+++ lib/GL/mesa/src/drv/radeon/radeon_context.c	23 Sep 2002 03:20:44 -0000
@@ -353,6 +353,11 @@
    else
       rmesa->boxes = 0;
 
+   if (getenv("RADEON_THROTTLE_REFRESH"))
+      rmesa->vblwait_enabled = 1;
+   else
+      rmesa->vblwait_enabled = 0;
+
 
    /* Initialize the software rasterizer and helper modules.
     */
@@ -638,6 +643,9 @@
       ctx = rmesa->glCtx;
       if (ctx->Visual.doubleBufferMode) {
          _mesa_swapbuffers( ctx );  /* flush pending rendering comands */
+	 if ( rmesa->radeonScreen->irq && rmesa->vblwait_enabled ) {
+            radeonWaitForVBlank( rmesa );
+	 }
          if ( rmesa->doPageFlip ) {
             radeonPageFlip( dPriv );
          }
Index: lib/GL/mesa/src/drv/radeon/radeon_context.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_context.h,v
retrieving revision 1.13
diff -u -r1.13 radeon_context.h
--- lib/GL/mesa/src/drv/radeon/radeon_context.h	3 Jul 2002 08:25:42 -0000	1.13
+++ lib/GL/mesa/src/drv/radeon/radeon_context.h	23 Sep 2002 03:20:44 -0000
@@ -738,6 +738,11 @@
    GLmatrix tmpmat;
    GLuint last_ReallyEnabled;
 
+   /* VBlank sequence number
+    */
+   unsigned int vbl_seq;
+   int vblwait_enabled; 
+
    /* radeon_tcl.c
     */
    struct radeon_tcl_info tcl;
@@ -754,7 +759,6 @@
     */
    struct radeon_dri_mirror dri;
 
- 
    /* Performance counters
     */
    GLuint boxes;			/* Draw performance boxes */
Index: lib/GL/mesa/src/drv/radeon/radeon_ioctl.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v
retrieving revision 1.22
diff -u -r1.22 radeon_ioctl.c
--- lib/GL/mesa/src/drv/radeon/radeon_ioctl.c	26 Aug 2002 22:16:09 -0000	1.22
+++ lib/GL/mesa/src/drv/radeon/radeon_ioctl.c	23 Sep 2002 03:20:45 -0000
@@ -979,6 +979,29 @@
     UNLOCK_HARDWARE(rmesa);
 }
 
+void radeonWaitForVBlank( radeonContextPtr rmesa )
+{
+    int fd = rmesa->dri.fd, ret;
+    drmRadeonWaitVBlank vbl;
+
+    if ( !rmesa->radeonScreen->irq ) {
+	fprintf(stderr, "%s called without active IRQ, returning immediately\n", __FUNCTION__);
+	return;
+    }
+
+    vbl.type = RADEON_VBL_ABSOLUTE;
+    vbl.sequence = rmesa->vbl_seq + 1;
+
+    do {
+	ret = drmCommandWriteRead( fd, DRM_RADEON_WAIT_VBLANK, &vbl, sizeof(vbl) );
+	if (RADEON_DEBUG & DEBUG_IOCTL)
+	    fprintf(stderr, "%s: DRM_RADEON_WAIT_VBLANK ioctl returned %d\n", __FUNCTION__, ret);
+    } while ( ret && errno == EINTR );
+
+    rmesa->vbl_seq = vbl.sequence;
+}
+
+
 void radeonGetAllParams( radeonContextPtr rmesa )
 {
    int ret;
@@ -991,8 +1014,21 @@
 			      DRM_RADEON_GETPARAM,
 			      &gp, sizeof(gp));
    if (ret) {
-      fprintf(stderr, "drmRadeonGetParam: %d\n", ret);
+      fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_AGP_BUFFER_OFFSET): %d\n", ret);
       exit(1);
+   }
+
+   if ( rmesa->dri.drmMinor >= 6 ) {
+      gp.param = RADEON_PARAM_IRQ;
+      gp.value = &rmesa->radeonScreen->irq;
+
+         ret = drmCommandWriteRead( rmesa->dri.fd,
+				    DRM_RADEON_GETPARAM,
+				    &gp, sizeof(gp));
+	 if (ret) {
+	    fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_IRQ): %d\n", ret);
+	    exit(1);
+	 }
    }
 }
 
Index: lib/GL/mesa/src/drv/radeon/radeon_ioctl.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h,v
retrieving revision 1.6
diff -u -r1.6 radeon_ioctl.h
--- lib/GL/mesa/src/drv/radeon/radeon_ioctl.h	12 Jun 2002 15:50:26 -0000	1.6
+++ lib/GL/mesa/src/drv/radeon/radeon_ioctl.h	23 Sep 2002 03:20:45 -0000
@@ -93,6 +93,7 @@
 extern void radeonFlush( GLcontext *ctx );
 extern void radeonFinish( GLcontext *ctx );
 extern void radeonWaitForIdleLocked( radeonContextPtr rmesa );
+extern void radeonWaitForVBlank( radeonContextPtr rmesa );
 extern void radeonInitIoctlFuncs( GLcontext *ctx );
 extern void radeonGetAllParams( radeonContextPtr rmesa );
 
Index: lib/GL/mesa/src/drv/radeon/radeon_screen.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h,v
retrieving revision 1.7
diff -u -r1.7 radeon_screen.h
--- lib/GL/mesa/src/drv/radeon/radeon_screen.h	12 Jun 2002 15:50:26 -0000	1.7
+++ lib/GL/mesa/src/drv/radeon/radeon_screen.h	23 Sep 2002 03:20:45 -0000
@@ -62,6 +62,7 @@
    int cpp;
    int IsPCI;				/* Current card is a PCI card */
    int AGPMode;
+   unsigned int irq;			/* IRQ number (0 means none) */
 
    unsigned int frontOffset;
    unsigned int frontPitch;
Index: programs/Xserver/hw/xfree86/drivers/ati/radeon.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v
retrieving revision 1.23.2.2
diff -u -r1.23.2.2 radeon.h
--- programs/Xserver/hw/xfree86/drivers/ati/radeon.h	20 Sep 2002 20:18:18 -0000	1.23.2.2
+++ programs/Xserver/hw/xfree86/drivers/ati/radeon.h	23 Sep 2002 03:20:47 -0000
@@ -468,6 +468,8 @@
     CARD32            aux_sc_cntl;
 
     int               irq;
+    CARD32            gen_int_cntl;
+
 #endif
 
     XF86VideoAdaptorPtr adaptor;
Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v
retrieving revision 1.5.2.1
diff -u -r1.5.2.1 radeon_common.h
--- programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h	17 Sep 2002 18:07:07 -0000	1.5.2.1
+++ programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h	23 Sep 2002 03:20:47 -0000
@@ -70,6 +70,7 @@
 #define DRM_RADEON_INIT_HEAP              0x15
 #define DRM_RADEON_IRQ_EMIT               0x16
 #define DRM_RADEON_IRQ_WAIT               0x17
+#define DRM_RADEON_WAIT_VBLANK            0x18
 #define DRM_RADEON_MAX_DRM_COMMAND_INDEX  0x39
 
 
@@ -386,6 +387,17 @@
 #define RADEON_PARAM_LAST_FRAME 0x2
 #define RADEON_PARAM_LAST_DISPATCH 0x3
 #define RADEON_PARAM_LAST_CLEAR 0x4
+#define RADEON_PARAM_IRQ 0x5
+
+
+typedef struct drm_radeon_wait_vblank {
+	unsigned int type;
+	unsigned int sequence;
+} drmRadeonWaitVBlank;
+
+#define RADEON_VBL_ABSOLUTE 0	/* Wait for specific vblank sequence number */
+#define RADEON_VBL_RELATIVE 1	/* Wait for given number of vblanks */
+
 
 
 #define RADEON_MEM_REGION_AGP 1
Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v
retrieving revision 1.29.2.3
diff -u -r1.29.2.3 radeon_dri.c
--- programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c	20 Sep 2002 20:18:20 -0000	1.29.2.3
+++ programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c	23 Sep 2002 03:20:48 -0000
@@ -1329,6 +1329,11 @@
 	RADEONCP_STOP(pScrn, info);
     }
 
+    if (info->irq) {
+	drmCtlUninstHandler(info->drmFD);
+	info->irq = 0;
+    }
+
 				/* De-allocate vertex buffers */
     if (info->buffers) {
 	drmUnmapBufs(info->buffers);
Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v
retrieving revision 1.24.2.1
diff -u -r1.24.2.1 radeon_driver.c
--- programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c	20 Sep 2002 20:18:21 -0000	1.24.2.1
+++ programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c	23 Sep 2002 03:20:51 -0000
@@ -4487,6 +4487,11 @@
 	 * Charl P. Botha <http://cpbotha.net/> */
 	xf86EnablePciBusMaster(info->PciInfo, TRUE);
 
+	if (info->irq) {
+	    unsigned char *RADEONMMIO = info->MMIO;
+	    OUTREG(RADEON_GEN_INT_CNTL, info->gen_int_cntl);
+	}
+
 	RADEONCP_START(pScrn, info);
 	DRIUnlock(pScrn->pScreen);
     }
Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h,v
retrieving revision 1.49
diff -u -r1.49 drmP.h
--- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h	22 Aug 2002 19:35:31 -0000	1.49
+++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h	23 Sep 2002 03:20:52 -0000
@@ -806,10 +806,9 @@
 				   unsigned int cmd, unsigned long arg );
 extern int           DRM(irq_install)( drm_device_t *dev, int irq );
 extern int           DRM(irq_uninstall)( drm_device_t *dev );
-extern void          DRM(dma_service)( int irq, void *device,
-				       struct pt_regs *regs );
+extern void          DRM(dma_service)( DRM_IRQ_ARGS );
 #if __HAVE_DMA_IRQ_BH
-extern void          DRM(dma_immediate_bh)( void *dev );
+extern void          DRM(dma_immediate_bh)( DRM_TASKQUEUE_ARGS );
 #endif
 #endif
 #if DRM_DMA_HISTOGRAM
Index: programs/Xserver/hw/xfree86/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.4.2.6
diff -u -r1.4.2.6 radeon.h
--- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon.h	21 Sep 2002 14:20:52 -0000	1.4.2.6
+++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon.h	23 Sep 2002 03:20:52 -0000
@@ -71,6 +71,7 @@
  * 1.6 - Add static agp memory manager
  *       Add irq handler (won't be turned on unless X server knows to)
  *       Add irq ioctls and irq_active getparam.
+ *     - Add ioctl to wait for vertical blank(s) using IRQ
  */
 #define DRIVER_IOCTLS							     \
  [DRM_IOCTL_NR(DRM_IOCTL_DMA)]               = { radeon_cp_buffers,  1, 0 }, \
@@ -96,7 +97,8 @@
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_FREE)]       = { radeon_mem_free,    1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INIT_HEAP)]  = { radeon_mem_init_heap, 1, 1 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)]   = { radeon_irq_emit, 1, 0 }, \
- [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait, 1, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait, 1, 0 }, \
+ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VBL_WAIT)]   = { radeon_vblank_wait, 1, 0 }, \
 
 /* When a client dies:
  *    - Check for and clean up flipped page state
@@ -132,39 +134,47 @@
 
 
 #define __HAVE_DMA_IRQ		1
+#ifdef __linux__
 #define __HAVE_DMA_IRQ_BH	1 
+#endif
 #define __HAVE_SHARED_IRQ       1
 
+#ifdef __linux__ 
+#define LTQ(x) x
+#else 
+#define LTQ(x)
+#endif 
+
 #define DRIVER_PREINSTALL() do {				\
 	drm_radeon_private_t *dev_priv =			\
 		(drm_radeon_private_t *)dev->dev_private;	\
 	u32 tmp;						\
 								\
-	/* Clear bit if it's already high: */			\
-   	tmp = RADEON_READ( RADEON_GEN_INT_STATUS );		\
-   	tmp = tmp & RADEON_SW_INT_TEST_ACK;			\
-   	RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );		\
+	LTQ(INIT_LIST_HEAD( &dev_priv->vbl_tq.list );)		\
+	LTQ(dev_priv->vbl_tq.sync = 0;)				\
+	LTQ(dev_priv->vbl_tq.routine = DRM(vblank_bh);)		\
+	LTQ(dev_priv->vbl_tq.data = dev;)			\
 								\
  	/* Disable *all* interrupts */				\
       	RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );			\
+								\
+	/* Clear bits if they're already high */		\
+   	tmp = RADEON_READ( RADEON_GEN_INT_STATUS );		\
+   	RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );		\
 } while (0)
 
-#ifdef __linux__ 
-#define IWH(x) init_waitqueue_head(x) 
-#else 
-#define IWH(x) 
-#endif 
-
 #define DRIVER_POSTINSTALL() do {				\
 	drm_radeon_private_t *dev_priv =			\
 		(drm_radeon_private_t *)dev->dev_private;	\
 								\
    	atomic_set(&dev_priv->irq_received, 0);			\
    	atomic_set(&dev_priv->irq_emitted, 0);			\
-	IWH(&dev_priv->irq_queue);		\
+	LTQ(init_waitqueue_head(&dev_priv->irq_queue);)		\
+	LTQ(init_waitqueue_head(&dev_priv->vbl_queue);)		\
 								\
 	/* Turn on SW_INT only */				\
    	RADEON_WRITE( RADEON_GEN_INT_CNTL,			\
+		      RADEON_CRTC_VBLANK_MASK |			\
 		      RADEON_SW_INT_ENABLE );			\
 } while (0)
 
Index: programs/Xserver/hw/xfree86/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.4.2.4
diff -u -r1.4.2.4 radeon_drm.h
--- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h	21 Sep 2002 14:20:52 -0000	1.4.2.4
+++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drm.h	23 Sep 2002 03:20:53 -0000
@@ -378,6 +378,7 @@
 #define DRM_IOCTL_RADEON_INIT_HEAP  DRM_IOW( 0x55, drm_radeon_mem_init_heap_t)
 #define DRM_IOCTL_RADEON_IRQ_EMIT   DRM_IOWR( 0x56, drm_radeon_irq_emit_t)
 #define DRM_IOCTL_RADEON_IRQ_WAIT   DRM_IOW( 0x57, drm_radeon_irq_wait_t)
+#define DRM_IOCTL_RADEON_VBL_WAIT   DRM_IOWR(0x58, drm_radeon_vbl_wait_t)
 
 typedef struct drm_radeon_init {
 	enum {
@@ -517,7 +518,7 @@
 #define RADEON_PARAM_LAST_FRAME          2
 #define RADEON_PARAM_LAST_DISPATCH       3
 #define RADEON_PARAM_LAST_CLEAR          4
-#define RADEON_PARAM_IRQ_ACTIVE          5
+#define RADEON_PARAM_IRQ                 5
 
 typedef struct drm_radeon_getparam {
 	int param;
@@ -557,6 +558,14 @@
 typedef struct drm_radeon_irq_wait {
 	int irq_seq;
 } drm_radeon_irq_wait_t;
+
+#define RADEON_VBL_ABSOLUTE 0	/* Wait for specific vblank sequence number */
+#define RADEON_VBL_RELATIVE 1	/* Wait for given number of vblanks */
+
+typedef struct drm_radeon_vbl_wait {
+	unsigned int type;
+	unsigned int sequence;
+} drm_radeon_vbl_wait_t;
 
 
 #endif
Index: programs/Xserver/hw/xfree86/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.4.2.3
diff -u -r1.4.2.3 radeon_drv.h
--- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h	21 Sep 2002 14:20:53 -0000	1.4.2.3
+++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_drv.h	23 Sep 2002 03:20:54 -0000
@@ -139,6 +139,14 @@
 	struct mem_block *agp_heap;
 	struct mem_block *fb_heap;
 
+	/* VBLANK */
+#ifdef __linux__
+	struct tq_struct  vbl_tq;
+#endif
+   	wait_queue_head_t vbl_queue;
+   	atomic_t vbl_received;
+
+	/* SW interrupt */
    	wait_queue_head_t irq_queue;
    	atomic_t irq_received;
    	atomic_t irq_emitted;
@@ -187,12 +195,16 @@
 extern void radeon_mem_takedown( struct mem_block **heap );
 extern void radeon_mem_release( struct mem_block *heap );
 
+				/* radeon_irq.c */
 extern int radeon_irq_emit( DRM_IOCTL_ARGS );
 extern int radeon_irq_wait( DRM_IOCTL_ARGS );
+extern int radeon_vblank_wait( DRM_IOCTL_ARGS );
 
 extern int radeon_emit_and_wait_irq(drm_device_t *dev);
 extern int radeon_wait_irq(drm_device_t *dev, int irq_nr);
 extern int radeon_emit_irq(drm_device_t *dev);
+extern void radeon_vblank_bh( DRM_TASKQUEUE_ARGS );
+extern int radeon_wait_vblank(drm_device_t *dev, unsigned int *vbl_seq);
 
 
 /* Flags for stats.boxes
@@ -271,11 +283,15 @@
 
 
 #define RADEON_GEN_INT_CNTL		0x0040
+#	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
 #	define RADEON_GUI_IDLE_INT_ENABLE	(1 << 19)
 #	define RADEON_SW_INT_ENABLE		(1 << 25)
 
 #define RADEON_GEN_INT_STATUS		0x0044
+#	define RADEON_CRTC_VBLANK_STAT		(1 << 0)
+#	define RADEON_CRTC_VBLANK_STAT_ACK   	(1 << 0)
 #	define RADEON_GUI_IDLE_INT_TEST_ACK     (1 << 19)
+#	define RADEON_SW_INT_TEST		(1 << 25)
 #	define RADEON_SW_INT_TEST_ACK   	(1 << 25)
 #	define RADEON_SW_INT_FIRE		(1 << 26)
 
Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_irq.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/Attic/radeon_irq.c,v
retrieving revision 1.1.2.6
diff -u -r1.1.2.6 radeon_irq.c
--- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_irq.c	17 Sep 2002 13:30:17 -0000	1.1.2.6
+++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_irq.c	23 Sep 2002 03:20:56 -0000
@@ -58,39 +58,61 @@
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_radeon_private_t *dev_priv = 
 	   (drm_radeon_private_t *)dev->dev_private;
-   	u32 temp;
+   	u32 stat, ack = 0;
 
 	/* Need to wait for fifo to drain?
 	 */
-	temp = RADEON_READ(RADEON_GEN_INT_STATUS);  
-	temp = temp & RADEON_SW_INT_TEST_ACK;  
-	if (temp == 0) return;  
-	RADEON_WRITE(RADEON_GEN_INT_STATUS, temp);  
+	stat = RADEON_READ(RADEON_GEN_INT_STATUS);
 
-	atomic_inc(&dev_priv->irq_received);
+	/* SW interrupt */
+	if (stat & RADEON_SW_INT_TEST) {
+		ack |= RADEON_SW_INT_TEST_ACK;
+		atomic_inc(&dev_priv->irq_received);
 #ifdef __linux__
-	queue_task(&dev->tq, &tq_immediate);  
-	mark_bh(IMMEDIATE_BH);  
+		queue_task(&dev->tq, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
 #endif /* __linux__ */
 #ifdef __FreeBSD__
-	taskqueue_enqueue(taskqueue_swi, &dev->task);
+		wakeup( &dev_priv->irq_queue );
 #endif /* __FreeBSD__ */
-}
+	}
+
+	/* VBLANK interrupt */
+	if (stat & RADEON_CRTC_VBLANK_STAT) {
+		ack |= RADEON_CRTC_VBLANK_STAT_ACK;
+		atomic_inc(&dev_priv->vbl_received);
+#ifdef __linux__
+		queue_task(&dev_priv->vbl_tq, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+		wakeup( &dev_priv->vbl_queue );
+#endif /* __FreeBSD__ */
+	}
 
+	if (ack)
+		RADEON_WRITE(RADEON_GEN_INT_STATUS, ack);
+}
+ 
+#ifdef __linux__
 void DRM(dma_immediate_bh)( DRM_TASKQUEUE_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_radeon_private_t *dev_priv = 
 	   (drm_radeon_private_t *)dev->dev_private;
 
-#ifdef __linux__
 	wake_up_interruptible(&dev_priv->irq_queue); 
-#endif /* __linux__ */
-#ifdef __FreeBSD__
-	wakeup( &dev_priv->irq_queue );
-#endif
 }
 
+void DRM(vblank_bh)( DRM_TASKQUEUE_ARGS )
+{
+	drm_device_t *dev = (drm_device_t *) arg;
+	drm_radeon_private_t *dev_priv = 
+	   (drm_radeon_private_t *)dev->dev_private;
+
+	wake_up_interruptible( &dev_priv->vbl_queue ); 
+}
+#endif /* __linux__ */
 
 int radeon_emit_irq(drm_device_t *dev)
 {
@@ -156,6 +178,42 @@
 #endif /* __FreeBSD__ */
 }
 
+int radeon_wait_vblank(drm_device_t *dev, unsigned int *sequence)
+{
+  	drm_radeon_private_t *dev_priv = 
+	   (drm_radeon_private_t *)dev->dev_private;
+#ifdef __linux__
+	DECLARE_WAITQUEUE(entry, current);
+#endif /* __linux__ */
+	unsigned int cur_vblank;
+	int ret = 0;
+
+	/* Assume that the user has missed the current sequence number by about
+	 * a day rather than she wants to wait for years using vertical blanks :)
+	 */
+	while ( ( ( cur_vblank = atomic_read(&dev_priv->vbl_received ) )
+		+ ~*sequence + 1 ) > (1<<23) ) {
+		dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+#ifdef __linux__
+		interruptible_sleep_on( &dev_priv->vbl_queue );
+
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+#endif /* __linux__ */
+#ifdef __FreeBSD__
+		ret = tsleep( &dev_priv->vbl_queue, 3*hz, "rdnvbl", PZERO | PCATCH);
+		if (ret)
+			return ret;
+#endif /* __FreeBSD__ */
+	}
+
+	*sequence = cur_vblank;
+
+	return ret;
+}
+
 
 int radeon_emit_and_wait_irq(drm_device_t *dev)
 {
@@ -210,5 +268,32 @@
 				  sizeof(irqwait) );
 
 	return radeon_wait_irq( dev, irqwait.irq_seq );
+}
+
+int radeon_vblank_wait( DRM_IOCTL_ARGS )
+{
+	DRM_DEVICE;
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	drm_radeon_vbl_wait_t vblwait;
+	int ret;
+
+	if ( !dev_priv ) {
+		DRM_ERROR( "%s called with no initialization\n", __func__ );
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_radeon_vbl_wait_t *)data,
+				  sizeof(vblwait) );
+
+	if ( vblwait.type == RADEON_VBL_RELATIVE ) {
+		vblwait.sequence += atomic_read( &dev_priv->vbl_received );
+	}
+
+	ret = radeon_wait_vblank( dev, &vblwait.sequence );
+
+	DRM_COPY_TO_USER_IOCTL( (drm_radeon_vbl_wait_t *)data, vblwait,
+				sizeof(vblwait) );
+
+	return ret;
 }
 
Index: programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c,v
retrieving revision 1.8.2.5
diff -u -r1.8.2.5 radeon_state.c
--- programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c	21 Sep 2002 14:20:53 -0000	1.8.2.5
+++ programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/radeon_state.c	23 Sep 2002 03:20:57 -0000
@@ -2172,6 +2172,9 @@
 		dev_priv->stats.last_clear_reads++;
 		value = GET_SCRATCH( 2 );
 		break;
+	case RADEON_PARAM_IRQ:
+		value = dev->irq;
+		break;
 	default:
 		return DRM_ERR(EINVAL);
 	}

Reply via email to