diff options
Diffstat (limited to 'linux')
-rw-r--r-- | linux/drm.h | 2 | ||||
-rw-r--r-- | linux/i810_dma.c | 97 | ||||
-rw-r--r-- | linux/i810_drm.h | 6 | ||||
-rw-r--r-- | linux/i810_drv.c | 4 | ||||
-rw-r--r-- | linux/i810_drv.h | 5 |
5 files changed, 91 insertions, 23 deletions
diff --git a/linux/drm.h b/linux/drm.h index 4affcc41..5a979e1c 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -353,6 +353,8 @@ typedef struct drm_agp_info { #define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) #define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t) #define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46) +#define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t) +#define DRM_IOCTL_I810_DOCOPY DRM_IO ( 0x48) /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) diff --git a/linux/i810_dma.c b/linux/i810_dma.c index 96b7a44f..901be559 100644 --- a/linux/i810_dma.c +++ b/linux/i810_dma.c @@ -184,23 +184,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(¤t->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(¤t->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(¤t->mm->mmap_sem); + } else { + buf_priv->virtual = buf_priv->kernel_virtual; + buf_priv->currently_mapped = I810_BUF_MAPPED; } - up(¤t->mm->mmap_sem); return retcode; } @@ -209,13 +215,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(¤t->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(¤t->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(¤t->mm->mmap_sem); + } buf_priv->currently_mapped = I810_BUF_UNMAPPED; buf_priv->virtual = 0; - up(¤t->mm->mmap_sem); return retcode; } @@ -1354,3 +1369,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; +} diff --git a/linux/i810_drm.h b/linux/i810_drm.h index 4c8e09f6..c5f51c9a 100644 --- a/linux/i810_drm.h +++ b/linux/i810_drm.h @@ -178,6 +178,12 @@ typedef struct _drm_i810_vertex { int discard; /* client is finished with the buffer? */ } drm_i810_vertex_t; +typedef struct _drm_i810_copy_t { + int idx; /* buffer index */ + int used; /* nr bytes in use */ + void *address; /* Address to copy from */ +} drm_i810_copy_t; + typedef struct drm_i810_dma { void *virtual; int request_idx; diff --git a/linux/i810_drv.c b/linux/i810_drv.c index 6f78fbc9..d7fa9d88 100644 --- a/linux/i810_drv.c +++ b/linux/i810_drv.c @@ -42,7 +42,7 @@ EXPORT_SYMBOL(i810_cleanup); #define I810_DESC "Intel I810" #define I810_DATE "19991213" #define I810_MAJOR 1 -#define I810_MINOR 0 +#define I810_MINOR 1 #define I810_PATCHLEVEL 0 static drm_device_t i810_device; @@ -112,6 +112,8 @@ static drm_ioctl_desc_t i810_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)] = { i810_swap_bufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_COPY)] = { i810_copybuf, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_I810_DOCOPY)] = { i810_docopy, 1, 0 }, }; #define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls) diff --git a/linux/i810_drv.h b/linux/i810_drv.h index c387bf72..f5411c0b 100644 --- a/linux/i810_drv.h +++ b/linux/i810_drv.h @@ -106,7 +106,10 @@ extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid); extern int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma); - +extern int i810_copybuf(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +extern int i810_docopy(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); /* i810_bufs.c */ extern int i810_addbufs(struct inode *inode, struct file *filp, |