summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/i810_dma.c97
-rw-r--r--linux-core/i810_drm.h6
-rw-r--r--linux-core/i810_drv.c4
-rw-r--r--linux-core/i810_drv.h5
4 files changed, 89 insertions, 23 deletions
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c
index 96b7a44f..901be559 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/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(&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 +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(&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;
}
@@ -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-core/i810_drm.h b/linux-core/i810_drm.h
index 4c8e09f6..c5f51c9a 100644
--- a/linux-core/i810_drm.h
+++ b/linux-core/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-core/i810_drv.c b/linux-core/i810_drv.c
index 6f78fbc9..d7fa9d88 100644
--- a/linux-core/i810_drv.c
+++ b/linux-core/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-core/i810_drv.h b/linux-core/i810_drv.h
index c387bf72..f5411c0b 100644
--- a/linux-core/i810_drv.h
+++ b/linux-core/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,