diff options
Diffstat (limited to 'linux/mga_dma.c')
-rw-r--r-- | linux/mga_dma.c | 111 |
1 files changed, 82 insertions, 29 deletions
diff --git a/linux/mga_dma.c b/linux/mga_dma.c index b1491823..d314a1a8 100644 --- a/linux/mga_dma.c +++ b/linux/mga_dma.c @@ -56,7 +56,10 @@ int mga_do_wait_for_idle( drm_mga_private_t *dev_priv ) for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK; - if ( status == MGA_ENDPRDMASTS ) return 0; + if ( status == MGA_ENDPRDMASTS ) { + MGA_WRITE8( MGA_CRTC_INDEX, 0 ); + return 0; + } udelay( 1 ); } @@ -80,33 +83,37 @@ int mga_do_dma_idle( drm_mga_private_t *dev_priv ) return -EBUSY; } -int mga_do_dma_reset( drm_mga_private_t *dev_priv ) +int mga_do_dma_reset( drm_device_t *dev ) { + drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mga_primary_buffer_t *primary = &dev_priv->prim; - DRM_DEBUG( "%s\n", __FUNCTION__ ); + DRM_INFO( "%s\n", __FUNCTION__ ); /* The primary DMA stream should look like new right about now. */ primary->tail = 0; primary->space = primary->size; primary->last_flush = 0; + primary->last_wrap = 0; - sarea_priv->last_wrap = 0; + primary->status[0] = dev_priv->primary->offset; + primary->status[1] = 0; - /* FIXME: Reset counters, buffer ages etc... - */ + sarea_priv->last_wrap = 0; + sarea_priv->last_frame.head = 0; + sarea_priv->last_frame.wrap = 0; - /* FIXME: What else do we need to reinitialize? WARP stuff? - */ + mga_freelist_reset( dev ); return 0; } -int mga_do_engine_reset( drm_mga_private_t *dev_priv ) +int mga_do_engine_reset( drm_device_t *dev ) { - DRM_DEBUG( "%s\n", __FUNCTION__ ); + drm_mga_private_t *dev_priv = dev->dev_private; + DRM_INFO( "%s\n", __FUNCTION__ ); /* Okay, so we've completely screwed up and locked the engine. * How about we clean up after ourselves? @@ -122,19 +129,21 @@ int mga_do_engine_reset( drm_mga_private_t *dev_priv ) * 3D clients should probably die after calling this. The X * server should reset the engine state to known values. */ -#if 0 MGA_WRITE( MGA_PRIMPTR, - virt_to_bus((void *)dev_priv->prim.status_page) | - MGA_PRIMPTREN0 | - MGA_PRIMPTREN1 ); -#endif - - MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR ); - MGA_WRITE( MGA_IEN, MGA_SOFTRAPIEN ); + virt_to_bus((void *)dev_priv->prim.status) | + MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */ + MGA_PRIMPTREN1 ); /* DWGSYNC */ /* The primary DMA stream should look like new right about now. */ - mga_do_dma_reset( dev_priv ); + mga_do_dma_reset( dev ); + + /* Initialize the WARP engine again. + */ + if ( mga_warp_init( dev_priv ) < 0 ) { + /* Can we do anything else? */ + DRM_ERROR( "failed to reinit WARP engine!\n" ); + } /* This bad boy will never fail. */ @@ -269,7 +278,8 @@ static void mga_freelist_print( drm_device_t *dev ) DRM_INFO( "\n" ); DRM_INFO( "current dispatch: last=0x%x done=0x%x\n", dev_priv->sarea_priv->last_dispatch, - *dev_priv->prim.head - dev_priv->primary->offset ); + (unsigned int)(*dev_priv->prim.head - + dev_priv->primary->offset) ); DRM_INFO( "current freelist:\n" ); for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) { @@ -350,7 +360,6 @@ static void mga_freelist_cleanup( drm_device_t *dev ) static void mga_freelist_reset( drm_device_t *dev ) { drm_device_dma_t *dma = dev->dma; - drm_mga_private_t *dev_priv = dev->dev_private; drm_buf_t *buf; drm_mga_buf_priv_t *buf_priv; int i; @@ -408,15 +417,17 @@ int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf ) dev_priv->primary->offset, buf_priv->list_entry->age.wrap ); - if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) { - SET_AGE( &next->age, MGA_BUFFER_FREE, 0 ); - } - /* Put buffer on the head + 1, as the head is a sentinal. */ + next = buf_priv->list_entry; head = dev_priv->head; prev = head->next; + + if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) { + SET_AGE( &next->age, MGA_BUFFER_FREE, 0 ); + } + head->next = next; prev->prev = next; next->prev = head; @@ -482,14 +493,14 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) DRM_IOREMAP( dev_priv->primary ); DRM_IOREMAP( dev_priv->buffers ); - ret = mga_warp_install_microcode( dev ); + ret = mga_warp_install_microcode( dev_priv ); if ( ret < 0 ) { DRM_ERROR( "failed to install WARP ucode!\n" ); mga_do_cleanup_dma( dev ); return ret; } - ret = mga_warp_init( dev ); + ret = mga_warp_init( dev_priv ); if ( ret < 0 ) { DRM_ERROR( "failed to init WARP engine!\n" ); mga_do_cleanup_dma( dev ); @@ -539,6 +550,49 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init ) return -ENOMEM; } + + if ( 0 ) { + drm_mga_primary_buffer_t *primary = &dev_priv->prim; + u32 tail; + DMA_LOCALS; + + BEGIN_DMA( 4 ); + + DMA_BLOCK( MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000 ); + + DMA_BLOCK( MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000 ); + + DMA_BLOCK( MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000 ); + + DMA_BLOCK( MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000, + MGA_DMAPAD, 0x00000000 ); + + ADVANCE_DMA(); + + tail = primary->tail + dev_priv->primary->offset - 4096; + + mga_flush_write_combine(); + MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER ); + + + if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { + DRM_INFO( "cool, we're fucked!\n" ); + mga_do_engine_reset( dev ); + } + } + + return 0; } @@ -627,11 +681,10 @@ int mga_dma_reset( struct inode *inode, struct file *filp, { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private; LOCK_TEST_WITH_RETURN( dev ); - return mga_do_dma_reset( dev_priv ); + return mga_do_dma_reset( dev ); } |