diff options
-rw-r--r-- | linux-core/r128_drv.c | 18 | ||||
-rw-r--r-- | linux/drm.h | 22 | ||||
-rw-r--r-- | linux/r128_bufs.c | 2 | ||||
-rw-r--r-- | linux/r128_cce.c | 897 | ||||
-rw-r--r-- | linux/r128_drm.h | 36 | ||||
-rw-r--r-- | linux/r128_drv.c | 18 | ||||
-rw-r--r-- | linux/r128_drv.h | 299 | ||||
-rw-r--r-- | linux/r128_state.c | 279 | ||||
-rw-r--r-- | shared-core/drm.h | 22 | ||||
-rw-r--r-- | shared/drm.h | 22 |
10 files changed, 1059 insertions, 556 deletions
diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c index ff20e599..e2ee253b 100644 --- a/linux-core/r128_drv.c +++ b/linux-core/r128_drv.c @@ -35,7 +35,7 @@ #define R128_NAME "r128" #define R128_DESC "ATI Rage 128" -#define R128_DATE "20000919" +#define R128_DATE "20000928" #define R128_MAJOR 1 #define R128_MINOR 1 #define R128_PATCHLEVEL 0 @@ -105,12 +105,16 @@ static drm_ioctl_desc_t r128_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, #endif - [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_init_cce, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_eng_reset, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_FLUSH)] = { r128_eng_flush, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_IDLE)] = { r128_cce_idle, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, }; #define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) diff --git a/linux/drm.h b/linux/drm.h index 5a979e1c..7bf24afe 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -11,11 +11,11 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -23,7 +23,7 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * + * * Authors: * Rickard E. (Rik) Faith <faith@valinux.com> * @@ -357,11 +357,15 @@ typedef struct drm_agp_info { #define DRM_IOCTL_I810_DOCOPY DRM_IO ( 0x48) /* Rage 128 specific ioctls */ -#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) -#define DRM_IOCTL_R128_RESET DRM_IO( 0x41) -#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42) -#define DRM_IOCTL_R128_IDLE DRM_IO( 0x43) -#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) +#define DRM_IOCTL_R128_CCE_STOP DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) +#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x45) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x46) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x47, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOWR(0x48, drm_r128_vertex_t) +#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x49, drm_r128_packet_t) #endif diff --git a/linux/r128_bufs.c b/linux/r128_bufs.c index 0053c0fe..bf3dff7f 100644 --- a/linux/r128_bufs.c +++ b/linux/r128_bufs.c @@ -235,7 +235,7 @@ int r128_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd, if (dma->flags & _DRM_DMA_USE_AGP) { drm_map_t *map; - map = dev_priv->agp_vertbufs; + map = dev_priv->vertex_buffers; if (!map) { retcode = -EINVAL; goto done; diff --git a/linux/r128_cce.c b/linux/r128_cce.c index d9f988ed..60a0fef8 100644 --- a/linux/r128_cce.c +++ b/linux/r128_cce.c @@ -1,4 +1,4 @@ -/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*- +/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*- * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com * * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. @@ -39,6 +39,51 @@ /* FIXME: Temporary CCE packet buffer */ u32 r128_cce_buffer[(1 << 14)] __attribute__ ((aligned (32))); +/* CCE microcode (from ATI) */ +static u32 r128_cce_microcode[] = { + 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, + 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, + 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1, + 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11, + 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28, + 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9, + 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656, + 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1, + 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071, + 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2, + 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1, + 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1, + 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1, + 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2, + 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1, + 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82, + 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729, + 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008, + 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0, + 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1, + 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1, + 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0, + 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370, + 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1, + 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793, + 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1, + 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1, + 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1, + 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1, + 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894, + 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14, + 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1, + 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1, + 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1, + 409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + #define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size) @@ -68,9 +113,6 @@ int R128_READ_PLL(drm_device_t *dev, int addr) return R128_READ(R128_CLOCK_CNTL_DATA); } -/* GH: This should really use my PIII mb() patch */ -#define r128_flush_write_combine() mb() - static void r128_status(drm_device_t *dev) { @@ -86,194 +128,15 @@ static void r128_status(drm_device_t *dev) (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR)); } -static int r128_do_cleanup_cce(drm_device_t *dev) -{ - if (dev->dev_private) { - drm_r128_private_t *dev_priv = dev->dev_private; - - if (!dev_priv->is_pci) { - DO_REMAPFREE(dev_priv->agp_ring); - DO_REMAPFREE(dev_priv->agp_read_ptr); - DO_REMAPFREE(dev_priv->agp_vertbufs); - DO_REMAPFREE(dev_priv->agp_indbufs); - DO_REMAPFREE(dev_priv->agp_textures); - } - - drm_free(dev->dev_private, sizeof(drm_r128_private_t), - DRM_MEM_DRIVER); - dev->dev_private = NULL; - } - - return 0; -} - -static int r128_do_init_cce(drm_device_t *dev, drm_r128_init_t *init) -{ - drm_r128_private_t *dev_priv; - int i; - - dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); - if (dev_priv == NULL) return -ENOMEM; - dev->dev_private = (void *)dev_priv; - - memset(dev_priv, 0, sizeof(drm_r128_private_t)); - - dev_priv->is_pci = init->is_pci; - - dev_priv->usec_timeout = init->usec_timeout; - if (dev_priv->usec_timeout < 1 || - dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) { - drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); - dev->dev_private = NULL; - return -EINVAL; - } - - dev_priv->cce_mode = init->cce_mode; - dev_priv->cce_fifo_size = init->cce_fifo_size; - dev_priv->cce_is_bm_mode = - ((init->cce_mode == R128_PM4_192BM) || - (init->cce_mode == R128_PM4_128BM_64INDBM) || - (init->cce_mode == R128_PM4_64BM_128INDBM) || - (init->cce_mode == R128_PM4_64BM_64VCBM_64INDBM)); - dev_priv->cce_secure = init->cce_secure; - - dev_priv->cce_buffer = r128_cce_buffer; - - if (dev_priv->cce_is_bm_mode && dev_priv->is_pci) { - drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); - dev->dev_private = NULL; - return -EINVAL; - } - - for (i = 0; i < dev->map_count; i++) { - if (dev->maplist[i]->type == _DRM_SHM) { - dev_priv->sarea = dev->maplist[i]; - break; - } - } - - DO_FIND_MAP(dev_priv->fb, init->fb_offset); - if (!dev_priv->is_pci) { - DO_FIND_MAP(dev_priv->agp_ring, init->agp_ring_offset); - DO_FIND_MAP(dev_priv->agp_read_ptr, init->agp_read_ptr_offset); - DO_FIND_MAP(dev_priv->agp_vertbufs, init->agp_vertbufs_offset); - DO_FIND_MAP(dev_priv->agp_indbufs, init->agp_indbufs_offset); - DO_FIND_MAP(dev_priv->agp_textures, init->agp_textures_offset); - } - DO_FIND_MAP(dev_priv->mmio, init->mmio_offset); - - dev_priv->sarea_priv = - (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle + - init->sarea_priv_offset); - - if (!dev_priv->is_pci) { - DO_REMAP(dev_priv->agp_ring); - DO_REMAP(dev_priv->agp_read_ptr); - DO_REMAP(dev_priv->agp_vertbufs); -#if 0 - DO_REMAP(dev_priv->agp_indirectbufs); - DO_REMAP(dev_priv->agp_textures); -#endif - - dev_priv->ring_size = init->ring_size; - dev_priv->ring_sizel2qw = drm_order(init->ring_size/8); - dev_priv->ring_entries = init->ring_size/sizeof(u32); - dev_priv->ring_read_ptr = ((__volatile__ u32 *) - dev_priv->agp_read_ptr->handle); - dev_priv->ring_start = (u32 *)dev_priv->agp_ring->handle; - dev_priv->ring_end = ((u32 *)dev_priv->agp_ring->handle - + dev_priv->ring_entries); - } - - dev_priv->submit_age = 0; - R128_WRITE(R128_VB_AGE_REG, dev_priv->submit_age); - - return 0; -} - - /* ================================================================ * GH: Done from here down */ -int r128_init_cce( 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_r128_init_t init; - - if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) ) - return -EFAULT; - - switch ( init.func ) { - case R128_INIT_CCE: - return r128_do_init_cce( dev, &init ); - case R128_CLEANUP_CCE: - return r128_do_cleanup_cce( dev ); - } - - return -EINVAL; -} /* ================================================================ - * Freelist management - */ - -void r128_freelist_reset( drm_device_t *dev ) -{ - drm_device_dma_t *dma = dev->dma; - int i; - - for ( i = 0 ; i < dma->buf_count ; i++ ) { - drm_buf_t *buf = dma->buflist[i]; - drm_r128_buf_priv_t *buf_priv = buf->dev_private; - buf_priv->age = 0; - } -} - -drm_buf_t *r128_freelist_get( drm_device_t *dev ) -{ - drm_device_dma_t *dma = dev->dma; - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_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; - } - - for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { - u32 done_age = R128_READ( R128_VB_AGE_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 ); - } - - r128_status( dev ); - return NULL; -} - - -/* ================================================================ - * Engine control + * Engine, FIFO control */ static int r128_do_pixcache_flush( drm_r128_private_t *dev_priv ) @@ -306,7 +169,7 @@ static int r128_do_wait_for_fifo( drm_r128_private_t *dev_priv, int entries ) return -EBUSY; } -int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ) +static int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ) { int i, ret; @@ -323,6 +186,97 @@ int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ) return -EBUSY; } + +/* ================================================================ + * CCE control, initialization + */ + +/* Load the microcode for the CCE */ +static void r128_cce_load_microcode( drm_r128_private_t *dev_priv ) +{ + int i; + + r128_do_wait_for_idle( dev_priv ); + + R128_WRITE( R128_PM4_MICROCODE_ADDR, 0 ); + for ( i = 0 ; i < 256 ; i++ ) { + R128_WRITE( R128_PM4_MICROCODE_DATAH, + r128_cce_microcode[i * 2] ); + R128_WRITE( R128_PM4_MICROCODE_DATAL, + r128_cce_microcode[i * 2 + 1] ); + } +} + +/* Flush any pending commands to the CCE. This should only be used just + * prior to a wait for idle, as it informs the engine that the command + * stream is ending. + */ +static void r128_do_cce_flush( drm_r128_private_t *dev_priv ) +{ + u32 tmp; + + tmp = R128_READ( R128_PM4_BUFFER_DL_WPTR ) | R128_PM4_BUFFER_DL_DONE; + R128_WRITE( R128_PM4_BUFFER_DL_WPTR, tmp ); +} + +/* Wait for the CCE to go idle. + */ +static int r128_do_cce_idle( drm_r128_private_t *dev_priv ) +{ + int i; + + for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { + if ( *dev_priv->ring.head == dev_priv->ring.tail ) { + int pm4stat = R128_READ( R128_PM4_STAT ); + if ( ( (pm4stat & R128_PM4_FIFOCNT_MASK) >= + dev_priv->cce_fifo_size ) && + !(pm4stat & (R128_PM4_BUSY | + R128_PM4_GUI_ACTIVE)) ) { + return r128_do_pixcache_flush( dev_priv ); + } + } + udelay( 1 ); + } + + return -EBUSY; +} + +/* Start the Concurrent Command Engine. + */ +static void r128_do_cce_start( drm_r128_private_t *dev_priv ) +{ + r128_do_wait_for_idle( dev_priv ); + + R128_WRITE( R128_PM4_BUFFER_CNTL, + dev_priv->cce_mode | dev_priv->ring.size_l2qw ); + R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */ + R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN ); +} + +/* Reset the Concurrent Command Engine. This will not flush any pending + * commangs, so you must wait for the CCE command stream to complete + * before calling this routine. + */ +static void r128_do_cce_reset( drm_r128_private_t *dev_priv ) +{ + R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 ); + R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 ); + *dev_priv->ring.head = 0; + dev_priv->ring.tail = 0; +} + +/* Stop the Concurrent Command Engine. This will not flush any pending + * commangs, so you must flush the command stream and wait for the CCE + * to go idle before calling this routine. + */ +static void r128_do_cce_stop( drm_r128_private_t *dev_priv ) +{ + R128_WRITE( R128_PM4_MICRO_CNTL, 0 ); + R128_WRITE( R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4 ); +} + +/* Reset the engine, and the CCE if it is currently running. + */ static int r128_do_engine_reset( drm_device_t *dev ) { drm_r128_private_t *dev_priv = dev->dev_private; @@ -350,146 +304,413 @@ static int r128_do_engine_reset( drm_device_t *dev ) R128_WRITE( R128_CLOCK_CNTL_INDEX, clock_cntl_index ); R128_WRITE( R128_GEN_RESET_CNTL, gen_reset_cntl ); - /* For CCE ring buffer only */ - if ( dev_priv->cce_is_bm_mode ) { - R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 ); - R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 ); - *dev_priv->ring_read_ptr = 0; - dev_priv->sarea_priv->ring_write = 0; - } + /* Reset the CCE ring */ + r128_do_cce_reset( dev_priv ); - /* Reset the CCE mode */ - r128_do_wait_for_idle( dev_priv ); - R128_WRITE( R128_PM4_BUFFER_CNTL, - dev_priv->cce_mode | dev_priv->ring_sizel2qw ); - R128_READ( R128_PM4_BUFFER_ADDR ); /* as per the sample code */ - R128_WRITE( R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN ); + if ( dev_priv->cce_running ) { + /* Start the CCE again */ + r128_do_cce_start( dev_priv ); + } + /* Reset any pending vertex, indirect buffers */ r128_freelist_reset( dev ); + return 0; } -int r128_eng_reset( struct inode *inode, struct file *filp, +static void r128_cce_init_ring_buffer( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 ring_start; + u32 tmp; + + /* The manual (p. 2) says this address is in "VM space". This + * means it's an offset from the start of AGP space. + */ + ring_start = dev_priv->cce_ring->offset - dev->agp->base; + R128_WRITE( R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET ); + + R128_WRITE( R128_PM4_BUFFER_DL_WPTR, 0 ); + R128_WRITE( R128_PM4_BUFFER_DL_RPTR, 0 ); + + /* DL_RPTR_ADDR is a physical address in AGP space. */ + *dev_priv->ring.head = 0; + R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, + dev_priv->ring_rptr->offset ); + + /* Set watermark control */ + R128_WRITE( R128_PM4_BUFFER_WM_CNTL, + ((R128_WATERMARK_L/4) << R128_WMA_SHIFT) + | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT) + | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT) + | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT) ); + + /* Force read. Why? Because it's in the examples... */ + R128_READ( R128_PM4_BUFFER_ADDR ); + + /* Turn on bus mastering */ + tmp = R128_READ( R128_BUS_CNTL ) & ~R128_BUS_MASTER_DIS; + R128_WRITE( R128_BUS_CNTL, tmp ); +} + +static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) +{ + drm_r128_private_t *dev_priv; + int i; + + dev_priv = drm_alloc( sizeof(drm_r128_private_t), DRM_MEM_DRIVER ); + if ( dev_priv == NULL ) + return -ENOMEM; + dev->dev_private = (void *)dev_priv; + + memset( dev_priv, 0, sizeof(drm_r128_private_t) ); + + dev_priv->is_pci = init->is_pci; + + /* GH: We don't support PCI cards until PCI GART is implemented. + * Fail here so we can remove all checks for PCI cards around + * the CCE ring code. + */ + if ( dev_priv->is_pci ) { + drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER ); + dev->dev_private = NULL; + return -EINVAL; + } + + dev_priv->usec_timeout = init->usec_timeout; + if ( dev_priv->usec_timeout < 1 || + dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT ) { + drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER ); + dev->dev_private = NULL; + return -EINVAL; + } + + dev_priv->cce_mode = init->cce_mode; + dev_priv->cce_secure = init->cce_secure; + + /* We don't support anything other than bus-mastering ring mode, + * but the ring can be in either AGP or PCI space for the ring + * read pointer. + */ + if ( ( init->cce_mode != R128_PM4_192BM ) && + ( init->cce_mode != R128_PM4_128BM_64INDBM ) && + ( init->cce_mode != R128_PM4_64BM_128INDBM ) && + ( init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM ) ) { + drm_free( dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER ); + dev->dev_private = NULL; + return -EINVAL; + } + + switch ( init->cce_mode ) { + case R128_PM4_NONPM4: + dev_priv->cce_fifo_size = 0; + break; + case R128_PM4_192PIO: + case R128_PM4_192BM: + dev_priv->cce_fifo_size = 192; + break; + case R128_PM4_128PIO_64INDBM: + case R128_PM4_128BM_64INDBM: + dev_priv->cce_fifo_size = 128; + break; + case R128_PM4_64PIO_128INDBM: + case R128_PM4_64BM_128INDBM: + case R128_PM4_64PIO_64VCBM_64INDBM: + case R128_PM4_64BM_64VCBM_64INDBM: + case R128_PM4_64PIO_64VCPIO_64INDPIO: + dev_priv->cce_fifo_size = 64; + break; + } + + dev_priv->fb_bpp = init->fb_bpp; + dev_priv->front_offset = init->front_offset; + dev_priv->front_pitch = init->front_pitch; + dev_priv->front_x = init->front_x; + dev_priv->front_y = init->front_y; + dev_priv->back_offset = init->back_offset; + dev_priv->back_pitch = init->back_pitch; + dev_priv->back_x = init->back_x; + dev_priv->back_y = init->back_y; + + dev_priv->depth_bpp = init->depth_bpp; + dev_priv->back_offset = init->depth_offset; + dev_priv->back_pitch = init->depth_pitch; + dev_priv->back_x = init->depth_x; + dev_priv->back_y = init->depth_y; + + /* FIXME: We want multiple shared areas, including one shared + * only by the X Server and kernel module. + */ + for ( i = 0 ; i < dev->map_count ; i++ ) { + if ( dev->maplist[i]->type == _DRM_SHM ) { + dev_priv->sarea = dev->maplist[i]; + break; + } + } + + DO_FIND_MAP( dev_priv->fb, init->fb_offset ); + DO_FIND_MAP( dev_priv->mmio, init->mmio_offset ); + + DO_FIND_MAP( dev_priv->cce_ring, init->ring_offset ); + DO_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset ); + + DO_FIND_MAP( dev_priv->vertex_buffers, + init->vertex_buffers_offset ); + DO_FIND_MAP( dev_priv->indirect_buffers, + init->indirect_buffers_offset ); + + if ( !dev_priv->is_pci ) { + DO_FIND_MAP( dev_priv->agp_textures, + init->agp_textures_offset ); + } + + dev_priv->sarea_priv = + (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle + + init->sarea_priv_offset); + + DO_REMAP( dev_priv->cce_ring ); + DO_REMAP( dev_priv->ring_rptr ); + DO_REMAP( dev_priv->vertex_buffers ); + DO_REMAP( dev_priv->indirect_buffers ); +#if 0 + if ( !dev_priv->is_pci ) { + DO_REMAP( dev_priv->agp_textures ); + } +#endif + + dev_priv->ring.head = ((__volatile__ u32 *) + dev_priv->ring_rptr->handle); + + dev_priv->ring.start = (u32 *)dev_priv->cce_ring->handle; + dev_priv->ring.end = ((u32 *)dev_priv->cce_ring->handle + + init->ring_size / sizeof(u32)); + dev_priv->ring.size = init->ring_size; + dev_priv->ring.size_l2qw = drm_order( init->ring_size / 8 ); + + dev_priv->ring.tail_mask = + (dev_priv->ring.size / sizeof(u32)) - 1; + + dev_priv->submit_age = 0; + R128_WRITE( R128_VB_AGE_REG, dev_priv->submit_age ); + + DRM_INFO( "agp=0x%08x ring=0x%08x rtpr=0x%08x\n", + dev->agp->base, + dev_priv->cce_ring->offset, + dev_priv->ring_rptr->offset + ); + + + r128_cce_init_ring_buffer( dev ); + r128_cce_load_microcode( dev_priv ); + r128_do_engine_reset( dev ); + + return 0; +} + +static int r128_do_cleanup_cce( drm_device_t *dev ) +{ + if ( dev->dev_private ) { + drm_r128_private_t *dev_priv = dev->dev_private; + + DO_REMAPFREE( dev_priv->cce_ring ); + DO_REMAPFREE( dev_priv->ring_rptr ); + DO_REMAPFREE( dev_priv->vertex_buffers ); + DO_REMAPFREE( dev_priv->indirect_buffers ); +#if 0 + if ( !dev_priv->is_pci ) { + DO_REMAPFREE( dev_priv->agp_textures ); + } +#endif + + drm_free( dev->dev_private, sizeof(drm_r128_private_t), + DRM_MEM_DRIVER ); + dev->dev_private = NULL; + } + + return 0; +} + +int r128_cce_init( 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_r128_init_t init; + + if ( copy_from_user( &init, (drm_r128_init_t *)arg, sizeof(init) ) ) + return -EFAULT; + + switch ( init.func ) { + case R128_INIT_CCE: + return r128_do_init_cce( dev, &init ); + case R128_CLEANUP_CCE: + return r128_do_cleanup_cce( dev ); + } + + return -EINVAL; +} + +int r128_cce_start( 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_r128_private_t *dev_priv = dev->dev_private; if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { - DRM_ERROR( "r128_eng_reset called without lock held\n" ); + DRM_ERROR( "r128_cce_start called without lock held\n" ); return -EINVAL; } - return r128_do_engine_reset( dev ); + if ( dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) + return 0; + + r128_do_cce_start( dev_priv ); + + dev_priv->cce_running = 1; + return 0; } -static int r128_do_engine_flush( drm_device_t *dev ) +int r128_cce_stop( 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_r128_private_t *dev_priv = dev->dev_private; - u32 tmp; - tmp = R128_READ( R128_PM4_BUFFER_DL_WPTR ); - R128_WRITE( R128_PM4_BUFFER_DL_WPTR, tmp | R128_PM4_BUFFER_DL_DONE ); + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "r128_cce_stop called without lock held\n" ); + return -EINVAL; + } + + if ( !dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) + return 0; + + /* Flush any pending CCE commands, then turn off the engine */ + r128_do_cce_flush( dev_priv ); + r128_do_cce_idle( dev_priv ); + r128_do_cce_stop( dev_priv ); + + /* Mark the CCE as off so it is not reset */ + dev_priv->cce_running = 0; + + /* Reset the engine, but not the CCE */ + r128_do_engine_reset( dev ); return 0; } -int r128_eng_flush( struct inode *inode, struct file *filp, +/* Just reset the CCE ring. Called as part of an X Server engine reset. + */ +int r128_cce_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_r128_private_t *dev_priv = dev->dev_private; if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { - DRM_ERROR( "r128_eng_flush called without lock held\n" ); + DRM_ERROR( "r128_cce_reset called without lock held\n" ); return -EINVAL; } - return r128_do_engine_flush( dev ); -} + if ( !dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4 ) + return 0; + r128_do_cce_reset( dev_priv ); -/* ================================================================ - * CCE FIFO control - */ + /* The ring is no longer in use */ + dev_priv->cce_running = 0; + return 0; +} -static int r128_do_cce_wait_for_fifo( drm_r128_private_t *dev_priv, - int entries ) +int r128_cce_idle( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) { - int i; + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; - for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - int slots = R128_READ( R128_PM4_STAT ) & R128_PM4_FIFOCNT_MASK; - if ( slots >= entries ) return 0; - udelay( 1 ); + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "r128_cce_idle called without lock held\n" ); + return -EINVAL; } - return -EBUSY; + + r128_do_cce_flush( dev_priv ); + return r128_do_cce_idle( dev_priv ); } -static inline int r128_do_cce_idle_ring( drm_r128_private_t *dev_priv ) +int r128_engine_reset( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) { - int i; + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; - for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - if ( *dev_priv->ring_read_ptr == - dev_priv->sarea_priv->ring_write ) { - int pm4stat = R128_READ( R128_PM4_STAT ); - if ( (pm4stat & R128_PM4_FIFOCNT_MASK) >= - dev_priv->cce_fifo_size && - !(pm4stat & (R128_PM4_BUSY | - R128_PM4_GUI_ACTIVE)) ) { - return r128_do_pixcache_flush( dev_priv ); - } - } - udelay( 1 ); + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "r128_engine_reset called without lock held\n" ); + return -EINVAL; } - return -EBUSY; + + return r128_do_engine_reset( dev ); } -static inline int r128_do_cce_idle_pio( drm_r128_private_t *dev_priv ) + +/* ================================================================ + * Freelist management + */ + +void r128_freelist_reset( drm_device_t *dev ) { - int ret; + drm_device_dma_t *dma = dev->dma; int i; - ret = r128_do_cce_wait_for_fifo( dev_priv, dev_priv->cce_fifo_size ); - if ( ret < 0 ) return ret; - - for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - int pm4stat = R128_READ( R128_PM4_STAT ); - if ( !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE)) ) { - return r128_do_pixcache_flush( dev_priv ); - } - udelay( 1 ); + for ( i = 0 ; i < dma->buf_count ; i++ ) { + drm_buf_t *buf = dma->buflist[i]; + drm_r128_buf_priv_t *buf_priv = buf->dev_private; + buf_priv->age = 0; } - return -EBUSY; } -static int r128_do_cce_idle( drm_device_t *dev ) +drm_buf_t *r128_freelist_get( drm_device_t *dev ) { + drm_device_dma_t *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_buf_priv_t *buf_priv; + drm_buf_t *buf; + int i, t; + + /* FIXME: Optimize -- use freelist code */ - if ( dev_priv->cce_is_bm_mode ) { - return r128_do_cce_idle_ring( dev_priv ); - } else { - return r128_do_cce_idle_pio( dev_priv ); + for ( i = 0 ; i < dma->buf_count ; i++ ) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if ( buf->pid == 0 ) return buf; } -} -int r128_cce_idle( 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; + for ( t = 0 ; t < dev_priv->usec_timeout ; t++ ) { + u32 done_age = R128_READ( R128_VB_AGE_REG ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "r128_wait_idle called without lock held\n" ); - return -EINVAL; + 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 ); } - return r128_do_cce_idle( dev ); + r128_status( dev ); + return NULL; } @@ -497,6 +718,34 @@ int r128_cce_idle( struct inode *inode, struct file *filp, * CCE packet submission */ +int r128_wait_ring( drm_r128_private_t *dev_priv, int n ) +{ + drm_r128_ring_buffer_t *ring = &dev_priv->ring; + int i; + + for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { + ring->space = *ring->head - dev_priv->ring.tail; + if ( ring->space <= 0 ) + ring->space += ring->size; + + if ( ring->space >= n ) + return 0; + + udelay( 1 ); + } + + return -EBUSY; +} + +void r128_update_ring_snapshot( drm_r128_private_t *dev_priv ) +{ + drm_r128_ring_buffer_t *ring = &dev_priv->ring; + + ring->space = *ring->head - dev_priv->ring.tail; + if ( ring->space <= 0 ) + ring->space += ring->size; +} + static int r128_verify_command( drm_r128_private_t *dev_priv, u32 cmd, int *size ) { @@ -543,6 +792,7 @@ static int r128_verify_command( drm_r128_private_t *dev_priv, static int r128_submit_packet_ring_secure( drm_r128_private_t *dev_priv, u32 *commands, int *count ) { +#if 0 int write = dev_priv->sarea_priv->ring_write; int *write_ptr = dev_priv->ring_start + write; int c = *count; @@ -589,48 +839,14 @@ static int r128_submit_packet_ring_secure( drm_r128_private_t *dev_priv, R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write ); *count = 0; - - return 0; -} - -static int r128_submit_packet_pio_secure( drm_r128_private_t *dev_priv, - u32 *commands, int *count ) -{ - u32 tmp = 0; - int psize = 0; - int writing = 1; - int addr = R128_PM4_FIFO_DATA_EVEN; - int ret; - - while ( *count > 0 ) { - tmp = *commands++; - if (!psize) { - writing = r128_verify_command( dev_priv, tmp, &psize ); - } - psize--; - - if ( writing ) { - ret = r128_do_cce_wait_for_fifo( dev_priv, 1 ); - if ( ret ) return ret; - R128_WRITE( addr, tmp ); - addr ^= 0x0004; - } - - *count -= 1; - } - - if ( addr == R128_PM4_FIFO_DATA_ODD ) { - ret = r128_do_cce_wait_for_fifo( dev_priv, 1 ); - if ( ret < 0 ) return ret; - R128_WRITE( addr, R128_CCE_PACKET2 ); - } - +#endif return 0; } static int r128_submit_packet_ring_insecure( drm_r128_private_t *dev_priv, u32 *commands, int *count ) { +#if 0 int write = dev_priv->sarea_priv->ring_write; int *write_ptr = dev_priv->ring_start + write; int c = *count; @@ -667,31 +883,7 @@ static int r128_submit_packet_ring_insecure( drm_r128_private_t *dev_priv, R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write ); *count = 0; - - return 0; -} - -static int r128_submit_packet_pio_insecure( drm_r128_private_t *dev_priv, - u32 *commands, int *count ) -{ - int ret; - - while ( *count > 1 ) { - ret = r128_do_cce_wait_for_fifo( dev_priv, 2 ); - if ( ret < 0 ) return ret; - R128_WRITE( R128_PM4_FIFO_DATA_EVEN, *commands++ ); - R128_WRITE( R128_PM4_FIFO_DATA_ODD, *commands++ ); - *count -= 2; - } - - if ( *count ) { - ret = r128_do_cce_wait_for_fifo( dev_priv, 2 ); - if ( ret < 0 ) return ret; - R128_WRITE( R128_PM4_FIFO_DATA_EVEN, *commands++ ); - R128_WRITE( R128_PM4_FIFO_DATA_ODD, R128_CCE_PACKET2 ); - *count = 0; - } - +#endif return 0; } @@ -703,28 +895,23 @@ int r128_do_submit_packet( drm_r128_private_t *dev_priv, u32 *buffer, int count ) { int c = count; - int ret; - - if ( dev_priv->cce_is_bm_mode ) { - int left = 0; + int ret = 0; - if ( c >= dev_priv->ring_entries ) { - c = dev_priv->ring_entries - 1; - left = count - c; - } +#if 0 + int left = 0; - /* Since this is only used by the kernel we can use the - * insecure ring buffer submit packet routine. - */ - ret = r128_submit_packet_ring_insecure( dev_priv, buffer, &c ); - c += left; - } else { - /* Since this is only used by the kernel we can use the - * insecure PIO submit packet routine. - */ - ret = r128_submit_packet_pio_insecure( dev_priv, buffer, &c ); + if ( c >= dev_priv->ring_entries ) { + c = dev_priv->ring_entries - 1; + left = count - c; } + /* Since this is only used by the kernel we can use the + * insecure ring buffer submit packet routine. + */ + ret = r128_submit_packet_ring_insecure( dev_priv, buffer, &c ); + c += left; +#endif + return ( ret < 0 ) ? ret : c; } @@ -743,6 +930,12 @@ int r128_cce_packet( struct inode *inode, struct file *filp, int size; int ret = 0; +#if 0 + /* GH: Disable packet submission for now. + */ + return -EINVAL; +#endif + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || dev->lock.pid != current->pid ) { DRM_ERROR( "r128_submit_packet called without lock held\n" ); @@ -753,10 +946,11 @@ int r128_cce_packet( struct inode *inode, struct file *filp, sizeof(packet) ) ) return -EFAULT; +#if 0 c = packet.count; size = c * sizeof(*buffer); - if ( dev_priv->cce_is_bm_mode ) { + { int left = 0; if ( c >= dev_priv->ring_entries ) { @@ -779,23 +973,12 @@ int r128_cce_packet( struct inode *inode, struct file *filp, buffer, &c ); } c += left; - } else { - buffer = kmalloc( size, 0 ); - if ( buffer == NULL ) - return -ENOMEM; - if ( copy_from_user( buffer, packet.buffer, size ) ) - return -EFAULT; - - if ( dev_priv->cce_secure ) { - ret = r128_submit_packet_pio_secure( dev_priv, - buffer, &c ); - } else { - ret = r128_submit_packet_pio_insecure( dev_priv, - buffer, &c ); - } } kfree( buffer ); +#else + c = 0; +#endif packet.count = c; if ( copy_to_user( (drm_r128_packet_t *)arg, &packet, diff --git a/linux/r128_drm.h b/linux/r128_drm.h index 0870b6cb..8afbdaa3 100644 --- a/linux/r128_drm.h +++ b/linux/r128_drm.h @@ -51,9 +51,9 @@ #define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */ #define R128_REQUIRE_QUIESCENCE 0x400 -#define R128_FRONT 0x1 -#define R128_BACK 0x2 -#define R128_DEPTH 0x4 +#define R128_FRONT 0x1 +#define R128_BACK 0x2 +#define R128_DEPTH 0x4 /* Keep these small for testing. */ @@ -140,7 +140,6 @@ typedef struct drm_r128_sarea { drm_tex_region_t tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1]; int tex_age[R128_NR_TEX_HEAPS]; int ctx_owner; - int ring_write; } drm_r128_sarea_t; @@ -155,24 +154,35 @@ typedef struct drm_r128_init { int sarea_priv_offset; int is_pci; int cce_mode; - int cce_fifo_size; int cce_secure; int ring_size; int usec_timeout; - int fb_offset; - int agp_ring_offset; - int agp_read_ptr_offset; - int agp_vertbufs_offset; - int agp_indbufs_offset; - int agp_textures_offset; - int mmio_offset; + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int front_x, front_y; + unsigned int back_offset, back_pitch; + unsigned int back_x, back_y; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + unsigned int depth_x, depth_y; + + unsigned int fb_offset; + unsigned int mmio_offset; + unsigned int ring_offset; + unsigned int ring_rptr_offset; + unsigned int vertex_buffers_offset; + unsigned int indirect_buffers_offset; + unsigned int agp_textures_offset; } drm_r128_init_t; typedef struct drm_r128_clear { + unsigned int flags; + int x, y, w, h; unsigned int clear_color; unsigned int clear_depth; - unsigned int flags; + unsigned int color_mask; + unsigned int depth_mask; } drm_r128_clear_t; typedef struct drm_r128_vertex { diff --git a/linux/r128_drv.c b/linux/r128_drv.c index ff20e599..e2ee253b 100644 --- a/linux/r128_drv.c +++ b/linux/r128_drv.c @@ -35,7 +35,7 @@ #define R128_NAME "r128" #define R128_DESC "ATI Rage 128" -#define R128_DATE "20000919" +#define R128_DATE "20000928" #define R128_MAJOR 1 #define R128_MINOR 1 #define R128_PATCHLEVEL 0 @@ -105,12 +105,16 @@ static drm_ioctl_desc_t r128_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, #endif - [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_init_cce, 1, 1 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_eng_reset, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_FLUSH)] = { r128_eng_flush, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_IDLE)] = { r128_cce_idle, 1, 0 }, - [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_cce_init, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_START)] = { r128_cce_start, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_STOP)] = { r128_cce_stop, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_RESET)] = { r128_cce_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CCE_IDLE)] = { r128_cce_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_engine_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_SWAP)] = { r128_cce_swap, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_CLEAR)] = { r128_cce_clear, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, }; #define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) diff --git a/linux/r128_drv.h b/linux/r128_drv.h index 7139eddf..d51f4af0 100644 --- a/linux/r128_drv.h +++ b/linux/r128_drv.h @@ -29,105 +29,119 @@ * */ -#ifndef _R128_DRV_H_ -#define _R128_DRV_H_ +#ifndef __R128_DRV_H__ +#define __R128_DRV_H__ typedef struct drm_r128_freelist { - unsigned int age; - drm_buf_t *buf; + unsigned int age; + drm_buf_t *buf; struct drm_r128_freelist *next; struct drm_r128_freelist *prev; } drm_r128_freelist_t; typedef struct drm_r128_ring_buffer { - __volatile__ u32 *read_ptr; - - u32 start; - u32 end; - int size; - int size_l2qw; - u32 *virtual_start; - - int head; - int tail; - u32 tail_mask; - int space; + u32 *start; + u32 *end; + int size; + int size_l2qw; + + volatile u32 *head; + u32 tail; + u32 tail_mask; + int space; } drm_r128_ring_buffer_t; typedef struct drm_r128_private { - __volatile__ u32 *ring_read_ptr; + drm_r128_ring_buffer_t ring; drm_r128_sarea_t *sarea_priv; - u32 *ring_start; - u32 *ring_end; - int ring_size; - int ring_sizel2qw; - int ring_entries; - - int cce_mode; - int cce_fifo_size; - int cce_is_bm_mode; - int cce_secure; - u32 *cce_buffer; + int cce_mode; + int cce_fifo_size; + int cce_secure; + int cce_running; drm_r128_freelist_t *head; drm_r128_freelist_t *tail; - unsigned int submit_age; - - int usec_timeout; - int is_pci; - - drm_map_t *sarea; - drm_map_t *fb; - drm_map_t *agp_ring; - drm_map_t *agp_read_ptr; - drm_map_t *agp_vertbufs; - drm_map_t *agp_indbufs; - drm_map_t *agp_textures; - drm_map_t *mmio; + unsigned int submit_age; + + int usec_timeout; + int is_pci; + + unsigned int fb_bpp; + unsigned int front_offset; + unsigned int front_pitch; + unsigned int front_x; + unsigned int front_y; + unsigned int back_offset; + unsigned int back_pitch; + unsigned int back_x; + unsigned int back_y; + + unsigned int depth_bpp; + unsigned int depth_offset; + unsigned int depth_pitch; + unsigned int depth_x; + unsigned int depth_y; + + drm_map_t *sarea; + drm_map_t *fb; + drm_map_t *mmio; + drm_map_t *cce_ring; + drm_map_t *ring_rptr; + drm_map_t *vertex_buffers; + drm_map_t *indirect_buffers; + drm_map_t *agp_textures; } drm_r128_private_t; typedef struct drm_r128_buf_priv { - u32 age; - int discard; - int dispatched; + u32 age; + int discard; + int dispatched; drm_r128_freelist_t *my_freelist; } drm_r128_buf_priv_t; /* r128_drv.c */ -extern int r128_version(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int r128_open(struct inode *inode, struct file *filp); -extern int r128_release(struct inode *inode, struct file *filp); -extern int r128_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int r128_lock(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int r128_unlock(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - - /* r128_dma.c */ -extern int r128_init_cce(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int r128_eng_reset(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int r128_eng_flush(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int r128_cce_packet(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int r128_cce_idle(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - -extern void r128_flush_write_combine( void ); -extern int r128_do_wait_for_idle( drm_r128_private_t *dev_priv ); -extern int r128_do_submit_packet( drm_r128_private_t *dev_priv, - u32 *buffer, int count ); +extern int r128_version( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_open( struct inode *inode, struct file *filp ); +extern int r128_release( struct inode *inode, struct file *filp ); +extern int r128_ioctl( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_lock( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_unlock( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); + + /* r128_cce.c */ +extern int r128_cce_init( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_cce_start( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_cce_stop( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_cce_reset( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_cce_idle( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_engine_reset( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_cce_packet( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); + +extern void r128_freelist_reset( drm_device_t *dev ); extern drm_buf_t *r128_freelist_get( drm_device_t *dev ); +extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n ); +extern void r128_update_ring_snapshot( drm_r128_private_t *dev_priv ); + /* r128_state.c */ -extern int r128_cce_vertex(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int r128_cce_clear( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_cce_swap( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_cce_vertex( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); /* r128_bufs.c */ extern int r128_addbufs(struct inode *inode, struct file *filp, @@ -182,12 +196,29 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); #define R128_AUX3_SC_TOP 0x168c #define R128_AUX3_SC_BOTTOM 0x1690 +#define R128_BUS_CNTL 0x0030 +# define R128_BUS_MASTER_DIS (1 << 6) + #define R128_CLOCK_CNTL_INDEX 0x0008 #define R128_CLOCK_CNTL_DATA 0x000c # define R128_PLL_WR_EN (1 << 7) #define R128_CONSTANT_COLOR_C 0x1d34 +#define R128_DP_GUI_MASTER_CNTL 0x146c +# define R128_GMC_BRUSH_SOLID_COLOR (13 << 4) +# define R128_GMC_BRUSH_NONE (15 << 4) +# define R128_GMC_DST_16BPP (4 << 8) +# define R128_GMC_DST_24BPP (5 << 8) +# define R128_GMC_DST_32BPP (6 << 8) +# define R128_GMC_SRC_DATATYPE_COLOR (3 << 12) +# define R128_DP_SRC_SOURCE_MEMORY (2 << 24) +# define R128_DP_SRC_SOURCE_HOST_DATA (3 << 24) +# define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28) +# define R128_GMC_AUX_CLIP_DIS (1 << 29) +# define R128_GMC_WR_MSK_DIS (1 << 30) +# define R128_ROP3_S 0x00cc0000 +# define R128_ROP3_P 0x00f00000 #define R128_DP_WRITE_MASK 0x16cc #define R128_DST_PITCH_OFFSET_C 0x1c80 @@ -214,7 +245,25 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); # define R128_PC_FLUSH_ALL 0x00ff # define R128_PC_BUSY (1 << 31) +#define R128_PRIM_TEX_CNTL_C 0x1cb0 + +#define R128_SCALE_3D_CNTL 0x1a00 +#define R128_SEC_TEX_CNTL_C 0x1d00 +#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c +#define R128_SETUP_CNTL 0x1bc4 +#define R128_STEN_REF_MASK_C 0x1d40 + +#define R128_TEX_CNTL_C 0x1c9c +# define R128_TEX_CACHE_FLUSH (1 << 23) + +#define R128_WINDOW_XY_OFFSET 0x1bcc + + +/* CCE registers + */ +#define R128_PM4_BUFFER_OFFSET 0x0700 #define R128_PM4_BUFFER_CNTL 0x0704 +# define R128_PM4_MASK (15 << 28) # define R128_PM4_NONPM4 (0 << 28) # define R128_PM4_192PIO (1 << 28) # define R128_PM4_192BM (2 << 28) @@ -226,6 +275,13 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); # define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) # define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) +#define R128_PM4_BUFFER_WM_CNTL 0x0708 +# define R128_WMA_SHIFT 0 +# define R128_WMB_SHIFT 8 +# define R128_WMC_SHIFT 16 +# define R128_WB_WM_SHIFT 24 + +#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c #define R128_PM4_BUFFER_DL_RPTR 0x0710 #define R128_PM4_BUFFER_DL_WPTR 0x0714 # define R128_PM4_BUFFER_DL_DONE (1 << 31) @@ -237,6 +293,11 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); # define R128_PM4_BUSY (1 << 16) # define R128_PM4_GUI_ACTIVE (1 << 31) +#define R128_PM4_MICROCODE_ADDR 0x07d4 +#define R128_PM4_MICROCODE_RADDR 0x07d8 +#define R128_PM4_MICROCODE_DATAH 0x07dc +#define R128_PM4_MICROCODE_DATAL 0x07e0 + #define R128_PM4_BUFFER_ADDR 0x07f0 #define R128_PM4_MICRO_CNTL 0x07fc # define R128_PM4_MICRO_FREERUN (1 << 30) @@ -244,19 +305,6 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); #define R128_PM4_FIFO_DATA_EVEN 0x1000 #define R128_PM4_FIFO_DATA_ODD 0x1004 -#define R128_PRIM_TEX_CNTL_C 0x1cb0 - -#define R128_SCALE_3D_CNTL 0x1a00 -#define R128_SEC_TEX_CNTL_C 0x1d00 -#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c -#define R128_SETUP_CNTL 0x1bc4 -#define R128_STEN_REF_MASK_C 0x1d40 - -#define R128_TEX_CNTL_C 0x1c9c -# define R128_TEX_CACHE_FLUSH (1 << 23) - -#define R128_WINDOW_XY_OFFSET 0x1bcc - /* CCE command packets */ @@ -264,6 +312,9 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); #define R128_CCE_PACKET1 0x40000000 #define R128_CCE_PACKET2 0x80000000 #define R128_CCE_PACKET3 0xC0000000 +# define R128_CNTL_HOSTDATA_BLT 0x00009400 +# define R128_CNTL_PAINT_MULTI 0x00009A00 +# define R128_CNTL_BITBLT_MULTI 0x00009B00 # define R128_3D_RNDR_GEN_INDX_PRIM 0x00002300 #define R128_CCE_PACKET_MASK 0xC0000000 @@ -285,6 +336,13 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); #define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030 #define R128_CCE_VC_CNTL_NUM_SHIFT 16 +/* Constants */ +#define R128_AGP_OFFSET 0x02000000 + +#define R128_WATERMARK_L 16 +#define R128_WATERMARK_M 8 +#define R128_WATERMARK_N 8 +#define R128_WATERMARK_K 128 #define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */ @@ -328,77 +386,44 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr); (pkt) | ((n) << 16)) -#define R128_VERBOSE 0 +#define r128_flush_write_combine() mb() + -#if 0 +#define R128_VERBOSE 0 -#define RING_LOCALS unsigned long outring, ringmask; volatile u32 *virt; +#define RING_LOCALS int write; unsigned int mask; volatile u32 *ring; #define BEGIN_RING( n ) do { \ if ( R128_VERBOSE ) { \ - DRM_DEBUG( "BEGIN_RING( %d ) in %s\n", \ + DRM_INFO( "BEGIN_RING( %d ) in %s\n", \ n, __FUNCTION__ ); \ } \ if ( dev_priv->ring.space < n * sizeof(u32) ) { \ r128_wait_ring( dev_priv, n * sizeof(u32) ); \ } \ dev_priv->ring.space -= n * sizeof(u32); \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->->ring.virtual_start; \ -} while (0) - -#define ADVANCE_RING() do { \ - if ( R128_VERBOSE ) { \ - DRM_DEBUG( "ADVANCE_RING()\n" ); \ - } \ - dev_priv->sarea_priv->ring_write = write; - R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write ); - __ret = r128_do_submit_packet( dev_priv, buffer, outring ); \ - if ( __ret < 0 ) { \ - DRM_ERROR( "ADVANCE_RING fucked up!\n" ); \ - } \ -} while (0) - -#define OUT_RING( x ) do { \ - if ( R128_VERBOSE ) { \ - DRM_DEBUG( " OUT_RING( 0x%08x )\n", \ - (unsigned int)(x) ); \ - } \ - buffer[outring++] = x; \ -} while (0) - -#else - -#define RING_LOCALS unsigned long outring; u32 *buffer; int __ret; - -#define BEGIN_RING( n ) do { \ - if ( R128_VERBOSE ) { \ - DRM_DEBUG( "BEGIN_RING( %d ) in %s\n", \ - n, __FUNCTION__ ); \ - } \ - outring = 0; \ - buffer = dev_priv->cce_buffer; \ + write = dev_priv->ring.tail; \ + mask = dev_priv->ring.tail_mask; \ + ring = dev_priv->ring.start; \ } while (0) #define ADVANCE_RING() do { \ if ( R128_VERBOSE ) { \ - DRM_DEBUG( "ADVANCE_RING()\n" ); \ - } \ - __ret = r128_do_submit_packet( dev_priv, buffer, outring ); \ - if ( __ret < 0 ) { \ - DRM_ERROR( "ADVANCE_RING fucked up!\n" ); \ + DRM_INFO( "ADVANCE_RING() tail=0x%06x wr=0x%06x\n", \ + write, dev_priv->ring.tail ); \ } \ + r128_flush_write_combine(); \ + dev_priv->ring.tail = write; \ + R128_WRITE( R128_PM4_BUFFER_DL_WPTR, write ); \ } while (0) #define OUT_RING( x ) do { \ if ( R128_VERBOSE ) { \ - DRM_DEBUG( " OUT_RING( 0x%08x )\n", \ - (unsigned int)(x) ); \ + DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ + (unsigned int)(x), write ); \ } \ - buffer[outring++] = x; \ + ring[write++] = x; \ + write &= mask; \ } while (0) -#endif - -#endif +#endif /* __R128_DRV_H__ */ diff --git a/linux/r128_state.c b/linux/r128_state.c index 124d9938..b9ea930b 100644 --- a/linux/r128_state.c +++ b/linux/r128_state.c @@ -181,7 +181,7 @@ static inline void r128_emit_tex0( drm_r128_private_t *dev_priv ) RING_LOCALS; DRM_DEBUG( " %s\n", __FUNCTION__ ); - BEGIN_RING( 3 ); + BEGIN_RING( 7 + R128_TEX_MAXLEVELS ); OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C, 2 + R128_TEX_MAXLEVELS ) ); @@ -207,7 +207,7 @@ static inline void r128_emit_tex1( drm_r128_private_t *dev_priv ) RING_LOCALS; DRM_DEBUG( " %s\n", __FUNCTION__ ); - BEGIN_RING( 3 ); + BEGIN_RING( 5 + R128_TEX_MAXLEVELS ); OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C, 1 + R128_TEX_MAXLEVELS ) ); @@ -274,16 +274,214 @@ static inline void r128_emit_state( drm_r128_private_t *dev_priv ) * CCE command dispatch functions */ -static void r128_cce_dispatch_swap( drm_device_t *dev ) +static void r128_print_dirty( const char *msg, unsigned int flags ) { - + DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n", + msg, + flags, + (flags & R128_UPLOAD_CORE) ? "core, " : "", + (flags & R128_UPLOAD_CONTEXT) ? "context, " : "", + (flags & R128_UPLOAD_SETUP) ? "setup, " : "", + (flags & R128_UPLOAD_TEX0) ? "tex0, " : "", + (flags & R128_UPLOAD_TEX1) ? "tex1, " : "", + (flags & R128_UPLOAD_MASKS) ? "masks, " : "", + (flags & R128_UPLOAD_WINDOW) ? "window, " : "", + (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "", + (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" ); } -static void r128_cce_dispatch_clear( drm_device_t *dev, int flags, +static void r128_cce_dispatch_clear( drm_device_t *dev, + unsigned int flags, + int cx, int cy, int cw, int ch, unsigned int clear_color, - unsigned int clear_depth ) + unsigned int clear_depth, + unsigned int color_mask, + unsigned int depth_mask ) { + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; + int nbox = sarea_priv->nbox; + drm_clip_rect_t *pbox = sarea_priv->boxes; + u32 fb_bpp, depth_bpp; + int i; + RING_LOCALS; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + switch ( dev_priv->fb_bpp ) { + case 16: + fb_bpp = R128_GMC_DST_16BPP; + break; + case 24: + fb_bpp = R128_GMC_DST_24BPP; + break; + case 32: + default: + fb_bpp = R128_GMC_DST_32BPP; + break; + } + switch ( dev_priv->depth_bpp ) { + case 16: + depth_bpp = R128_GMC_DST_16BPP; + break; + case 24: + depth_bpp = R128_GMC_DST_32BPP; + break; + case 32: + depth_bpp = R128_GMC_DST_32BPP; + break; + default: + return; + } + + for ( i = 0 ; i < nbox ; i++ ) { + int x = pbox[i].x1; + int y = pbox[i].y1; + int w = pbox[i].x2 - x; + int h = pbox[i].y2 - y; + + DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n", + pbox[i].x1, pbox[i].y1, pbox[i].x2, + pbox[i].y2, flags ); + + if ( flags & (R128_FRONT | R128_BACK) ) { + BEGIN_RING( 7 ); + + OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) ); + OUT_RING( color_mask ); + + ADVANCE_RING(); + } + + if ( flags & R128_FRONT ) { + int fx = x + dev_priv->front_x; + int fy = y + dev_priv->front_y; + + DRM_DEBUG( "clear front\n"); + BEGIN_RING( 5 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 3 ) ); + OUT_RING( R128_GMC_BRUSH_SOLID_COLOR + | fb_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + OUT_RING( clear_color ); + OUT_RING( (fx << 16) | fy ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } + + if ( flags & R128_BACK ) { + int bx = x + dev_priv->back_x; + int by = y + dev_priv->back_y; + + DRM_DEBUG( "clear back\n" ); + BEGIN_RING( 5 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 3 ) ); + OUT_RING( R128_GMC_BRUSH_SOLID_COLOR + | fb_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + OUT_RING( clear_color ); + OUT_RING( (bx << 16) | by ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } + + if ( flags & R128_DEPTH ) { + int dx = x + dev_priv->depth_x; + int dy = y + dev_priv->depth_y; + + DRM_DEBUG( "clear depth\n" ); + BEGIN_RING( 7 ); + + OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) ); + OUT_RING( depth_mask ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 3 ) ); + OUT_RING( R128_GMC_BRUSH_SOLID_COLOR + | depth_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + OUT_RING( clear_depth ); + OUT_RING( (dx << 16) | dy ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } + } +} + +static void r128_cce_dispatch_swap( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; + int nbox = sarea_priv->nbox; + drm_clip_rect_t *pbox = sarea_priv->boxes; + u32 fb_bpp; + int i; + RING_LOCALS; + DRM_INFO( "%s\n", __FUNCTION__ ); + + switch ( dev_priv->fb_bpp ) { + case 16: + fb_bpp = R128_GMC_DST_16BPP; + break; + case 24: + fb_bpp = R128_GMC_DST_24BPP; + break; + case 32: + default: + fb_bpp = R128_GMC_DST_32BPP; + break; + } + + for ( i = 0 ; i < nbox ; i++ ) { + int fx = pbox[i].x1; + int fy = pbox[i].y1; + int fw = pbox[i].x2 - fx; + int fh = pbox[i].y2 - fy; + int bx = fx + dev_priv->back_x; + int by = fy + dev_priv->back_y; + + fx += dev_priv->front_x; + fy += dev_priv->front_x; + + BEGIN_RING( 5 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 3 ) ); + OUT_RING( R128_GMC_BRUSH_NONE + | R128_GMC_SRC_DATATYPE_COLOR + | R128_DP_SRC_SOURCE_MEMORY + | fb_bpp + | R128_ROP3_S + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS + | R128_GMC_WR_MSK_DIS ); + + OUT_RING( (bx << 16) | by ); + OUT_RING( (fx << 16) | fy ); + OUT_RING( (fw << 16) | fh ); + ADVANCE_RING(); + } + +#if 0 + BEGIN_RING( 2 ); + + OUT_RING( CCE_PACKET0( R128_SWAP_AGE_REG, 0 ) ); + OUT_RING( r128ctx->lastSwapAge ); + + ADVANCE_RING(); +#endif } static void r128_cce_dispatch_vertex( drm_device_t *dev, @@ -295,7 +493,7 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, int vertsize = sarea_priv->vertsize; int format = sarea_priv->vc_format; int index = buf->idx; - int offset = dev_priv->agp_vertbufs->offset + int offset = dev_priv->vertex_buffers->offset + buf->offset - dev->agp->base; int size = buf->used / (vertsize * sizeof(u32)); int prim; @@ -309,6 +507,11 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, DRM_DEBUG( "vertex size = %d\n", vertsize ); DRM_DEBUG( "vertex format = 0x%x\n", format ); + r128_update_ring_snapshot( dev_priv ); + + if ( 0 ) + r128_print_dirty( "dispatch_vertex", sarea_priv->dirty ); + prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST; if ( buf->used ) { @@ -389,6 +592,68 @@ static void r128_get_vertex_buffer( drm_device_t *dev, drm_r128_vertex_t *v ) v->granted = 1; } +int r128_cce_clear( 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_r128_private_t *dev_priv = dev->dev_private; + drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_r128_clear_t clear; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "r128_cce_clear called without lock held\n" ); + return -EINVAL; + } + + if ( copy_from_user( &clear, (drm_r128_clear_t *) arg, + sizeof(clear) ) ) + return -EFAULT; + + if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) + sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; + + r128_cce_dispatch_clear( dev, clear.flags, + clear.x, clear.y, clear.w, clear.h, + clear.clear_color, clear.clear_depth, + clear.color_mask, clear.depth_mask ); + + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; + + return 0; +} + +int r128_cce_swap( 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_r128_private_t *dev_priv = dev->dev_private; + drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "r128_cce_swap called without lock held\n" ); + return -EINVAL; + } + + if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) + sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; + + r128_cce_dispatch_swap( dev ); + + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; + + return 0; +} + int r128_cce_vertex( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { diff --git a/shared-core/drm.h b/shared-core/drm.h index 5a979e1c..7bf24afe 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -11,11 +11,11 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -23,7 +23,7 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * + * * Authors: * Rickard E. (Rik) Faith <faith@valinux.com> * @@ -357,11 +357,15 @@ typedef struct drm_agp_info { #define DRM_IOCTL_I810_DOCOPY DRM_IO ( 0x48) /* Rage 128 specific ioctls */ -#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) -#define DRM_IOCTL_R128_RESET DRM_IO( 0x41) -#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42) -#define DRM_IOCTL_R128_IDLE DRM_IO( 0x43) -#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) +#define DRM_IOCTL_R128_CCE_STOP DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) +#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x45) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x46) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x47, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOWR(0x48, drm_r128_vertex_t) +#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x49, drm_r128_packet_t) #endif diff --git a/shared/drm.h b/shared/drm.h index 5a979e1c..7bf24afe 100644 --- a/shared/drm.h +++ b/shared/drm.h @@ -11,11 +11,11 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -23,7 +23,7 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * + * * Authors: * Rickard E. (Rik) Faith <faith@valinux.com> * @@ -357,11 +357,15 @@ typedef struct drm_agp_info { #define DRM_IOCTL_I810_DOCOPY DRM_IO ( 0x48) /* Rage 128 specific ioctls */ -#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) -#define DRM_IOCTL_R128_RESET DRM_IO( 0x41) -#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42) -#define DRM_IOCTL_R128_IDLE DRM_IO( 0x43) -#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t) +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41) +#define DRM_IOCTL_R128_CCE_STOP DRM_IO( 0x42) +#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43) +#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x45) +#define DRM_IOCTL_R128_SWAP DRM_IO( 0x46) +#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x47, drm_r128_clear_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOWR(0x48, drm_r128_vertex_t) +#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x49, drm_r128_packet_t) #endif |