diff options
| -rw-r--r-- | linux-core/i810_dma.c | 97 | ||||
| -rw-r--r-- | linux-core/i810_drm.h | 6 | ||||
| -rw-r--r-- | linux-core/i810_drv.c | 4 | ||||
| -rw-r--r-- | linux-core/i810_drv.h | 5 | ||||
| -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 | ||||
| -rw-r--r-- | shared-core/drm.h | 2 | ||||
| -rw-r--r-- | shared/drm.h | 2 | 
11 files changed, 184 insertions, 46 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(¤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-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,  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,  diff --git a/shared-core/drm.h b/shared-core/drm.h index 4affcc41..5a979e1c 100644 --- a/shared-core/drm.h +++ b/shared-core/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/shared/drm.h b/shared/drm.h index 4affcc41..5a979e1c 100644 --- a/shared/drm.h +++ b/shared/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)  | 
