diff options
Diffstat (limited to 'linux')
| -rw-r--r-- | linux/mga_dma.c | 30 | ||||
| -rw-r--r-- | linux/mga_drv.c | 4 | ||||
| -rw-r--r-- | linux/mga_drv.h | 45 | ||||
| -rw-r--r-- | linux/mga_state.c | 23 | 
4 files changed, 83 insertions, 19 deletions
diff --git a/linux/mga_dma.c b/linux/mga_dma.c index bfc661c3..66c9df9f 100644 --- a/linux/mga_dma.c +++ b/linux/mga_dma.c @@ -64,7 +64,10 @@ int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )  		udelay( 1 );  	} -	DRM_DEBUG( "failed! status=0x%08x\n", status ); +#if MGA_DMA_DEBUG +	DRM_ERROR( "failed!\n" ); +	DRM_INFO( "   status=0x%08x\n", status ); +#endif  	return -EBUSY;  } @@ -80,7 +83,9 @@ int mga_do_dma_idle( drm_mga_private_t *dev_priv )  		udelay( 1 );  	} -	DRM_DEBUG( "failed! status=0x%08x\n", status ); +#if MGA_DMA_DEBUG +	DRM_ERROR( "failed! status=0x%08x\n", status ); +#endif  	return -EBUSY;  } @@ -209,7 +214,7 @@ void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )  	DMA_BLOCK( MGA_DMAPAD,	0x00000000,  		   MGA_DMAPAD,	0x00000000,  		   MGA_DMAPAD,	0x00000000, -		   MGA_DWGSYNC,	0x12345678 ); +		   MGA_DMAPAD,	0x00000000 );  	ADVANCE_DMA(); @@ -236,11 +241,13 @@ void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )  	mga_flush_write_combine();  	MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); +	set_bit( 0, &primary->wrapped );  	DRM_DEBUG( "%s: done.\n", __FUNCTION__ );  }  void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )  { +	drm_mga_primary_buffer_t *primary = &dev_priv->prim;  	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;  	u32 head = dev_priv->primary->offset;  	DRM_DEBUG( "%s:\n", __FUNCTION__ ); @@ -251,6 +258,7 @@ void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )  	mga_flush_write_combine();  	MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL ); +	clear_bit( 0, &primary->wrapped );  	DRM_DEBUG( "%s: done.\n", __FUNCTION__ );  } @@ -542,6 +550,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )  	dev_priv->prim.tail = 0;  	dev_priv->prim.space = dev_priv->prim.size; +	dev_priv->prim.wrapped = 0;  	dev_priv->prim.last_flush = 0;  	dev_priv->prim.last_wrap = 0; @@ -633,15 +642,21 @@ int mga_dma_flush( struct inode *inode, struct file *filp,  		   (lock.flags & _DRM_LOCK_FLUSH_ALL) ?	"flush all, " : "",  		   (lock.flags & _DRM_LOCK_QUIESCENT) ?	"idle, " : "" ); -	WRAP_TEST_WITH_RETURN( dev_priv ); +	WRAP_WAIT_WITH_RETURN( dev_priv ); -#if 0  	if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {  		mga_do_dma_flush( dev_priv );  	} -#endif +  	if ( lock.flags & _DRM_LOCK_QUIESCENT ) { +#if MGA_DMA_DEBUG +		int ret = mga_do_wait_for_idle( dev_priv ); +		if ( ret < 0 ) +			DRM_INFO( __FUNCTION__": -EBUSY\n" ); +		return ret; +#else  		return mga_do_wait_for_idle( dev_priv ); +#endif  	} else {  		return 0;  	} @@ -693,6 +708,7 @@ int mga_dma_buffers( struct inode *inode, struct file *filp,  	drm_file_t *priv = filp->private_data;  	drm_device_t *dev = priv->dev;  	drm_device_dma_t *dma = dev->dma; +	drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;  	drm_dma_t d;  	int ret = 0; @@ -717,6 +733,8 @@ int mga_dma_buffers( struct inode *inode, struct file *filp,  		return -EINVAL;  	} +	WRAP_TEST_WITH_RETURN( dev_priv ); +  	d.granted_count = 0;  	if ( d.request_count ) { diff --git a/linux/mga_drv.c b/linux/mga_drv.c index 42794e82..bea65cfa 100644 --- a/linux/mga_drv.c +++ b/linux/mga_drv.c @@ -38,11 +38,11 @@  #define DRIVER_NAME		"mga"  #define DRIVER_DESC		"Matrox G200/G400" -#define DRIVER_DATE		"20010319" +#define DRIVER_DATE		"20010321"  #define DRIVER_MAJOR		3  #define DRIVER_MINOR		0 -#define DRIVER_PATCHLEVEL	1 +#define DRIVER_PATCHLEVEL	2  #define DRIVER_IOCTLS							   \  	[DRM_IOCTL_NR(DRM_IOCTL_DMA)]	      = { mga_dma_buffers, 1, 0 }, \ diff --git a/linux/mga_drv.h b/linux/mga_drv.h index bd33d9d1..bc70d750 100644 --- a/linux/mga_drv.h +++ b/linux/mga_drv.h @@ -38,6 +38,7 @@ typedef struct drm_mga_primary_buffer {  	u32 tail;  	int space; +	volatile int wrapped;  	volatile u32 *status; @@ -123,7 +124,6 @@ extern void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv );  extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ); -  				/* mga_state.c */  extern int  mga_dma_clear( struct inode *inode, struct file *filp,  			   unsigned int cmd, unsigned long arg ); @@ -193,10 +193,26 @@ do {									\  #define WRAP_TEST_WITH_RETURN( dev_priv )				\  do {									\ -	if ( dev_priv->sarea_priv->last_wrap <				\ -	     dev_priv->prim.last_wrap ) {				\ -		if ( mga_do_wait_for_idle( dev_priv ) < 0 )		\ +	if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {			\ +		if ( mga_is_idle( dev_priv ) ) {			\ +			mga_do_dma_wrap_end( dev_priv );		\ +		} else if ( dev_priv->prim.space <			\ +			    dev_priv->prim.high_mark ) {		\ +			if ( MGA_DMA_DEBUG )				\ +				DRM_INFO( __FUNCTION__": wrap...\n" );	\ +			return -EBUSY;					\ +		}							\ +	}								\ +} while (0) + +#define WRAP_WAIT_WITH_RETURN( dev_priv )				\ +do {									\ +	if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {			\ +		if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {		\ +			if ( MGA_DMA_DEBUG )				\ +				DRM_INFO( __FUNCTION__": wrap...\n" );	\  			return -EBUSY;					\ +		}							\  		mga_do_dma_wrap_end( dev_priv );			\  	}								\  } while (0) @@ -252,10 +268,13 @@ do {									\  			  MGA_READ( MGA_PRIMADDRESS ) -			\  			  dev_priv->primary->offset );			\  	}								\ -	if ( dev_priv->prim.space < dev_priv->prim.high_mark ) {	\ -		mga_do_dma_wrap_start( dev_priv );			\ -	} else {							\ -		mga_do_dma_flush( dev_priv );				\ +	if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) {		\ +		if ( dev_priv->prim.space <				\ +		     dev_priv->prim.high_mark ) {			\ +			mga_do_dma_wrap_start( dev_priv );		\ +		} else {						\ +			mga_do_dma_flush( dev_priv );			\ +		}							\  	}								\  } while (0) @@ -317,7 +336,7 @@ do {									\  #define MGA_DMA_IDLE_MASK		(MGA_SOFTRAPEN |		\  					 MGA_ENDPRDMASTS) -#define MGA_DMA_SOFTRAP_SIZE		32 * DMA_BLOCK_SIZE +#define MGA_DMA_DEBUG			0 @@ -599,4 +618,12 @@ do {									\  				 MGA_BLTMOD_BFCOL |			\  				 MGA_CLIPDIS) +/* Simple idle test. + */ +static inline int mga_is_idle( drm_mga_private_t *dev_priv ) +{ +	u32 status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK; +	return ( status == MGA_ENDPRDMASTS ); +} +  #endif diff --git a/linux/mga_state.c b/linux/mga_state.c index de5a4309..99778c58 100644 --- a/linux/mga_state.c +++ b/linux/mga_state.c @@ -515,6 +515,15 @@ static void mga_dma_dispatch_clear( drm_device_t *dev,  	DMA_LOCALS;  	DRM_DEBUG( __FUNCTION__ ":\n" ); +	BEGIN_DMA( 1 ); + +	DMA_BLOCK( MGA_DMAPAD,	0x00000000, +		   MGA_DMAPAD,	0x00000000, +		   MGA_DWGSYNC,	0x00007100, +		   MGA_DWGSYNC,	0x00007000 ); + +	ADVANCE_DMA(); +  	for ( i = 0 ; i < nbox ; i++ ) {  		drm_clip_rect_t *box = &pbox[i];  		u32 height = box->y2 - box->y1; @@ -757,7 +766,12 @@ static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf,  	y2 = length / 64; -	BEGIN_DMA( 4 ); +	BEGIN_DMA( 5 ); + +	DMA_BLOCK( MGA_DMAPAD,	0x00000000, +		   MGA_DMAPAD,	0x00000000, +		   MGA_DWGSYNC,	0x00007100, +		   MGA_DWGSYNC,	0x00007000 );  	DMA_BLOCK( MGA_DSTORG,	dstorg,  		   MGA_MACCESS,	0x00000000, @@ -1009,8 +1023,13 @@ int mga_dma_iload( struct inode *inode, struct file *filp,  	if ( copy_from_user( &iload, (drm_mga_iload_t *)arg, sizeof(iload) ) )  		return -EFAULT; -	if ( mga_do_wait_for_idle( dev_priv ) < 0 ) +#if 0 +	if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { +		if ( MGA_DMA_DEBUG ) +			DRM_INFO( __FUNCTION__": -EBUSY\n" );  		return -EBUSY; +	} +#endif  	buf = dma->buflist[iload.idx];  	buf_priv = buf->dev_private;  | 
