From 92b0aaa6fe787c2e17bba1973d19d6fd5a61d03a Mon Sep 17 00:00:00 2001 From: Gareth Hughes Date: Wed, 21 Mar 2001 13:10:27 +0000 Subject: - Fix MGA header info. - Update date strings. - Fix MGA hangs (undocumented side effects of DWGSYNC). - Remove idle before ILOAD??? Seems fine with the above fix. --- linux/mga_dma.c | 30 ++++++++++++++++++++++++------ linux/mga_drv.c | 4 ++-- linux/mga_drv.h | 45 ++++++++++++++++++++++++++++++++++++--------- linux/mga_state.c | 23 +++++++++++++++++++++-- 4 files changed, 83 insertions(+), 19 deletions(-) (limited to 'linux') 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; -- cgit v1.2.3