Merged mga-0-0-3-branch
authorKeith Whitwell <keith@tungstengraphics.com>
Thu, 25 May 2000 21:06:02 +0000 (21:06 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Thu, 25 May 2000 21:06:02 +0000 (21:06 +0000)
- New security model for i810
- Enable i810 dri by default
- New indexed vertex path for mga
- Mga kernel driver rework
- Removed dead files in i810 driver

18 files changed:
linux-core/i810_dma.c
linux-core/i810_drm.h
linux-core/i810_drv.c
linux-core/i810_drv.h
linux-core/mga_drv.c
linux/drm.h
linux/i810_bufs.c
linux/i810_dma.c
linux/i810_drm.h
linux/i810_drv.c
linux/i810_drv.h
linux/mga_dma.c
linux/mga_drm.h
linux/mga_drv.c
linux/mga_drv.h
linux/mga_state.c
shared-core/drm.h
shared/drm.h

index 6ac4d2e..f041f20 100644 (file)
 
 #include <linux/interrupt.h>   /* For task queue support */
 
-#define I810_BUF_FREE          1
-#define I810_BUF_USED          0
+#define I810_BUF_FREE          2
+#define I810_BUF_CLIENT                1
+#define I810_BUF_HARDWARE              0
+
+#define I810_BUF_UNMAPPED 0
+#define I810_BUF_MAPPED   1
 
 #define I810_REG(reg)          2
 #define I810_BASE(reg)         ((unsigned long) \
@@ -91,7 +95,7 @@ static inline void i810_print_status_page(drm_device_t *dev)
        DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
        DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
        for(i = 6; i < dma->buf_count + 6; i++) {
-               DRM_DEBUG(  "buffer status idx : %d used: %d\n", i - 6, temp[i]);
+               DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]);
        }
 }
 
@@ -108,7 +112,7 @@ static drm_buf_t *i810_freelist_get(drm_device_t *dev)
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
                /* In use is already a pointer */
                used = cmpxchg(buf_priv->in_use, I810_BUF_FREE, 
-                              I810_BUF_USED);
+                              I810_BUF_CLIENT);
                if(used == I810_BUF_FREE) {
                        return buf;
                }
@@ -126,8 +130,8 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
        int used;
    
        /* In use is already a pointer */
-       used = cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE);
-       if(used != I810_BUF_USED) {
+       used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
+       if(used != I810_BUF_CLIENT) {
                DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
                return -EINVAL;
        }
@@ -135,26 +139,114 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
        return 0;
 }
 
-static int i810_dma_get_buffers(drm_device_t *dev, drm_dma_t *d)
+static struct file_operations i810_buffer_fops = {
+       open:    i810_open,
+       flush:   drm_flush,
+       release: i810_release,
+       ioctl:   i810_ioctl,
+       mmap:    i810_mmap_buffers,
+       read:    drm_read,
+       fasync:  drm_fasync,
+       poll:    drm_poll,
+};
+
+int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+{
+       drm_file_t        *priv   = filp->private_data;
+       drm_device_t      *dev    = priv->dev;
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_buf_t *buf = dev_priv->mmap_buffer;
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+   
+       vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+       vma->vm_file = filp;
+   
+       buf_priv->currently_mapped = I810_BUF_MAPPED;
+
+       if (remap_page_range(vma->vm_start,
+                            VM_OFFSET(vma),
+                            vma->vm_end - vma->vm_start,
+                            vma->vm_page_prot)) return -EAGAIN;
+       return 0;
+}
+
+static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
 {
-       int               i;
+       drm_file_t        *priv   = filp->private_data;
+       drm_device_t      *dev    = priv->dev;
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       struct file_operations *old_fops;
+       int retcode = 0;
+
+       if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
+       down(&current->mm->mmap_sem);
+       old_fops = filp->f_op;
+       filp->f_op = &i810_buffer_fops;
+       dev_priv->mmap_buffer = buf;
+       buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, 
+                                           PROT_READ|PROT_WRITE,
+                                           MAP_SHARED, 
+                                           buf->bus_address);
+       dev_priv->mmap_buffer = NULL;
+       filp->f_op = old_fops;
+       if ((unsigned long)buf_priv->virtual > -1024UL) {
+               /* Real error */
+               DRM_DEBUG("mmap error\n");
+               retcode = (signed int)buf_priv->virtual;
+               buf_priv->virtual = 0;
+       }
+       up(&current->mm->mmap_sem);
+       return retcode;
+}
+
+static int i810_unmap_buffer(drm_buf_t *buf)
+{
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       int retcode = 0;
+
+       if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL;
+       down(&current->mm->mmap_sem);
+        retcode = do_munmap((unsigned long)buf_priv->virtual, 
+                           (size_t) buf->total);
+       buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+       buf_priv->virtual = 0;
+       up(&current->mm->mmap_sem);
+
+       return retcode;
+}
+
+static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, 
+                              struct file *filp)
+{
+       drm_file_t        *priv   = filp->private_data;
        drm_buf_t         *buf;
+       drm_i810_buf_priv_t *buf_priv;
+       int retcode = 0;
 
-       for (i = d->granted_count; i < d->request_count; i++) {
-               buf = i810_freelist_get(dev);
-               if (!buf) break;
-               buf->pid     = current->pid;
-               copy_to_user_ret(&d->request_indices[i],
-                                &buf->idx,
-                                sizeof(buf->idx),
-                                -EFAULT);
-               copy_to_user_ret(&d->request_sizes[i],
-                                &buf->total,
-                                sizeof(buf->total),
-                                -EFAULT);
-               ++d->granted_count;
+       buf = i810_freelist_get(dev);
+       if (!buf) {
+               retcode = -ENOMEM;
+               DRM_DEBUG("%s retcode %d\n", __FUNCTION__, retcode);
+               goto out_get_buf;
        }
-       return 0;
+   
+       retcode = i810_map_buffer(buf, filp);
+       if(retcode) {
+               i810_freelist_put(dev, buf);
+               DRM_DEBUG("mapbuf failed in %s retcode %d\n", 
+                         __FUNCTION__, retcode);
+               goto out_get_buf;
+       }
+       buf->pid     = priv->pid;
+       buf_priv = buf->dev_private;    
+       d->granted = 1;
+       d->request_idx = buf->idx;
+       d->request_size = buf->total;
+       d->virtual = buf_priv->virtual;
+
+out_get_buf:
+       return retcode;
 }
 
 static unsigned long i810_alloc_page(drm_device_t *dev)
@@ -185,7 +277,10 @@ static void i810_free_page(drm_device_t *dev, unsigned long page)
 
 static int i810_dma_cleanup(drm_device_t *dev)
 {
+       drm_device_dma_t *dma = dev->dma;
+
        if(dev->dev_private) {
+               int i;
                drm_i810_private_t *dev_priv = 
                        (drm_i810_private_t *) dev->dev_private;
           
@@ -201,6 +296,12 @@ static int i810_dma_cleanup(drm_device_t *dev)
                drm_free(dev->dev_private, sizeof(drm_i810_private_t), 
                         DRM_MEM_DRIVER);
                dev->dev_private = NULL;
+
+               for (i = 0; i < dma->buf_count; i++) {
+                       drm_buf_t *buf = dma->buflist[ i ];
+                       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+                       drm_ioremapfree(buf_priv->kernel_virtual, buf->total);
+               }
        }
        return 0;
 }
@@ -211,6 +312,7 @@ static int i810_wait_ring(drm_device_t *dev, int n)
        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
        int iters = 0;
        unsigned long end;
+       unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 
        end = jiffies + (HZ*3);
        while (ring->space < n) {
@@ -218,9 +320,11 @@ static int i810_wait_ring(drm_device_t *dev, int n)
        
                ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
                ring->space = ring->head - (ring->tail+8);
+               if (ring->space < 0) ring->space += ring->Size;
           
-               if (ring->space < 0) ring->space += ring->Size;
-          
+               if (ring->head != last_head)
+                  end = jiffies + (HZ*3);
+         
                iters++;
                if((signed)(end - jiffies) <= 0) {
                        DRM_ERROR("space: %d wanted %d\n", ring->space, n);
@@ -250,9 +354,9 @@ static int i810_freelist_init(drm_device_t *dev)
 {
        drm_device_dma_t *dma = dev->dma;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-       u8 *hw_status = (u8 *)dev_priv->hw_status_page;
-       int i;
        int my_idx = 24;
+       u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
+       int i;
    
        if(dma->buf_count > 1019) {
                /* Not enough space in the status page for the freelist */
@@ -263,11 +367,14 @@ static int i810_freelist_init(drm_device_t *dev)
                drm_buf_t *buf = dma->buflist[ i ];
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
           
-               buf_priv->in_use = hw_status + my_idx;
-               DRM_DEBUG("buf_priv->in_use : %p\n", buf_priv->in_use);
-               *buf_priv->in_use = I810_BUF_FREE;
+               buf_priv->in_use = hw_status++;
                buf_priv->my_use_idx = my_idx;
                my_idx += 4;
+
+               *buf_priv->in_use = I810_BUF_FREE;
+
+               buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, 
+                                                      buf->total);
        }
        return 0;
 }
@@ -301,9 +408,11 @@ static int i810_dma_initialize(drm_device_t *dev,
        dev_priv->ring.Start = init->ring_start;
        dev_priv->ring.End = init->ring_end;
        dev_priv->ring.Size = init->ring_size;
+
        dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + 
                                                   init->ring_start, 
                                                   init->ring_size);
+
        dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
    
        if (dev_priv->ring.virtual_start == NULL) {
@@ -312,6 +421,17 @@ static int i810_dma_initialize(drm_device_t *dev,
                          " ring buffer\n");
                return -ENOMEM;
        }
+
+       dev_priv->w = init->w;
+       dev_priv->h = init->h;
+       dev_priv->pitch = init->pitch;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->depth_offset = init->depth_offset;
+
+       dev_priv->front_di1 = init->front_offset | init->pitch_bits;
+       dev_priv->back_di1 = init->back_offset | init->pitch_bits;
+       dev_priv->zi1 = init->depth_offset | init->pitch_bits;
+       
    
        /* Program Hardware Status Page */
        dev_priv->hw_status_page = i810_alloc_page(dev);
@@ -366,37 +486,270 @@ int i810_dma_init(struct inode *inode, struct file *filp,
        return retcode;
 }
 
-static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf,
-                                     int used )
+
+
+/* Most efficient way to verify state for the i810 is as it is
+ * emitted.  Non-conformant state is silently dropped.
+ *
+ * Use 'volatile' & local var tmp to force the emitted values to be
+ * identical to the verified ones.
+ */
+static void i810EmitContextVerified( drm_device_t *dev, 
+                                    volatile unsigned int *code ) 
+{      
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
+
+       OUT_RING( GFX_OP_COLOR_FACTOR );
+       OUT_RING( code[I810_CTXREG_CF1] );
+
+       OUT_RING( GFX_OP_STIPPLE );
+       OUT_RING( code[I810_CTXREG_ST1] );
+
+       for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
+               tmp = code[i];
+
+               if ((tmp & (7<<29)) == (3<<29) &&
+                   (tmp & (0x1f<<24)) < (0x1d<<24)) 
+               {
+                       OUT_RING( tmp ); 
+                       j++;
+               } 
+       }
+
+       if (j & 1) 
+               OUT_RING( 0 ); 
+
+       ADVANCE_LP_RING();
+}
+
+static void i810EmitTexVerified( drm_device_t *dev, 
+                                volatile unsigned int *code ) 
+{      
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
+
+       OUT_RING( GFX_OP_MAP_INFO );
+       OUT_RING( code[I810_TEXREG_MI1] );
+       OUT_RING( code[I810_TEXREG_MI2] );
+       OUT_RING( code[I810_TEXREG_MI3] );
+
+       for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
+               tmp = code[i];
+
+               if ((tmp & (7<<29)) == (3<<29) &&
+                   (tmp & (0x1f<<24)) < (0x1d<<24)) 
+               {
+                       OUT_RING( tmp ); 
+                       j++;
+               }
+       } 
+               
+       if (j & 1) 
+               OUT_RING( 0 ); 
+
+       ADVANCE_LP_RING();
+}
+
+
+/* Need to do some additional checking when setting the dest buffer.
+ */
+static void i810EmitDestVerified( drm_device_t *dev, 
+                                 volatile unsigned int *code ) 
+{      
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
+
+       tmp = code[I810_DESTREG_DI1];
+       if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
+               OUT_RING( CMD_OP_DESTBUFFER_INFO );
+               OUT_RING( tmp );
+       } else
+          DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
+                    tmp, dev_priv->front_di1, dev_priv->back_di1);
+
+       /* invarient:
+        */
+       OUT_RING( CMD_OP_Z_BUFFER_INFO );
+       OUT_RING( dev_priv->zi1 );
+
+       OUT_RING( GFX_OP_DESTBUFFER_VARS );
+       OUT_RING( code[I810_DESTREG_DV1] );
+
+       OUT_RING( GFX_OP_DRAWRECT_INFO );
+       OUT_RING( code[I810_DESTREG_DR1] );
+       OUT_RING( code[I810_DESTREG_DR2] );
+       OUT_RING( code[I810_DESTREG_DR3] );
+       OUT_RING( code[I810_DESTREG_DR4] );
+       OUT_RING( 0 );
+
+       ADVANCE_LP_RING();
+}
+
+
+
+static void i810EmitState( drm_device_t *dev )
 {
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-       unsigned long address = (unsigned long)buf->bus_address;
-       unsigned long start = address - dev->agp->base;
-       RING_LOCALS;
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int dirty = sarea_priv->dirty;
 
-       dev_priv->counter++;
-       DRM_DEBUG(  "dispatch counter : %ld\n", dev_priv->counter);
-       DRM_DEBUG(  "i810_dma_dispatch\n");
-       DRM_DEBUG(  "start : 0x%lx\n", start);
-       DRM_DEBUG(  "used : 0x%x\n", used);
-       DRM_DEBUG(  "start + used - 4 : 0x%lx\n", start + used - 4);
-       i810_kernel_lost_context(dev);
+       if (dirty & I810_UPLOAD_BUFFERS) {
+               i810EmitDestVerified( dev, sarea_priv->BufferState );
+               sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
+       }
 
-       BEGIN_LP_RING(10);
-       OUT_RING( CMD_OP_BATCH_BUFFER );
-       OUT_RING( start | BB1_PROTECTED );
-       OUT_RING( start + used - 4 );
-       OUT_RING( CMD_STORE_DWORD_IDX );
-       OUT_RING( 20 );
-       OUT_RING( dev_priv->counter );
-       OUT_RING( CMD_STORE_DWORD_IDX );
-       OUT_RING( buf_priv->my_use_idx );
-       OUT_RING( I810_BUF_FREE );   
-       OUT_RING( CMD_REPORT_HEAD );
-       ADVANCE_LP_RING();
+       if (dirty & I810_UPLOAD_CTX) {
+               i810EmitContextVerified( dev, sarea_priv->ContextState );
+               sarea_priv->dirty &= ~I810_UPLOAD_CTX;
+       }
+
+       if (dirty & I810_UPLOAD_TEX0) {
+               i810EmitTexVerified( dev, sarea_priv->TexState[0] );
+               sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
+       }
+
+       if (dirty & I810_UPLOAD_TEX1) {
+               i810EmitTexVerified( dev, sarea_priv->TexState[1] );
+               sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
+       }
+}
+
+
+
+/* need to verify 
+ */
+static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, 
+                                    unsigned int clear_color,
+                                    unsigned int clear_zval )
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = 2;
+       int i;
+       RING_LOCALS;
+
+       i810_kernel_lost_context(dev);
+
+       if (nbox > I810_NR_SAREA_CLIPRECTS)
+               nbox = I810_NR_SAREA_CLIPRECTS;
+
+       for (i = 0 ; i < nbox ; i++, pbox++) {
+               unsigned int x = pbox->x1;
+               unsigned int y = pbox->y1;
+               unsigned int width = (pbox->x2 - x) * cpp;
+               unsigned int height = pbox->y2 - y;
+               unsigned int start = y * pitch + x * cpp;
+
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w ||
+                   pbox->y2 > dev_priv->h)
+                       continue;
+
+               if ( flags & I810_FRONT ) {         
+                       DRM_DEBUG("clear front\n");
+                       BEGIN_LP_RING( 6 );         
+                       OUT_RING( BR00_BITBLT_CLIENT | 
+                                 BR00_OP_COLOR_BLT | 0x3 );
+                       OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+                       OUT_RING( (height << 16) | width );
+                       OUT_RING( start );
+                       OUT_RING( clear_color );
+                       OUT_RING( 0 );
+                       ADVANCE_LP_RING();
+               }
+
+               if ( flags & I810_BACK ) {
+                       DRM_DEBUG("clear back\n");
+                       BEGIN_LP_RING( 6 );         
+                       OUT_RING( BR00_BITBLT_CLIENT | 
+                                 BR00_OP_COLOR_BLT | 0x3 );
+                       OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+                       OUT_RING( (height << 16) | width );
+                       OUT_RING( dev_priv->back_offset + start );
+                       OUT_RING( clear_color );
+                       OUT_RING( 0 );
+                       ADVANCE_LP_RING();
+               }
+
+               if ( flags & I810_DEPTH ) {
+                       DRM_DEBUG("clear depth\n");
+                       BEGIN_LP_RING( 6 );         
+                       OUT_RING( BR00_BITBLT_CLIENT | 
+                                 BR00_OP_COLOR_BLT | 0x3 );
+                       OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+                       OUT_RING( (height << 16) | width );
+                       OUT_RING( dev_priv->depth_offset + start );
+                       OUT_RING( clear_zval );
+                       OUT_RING( 0 );
+                       ADVANCE_LP_RING();
+               }
+       }
+}
+
+static void i810_dma_dispatch_swap( drm_device_t *dev )
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = 2;
+       int ofs = dev_priv->back_offset;
+       int i;
+       RING_LOCALS;
+
+       DRM_DEBUG("swapbuffers\n");
+
+       i810_kernel_lost_context(dev);
+
+       if (nbox > I810_NR_SAREA_CLIPRECTS)
+               nbox = I810_NR_SAREA_CLIPRECTS;
+
+       for (i = 0 ; i < nbox; i++, pbox++) 
+       {
+               unsigned int w = pbox->x2 - pbox->x1;
+               unsigned int h = pbox->y2 - pbox->y1;
+               unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
+               unsigned int start = ofs + dst;
+
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w ||
+                   pbox->y2 > dev_priv->h)
+                       continue;
+               DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
+                         pbox[i].x1, pbox[i].y1,
+                         pbox[i].x2, pbox[i].y2);
+
+               BEGIN_LP_RING( 6 );
+               OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
+               OUT_RING( pitch | (0xCC << 16));
+               OUT_RING( (h << 16) | (w * cpp));
+               OUT_RING( dst );
+               OUT_RING( pitch );      
+               OUT_RING( start );
+               ADVANCE_LP_RING();
+       }
 }
 
+
 static void i810_dma_dispatch_vertex(drm_device_t *dev, 
                                     drm_buf_t *buf,
                                     int discard,
@@ -409,14 +762,29 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
        int nbox = sarea_priv->nbox;
        unsigned long address = (unsigned long)buf->bus_address;
        unsigned long start = address - dev->agp->base;     
-       int i = 0;
+       int i = 0, u;
        RING_LOCALS;
 
-   
+       i810_kernel_lost_context(dev);
+
        if (nbox > I810_NR_SAREA_CLIPRECTS) 
                nbox = I810_NR_SAREA_CLIPRECTS;
-   
-       DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", 
+
+       if (discard) {
+               u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, 
+                           I810_BUF_HARDWARE);
+               if(u != I810_BUF_CLIENT) {
+                       DRM_DEBUG("xxxx 2\n");
+               }
+       }
+
+       if (used > 4*1024) 
+               used = 0;
+
+       if (sarea_priv->dirty)
+          i810EmitState( dev );
+
+       DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", 
                  address, used, nbox);
 
        dev_priv->counter++;
@@ -425,8 +793,20 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
        DRM_DEBUG(  "start : %lx\n", start);
        DRM_DEBUG(  "used : %d\n", used);
        DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
-       i810_kernel_lost_context(dev);
 
+       if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
+               *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
+                                            sarea_priv->vertex_prim |
+                                            ((used/4)-2));
+               
+               if (used & 4) {
+                       *(u32 *)((u32)buf_priv->virtual + used) = 0;
+                       used += 4;
+               }
+
+               i810_unmap_buffer(buf);
+       }
+                  
        if (used) {
                do {
                        if (i < nbox) {
@@ -434,7 +814,7 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
                                OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | 
                                          SC_ENABLE );
                                OUT_RING( GFX_OP_SCISSOR_INFO );
-                               OUT_RING( box[i].x1 | (box[i].y1 << 16) );
+                               OUT_RING( box[i].x1 | (box[i].y1<<16) );
                                OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
                                ADVANCE_LP_RING();
                        }
@@ -479,7 +859,9 @@ static void i810_dma_service(int irq, void *device, struct pt_regs *regs)
        temp = temp & ~(0x6000);
        if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, 
                                   temp); /* Clear all interrupts */
-   
+       else
+          return;
        queue_task(&dev->tq, &tq_immediate);
        mark_bh(IMMEDIATE_BH);
 }
@@ -539,7 +921,7 @@ int i810_irq_install(drm_device_t *dev, int irq)
                                /* Install handler */
        if ((retcode = request_irq(dev->irq,
                                   i810_dma_service,
-                                  0,
+                                  SA_SHIRQ,
                                   dev->devname,
                                   dev))) {
                down(&dev->struct_sem);
@@ -560,6 +942,9 @@ int i810_irq_uninstall(drm_device_t *dev)
        int irq;
        u16 temp;
 
+
+/*     return 0; */
+
        down(&dev->struct_sem);
        irq      = dev->irq;
        dev->irq = 0;
@@ -618,10 +1003,15 @@ static inline void i810_dma_emit_flush(drm_device_t *dev)
        RING_LOCALS;
 
        i810_kernel_lost_context(dev);
+
        BEGIN_LP_RING(2);
        OUT_RING( CMD_REPORT_HEAD );
-       OUT_RING( GFX_OP_USER_INTERRUPT );
+       OUT_RING( GFX_OP_USER_INTERRUPT );
        ADVANCE_LP_RING();
+
+/*     i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
+/*             atomic_set(&dev_priv->flush_done, 1); */
+/*             wake_up_interruptible(&dev_priv->flush_queue); */
 }
 
 static inline void i810_dma_quiescent_emit(drm_device_t *dev)
@@ -630,13 +1020,17 @@ static inline void i810_dma_quiescent_emit(drm_device_t *dev)
        RING_LOCALS;
 
        i810_kernel_lost_context(dev);
-       BEGIN_LP_RING(4);
 
+       BEGIN_LP_RING(4);
        OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
        OUT_RING( CMD_REPORT_HEAD );
-       OUT_RING( GFX_OP_USER_INTERRUPT );
-       OUT_RING( 0 );
+       OUT_RING( 0 );
+       OUT_RING( GFX_OP_USER_INTERRUPT );
        ADVANCE_LP_RING();
+
+/*     i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
+/*             atomic_set(&dev_priv->flush_done, 1); */
+/*             wake_up_interruptible(&dev_priv->flush_queue); */
 }
 
 static void i810_dma_quiescent(drm_device_t *dev)
@@ -676,8 +1070,9 @@ static int i810_flush_queue(drm_device_t *dev)
 {
        DECLARE_WAITQUEUE(entry, current);
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+       drm_device_dma_t *dma = dev->dma;
        unsigned long end;
-       int ret = 0;      
+       int i, ret = 0;      
 
        if(dev_priv == NULL) {
                return 0;
@@ -702,7 +1097,21 @@ static int i810_flush_queue(drm_device_t *dev)
    
        current->state = TASK_RUNNING;
        remove_wait_queue(&dev_priv->flush_queue, &entry);
-   
+
+
+       for (i = 0; i < dma->buf_count; i++) {
+               drm_buf_t *buf = dma->buflist[ i ];
+               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+          
+               int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE, 
+                                  I810_BUF_FREE);
+
+               if (used == I810_BUF_HARDWARE)
+                       DRM_DEBUG("reclaimed from HARDWARE\n");
+               if (used == I810_BUF_CLIENT)
+                       DRM_DEBUG("still on client HARDWARE\n");
+       }
+
        return ret;
 }
 
@@ -713,20 +1122,23 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
        int              i;
 
        if (!dma) return;
-       if(dev->dev_private == NULL) return;
-       if(dma->buflist == NULL) return;
+       if (!dev->dev_private) return;
+       if (!dma->buflist) return;
+
         i810_flush_queue(dev);
 
        for (i = 0; i < dma->buf_count; i++) {
                drm_buf_t *buf = dma->buflist[ i ];
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
           
-               /* Only buffers that need to get reclaimed ever 
-                * get set to free 
-                */
                if (buf->pid == pid && buf_priv) {
-                       cmpxchg(buf_priv->in_use, 
-                               I810_BUF_USED, I810_BUF_FREE);
+                       int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, 
+                                          I810_BUF_FREE);
+
+                       if (used == I810_BUF_CLIENT)
+                               DRM_DEBUG("reclaimed from client\n");
+                       if(buf_priv->currently_mapped == I810_BUF_MAPPED)
+                               buf_priv->currently_mapped = I810_BUF_UNMAPPED;
                }
        }
 }
@@ -760,19 +1172,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
         */
 
        if (!ret) {
-#if 0
-               if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
-                   != lock.context) {
-                       long j = jiffies - dev->lock.lock_time;
-
-                       if (j > 0 && j <= DRM_LOCK_SLICE) {
-                               /* Can't take lock if we just had it and
-                                  there is contention. */
-                               current->state = TASK_INTERRUPTIBLE;
-                               schedule_timeout(j);
-                       }
-               }
-#endif
                add_wait_queue(&dev->lock.lock_queue, &entry);
                for (;;) {
                        if (!dev->lock.hw_lock) {
@@ -829,90 +1228,80 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp,
        return 0;
 }
 
-static int i810DmaGeneral(drm_device_t *dev, drm_i810_general_t *args)
-{
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf = dma->buflist[ args->idx ];
-       
-       if (!args->used) {
-               i810_freelist_put(dev, buf);
-       } else {  
-               i810_dma_dispatch_general( dev, buf, args->used );
-               atomic_add(args->used, &dma->total_bytes);
-               atomic_inc(&dma->total_dmas);
-       }
-       return 0; 
-}
-
-static int i810DmaVertex(drm_device_t *dev, drm_i810_vertex_t *args)
-{
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf = dma->buflist[ args->idx ];
-       i810_dma_dispatch_vertex( dev, buf, args->discard, args->used );
-       atomic_add(args->used, &dma->total_bytes);
-       atomic_inc(&dma->total_dmas);
-       return 0;
-}
 
-int i810_dma_general(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
+int i810_dma_vertex(struct inode *inode, struct file *filp,
+              unsigned int cmd, unsigned long arg)
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
-       drm_i810_general_t general;
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+       drm_device_dma_t *dma = dev->dma;
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
                                        dev_priv->sarea_priv; 
+       drm_i810_vertex_t vertex;
 
-       int retcode = 0;
-       
-       copy_from_user_ret(&general, (drm_i810_general_t *)arg, sizeof(general),
+       copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex),
                           -EFAULT);
 
-       DRM_DEBUG("i810 dma general idx %d used %d\n",
-                 general.idx, general.used);
-   
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-               DRM_ERROR("i810_dma_general called without lock held\n");
+               DRM_ERROR("i810_dma_vertex called without lock held\n");
                return -EINVAL;
        }
 
-       retcode = i810DmaGeneral(dev, &general);
+       DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
+                 vertex.idx, vertex.used, vertex.discard);
+
+       i810_dma_dispatch_vertex( dev, 
+                                 dma->buflist[ vertex.idx ], 
+                                 vertex.discard, vertex.used );
+
+       atomic_add(vertex.used, &dma->total_bytes);
+       atomic_inc(&dma->total_dmas);
        sarea_priv->last_enqueue = dev_priv->counter-1;
        sarea_priv->last_dispatch = (int) hw_status[5];
    
-       return retcode;
+       return 0;
 }
 
-int i810_dma_vertex(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+
+
+int i810_clear_bufs(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-       u32 *hw_status = (u32 *)dev_priv->hw_status_page;
-       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
-                                       dev_priv->sarea_priv; 
-       drm_i810_vertex_t vertex;
-       int retcode = 0;
+       drm_i810_clear_t clear;
 
-       copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex),
+       copy_from_user_ret(&clear, (drm_i810_clear_t *)arg, sizeof(clear), 
                           -EFAULT);
+   
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-               DRM_ERROR("i810_dma_vertex called without lock held\n");
+               DRM_ERROR("i810_clear_bufs called without lock held\n");
                return -EINVAL;
        }
 
-       DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
-                 vertex.idx, vertex.used, vertex.discard);
+       i810_dma_dispatch_clear( dev, clear.flags, 
+                                clear.clear_color, 
+                                clear.clear_depth );
+       return 0;
+}
 
-       retcode = i810DmaVertex(dev, &vertex);
-       sarea_priv->last_enqueue = dev_priv->counter-1;
-       sarea_priv->last_dispatch = (int) hw_status[5];
+int i810_swap_bufs(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;
    
-       return retcode;
+       DRM_DEBUG("i810_swap_bufs\n");
 
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i810_swap_buf called without lock held\n");
+               return -EINVAL;
+       }
+
+       i810_dma_dispatch_swap( dev );
+       return 0;
 }
 
 int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
@@ -929,53 +1318,32 @@ int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
-int i810_dma(struct inode *inode, struct file *filp, unsigned int cmd,
-           unsigned long arg)
+int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
+               unsigned long arg)
 {
        drm_file_t        *priv     = filp->private_data;
        drm_device_t      *dev      = priv->dev;
-       drm_device_dma_t  *dma      = dev->dma;
        int               retcode   = 0;
-       drm_dma_t         d;
+       drm_i810_dma_t    d;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
                                        dev_priv->sarea_priv; 
 
-
-       copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
-       DRM_DEBUG("%d %d: %d send, %d req\n",
-                 current->pid, d.context, d.send_count, d.request_count);
+       DRM_DEBUG("getbuf\n");
+       copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT);
    
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
                DRM_ERROR("i810_dma called without lock held\n");
                return -EINVAL;
        }
-
-       /* Please don't send us buffers.
-        */
-       if (d.send_count != 0) {
-               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         current->pid, d.send_count);
-               return -EINVAL;
-       }
        
-       /* We'll send you buffers.
-        */
-       if (d.request_count < 0 || d.request_count > dma->buf_count) {
-               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         current->pid, d.request_count, dma->buf_count);
-               return -EINVAL;
-       }
-       
-       d.granted_count = 0;
+       d.granted = 0;
 
-       if (!retcode && d.request_count) {
-               retcode = i810_dma_get_buffers(dev, &d);
-       }
+       retcode = i810_dma_get_buffer(dev, &d, filp);
 
-       DRM_DEBUG("i810_dma: %d returning, granted = %d\n",
-                 current->pid, d.granted_count);
+       DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
+                 current->pid, retcode, d.granted);
 
        copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);   
        sarea_priv->last_dispatch = (int) hw_status[5];
index 0754874..4c8e09f 100644 (file)
  * if you change them, you must change the defines in the Xserver.
  */
 
-/* Might one day want to support the client-side ringbuffer code again.
- */
 #ifndef _I810_DEFINES_
 #define _I810_DEFINES_
 
-#define I810_USE_BATCH                 1
 #define I810_DMA_BUF_ORDER             12
 #define I810_DMA_BUF_SZ                (1<<I810_DMA_BUF_ORDER)
 #define I810_DMA_BUF_NR                256
-#define I810_NR_SAREA_CLIPRECTS        2
+#define I810_NR_SAREA_CLIPRECTS        8
 
 /* Each region is a minimum of 64k, and there are at most 64 of them.
  */
-
 #define I810_NR_TEX_REGIONS 64
 #define I810_LOG_MIN_TEX_REGION_SIZE 16
 #endif
 
+#define I810_UPLOAD_TEX0IMAGE  0x1 /* handled clientside */
+#define I810_UPLOAD_TEX1IMAGE  0x2 /* handled clientside */
+#define I810_UPLOAD_CTX        0x4
+#define I810_UPLOAD_BUFFERS    0x8
+#define I810_UPLOAD_TEX0       0x10
+#define I810_UPLOAD_TEX1       0x20
+#define I810_UPLOAD_CLIPRECTS  0x40
+
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer.  These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+/* Destbuffer state 
+ *    - backbuffer linear offset and pitch -- invarient in the current dri
+ *    - zbuffer linear offset and pitch -- also invarient
+ *    - drawing origin in back and depth buffers.
+ *
+ * Keep the depth/back buffer state here to acommodate private buffers
+ * in the future.
+ */
+#define I810_DESTREG_DI0  0    /* CMD_OP_DESTBUFFER_INFO (2 dwords) */
+#define I810_DESTREG_DI1  1
+#define I810_DESTREG_DV0  2    /* GFX_OP_DESTBUFFER_VARS (2 dwords) */
+#define I810_DESTREG_DV1  3
+#define I810_DESTREG_DR0  4    /* GFX_OP_DRAWRECT_INFO (4 dwords) */
+#define I810_DESTREG_DR1  5
+#define I810_DESTREG_DR2  6
+#define I810_DESTREG_DR3  7
+#define I810_DESTREG_DR4  8
+#define I810_DEST_SETUP_SIZE 10
+
+/* Context state
+ */
+#define I810_CTXREG_CF0   0    /* GFX_OP_COLOR_FACTOR */
+#define I810_CTXREG_CF1   1    
+#define I810_CTXREG_ST0   2     /* GFX_OP_STIPPLE */
+#define I810_CTXREG_ST1   3
+#define I810_CTXREG_VF    4    /* GFX_OP_VERTEX_FMT */
+#define I810_CTXREG_MT    5    /* GFX_OP_MAP_TEXELS */
+#define I810_CTXREG_MC0   6    /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
+#define I810_CTXREG_MC1   7     /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
+#define I810_CTXREG_MC2   8    /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
+#define I810_CTXREG_MA0   9    /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
+#define I810_CTXREG_MA1   10   /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
+#define I810_CTXREG_MA2   11   /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */
+#define I810_CTXREG_SDM   12   /* GFX_OP_SRC_DEST_MONO */
+#define I810_CTXREG_FOG   13   /* GFX_OP_FOG_COLOR */
+#define I810_CTXREG_B1    14   /* GFX_OP_BOOL_1 */
+#define I810_CTXREG_B2    15   /* GFX_OP_BOOL_2 */
+#define I810_CTXREG_LCS   16   /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */
+#define I810_CTXREG_PV    17   /* GFX_OP_PV_RULE -- Invarient! */
+#define I810_CTXREG_ZA    18   /* GFX_OP_ZBIAS_ALPHAFUNC */
+#define I810_CTXREG_AA    19   /* GFX_OP_ANTIALIAS */
+#define I810_CTX_SETUP_SIZE 20 
+
+/* Texture state (per tex unit)
+ */
+#define I810_TEXREG_MI0  0     /* GFX_OP_MAP_INFO (4 dwords) */
+#define I810_TEXREG_MI1  1     
+#define I810_TEXREG_MI2  2     
+#define I810_TEXREG_MI3  3     
+#define I810_TEXREG_MF   4     /* GFX_OP_MAP_FILTER */
+#define I810_TEXREG_MLC  5     /* GFX_OP_MAP_LOD_CTL */
+#define I810_TEXREG_MLL  6     /* GFX_OP_MAP_LOD_LIMITS */
+#define I810_TEXREG_MCS  7     /* GFX_OP_MAP_COORD_SETS ??? */
+#define I810_TEX_SETUP_SIZE 8
+
+#define I810_FRONT   0x1
+#define I810_BACK    0x2
+#define I810_DEPTH   0x4
+
+
 typedef struct _drm_i810_init {
-       enum {
-               I810_INIT_DMA = 0x01,
-               I810_CLEANUP_DMA = 0x02
+       enum {
+               I810_INIT_DMA = 0x01,
+               I810_CLEANUP_DMA = 0x02
        } func;
-       int ring_map_idx;
-       int buffer_map_idx;
+       int ring_map_idx;
+       int buffer_map_idx;
        int sarea_priv_offset;
-       unsigned long ring_start;
-       unsigned long ring_end;
-       unsigned long ring_size;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits; 
 } drm_i810_init_t;
 
 /* Warning: If you change the SAREA structure you must change the Xserver
@@ -46,6 +123,11 @@ typedef struct _drm_i810_tex_region {
 } drm_i810_tex_region_t;
 
 typedef struct _drm_i810_sarea {
+       unsigned int ContextState[I810_CTX_SETUP_SIZE];
+       unsigned int BufferState[I810_DEST_SETUP_SIZE];
+       unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+       unsigned int dirty;
+
        unsigned int nbox;
        drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
 
@@ -72,12 +154,18 @@ typedef struct _drm_i810_sarea {
        int last_dispatch;      /* age of the most recently dispatched buffer */
        int last_quiescent;     /*  */
        int ctxOwner;           /* last context to upload state */
+
+       int vertex_prim;
+
 } drm_i810_sarea_t;
 
-typedef struct _drm_i810_general {
-       int idx;
-       int used;
-} drm_i810_general_t;
+typedef struct _drm_i810_clear {
+       int clear_color;
+       int clear_depth;
+       int flags;
+} drm_i810_clear_t;
+
+
 
 /* These may be placeholders if we have more cliprects than
  * I810_NR_SAREA_CLIPRECTS.  In that case, the client sets discard to
@@ -90,4 +178,11 @@ typedef struct _drm_i810_vertex {
        int discard;            /* client is finished with the buffer? */
 } drm_i810_vertex_t;
 
+typedef struct drm_i810_dma {
+       void *virtual;
+       int request_idx;
+       int request_size;
+       int granted;
+} drm_i810_dma_t;
+
 #endif /* _I810_DRM_H_ */
index f1c8325..75b402d 100644 (file)
@@ -80,7 +80,6 @@ static drm_ioctl_desc_t             i810_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]    = { i810_addbufs,   1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]   = { i810_markbufs,  1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]   = { i810_infobufs,  1, 0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]    = { i810_mapbufs,   1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]   = { i810_freebufs,  1, 0 },
 
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]     = { i810_addctx,    1, 1 },
@@ -93,8 +92,6 @@ static drm_ioctl_desc_t             i810_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]    = { drm_adddraw,    1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]     = { drm_rmdraw,     1, 1 },
 
-       [DRM_IOCTL_NR(DRM_IOCTL_DMA)]         = { i810_dma,       1, 0 },
-
        [DRM_IOCTL_NR(DRM_IOCTL_LOCK)]        = { i810_lock,      1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]      = { i810_unlock,    1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_FINISH)]      = { drm_finish,     1, 0 },
@@ -107,11 +104,14 @@ static drm_ioctl_desc_t         i810_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]    = { drm_agp_free,    1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]    = { drm_agp_bind,    1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]  = { drm_agp_unbind,  1, 1 },
+
        [DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)]   = { i810_dma_init,   1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_I810_DMA)]    = { i810_dma_general,1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_CLEAR)]  = { i810_clear_bufs, 1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)]  = { i810_flush_ioctl,1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage,     1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf,     1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)]   = { i810_swap_bufs,  1, 0 },
 };
 
 #define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls)
index 1badd36..334cacb 100644 (file)
 #ifndef _I810_DRV_H_
 #define _I810_DRV_H_
 
+typedef struct drm_i810_buf_priv {
+       u32 *in_use;
+       int my_use_idx;
+       int currently_mapped;
+       void *virtual;
+       void *kernel_virtual;
+       int map_count;
+       struct vm_area_struct *vma;
+} drm_i810_buf_priv_t;
+
 typedef struct _drm_i810_ring_buffer{
        int tail_mask;
        unsigned long Start;
@@ -55,6 +65,15 @@ typedef struct drm_i810_private {
 
        atomic_t flush_done;
        wait_queue_head_t flush_queue;  /* Processes waiting until flush    */
+       drm_buf_t *mmap_buffer;
+
+       
+       u32 front_di1, back_di1, zi1;
+       
+       int back_offset;
+       int depth_offset;
+       int w, h;
+       int pitch;
 } drm_i810_private_t;
 
                                /* i810_drv.c */
@@ -71,8 +90,8 @@ extern int  i810_unlock(struct inode *inode, struct file *filp,
 
                                /* i810_dma.c */
 extern int  i810_dma_schedule(drm_device_t *dev, int locked);
-extern int  i810_dma(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
+extern int  i810_getbuf(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
 extern int  i810_irq_install(drm_device_t *dev, int irq);
 extern int  i810_irq_uninstall(drm_device_t *dev);
 extern int  i810_control(struct inode *inode, struct file *filp,
@@ -86,6 +105,7 @@ extern int  i810_flush_ioctl(struct inode *inode, struct file *filp,
 extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid);
 extern int  i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
                        unsigned long arg);
+extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
 
 
                                /* i810_bufs.c */
@@ -97,8 +117,6 @@ extern int  i810_markbufs(struct inode *inode, struct file *filp,
                         unsigned int cmd, unsigned long arg);
 extern int  i810_freebufs(struct inode *inode, struct file *filp,
                         unsigned int cmd, unsigned long arg);
-extern int  i810_mapbufs(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
 extern int  i810_addmap(struct inode *inode, struct file *filp,
                       unsigned int cmd, unsigned long arg);
 
@@ -121,32 +139,17 @@ extern int  i810_rmctx(struct inode *inode, struct file *filp,
 extern int  i810_context_switch(drm_device_t *dev, int old, int new);
 extern int  i810_context_switch_complete(drm_device_t *dev, int new);
 
-
-
-
-/* Copy the outstanding cliprects for every I810_DMA_VERTEX buffer.
- * This can be fixed by emitting directly to the ringbuffer in the
- * 'vertex_dma' ioctl.  
-*/
-typedef struct {
-       u32 *in_use;
-       int my_use_idx;
-} drm_i810_buf_priv_t;
-
-
-#define I810_DMA_GENERAL 0
-#define I810_DMA_VERTEX  1
-#define I810_DMA_DISCARD 2     /* not used */
-
 #define I810_VERBOSE 0
 
 
 int i810_dma_vertex(struct inode *inode, struct file *filp,
                    unsigned int cmd, unsigned long arg);
 
-int i810_dma_general(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg);
+int i810_swap_bufs(struct inode *inode, struct file *filp,
+                  unsigned int cmd, unsigned long arg);
 
+int i810_clear_bufs(struct inode *inode, struct file *filp,
+                   unsigned int cmd, unsigned long arg);
 
 #define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
@@ -200,5 +203,22 @@ int i810_dma_general(struct inode *inode, struct file *filp,
 #define SCI_YMAX_MASK      (0xffff<<16)
 #define SCI_XMAX_MASK      (0xffff<<0)
 
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x2)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+#define GFX_OP_PRIMITIVE         ((0x3<<29)|(0x1f<<24))
+
+#define CMD_OP_Z_BUFFER_INFO     ((0x0<<29)|(0x16<<23))
+#define CMD_OP_DESTBUFFER_INFO   ((0x0<<29)|(0x15<<23))
+
+#define BR00_BITBLT_CLIENT   0x40000000
+#define BR00_OP_COLOR_BLT    0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR13_SOLID_PATTERN   0x80000000
+
+
+
 #endif
 
index 82dda64..5fabe1f 100644 (file)
@@ -111,6 +111,7 @@ static drm_ioctl_desc_t           mga_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)]   = { mga_iload,       1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)]  = { mga_vertex,      1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)]   = { mga_flush_ioctl, 1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_indices,     1, 0 },
 };
 
 #define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
index 25e4cce..74ef83f 100644 (file)
@@ -341,13 +341,16 @@ typedef struct drm_agp_info {
 #define DRM_IOCTL_MGA_ILOAD   DRM_IOW( 0x43, drm_mga_iload_t)
 #define DRM_IOCTL_MGA_VERTEX  DRM_IOW( 0x44, drm_mga_vertex_t)
 #define DRM_IOCTL_MGA_FLUSH   DRM_IOW( 0x45, drm_lock_t )
+#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
 
 /* I810 specific ioctls */
 #define DRM_IOCTL_I810_INIT    DRM_IOW( 0x40, drm_i810_init_t)
 #define DRM_IOCTL_I810_VERTEX  DRM_IOW( 0x41, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_DMA     DRM_IOW( 0x42, drm_i810_general_t)
+#define DRM_IOCTL_I810_CLEAR   DRM_IOW( 0x42, drm_i810_clear_t)
 #define DRM_IOCTL_I810_FLUSH   DRM_IO ( 0x43)
 #define DRM_IOCTL_I810_GETAGE  DRM_IO ( 0x44)
+#define DRM_IOCTL_I810_GETBUF  DRM_IOW( 0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP    DRM_IO ( 0x46)
 
 /* Rage 128 specific ioctls */
 #define DRM_IOCTL_R128_INIT    DRM_IOW( 0x40, drm_r128_init_t)
index c025e40..9737ae9 100644 (file)
@@ -120,6 +120,7 @@ int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
                buf->dev_private = drm_alloc(sizeof(drm_i810_buf_priv_t), 
                                             DRM_MEM_BUFS);
                buf->dev_priv_size = sizeof(drm_i810_buf_priv_t);
+               memset(buf->dev_private, 0, sizeof(drm_i810_buf_priv_t));
 
 #if DRM_DMA_HISTOGRAM
                buf->time_queued = 0;
@@ -332,113 +333,3 @@ int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
-int i810_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
-                unsigned long arg)
-{
-       drm_file_t       *priv   = filp->private_data;
-       drm_device_t     *dev    = priv->dev;
-       drm_device_dma_t *dma    = dev->dma;
-       int              retcode = 0;
-       const int        zero    = 0;
-       unsigned long    virtual;
-       unsigned long    address;
-       drm_buf_map_t    request;
-       int              i;
-
-       if (!dma) return -EINVAL;
-       
-       DRM_DEBUG("\n");
-
-       spin_lock(&dev->count_lock);
-       if (atomic_read(&dev->buf_alloc)) {
-               spin_unlock(&dev->count_lock);
-               DRM_DEBUG("Busy\n");
-               return -EBUSY;
-       }
-       ++dev->buf_use;         /* Can't allocate more after this call */
-       spin_unlock(&dev->count_lock);
-
-       copy_from_user_ret(&request,
-                          (drm_buf_map_t *)arg,
-                          sizeof(request),
-                          -EFAULT);
-       DRM_DEBUG("dma->flags : %lx\n", dma->flags);
-       if (request.count >= dma->buf_count) {
-               if(dma->flags & _DRM_DMA_USE_AGP) {
-                       drm_i810_private_t *dev_priv = 
-                               (drm_i810_private_t *)dev->dev_private;
-                       drm_map_t *map = NULL;
-             
-                       map = dev->maplist[dev_priv->buffer_map_idx];
-                       if (!map) {
-                               DRM_DEBUG("map is null\n");
-                               retcode = -EINVAL;
-                               goto done;
-                       }
-                       DRM_DEBUG("map->offset : %lx\n", map->offset);
-                       DRM_DEBUG("map->size : %lx\n", map->size);
-                       DRM_DEBUG("map->type : %d\n", map->type);
-                       DRM_DEBUG("map->flags : %x\n", map->flags);
-                       DRM_DEBUG("map->handle : %lx\n", map->handle);
-                       DRM_DEBUG("map->mtrr : %d\n", map->mtrr);
-                       down(&current->mm->mmap_sem);
-                       virtual = do_mmap(filp, 0, map->size, 
-                                         PROT_READ|PROT_WRITE,
-                                         MAP_SHARED, 
-                                         (unsigned long)map->offset);
-
-                       up(&current->mm->mmap_sem);
-               } else {
-                       down(&current->mm->mmap_sem);
-                       virtual = do_mmap(filp, 0, dma->byte_count,
-                                         PROT_READ|PROT_WRITE, MAP_SHARED, 0);
-                       up(&current->mm->mmap_sem);
-               }
-               if (virtual > -1024UL) {
-                       /* Real error */
-                       DRM_DEBUG("mmap error\n");
-                       retcode = (signed long)virtual;
-                       goto done;
-               }
-               request.virtual = (void *)virtual;
-          
-               for (i = 0; i < dma->buf_count; i++) {
-                       if (copy_to_user(&request.list[i].idx,
-                                        &dma->buflist[i]->idx,
-                                        sizeof(request.list[0].idx))) {
-                               retcode = -EFAULT;
-                               goto done;
-                       }
-                       if (copy_to_user(&request.list[i].total,
-                                        &dma->buflist[i]->total,
-                                        sizeof(request.list[0].total))) {
-                               retcode = -EFAULT;
-                               goto done;
-                       }
-                       if (copy_to_user(&request.list[i].used,
-                                        &zero,
-                                        sizeof(zero))) {
-                               retcode = -EFAULT;
-                               goto done;
-                       }
-                       address = virtual + dma->buflist[i]->offset;
-                       if (copy_to_user(&request.list[i].address,
-                                        &address,
-                                        sizeof(address))) {
-                               retcode = -EFAULT;
-                               goto done;
-                       }
-               }
-       }
- done:
-       request.count = dma->buf_count;
-       DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
-   
-       copy_to_user_ret((drm_buf_map_t *)arg,
-                        &request,
-                        sizeof(request),
-                        -EFAULT);
-
-       DRM_DEBUG("retcode : %d\n", retcode);
-       return retcode;
-}
index 6ac4d2e..f041f20 100644 (file)
 
 #include <linux/interrupt.h>   /* For task queue support */
 
-#define I810_BUF_FREE          1
-#define I810_BUF_USED          0
+#define I810_BUF_FREE          2
+#define I810_BUF_CLIENT                1
+#define I810_BUF_HARDWARE              0
+
+#define I810_BUF_UNMAPPED 0
+#define I810_BUF_MAPPED   1
 
 #define I810_REG(reg)          2
 #define I810_BASE(reg)         ((unsigned long) \
@@ -91,7 +95,7 @@ static inline void i810_print_status_page(drm_device_t *dev)
        DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
        DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
        for(i = 6; i < dma->buf_count + 6; i++) {
-               DRM_DEBUG(  "buffer status idx : %d used: %d\n", i - 6, temp[i]);
+               DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]);
        }
 }
 
@@ -108,7 +112,7 @@ static drm_buf_t *i810_freelist_get(drm_device_t *dev)
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
                /* In use is already a pointer */
                used = cmpxchg(buf_priv->in_use, I810_BUF_FREE, 
-                              I810_BUF_USED);
+                              I810_BUF_CLIENT);
                if(used == I810_BUF_FREE) {
                        return buf;
                }
@@ -126,8 +130,8 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
        int used;
    
        /* In use is already a pointer */
-       used = cmpxchg(buf_priv->in_use, I810_BUF_USED, I810_BUF_FREE);
-       if(used != I810_BUF_USED) {
+       used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
+       if(used != I810_BUF_CLIENT) {
                DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
                return -EINVAL;
        }
@@ -135,26 +139,114 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
        return 0;
 }
 
-static int i810_dma_get_buffers(drm_device_t *dev, drm_dma_t *d)
+static struct file_operations i810_buffer_fops = {
+       open:    i810_open,
+       flush:   drm_flush,
+       release: i810_release,
+       ioctl:   i810_ioctl,
+       mmap:    i810_mmap_buffers,
+       read:    drm_read,
+       fasync:  drm_fasync,
+       poll:    drm_poll,
+};
+
+int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+{
+       drm_file_t        *priv   = filp->private_data;
+       drm_device_t      *dev    = priv->dev;
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_buf_t *buf = dev_priv->mmap_buffer;
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+   
+       vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+       vma->vm_file = filp;
+   
+       buf_priv->currently_mapped = I810_BUF_MAPPED;
+
+       if (remap_page_range(vma->vm_start,
+                            VM_OFFSET(vma),
+                            vma->vm_end - vma->vm_start,
+                            vma->vm_page_prot)) return -EAGAIN;
+       return 0;
+}
+
+static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
 {
-       int               i;
+       drm_file_t        *priv   = filp->private_data;
+       drm_device_t      *dev    = priv->dev;
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       struct file_operations *old_fops;
+       int retcode = 0;
+
+       if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
+       down(&current->mm->mmap_sem);
+       old_fops = filp->f_op;
+       filp->f_op = &i810_buffer_fops;
+       dev_priv->mmap_buffer = buf;
+       buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, 
+                                           PROT_READ|PROT_WRITE,
+                                           MAP_SHARED, 
+                                           buf->bus_address);
+       dev_priv->mmap_buffer = NULL;
+       filp->f_op = old_fops;
+       if ((unsigned long)buf_priv->virtual > -1024UL) {
+               /* Real error */
+               DRM_DEBUG("mmap error\n");
+               retcode = (signed int)buf_priv->virtual;
+               buf_priv->virtual = 0;
+       }
+       up(&current->mm->mmap_sem);
+       return retcode;
+}
+
+static int i810_unmap_buffer(drm_buf_t *buf)
+{
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       int retcode = 0;
+
+       if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL;
+       down(&current->mm->mmap_sem);
+        retcode = do_munmap((unsigned long)buf_priv->virtual, 
+                           (size_t) buf->total);
+       buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+       buf_priv->virtual = 0;
+       up(&current->mm->mmap_sem);
+
+       return retcode;
+}
+
+static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, 
+                              struct file *filp)
+{
+       drm_file_t        *priv   = filp->private_data;
        drm_buf_t         *buf;
+       drm_i810_buf_priv_t *buf_priv;
+       int retcode = 0;
 
-       for (i = d->granted_count; i < d->request_count; i++) {
-               buf = i810_freelist_get(dev);
-               if (!buf) break;
-               buf->pid     = current->pid;
-               copy_to_user_ret(&d->request_indices[i],
-                                &buf->idx,
-                                sizeof(buf->idx),
-                                -EFAULT);
-               copy_to_user_ret(&d->request_sizes[i],
-                                &buf->total,
-                                sizeof(buf->total),
-                                -EFAULT);
-               ++d->granted_count;
+       buf = i810_freelist_get(dev);
+       if (!buf) {
+               retcode = -ENOMEM;
+               DRM_DEBUG("%s retcode %d\n", __FUNCTION__, retcode);
+               goto out_get_buf;
        }
-       return 0;
+   
+       retcode = i810_map_buffer(buf, filp);
+       if(retcode) {
+               i810_freelist_put(dev, buf);
+               DRM_DEBUG("mapbuf failed in %s retcode %d\n", 
+                         __FUNCTION__, retcode);
+               goto out_get_buf;
+       }
+       buf->pid     = priv->pid;
+       buf_priv = buf->dev_private;    
+       d->granted = 1;
+       d->request_idx = buf->idx;
+       d->request_size = buf->total;
+       d->virtual = buf_priv->virtual;
+
+out_get_buf:
+       return retcode;
 }
 
 static unsigned long i810_alloc_page(drm_device_t *dev)
@@ -185,7 +277,10 @@ static void i810_free_page(drm_device_t *dev, unsigned long page)
 
 static int i810_dma_cleanup(drm_device_t *dev)
 {
+       drm_device_dma_t *dma = dev->dma;
+
        if(dev->dev_private) {
+               int i;
                drm_i810_private_t *dev_priv = 
                        (drm_i810_private_t *) dev->dev_private;
           
@@ -201,6 +296,12 @@ static int i810_dma_cleanup(drm_device_t *dev)
                drm_free(dev->dev_private, sizeof(drm_i810_private_t), 
                         DRM_MEM_DRIVER);
                dev->dev_private = NULL;
+
+               for (i = 0; i < dma->buf_count; i++) {
+                       drm_buf_t *buf = dma->buflist[ i ];
+                       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+                       drm_ioremapfree(buf_priv->kernel_virtual, buf->total);
+               }
        }
        return 0;
 }
@@ -211,6 +312,7 @@ static int i810_wait_ring(drm_device_t *dev, int n)
        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
        int iters = 0;
        unsigned long end;
+       unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 
        end = jiffies + (HZ*3);
        while (ring->space < n) {
@@ -218,9 +320,11 @@ static int i810_wait_ring(drm_device_t *dev, int n)
        
                ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
                ring->space = ring->head - (ring->tail+8);
+               if (ring->space < 0) ring->space += ring->Size;
           
-               if (ring->space < 0) ring->space += ring->Size;
-          
+               if (ring->head != last_head)
+                  end = jiffies + (HZ*3);
+         
                iters++;
                if((signed)(end - jiffies) <= 0) {
                        DRM_ERROR("space: %d wanted %d\n", ring->space, n);
@@ -250,9 +354,9 @@ static int i810_freelist_init(drm_device_t *dev)
 {
        drm_device_dma_t *dma = dev->dma;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-       u8 *hw_status = (u8 *)dev_priv->hw_status_page;
-       int i;
        int my_idx = 24;
+       u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
+       int i;
    
        if(dma->buf_count > 1019) {
                /* Not enough space in the status page for the freelist */
@@ -263,11 +367,14 @@ static int i810_freelist_init(drm_device_t *dev)
                drm_buf_t *buf = dma->buflist[ i ];
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
           
-               buf_priv->in_use = hw_status + my_idx;
-               DRM_DEBUG("buf_priv->in_use : %p\n", buf_priv->in_use);
-               *buf_priv->in_use = I810_BUF_FREE;
+               buf_priv->in_use = hw_status++;
                buf_priv->my_use_idx = my_idx;
                my_idx += 4;
+
+               *buf_priv->in_use = I810_BUF_FREE;
+
+               buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, 
+                                                      buf->total);
        }
        return 0;
 }
@@ -301,9 +408,11 @@ static int i810_dma_initialize(drm_device_t *dev,
        dev_priv->ring.Start = init->ring_start;
        dev_priv->ring.End = init->ring_end;
        dev_priv->ring.Size = init->ring_size;
+
        dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + 
                                                   init->ring_start, 
                                                   init->ring_size);
+
        dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
    
        if (dev_priv->ring.virtual_start == NULL) {
@@ -312,6 +421,17 @@ static int i810_dma_initialize(drm_device_t *dev,
                          " ring buffer\n");
                return -ENOMEM;
        }
+
+       dev_priv->w = init->w;
+       dev_priv->h = init->h;
+       dev_priv->pitch = init->pitch;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->depth_offset = init->depth_offset;
+
+       dev_priv->front_di1 = init->front_offset | init->pitch_bits;
+       dev_priv->back_di1 = init->back_offset | init->pitch_bits;
+       dev_priv->zi1 = init->depth_offset | init->pitch_bits;
+       
    
        /* Program Hardware Status Page */
        dev_priv->hw_status_page = i810_alloc_page(dev);
@@ -366,37 +486,270 @@ int i810_dma_init(struct inode *inode, struct file *filp,
        return retcode;
 }
 
-static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf,
-                                     int used )
+
+
+/* Most efficient way to verify state for the i810 is as it is
+ * emitted.  Non-conformant state is silently dropped.
+ *
+ * Use 'volatile' & local var tmp to force the emitted values to be
+ * identical to the verified ones.
+ */
+static void i810EmitContextVerified( drm_device_t *dev, 
+                                    volatile unsigned int *code ) 
+{      
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
+
+       OUT_RING( GFX_OP_COLOR_FACTOR );
+       OUT_RING( code[I810_CTXREG_CF1] );
+
+       OUT_RING( GFX_OP_STIPPLE );
+       OUT_RING( code[I810_CTXREG_ST1] );
+
+       for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
+               tmp = code[i];
+
+               if ((tmp & (7<<29)) == (3<<29) &&
+                   (tmp & (0x1f<<24)) < (0x1d<<24)) 
+               {
+                       OUT_RING( tmp ); 
+                       j++;
+               } 
+       }
+
+       if (j & 1) 
+               OUT_RING( 0 ); 
+
+       ADVANCE_LP_RING();
+}
+
+static void i810EmitTexVerified( drm_device_t *dev, 
+                                volatile unsigned int *code ) 
+{      
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
+
+       OUT_RING( GFX_OP_MAP_INFO );
+       OUT_RING( code[I810_TEXREG_MI1] );
+       OUT_RING( code[I810_TEXREG_MI2] );
+       OUT_RING( code[I810_TEXREG_MI3] );
+
+       for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
+               tmp = code[i];
+
+               if ((tmp & (7<<29)) == (3<<29) &&
+                   (tmp & (0x1f<<24)) < (0x1d<<24)) 
+               {
+                       OUT_RING( tmp ); 
+                       j++;
+               }
+       } 
+               
+       if (j & 1) 
+               OUT_RING( 0 ); 
+
+       ADVANCE_LP_RING();
+}
+
+
+/* Need to do some additional checking when setting the dest buffer.
+ */
+static void i810EmitDestVerified( drm_device_t *dev, 
+                                 volatile unsigned int *code ) 
+{      
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
+
+       tmp = code[I810_DESTREG_DI1];
+       if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
+               OUT_RING( CMD_OP_DESTBUFFER_INFO );
+               OUT_RING( tmp );
+       } else
+          DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
+                    tmp, dev_priv->front_di1, dev_priv->back_di1);
+
+       /* invarient:
+        */
+       OUT_RING( CMD_OP_Z_BUFFER_INFO );
+       OUT_RING( dev_priv->zi1 );
+
+       OUT_RING( GFX_OP_DESTBUFFER_VARS );
+       OUT_RING( code[I810_DESTREG_DV1] );
+
+       OUT_RING( GFX_OP_DRAWRECT_INFO );
+       OUT_RING( code[I810_DESTREG_DR1] );
+       OUT_RING( code[I810_DESTREG_DR2] );
+       OUT_RING( code[I810_DESTREG_DR3] );
+       OUT_RING( code[I810_DESTREG_DR4] );
+       OUT_RING( 0 );
+
+       ADVANCE_LP_RING();
+}
+
+
+
+static void i810EmitState( drm_device_t *dev )
 {
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-       unsigned long address = (unsigned long)buf->bus_address;
-       unsigned long start = address - dev->agp->base;
-       RING_LOCALS;
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int dirty = sarea_priv->dirty;
 
-       dev_priv->counter++;
-       DRM_DEBUG(  "dispatch counter : %ld\n", dev_priv->counter);
-       DRM_DEBUG(  "i810_dma_dispatch\n");
-       DRM_DEBUG(  "start : 0x%lx\n", start);
-       DRM_DEBUG(  "used : 0x%x\n", used);
-       DRM_DEBUG(  "start + used - 4 : 0x%lx\n", start + used - 4);
-       i810_kernel_lost_context(dev);
+       if (dirty & I810_UPLOAD_BUFFERS) {
+               i810EmitDestVerified( dev, sarea_priv->BufferState );
+               sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
+       }
 
-       BEGIN_LP_RING(10);
-       OUT_RING( CMD_OP_BATCH_BUFFER );
-       OUT_RING( start | BB1_PROTECTED );
-       OUT_RING( start + used - 4 );
-       OUT_RING( CMD_STORE_DWORD_IDX );
-       OUT_RING( 20 );
-       OUT_RING( dev_priv->counter );
-       OUT_RING( CMD_STORE_DWORD_IDX );
-       OUT_RING( buf_priv->my_use_idx );
-       OUT_RING( I810_BUF_FREE );   
-       OUT_RING( CMD_REPORT_HEAD );
-       ADVANCE_LP_RING();
+       if (dirty & I810_UPLOAD_CTX) {
+               i810EmitContextVerified( dev, sarea_priv->ContextState );
+               sarea_priv->dirty &= ~I810_UPLOAD_CTX;
+       }
+
+       if (dirty & I810_UPLOAD_TEX0) {
+               i810EmitTexVerified( dev, sarea_priv->TexState[0] );
+               sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
+       }
+
+       if (dirty & I810_UPLOAD_TEX1) {
+               i810EmitTexVerified( dev, sarea_priv->TexState[1] );
+               sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
+       }
+}
+
+
+
+/* need to verify 
+ */
+static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, 
+                                    unsigned int clear_color,
+                                    unsigned int clear_zval )
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = 2;
+       int i;
+       RING_LOCALS;
+
+       i810_kernel_lost_context(dev);
+
+       if (nbox > I810_NR_SAREA_CLIPRECTS)
+               nbox = I810_NR_SAREA_CLIPRECTS;
+
+       for (i = 0 ; i < nbox ; i++, pbox++) {
+               unsigned int x = pbox->x1;
+               unsigned int y = pbox->y1;
+               unsigned int width = (pbox->x2 - x) * cpp;
+               unsigned int height = pbox->y2 - y;
+               unsigned int start = y * pitch + x * cpp;
+
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w ||
+                   pbox->y2 > dev_priv->h)
+                       continue;
+
+               if ( flags & I810_FRONT ) {         
+                       DRM_DEBUG("clear front\n");
+                       BEGIN_LP_RING( 6 );         
+                       OUT_RING( BR00_BITBLT_CLIENT | 
+                                 BR00_OP_COLOR_BLT | 0x3 );
+                       OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+                       OUT_RING( (height << 16) | width );
+                       OUT_RING( start );
+                       OUT_RING( clear_color );
+                       OUT_RING( 0 );
+                       ADVANCE_LP_RING();
+               }
+
+               if ( flags & I810_BACK ) {
+                       DRM_DEBUG("clear back\n");
+                       BEGIN_LP_RING( 6 );         
+                       OUT_RING( BR00_BITBLT_CLIENT | 
+                                 BR00_OP_COLOR_BLT | 0x3 );
+                       OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+                       OUT_RING( (height << 16) | width );
+                       OUT_RING( dev_priv->back_offset + start );
+                       OUT_RING( clear_color );
+                       OUT_RING( 0 );
+                       ADVANCE_LP_RING();
+               }
+
+               if ( flags & I810_DEPTH ) {
+                       DRM_DEBUG("clear depth\n");
+                       BEGIN_LP_RING( 6 );         
+                       OUT_RING( BR00_BITBLT_CLIENT | 
+                                 BR00_OP_COLOR_BLT | 0x3 );
+                       OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
+                       OUT_RING( (height << 16) | width );
+                       OUT_RING( dev_priv->depth_offset + start );
+                       OUT_RING( clear_zval );
+                       OUT_RING( 0 );
+                       ADVANCE_LP_RING();
+               }
+       }
+}
+
+static void i810_dma_dispatch_swap( drm_device_t *dev )
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       drm_clip_rect_t *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = 2;
+       int ofs = dev_priv->back_offset;
+       int i;
+       RING_LOCALS;
+
+       DRM_DEBUG("swapbuffers\n");
+
+       i810_kernel_lost_context(dev);
+
+       if (nbox > I810_NR_SAREA_CLIPRECTS)
+               nbox = I810_NR_SAREA_CLIPRECTS;
+
+       for (i = 0 ; i < nbox; i++, pbox++) 
+       {
+               unsigned int w = pbox->x2 - pbox->x1;
+               unsigned int h = pbox->y2 - pbox->y1;
+               unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
+               unsigned int start = ofs + dst;
+
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w ||
+                   pbox->y2 > dev_priv->h)
+                       continue;
+               DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
+                         pbox[i].x1, pbox[i].y1,
+                         pbox[i].x2, pbox[i].y2);
+
+               BEGIN_LP_RING( 6 );
+               OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
+               OUT_RING( pitch | (0xCC << 16));
+               OUT_RING( (h << 16) | (w * cpp));
+               OUT_RING( dst );
+               OUT_RING( pitch );      
+               OUT_RING( start );
+               ADVANCE_LP_RING();
+       }
 }
 
+
 static void i810_dma_dispatch_vertex(drm_device_t *dev, 
                                     drm_buf_t *buf,
                                     int discard,
@@ -409,14 +762,29 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
        int nbox = sarea_priv->nbox;
        unsigned long address = (unsigned long)buf->bus_address;
        unsigned long start = address - dev->agp->base;     
-       int i = 0;
+       int i = 0, u;
        RING_LOCALS;
 
-   
+       i810_kernel_lost_context(dev);
+
        if (nbox > I810_NR_SAREA_CLIPRECTS) 
                nbox = I810_NR_SAREA_CLIPRECTS;
-   
-       DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", 
+
+       if (discard) {
+               u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, 
+                           I810_BUF_HARDWARE);
+               if(u != I810_BUF_CLIENT) {
+                       DRM_DEBUG("xxxx 2\n");
+               }
+       }
+
+       if (used > 4*1024) 
+               used = 0;
+
+       if (sarea_priv->dirty)
+          i810EmitState( dev );
+
+       DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", 
                  address, used, nbox);
 
        dev_priv->counter++;
@@ -425,8 +793,20 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
        DRM_DEBUG(  "start : %lx\n", start);
        DRM_DEBUG(  "used : %d\n", used);
        DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
-       i810_kernel_lost_context(dev);
 
+       if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
+               *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
+                                            sarea_priv->vertex_prim |
+                                            ((used/4)-2));
+               
+               if (used & 4) {
+                       *(u32 *)((u32)buf_priv->virtual + used) = 0;
+                       used += 4;
+               }
+
+               i810_unmap_buffer(buf);
+       }
+                  
        if (used) {
                do {
                        if (i < nbox) {
@@ -434,7 +814,7 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
                                OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | 
                                          SC_ENABLE );
                                OUT_RING( GFX_OP_SCISSOR_INFO );
-                               OUT_RING( box[i].x1 | (box[i].y1 << 16) );
+                               OUT_RING( box[i].x1 | (box[i].y1<<16) );
                                OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
                                ADVANCE_LP_RING();
                        }
@@ -479,7 +859,9 @@ static void i810_dma_service(int irq, void *device, struct pt_regs *regs)
        temp = temp & ~(0x6000);
        if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, 
                                   temp); /* Clear all interrupts */
-   
+       else
+          return;
        queue_task(&dev->tq, &tq_immediate);
        mark_bh(IMMEDIATE_BH);
 }
@@ -539,7 +921,7 @@ int i810_irq_install(drm_device_t *dev, int irq)
                                /* Install handler */
        if ((retcode = request_irq(dev->irq,
                                   i810_dma_service,
-                                  0,
+                                  SA_SHIRQ,
                                   dev->devname,
                                   dev))) {
                down(&dev->struct_sem);
@@ -560,6 +942,9 @@ int i810_irq_uninstall(drm_device_t *dev)
        int irq;
        u16 temp;
 
+
+/*     return 0; */
+
        down(&dev->struct_sem);
        irq      = dev->irq;
        dev->irq = 0;
@@ -618,10 +1003,15 @@ static inline void i810_dma_emit_flush(drm_device_t *dev)
        RING_LOCALS;
 
        i810_kernel_lost_context(dev);
+
        BEGIN_LP_RING(2);
        OUT_RING( CMD_REPORT_HEAD );
-       OUT_RING( GFX_OP_USER_INTERRUPT );
+       OUT_RING( GFX_OP_USER_INTERRUPT );
        ADVANCE_LP_RING();
+
+/*     i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
+/*             atomic_set(&dev_priv->flush_done, 1); */
+/*             wake_up_interruptible(&dev_priv->flush_queue); */
 }
 
 static inline void i810_dma_quiescent_emit(drm_device_t *dev)
@@ -630,13 +1020,17 @@ static inline void i810_dma_quiescent_emit(drm_device_t *dev)
        RING_LOCALS;
 
        i810_kernel_lost_context(dev);
-       BEGIN_LP_RING(4);
 
+       BEGIN_LP_RING(4);
        OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
        OUT_RING( CMD_REPORT_HEAD );
-       OUT_RING( GFX_OP_USER_INTERRUPT );
-       OUT_RING( 0 );
+       OUT_RING( 0 );
+       OUT_RING( GFX_OP_USER_INTERRUPT );
        ADVANCE_LP_RING();
+
+/*     i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
+/*             atomic_set(&dev_priv->flush_done, 1); */
+/*             wake_up_interruptible(&dev_priv->flush_queue); */
 }
 
 static void i810_dma_quiescent(drm_device_t *dev)
@@ -676,8 +1070,9 @@ static int i810_flush_queue(drm_device_t *dev)
 {
        DECLARE_WAITQUEUE(entry, current);
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+       drm_device_dma_t *dma = dev->dma;
        unsigned long end;
-       int ret = 0;      
+       int i, ret = 0;      
 
        if(dev_priv == NULL) {
                return 0;
@@ -702,7 +1097,21 @@ static int i810_flush_queue(drm_device_t *dev)
    
        current->state = TASK_RUNNING;
        remove_wait_queue(&dev_priv->flush_queue, &entry);
-   
+
+
+       for (i = 0; i < dma->buf_count; i++) {
+               drm_buf_t *buf = dma->buflist[ i ];
+               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+          
+               int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE, 
+                                  I810_BUF_FREE);
+
+               if (used == I810_BUF_HARDWARE)
+                       DRM_DEBUG("reclaimed from HARDWARE\n");
+               if (used == I810_BUF_CLIENT)
+                       DRM_DEBUG("still on client HARDWARE\n");
+       }
+
        return ret;
 }
 
@@ -713,20 +1122,23 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
        int              i;
 
        if (!dma) return;
-       if(dev->dev_private == NULL) return;
-       if(dma->buflist == NULL) return;
+       if (!dev->dev_private) return;
+       if (!dma->buflist) return;
+
         i810_flush_queue(dev);
 
        for (i = 0; i < dma->buf_count; i++) {
                drm_buf_t *buf = dma->buflist[ i ];
                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
           
-               /* Only buffers that need to get reclaimed ever 
-                * get set to free 
-                */
                if (buf->pid == pid && buf_priv) {
-                       cmpxchg(buf_priv->in_use, 
-                               I810_BUF_USED, I810_BUF_FREE);
+                       int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, 
+                                          I810_BUF_FREE);
+
+                       if (used == I810_BUF_CLIENT)
+                               DRM_DEBUG("reclaimed from client\n");
+                       if(buf_priv->currently_mapped == I810_BUF_MAPPED)
+                               buf_priv->currently_mapped = I810_BUF_UNMAPPED;
                }
        }
 }
@@ -760,19 +1172,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
         */
 
        if (!ret) {
-#if 0
-               if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
-                   != lock.context) {
-                       long j = jiffies - dev->lock.lock_time;
-
-                       if (j > 0 && j <= DRM_LOCK_SLICE) {
-                               /* Can't take lock if we just had it and
-                                  there is contention. */
-                               current->state = TASK_INTERRUPTIBLE;
-                               schedule_timeout(j);
-                       }
-               }
-#endif
                add_wait_queue(&dev->lock.lock_queue, &entry);
                for (;;) {
                        if (!dev->lock.hw_lock) {
@@ -829,90 +1228,80 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp,
        return 0;
 }
 
-static int i810DmaGeneral(drm_device_t *dev, drm_i810_general_t *args)
-{
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf = dma->buflist[ args->idx ];
-       
-       if (!args->used) {
-               i810_freelist_put(dev, buf);
-       } else {  
-               i810_dma_dispatch_general( dev, buf, args->used );
-               atomic_add(args->used, &dma->total_bytes);
-               atomic_inc(&dma->total_dmas);
-       }
-       return 0; 
-}
-
-static int i810DmaVertex(drm_device_t *dev, drm_i810_vertex_t *args)
-{
-       drm_device_dma_t *dma = dev->dma;
-       drm_buf_t *buf = dma->buflist[ args->idx ];
-       i810_dma_dispatch_vertex( dev, buf, args->discard, args->used );
-       atomic_add(args->used, &dma->total_bytes);
-       atomic_inc(&dma->total_dmas);
-       return 0;
-}
 
-int i810_dma_general(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg)
+int i810_dma_vertex(struct inode *inode, struct file *filp,
+              unsigned int cmd, unsigned long arg)
 {
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
-       drm_i810_general_t general;
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
+       drm_device_dma_t *dma = dev->dma;
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
                                        dev_priv->sarea_priv; 
+       drm_i810_vertex_t vertex;
 
-       int retcode = 0;
-       
-       copy_from_user_ret(&general, (drm_i810_general_t *)arg, sizeof(general),
+       copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex),
                           -EFAULT);
 
-       DRM_DEBUG("i810 dma general idx %d used %d\n",
-                 general.idx, general.used);
-   
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-               DRM_ERROR("i810_dma_general called without lock held\n");
+               DRM_ERROR("i810_dma_vertex called without lock held\n");
                return -EINVAL;
        }
 
-       retcode = i810DmaGeneral(dev, &general);
+       DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
+                 vertex.idx, vertex.used, vertex.discard);
+
+       i810_dma_dispatch_vertex( dev, 
+                                 dma->buflist[ vertex.idx ], 
+                                 vertex.discard, vertex.used );
+
+       atomic_add(vertex.used, &dma->total_bytes);
+       atomic_inc(&dma->total_dmas);
        sarea_priv->last_enqueue = dev_priv->counter-1;
        sarea_priv->last_dispatch = (int) hw_status[5];
    
-       return retcode;
+       return 0;
 }
 
-int i810_dma_vertex(struct inode *inode, struct file *filp,
-              unsigned int cmd, unsigned long arg)
+
+
+int i810_clear_bufs(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_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
-       u32 *hw_status = (u32 *)dev_priv->hw_status_page;
-       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
-                                       dev_priv->sarea_priv; 
-       drm_i810_vertex_t vertex;
-       int retcode = 0;
+       drm_i810_clear_t clear;
 
-       copy_from_user_ret(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex),
+       copy_from_user_ret(&clear, (drm_i810_clear_t *)arg, sizeof(clear), 
                           -EFAULT);
+   
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-               DRM_ERROR("i810_dma_vertex called without lock held\n");
+               DRM_ERROR("i810_clear_bufs called without lock held\n");
                return -EINVAL;
        }
 
-       DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
-                 vertex.idx, vertex.used, vertex.discard);
+       i810_dma_dispatch_clear( dev, clear.flags, 
+                                clear.clear_color, 
+                                clear.clear_depth );
+       return 0;
+}
 
-       retcode = i810DmaVertex(dev, &vertex);
-       sarea_priv->last_enqueue = dev_priv->counter-1;
-       sarea_priv->last_dispatch = (int) hw_status[5];
+int i810_swap_bufs(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;
    
-       return retcode;
+       DRM_DEBUG("i810_swap_bufs\n");
 
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("i810_swap_buf called without lock held\n");
+               return -EINVAL;
+       }
+
+       i810_dma_dispatch_swap( dev );
+       return 0;
 }
 
 int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
@@ -929,53 +1318,32 @@ int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
        return 0;
 }
 
-int i810_dma(struct inode *inode, struct file *filp, unsigned int cmd,
-           unsigned long arg)
+int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
+               unsigned long arg)
 {
        drm_file_t        *priv     = filp->private_data;
        drm_device_t      *dev      = priv->dev;
-       drm_device_dma_t  *dma      = dev->dma;
        int               retcode   = 0;
-       drm_dma_t         d;
+       drm_i810_dma_t    d;
        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
                                        dev_priv->sarea_priv; 
 
-
-       copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
-       DRM_DEBUG("%d %d: %d send, %d req\n",
-                 current->pid, d.context, d.send_count, d.request_count);
+       DRM_DEBUG("getbuf\n");
+       copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT);
    
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
                DRM_ERROR("i810_dma called without lock held\n");
                return -EINVAL;
        }
-
-       /* Please don't send us buffers.
-        */
-       if (d.send_count != 0) {
-               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         current->pid, d.send_count);
-               return -EINVAL;
-       }
        
-       /* We'll send you buffers.
-        */
-       if (d.request_count < 0 || d.request_count > dma->buf_count) {
-               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         current->pid, d.request_count, dma->buf_count);
-               return -EINVAL;
-       }
-       
-       d.granted_count = 0;
+       d.granted = 0;
 
-       if (!retcode && d.request_count) {
-               retcode = i810_dma_get_buffers(dev, &d);
-       }
+       retcode = i810_dma_get_buffer(dev, &d, filp);
 
-       DRM_DEBUG("i810_dma: %d returning, granted = %d\n",
-                 current->pid, d.granted_count);
+       DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
+                 current->pid, retcode, d.granted);
 
        copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);   
        sarea_priv->last_dispatch = (int) hw_status[5];
index 0754874..4c8e09f 100644 (file)
  * if you change them, you must change the defines in the Xserver.
  */
 
-/* Might one day want to support the client-side ringbuffer code again.
- */
 #ifndef _I810_DEFINES_
 #define _I810_DEFINES_
 
-#define I810_USE_BATCH                 1
 #define I810_DMA_BUF_ORDER             12
 #define I810_DMA_BUF_SZ                (1<<I810_DMA_BUF_ORDER)
 #define I810_DMA_BUF_NR                256
-#define I810_NR_SAREA_CLIPRECTS        2
+#define I810_NR_SAREA_CLIPRECTS        8
 
 /* Each region is a minimum of 64k, and there are at most 64 of them.
  */
-
 #define I810_NR_TEX_REGIONS 64
 #define I810_LOG_MIN_TEX_REGION_SIZE 16
 #endif
 
+#define I810_UPLOAD_TEX0IMAGE  0x1 /* handled clientside */
+#define I810_UPLOAD_TEX1IMAGE  0x2 /* handled clientside */
+#define I810_UPLOAD_CTX        0x4
+#define I810_UPLOAD_BUFFERS    0x8
+#define I810_UPLOAD_TEX0       0x10
+#define I810_UPLOAD_TEX1       0x20
+#define I810_UPLOAD_CLIPRECTS  0x40
+
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer.  These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+/* Destbuffer state 
+ *    - backbuffer linear offset and pitch -- invarient in the current dri
+ *    - zbuffer linear offset and pitch -- also invarient
+ *    - drawing origin in back and depth buffers.
+ *
+ * Keep the depth/back buffer state here to acommodate private buffers
+ * in the future.
+ */
+#define I810_DESTREG_DI0  0    /* CMD_OP_DESTBUFFER_INFO (2 dwords) */
+#define I810_DESTREG_DI1  1
+#define I810_DESTREG_DV0  2    /* GFX_OP_DESTBUFFER_VARS (2 dwords) */
+#define I810_DESTREG_DV1  3
+#define I810_DESTREG_DR0  4    /* GFX_OP_DRAWRECT_INFO (4 dwords) */
+#define I810_DESTREG_DR1  5
+#define I810_DESTREG_DR2  6
+#define I810_DESTREG_DR3  7
+#define I810_DESTREG_DR4  8
+#define I810_DEST_SETUP_SIZE 10
+
+/* Context state
+ */
+#define I810_CTXREG_CF0   0    /* GFX_OP_COLOR_FACTOR */
+#define I810_CTXREG_CF1   1    
+#define I810_CTXREG_ST0   2     /* GFX_OP_STIPPLE */
+#define I810_CTXREG_ST1   3
+#define I810_CTXREG_VF    4    /* GFX_OP_VERTEX_FMT */
+#define I810_CTXREG_MT    5    /* GFX_OP_MAP_TEXELS */
+#define I810_CTXREG_MC0   6    /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
+#define I810_CTXREG_MC1   7     /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
+#define I810_CTXREG_MC2   8    /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
+#define I810_CTXREG_MA0   9    /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
+#define I810_CTXREG_MA1   10   /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
+#define I810_CTXREG_MA2   11   /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */
+#define I810_CTXREG_SDM   12   /* GFX_OP_SRC_DEST_MONO */
+#define I810_CTXREG_FOG   13   /* GFX_OP_FOG_COLOR */
+#define I810_CTXREG_B1    14   /* GFX_OP_BOOL_1 */
+#define I810_CTXREG_B2    15   /* GFX_OP_BOOL_2 */
+#define I810_CTXREG_LCS   16   /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */
+#define I810_CTXREG_PV    17   /* GFX_OP_PV_RULE -- Invarient! */
+#define I810_CTXREG_ZA    18   /* GFX_OP_ZBIAS_ALPHAFUNC */
+#define I810_CTXREG_AA    19   /* GFX_OP_ANTIALIAS */
+#define I810_CTX_SETUP_SIZE 20 
+
+/* Texture state (per tex unit)
+ */
+#define I810_TEXREG_MI0  0     /* GFX_OP_MAP_INFO (4 dwords) */
+#define I810_TEXREG_MI1  1     
+#define I810_TEXREG_MI2  2     
+#define I810_TEXREG_MI3  3     
+#define I810_TEXREG_MF   4     /* GFX_OP_MAP_FILTER */
+#define I810_TEXREG_MLC  5     /* GFX_OP_MAP_LOD_CTL */
+#define I810_TEXREG_MLL  6     /* GFX_OP_MAP_LOD_LIMITS */
+#define I810_TEXREG_MCS  7     /* GFX_OP_MAP_COORD_SETS ??? */
+#define I810_TEX_SETUP_SIZE 8
+
+#define I810_FRONT   0x1
+#define I810_BACK    0x2
+#define I810_DEPTH   0x4
+
+
 typedef struct _drm_i810_init {
-       enum {
-               I810_INIT_DMA = 0x01,
-               I810_CLEANUP_DMA = 0x02
+       enum {
+               I810_INIT_DMA = 0x01,
+               I810_CLEANUP_DMA = 0x02
        } func;
-       int ring_map_idx;
-       int buffer_map_idx;
+       int ring_map_idx;
+       int buffer_map_idx;
        int sarea_priv_offset;
-       unsigned long ring_start;
-       unsigned long ring_end;
-       unsigned long ring_size;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits; 
 } drm_i810_init_t;
 
 /* Warning: If you change the SAREA structure you must change the Xserver
@@ -46,6 +123,11 @@ typedef struct _drm_i810_tex_region {
 } drm_i810_tex_region_t;
 
 typedef struct _drm_i810_sarea {
+       unsigned int ContextState[I810_CTX_SETUP_SIZE];
+       unsigned int BufferState[I810_DEST_SETUP_SIZE];
+       unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+       unsigned int dirty;
+
        unsigned int nbox;
        drm_clip_rect_t boxes[I810_NR_SAREA_CLIPRECTS];
 
@@ -72,12 +154,18 @@ typedef struct _drm_i810_sarea {
        int last_dispatch;      /* age of the most recently dispatched buffer */
        int last_quiescent;     /*  */
        int ctxOwner;           /* last context to upload state */
+
+       int vertex_prim;
+
 } drm_i810_sarea_t;
 
-typedef struct _drm_i810_general {
-       int idx;
-       int used;
-} drm_i810_general_t;
+typedef struct _drm_i810_clear {
+       int clear_color;
+       int clear_depth;
+       int flags;
+} drm_i810_clear_t;
+
+
 
 /* These may be placeholders if we have more cliprects than
  * I810_NR_SAREA_CLIPRECTS.  In that case, the client sets discard to
@@ -90,4 +178,11 @@ typedef struct _drm_i810_vertex {
        int discard;            /* client is finished with the buffer? */
 } drm_i810_vertex_t;
 
+typedef struct drm_i810_dma {
+       void *virtual;
+       int request_idx;
+       int request_size;
+       int granted;
+} drm_i810_dma_t;
+
 #endif /* _I810_DRM_H_ */
index f1c8325..75b402d 100644 (file)
@@ -80,7 +80,6 @@ static drm_ioctl_desc_t             i810_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]    = { i810_addbufs,   1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]   = { i810_markbufs,  1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]   = { i810_infobufs,  1, 0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]    = { i810_mapbufs,   1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]   = { i810_freebufs,  1, 0 },
 
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]     = { i810_addctx,    1, 1 },
@@ -93,8 +92,6 @@ static drm_ioctl_desc_t             i810_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)]    = { drm_adddraw,    1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)]     = { drm_rmdraw,     1, 1 },
 
-       [DRM_IOCTL_NR(DRM_IOCTL_DMA)]         = { i810_dma,       1, 0 },
-
        [DRM_IOCTL_NR(DRM_IOCTL_LOCK)]        = { i810_lock,      1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]      = { i810_unlock,    1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_FINISH)]      = { drm_finish,     1, 0 },
@@ -107,11 +104,14 @@ static drm_ioctl_desc_t         i810_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)]    = { drm_agp_free,    1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)]    = { drm_agp_bind,    1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]  = { drm_agp_unbind,  1, 1 },
+
        [DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)]   = { i810_dma_init,   1, 1 },
        [DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 },
-       [DRM_IOCTL_NR(DRM_IOCTL_I810_DMA)]    = { i810_dma_general,1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_CLEAR)]  = { i810_clear_bufs, 1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)]  = { i810_flush_ioctl,1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage,     1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf,     1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_I810_SWAP)]   = { i810_swap_bufs,  1, 0 },
 };
 
 #define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls)
index 1badd36..334cacb 100644 (file)
 #ifndef _I810_DRV_H_
 #define _I810_DRV_H_
 
+typedef struct drm_i810_buf_priv {
+       u32 *in_use;
+       int my_use_idx;
+       int currently_mapped;
+       void *virtual;
+       void *kernel_virtual;
+       int map_count;
+       struct vm_area_struct *vma;
+} drm_i810_buf_priv_t;
+
 typedef struct _drm_i810_ring_buffer{
        int tail_mask;
        unsigned long Start;
@@ -55,6 +65,15 @@ typedef struct drm_i810_private {
 
        atomic_t flush_done;
        wait_queue_head_t flush_queue;  /* Processes waiting until flush    */
+       drm_buf_t *mmap_buffer;
+
+       
+       u32 front_di1, back_di1, zi1;
+       
+       int back_offset;
+       int depth_offset;
+       int w, h;
+       int pitch;
 } drm_i810_private_t;
 
                                /* i810_drv.c */
@@ -71,8 +90,8 @@ extern int  i810_unlock(struct inode *inode, struct file *filp,
 
                                /* i810_dma.c */
 extern int  i810_dma_schedule(drm_device_t *dev, int locked);
-extern int  i810_dma(struct inode *inode, struct file *filp,
-                     unsigned int cmd, unsigned long arg);
+extern int  i810_getbuf(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
 extern int  i810_irq_install(drm_device_t *dev, int irq);
 extern int  i810_irq_uninstall(drm_device_t *dev);
 extern int  i810_control(struct inode *inode, struct file *filp,
@@ -86,6 +105,7 @@ extern int  i810_flush_ioctl(struct inode *inode, struct file *filp,
 extern void i810_reclaim_buffers(drm_device_t *dev, pid_t pid);
 extern int  i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
                        unsigned long arg);
+extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
 
 
                                /* i810_bufs.c */
@@ -97,8 +117,6 @@ extern int  i810_markbufs(struct inode *inode, struct file *filp,
                         unsigned int cmd, unsigned long arg);
 extern int  i810_freebufs(struct inode *inode, struct file *filp,
                         unsigned int cmd, unsigned long arg);
-extern int  i810_mapbufs(struct inode *inode, struct file *filp,
-                       unsigned int cmd, unsigned long arg);
 extern int  i810_addmap(struct inode *inode, struct file *filp,
                       unsigned int cmd, unsigned long arg);
 
@@ -121,32 +139,17 @@ extern int  i810_rmctx(struct inode *inode, struct file *filp,
 extern int  i810_context_switch(drm_device_t *dev, int old, int new);
 extern int  i810_context_switch_complete(drm_device_t *dev, int new);
 
-
-
-
-/* Copy the outstanding cliprects for every I810_DMA_VERTEX buffer.
- * This can be fixed by emitting directly to the ringbuffer in the
- * 'vertex_dma' ioctl.  
-*/
-typedef struct {
-       u32 *in_use;
-       int my_use_idx;
-} drm_i810_buf_priv_t;
-
-
-#define I810_DMA_GENERAL 0
-#define I810_DMA_VERTEX  1
-#define I810_DMA_DISCARD 2     /* not used */
-
 #define I810_VERBOSE 0
 
 
 int i810_dma_vertex(struct inode *inode, struct file *filp,
                    unsigned int cmd, unsigned long arg);
 
-int i810_dma_general(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg);
+int i810_swap_bufs(struct inode *inode, struct file *filp,
+                  unsigned int cmd, unsigned long arg);
 
+int i810_clear_bufs(struct inode *inode, struct file *filp,
+                   unsigned int cmd, unsigned long arg);
 
 #define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
@@ -200,5 +203,22 @@ int i810_dma_general(struct inode *inode, struct file *filp,
 #define SCI_YMAX_MASK      (0xffff<<16)
 #define SCI_XMAX_MASK      (0xffff<<0)
 
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x2)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+#define GFX_OP_PRIMITIVE         ((0x3<<29)|(0x1f<<24))
+
+#define CMD_OP_Z_BUFFER_INFO     ((0x0<<29)|(0x16<<23))
+#define CMD_OP_DESTBUFFER_INFO   ((0x0<<29)|(0x15<<23))
+
+#define BR00_BITBLT_CLIENT   0x40000000
+#define BR00_OP_COLOR_BLT    0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR13_SOLID_PATTERN   0x80000000
+
+
+
 #endif
 
index 371706f..fe6a7b5 100644 (file)
@@ -53,6 +53,7 @@ static unsigned long mga_alloc_page(drm_device_t *dev)
 {
        unsigned long address;
    
+       DRM_DEBUG("%s\n", __FUNCTION__);
        address = __get_free_page(GFP_KERNEL);
        if(address == 0UL) {
                return 0;
@@ -65,6 +66,8 @@ static unsigned long mga_alloc_page(drm_device_t *dev)
 
 static void mga_free_page(drm_device_t *dev, unsigned long page)
 {
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        if(page == 0UL) {
                return;
        }
@@ -80,9 +83,11 @@ static void mga_delay(void)
        return;
 }
 
-static void mga_flush_write_combine(void)
+void mga_flush_write_combine(void)
 {
        int xchangeDummy;
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        __asm__ volatile(" push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy));
        __asm__ volatile(" push %%eax ; push %%ebx ; push %%ecx ; push %%edx ;"
                         " movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;"
@@ -94,18 +99,6 @@ static void mga_flush_write_combine(void)
 #define MGA_BUF_USED   0xffffffff
 #define MGA_BUF_FREE   0
 
-static void mga_freelist_debug(drm_mga_freelist_t *item)
-{
-       if(item->buf != NULL) {
-               DRM_DEBUG("buf index : %d\n", item->buf->idx);
-       } else {
-               DRM_DEBUG("Freelist head\n");
-       }
-       DRM_DEBUG("item->age : %x\n", item->age);
-       DRM_DEBUG("item->next : %p\n", item->next);
-       DRM_DEBUG("item->prev : %p\n", item->prev);
-}
-
 static int mga_freelist_init(drm_device_t *dev)
 {
        drm_device_dma_t *dma = dev->dma;
@@ -114,7 +107,9 @@ static int mga_freelist_init(drm_device_t *dev)
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
        drm_mga_freelist_t *item;
        int i;
-   
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
        if(dev_priv->head == NULL) return -ENOMEM;
        memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
@@ -136,19 +131,10 @@ static int mga_freelist_init(drm_device_t *dev)
                item->buf = buf;
                buf_priv->my_freelist = item;
                buf_priv->discard = 0;
+               buf_priv->dispatched = 0;
                dev_priv->head->next = item;
        }
    
-       item = dev_priv->head;
-       while(item) {
-               mga_freelist_debug(item);
-               item = item->next;
-       }
-       DRM_DEBUG("Head\n");
-       mga_freelist_debug(dev_priv->head);
-       DRM_DEBUG("Tail\n");
-       mga_freelist_debug(dev_priv->tail);
-   
        return 0;
 }
 
@@ -158,6 +144,8 @@ static void mga_freelist_cleanup(drm_device_t *dev)
        drm_mga_freelist_t *item;
        drm_mga_freelist_t *prev;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        item = dev_priv->head;
        while(item) {
                prev = item;
@@ -174,14 +162,14 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
        drm_device_dma_t  *dma      = dev->dma;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       __volatile__ unsigned int *status =
-               (__volatile__ unsigned int *)dev_priv->status_page;
        unsigned long end;
        int i;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
        end = jiffies + (HZ*3);
        while(1) {
-               if(!test_and_set_bit(0, &dev_priv->dispatch_lock)) {
+               if(!test_and_set_bit(MGA_IN_DISPATCH, 
+                                    &dev_priv->dispatch_status)) {
                        break;
                }
                if((signed)(end - jiffies) <= 0) {
@@ -205,51 +193,25 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
                }
                for (i = 0 ; i < 2000 ; i++) mga_delay();         
        }
-       DRM_DEBUG("status[1] : %x last_sync_tag : %x\n", status[1],
-                 dev_priv->last_sync_tag);
        sarea_priv->dirty |= MGA_DMA_FLUSH;
 
 out_status:
-       clear_bit(0, &dev_priv->dispatch_lock);
+       clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
 out_nolock:
 }
 
-#define FREELIST_INITIAL (MGA_DMA_BUF_NR * 2)
-#define FREELIST_COMPARE(age) ((age >> 2))
-
-unsigned int mga_create_sync_tag(drm_device_t *dev)
+static void mga_reset_freelist(drm_device_t *dev)
 {
-       drm_mga_private_t *dev_priv = 
-               (drm_mga_private_t *) dev->dev_private;
-       unsigned int temp;
-       drm_buf_t *buf;
+       drm_device_dma_t  *dma      = dev->dma;
+       drm_buf_t *buf;
        drm_mga_buf_priv_t *buf_priv;
-       drm_device_dma_t *dma = dev->dma;
-       int i;
-   
-       dev_priv->sync_tag++;
-   
-       if(dev_priv->sync_tag < FREELIST_INITIAL) {
-               dev_priv->sync_tag = FREELIST_INITIAL;
-       }
-       if(dev_priv->sync_tag > 0x3fffffff) {
-               mga_flush_queue(dev);
-               mga_dma_quiescent(dev);
-           
-               for (i = 0; i < dma->buf_count; i++) {
-                       buf = dma->buflist[ i ];
-                       buf_priv = buf->dev_private;
-                       buf_priv->my_freelist->age = MGA_BUF_FREE;
-               }
-               
-               dev_priv->sync_tag = FREELIST_INITIAL;
-       }
-       temp = dev_priv->sync_tag << 2;
-
-       dev_priv->sarea_priv->last_enqueue = temp;
+       int i;
 
-       DRM_DEBUG("sync_tag : %x\n", temp);
-       return temp;
+       for (i = 0; i < dma->buf_count; i++) {
+               buf = dma->buflist[ i ];
+               buf_priv = buf->dev_private;
+               buf_priv->my_freelist->age = MGA_BUF_FREE;
+       }
 }
 
 /* Least recently used :
@@ -258,23 +220,52 @@ unsigned int mga_create_sync_tag(drm_device_t *dev)
 
 drm_buf_t *mga_freelist_get(drm_device_t *dev)
 {
+       DECLARE_WAITQUEUE(entry, current);
        drm_mga_private_t *dev_priv = 
                (drm_mga_private_t *) dev->dev_private;
-       __volatile__ unsigned int *status = 
-               (__volatile__ unsigned int *)dev_priv->status_page;
        drm_mga_freelist_t *prev;
        drm_mga_freelist_t *next;
+       static int failed = 0;
+
+       DRM_DEBUG("%s : tail->age : %d last_prim_age : %d\n", __FUNCTION__,
+              dev_priv->tail->age, dev_priv->last_prim_age);
    
-       if((dev_priv->tail->age >> 2) <= FREELIST_COMPARE(status[1])) {
+       if(failed >= 1000 && dev_priv->tail->age >= dev_priv->last_prim_age) {
+               DRM_DEBUG("I'm waiting on the freelist!!! %d\n", 
+                      dev_priv->last_prim_age);
+               set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
+               current->state = TASK_INTERRUPTIBLE;
+               add_wait_queue(&dev_priv->buf_queue, &entry);
+               for (;;) {
+                       mga_dma_schedule(dev, 0);
+                       if(!test_bit(MGA_IN_GETBUF, 
+                                    &dev_priv->dispatch_status)) 
+                               break;
+                       atomic_inc(&dev->total_sleeps);
+                       schedule();
+                       if (signal_pending(current)) {
+                               clear_bit(MGA_IN_GETBUF,
+                                         &dev_priv->dispatch_status);
+                               goto failed_getbuf;
+                       }
+               }
+               current->state = TASK_RUNNING;
+               remove_wait_queue(&dev_priv->buf_queue, &entry);
+       }
+   
+       if(dev_priv->tail->age < dev_priv->last_prim_age) {
                prev = dev_priv->tail->prev;
                next = dev_priv->tail;
                prev->next = NULL;
                next->prev = next->next = NULL;
                dev_priv->tail = prev;
                next->age = MGA_BUF_USED;
+               failed = 0;
                return next->buf;
-       } 
+       }
 
+failed_getbuf:
+       failed++;
        return NULL;
 }
 
@@ -287,6 +278,8 @@ int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf)
        drm_mga_freelist_t *head;
        drm_mga_freelist_t *next;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        if(buf_priv->my_freelist->age == MGA_BUF_USED) {
                /* Discarded buffer, put it on the tail */
                next = buf_priv->my_freelist;
@@ -313,32 +306,6 @@ int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf)
        return 0;
 }
 
-static void mga_print_all_primary(drm_device_t *dev)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_prim_buf_t *prim;
-       int i;
-
-       DRM_DEBUG("Full list of primarys\n");
-       for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) {
-               prim = dev_priv->prim_bufs[i];
-               DRM_DEBUG("index : %d num_dwords : %d "
-                         "max_dwords : %d phy_head : %x\n",
-                         prim->idx, prim->num_dwords, 
-                         prim->max_dwords, prim->phys_head);
-               DRM_DEBUG("sec_used : %d swap_pending : %x "
-                         "in_use : %x force_fire : %d\n",
-                         prim->sec_used, prim->swap_pending, 
-                         prim->in_use, atomic_read(&prim->force_fire));
-               DRM_DEBUG("needs_overflow : %d\n", 
-                         atomic_read(&prim->needs_overflow));
-       }
-   
-       DRM_DEBUG("current_idx : %d, next_idx : %d, last_idx : %d\n",
-                 dev_priv->next_prim->idx, dev_priv->last_prim->idx,
-                 dev_priv->current_prim->idx);
-}
-
 static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init)
 {
        drm_mga_private_t *dev_priv = dev->dev_private;
@@ -346,10 +313,9 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init)
        int i, temp, size_of_buf;
        int offset = init->reserved_map_agpstart;
 
-       DRM_DEBUG("mga_init_primary_bufs\n");
+       DRM_DEBUG("%s\n", __FUNCTION__);
        dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) / 
                                  PAGE_SIZE) * PAGE_SIZE;
-       DRM_DEBUG("primary_size\n");
        size_of_buf = dev_priv->primary_size / MGA_NUM_PRIM_BUFS;
        dev_priv->warp_ucode_size = init->warp_ucode_size;
        dev_priv->prim_bufs = drm_alloc(sizeof(drm_mga_prim_buf_t *) * 
@@ -359,18 +325,12 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init)
                DRM_ERROR("Unable to allocate memory for prim_buf\n");
                return -ENOMEM;
        }
-       DRM_DEBUG("memset\n");
        memset(dev_priv->prim_bufs, 
               0, sizeof(drm_mga_prim_buf_t *) * (MGA_NUM_PRIM_BUFS + 1));
    
        temp = init->warp_ucode_size + dev_priv->primary_size;
        temp = ((temp + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
           
-       DRM_DEBUG("temp : %x\n", temp);
-       DRM_DEBUG("dev->agp->base: %lx\n", dev->agp->base);
-       DRM_DEBUG("init->reserved_map_agpstart: %x\n", 
-                 init->reserved_map_agpstart);
-       DRM_DEBUG("ioremap\n");
        dev_priv->ioremap = drm_ioremap(dev->agp->base + offset, 
                                        temp);
        if(dev_priv->ioremap == NULL) {
@@ -380,11 +340,9 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init)
        init_waitqueue_head(&dev_priv->wait_queue);
    
        for(i = 0; i < MGA_NUM_PRIM_BUFS; i++) {
-               DRM_DEBUG("For loop\n");
                prim_buffer = drm_alloc(sizeof(drm_mga_prim_buf_t), 
                                        DRM_MEM_DRIVER);
                if(prim_buffer == NULL) return -ENOMEM;
-               DRM_DEBUG("memset\n");
                memset(prim_buffer, 0, sizeof(drm_mga_prim_buf_t));
                prim_buffer->phys_head = offset + dev->agp->base;
                prim_buffer->current_dma_ptr = 
@@ -397,17 +355,18 @@ static int mga_init_primary_bufs(drm_device_t *dev, drm_mga_init_t *init)
                prim_buffer->max_dwords -= 5; /* Leave room for the softrap */
                prim_buffer->sec_used = 0;
                prim_buffer->idx = i;
+               prim_buffer->prim_age = i + 1;
                offset = offset + size_of_buf;
                dev_priv->prim_bufs[i] = prim_buffer;
-               DRM_DEBUG("Looping\n");
        }
        dev_priv->current_prim_idx = 0;
         dev_priv->next_prim = 
                dev_priv->last_prim = 
                dev_priv->current_prim =
                dev_priv->prim_bufs[0];
-       set_bit(0, &dev_priv->current_prim->in_use);
-       DRM_DEBUG("init done\n");
+       dev_priv->next_prim_age = 2;    
+       dev_priv->last_prim_age = 1;
+       set_bit(MGA_BUF_IN_USE, &dev_priv->current_prim->buffer_status);
        return 0;
 }
 
@@ -421,9 +380,8 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
        int i;
        int next_idx;
                PRIMLOCALS;
-   
-       DRM_DEBUG("mga_fire_primary\n");
-       dev_priv->last_sync_tag = mga_create_sync_tag(dev); 
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
        dev_priv->last_prim = prim;
    
        /* We never check for overflow, b/c there is always room */
@@ -434,7 +392,7 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
        }
        PRIMOUTREG( MGAREG_DMAPAD, 0);
        PRIMOUTREG( MGAREG_DMAPAD, 0);
-               PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
+               PRIMOUTREG( MGAREG_DMAPAD, 0);
        PRIMOUTREG( MGAREG_SOFTRAP, 0);
        PRIMFINISH(prim);
 
@@ -469,13 +427,13 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
                        for (i = 0 ; i < 4096 ; i++) mga_delay();
                }
        }
-       
+
        mga_flush_write_combine();
        atomic_inc(&dev_priv->pending_bufs);
-       atomic_inc(&dma->total_lost);
                MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
        MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp);
        prim->num_dwords = 0;
+       sarea_priv->last_enqueue = prim->prim_age;
     
        next_idx = prim->idx + 1;
        if(next_idx >= MGA_NUM_PRIM_BUFS) 
@@ -487,11 +445,10 @@ void mga_fire_primary(drm_device_t *dev, drm_mga_prim_buf_t *prim)
  out_prim_wait:
        prim->num_dwords = 0;
        prim->sec_used = 0;
-       clear_bit(0, &prim->in_use);
+       clear_bit(MGA_BUF_IN_USE, &prim->buffer_status);
        wake_up_interruptible(&dev_priv->wait_queue);
-       clear_bit(0, &prim->swap_pending);
-       clear_bit(0, &dev_priv->dispatch_lock);
-       atomic_dec(&dev_priv->pending_bufs);
+       clear_bit(MGA_BUF_SWAP_PENDING, &prim->buffer_status);
+       clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
 }
 
 int mga_advance_primary(drm_device_t *dev)
@@ -506,27 +463,28 @@ int mga_advance_primary(drm_device_t *dev)
        /* This needs to reset the primary buffer if available,
         * we should collect stats on how many times it bites
         * it's tail */
+       DRM_DEBUG("%s\n", __FUNCTION__);
    
        next_prim_idx = dev_priv->current_prim_idx + 1;
        if(next_prim_idx >= MGA_NUM_PRIM_BUFS)
                next_prim_idx = 0;
        prim_buffer = dev_priv->prim_bufs[next_prim_idx];
-       atomic_set(&dev_priv->in_wait, 1);
+       set_bit(MGA_IN_WAIT, &dev_priv->dispatch_status);
    
        /* In use is cleared in interrupt handler */
    
-       if(test_and_set_bit(0, &prim_buffer->in_use)) {
+       if(test_and_set_bit(MGA_BUF_IN_USE, &prim_buffer->buffer_status)) {
                add_wait_queue(&dev_priv->wait_queue, &entry);
+               current->state = TASK_INTERRUPTIBLE;
+
                for (;;) {
-                       current->state = TASK_INTERRUPTIBLE;
                        mga_dma_schedule(dev, 0);
-                       if(!test_and_set_bit(0, &prim_buffer->in_use)) break;
+                       if(!test_and_set_bit(MGA_BUF_IN_USE, 
+                                            &prim_buffer->buffer_status)) 
+                               break;
                        atomic_inc(&dev->total_sleeps);
                        atomic_inc(&dma->total_missed_sched);
-                       mga_print_all_primary(dev);
-                       DRM_DEBUG("Schedule in advance\n");
-                       /* Three second delay */
-                       schedule_timeout(HZ*3);
+                       schedule();
                        if (signal_pending(current)) {
                                ret = -ERESTARTSYS;
                                break;
@@ -536,16 +494,27 @@ int mga_advance_primary(drm_device_t *dev)
                remove_wait_queue(&dev_priv->wait_queue, &entry);
                if(ret) return ret;
        }
-       atomic_set(&dev_priv->in_wait, 0);
+       clear_bit(MGA_IN_WAIT, &dev_priv->dispatch_status);
+
        /* This primary buffer is now free to use */
        prim_buffer->current_dma_ptr = prim_buffer->head;
        prim_buffer->num_dwords = 0;
        prim_buffer->sec_used = 0;
-       atomic_set(&prim_buffer->needs_overflow, 0);
+       prim_buffer->prim_age = dev_priv->next_prim_age++;
+       if(prim_buffer->prim_age == 0 || prim_buffer->prim_age == 0xffffffff) {
+          mga_flush_queue(dev);
+          mga_dma_quiescent(dev);
+          mga_reset_freelist(dev);
+          prim_buffer->prim_age = (dev_priv->next_prim_age += 2);
+       }
+
+       /* Reset all buffer status stuff */
+       clear_bit(MGA_BUF_NEEDS_OVERFLOW, &prim_buffer->buffer_status);
+       clear_bit(MGA_BUF_FORCE_FIRE, &prim_buffer->buffer_status);
+       clear_bit(MGA_BUF_SWAP_PENDING, &prim_buffer->buffer_status);
+
        dev_priv->current_prim = prim_buffer;
        dev_priv->current_prim_idx = next_prim_idx;
-       DRM_DEBUG("Primarys at advance\n");
-       mga_print_all_primary(dev);
        return 0;
 }
 
@@ -554,21 +523,29 @@ static inline int mga_decide_to_fire(drm_device_t *dev)
 {
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
        drm_device_dma_t  *dma      = dev->dma;
-       
-       if(atomic_read(&dev_priv->next_prim->force_fire))
-       {
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       if(test_bit(MGA_BUF_FORCE_FIRE, &dev_priv->next_prim->buffer_status)) {
                atomic_inc(&dma->total_prio);
                return 1;
        }
 
-       if (atomic_read(&dev_priv->in_flush) && dev_priv->next_prim->num_dwords)
-       {
+       if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) &&
+           dev_priv->next_prim->num_dwords) {
+               atomic_inc(&dma->total_prio);
+               return 1;
+       }
+
+       if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
+           dev_priv->next_prim->num_dwords) {
                atomic_inc(&dma->total_prio);
                return 1;
        }
    
        if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS - 1) {
-               if(test_bit(0, &dev_priv->next_prim->swap_pending)) {
+               if(test_bit(MGA_BUF_SWAP_PENDING, 
+                           &dev_priv->next_prim->buffer_status)) {
                        atomic_inc(&dma->total_dmas);
                        return 1;
                }
@@ -602,10 +579,11 @@ int mga_dma_schedule(drm_device_t *dev, int locked)
                return -EBUSY;
        }
    
-               DRM_DEBUG("mga_dma_schedule\n");
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
-       if(atomic_read(&dev_priv->in_flush) || 
-          atomic_read(&dev_priv->in_wait)) {
+       if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) || 
+          test_bit(MGA_IN_WAIT, &dev_priv->dispatch_status) ||
+          test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) {
                locked = 1;
        }
    
@@ -613,27 +591,25 @@ int mga_dma_schedule(drm_device_t *dev, int locked)
            !drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) {
                atomic_inc(&dma->total_missed_lock);
                clear_bit(0, &dev->dma_flag);
+               DRM_DEBUG("Not locked\n");
                return -EBUSY;
        }
        DRM_DEBUG("I'm locked\n");
 
-   
-       if(!test_and_set_bit(0, &dev_priv->dispatch_lock)) {
+       if(!test_and_set_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status)) {
                /* Fire dma buffer */
                if(mga_decide_to_fire(dev)) {
-                       DRM_DEBUG("mga_fire_primary\n");
                        DRM_DEBUG("idx :%d\n", dev_priv->next_prim->idx);
-                       atomic_set(&dev_priv->next_prim->force_fire, 0);
-                       if(dev_priv->current_prim == dev_priv->next_prim &&
-                          dev_priv->next_prim->num_dwords != 0) {
+                       clear_bit(MGA_BUF_FORCE_FIRE, 
+                                 &dev_priv->next_prim->buffer_status);
+                       if(dev_priv->current_prim == dev_priv->next_prim) {
                                /* Schedule overflow for a later time */
-                               atomic_set(
-                                       &dev_priv->current_prim->needs_overflow,
-                                       1);
+                               set_bit(MGA_BUF_NEEDS_OVERFLOW,
+                                       &dev_priv->next_prim->buffer_status);
                        }
                        mga_fire_primary(dev, dev_priv->next_prim);
                } else {
-                       clear_bit(0, &dev_priv->dispatch_lock);
+                       clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
                }
        } else {
                DRM_DEBUG("I can't get the dispatch lock\n");
@@ -646,17 +622,26 @@ int mga_dma_schedule(drm_device_t *dev, int locked)
                }
        }
 
-       clear_bit(0, &dev->dma_flag);
-   
-       if(atomic_read(&dev_priv->in_flush) == 1 &&
-          dev_priv->next_prim->num_dwords == 0) {
-               /* Everything is on the hardware */
-               DRM_DEBUG("Primarys at Flush\n");
-               mga_print_all_primary(dev);
-               atomic_set(&dev_priv->in_flush, 0);
+       if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
+          dev_priv->next_prim->num_dwords == 0 &&
+          atomic_read(&dev_priv->pending_bufs) == 0) {
+               /* Everything has been processed by the hardware */
+               clear_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status);
                wake_up_interruptible(&dev_priv->flush_queue);
        }
 
+       if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) &&
+          dev_priv->tail->age < dev_priv->last_prim_age) {
+               clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
+               DRM_DEBUG("Waking up buf queue\n");
+               wake_up_interruptible(&dev_priv->buf_queue);
+       } else if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) {
+               DRM_DEBUG("Not waking buf_queue on %d %d\n", 
+                         atomic_read(&dev->total_irq), 
+                         dev_priv->last_prim_age);
+       }
+
+       clear_bit(0, &dev->dma_flag);
        return 0;
 }
 
@@ -665,33 +650,35 @@ static void mga_dma_service(int irq, void *device, struct pt_regs *regs)
        drm_device_t     *dev = (drm_device_t *)device;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
        drm_mga_prim_buf_t *last_prim_buffer;
-       __volatile__ unsigned int *status = 
-               (__volatile__ unsigned int *)dev_priv->status_page;
-    
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
        atomic_inc(&dev->total_irq);
+       if((MGA_READ(MGAREG_STATUS) & 0x00000001) != 0x00000001) return;
        MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
        last_prim_buffer = dev_priv->last_prim;
        last_prim_buffer->num_dwords = 0;
        last_prim_buffer->sec_used = 0;
-       clear_bit(0, &last_prim_buffer->in_use);
+       dev_priv->sarea_priv->last_dispatch = 
+               dev_priv->last_prim_age = last_prim_buffer->prim_age;
+       clear_bit(MGA_BUF_IN_USE, &last_prim_buffer->buffer_status);
        wake_up_interruptible(&dev_priv->wait_queue);
-       clear_bit(0, &last_prim_buffer->swap_pending);
-       clear_bit(0, &dev_priv->dispatch_lock);
+       clear_bit(MGA_BUF_SWAP_PENDING, &last_prim_buffer->buffer_status);
+       clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
        atomic_dec(&dev_priv->pending_bufs);
-       dev_priv->sarea_priv->last_dispatch = status[1];
        queue_task(&dev->tq, &tq_immediate);
        mark_bh(IMMEDIATE_BH);
 }
 
 static void mga_dma_task_queue(void *device)
 {
-       drm_device_t *dev = (drm_device_t *) device;
-
-       mga_dma_schedule(dev, 0);
+       DRM_DEBUG("%s\n", __FUNCTION__);
+       mga_dma_schedule((drm_device_t *)device, 0);
 }
 
 int mga_dma_cleanup(drm_device_t *dev)
 {
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        if(dev->dev_private) {
                drm_mga_private_t *dev_priv = 
                        (drm_mga_private_t *) dev->dev_private;
@@ -740,14 +727,13 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
        drm_map_t *sarea_map = NULL;
        int i;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
        if(dev_priv == NULL) return -ENOMEM;
        dev->dev_private = (void *) dev_priv;
 
-       DRM_DEBUG("dev_private\n");
-
        memset(dev_priv, 0, sizeof(drm_mga_private_t));
-       atomic_set(&dev_priv->in_flush, 0);
 
        if((init->reserved_map_idx >= dev->map_count) ||
           (init->buffer_map_idx >= dev->map_count)) {
@@ -762,7 +748,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
        dev_priv->sarea_priv = (drm_mga_sarea_t *) 
                ((u8 *)sarea_map->handle + 
                 init->sarea_priv_offset);
-       DRM_DEBUG("sarea_priv\n");
 
        /* Scale primary size to the next page */
        dev_priv->chipset = init->chipset;
@@ -777,6 +762,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
 
        dev_priv->mAccess = init->mAccess;
        init_waitqueue_head(&dev_priv->flush_queue);
+       init_waitqueue_head(&dev_priv->buf_queue);
        dev_priv->WarpPipe = -1;
 
        DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n",
@@ -796,20 +782,17 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
                          dev_priv->WarpIndex[i].phys_addr,
                          dev_priv->WarpIndex[i].size);
 
-       DRM_DEBUG("Doing init prim buffers\n");
        if(mga_init_primary_bufs(dev, init) != 0) {
                DRM_ERROR("Can not initialize primary buffers\n");
                mga_dma_cleanup(dev);
                return -ENOMEM;
        }
-       DRM_DEBUG("Done with init prim buffers\n");
        dev_priv->real_status_page = mga_alloc_page(dev);
        if(dev_priv->real_status_page == 0UL) {
                mga_dma_cleanup(dev);
                DRM_ERROR("Can not allocate status page\n");
                return -ENOMEM;
        }
-       DRM_DEBUG("Status page at %lx\n", dev_priv->real_status_page);
 
        dev_priv->status_page = 
                ioremap_nocache(virt_to_bus((void *)dev_priv->real_status_page),
@@ -821,38 +804,23 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
                return -ENOMEM;
        }
 
-       DRM_DEBUG("Status page remapped to %p\n", dev_priv->status_page);
        /* Write status page when secend or softrap occurs */
        MGA_WRITE(MGAREG_PRIMPTR, 
                  virt_to_bus((void *)dev_priv->real_status_page) | 0x00000003);
-   
-       dev_priv->device = pci_find_device(0x102b, 0x0525, NULL);
-       if(dev_priv->device == NULL) {
-               DRM_ERROR("Could not find pci device for card\n");
-               mga_dma_cleanup(dev);
-               return -EINVAL;
-       }
-   
-       DRM_DEBUG("dma initialization\n");
+      
 
        /* Private is now filled in, initialize the hardware */
        {
-               __volatile__ unsigned int *status = 
-                       (unsigned int *)dev_priv->status_page;
                PRIMLOCALS;
                PRIMGETPTR( dev_priv );
-          
-               dev_priv->last_sync_tag = mga_create_sync_tag(dev);
-          
+                  
                PRIMOUTREG(MGAREG_DMAPAD, 0);
                PRIMOUTREG(MGAREG_DMAPAD, 0);
-               PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
+               PRIMOUTREG(MGAREG_DWGSYNC, 0x0100);
                PRIMOUTREG(MGAREG_SOFTRAP, 0);
                /* Poll for the first buffer to insure that
                 * the status register will be correct
                 */
-               DRM_DEBUG("phys_head : %lx\n", (unsigned long)phys_head);
-               status[1] = 0;
           
                mga_flush_write_combine();
                MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL);
@@ -860,9 +828,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
                MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) | 
                                           PDEA_pagpxfer_enable));
           
-               while(MGA_READ(MGAREG_DWGSYNC) != dev_priv->last_sync_tag) ;
-               DRM_DEBUG("status[0] after initialization : %x\n", status[0]);
-               DRM_DEBUG("status[1] after initialization : %x\n", status[1]);
+               while(MGA_READ(MGAREG_DWGSYNC) != 0x0100) ;
        }
 
        if(mga_freelist_init(dev) != 0) {
@@ -870,7 +836,6 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
                mga_dma_cleanup(dev);
                return -ENOMEM;
        }
-       DRM_DEBUG("dma init was successful\n");
        return 0;
 }
 
@@ -881,6 +846,8 @@ int mga_dma_init(struct inode *inode, struct file *filp,
        drm_device_t *dev = priv->dev;
        drm_mga_init_t init;
    
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        copy_from_user_ret(&init, (drm_mga_init_t *)arg, sizeof(init), -EFAULT);
    
        switch(init.func) {
@@ -925,7 +892,7 @@ int mga_irq_install(drm_device_t *dev, int irq)
                                /* Install handler */
        if ((retcode = request_irq(dev->irq,
                                   mga_dma_service,
-                                  0,
+                                  SA_SHIRQ,
                                   dev->devname,
                                   dev))) {
                down(&dev->struct_sem);
@@ -964,7 +931,9 @@ int mga_control(struct inode *inode, struct file *filp, unsigned int cmd,
        drm_control_t   ctl;
    
        copy_from_user_ret(&ctl, (drm_control_t *)arg, sizeof(ctl), -EFAULT);
-       
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        switch (ctl.func) {
        case DRM_INST_HANDLER:
                return mga_irq_install(dev, ctl.irq);
@@ -981,30 +950,33 @@ static int mga_flush_queue(drm_device_t *dev)
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
        int ret = 0;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        if(dev_priv == NULL) {
                return 0;
        }
    
        if(dev_priv->next_prim->num_dwords != 0) {
-               atomic_set(&dev_priv->in_flush, 1);
+               set_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status);
                current->state = TASK_INTERRUPTIBLE;
                add_wait_queue(&dev_priv->flush_queue, &entry);
                for (;;) {
                        mga_dma_schedule(dev, 0);
-                       if (atomic_read(&dev_priv->in_flush) == 0) 
+                       if (!test_bit(MGA_IN_FLUSH, 
+                                     &dev_priv->dispatch_status)) 
                                break;
                        atomic_inc(&dev->total_sleeps);
-                       DRM_DEBUG("Schedule in flush_queue\n");
-                       schedule_timeout(HZ*3);
+                       schedule();
                        if (signal_pending(current)) {
                                ret = -EINTR; /* Can't restart */
+                               clear_bit(MGA_IN_FLUSH, 
+                                         &dev_priv->dispatch_status);
                                break;
                        }
                }
                current->state = TASK_RUNNING;
                remove_wait_queue(&dev_priv->flush_queue, &entry);
        }
-       atomic_set(&dev_priv->in_flush, 0);
        return ret;
 }
 
@@ -1018,6 +990,7 @@ void mga_reclaim_buffers(drm_device_t *dev, pid_t pid)
        if(dev->dev_private == NULL) return;
        if(dma->buflist == NULL) return;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
         mga_flush_queue(dev);
 
        for (i = 0; i < dma->buf_count; i++) {
@@ -1043,6 +1016,7 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
        int               ret   = 0;
        drm_lock_t        lock;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
        copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
 
        if (lock.context == DRM_KERNEL_CONTEXT) {
@@ -1081,7 +1055,6 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd,
                                /* Contention */
                        atomic_inc(&dev->total_sleeps);
                        current->state = TASK_INTERRUPTIBLE;
-                       DRM_DEBUG("Calling lock schedule\n");
                        schedule();
                        if (signal_pending(current)) {
                                ret = -ERESTARTSYS;
@@ -1111,11 +1084,8 @@ int mga_flush_ioctl(struct inode *inode, struct file *filp,
        drm_device_t      *dev    = priv->dev;
        drm_lock_t        lock;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       __volatile__ unsigned int *status = 
-               (__volatile__ unsigned int *)dev_priv->status_page;
-       int              i;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
        copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT);
 
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
@@ -1124,28 +1094,17 @@ int mga_flush_ioctl(struct inode *inode, struct file *filp,
        }
 
        if(lock.flags & _DRM_LOCK_FLUSH || lock.flags & _DRM_LOCK_FLUSH_ALL) {
-               mga_flush_queue(dev);
-
-               if((MGA_READ(MGAREG_STATUS) & 0x00030001) == 0x00020000 &&
-                  status[1] != dev_priv->last_sync_tag) 
-               {
-                       DRM_DEBUG("Reseting hardware status\n");
-                       MGA_WRITE(MGAREG_DWGSYNC, dev_priv->last_sync_tag);
-
-                       while(MGA_READ(MGAREG_DWGSYNC) != 
-                             dev_priv->last_sync_tag) 
-                       {
-                               for(i = 0; i < 4096; i++) mga_delay();
-                       }
-
-                       status[1] = 
-                               sarea_priv->last_dispatch = 
-                               dev_priv->last_sync_tag;
-               } else {
-                       sarea_priv->last_dispatch = status[1];
-               }
+               drm_mga_prim_buf_t *temp_buf =
+                       dev_priv->prim_bufs[dev_priv->current_prim_idx];
+
+               if(temp_buf && temp_buf->num_dwords) {
+                       set_bit(MGA_BUF_FORCE_FIRE, &temp_buf->buffer_status);
+                       mga_advance_primary(dev);
+                       mga_dma_schedule(dev, 1);
+               }
        }
        if(lock.flags & _DRM_LOCK_QUIESCENT) {
+               mga_flush_queue(dev);
                mga_dma_quiescent(dev);
        }
 
index 12a858e..7228b90 100644 (file)
@@ -37,6 +37,7 @@
  */
 #ifndef _MGA_DEFINES_
 #define _MGA_DEFINES_
+
 #define MGA_F  0x1             /* fog */
 #define MGA_A  0x2             /* alpha */
 #define MGA_S  0x4             /* specular */
 
 #define MGA_MAX_G400_PIPES 16
 #define MGA_MAX_G200_PIPES  8  /* no multitex */
-
 #define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES
 
 #define MGA_CARD_TYPE_G200 1
 #define MGA_CARD_TYPE_G400 2
+
 #define MGA_FRONT   0x1
 #define MGA_BACK    0x2
 #define MGA_DEPTH   0x4
 #define MGA_UPLOAD_TEX0       0x2
 #define MGA_UPLOAD_TEX1       0x4
 #define MGA_UPLOAD_PIPE       0x8
-#define MGA_UPLOAD_TEX0IMAGE  0x10
-#define MGA_UPLOAD_TEX1IMAGE  0x20
+#define MGA_UPLOAD_TEX0IMAGE  0x10 /* handled client-side */
+#define MGA_UPLOAD_TEX1IMAGE  0x20 /* handled client-side */
 #define MGA_UPLOAD_2D        0x40
 #define MGA_WAIT_AGE          0x80 /* handled client-side */
 #define MGA_UPLOAD_CLIPRECTS  0x100 /* handled client-side */
 #define MGA_DMA_FLUSH        0x200 /* set when someone gets the lock
                                        quiescent */
 
-/* 64 buffers of 16k each, total 1 meg.
+/* 32 buffers of 64k each, total 2 meg.
  */
-#define MGA_DMA_BUF_ORDER     14
+#define MGA_DMA_BUF_ORDER     16
 #define MGA_DMA_BUF_SZ        (1<<MGA_DMA_BUF_ORDER)
-#define MGA_DMA_BUF_NR        63
+#define MGA_DMA_BUF_NR        31
 
 /* Keep these small for testing.
  */
@@ -159,19 +160,19 @@ typedef struct drm_mga_init {
        int sarea_priv_offset;
        int primary_size;
        int warp_ucode_size;
-       int frontOffset;
-       int backOffset;
-       int depthOffset;
-       int textureOffset;
-       int textureSize;
-        int agpTextureOffset;
-        int agpTextureSize;
-       int cpp;
-       int stride;
+       unsigned int frontOffset;
+       unsigned int backOffset;
+       unsigned int depthOffset;
+       unsigned int textureOffset;
+       unsigned int textureSize;
+        unsigned int agpTextureOffset;
+        unsigned int agpTextureSize;
+       unsigned int cpp;
+       unsigned int stride;
        int sgram;
        int chipset;
        drm_mga_warp_index_t WarpIndex[MGA_MAX_WARP_PIPES];
-       int mAccess;
+       unsigned int mAccess;
 } drm_mga_init_t;
 
 /* Warning: if you change the sarea structure, you must change the Xserver
@@ -180,7 +181,7 @@ typedef struct drm_mga_init {
 typedef struct _drm_mga_tex_region {
        unsigned char next, prev;       
        unsigned char in_use;   
-       int age;                        
+       unsigned int age;                       
 } drm_mga_tex_region_t;
 
 typedef struct _drm_mga_sarea {
@@ -219,9 +220,9 @@ typedef struct _drm_mga_sarea {
    
        /* Counters for aging textures and for client-side throttling.
         */
-        int last_enqueue;      /* last time a buffer was enqueued */
-       int last_dispatch;      /* age of the most recently dispatched buffer */
-       int last_quiescent;     /*  */
+        unsigned int last_enqueue;     /* last time a buffer was enqueued */
+       unsigned int last_dispatch;     /* age of the most recently dispatched buffer */
+       unsigned int last_quiescent;     /*  */
 
 
        /* LRU lists for texture memory in agp space and on the card
@@ -237,9 +238,9 @@ typedef struct _drm_mga_sarea {
 /* Device specific ioctls:
  */
 typedef struct _drm_mga_clear {
-       int clear_color;
-       int clear_depth;
-       int flags;
+       unsigned int clear_color;
+       unsigned int clear_depth;
+       unsigned int flags;
 } drm_mga_clear_t;
 
 typedef struct _drm_mga_swap {
@@ -258,4 +259,11 @@ typedef struct _drm_mga_vertex {
        int discard;            /* client finished with buffer?  */
 } drm_mga_vertex_t;
 
+typedef struct _drm_mga_indices {
+       int idx;                /* buffer to queue */
+       unsigned int start;             
+       unsigned int end;               
+       int discard;            /* client finished with buffer?  */
+} drm_mga_indices_t;
+
 #endif
index 82dda64..5fabe1f 100644 (file)
@@ -111,6 +111,7 @@ static drm_ioctl_desc_t           mga_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_MGA_ILOAD)]   = { mga_iload,       1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_MGA_VERTEX)]  = { mga_vertex,      1, 0 },
        [DRM_IOCTL_NR(DRM_IOCTL_MGA_FLUSH)]   = { mga_flush_ioctl, 1, 0 },
+       [DRM_IOCTL_NR(DRM_IOCTL_MGA_INDICES)] = { mga_indices,     1, 0 },
 };
 
 #define MGA_IOCTL_COUNT DRM_ARRAY_SIZE(mga_ioctls)
index 801e707..80d63c4 100644 (file)
 #ifndef _MGA_DRV_H_
 #define _MGA_DRV_H_
 
+#define MGA_BUF_IN_USE         0
+#define MGA_BUF_SWAP_PENDING   1
+#define MGA_BUF_FORCE_FIRE     2
+#define MGA_BUF_NEEDS_OVERFLOW 3
+
 typedef struct {
+       u32 buffer_status;
        unsigned int num_dwords;
        unsigned int max_dwords;
        u32 *current_dma_ptr;
        u32 *head;
        u32 phys_head;
+       unsigned int prim_age;
        int sec_used;
        int idx;
-       int swap_pending;
-       u32 in_use;
-       atomic_t force_fire;
-       atomic_t needs_overflow;
 } drm_mga_prim_buf_t;
 
 typedef struct _drm_mga_freelist {
@@ -53,31 +56,33 @@ typedef struct _drm_mga_freelist {
        struct _drm_mga_freelist *prev;
 } drm_mga_freelist_t;
 
+#define MGA_IN_DISPATCH   0
+#define MGA_IN_FLUSH      1
+#define MGA_IN_WAIT       2
+#define MGA_IN_GETBUF    3
+
 typedef struct _drm_mga_private {
+       u32 dispatch_status;
+       unsigned int next_prim_age;
+       __volatile__ unsigned int last_prim_age;
        int reserved_map_idx;
        int buffer_map_idx;
        drm_mga_sarea_t *sarea_priv;
        int primary_size;
        int warp_ucode_size;
        int chipset;
-       int frontOffset;
-       int backOffset;
-       int depthOffset;
-       int textureOffset;
-       int textureSize;
+       unsigned int frontOffset;
+       unsigned int backOffset;
+       unsigned int depthOffset;
+       unsigned int textureOffset;
+       unsigned int textureSize;
        int cpp;
-       int stride;
+       unsigned int stride;
        int sgram;
        int use_agp;
        drm_mga_warp_index_t WarpIndex[MGA_MAX_G400_PIPES];
        unsigned int WarpPipe;
-       __volatile__ unsigned long softrap_age;
-       u32 dispatch_lock;
-       atomic_t in_flush;
-       atomic_t in_wait;
        atomic_t pending_bufs;
-       unsigned int last_sync_tag;
-       unsigned int sync_tag;
        void *status_page;
        unsigned long real_status_page;
        u8 *ioremap;
@@ -86,12 +91,11 @@ typedef struct _drm_mga_private {
        drm_mga_prim_buf_t *last_prim;
        drm_mga_prim_buf_t *current_prim;
        int current_prim_idx;
-       struct pci_dev *device;
        drm_mga_freelist_t *head;
        drm_mga_freelist_t *tail;
        wait_queue_head_t flush_queue;  /* Processes waiting until flush    */
        wait_queue_head_t wait_queue;   /* Processes waiting until interrupt */
-
+       wait_queue_head_t buf_queue;    /* Processes waiting for a free buf */
        /* Some validated register values:
         */     
        u32 mAccess;
@@ -126,7 +130,7 @@ extern int mga_dma_init(struct inode *inode, struct file *filp,
 extern int mga_dma_cleanup(drm_device_t *dev);
 extern int mga_flush_ioctl(struct inode *inode, struct file *filp,
                           unsigned int cmd, unsigned long arg);
-
+extern void mga_flush_write_combine(void);
 extern unsigned int mga_create_sync_tag(drm_device_t *dev);
 extern drm_buf_t *mga_freelist_get(drm_device_t *dev);
 extern int mga_freelist_put(drm_device_t *dev, drm_buf_t *buf);
@@ -156,6 +160,8 @@ extern int  mga_iload(struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg);
 extern int  mga_vertex(struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg);
+extern int  mga_indices(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
                                /* mga_context.c */
 extern int  mga_resctx(struct inode *inode, struct file *filp,
                       unsigned int cmd, unsigned long arg);
@@ -186,6 +192,7 @@ typedef enum {
 typedef struct {
        drm_mga_freelist_t *my_freelist;
        int discard;
+       int dispatched;
 } drm_mga_buf_priv_t;
 
 #define DWGREG0        0x1c00
@@ -206,15 +213,16 @@ typedef struct {
 
 #define PRIM_OVERFLOW(dev, dev_priv, length) do {                      \
        drm_mga_prim_buf_t *tmp_buf =                                   \
-               dev_priv->prim_bufs[dev_priv->current_prim_idx];        \
-       if( tmp_buf->max_dwords - tmp_buf->num_dwords < length ||       \
-           tmp_buf->sec_used > MGA_DMA_BUF_NR/2) {                     \
-               atomic_set(&tmp_buf->force_fire, 1);                    \
-               mga_advance_primary(dev);                               \
-               mga_dma_schedule(dev, 1);                               \
-       } else if( atomic_read(&tmp_buf->needs_overflow)) {             \
-               mga_advance_primary(dev);                               \
-               mga_dma_schedule(dev, 1);                               \
+               dev_priv->prim_bufs[dev_priv->current_prim_idx];        \
+       if( test_bit(MGA_BUF_NEEDS_OVERFLOW,                            \
+                 &tmp_buf->buffer_status)) {                           \
+               mga_advance_primary(dev);                               \
+               mga_dma_schedule(dev, 1);                               \
+       } else if( tmp_buf->max_dwords - tmp_buf->num_dwords < length ||\
+           tmp_buf->sec_used > MGA_DMA_BUF_NR/2) {                     \
+               set_bit(MGA_BUF_FORCE_FIRE, &tmp_buf->buffer_status);   \
+               mga_advance_primary(dev);                               \
+               mga_dma_schedule(dev, 1);                               \
        }                                                               \
 } while(0)
 
@@ -266,6 +274,13 @@ drm_mga_prim_buf_t *tmp_buf =                                      \
        tmp_buf->sec_used++;                                            \
 } while (0)
 
+#define AGEBUF(dev_priv, buf_priv)     do {                            \
+       drm_mga_prim_buf_t *tmp_buf =                                   \
+               dev_priv->prim_bufs[dev_priv->current_prim_idx];        \
+       buf_priv->my_freelist->age = tmp_buf->prim_age;                 \
+} while (0)
+
+
 #define PRIMOUTREG(reg, val) do {                                      \
        tempIndex[outcount]=ADRINDEX(reg);                              \
        dma_ptr[1+outcount] = val;                                      \
@@ -379,6 +394,9 @@ drm_mga_prim_buf_t *tmp_buf =                                       \
 #define DC_pattern_disable                     0x0
 #define DC_transc_disable                      0x0
 
+#define SETADD_mode_vertlist                           0x0     
+
+
 #define MGA_CLEAR_CMD (DC_opcod_trap | DC_arzero_enable |              \
                       DC_sgnzero_enable | DC_shftzero_enable |         \
                       (0xC << DC_bop_SHIFT) | DC_clipdis_enable |      \
index a70f86d..dc22776 100644 (file)
@@ -41,14 +41,15 @@ static void mgaEmitClipRect( drm_mga_private_t *dev_priv,
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        unsigned int *regs = sarea_priv->ContextState;
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        /* This takes 10 dwords */
        PRIMGETPTR( dev_priv );
    
        /* Force reset of dwgctl (eliminates clip disable) */
        PRIMOUTREG( MGAREG_DMAPAD, 0 );
-       PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 );
-       PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 );
+       PRIMOUTREG( MGAREG_DWGSYNC, 0 );
+       PRIMOUTREG( MGAREG_DWGSYNC, 0 );
        PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
 
        PRIMOUTREG( MGAREG_DMAPAD, 0 );
@@ -64,6 +65,7 @@ static void mgaEmitContext(drm_mga_private_t *dev_priv )
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        unsigned int *regs = sarea_priv->ContextState;
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
        
        /* This takes a max of 15 dwords */
        PRIMGETPTR( dev_priv );
@@ -98,6 +100,7 @@ static void mgaG200EmitTex( drm_mga_private_t *dev_priv )
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        unsigned int *regs = sarea_priv->TexState[0];
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        PRIMGETPTR( dev_priv );
    
@@ -132,6 +135,7 @@ static void mgaG400EmitTex0( drm_mga_private_t *dev_priv )
        unsigned int *regs = sarea_priv->TexState[0];
        int multitex = sarea_priv->WarpPipe & MGA_T2;
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
    
        PRIMGETPTR( dev_priv );
    
@@ -179,6 +183,7 @@ static void mgaG400EmitTex1( drm_mga_private_t *dev_priv )
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        unsigned int *regs = sarea_priv->TexState[1];
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
    
        PRIMGETPTR(dev_priv);
 
@@ -217,6 +222,7 @@ static void mgaG400EmitPipe(drm_mga_private_t *dev_priv )
        unsigned int pipe = sarea_priv->WarpPipe;
        float fParam = 12800.0f;
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
    
        PRIMGETPTR(dev_priv);
 
@@ -255,7 +261,7 @@ static void mgaG400EmitPipe(drm_mga_private_t *dev_priv )
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
-       PRIMOUTREG(MGAREG_WIADDR2, (__u32)(dev_priv->WarpIndex[pipe].phys_addr |
+       PRIMOUTREG(MGAREG_WIADDR2, (u32)(dev_priv->WarpIndex[pipe].phys_addr |
                                           WIA_wmode_start | WIA_wagp_agp));
        PRIMADVANCE(dev_priv);
 }
@@ -265,6 +271,7 @@ static void mgaG200EmitPipe( drm_mga_private_t *dev_priv )
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        unsigned int pipe = sarea_priv->WarpPipe;
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        PRIMGETPTR(dev_priv);
    
@@ -284,7 +291,7 @@ static void mgaG200EmitPipe( drm_mga_private_t *dev_priv )
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
        PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
-       PRIMOUTREG(MGAREG_WIADDR, (__u32)(dev_priv->WarpIndex[pipe].phys_addr | 
+       PRIMOUTREG(MGAREG_WIADDR, (u32)(dev_priv->WarpIndex[pipe].phys_addr | 
                                          WIA_wmode_start | WIA_wagp_agp));
 
        PRIMADVANCE(dev_priv);
@@ -294,6 +301,7 @@ static void mgaEmitState( drm_mga_private_t *dev_priv )
 {
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        unsigned int dirty = sarea_priv->dirty;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        if (dev_priv->chipset == MGA_CARD_TYPE_G400) {     
                int multitex = sarea_priv->WarpPipe & MGA_T2;
@@ -343,6 +351,8 @@ static int mgaVerifyContext(drm_mga_private_t *dev_priv )
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
        unsigned int *regs = sarea_priv->ContextState;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
            regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
                DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n", 
@@ -362,6 +372,8 @@ static int mgaVerifyTex(drm_mga_private_t *dev_priv,
 {
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
                DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n", 
                       sarea_priv->TexState[unit][MGA_TEXREG_ORG],
@@ -379,6 +391,8 @@ static int mgaVerifyState( drm_mga_private_t *dev_priv )
        unsigned int dirty = sarea_priv->dirty;
        int rv = 0;
 
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
                sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
 
@@ -409,6 +423,8 @@ static int mgaVerifyIload( drm_mga_private_t *dev_priv,
                           unsigned long bus_address, 
                           unsigned int dstOrg, int length )
 {
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
        if(dstOrg < dev_priv->textureOffset ||
           dstOrg + length > 
           (dev_priv->textureOffset + dev_priv->textureSize)) {
@@ -432,14 +448,13 @@ static void mga_dma_dispatch_tex_blit( drm_device_t *dev,
        int use_agp = PDEA_pagpxfer_enable | 0x00000001;
        u16 y2;
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
     
         y2 = length / 64;
  
        PRIM_OVERFLOW(dev, dev_priv, 30);
        PRIMGETPTR( dev_priv );
 
-       dev_priv->last_sync_tag = mga_create_sync_tag(dev);
-
        PRIMOUTREG( MGAREG_DSTORG, destOrg);
        PRIMOUTREG( MGAREG_MACCESS, 0x00000000);
        DRM_DEBUG("srcorg : %lx\n", bus_address | use_agp);
@@ -459,7 +474,7 @@ static void mga_dma_dispatch_tex_blit( drm_device_t *dev,
        PRIMOUTREG( MGAREG_SRCORG, 0);
        PRIMOUTREG( MGAREG_PITCH, dev_priv->stride / dev_priv->cpp);
        PRIMOUTREG( MGAREG_DMAPAD, 0);
-       PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
+       PRIMOUTREG( MGAREG_DMAPAD, 0);
        PRIMADVANCE(dev_priv);
 }
 
@@ -475,33 +490,101 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev,
        int i = 0;
        int primary_needed;
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        DRM_DEBUG("dispatch vertex %d addr 0x%lx, "
                  "length 0x%x nbox %d dirty %x\n", 
                  buf->idx, address, length, 
                  sarea_priv->nbox, sarea_priv->dirty);
 
+       DRM_DEBUG("used : %d, total : %d\n", buf->used, buf->total);
+       if(sarea_priv->WarpPipe & MGA_T2) { 
+          if ((buf->used/4) % 10)
+            DRM_DEBUG("Multitex Buf is not aligned properly!!!\n");
+       } else { 
+          if ((buf->used/4) % 8)
+            DRM_DEBUG("Buf is not aligned properly!!!\n");
+       }
 
-       dev_priv->last_sync_tag = mga_create_sync_tag(dev);
+       if (buf->used) {
+               /* WARNING: if you change any of the state functions verify
+                * these numbers (Overestimating this doesn't hurt).  
+                */
+               buf_priv->dispatched = 1;
+               primary_needed = (25+15+30+25+ 
+                                 10 + 
+                                 15 * MGA_NR_SAREA_CLIPRECTS);
+               PRIM_OVERFLOW(dev, dev_priv, primary_needed);
+               mgaEmitState( dev_priv );
 
-       if (buf_priv->discard) { 
-               buf_priv->my_freelist->age = dev_priv->last_sync_tag;
+               do {
+                       if (i < sarea_priv->nbox) {
+                               DRM_DEBUG("idx %d Emit box %d/%d:"
+                                         "%d,%d - %d,%d\n", 
+                                         buf->idx,
+                                         i, sarea_priv->nbox,
+                                         sarea_priv->boxes[i].x1, 
+                                         sarea_priv->boxes[i].y1,
+                                         sarea_priv->boxes[i].x2, 
+                                         sarea_priv->boxes[i].y2);
+                               
+                               mgaEmitClipRect( dev_priv, 
+                                                &sarea_priv->boxes[i] );
+                       }
+                       
+                       PRIMGETPTR(dev_priv);
+                       PRIMOUTREG( MGAREG_DMAPAD, 0);
+                       PRIMOUTREG( MGAREG_DMAPAD, 0);
+                       PRIMOUTREG( MGAREG_SECADDRESS, 
+                                   ((u32)address) | TT_VERTEX);
+                       PRIMOUTREG( MGAREG_SECEND, 
+                                   (((u32)(address + length)) | 
+                                    use_agp));
+                       PRIMADVANCE( dev_priv );               
+               }  while (++i < sarea_priv->nbox);
+       }
+
+       if (buf_priv->discard) {
+               if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv);
+               buf_priv->dispatched = 0;
                mga_freelist_put(dev, buf);
        }
 
 
-       /* WARNING: if you change any of the state functions verify
-        * these numbers (Overestimating this doesn't hurt).  
-        */
-       primary_needed = (25+15+30+25+ 
-                         10 + 
-                         15 * MGA_NR_SAREA_CLIPRECTS);
+}
 
 
-       PRIM_OVERFLOW(dev, dev_priv, primary_needed);
-       mgaEmitState( dev_priv );
+static void mga_dma_dispatch_indices(drm_device_t *dev, 
+                                    drm_buf_t *buf,
+                                    unsigned int start,
+                                    unsigned int end)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int address = (unsigned int)buf->bus_address;
+       int use_agp = PDEA_pagpxfer_enable;
+       int i = 0;
+       int primary_needed;
+       PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       DRM_DEBUG("dispatch indices %d addr 0x%x, "
+                 "start 0x%x end 0x%x nbox %d dirty %x\n", 
+                 buf->idx, address, start, end, 
+                 sarea_priv->nbox, sarea_priv->dirty);
+
+       if (start != end) {
+               /* WARNING: if you change any of the state functions verify
+                * these numbers (Overestimating this doesn't hurt).  
+                */
+               buf_priv->dispatched = 1;
+               primary_needed = (25+15+30+25+ 
+                                 10 + 
+                                 15 * MGA_NR_SAREA_CLIPRECTS);
+               PRIM_OVERFLOW(dev, dev_priv, primary_needed);
+               mgaEmitState( dev_priv );
 
-       if (buf->used) {
                do {
                        if (i < sarea_priv->nbox) {
                                DRM_DEBUG("idx %d Emit box %d/%d:"
@@ -520,21 +603,18 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev,
                        PRIMGETPTR(dev_priv);
                        PRIMOUTREG( MGAREG_DMAPAD, 0);
                        PRIMOUTREG( MGAREG_DMAPAD, 0);
-                       PRIMOUTREG( MGAREG_SECADDRESS, 
-                                   ((__u32)address) | TT_VERTEX);
-                       PRIMOUTREG( MGAREG_SECEND, 
-                                   (((__u32)(address + length)) | 
-                                    use_agp));
+                       PRIMOUTREG( MGAREG_SETUPADDRESS, 
+                                   ((address + start) | SETADD_mode_vertlist));
+                       PRIMOUTREG( MGAREG_SETUPEND, 
+                                   ((address + end) | use_agp));
                        PRIMADVANCE( dev_priv );               
                }  while (++i < sarea_priv->nbox);
        }
-
-       PRIMGETPTR( dev_priv );
-       PRIMOUTREG(MGAREG_DMAPAD, 0);
-       PRIMOUTREG(MGAREG_DMAPAD, 0);
-       PRIMOUTREG(MGAREG_DMAPAD, 0);
-       PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);   
-       PRIMADVANCE( dev_priv );
+       if (buf_priv->discard) {
+               if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv);
+               buf_priv->dispatched = 0;
+               mga_freelist_put(dev, buf);
+       }
 }
 
 
@@ -551,6 +631,7 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int flags,
        int i;
        int primary_needed;
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        if ( dev_priv->sgram ) 
                cmd = MGA_CLEAR_CMD | DC_atype_blk;
@@ -561,7 +642,6 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int flags,
        if(primary_needed == 0) primary_needed = 70;
        PRIM_OVERFLOW(dev, dev_priv, primary_needed);
        PRIMGETPTR( dev_priv );
-       dev_priv->last_sync_tag = mga_create_sync_tag(dev);
    
        for (i = 0 ; i < nbox ; i++) {
                unsigned int height = pbox[i].y2 - pbox[i].y1;
@@ -615,11 +695,6 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, int flags,
        PRIMOUTREG( MGAREG_DMAPAD, 0);   
        PRIMOUTREG( MGAREG_DMAPAD, 0);
        PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
-
-       PRIMOUTREG( MGAREG_DMAPAD, 0);
-       PRIMOUTREG( MGAREG_DMAPAD, 0);
-       PRIMOUTREG( MGAREG_DMAPAD, 0);
-       PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
        PRIMADVANCE(dev_priv);
 }
 
@@ -633,14 +708,13 @@ static void mga_dma_dispatch_swap( drm_device_t *dev )
        int i;
        int primary_needed;
        PRIMLOCALS;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        primary_needed = nbox * 5;
        primary_needed += 60;
        PRIM_OVERFLOW(dev, dev_priv, primary_needed);
        PRIMGETPTR( dev_priv );
    
-       dev_priv->last_sync_tag = mga_create_sync_tag(dev);
-
        PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
        PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
        PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
@@ -668,13 +742,9 @@ static void mga_dma_dispatch_swap( drm_device_t *dev )
        /* Force reset of DWGCTL */
        PRIMOUTREG( MGAREG_DMAPAD, 0);
        PRIMOUTREG( MGAREG_DMAPAD, 0);
-       PRIMOUTREG( MGAREG_DMAPAD, 0);
+       PRIMOUTREG( MGAREG_SRCORG, 0);
        PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
 
-       PRIMOUTREG( MGAREG_SRCORG, 0);
-       PRIMOUTREG( MGAREG_DMAPAD, 0);
-       PRIMOUTREG( MGAREG_DMAPAD, 0);
-       PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
        PRIMADVANCE(dev_priv);
 }
 
@@ -685,12 +755,11 @@ int mga_clear_bufs(struct inode *inode, struct file *filp,
        drm_device_t *dev = priv->dev;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       __volatile__ unsigned int *status = 
-               (__volatile__ unsigned int *)dev_priv->status_page;
        drm_mga_clear_t clear;
 
        copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, sizeof(clear), 
                           -EFAULT);
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
                DRM_ERROR("mga_clear_bufs called without lock held\n");
@@ -707,8 +776,8 @@ int mga_clear_bufs(struct inode *inode, struct file *filp,
                                clear.clear_color, 
                                clear.clear_depth );
        PRIMUPDATE(dev_priv);
+       mga_flush_write_combine();
        mga_dma_schedule(dev, 1);
-       sarea_priv->last_dispatch = status[1];
        return 0;
 }
 
@@ -719,8 +788,7 @@ int mga_swap_bufs(struct inode *inode, struct file *filp,
        drm_device_t *dev = priv->dev;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
        drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       __volatile__ unsigned int *status = 
-               (__volatile__ unsigned int *)dev_priv->status_page;
+       DRM_DEBUG("%s\n", __FUNCTION__);
    
        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
                DRM_ERROR("mga_swap_bufs called without lock held\n");
@@ -735,10 +803,9 @@ int mga_swap_bufs(struct inode *inode, struct file *filp,
        dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
        mga_dma_dispatch_swap( dev );
        PRIMUPDATE(dev_priv);
-       set_bit(0, &dev_priv->current_prim->swap_pending);
-       dev_priv->current_prim->swap_pending = 1;
+       set_bit(MGA_BUF_SWAP_PENDING, &dev_priv->current_prim->buffer_status);
+       mga_flush_write_combine();
        mga_dma_schedule(dev, 1);
-       sarea_priv->last_dispatch = status[1];
        return 0;
 }
 
@@ -750,12 +817,11 @@ int mga_iload(struct inode *inode, struct file *filp,
        drm_device_dma_t  *dma      = dev->dma;
                drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
                drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-               __volatile__ unsigned int *status = 
-               (__volatile__ unsigned int *)dev_priv->status_page;
        drm_buf_t *buf;
        drm_mga_buf_priv_t *buf_priv;
        drm_mga_iload_t iload;
        unsigned long bus_address;
+       DRM_DEBUG("%s\n", __FUNCTION__);
    
        DRM_DEBUG("Starting Iload\n");
        copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, sizeof(iload),
@@ -784,11 +850,11 @@ int mga_iload(struct inode *inode, struct file *filp,
 
        mga_dma_dispatch_tex_blit(dev, bus_address, iload.length, 
                                  iload.destOrg);
-       buf_priv->my_freelist->age = dev_priv->last_sync_tag;
+       AGEBUF(dev_priv, buf_priv);
        buf_priv->discard = 1;
        mga_freelist_put(dev, buf);
+       mga_flush_write_combine();
        mga_dma_schedule(dev, 1);
-       sarea_priv->last_dispatch = status[1];
        return 0; 
 }
 
@@ -798,13 +864,11 @@ int mga_vertex(struct inode *inode, struct file *filp,
        drm_file_t *priv = filp->private_data;
        drm_device_t *dev = priv->dev;
        drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       __volatile__ unsigned int *status = 
-               (__volatile__ unsigned int *)dev_priv->status_page;
        drm_device_dma_t *dma = dev->dma;
        drm_buf_t *buf;
        drm_mga_buf_priv_t *buf_priv;
        drm_mga_vertex_t vertex;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        copy_from_user_ret(&vertex, (drm_mga_vertex_t *)arg, sizeof(vertex),
                           -EFAULT);
@@ -823,25 +887,75 @@ int mga_vertex(struct inode *inode, struct file *filp,
        buf_priv->discard = vertex.discard;
    
        if (!mgaVerifyState(dev_priv)) {
-          if (vertex.discard) { 
-               buf_priv->my_freelist->age = dev_priv->last_sync_tag;
-               mga_freelist_put(dev, buf);
+          if (vertex.discard) {
+               if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv);
+               buf_priv->dispatched = 0;
+               mga_freelist_put(dev, buf);
           }
+          DRM_DEBUG("bad state\n");
           return -EINVAL;
        }
 
        mga_dma_dispatch_vertex(dev, buf);
 
        PRIMUPDATE(dev_priv);
+       mga_flush_write_combine();
        mga_dma_schedule(dev, 1);
-       sarea_priv->last_dispatch = status[1];
        return 0;
 }
 
+
+int mga_indices(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_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
+       drm_device_dma_t *dma = dev->dma;
+       drm_buf_t *buf;
+       drm_mga_buf_priv_t *buf_priv;
+       drm_mga_indices_t indices;
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       copy_from_user_ret(&indices, (drm_mga_indices_t *)arg, sizeof(indices),
+                          -EFAULT);
+   
+       if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("mga_indices called without lock held\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("mga_indices\n");
+
+       buf = dma->buflist[ indices.idx ];
+       buf_priv = buf->dev_private;
+
+       buf_priv->discard = indices.discard;
+   
+       if (!mgaVerifyState(dev_priv)) {
+          if (indices.discard) {
+               if(buf_priv->dispatched == 1) AGEBUF(dev_priv, buf_priv);
+               buf_priv->dispatched = 0;
+               mga_freelist_put(dev, buf);
+          }
+          return -EINVAL;
+       }
+
+       mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
+
+       PRIMUPDATE(dev_priv);
+       mga_flush_write_combine();
+       mga_dma_schedule(dev, 1);
+       return 0;
+}
+
+
+
 static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d)
 {
        int i;
        drm_buf_t *buf;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        for (i = d->granted_count; i < d->request_count; i++) {
                buf = mga_freelist_get(dev);
@@ -866,12 +980,9 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
        drm_file_t        *priv     = filp->private_data;
        drm_device_t      *dev      = priv->dev;
        drm_device_dma_t  *dma      = dev->dma;
-       drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       __volatile__ unsigned int *status = 
-               (__volatile__ unsigned int *)dev_priv->status_page;
        int               retcode   = 0;
        drm_dma_t         d;
+       DRM_DEBUG("%s\n", __FUNCTION__);
 
        copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
        DRM_DEBUG("%d %d: %d send, %d req\n",
@@ -907,6 +1018,5 @@ int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
        DRM_DEBUG("%d returning, granted = %d\n",
                  current->pid, d.granted_count);
        copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
-       sarea_priv->last_dispatch = status[1];
        return retcode;
 }
index 25e4cce..74ef83f 100644 (file)
@@ -341,13 +341,16 @@ typedef struct drm_agp_info {
 #define DRM_IOCTL_MGA_ILOAD   DRM_IOW( 0x43, drm_mga_iload_t)
 #define DRM_IOCTL_MGA_VERTEX  DRM_IOW( 0x44, drm_mga_vertex_t)
 #define DRM_IOCTL_MGA_FLUSH   DRM_IOW( 0x45, drm_lock_t )
+#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
 
 /* I810 specific ioctls */
 #define DRM_IOCTL_I810_INIT    DRM_IOW( 0x40, drm_i810_init_t)
 #define DRM_IOCTL_I810_VERTEX  DRM_IOW( 0x41, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_DMA     DRM_IOW( 0x42, drm_i810_general_t)
+#define DRM_IOCTL_I810_CLEAR   DRM_IOW( 0x42, drm_i810_clear_t)
 #define DRM_IOCTL_I810_FLUSH   DRM_IO ( 0x43)
 #define DRM_IOCTL_I810_GETAGE  DRM_IO ( 0x44)
+#define DRM_IOCTL_I810_GETBUF  DRM_IOW( 0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP    DRM_IO ( 0x46)
 
 /* Rage 128 specific ioctls */
 #define DRM_IOCTL_R128_INIT    DRM_IOW( 0x40, drm_r128_init_t)
index 25e4cce..74ef83f 100644 (file)
@@ -341,13 +341,16 @@ typedef struct drm_agp_info {
 #define DRM_IOCTL_MGA_ILOAD   DRM_IOW( 0x43, drm_mga_iload_t)
 #define DRM_IOCTL_MGA_VERTEX  DRM_IOW( 0x44, drm_mga_vertex_t)
 #define DRM_IOCTL_MGA_FLUSH   DRM_IOW( 0x45, drm_lock_t )
+#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
 
 /* I810 specific ioctls */
 #define DRM_IOCTL_I810_INIT    DRM_IOW( 0x40, drm_i810_init_t)
 #define DRM_IOCTL_I810_VERTEX  DRM_IOW( 0x41, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_DMA     DRM_IOW( 0x42, drm_i810_general_t)
+#define DRM_IOCTL_I810_CLEAR   DRM_IOW( 0x42, drm_i810_clear_t)
 #define DRM_IOCTL_I810_FLUSH   DRM_IO ( 0x43)
 #define DRM_IOCTL_I810_GETAGE  DRM_IO ( 0x44)
+#define DRM_IOCTL_I810_GETBUF  DRM_IOW( 0x45, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP    DRM_IO ( 0x46)
 
 /* Rage 128 specific ioctls */
 #define DRM_IOCTL_R128_INIT    DRM_IOW( 0x40, drm_r128_init_t)