vserver 1.9.5.x5
[linux-2.6.git] / drivers / char / drm / gamma_dma.c
index 8b61248..e486fb8 100644 (file)
@@ -116,7 +116,7 @@ static inline int gamma_dma_is_ready(drm_device_t *dev)
        return (!GAMMA_READ(GAMMA_DMACOUNT));
 }
 
-irqreturn_t gamma_dma_service( DRM_IRQ_ARGS )
+irqreturn_t gamma_driver_irq_handler( DRM_IRQ_ARGS )
 {
        drm_device_t     *dev = (drm_device_t *)arg;
        drm_device_dma_t *dma = dev->dma;
@@ -262,7 +262,7 @@ static void gamma_dma_timer_bh(unsigned long dev)
        gamma_dma_schedule((drm_device_t *)dev, 0);
 }
 
-void gamma_dma_immediate_bh(void *dev)
+void gamma_irq_immediate_bh(void *dev)
 {
        gamma_dma_schedule(dev, 0);
 }
@@ -346,6 +346,9 @@ static int gamma_dma_priority(struct file *filp,
        drm_buf_t         *buf;
        drm_buf_t         *last_buf = NULL;
        drm_device_dma_t  *dma      = dev->dma;
+       int               *send_indices = NULL;
+       int               *send_sizes = NULL;
+
        DECLARE_WAITQUEUE(entry, current);
 
                                /* Turn off interrupt handling */
@@ -365,11 +368,31 @@ static int gamma_dma_priority(struct file *filp,
                ++must_free;
        }
 
+       send_indices = DRM(alloc)(d->send_count * sizeof(*send_indices),
+                                 DRM_MEM_DRIVER);
+       if (send_indices == NULL)
+               return -ENOMEM;
+       if (copy_from_user(send_indices, d->send_indices, 
+                          d->send_count * sizeof(*send_indices))) {
+               retcode = -EFAULT;
+                goto cleanup;
+       }
+       
+       send_sizes = DRM(alloc)(d->send_count * sizeof(*send_sizes),
+                               DRM_MEM_DRIVER);
+       if (send_sizes == NULL)
+               return -ENOMEM;
+       if (copy_from_user(send_sizes, d->send_sizes, 
+                          d->send_count * sizeof(*send_sizes))) {
+               retcode = -EFAULT;
+                goto cleanup;
+       }
+
        for (i = 0; i < d->send_count; i++) {
-               idx = d->send_indices[i];
+               idx = send_indices[i];
                if (idx < 0 || idx >= dma->buf_count) {
                        DRM_ERROR("Index %d (of %d max)\n",
-                                 d->send_indices[i], dma->buf_count - 1);
+                                 send_indices[i], dma->buf_count - 1);
                        continue;
                }
                buf = dma->buflist[ idx ];
@@ -391,7 +414,7 @@ static int gamma_dma_priority(struct file *filp,
                                   process closes the /dev/drm? handle, so
                                   it can't also be doing DMA. */
                buf->list         = DRM_LIST_PRIO;
-               buf->used         = d->send_sizes[i];
+               buf->used         = send_sizes[i];
                buf->context      = d->context;
                buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED;
                address           = (unsigned long)buf->address;
@@ -402,14 +425,14 @@ static int gamma_dma_priority(struct file *filp,
                if (buf->pending) {
                        DRM_ERROR("Sending pending buffer:"
                                  " buffer %d, offset %d\n",
-                                 d->send_indices[i], i);
+                                 send_indices[i], i);
                        retcode = -EINVAL;
                        goto cleanup;
                }
                if (buf->waiting) {
                        DRM_ERROR("Sending waiting buffer:"
                                  " buffer %d, offset %d\n",
-                                 d->send_indices[i], i);
+                                 send_indices[i], i);
                        retcode = -EINVAL;
                        goto cleanup;
                }
@@ -458,6 +481,12 @@ cleanup:
                gamma_dma_ready(dev);
                gamma_free_buffer(dev, last_buf);
        }
+       if (send_indices)
+               DRM(free)(send_indices, d->send_count * sizeof(*send_indices), 
+                         DRM_MEM_DRIVER);
+       if (send_sizes)
+               DRM(free)(send_sizes, d->send_count * sizeof(*send_sizes), 
+                         DRM_MEM_DRIVER);
 
        if (must_free && !dev->context_flag) {
                if (gamma_lock_free(dev, &dev->lock.hw_lock->lock,
@@ -476,9 +505,13 @@ static int gamma_dma_send_buffers(struct file *filp,
        drm_buf_t         *last_buf = NULL;
        int               retcode   = 0;
        drm_device_dma_t  *dma      = dev->dma;
+       int               send_index;
+
+       if (get_user(send_index, &d->send_indices[d->send_count-1]))
+               return -EFAULT;
 
        if (d->flags & _DRM_DMA_BLOCK) {
-               last_buf = dma->buflist[d->send_indices[d->send_count-1]];
+               last_buf = dma->buflist[send_index];
                add_wait_queue(&last_buf->dma_wait, &entry);
        }
 
@@ -532,9 +565,10 @@ int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
        drm_device_t      *dev      = priv->dev;
        drm_device_dma_t  *dma      = dev->dma;
        int               retcode   = 0;
+       drm_dma_t         __user *argp = (void __user *)arg;
        drm_dma_t         d;
 
-       if (copy_from_user(&d, (drm_dma_t *)arg, sizeof(d)))
+       if (copy_from_user(&d, argp, sizeof(d)))
                return -EFAULT;
 
        if (d.send_count < 0 || d.send_count > dma->buf_count) {
@@ -564,7 +598,7 @@ int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
 
        DRM_DEBUG("%d returning, granted = %d\n",
                  current->pid, d.granted_count);
-       if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
+       if (copy_to_user(argp, &d, sizeof(d)))
                return -EFAULT;
 
        return retcode;
@@ -605,12 +639,12 @@ static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
                        break;
                }
        }
-
-       DRM_FIND_MAP( dev_priv->mmio0, init->mmio0 );
-       DRM_FIND_MAP( dev_priv->mmio1, init->mmio1 );
-       DRM_FIND_MAP( dev_priv->mmio2, init->mmio2 );
-       DRM_FIND_MAP( dev_priv->mmio3, init->mmio3 );
-
+       
+       dev_priv->mmio0 = drm_core_findmap(dev, init->mmio0);
+       dev_priv->mmio1 = drm_core_findmap(dev, init->mmio1);
+       dev_priv->mmio2 = drm_core_findmap(dev, init->mmio2);
+       dev_priv->mmio3 = drm_core_findmap(dev, init->mmio3);
+       
        dev_priv->sarea_priv = (drm_gamma_sarea_t *)
                ((u8 *)dev_priv->sarea->handle +
                 init->sarea_priv_offset);
@@ -627,9 +661,8 @@ static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
 
                buf = dma->buflist[GLINT_DRI_BUF_COUNT];
        } else {
-               DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
-
-               DRM_IOREMAP( dev_priv->buffers, dev );
+               dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+               drm_core_ioremap( dev->agp_buffer_map, dev);
 
                buf = dma->buflist[GLINT_DRI_BUF_COUNT];
                pgt = buf->address;
@@ -656,19 +689,18 @@ int gamma_do_cleanup_dma( drm_device_t *dev )
 {
        DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-#if _HAVE_DMA_IRQ
        /* Make sure interrupts are disabled here because the uninstall ioctl
         * may not have been called from userspace and after dev_private
         * is freed, it's too late.
         */
-       if ( dev->irq ) DRM(irq_uninstall)(dev);
-#endif
+       if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+               if ( dev->irq_enabled ) 
+                       DRM(irq_uninstall)(dev);
 
        if ( dev->dev_private ) {
-               drm_gamma_private_t *dev_priv = dev->dev_private;
 
-               if ( dev_priv->buffers != NULL )
-                       DRM_IOREMAPFREE( dev_priv->buffers, dev );
+               if ( dev->agp_buffer_map != NULL )
+                       drm_core_ioremapfree( dev->agp_buffer_map, dev );
 
                DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
                           DRM_MEM_DRIVER );
@@ -687,7 +719,7 @@ int gamma_dma_init( struct inode *inode, struct file *filp,
 
        LOCK_TEST_WITH_RETURN( dev, filp );
 
-       if ( copy_from_user( &init, (drm_gamma_init_t *)arg, sizeof(init) ) )
+       if ( copy_from_user( &init, (drm_gamma_init_t __user *)arg, sizeof(init) ) )
                return -EFAULT;
 
        switch ( init.func ) {
@@ -756,7 +788,7 @@ int gamma_dma_copy( struct inode *inode, struct file *filp,
        drm_device_t *dev = priv->dev;
        drm_gamma_copy_t copy;
 
-       if ( copy_from_user( &copy, (drm_gamma_copy_t *)arg, sizeof(copy) ) )
+       if ( copy_from_user( &copy, (drm_gamma_copy_t __user *)arg, sizeof(copy) ) )
                return -EFAULT;
 
        return gamma_do_copy_dma( dev, &copy );
@@ -771,12 +803,11 @@ int gamma_getsareactx(struct inode *inode, struct file *filp,
 {
        drm_file_t      *priv   = filp->private_data;
        drm_device_t    *dev    = priv->dev;
+       drm_ctx_priv_map_t __user *argp = (void __user *)arg;
        drm_ctx_priv_map_t request;
        drm_map_t *map;
 
-       if (copy_from_user(&request,
-                          (drm_ctx_priv_map_t *)arg,
-                          sizeof(request)))
+       if (copy_from_user(&request, argp, sizeof(request)))
                return -EFAULT;
 
        down(&dev->struct_sem);
@@ -789,7 +820,7 @@ int gamma_getsareactx(struct inode *inode, struct file *filp,
        up(&dev->struct_sem);
 
        request.handle = map->handle;
-       if (copy_to_user((drm_ctx_priv_map_t *)arg, &request, sizeof(request)))
+       if (copy_to_user(argp, &request, sizeof(request)))
                return -EFAULT;
        return 0;
 }
@@ -805,7 +836,7 @@ int gamma_setsareactx(struct inode *inode, struct file *filp,
        struct list_head *list;
 
        if (copy_from_user(&request,
-                          (drm_ctx_priv_map_t *)arg,
+                          (drm_ctx_priv_map_t __user *)arg,
                           sizeof(request)))
                return -EFAULT;
 
@@ -835,7 +866,7 @@ int gamma_setsareactx(struct inode *inode, struct file *filp,
        return 0;
 }
 
-void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
+void gamma_driver_irq_preinstall( drm_device_t *dev ) {
        drm_gamma_private_t *dev_priv =
                                (drm_gamma_private_t *)dev->dev_private;
 
@@ -846,7 +877,7 @@ void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
        GAMMA_WRITE( GAMMA_GDMACONTROL,         0x00000000 );
 }
 
-void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
+void gamma_driver_irq_postinstall( drm_device_t *dev ) {
        drm_gamma_private_t *dev_priv =
                                (drm_gamma_private_t *)dev->dev_private;
 
@@ -858,7 +889,7 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
        GAMMA_WRITE( GAMMA_GDELAYTIMER,         0x00039090 );
 }
 
-void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+void gamma_driver_irq_uninstall( drm_device_t *dev ) {
        drm_gamma_private_t *dev_priv =
                                (drm_gamma_private_t *)dev->dev_private;
        if (!dev_priv)
@@ -871,3 +902,45 @@ void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
        GAMMA_WRITE( GAMMA_COMMANDINTENABLE,    0x00000000 );
        GAMMA_WRITE( GAMMA_GINTENABLE,          0x00000000 );
 }
+
+extern drm_ioctl_desc_t DRM(ioctls)[];
+
+static int gamma_driver_preinit(drm_device_t *dev)
+{
+       /* reset the finish ioctl */
+       DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_FINISH)].func = DRM(finish);
+       return 0;
+}
+
+static void gamma_driver_pretakedown(drm_device_t *dev)
+{
+       gamma_do_cleanup_dma(dev);
+}
+
+static void gamma_driver_dma_ready(drm_device_t *dev)
+{
+       gamma_dma_ready(dev);
+}
+
+static int gamma_driver_dma_quiescent(drm_device_t *dev)
+{
+       drm_gamma_private_t *dev_priv = (
+               drm_gamma_private_t *)dev->dev_private;
+       if (dev_priv->num_rast == 2)
+               gamma_dma_quiescent_dual(dev);
+       else gamma_dma_quiescent_single(dev);
+       return 0;
+}
+
+void gamma_driver_register_fns(drm_device_t *dev)
+{
+       dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
+       DRM(fops).read = gamma_fops_read;
+       DRM(fops).poll = gamma_fops_poll;
+       dev->driver.preinit = gamma_driver_preinit;
+       dev->driver.pretakedown = gamma_driver_pretakedown;
+       dev->driver.dma_ready = gamma_driver_dma_ready;
+       dev->driver.dma_quiescent = gamma_driver_dma_quiescent;
+       dev->driver.dma_flush_block_and_flush = gamma_flush_block_and_flush;
+       dev->driver.dma_flush_unblock = gamma_flush_unblock;
+}