summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorGareth Hughes <gareth@users.sourceforge.net>2001-03-21 13:10:27 +0000
committerGareth Hughes <gareth@users.sourceforge.net>2001-03-21 13:10:27 +0000
commit92b0aaa6fe787c2e17bba1973d19d6fd5a61d03a (patch)
treea3e5c187618eea1fcc0381cdef540b4b88822dfc /linux
parentb90028231c5c73783ee45124903794970f244978 (diff)
- 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.
Diffstat (limited to 'linux')
-rw-r--r--linux/mga_dma.c30
-rw-r--r--linux/mga_drv.c4
-rw-r--r--linux/mga_drv.h45
-rw-r--r--linux/mga_state.c23
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;