patch-2.4.23 linux-2.4.23/drivers/char/drm/drm_dma.h

Next file: linux-2.4.23/drivers/char/drm/drm_drv.h
Previous file: linux-2.4.23/drivers/char/drm/drm_context.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/drivers/char/drm/drm_dma.h linux-2.4.23/drivers/char/drm/drm_dma.h
@@ -30,7 +30,7 @@
  */
 
 #include "drmP.h"
-
+#include "drm_os_linux.h"
 #include <linux/interrupt.h>	/* For task queue support */
 
 #ifndef __HAVE_DMA_WAITQUEUE
@@ -537,8 +537,18 @@
 	dev->tq.data = dev;
 #endif
 
+#if __HAVE_VBL_IRQ
+	init_waitqueue_head(&dev->vbl_queue);
+
+	spin_lock_init( &dev->vbl_lock );
+
+	INIT_LIST_HEAD( &dev->vbl_sigs.head );
+
+	dev->vbl_pending = 0;
+#endif
+
 				/* Before installing handler */
-	DRIVER_PREINSTALL();
+	DRM(driver_irq_preinstall)(dev);
 
 				/* Install handler */
 	ret = request_irq( dev->irq, DRM(dma_service),
@@ -551,7 +561,7 @@
 	}
 
 				/* After installing handler */
-	DRIVER_POSTINSTALL();
+	DRM(driver_irq_postinstall)(dev);
 
 	return 0;
 }
@@ -570,7 +580,7 @@
 
 	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
 
-	DRIVER_UNINSTALL();
+	DRM(driver_irq_uninstall)( dev );
 
 	free_irq( irq, dev );
 
@@ -597,6 +607,142 @@
 	}
 }
 
+#if __HAVE_VBL_IRQ
+
+int DRM(wait_vblank)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data )
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_wait_vblank_t vblwait;
+	struct timeval now;
+	int ret = 0;
+	unsigned int flags;
+
+	if (!dev->irq)
+		return -EINVAL;
+
+	DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
+				  sizeof(vblwait) );
+
+	switch ( vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK ) {
+	case _DRM_VBLANK_RELATIVE:
+		vblwait.request.sequence += atomic_read( &dev->vbl_received );
+		vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
+	case _DRM_VBLANK_ABSOLUTE:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK;
+	
+	if ( flags & _DRM_VBLANK_SIGNAL ) {
+		unsigned long irqflags;
+		drm_vbl_sig_t *vbl_sig;
+		
+		vblwait.reply.sequence = atomic_read( &dev->vbl_received );
+
+		spin_lock_irqsave( &dev->vbl_lock, irqflags );
+
+		/* Check if this task has already scheduled the same signal
+		 * for the same vblank sequence number; nothing to be done in
+		 * that case
+		 */
+		list_for_each( ( (struct list_head *) vbl_sig ), &dev->vbl_sigs.head ) {
+			if (vbl_sig->sequence == vblwait.request.sequence
+			    && vbl_sig->info.si_signo == vblwait.request.signal
+			    && vbl_sig->task == current)
+			{
+				spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+				goto done;
+			}
+		}
+
+		if ( dev->vbl_pending >= 100 ) {
+			spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+			return -EBUSY;
+		}
+
+		dev->vbl_pending++;
+
+		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+
+		if ( !( vbl_sig = kmalloc(sizeof(drm_vbl_sig_t), GFP_KERNEL) ) ) 
+			return -ENOMEM;
+		
+
+		memset( (void *)vbl_sig, 0, sizeof(*vbl_sig) );
+
+		vbl_sig->sequence = vblwait.request.sequence;
+		vbl_sig->info.si_signo = vblwait.request.signal;
+		vbl_sig->task = current;
+
+		spin_lock_irqsave( &dev->vbl_lock, irqflags );
+
+		list_add_tail( (struct list_head *) vbl_sig, &dev->vbl_sigs.head );
+
+		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
+	} else {
+		ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
+
+		do_gettimeofday( &now );
+		vblwait.reply.tval_sec = now.tv_sec;
+		vblwait.reply.tval_usec = now.tv_usec;
+	}
+
+done:
+	DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
+				sizeof(vblwait) );
+
+	return ret;
+}
+
+void DRM(vbl_send_signals)( drm_device_t *dev )
+{
+	struct list_head *tmp;
+	drm_vbl_sig_t *vbl_sig;
+	unsigned int vbl_seq = atomic_read( &dev->vbl_received );
+	unsigned long flags;
+
+	spin_lock_irqsave( &dev->vbl_lock, flags );
+
+	list_for_each_safe( ( (struct list_head *) vbl_sig ), tmp, &dev->vbl_sigs.head ) {
+		if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
+			vbl_sig->info.si_code = vbl_seq;
+			send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
+
+			list_del( (struct list_head *) vbl_sig );
+
+
+			kfree( vbl_sig );
+			dev->vbl_pending--;
+		}
+	}
+
+	spin_unlock_irqrestore( &dev->vbl_lock, flags );
+}
+
+#endif	/* __HAVE_VBL_IRQ */
+
+#else
+
+int DRM(control)( struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg )
+{
+	drm_control_t ctl;
+
+	if ( copy_from_user( &ctl, (drm_control_t *)arg, sizeof(ctl) ) )
+		return -EFAULT;
+
+	switch ( ctl.func ) {
+	case DRM_INST_HANDLER:
+	case DRM_UNINST_HANDLER:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 #endif /* __HAVE_DMA_IRQ */
 
 #endif /* __HAVE_DMA */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)