diff --git a/linux-core/mach64_drv.c b/linux-core/mach64_drv.c index 5063e523..4b44f182 100644 --- a/linux-core/mach64_drv.c +++ b/linux-core/mach64_drv.c @@ -37,22 +37,22 @@ #define DRIVER_NAME "mach64" #define DRIVER_DESC "DRM module for the ATI Rage Pro" -#define DRIVER_DATE "20010107" +#define DRIVER_DATE "20020417" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 -#define DRIVER_IOCTLS \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_INIT)] = { mach64_dma_init, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_CLEAR)] = { mach64_dma_clear, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_SWAP)] = { mach64_dma_swap, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_IDLE)] = { mach64_dma_idle, 1, 0 }, +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mach64_dma_buffers, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_INIT)] = { mach64_dma_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_CLEAR)] = { mach64_dma_clear, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_SWAP)] = { mach64_dma_swap, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_IDLE)] = { mach64_dma_idle, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_VERTEX)] = { mach64_dma_vertex, 1, 0 } #if 0 - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mach64_dma, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_VERTEX)] = { mach64_vertex, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MACH64_BLIT)] = { mach64_blit, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MACH64_FLUSH)] = { mach64_flush, 1, 0 }, #endif diff --git a/linux/drm.h b/linux/drm.h index a96b56d5..6fc2c259 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -456,7 +456,6 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_I810_MC DRM_IOW( 0x4c, drm_i810_mc_t) #define DRM_IOCTL_I810_RSTATUS DRM_IO ( 0x4d ) - /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) #define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) @@ -516,10 +515,13 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46) #define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t) #define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48) + /* Mach64 specific ioctls */ -#define DRM_IOCTL_MACH64_INIT DRM_IOW( 0x40, drm_mach64_init_t) -#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( 0x41, drm_mach64_clear_t) -#define DRM_IOCTL_MACH64_SWAP DRM_IO( 0x42) -#define DRM_IOCTL_MACH64_IDLE DRM_IO( 0x43) +#define DRM_IOCTL_MACH64_INIT DRM_IOW( 0x40, drm_mach64_init_t) +#define DRM_IOCTL_MACH64_IDLE DRM_IO( 0x41) +#define DRM_IOCTL_MACH64_RESET DRM_IO( 0x42) +#define DRM_IOCTL_MACH64_SWAP DRM_IO( 0x43) +#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( 0x44, drm_mach64_clear_t) +#define DRM_IOCTL_MACH64_VERTEX DRM_IOW( 0x45, drm_mach64_vertex_t) #endif diff --git a/linux/mach64_dma.c b/linux/mach64_dma.c index 1c1b5769..9f47670a 100644 --- a/linux/mach64_dma.c +++ b/linux/mach64_dma.c @@ -35,7 +35,7 @@ /* ================================================================ - * Engine control + * Engine, FIFO control */ int mach64_do_wait_for_fifo( drm_mach64_private_t *dev_priv, int entries ) @@ -72,217 +72,16 @@ int mach64_do_wait_for_idle( drm_mach64_private_t *dev_priv ) return -EBUSY; } -static void scratch_reg0_test(drm_mach64_private_t *dev_priv ) -{ - u32 scratch_reg0; - scratch_reg0=MACH64_READ( MACH64_SCRATCH_REG0 ); - - MACH64_WRITE( MACH64_SCRATCH_REG0, 0x55555555 ); - if ( MACH64_READ( MACH64_SCRATCH_REG0 ) == 0x55555555 ) { - MACH64_WRITE( MACH64_SCRATCH_REG0, 0xaaaaaaaa ); - - if ( MACH64_READ( MACH64_SCRATCH_REG0 ) != 0xaaaaaaaa ) { - DRM_ERROR( "2nd scratch reg failed!\n" ); - } - } else { - DRM_ERROR( "1st scratch reg failed!\n" ); - } - MACH64_WRITE( MACH64_SCRATCH_REG0, scratch_reg0 ); -} - -static void dump_engine_info( drm_mach64_private_t *dev_priv ) -{ - DRM_INFO( "\n" ); - if ( !dev_priv->is_pci) - { - DRM_INFO( " AGP_BASE = 0x%08x\n", MACH64_READ( MACH64_AGP_BASE ) ); - DRM_INFO( " AGP_CNTL = 0x%08x\n", MACH64_READ( MACH64_AGP_CNTL ) ); - } - DRM_INFO( " ALPHA_TST_CNTL = 0x%08x\n", MACH64_READ( MACH64_ALPHA_TST_CNTL ) ); - DRM_INFO( "\n" ); - DRM_INFO( " BM_COMMAND = 0x%08x\n", MACH64_READ( MACH64_BM_COMMAND ) ); - DRM_INFO( "BM_FRAME_BUF_OFFSET = 0x%08x\n", MACH64_READ( MACH64_BM_FRAME_BUF_OFFSET ) ); - DRM_INFO( " BM_GUI_TABLE = 0x%08x\n", MACH64_READ( MACH64_BM_GUI_TABLE ) ); - DRM_INFO( " BM_STATUS = 0x%08x\n", MACH64_READ( MACH64_BM_STATUS ) ); - DRM_INFO( " BM_SYSTEM_MEM_ADDR = 0x%08x\n", MACH64_READ( MACH64_BM_SYSTEM_MEM_ADDR ) ); - DRM_INFO( " BM_SYSTEM_TABLE = 0x%08x\n", MACH64_READ( MACH64_BM_SYSTEM_TABLE ) ); - DRM_INFO( " BUS_CNTL = 0x%08x\n", MACH64_READ( MACH64_BUS_CNTL ) ); - DRM_INFO( "\n" ); - /* DRM_INFO( " CLOCK_CNTL = 0x%08x\n", MACH64_READ( MACH64_CLOCK_CNTL ) ); */ - DRM_INFO( " CLR_CMP_CLR = 0x%08x\n", MACH64_READ( MACH64_CLR_CMP_CLR ) ); - DRM_INFO( " CLR_CMP_CNTL = 0x%08x\n", MACH64_READ( MACH64_CLR_CMP_CNTL ) ); - /* DRM_INFO( " CLR_CMP_MSK = 0x%08x\n", MACH64_READ( MACH64_CLR_CMP_MSK ) ); */ - DRM_INFO( " CONFIG_CHIP_ID = 0x%08x\n", MACH64_READ( MACH64_CONFIG_CHIP_ID ) ); - DRM_INFO( " CONFIG_CNTL = 0x%08x\n", MACH64_READ( MACH64_CONFIG_CNTL ) ); - DRM_INFO( " CONFIG_STAT0 = 0x%08x\n", MACH64_READ( MACH64_CONFIG_STAT0 ) ); - DRM_INFO( " CONFIG_STAT1 = 0x%08x\n", MACH64_READ( MACH64_CONFIG_STAT1 ) ); - DRM_INFO( " CONFIG_STAT2 = 0x%08x\n", MACH64_READ( MACH64_CONFIG_STAT2 ) ); - DRM_INFO( " CRC_SIG = 0x%08x\n", MACH64_READ( MACH64_CRC_SIG ) ); - DRM_INFO( " CUSTOM_MACRO_CNTL = 0x%08x\n", MACH64_READ( MACH64_CUSTOM_MACRO_CNTL ) ); - DRM_INFO( "\n" ); - /* DRM_INFO( " DAC_CNTL = 0x%08x\n", MACH64_READ( MACH64_DAC_CNTL ) ); */ - /* DRM_INFO( " DAC_REGS = 0x%08x\n", MACH64_READ( MACH64_DAC_REGS ) ); */ - DRM_INFO( " DP_BKGD_CLR = 0x%08x\n", MACH64_READ( MACH64_DP_BKGD_CLR ) ); - DRM_INFO( " DP_FRGD_CLR = 0x%08x\n", MACH64_READ( MACH64_DP_FRGD_CLR ) ); - DRM_INFO( " DP_MIX = 0x%08x\n", MACH64_READ( MACH64_DP_MIX ) ); - DRM_INFO( " DP_PIX_WIDTH = 0x%08x\n", MACH64_READ( MACH64_DP_PIX_WIDTH ) ); - DRM_INFO( " DP_SRC = 0x%08x\n", MACH64_READ( MACH64_DP_SRC ) ); - DRM_INFO( " DP_WRITE_MASK = 0x%08x\n", MACH64_READ( MACH64_DP_WRITE_MASK ) ); - DRM_INFO( " DSP_CONFIG = 0x%08x\n", MACH64_READ( MACH64_DSP_CONFIG ) ); - DRM_INFO( " DSP_ON_OFF = 0x%08x\n", MACH64_READ( MACH64_DSP_ON_OFF ) ); - DRM_INFO( " DST_CNTL = 0x%08x\n", MACH64_READ( MACH64_DST_CNTL ) ); - DRM_INFO( " DST_OFF_PITCH = 0x%08x\n", MACH64_READ( MACH64_DST_OFF_PITCH ) ); - DRM_INFO( "\n" ); - /* DRM_INFO( " EXT_DAC_REGS = 0x%08x\n", MACH64_READ( MACH64_EXT_DAC_REGS ) ); */ - DRM_INFO( " EXT_MEM_CNTL = 0x%08x\n", MACH64_READ( MACH64_EXT_MEM_CNTL ) ); - DRM_INFO( "\n" ); - DRM_INFO( " FIFO_STAT = 0x%08x\n", MACH64_READ( MACH64_FIFO_STAT ) ); - DRM_INFO( "\n" ); - DRM_INFO( " GEN_TEST_CNTL = 0x%08x\n", MACH64_READ( MACH64_GEN_TEST_CNTL ) ); - /* DRM_INFO( " GP_IO = 0x%08x\n", MACH64_READ( MACH64_GP_IO ) ); */ - DRM_INFO( " GUI_CMDFIFO_DATA = 0x%08x\n", MACH64_READ( MACH64_GUI_CMDFIFO_DATA ) ); - DRM_INFO( " GUI_CMDFIFO_DEBUG = 0x%08x\n", MACH64_READ( MACH64_GUI_CMDFIFO_DEBUG ) ); - DRM_INFO( " GUI_CNTL = 0x%08x\n", MACH64_READ( MACH64_GUI_CNTL ) ); - DRM_INFO( " GUI_STAT = 0x%08x\n", MACH64_READ( MACH64_GUI_STAT ) ); - DRM_INFO( " GUI_TRAJ_CNTL = 0x%08x\n", MACH64_READ( MACH64_GUI_TRAJ_CNTL ) ); - DRM_INFO( "\n" ); - DRM_INFO( " HOST_CNTL = 0x%08x\n", MACH64_READ( MACH64_HOST_CNTL ) ); - DRM_INFO( " HW_DEBUG = 0x%08x\n", MACH64_READ( MACH64_HW_DEBUG ) ); - DRM_INFO( "\n" ); - DRM_INFO( " MEM_ADDR_CONFIG = 0x%08x\n", MACH64_READ( MACH64_MEM_ADDR_CONFIG ) ); - DRM_INFO( " MEM_BUF_CNTL = 0x%08x\n", MACH64_READ( MACH64_MEM_BUF_CNTL ) ); - DRM_INFO( "\n" ); - DRM_INFO( " SCALE_3D_CNTL = 0x%08x\n", MACH64_READ( MACH64_SCALE_3D_CNTL ) ); - DRM_INFO( " SCRATCH_REG0 = 0x%08x\n", MACH64_READ( MACH64_SCRATCH_REG0 ) ); - DRM_INFO( " SCRATCH_REG1 = 0x%08x\n", MACH64_READ( MACH64_SCRATCH_REG1 ) ); - DRM_INFO( " SETUP_CNTL = 0x%08x\n", MACH64_READ( MACH64_SETUP_CNTL ) ); - DRM_INFO( " SRC_CNTL = 0x%08x\n", MACH64_READ( MACH64_SRC_CNTL ) ); - DRM_INFO( "\n" ); - DRM_INFO( " TEX_CNTL = 0x%08x\n", MACH64_READ( MACH64_TEX_CNTL ) ); - DRM_INFO( " TEX_SIZE_PITCH = 0x%08x\n", MACH64_READ( MACH64_TEX_SIZE_PITCH ) ); - DRM_INFO( " TIMER_CONFIG = 0x%08x\n", MACH64_READ( MACH64_TIMER_CONFIG ) ); - DRM_INFO( "\n" ); - DRM_INFO( " Z_CNTL = 0x%08x\n", MACH64_READ( MACH64_Z_CNTL ) ); - DRM_INFO( " Z_OFF_PITCH = 0x%08x\n", MACH64_READ( MACH64_Z_OFF_PITCH ) ); - DRM_INFO( "\n" ); -} - - -static void bm_dma_test(drm_mach64_private_t *dev_priv) -{ - struct pci_pool *pool; - dma_addr_t table_handle, data_handle; - u32 table_addr, data_addr; - u32 *table, *data; - - void *cpu_addr_table, *cpu_addr_data; - int i; - - DRM_INFO( "Creating pool ... \n"); - pool = pci_pool_create( "mach64", NULL, 0x4000, - 0x4000, 0x4000, SLAB_ATOMIC ); - - if (!pool) { - DRM_INFO( "pci_pool_create failed!\n" ); - return; - } - - DRM_INFO( "Allocating table memory ...\n" ); - cpu_addr_table = pci_pool_alloc( pool, SLAB_ATOMIC, &table_handle ); - if (!cpu_addr_table || !table_handle) { - DRM_INFO( "table-memory allocation failed!\n" ); - return; - } else { - table = (u32 *) cpu_addr_table; - table_addr = (u32) table_handle; - memset( cpu_addr_table, 0x0, 0x4000 ); - } - - DRM_INFO( "Allocating data memory ...\n" ); - cpu_addr_data = pci_pool_alloc( pool, SLAB_ATOMIC, &data_handle ); - if (!cpu_addr_data || !data_handle) { - DRM_INFO( "data-memory allocation failed!\n" ); - return; - } else { - data = (u32 *) cpu_addr_data; - data_addr = (u32) data_handle; - } - - MACH64_WRITE( MACH64_SRC_CNTL, 0x00000000 ); - MACH64_WRITE( MACH64_PAT_REG0, 0x11111111 ); - - DRM_INFO( "(Before DMA Transfer) PAT_REG0 = 0x%08x\n", - MACH64_READ( MACH64_PAT_REG0 ) ); - - data[0] = 0x000000a0; - data[1] = 0x22222222; - data[2] = 0x000000a0; - data[3] = 0x22222222; - data[4] = 0x000000a0; - data[5] = 0x22222222; - data[6] = 0x0000006d; - data[7] = 0x00000000; - - DRM_INFO( "Preparing table ...\n" ); - table[0] = MACH64_BM_ADDR + APERTURE_OFFSET; - table[1] = data_addr; - table[2] = 8 * sizeof( u32 ) | 0x80000000 | 0x40000000; - table[3] = 0; - - DRM_INFO( "table[0] = 0x%08x\n", table[0] ); - DRM_INFO( "table[1] = 0x%08x\n", table[1] ); - DRM_INFO( "table[2] = 0x%08x\n", table[2] ); - DRM_INFO( "table[3] = 0x%08x\n", table[3] ); - - for ( i = 0 ; i < 8 ; i++) { - DRM_INFO( " data[%d] = 0x%08x\n", i, data[i] ); - } - - mb(); - - DRM_INFO( "waiting for idle...\n" ); - mach64_do_wait_for_idle( dev_priv ); - DRM_INFO( "waiting for idle... done.\n" ); - - DRM_INFO( "BUS_CNTL = 0x%08x\n", MACH64_READ( MACH64_BUS_CNTL ) ); - DRM_INFO( "SRC_CNTL = 0x%08x\n", MACH64_READ( MACH64_SRC_CNTL ) ); - DRM_INFO( "\n" ); - DRM_INFO( "data = 0x%08x\n", data_addr ); - DRM_INFO( "table = 0x%08x\n", table_addr ); - - DRM_INFO( "starting DMA transfer...\n" ); - MACH64_WRITE( MACH64_BM_GUI_TABLE, - table_addr | - MACH64_CIRCULAR_BUF_SIZE_16KB ); - - MACH64_WRITE( MACH64_SRC_CNTL, - MACH64_SRC_BM_ENABLE | MACH64_SRC_BM_SYNC | - MACH64_SRC_BM_OP_SYSTEM_TO_REG ); - - /* Kick off the transfer */ - DRM_INFO( "starting DMA transfer... done.\n" ); - MACH64_WRITE( MACH64_DST_HEIGHT_WIDTH, 0 ); - MACH64_WRITE( MACH64_SRC_CNTL, 0 ); - - DRM_INFO( "waiting for idle [locked_after_dma??]...\n" ); - if ((i=mach64_do_wait_for_idle( dev_priv ))) { - DRM_INFO( "mach64_do_wait_for_idle failed (result=%d)\n", i); - DRM_INFO( "resetting engine ..."); - mach64_do_engine_reset( dev_priv ); - } - - DRM_INFO( "(After DMA Transfer) PAT_REG0 = 0x%08x\n", - MACH64_READ( MACH64_PAT_REG0 ) ); - - DRM_INFO( "freeing memory.\n" ); - pci_pool_free( pool, cpu_addr_table, table_handle ); - pci_pool_free( pool, cpu_addr_data, data_handle ); - pci_pool_destroy( pool ); - DRM_INFO( "returning ...\n" ); -} - -int mach64_do_engine_reset( drm_mach64_private_t *dev_priv ) + +/* ================================================================ + * DMA initialization, cleanup + */ + +/* Reset the engine. This will stop the DMA if it is running. + */ +int mach64_do_engine_reset( drm_device_t *dev ) { + drm_mach64_private_t *dev_priv = dev->dev_private; u32 bus_cntl, gen_test_cntl; DRM_DEBUG( "%s\n", __FUNCTION__ ); @@ -312,8 +111,6 @@ int mach64_do_engine_reset( drm_mach64_private_t *dev_priv ) return 0; } - - static int mach64_do_dma_init( drm_device_t *dev, drm_mach64_init_t *init ) { drm_mach64_private_t *dev_priv; @@ -360,21 +157,21 @@ static int mach64_do_dma_init( drm_device_t *dev, drm_mach64_init_t *init ) } if(!dev_priv->sarea) { dev->dev_private = (void *)dev_priv; - mach64_do_dma_cleanup(dev); + mach64_do_cleanup_dma(dev); DRM_ERROR("can not find sarea!\n"); return -EINVAL; } DRM_FIND_MAP( dev_priv->fb, init->fb_offset ); if(!dev_priv->fb) { dev->dev_private = (void *)dev_priv; - mach64_do_dma_cleanup(dev); + mach64_do_cleanup_dma(dev); DRM_ERROR("can not find frame buffer map!\n"); return -EINVAL; } DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset ); if(!dev_priv->mmio) { dev->dev_private = (void *)dev_priv; - mach64_do_dma_cleanup(dev); + mach64_do_cleanup_dma(dev); DRM_ERROR("can not find mmio map!\n"); return -EINVAL; } @@ -387,14 +184,14 @@ static int mach64_do_dma_init( drm_device_t *dev, drm_mach64_init_t *init ) DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset ); if( !dev_priv->buffers ) { dev->dev_private = (void *)dev_priv; - mach64_do_dma_cleanup( dev ); + mach64_do_cleanup_dma( dev ); DRM_ERROR( "can not find dma buffer map!\n" ); return -EINVAL; } DRM_IOREMAP( dev_priv->buffers ); if( !dev_priv->buffers->handle ) { dev->dev_private = (void *) dev_priv; - mach64_do_dma_cleanup( dev ); + mach64_do_cleanup_dma( dev ); DRM_ERROR( "can not ioremap virtual address for" " dma buffer\n" ); return -ENOMEM; @@ -413,13 +210,10 @@ static int mach64_do_dma_init( drm_device_t *dev, drm_mach64_init_t *init ) dev->dev_private = (void *) dev_priv; - bm_dma_test( dev_priv ); - - return 0; } -static int mach64_do_dma_cleanup( drm_device_t *dev ) +int mach64_do_cleanup_dma( drm_device_t *dev ) { DRM_DEBUG( "%s\n", __FUNCTION__ ); @@ -453,7 +247,7 @@ int mach64_dma_init( struct inode *inode, struct file *filp, case MACH64_INIT_DMA: return mach64_do_dma_init( dev, &init ); case MACH64_CLEANUP_DMA: - return mach64_do_dma_cleanup( dev ); + return mach64_do_cleanup_dma( dev ); } return -EINVAL; @@ -465,14 +259,143 @@ int mach64_dma_idle( struct inode *inode, struct file *filp, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_mach64_private_t *dev_priv = dev->dev_private; + DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } - + LOCK_TEST_WITH_RETURN( dev ); + return mach64_do_wait_for_idle( dev_priv ); } +int mach64_engine_reset( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + LOCK_TEST_WITH_RETURN( dev ); + + return mach64_do_engine_reset( dev ); +} + + +/* ================================================================ + * Primary DMA stream management + */ + + +/* ================================================================ + * Freelist management + */ +#define MACH64_BUFFER_USED 0xffffffff +#define MACH64_BUFFER_FREE 0 + +drm_buf_t *mach64_freelist_get( drm_device_t *dev ) +{ + drm_device_dma_t *dma = dev->dma; + drm_mach64_private_t *dev_priv = dev->dev_private; + drm_mach64_buf_priv_t *buf_priv; + drm_buf_t *buf; + int i, t; + + /* FIXME: Optimize -- use freelist code */ + + for ( i = 0 ; i < dma->buf_count ; i++ ) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if ( buf->pid == 0 ) + return buf; + } + +#if 0 + for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { + u32 done_age = MACH64_READ( MACH64_LAST_DISPATCH_REG ); + + for ( i = 0 ; i < dma->buf_count ; i++ ) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if ( buf->pending && buf_priv->age <= done_age ) { + /* The buffer has been processed, so it + * can now be used. + */ + buf->pending = 0; + return buf; + } + } + udelay( 1 ); + } +#endif + + DRM_ERROR( "returning NULL!\n" ); + return NULL; +} +/* ================================================================ + * DMA command submission + */ + + +static int mach64_dma_get_buffers( drm_device_t *dev, drm_dma_t *d ) +{ + int i; + drm_buf_t *buf; + + for ( i = d->granted_count ; i < d->request_count ; i++ ) { + buf = mach64_freelist_get( dev ); + if ( !buf ) return -EAGAIN; + + buf->pid = current->pid; + + if ( copy_to_user( &d->request_indices[i], &buf->idx, + sizeof(buf->idx) ) ) + return -EFAULT; + if ( copy_to_user( &d->request_sizes[i], &buf->total, + sizeof(buf->total) ) ) + return -EFAULT; + + d->granted_count++; + } + return 0; +} + +int mach64_dma_buffers( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_device_dma_t *dma = dev->dma; + int ret = 0; + drm_dma_t d; + + LOCK_TEST_WITH_RETURN( dev ); + + if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) ) + return -EFAULT; + + /* Please don't send us buffers. + */ + if ( d.send_count != 0 ) { + DRM_ERROR( "Process %d trying to send %d buffers via drmDMA\n", + current->pid, d.send_count ); + return -EINVAL; + } + + /* We'll send you buffers. + */ + if ( d.request_count < 0 || d.request_count > dma->buf_count ) { + DRM_ERROR( "Process %d trying to get %d buffers (of %d max)\n", + current->pid, d.request_count, dma->buf_count ); + return -EINVAL; + } + + d.granted_count = 0; + + if ( d.request_count ) { + ret = mach64_dma_get_buffers( dev, &d ); + } + + if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) ) + return -EFAULT; + + return ret; +} diff --git a/linux/mach64_drm.h b/linux/mach64_drm.h index 8450ca35..4aebaba3 100644 --- a/linux/mach64_drm.h +++ b/linux/mach64_drm.h @@ -170,4 +170,11 @@ typedef struct drm_mach64_clear { unsigned int clear_depth; } drm_mach64_clear_t; +typedef struct drm_mach64_vertex { + int prim; + int idx; /* Index of vertex buffer */ + int count; /* Number of vertices in buffer */ + int discard; /* Client finished with buffer? */ +} drm_mach64_vertex_t; + #endif diff --git a/linux/mach64_drv.c b/linux/mach64_drv.c index 5063e523..4b44f182 100644 --- a/linux/mach64_drv.c +++ b/linux/mach64_drv.c @@ -37,22 +37,22 @@ #define DRIVER_NAME "mach64" #define DRIVER_DESC "DRM module for the ATI Rage Pro" -#define DRIVER_DATE "20010107" +#define DRIVER_DATE "20020417" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 -#define DRIVER_IOCTLS \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_INIT)] = { mach64_dma_init, 1, 1 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_CLEAR)] = { mach64_dma_clear, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_SWAP)] = { mach64_dma_swap, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_IDLE)] = { mach64_dma_idle, 1, 0 }, +#define DRIVER_IOCTLS \ + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mach64_dma_buffers, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_INIT)] = { mach64_dma_init, 1, 1 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_CLEAR)] = { mach64_dma_clear, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_SWAP)] = { mach64_dma_swap, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_IDLE)] = { mach64_dma_idle, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_MACH64_VERTEX)] = { mach64_dma_vertex, 1, 0 } #if 0 - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { mach64_dma, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_MACH64_VERTEX)] = { mach64_vertex, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MACH64_BLIT)] = { mach64_blit, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_MACH64_FLUSH)] = { mach64_flush, 1, 0 }, #endif diff --git a/linux/mach64_drv.h b/linux/mach64_drv.h index fa038d72..2bab6063 100644 --- a/linux/mach64_drv.h +++ b/linux/mach64_drv.h @@ -99,17 +99,24 @@ extern int mach64_dma_init( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int mach64_dma_idle( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int mach64_engine_reset( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int mach64_dma_buffers( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); extern int mach64_do_wait_for_fifo( drm_mach64_private_t *dev_priv, int entries ); extern int mach64_do_wait_for_idle( drm_mach64_private_t *dev_priv ); -extern int mach64_do_engine_reset( drm_mach64_private_t *dev_priv ); +extern int mach64_do_engine_reset( drm_device_t *dev ); +extern int mach64_do_cleanup_dma( drm_device_t *dev ); - /* r128_state.c */ + /* mach64_state.c */ extern int mach64_dma_clear( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int mach64_dma_swap( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int mach64_dma_vertex( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); /* ================================================================ diff --git a/linux/mach64_state.c b/linux/mach64_state.c index 62f16eaf..aec84dbf 100644 --- a/linux/mach64_state.c +++ b/linux/mach64_state.c @@ -294,6 +294,101 @@ static void mach64_dma_dispatch_swap( drm_device_t *dev ) #endif } +static void mach64_dma_dispatch_vertex( drm_device_t *dev, + drm_buf_t *buf ) +{ + drm_mach64_private_t *dev_priv = dev->dev_private; + drm_mach64_buf_priv_t *buf_priv = buf->dev_private; + drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; + int offset = buf->bus_address; + int size = buf->used; + int i = 0; + DRM_DEBUG( "%s: buf=%d nbox=%d\n", + __FUNCTION__, buf->idx, sarea_priv->nbox ); + + if ( 0 ) + mach64_print_dirty( "dispatch_vertex", sarea_priv->dirty ); + + DRM_INFO( "idx = %u, offset=0x%08x, address=0x%08x, used=%u\n", buf->idx, buf->bus_address, buf->address, buf->used ); + + if ( buf->used ) { +#if 0 + buf_priv->dispatched = 1; + + if ( sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS ) { + mach64_emit_state( dev_priv ); + } +#endif + + do { +#if 0 + /* Emit the next set of up to three cliprects */ + if ( i < sarea_priv->nbox ) { + mach64_emit_clip_rects( dev_priv, + &sarea_priv->boxes[i]); + } +#endif + + /* Emit the vertex buffer rendering commands */ + if (0) { + unsigned * p = buf->address; + unsigned used = buf->used >> 2; + + while(used) + { + unsigned reg, count; + + reg = *p & 0xffff; + count = (*p >> 16) + 1; + + p++; + used--; + + while(count && used) + { + unsigned data; + + data = *p; + + /* MACH64_WRITE( reg, data ); */ + + p++; + used--; + count--; + } + } + } + } while ( ++i < sarea_priv->nbox ); + } + +#if 0 + if ( buf_priv->discard ) { + buf_priv->age = dev_priv->sarea_priv->last_dispatch; + + /* Emit the vertex buffer age */ + BEGIN_RING( 2 ); + + OUT_RING( CCE_PACKET0( MACH64_LAST_DISPATCH_REG, 0 ) ); + OUT_RING( buf_priv->age ); + + ADVANCE_RING(); + + buf->pending = 1; + buf->used = 0; + /* FIXME: Check dispatched field */ + buf_priv->dispatched = 0; + } +#else + buf->used = 0; + buf->pid = 0; +#endif + + dev_priv->sarea_priv->last_dispatch++; + + sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS; + sarea_priv->nbox = 0; +} + /* ================================================================ * IOCTL functions @@ -351,3 +446,66 @@ int mach64_dma_swap( struct inode *inode, struct file *filp, MACH64_UPLOAD_MISC); return 0; } + +int mach64_dma_vertex( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_mach64_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + drm_buf_t *buf; + drm_mach64_buf_priv_t *buf_priv; + drm_mach64_vertex_t vertex; + + LOCK_TEST_WITH_RETURN( dev ); + + if ( !dev_priv ) { + DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); + return -EINVAL; + } + + if ( copy_from_user( &vertex, (drm_mach64_vertex_t *)arg, + sizeof(vertex) ) ) + return -EFAULT; + + DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%d\n", + __FUNCTION__, current->pid, + vertex.idx, vertex.count, vertex.discard ); + +#if 0 + if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) { + DRM_ERROR( "buffer index %d (of %d max)\n", + vertex.idx, dma->buf_count - 1 ); + return -EINVAL; + } + if ( vertex.prim < 0 || + vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) { + DRM_ERROR( "buffer prim %d\n", vertex.prim ); + return -EINVAL; + } +#endif + + buf = dma->buflist[vertex.idx]; + buf_priv = buf->dev_private; + + if ( buf->pid != current->pid ) { + DRM_ERROR( "process %d using buffer owned by %d\n", + current->pid, buf->pid ); + return -EINVAL; + } + if ( buf->pending ) { + DRM_ERROR( "sending pending buffer %d\n", vertex.idx ); + return -EINVAL; + } + + buf->used = vertex.count; +#if 0 + buf_priv->prim = vertex.prim; + buf_priv->discard = vertex.discard; +#endif + + mach64_dma_dispatch_vertex( dev, buf ); + + return 0; +} diff --git a/shared-core/drm.h b/shared-core/drm.h index a96b56d5..6fc2c259 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -456,7 +456,6 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_I810_MC DRM_IOW( 0x4c, drm_i810_mc_t) #define DRM_IOCTL_I810_RSTATUS DRM_IO ( 0x4d ) - /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) #define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) @@ -516,10 +515,13 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46) #define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t) #define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48) + /* Mach64 specific ioctls */ -#define DRM_IOCTL_MACH64_INIT DRM_IOW( 0x40, drm_mach64_init_t) -#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( 0x41, drm_mach64_clear_t) -#define DRM_IOCTL_MACH64_SWAP DRM_IO( 0x42) -#define DRM_IOCTL_MACH64_IDLE DRM_IO( 0x43) +#define DRM_IOCTL_MACH64_INIT DRM_IOW( 0x40, drm_mach64_init_t) +#define DRM_IOCTL_MACH64_IDLE DRM_IO( 0x41) +#define DRM_IOCTL_MACH64_RESET DRM_IO( 0x42) +#define DRM_IOCTL_MACH64_SWAP DRM_IO( 0x43) +#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( 0x44, drm_mach64_clear_t) +#define DRM_IOCTL_MACH64_VERTEX DRM_IOW( 0x45, drm_mach64_vertex_t) #endif diff --git a/shared/drm.h b/shared/drm.h index a96b56d5..6fc2c259 100644 --- a/shared/drm.h +++ b/shared/drm.h @@ -456,7 +456,6 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_I810_MC DRM_IOW( 0x4c, drm_i810_mc_t) #define DRM_IOCTL_I810_RSTATUS DRM_IO ( 0x4d ) - /* Rage 128 specific ioctls */ #define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) #define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) @@ -516,10 +515,13 @@ typedef struct drm_scatter_gather { #define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46) #define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t) #define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48) + /* Mach64 specific ioctls */ -#define DRM_IOCTL_MACH64_INIT DRM_IOW( 0x40, drm_mach64_init_t) -#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( 0x41, drm_mach64_clear_t) -#define DRM_IOCTL_MACH64_SWAP DRM_IO( 0x42) -#define DRM_IOCTL_MACH64_IDLE DRM_IO( 0x43) +#define DRM_IOCTL_MACH64_INIT DRM_IOW( 0x40, drm_mach64_init_t) +#define DRM_IOCTL_MACH64_IDLE DRM_IO( 0x41) +#define DRM_IOCTL_MACH64_RESET DRM_IO( 0x42) +#define DRM_IOCTL_MACH64_SWAP DRM_IO( 0x43) +#define DRM_IOCTL_MACH64_CLEAR DRM_IOW( 0x44, drm_mach64_clear_t) +#define DRM_IOCTL_MACH64_VERTEX DRM_IOW( 0x45, drm_mach64_vertex_t) #endif