summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rw-r--r--linux/drm.h22
-rw-r--r--linux/r128_bufs.c2
-rw-r--r--linux/r128_cce.c897
-rw-r--r--linux/r128_drm.h36
-rw-r--r--linux/r128_drv.c18
-rw-r--r--linux/r128_drv.h299
-rw-r--r--linux/r128_state.c279
7 files changed, 1022 insertions, 531 deletions
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 )
{