i830_dma.c

来自「底层驱动开发」· C语言 代码 · 共 1,601 行 · 第 1/3 页

C
1,601
字号
	BEGIN_LP_RING( 2 );    	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); 	OUT_RING( 0 );	ADVANCE_LP_RING();	BEGIN_LP_RING( 6 );	OUT_RING( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP );		OUT_RING( 0 );	if ( dev_priv->current_page == 0 ) {		OUT_RING( dev_priv->back_offset );		dev_priv->current_page = 1;	} else {		OUT_RING( dev_priv->front_offset );		dev_priv->current_page = 0;	}	OUT_RING(0);	ADVANCE_LP_RING();	BEGIN_LP_RING( 2 );	OUT_RING( MI_WAIT_FOR_EVENT |		  MI_WAIT_FOR_PLANE_A_FLIP );	OUT_RING( 0 );	ADVANCE_LP_RING();		dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;}static void i830_dma_dispatch_vertex(drm_device_t *dev, 				     drm_buf_t *buf,				     int discard,				     int used){   	drm_i830_private_t *dev_priv = dev->dev_private;	drm_i830_buf_priv_t *buf_priv = buf->dev_private;   	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;   	drm_clip_rect_t *box = sarea_priv->boxes;   	int nbox = sarea_priv->nbox;	unsigned long address = (unsigned long)buf->bus_address;	unsigned long start = address - dev->agp->base;     	int i = 0, u;   	RING_LOCALS;   	i830_kernel_lost_context(dev);   	if (nbox > I830_NR_SAREA_CLIPRECTS) 		nbox = I830_NR_SAREA_CLIPRECTS;	if (discard) {		u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 			    I830_BUF_HARDWARE);		if(u != I830_BUF_CLIENT) {			DRM_DEBUG("xxxx 2\n");		}	}	if (used > 4*1023) 		used = 0;	if (sarea_priv->dirty)	   i830EmitState( dev );  	DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", 		  address, used, nbox);   	dev_priv->counter++;   	DRM_DEBUG(  "dispatch counter : %ld\n", dev_priv->counter);   	DRM_DEBUG(  "i830_dma_dispatch\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 == I830_BUF_MAPPED) {		u32 *vp = buf_priv->kernel_virtual;		vp[0] = (GFX_OP_PRIMITIVE |			sarea_priv->vertex_prim |			((used/4)-2));		if (dev_priv->use_mi_batchbuffer_start) {			vp[used/4] = MI_BATCH_BUFFER_END;			used += 4; 		}				if (used & 4) {			vp[used/4] = 0;			used += 4;		}		i830_unmap_buffer(buf);	}		   	if (used) {		do {			if (i < nbox) {				BEGIN_LP_RING(6);				OUT_RING( GFX_OP_DRAWRECT_INFO );				OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR1] );				OUT_RING( box[i].x1 | (box[i].y1<<16) );				OUT_RING( box[i].x2 | (box[i].y2<<16) );				OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR4] );				OUT_RING( 0 );				ADVANCE_LP_RING();			}			if (dev_priv->use_mi_batchbuffer_start) {				BEGIN_LP_RING(2);				OUT_RING( MI_BATCH_BUFFER_START | (2<<6) );				OUT_RING( start | MI_BATCH_NON_SECURE );				ADVANCE_LP_RING();			} 			else {				BEGIN_LP_RING(4);				OUT_RING( MI_BATCH_BUFFER );				OUT_RING( start | MI_BATCH_NON_SECURE );				OUT_RING( start + used - 4 );				OUT_RING( 0 );				ADVANCE_LP_RING();			}		} while (++i < nbox);	}	if (discard) {		dev_priv->counter++;		(void) cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,			       I830_BUF_HARDWARE);		BEGIN_LP_RING(8);		OUT_RING( CMD_STORE_DWORD_IDX );		OUT_RING( 20 );		OUT_RING( dev_priv->counter );		OUT_RING( CMD_STORE_DWORD_IDX );		OUT_RING( buf_priv->my_use_idx );		OUT_RING( I830_BUF_FREE );		OUT_RING( CMD_REPORT_HEAD );		OUT_RING( 0 );		ADVANCE_LP_RING();	}}static void i830_dma_quiescent(drm_device_t *dev){      	drm_i830_private_t *dev_priv = dev->dev_private;   	RING_LOCALS;  	i830_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();	i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );}static int i830_flush_queue(drm_device_t *dev){   	drm_i830_private_t *dev_priv = dev->dev_private;	drm_device_dma_t *dma = dev->dma;   	int i, ret = 0;   	RING_LOCALS;	   	i830_kernel_lost_context(dev);   	BEGIN_LP_RING(2);      	OUT_RING( CMD_REPORT_HEAD );      	OUT_RING( 0 );      	ADVANCE_LP_RING();	i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );   	for (i = 0; i < dma->buf_count; i++) {	   	drm_buf_t *buf = dma->buflist[ i ];	   	drm_i830_buf_priv_t *buf_priv = buf->dev_private;	   		int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE, 				   I830_BUF_FREE);		if (used == I830_BUF_HARDWARE)			DRM_DEBUG("reclaimed from HARDWARE\n");		if (used == I830_BUF_CLIENT)			DRM_DEBUG("still on client\n");	}   	return ret;}/* Must be called with the lock held */void i830_reclaim_buffers(drm_device_t *dev, struct file *filp){	drm_device_dma_t *dma = dev->dma;	int		 i;	if (!dma) return;      	if (!dev->dev_private) return;	if (!dma->buflist) return;        i830_flush_queue(dev);	for (i = 0; i < dma->buf_count; i++) {	   	drm_buf_t *buf = dma->buflist[ i ];	   	drm_i830_buf_priv_t *buf_priv = buf->dev_private;	   		if (buf->filp == filp && buf_priv) {			int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 					   I830_BUF_FREE);			if (used == I830_BUF_CLIENT)				DRM_DEBUG("reclaimed from client\n");		   	if(buf_priv->currently_mapped == I830_BUF_MAPPED)		     		buf_priv->currently_mapped = I830_BUF_UNMAPPED;		}	}}static int i830_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->head->dev;	LOCK_TEST_WITH_RETURN(dev, filp);   	i830_flush_queue(dev);   	return 0;}static int i830_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->head->dev;	drm_device_dma_t *dma = dev->dma;   	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;      	u32 *hw_status = dev_priv->hw_status_page;   	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)      					dev_priv->sarea_priv; 	drm_i830_vertex_t vertex;	if (copy_from_user(&vertex, (drm_i830_vertex_t __user *)arg, sizeof(vertex)))		return -EFAULT;	LOCK_TEST_WITH_RETURN(dev, filp);	DRM_DEBUG("i830 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;	i830_dma_dispatch_vertex( dev, 				  dma->buflist[ vertex.idx ], 				  vertex.discard, vertex.used );	sarea_priv->last_enqueue = dev_priv->counter-1;   	sarea_priv->last_dispatch = (int) hw_status[5];   	return 0;}static int i830_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->head->dev;	drm_i830_clear_t clear;   	if (copy_from_user(&clear, (drm_i830_clear_t __user *)arg, sizeof(clear)))		return -EFAULT;   	LOCK_TEST_WITH_RETURN(dev, filp);	/* GH: Someone's doing nasty things... */	if (!dev->dev_private) {		return -EINVAL;	}	i830_dma_dispatch_clear( dev, clear.flags, 				 clear.clear_color, 				 clear.clear_depth,			         clear.clear_depthmask);   	return 0;}static int i830_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->head->dev;   	DRM_DEBUG("i830_swap_bufs\n");	LOCK_TEST_WITH_RETURN(dev, filp);	i830_dma_dispatch_swap( dev );   	return 0;}/* Not sure why this isn't set all the time: */ static void i830_do_init_pageflip( drm_device_t *dev ){	drm_i830_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;}static int i830_do_cleanup_pageflip( drm_device_t *dev ){	drm_i830_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("%s\n", __FUNCTION__);	if (dev_priv->current_page != 0)		i830_dma_dispatch_flip( dev );	dev_priv->page_flipping = 0;	return 0;}static int i830_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->head->dev;	drm_i830_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("%s\n", __FUNCTION__);	LOCK_TEST_WITH_RETURN(dev, filp);	if (!dev_priv->page_flipping) 		i830_do_init_pageflip( dev );	i830_dma_dispatch_flip( dev );   	return 0;}static int i830_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->head->dev;   	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;      	u32 *hw_status = dev_priv->hw_status_page;   	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)      					dev_priv->sarea_priv;       	sarea_priv->last_dispatch = (int) hw_status[5];	return 0;}static int i830_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->head->dev;	int		  retcode   = 0;	drm_i830_dma_t	  d;   	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;   	u32 *hw_status = dev_priv->hw_status_page;   	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)      					dev_priv->sarea_priv; 	DRM_DEBUG("getbuf\n");   	if (copy_from_user(&d, (drm_i830_dma_t __user *)arg, sizeof(d)))		return -EFAULT;   	LOCK_TEST_WITH_RETURN(dev, filp);		d.granted = 0;	retcode = i830_dma_get_buffer(dev, &d, filp);	DRM_DEBUG("i830_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;}static int i830_copybuf(struct inode *inode,			 struct file *filp, unsigned int cmd, unsigned long arg){	/* Never copy - 2.4.x doesn't need it */	return 0;}static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,			unsigned long arg){	return 0;}static int i830_getparam( struct inode *inode, struct file *filp, 			unsigned int cmd, unsigned long arg ){	drm_file_t	  *priv	    = filp->private_data;	drm_device_t	  *dev	    = priv->head->dev;	drm_i830_private_t *dev_priv = dev->dev_private;	drm_i830_getparam_t param;	int value;	if ( !dev_priv ) {		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );		return -EINVAL;	}	if (copy_from_user(&param, (drm_i830_getparam_t __user *)arg, sizeof(param) ))		return -EFAULT;	switch( param.param ) {	case I830_PARAM_IRQ_ACTIVE:		value = dev->irq_enabled;		break;	default:		return -EINVAL;	}	if ( copy_to_user( param.value, &value, sizeof(int) ) ) {		DRM_ERROR( "copy_to_user\n" );		return -EFAULT;	}		return 0;}static int i830_setparam( struct inode *inode, struct file *filp,			unsigned int cmd, unsigned long arg ){	drm_file_t	  *priv	    = filp->private_data;	drm_device_t	  *dev	    = priv->head->dev;	drm_i830_private_t *dev_priv = dev->dev_private;	drm_i830_setparam_t param;	if ( !dev_priv ) {		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );		return -EINVAL;	}	if (copy_from_user(&param, (drm_i830_setparam_t __user *)arg, sizeof(param) ))		return -EFAULT;	switch( param.param ) {	case I830_SETPARAM_USE_MI_BATCHBUFFER_START:		dev_priv->use_mi_batchbuffer_start = param.value;		break;	default:		return -EINVAL;	}	return 0;}void i830_driver_pretakedown(drm_device_t *dev){	i830_dma_cleanup( dev );}void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp){	if (dev->dev_private) {		drm_i830_private_t *dev_priv = dev->dev_private;		if (dev_priv->page_flipping) {			i830_do_cleanup_pageflip(dev);		}	}}void i830_driver_release(drm_device_t *dev, struct file *filp){	i830_reclaim_buffers(dev, filp);}int i830_driver_dma_quiescent(drm_device_t *dev){	i830_dma_quiescent( dev );	return 0;}drm_ioctl_desc_t i830_ioctls[] = {	[DRM_IOCTL_NR(DRM_I830_INIT)]     = { i830_dma_init,    1, 1 },	[DRM_IOCTL_NR(DRM_I830_VERTEX)]   = { i830_dma_vertex,  1, 0 },	[DRM_IOCTL_NR(DRM_I830_CLEAR)]    = { i830_clear_bufs,  1, 0 },	[DRM_IOCTL_NR(DRM_I830_FLUSH)]    = { i830_flush_ioctl, 1, 0 },	[DRM_IOCTL_NR(DRM_I830_GETAGE)]   = { i830_getage,      1, 0 },	[DRM_IOCTL_NR(DRM_I830_GETBUF)]   = { i830_getbuf,      1, 0 },	[DRM_IOCTL_NR(DRM_I830_SWAP)]     = { i830_swap_bufs,   1, 0 },	[DRM_IOCTL_NR(DRM_I830_COPY)]     = { i830_copybuf,     1, 0 },	[DRM_IOCTL_NR(DRM_I830_DOCOPY)]   = { i830_docopy,      1, 0 },	[DRM_IOCTL_NR(DRM_I830_FLIP)]     = { i830_flip_bufs,   1, 0 },	[DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = { i830_irq_emit,    1, 0 },	[DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = { i830_irq_wait,    1, 0 },	[DRM_IOCTL_NR(DRM_I830_GETPARAM)] = { i830_getparam,    1, 0 },	[DRM_IOCTL_NR(DRM_I830_SETPARAM)] = { i830_setparam,    1, 0 } };int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);/** * Determine if the device really is AGP or not. * * All Intel graphics chipsets are treated as AGP, even if they are really * PCI-e. * * \param dev   The device to be tested. * * \returns * A value of 1 is always retured to indictate every i8xx is AGP. */int i830_driver_device_is_agp(drm_device_t * dev){	return 1;}

⌨️ 快捷键说明

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