i810_dma.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 1,394 行 · 第 1/3 页

C
1,394
字号
	}	OUT_RING(0);	ADVANCE_LP_RING();	BEGIN_LP_RING(2);	OUT_RING( CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP );	OUT_RING( 0 );	ADVANCE_LP_RING();	/* Increment the frame counter.  The client-side 3D driver must	 * throttle the framerate by waiting for this value before	 * performing the swapbuffer ioctl.	 */	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;}void i810_dma_quiescent(drm_device_t *dev){      	drm_i810_private_t *dev_priv = dev->dev_private;   	RING_LOCALS;/*  	printk("%s\n", __FUNCTION__); */  	i810_kernel_lost_context(dev);   	BEGIN_LP_RING(4);   	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );   	OUT_RING( CMD_REPORT_HEAD );      	OUT_RING( 0 );      	OUT_RING( 0 );   	ADVANCE_LP_RING();	i810_wait_ring( dev, dev_priv->ring.Size - 8 );}static int i810_flush_queue(drm_device_t *dev){   	drm_i810_private_t *dev_priv = dev->dev_private;	drm_device_dma_t *dma = dev->dma;   	int i, ret = 0;   	RING_LOCALS;	/*  	printk("%s\n", __FUNCTION__); */   	i810_kernel_lost_context(dev);   	BEGIN_LP_RING(2);      	OUT_RING( CMD_REPORT_HEAD );      	OUT_RING( 0 );      	ADVANCE_LP_RING();	i810_wait_ring( dev, dev_priv->ring.Size - 8 );   	for (i = 0; i < dma->buf_count; i++) {	   	drm_buf_t *buf = dma->buflist[ i ];	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;		int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,				   I810_BUF_FREE);		if (used == I810_BUF_HARDWARE)			DRM_DEBUG("reclaimed from HARDWARE\n");		if (used == I810_BUF_CLIENT)			DRM_DEBUG("still on client\n");	}   	return ret;}/* Must be called with the lock held */void i810_reclaim_buffers(struct file *filp){	drm_file_t    *priv   = filp->private_data;	drm_device_t  *dev    = priv->dev;	drm_device_dma_t *dma = dev->dma;	int		 i;	if (!dma) return;      	if (!dev->dev_private) return;	if (!dma->buflist) return;        i810_flush_queue(dev);	for (i = 0; i < dma->buf_count; i++) {	   	drm_buf_t *buf = dma->buflist[ i ];	   	drm_i810_buf_priv_t *buf_priv = buf->dev_private;		if (buf->filp == filp && buf_priv) {			int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,					   I810_BUF_FREE);			if (used == I810_BUF_CLIENT)				DRM_DEBUG("reclaimed from client\n");			if (buf_priv->currently_mapped == I810_BUF_MAPPED)		     		buf_priv->currently_mapped = I810_BUF_UNMAPPED;		}	}}int i810_flush_ioctl(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;	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("i810_flush_ioctl called without lock held\n");		return -EINVAL;	}   	i810_flush_queue(dev);   	return 0;}int i810_dma_vertex(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_device_dma_t *dma = dev->dma;   	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;      	u32 *hw_status = dev_priv->hw_status_page;   	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)     					dev_priv->sarea_priv;	drm_i810_vertex_t vertex;	if (copy_from_user(&vertex, (drm_i810_vertex_t __user *)arg, sizeof(vertex)))		return -EFAULT;	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("i810_dma_vertex called without lock held\n");		return -EINVAL;	}	DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",		  vertex.idx, vertex.used, vertex.discard);	if (vertex.idx < 0 || vertex.idx > dma->buf_count) 		return -EINVAL;	i810_dma_dispatch_vertex( dev,				  dma->buflist[ vertex.idx ],				  vertex.discard, vertex.used );   	atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);	atomic_inc(&dev->counts[_DRM_STAT_DMA]);	sarea_priv->last_enqueue = dev_priv->counter-1;   	sarea_priv->last_dispatch = (int) hw_status[5];	return 0;}int i810_clear_bufs(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_clear_t clear;   	if (copy_from_user(&clear, (drm_i810_clear_t __user *)arg, sizeof(clear)))		return -EFAULT;	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("i810_clear_bufs called without lock held\n");		return -EINVAL;	} 	/* GH: Someone's doing nasty things... */ 	if (!dev->dev_private) { 		return -EINVAL; 	}	i810_dma_dispatch_clear( dev, clear.flags,				 clear.clear_color,				 clear.clear_depth );   	return 0;}int i810_swap_bufs(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_DEBUG("i810_swap_bufs\n");	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("i810_swap_buf called without lock held\n");		return -EINVAL;	}	i810_dma_dispatch_swap( dev );   	return 0;}int i810_getage(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_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;      	u32 *hw_status = dev_priv->hw_status_page;   	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)     					dev_priv->sarea_priv;      	sarea_priv->last_dispatch = (int) hw_status[5];	return 0;}int i810_getbuf(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;	int		  retcode   = 0;	drm_i810_dma_t	  d;   	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;   	u32 *hw_status = dev_priv->hw_status_page;   	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)     					dev_priv->sarea_priv;   	if (copy_from_user(&d, (drm_i810_dma_t __user *)arg, sizeof(d)))		return -EFAULT;	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("i810_dma called without lock held\n");		return -EINVAL;	}	d.granted = 0;	retcode = i810_dma_get_buffer(dev, &d, filp);	DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",		  current->pid, retcode, d.granted);	if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d)))		return -EFAULT;   	sarea_priv->last_dispatch = (int) hw_status[5];	return retcode;}int i810_copybuf(struct inode *inode,		 struct file *filp, 		 unsigned int cmd,		 unsigned long arg){	/* Never copy - 2.4.x doesn't need it */	return 0;}int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,		unsigned long arg){	/* Never copy - 2.4.x doesn't need it */	return 0;}static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,		unsigned int last_render){	drm_i810_private_t *dev_priv = dev->dev_private;	drm_i810_buf_priv_t *buf_priv = buf->dev_private;	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;	unsigned long address = (unsigned long)buf->bus_address;	unsigned long start = address - dev->agp->base;	int u;	RING_LOCALS;	i810_kernel_lost_context(dev);	u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,		I810_BUF_HARDWARE);	if (u != I810_BUF_CLIENT) {		DRM_DEBUG("MC found buffer that isn't mine!\n");	}	if (used > 4*1024)		used = 0;	sarea_priv->dirty = 0x7f;	DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n",		address, used);	dev_priv->counter++;	DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);	DRM_DEBUG("i810_dma_dispatch_mc\n");	DRM_DEBUG("start : %lx\n", start);	DRM_DEBUG("used : %d\n", used);	DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);	if (buf_priv->currently_mapped == I810_BUF_MAPPED) {		if (used & 4) {			*(u32 *)((u32)buf_priv->virtual + used) = 0;			used += 4;		}		i810_unmap_buffer(buf);	}	BEGIN_LP_RING(4);	OUT_RING( CMD_OP_BATCH_BUFFER );	OUT_RING( start | BB1_PROTECTED );	OUT_RING( start + used - 4 );	OUT_RING( 0 );	ADVANCE_LP_RING();	BEGIN_LP_RING(8);	OUT_RING( CMD_STORE_DWORD_IDX );	OUT_RING( buf_priv->my_use_idx );	OUT_RING( I810_BUF_FREE );	OUT_RING( 0 );	OUT_RING( CMD_STORE_DWORD_IDX );	OUT_RING( 16 );	OUT_RING( last_render );	OUT_RING( 0 );	ADVANCE_LP_RING();}int i810_dma_mc(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_device_dma_t *dma = dev->dma;	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;	u32 *hw_status = dev_priv->hw_status_page;	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)		dev_priv->sarea_priv;	drm_i810_mc_t mc;	if (copy_from_user(&mc, (drm_i810_mc_t __user *)arg, sizeof(mc)))		return -EFAULT;	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("i810_dma_mc called without lock held\n");		return -EINVAL;	}	if (mc.idx >= dma->buf_count || mc.idx < 0)		return -EINVAL;	i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used,		mc.last_render );	atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]);	atomic_inc(&dev->counts[_DRM_STAT_DMA]);	sarea_priv->last_enqueue = dev_priv->counter-1;	sarea_priv->last_dispatch = (int) hw_status[5];	return 0;}int i810_rstatus(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_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;	return (int)(((u32 *)(dev_priv->hw_status_page))[4]);}int i810_ov0_info(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_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;	drm_i810_overlay_t data;	data.offset = dev_priv->overlay_offset;	data.physical = dev_priv->overlay_physical;	if (copy_to_user((drm_i810_overlay_t __user *)arg,&data,sizeof(data)))		return -EFAULT;	return 0;}int i810_fstatus(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_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("i810_fstatus called without lock held\n");		return -EINVAL;	}	return I810_READ(0x30008);}int i810_ov0_flip(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_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("i810_ov0_flip called without lock held\n");		return -EINVAL;	}	//Tell the overlay to update	I810_WRITE(0x30000,dev_priv->overlay_physical | 0x80000000);	return 0;}/* Not sure why this isn't set all the time: */ static void i810_do_init_pageflip( drm_device_t *dev ){	drm_i810_private_t *dev_priv = dev->dev_private;		DRM_DEBUG("%s\n", __FUNCTION__);	dev_priv->page_flipping = 1;	dev_priv->current_page = 0;	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;}int i810_do_cleanup_pageflip( drm_device_t *dev ){	drm_i810_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("%s\n", __FUNCTION__);	if (dev_priv->current_page != 0)		i810_dma_dispatch_flip( dev );	dev_priv->page_flipping = 0;	return 0;}int i810_flip_bufs(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_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("%s\n", __FUNCTION__);	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {		DRM_ERROR("i810_flip_buf called without lock held\n");		return -EINVAL;	}	if (!dev_priv->page_flipping) 		i810_do_init_pageflip( dev );	i810_dma_dispatch_flip( dev );   	return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?