diff options
author | Jose Fonseca <jrfonseca@users.sourceforge.net> | 2002-06-19 18:57:23 +0000 |
---|---|---|
committer | Jose Fonseca <jrfonseca@users.sourceforge.net> | 2002-06-19 18:57:23 +0000 |
commit | 8a6e0b2caae2e993fc2f3d91c42624df9ae3fd0f (patch) | |
tree | ed89783a22c70fb5cf852e662f8cf283d533110c /linux | |
parent | f7aa134628afc57ac02cd724ef8dd4731496375a (diff) |
Use of atomic bit ops in ADVANCE_RING() to lock the BUS when writing to the
descriptor table. Slight changes to make the GUI master operations be
handled more similarly to the Mach64 SDK example.
Diffstat (limited to 'linux')
-rw-r--r-- | linux/mach64_dma.c | 4 | ||||
-rw-r--r-- | linux/mach64_drv.h | 80 |
2 files changed, 57 insertions, 27 deletions
diff --git a/linux/mach64_dma.c b/linux/mach64_dma.c index af36c250..ce48534d 100644 --- a/linux/mach64_dma.c +++ b/linux/mach64_dma.c @@ -489,12 +489,16 @@ static int mach64_bm_dma_test( drm_device_t *dev ) data_addr = (u32) data_handle; } + mach64_do_wait_for_fifo( dev_priv, 4 ); + MACH64_WRITE( MACH64_SRC_CNTL, 0 ); MACH64_WRITE( MACH64_VERTEX_1_S, 0x00000000 ); MACH64_WRITE( MACH64_VERTEX_1_T, 0x00000000 ); MACH64_WRITE( MACH64_VERTEX_1_W, 0x00000000 ); + mach64_do_wait_for_idle( dev_priv ); + for (i=0; i < 3; i++) { DRM_DEBUG( "(Before DMA Transfer) reg %d = 0x%08x\n", i, MACH64_READ( (MACH64_VERTEX_1_S + i*4) ) ); diff --git a/linux/mach64_drv.h b/linux/mach64_drv.h index 2ae2e86f..49ba5048 100644 --- a/linux/mach64_drv.h +++ b/linux/mach64_drv.h @@ -476,12 +476,6 @@ static inline void mach64_ring_start( drm_mach64_private_t *dev_priv ) ( MACH64_READ(MACH64_BUS_CNTL) & ~MACH64_BUS_MASTER_DIS ) | MACH64_BUS_EXT_REG_EN ); - /* enable GUI bus mastering, and sync the bus master to the GUI */ - MACH64_WRITE( MACH64_SRC_CNTL, - MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC | - MACH64_SRC_BM_OP_SYSTEM_TO_REG ); - - /* FIXME: See mach64_ring_resume */ mach64_do_wait_for_idle( dev_priv ); dev_priv->ring_running = 1; @@ -493,25 +487,11 @@ static inline void mach64_ring_resume( drm_mach64_private_t *dev_priv, drm_mach6 __FUNCTION__, ring->head_addr, ring->head, ring->tail, ring->space); -#if 0 - /* FIXME: at this moment this is always called on idle but we could gain something by just - * wait for FIFO when resuming the BM and in that case we will have to check for the apropriate - * number of free entries here - */ - mach64_do_wait_for_fifo( dev_priv, 2 ); -#endif - #if MACH64_EXTRA_CHECKING - if ( !(MACH64_READ(MACH64_SRC_CNTL) & MACH64_SRC_BM_ENABLE) ) { - DRM_ERROR("Call of %s without BM enabled!!!\n", __FUNCTION__ ); - mach64_dump_ring_info( dev_priv ); - return; - } - if ( MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE ) { DRM_ERROR("Call of %s with GUI ACTIVE!!!\n", __FUNCTION__ ); mach64_dump_ring_info( dev_priv ); - return; + mach64_do_wait_for_idle( dev_priv ); } if( ring->head_addr < ring->start_addr || ring->head_addr >= ring->start_addr + ring->size ) { @@ -524,6 +504,11 @@ static inline void mach64_ring_resume( drm_mach64_private_t *dev_priv, drm_mach6 /* reset descriptor table ring head */ MACH64_WRITE( MACH64_BM_GUI_TABLE_CMD, ring->head_addr | MACH64_CIRCULAR_BUF_SIZE_16KB ); + /* enable GUI bus mastering, and sync the bus master to the GUI */ + MACH64_WRITE( MACH64_SRC_CNTL, + MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC | + MACH64_SRC_BM_OP_SYSTEM_TO_REG ); + /* kick off the transfer */ MACH64_WRITE( MACH64_DST_HEIGHT_WIDTH, 0 ); } @@ -538,11 +523,9 @@ static inline void mach64_ring_stop( drm_mach64_private_t *dev_priv ) mach64_do_wait_for_fifo( dev_priv, 1 ); MACH64_WRITE( MACH64_SRC_CNTL, 0 ); -#if 1 - /* FIXME: This probably can be safely removed from here. */ + /* disable busmastering but keep the block 1 registers enabled */ mach64_do_wait_for_idle( dev_priv ); MACH64_WRITE( MACH64_BUS_CNTL, MACH64_READ( MACH64_BUS_CNTL ) | MACH64_BUS_MASTER_DIS | MACH64_BUS_EXT_REG_EN ); -#endif dev_priv->ring_running = 0; } @@ -556,7 +539,6 @@ do { \ mach64_ring_start( dev_priv ); \ } \ /* GUI_ACTIVE must be read before BM_GUI_TABLE to correctly determine the ring head */ \ - /* FIXME: See mach64_ring_resume */ \ gui_active = MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE; \ (ring)->head_addr = MACH64_READ(MACH64_BM_GUI_TABLE) & 0xfffffff0; \ if ( gui_active ) { \ @@ -662,7 +644,7 @@ do { \ * DMA descriptor ring macros */ -#define RING_LOCALS int tail, write; unsigned int mask; volatile u32 *ring; +#define RING_LOCALS int tail, write; unsigned int mask; volatile u32 *ring #define RING_WRITE_OFS write @@ -699,6 +681,49 @@ do { \ write &= mask; \ } while (0) + +#if defined(__i386__) + +/* Taken from include/asm-i386/bitops.h linux header */ +static __inline__ void mach64_clear_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( "lock;" + "btrl %1,%0" + :"=m" (*(volatile long *) addr) + :"Ir" (nr)); +} + +#elif defined(__powerpc__) + +/* Taken from the include/asm-ppc/bitops.h linux header */ +static __inline__ void mach64_clear_bit(int nr, volatile void *addr) +{ + unsigned long old; + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); + + __asm__ __volatile__("\n\ +1: lwarx %0,0,%3 \n\ + andc %0,%0,%2 \n\ + stwcx. %0,0,%3 \n\ + bne- 1b" + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc"); +} + +#else + +static __inline__ void mach64_clear_bit(int nr, volatile void *addr) +{ + unsigned long mask = 1 << (nr & 0x1f); + volatile unsigned long *p = ((unsigned long *)addr) + (nr >> 5); + + *p &= ~mask; +} + +#endif + #define ADVANCE_RING() \ do { \ if ( MACH64_VERBOSE ) { \ @@ -706,7 +731,8 @@ do { \ write, tail ); \ } \ mach64_flush_write_combine(); \ - ring[(tail - 2) & mask] &= cpu_to_le32( ~DMA_EOL ); \ + /* Clear DMA_EOL */ \ + mach64_clear_bit(31, &ring[(tail - 2) & mask]); \ mach64_flush_write_combine(); \ dev_priv->ring.tail = write; \ UPDATE_RING_HEAD( dev_priv, &(dev_priv)->ring ); \ |