summaryrefslogtreecommitdiff
path: root/linux/i810_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/i810_dma.c')
-rw-r--r--linux/i810_dma.c134
1 files changed, 102 insertions, 32 deletions
diff --git a/linux/i810_dma.c b/linux/i810_dma.c
index 96b7a44f..14c78071 100644
--- a/linux/i810_dma.c
+++ b/linux/i810_dma.c
@@ -33,7 +33,6 @@
#define __NO_VERSION__
#include "drmP.h"
#include "i810_drv.h"
-
#include <linux/interrupt.h> /* For task queue support */
/* in case we don't have a 2.3.99-pre6 kernel or later: */
@@ -156,16 +155,23 @@ static struct file_operations i810_buffer_fops = {
int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- drm_i810_private_t *dev_priv = dev->dev_private;
- drm_buf_t *buf = dev_priv->mmap_buffer;
- drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev;
+ drm_i810_private_t *dev_priv;
+ drm_buf_t *buf;
+ drm_i810_buf_priv_t *buf_priv;
+
+ lock_kernel();
+ dev = priv->dev;
+ dev_priv = dev->dev_private;
+ buf = dev_priv->mmap_buffer;
+ buf_priv = buf->dev_private;
vma->vm_flags |= (VM_IO | VM_DONTCOPY);
vma->vm_file = filp;
buf_priv->currently_mapped = I810_BUF_MAPPED;
+ unlock_kernel();
if (remap_page_range(vma->vm_start,
VM_OFFSET(vma),
@@ -184,23 +190,29 @@ static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
int retcode = 0;
if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
- down(&current->mm->mmap_sem);
- old_fops = filp->f_op;
- filp->f_op = &i810_buffer_fops;
- dev_priv->mmap_buffer = buf;
- buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
- PROT_READ|PROT_WRITE,
- MAP_SHARED,
- buf->bus_address);
- dev_priv->mmap_buffer = NULL;
- filp->f_op = old_fops;
- if ((unsigned long)buf_priv->virtual > -1024UL) {
- /* Real error */
- DRM_DEBUG("mmap error\n");
- retcode = (signed int)buf_priv->virtual;
- buf_priv->virtual = 0;
+
+ if(VM_DONTCOPY != 0) {
+ down(&current->mm->mmap_sem);
+ old_fops = filp->f_op;
+ filp->f_op = &i810_buffer_fops;
+ dev_priv->mmap_buffer = buf;
+ buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ buf->bus_address);
+ dev_priv->mmap_buffer = NULL;
+ filp->f_op = old_fops;
+ if ((unsigned long)buf_priv->virtual > -1024UL) {
+ /* Real error */
+ DRM_DEBUG("mmap error\n");
+ retcode = (signed int)buf_priv->virtual;
+ buf_priv->virtual = 0;
+ }
+ up(&current->mm->mmap_sem);
+ } else {
+ buf_priv->virtual = buf_priv->kernel_virtual;
+ buf_priv->currently_mapped = I810_BUF_MAPPED;
}
- up(&current->mm->mmap_sem);
return retcode;
}
@@ -209,13 +221,22 @@ static int i810_unmap_buffer(drm_buf_t *buf)
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
int retcode = 0;
- if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL;
- down(&current->mm->mmap_sem);
- retcode = do_munmap(current->mm, (unsigned long)buf_priv->virtual,
- (size_t) buf->total);
+ if(VM_DONTCOPY != 0) {
+ if(buf_priv->currently_mapped != I810_BUF_MAPPED)
+ return -EINVAL;
+ down(&current->mm->mmap_sem);
+#if LINUX_VERSION_CODE < 0x020399
+ retcode = do_munmap((unsigned long)buf_priv->virtual,
+ (size_t) buf->total);
+#else
+ retcode = do_munmap(current->mm,
+ (unsigned long)buf_priv->virtual,
+ (size_t) buf->total);
+#endif
+ up(&current->mm->mmap_sem);
+ }
buf_priv->currently_mapped = I810_BUF_UNMAPPED;
buf_priv->virtual = 0;
- up(&current->mm->mmap_sem);
return retcode;
}
@@ -261,8 +282,8 @@ static unsigned long i810_alloc_page(drm_device_t *dev)
if(address == 0UL)
return 0;
- atomic_inc(&mem_map[MAP_NR((void *) address)].count);
- set_bit(PG_locked, &mem_map[MAP_NR((void *) address)].flags);
+ atomic_inc(&virt_to_page(address)->count);
+ set_bit(PG_locked, &virt_to_page(address)->flags);
return address;
}
@@ -272,9 +293,9 @@ static void i810_free_page(drm_device_t *dev, unsigned long page)
if(page == 0UL)
return;
- atomic_dec(&mem_map[MAP_NR((void *) page)].count);
- clear_bit(PG_locked, &mem_map[MAP_NR((void *) page)].flags);
- wake_up(&mem_map[MAP_NR((void *) page)].wait);
+ atomic_dec(&virt_to_page(page)->count);
+ clear_bit(PG_locked, &virt_to_page(page)->flags);
+ wake_up(&virt_to_page(page)->wait);
free_page(page);
return;
}
@@ -1206,6 +1227,15 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
}
if (!ret) {
+ sigemptyset(&dev->sigmask);
+ sigaddset(&dev->sigmask, SIGSTOP);
+ sigaddset(&dev->sigmask, SIGTSTP);
+ sigaddset(&dev->sigmask, SIGTTIN);
+ sigaddset(&dev->sigmask, SIGTTOU);
+ dev->sigdata.context = lock.context;
+ dev->sigdata.lock = dev->lock.hw_lock;
+ block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+
if (lock.flags & _DRM_LOCK_QUIESCENT) {
DRM_DEBUG("_DRM_LOCK_QUIESCENT\n");
DRM_DEBUG("fred\n");
@@ -1354,3 +1384,43 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
return retcode;
}
+
+int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i810_copy_t d;
+ drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+ u32 *hw_status = (u32 *)dev_priv->hw_status_page;
+ drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+ dev_priv->sarea_priv;
+ drm_buf_t *buf;
+ drm_i810_buf_priv_t *buf_priv;
+ drm_device_dma_t *dma = dev->dma;
+
+ if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+ DRM_ERROR("i810_dma called without lock held\n");
+ return -EINVAL;
+ }
+
+ copy_from_user_ret(&d, (drm_i810_copy_t *)arg, sizeof(d), -EFAULT);
+
+ if(d.idx > dma->buf_count) return -EINVAL;
+ buf = dma->buflist[ d.idx ];
+ buf_priv = buf->dev_private;
+ if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM;
+
+ copy_from_user_ret(buf_priv->virtual, d.address, d.used, -EFAULT);
+
+ sarea_priv->last_dispatch = (int) hw_status[5];
+
+ return 0;
+}
+
+int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ if(VM_DONTCOPY == 0) return 1;
+ return 0;
+}