VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / char / drm / i830_dma.c
1 /* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
2  * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
3  *
4  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6  * All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  * 
15  * The above copyright notice and this permission notice (including the next
16  * paragraph) shall be included in all copies or substantial portions of the
17  * Software.
18  * 
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  *
27  * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
28  *          Jeff Hartmann <jhartmann@valinux.com>
29  *          Keith Whitwell <keith@tungstengraphics.com>
30  *          Abraham vd Merwe <abraham@2d3d.co.za>
31  *
32  */
33
34 #include "i830.h"
35 #include "drmP.h"
36 #include "drm.h"
37 #include "i830_drm.h"
38 #include "i830_drv.h"
39 #include <linux/interrupt.h>    /* For task queue support */
40 #include <linux/pagemap.h>      /* For FASTCALL on unlock_page() */
41 #include <linux/delay.h>
42 #include <asm/uaccess.h>
43
44 #define I830_BUF_FREE           2
45 #define I830_BUF_CLIENT         1
46 #define I830_BUF_HARDWARE       0
47
48 #define I830_BUF_UNMAPPED 0
49 #define I830_BUF_MAPPED   1
50
51 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
52 #define down_write down
53 #define up_write up
54 #endif
55
56 static inline void i830_print_status_page(drm_device_t *dev)
57 {
58         drm_device_dma_t *dma = dev->dma;
59         drm_i830_private_t *dev_priv = dev->dev_private;
60         u32 *temp = dev_priv->hw_status_page;
61         int i;
62
63         DRM_DEBUG(  "hw_status: Interrupt Status : %x\n", temp[0]);
64         DRM_DEBUG(  "hw_status: LpRing Head ptr : %x\n", temp[1]);
65         DRM_DEBUG(  "hw_status: IRing Head ptr : %x\n", temp[2]);
66         DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
67         DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
68         for(i = 9; i < dma->buf_count + 9; i++) {
69                 DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 9, temp[i]);
70         }
71 }
72
73 static drm_buf_t *i830_freelist_get(drm_device_t *dev)
74 {
75         drm_device_dma_t *dma = dev->dma;
76         int              i;
77         int              used;
78    
79         /* Linear search might not be the best solution */
80
81         for (i = 0; i < dma->buf_count; i++) {
82                 drm_buf_t *buf = dma->buflist[ i ];
83                 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
84                 /* In use is already a pointer */
85                 used = cmpxchg(buf_priv->in_use, I830_BUF_FREE, 
86                                I830_BUF_CLIENT);
87                 if(used == I830_BUF_FREE) {
88                         return buf;
89                 }
90         }
91         return NULL;
92 }
93
94 /* This should only be called if the buffer is not sent to the hardware
95  * yet, the hardware updates in use for us once its on the ring buffer.
96  */
97
98 static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
99 {
100         drm_i830_buf_priv_t *buf_priv = buf->dev_private;
101         int used;
102    
103         /* In use is already a pointer */
104         used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
105         if(used != I830_BUF_CLIENT) {
106                 DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
107                 return -EINVAL;
108         }
109    
110         return 0;
111 }
112
113 static struct file_operations i830_buffer_fops = {
114         .open    = DRM(open),
115         .flush   = DRM(flush),
116         .release = DRM(release),
117         .ioctl   = DRM(ioctl),
118         .mmap    = i830_mmap_buffers,
119         .fasync  = DRM(fasync),
120 };
121
122 int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
123 {
124         drm_file_t          *priv         = filp->private_data;
125         drm_device_t        *dev;
126         drm_i830_private_t  *dev_priv;
127         drm_buf_t           *buf;
128         drm_i830_buf_priv_t *buf_priv;
129
130         lock_kernel();
131         dev      = priv->dev;
132         dev_priv = dev->dev_private;
133         buf      = dev_priv->mmap_buffer;
134         buf_priv = buf->dev_private;
135    
136         vma->vm_flags |= (VM_IO | VM_DONTCOPY);
137         vma->vm_file = filp;
138    
139         buf_priv->currently_mapped = I830_BUF_MAPPED;
140         unlock_kernel();
141
142         if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
143                              VM_OFFSET(vma),
144                              vma->vm_end - vma->vm_start,
145                              vma->vm_page_prot)) return -EAGAIN;
146         return 0;
147 }
148
149 static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
150 {
151         drm_file_t        *priv   = filp->private_data;
152         drm_device_t      *dev    = priv->dev;
153         drm_i830_buf_priv_t *buf_priv = buf->dev_private;
154         drm_i830_private_t *dev_priv = dev->dev_private;
155         struct file_operations *old_fops;
156         unsigned long virtual;
157         int retcode = 0;
158
159         if(buf_priv->currently_mapped == I830_BUF_MAPPED) return -EINVAL;
160
161         down_write( &current->mm->mmap_sem );
162         old_fops = filp->f_op;
163         filp->f_op = &i830_buffer_fops;
164         dev_priv->mmap_buffer = buf;
165         virtual = do_mmap(filp, 0, buf->total, PROT_READ|PROT_WRITE,
166                             MAP_SHARED, buf->bus_address);
167         dev_priv->mmap_buffer = NULL;
168         filp->f_op = old_fops;
169         if (IS_ERR((void *)virtual)) {          /* ugh */
170                 /* Real error */
171                 DRM_ERROR("mmap error\n");
172                 retcode = virtual;
173                 buf_priv->virtual = NULL;
174         } else {
175                 buf_priv->virtual = (void __user *)virtual;
176         }
177         up_write( &current->mm->mmap_sem );
178
179         return retcode;
180 }
181
182 static int i830_unmap_buffer(drm_buf_t *buf)
183 {
184         drm_i830_buf_priv_t *buf_priv = buf->dev_private;
185         int retcode = 0;
186
187         if(buf_priv->currently_mapped != I830_BUF_MAPPED) 
188                 return -EINVAL;
189
190         down_write(&current->mm->mmap_sem);
191         retcode = do_munmap(current->mm,
192                             (unsigned long)buf_priv->virtual,
193                             (size_t) buf->total);
194         up_write(&current->mm->mmap_sem);
195
196         buf_priv->currently_mapped = I830_BUF_UNMAPPED;
197         buf_priv->virtual = NULL;
198
199         return retcode;
200 }
201
202 static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d, 
203                                struct file *filp)
204 {
205         drm_buf_t         *buf;
206         drm_i830_buf_priv_t *buf_priv;
207         int retcode = 0;
208
209         buf = i830_freelist_get(dev);
210         if (!buf) {
211                 retcode = -ENOMEM;
212                 DRM_DEBUG("retcode=%d\n", retcode);
213                 return retcode;
214         }
215    
216         retcode = i830_map_buffer(buf, filp);
217         if(retcode) {
218                 i830_freelist_put(dev, buf);
219                 DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
220                 return retcode;
221         }
222         buf->filp = filp;
223         buf_priv = buf->dev_private;    
224         d->granted = 1;
225         d->request_idx = buf->idx;
226         d->request_size = buf->total;
227         d->virtual = buf_priv->virtual;
228
229         return retcode;
230 }
231
232 int i830_dma_cleanup(drm_device_t *dev)
233 {
234         drm_device_dma_t *dma = dev->dma;
235
236 #if __HAVE_IRQ
237         /* Make sure interrupts are disabled here because the uninstall ioctl
238          * may not have been called from userspace and after dev_private
239          * is freed, it's too late.
240          */
241         if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
242 #endif
243
244         if (dev->dev_private) {
245                 int i;
246                 drm_i830_private_t *dev_priv = 
247                         (drm_i830_private_t *) dev->dev_private;
248            
249                 if (dev_priv->ring.virtual_start) {
250                         DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
251                                          dev_priv->ring.Size, dev);
252                 }
253                 if (dev_priv->hw_status_page) {
254                         pci_free_consistent(dev->pdev, PAGE_SIZE,
255                                             dev_priv->hw_status_page,
256                                             dev_priv->dma_status_page);
257                         /* Need to rewrite hardware status page */
258                         I830_WRITE(0x02080, 0x1ffff000);
259                 }
260
261                 DRM(free)(dev->dev_private, sizeof(drm_i830_private_t), 
262                          DRM_MEM_DRIVER);
263                 dev->dev_private = NULL;
264
265                 for (i = 0; i < dma->buf_count; i++) {
266                         drm_buf_t *buf = dma->buflist[ i ];
267                         drm_i830_buf_priv_t *buf_priv = buf->dev_private;
268                         if ( buf_priv->kernel_virtual && buf->total )
269                                 DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev);
270                 }
271         }
272         return 0;
273 }
274
275 int i830_wait_ring(drm_device_t *dev, int n, const char *caller)
276 {
277         drm_i830_private_t *dev_priv = dev->dev_private;
278         drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
279         int iters = 0;
280         unsigned long end;
281         unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
282
283         end = jiffies + (HZ*3);
284         while (ring->space < n) {       
285                 ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
286                 ring->space = ring->head - (ring->tail+8);
287                 if (ring->space < 0) ring->space += ring->Size;
288            
289                 if (ring->head != last_head) {
290                         end = jiffies + (HZ*3);
291                         last_head = ring->head;
292                 }
293           
294                 iters++;
295                 if(time_before(end, jiffies)) {
296                         DRM_ERROR("space: %d wanted %d\n", ring->space, n);
297                         DRM_ERROR("lockup\n");
298                         goto out_wait_ring;
299                 }
300                 udelay(1);
301                 dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
302         }
303
304 out_wait_ring:   
305         return iters;
306 }
307
308 static void i830_kernel_lost_context(drm_device_t *dev)
309 {
310         drm_i830_private_t *dev_priv = dev->dev_private;
311         drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
312       
313         ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
314         ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
315         ring->space = ring->head - (ring->tail+8);
316         if (ring->space < 0) ring->space += ring->Size;
317
318         if (ring->head == ring->tail)
319                 dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
320 }
321
322 static int i830_freelist_init(drm_device_t *dev, drm_i830_private_t *dev_priv)
323 {
324         drm_device_dma_t *dma = dev->dma;
325         int my_idx = 36;
326         u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
327         int i;
328
329         if(dma->buf_count > 1019) {
330                 /* Not enough space in the status page for the freelist */
331                 return -EINVAL;
332         }
333
334         for (i = 0; i < dma->buf_count; i++) {
335                 drm_buf_t *buf = dma->buflist[ i ];
336                 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
337
338                 buf_priv->in_use = hw_status++;
339                 buf_priv->my_use_idx = my_idx;
340                 my_idx += 4;
341
342                 *buf_priv->in_use = I830_BUF_FREE;
343
344                 buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address, 
345                                                         buf->total, dev);
346         }
347         return 0;
348 }
349
350 static int i830_dma_initialize(drm_device_t *dev, 
351                                drm_i830_private_t *dev_priv,
352                                drm_i830_init_t *init)
353 {
354         struct list_head *list;
355
356         memset(dev_priv, 0, sizeof(drm_i830_private_t));
357
358         list_for_each(list, &dev->maplist->head) {
359                 drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
360                 if( r_list->map &&
361                     r_list->map->type == _DRM_SHM &&
362                     r_list->map->flags & _DRM_CONTAINS_LOCK ) {
363                         dev_priv->sarea_map = r_list->map;
364                         break;
365                 }
366         }
367
368         if(!dev_priv->sarea_map) {
369                 dev->dev_private = (void *)dev_priv;
370                 i830_dma_cleanup(dev);
371                 DRM_ERROR("can not find sarea!\n");
372                 return -EINVAL;
373         }
374         DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
375         if(!dev_priv->mmio_map) {
376                 dev->dev_private = (void *)dev_priv;
377                 i830_dma_cleanup(dev);
378                 DRM_ERROR("can not find mmio map!\n");
379                 return -EINVAL;
380         }
381         DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
382         if(!dev_priv->buffer_map) {
383                 dev->dev_private = (void *)dev_priv;
384                 i830_dma_cleanup(dev);
385                 DRM_ERROR("can not find dma buffer map!\n");
386                 return -EINVAL;
387         }
388
389         dev_priv->sarea_priv = (drm_i830_sarea_t *)
390                 ((u8 *)dev_priv->sarea_map->handle +
391                  init->sarea_priv_offset);
392
393         dev_priv->ring.Start = init->ring_start;
394         dev_priv->ring.End = init->ring_end;
395         dev_priv->ring.Size = init->ring_size;
396
397         dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base + 
398                                                     init->ring_start, 
399                                                     init->ring_size, dev);
400
401         if (dev_priv->ring.virtual_start == NULL) {
402                 dev->dev_private = (void *) dev_priv;
403                 i830_dma_cleanup(dev);
404                 DRM_ERROR("can not ioremap virtual address for"
405                           " ring buffer\n");
406                 return -ENOMEM;
407         }
408
409         dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
410    
411         dev_priv->w = init->w;
412         dev_priv->h = init->h;
413         dev_priv->pitch = init->pitch;
414         dev_priv->back_offset = init->back_offset;
415         dev_priv->depth_offset = init->depth_offset;
416         dev_priv->front_offset = init->front_offset;
417
418         dev_priv->front_di1 = init->front_offset | init->pitch_bits;
419         dev_priv->back_di1 = init->back_offset | init->pitch_bits;
420         dev_priv->zi1 = init->depth_offset | init->pitch_bits;
421
422         DRM_DEBUG("front_di1 %x\n",    dev_priv->front_di1);
423         DRM_DEBUG("back_offset %x\n", dev_priv->back_offset);
424         DRM_DEBUG("back_di1 %x\n",    dev_priv->back_di1);
425         DRM_DEBUG("pitch_bits %x\n",    init->pitch_bits);
426
427         dev_priv->cpp = init->cpp;
428         /* We are using separate values as placeholders for mechanisms for
429          * private backbuffer/depthbuffer usage.
430          */
431
432         dev_priv->back_pitch = init->back_pitch;
433         dev_priv->depth_pitch = init->depth_pitch;
434         dev_priv->do_boxes = 0;
435         dev_priv->use_mi_batchbuffer_start = 0;
436
437         /* Program Hardware Status Page */
438         dev_priv->hw_status_page =
439                 pci_alloc_consistent(dev->pdev, PAGE_SIZE,
440                                                 &dev_priv->dma_status_page);
441         if (!dev_priv->hw_status_page) {
442                 dev->dev_private = (void *)dev_priv;
443                 i830_dma_cleanup(dev);
444                 DRM_ERROR("Can not allocate hardware status page\n");
445                 return -ENOMEM;
446         }
447         memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
448         DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
449    
450         I830_WRITE(0x02080, dev_priv->dma_status_page);
451         DRM_DEBUG("Enabled hardware status page\n");
452    
453         /* Now we need to init our freelist */
454         if(i830_freelist_init(dev, dev_priv) != 0) {
455                 dev->dev_private = (void *)dev_priv;
456                 i830_dma_cleanup(dev);
457                 DRM_ERROR("Not enough space in the status page for"
458                           " the freelist\n");
459                 return -ENOMEM;
460         }
461         dev->dev_private = (void *)dev_priv;
462
463         return 0;
464 }
465
466 int i830_dma_init(struct inode *inode, struct file *filp,
467                   unsigned int cmd, unsigned long arg)
468 {
469         drm_file_t *priv = filp->private_data;
470         drm_device_t *dev = priv->dev;
471         drm_i830_private_t *dev_priv;
472         drm_i830_init_t init;
473         int retcode = 0;
474         
475         if (copy_from_user(&init, (void * __user) arg, sizeof(init)))
476                 return -EFAULT;
477         
478         switch(init.func) {
479                 case I830_INIT_DMA:
480                         dev_priv = DRM(alloc)(sizeof(drm_i830_private_t), 
481                                               DRM_MEM_DRIVER);
482                         if(dev_priv == NULL) return -ENOMEM;
483                         retcode = i830_dma_initialize(dev, dev_priv, &init);
484                 break;
485                 case I830_CLEANUP_DMA:
486                         retcode = i830_dma_cleanup(dev);
487                 break;
488                 default:
489                         retcode = -EINVAL;
490                 break;
491         }
492    
493         return retcode;
494 }
495
496 #define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
497 #define ST1_ENABLE               (1<<16)
498 #define ST1_MASK                 (0xffff)
499
500 /* Most efficient way to verify state for the i830 is as it is
501  * emitted.  Non-conformant state is silently dropped.
502  */
503 static void i830EmitContextVerified( drm_device_t *dev,
504                                      unsigned int *code )
505 {
506         drm_i830_private_t *dev_priv = dev->dev_private;
507         int i, j = 0;
508         unsigned int tmp;
509         RING_LOCALS;
510
511         BEGIN_LP_RING( I830_CTX_SETUP_SIZE + 4 );
512
513         for ( i = 0 ; i < I830_CTXREG_BLENDCOLR0 ; i++ ) {
514                 tmp = code[i];
515                 if ((tmp & (7<<29)) == CMD_3D &&
516                     (tmp & (0x1f<<24)) < (0x1d<<24)) {
517                         OUT_RING( tmp ); 
518                         j++;
519                 } else {
520                         DRM_ERROR("Skipping %d\n", i);
521                 }
522         }
523
524         OUT_RING( STATE3D_CONST_BLEND_COLOR_CMD ); 
525         OUT_RING( code[I830_CTXREG_BLENDCOLR] ); 
526         j += 2;
527
528         for ( i = I830_CTXREG_VF ; i < I830_CTXREG_MCSB0 ; i++ ) {
529                 tmp = code[i];
530                 if ((tmp & (7<<29)) == CMD_3D &&
531                     (tmp & (0x1f<<24)) < (0x1d<<24)) {
532                         OUT_RING( tmp ); 
533                         j++;
534                 } else {
535                         DRM_ERROR("Skipping %d\n", i);
536                 }
537         }
538
539         OUT_RING( STATE3D_MAP_COORD_SETBIND_CMD ); 
540         OUT_RING( code[I830_CTXREG_MCSB1] ); 
541         j += 2;
542
543         if (j & 1) 
544                 OUT_RING( 0 ); 
545
546         ADVANCE_LP_RING();
547 }
548
549 static void i830EmitTexVerified( drm_device_t *dev, unsigned int *code ) 
550 {
551         drm_i830_private_t *dev_priv = dev->dev_private;
552         int i, j = 0;
553         unsigned int tmp;
554         RING_LOCALS;
555
556         if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
557             (code[I830_TEXREG_MI0] & ~(0xf*LOAD_TEXTURE_MAP0)) == 
558             (STATE3D_LOAD_STATE_IMMEDIATE_2|4)) {
559
560                 BEGIN_LP_RING( I830_TEX_SETUP_SIZE );
561
562                 OUT_RING( code[I830_TEXREG_MI0] ); /* TM0LI */
563                 OUT_RING( code[I830_TEXREG_MI1] ); /* TM0S0 */
564                 OUT_RING( code[I830_TEXREG_MI2] ); /* TM0S1 */
565                 OUT_RING( code[I830_TEXREG_MI3] ); /* TM0S2 */
566                 OUT_RING( code[I830_TEXREG_MI4] ); /* TM0S3 */
567                 OUT_RING( code[I830_TEXREG_MI5] ); /* TM0S4 */
568                 
569                 for ( i = 6 ; i < I830_TEX_SETUP_SIZE ; i++ ) {
570                         tmp = code[i];
571                         OUT_RING( tmp ); 
572                         j++;
573                 } 
574
575                 if (j & 1) 
576                         OUT_RING( 0 ); 
577
578                 ADVANCE_LP_RING();
579         }
580         else
581                 printk("rejected packet %x\n", code[0]);
582 }
583
584 static void i830EmitTexBlendVerified( drm_device_t *dev, 
585                                       unsigned int *code,
586                                       unsigned int num)
587 {
588         drm_i830_private_t *dev_priv = dev->dev_private;
589         int i, j = 0;
590         unsigned int tmp;
591         RING_LOCALS;
592
593         if (!num)
594                 return;
595
596         BEGIN_LP_RING( num + 1 );
597
598         for ( i = 0 ; i < num ; i++ ) {
599                 tmp = code[i];
600                 OUT_RING( tmp );
601                 j++;
602         }
603
604         if (j & 1) 
605                 OUT_RING( 0 ); 
606
607         ADVANCE_LP_RING();
608 }
609
610 static void i830EmitTexPalette( drm_device_t *dev,
611                                 unsigned int *palette,
612                                 int number,
613                                 int is_shared )
614 {
615         drm_i830_private_t *dev_priv = dev->dev_private;
616         int i;
617         RING_LOCALS;
618
619         return;
620
621         BEGIN_LP_RING( 258 );
622
623         if(is_shared == 1) {
624                 OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
625                          MAP_PALETTE_NUM(0) |
626                          MAP_PALETTE_BOTH);
627         } else {
628                 OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
629         }
630         for(i = 0; i < 256; i++) {
631                 OUT_RING(palette[i]);
632         }
633         OUT_RING(0);
634         /* KW:  WHERE IS THE ADVANCE_LP_RING?  This is effectively a noop! 
635          */
636 }
637
638 /* Need to do some additional checking when setting the dest buffer.
639  */
640 static void i830EmitDestVerified( drm_device_t *dev, 
641                                   unsigned int *code ) 
642 {       
643         drm_i830_private_t *dev_priv = dev->dev_private;
644         unsigned int tmp;
645         RING_LOCALS;
646
647         BEGIN_LP_RING( I830_DEST_SETUP_SIZE + 10 );
648
649
650         tmp = code[I830_DESTREG_CBUFADDR];
651         if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
652                 if (((int)outring) & 8) {
653                         OUT_RING(0);
654                         OUT_RING(0);
655                 }
656
657                 OUT_RING( CMD_OP_DESTBUFFER_INFO );
658                 OUT_RING( BUF_3D_ID_COLOR_BACK | 
659                           BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
660                           BUF_3D_USE_FENCE);
661                 OUT_RING( tmp );
662                 OUT_RING( 0 );
663
664                 OUT_RING( CMD_OP_DESTBUFFER_INFO );
665                 OUT_RING( BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE | 
666                           BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
667                 OUT_RING( dev_priv->zi1 );
668                 OUT_RING( 0 );
669         } else {
670                 DRM_ERROR("bad di1 %x (allow %x or %x)\n",
671                           tmp, dev_priv->front_di1, dev_priv->back_di1);
672         }
673
674         /* invarient:
675          */
676
677
678         OUT_RING( GFX_OP_DESTBUFFER_VARS );
679         OUT_RING( code[I830_DESTREG_DV1] );
680
681         OUT_RING( GFX_OP_DRAWRECT_INFO );
682         OUT_RING( code[I830_DESTREG_DR1] );
683         OUT_RING( code[I830_DESTREG_DR2] );
684         OUT_RING( code[I830_DESTREG_DR3] );
685         OUT_RING( code[I830_DESTREG_DR4] );
686
687         /* Need to verify this */
688         tmp = code[I830_DESTREG_SENABLE];
689         if((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
690                 OUT_RING( tmp );
691         } else {
692                 DRM_ERROR("bad scissor enable\n");
693                 OUT_RING( 0 );
694         }
695
696         OUT_RING( GFX_OP_SCISSOR_RECT );
697         OUT_RING( code[I830_DESTREG_SR1] );
698         OUT_RING( code[I830_DESTREG_SR2] );
699         OUT_RING( 0 );
700
701         ADVANCE_LP_RING();
702 }
703
704 static void i830EmitStippleVerified( drm_device_t *dev, 
705                                      unsigned int *code ) 
706 {
707         drm_i830_private_t *dev_priv = dev->dev_private;
708         RING_LOCALS;
709
710         BEGIN_LP_RING( 2 );
711         OUT_RING( GFX_OP_STIPPLE );
712         OUT_RING( code[1] );
713         ADVANCE_LP_RING();      
714 }
715
716
717 static void i830EmitState( drm_device_t *dev )
718 {
719         drm_i830_private_t *dev_priv = dev->dev_private;
720         drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
721         unsigned int dirty = sarea_priv->dirty;
722
723         DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
724
725         if (dirty & I830_UPLOAD_BUFFERS) {
726                 i830EmitDestVerified( dev, sarea_priv->BufferState );
727                 sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
728         }
729
730         if (dirty & I830_UPLOAD_CTX) {
731                 i830EmitContextVerified( dev, sarea_priv->ContextState );
732                 sarea_priv->dirty &= ~I830_UPLOAD_CTX;
733         }
734
735         if (dirty & I830_UPLOAD_TEX0) {
736                 i830EmitTexVerified( dev, sarea_priv->TexState[0] );
737                 sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
738         }
739
740         if (dirty & I830_UPLOAD_TEX1) {
741                 i830EmitTexVerified( dev, sarea_priv->TexState[1] );
742                 sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
743         }
744
745         if (dirty & I830_UPLOAD_TEXBLEND0) {
746                 i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[0],
747                                 sarea_priv->TexBlendStateWordsUsed[0]);
748                 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
749         }
750
751         if (dirty & I830_UPLOAD_TEXBLEND1) {
752                 i830EmitTexBlendVerified( dev, sarea_priv->TexBlendState[1],
753                                 sarea_priv->TexBlendStateWordsUsed[1]);
754                 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
755         }
756
757         if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
758                 i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
759         } else {
760                 if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
761                         i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
762                         sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
763                 }
764                 if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
765                         i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
766                         sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
767                 }
768
769                 /* 1.3:
770                  */
771 #if 0
772                 if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) {
773                         i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0);
774                         sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
775                 }
776                 if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) {
777                         i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0);
778                         sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
779                 }
780 #endif
781         }
782
783         /* 1.3:
784          */
785         if (dirty & I830_UPLOAD_STIPPLE) {
786                 i830EmitStippleVerified( dev, 
787                                          sarea_priv->StippleState);
788                 sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
789         }
790
791         if (dirty & I830_UPLOAD_TEX2) {
792                 i830EmitTexVerified( dev, sarea_priv->TexState2 );
793                 sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
794         }
795
796         if (dirty & I830_UPLOAD_TEX3) {
797                 i830EmitTexVerified( dev, sarea_priv->TexState3 );
798                 sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
799         }
800
801
802         if (dirty & I830_UPLOAD_TEXBLEND2) {
803                 i830EmitTexBlendVerified( 
804                         dev, 
805                         sarea_priv->TexBlendState2,
806                         sarea_priv->TexBlendStateWordsUsed2);
807
808                 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
809         }
810
811         if (dirty & I830_UPLOAD_TEXBLEND3) {
812                 i830EmitTexBlendVerified( 
813                         dev, 
814                         sarea_priv->TexBlendState3,
815                         sarea_priv->TexBlendStateWordsUsed3);
816                 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
817         }
818 }
819
820 /* ================================================================
821  * Performance monitoring functions
822  */
823
824 static void i830_fill_box( drm_device_t *dev,
825                            int x, int y, int w, int h,
826                            int r, int g, int b )
827 {
828         drm_i830_private_t *dev_priv = dev->dev_private;
829         u32 color;
830         unsigned int BR13, CMD;
831         RING_LOCALS;
832
833         BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1<<24);
834         CMD = XY_COLOR_BLT_CMD;
835         x += dev_priv->sarea_priv->boxes[0].x1;
836         y += dev_priv->sarea_priv->boxes[0].y1;
837
838         if (dev_priv->cpp == 4) {
839                 BR13 |= (1<<25);
840                 CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
841                 color = (((0xff) << 24) | (r << 16) | (g <<  8) | b);   
842         } else {
843                 color = (((r & 0xf8) << 8) |
844                          ((g & 0xfc) << 3) |
845                          ((b & 0xf8) >> 3));
846         }
847
848         BEGIN_LP_RING( 6 );         
849         OUT_RING( CMD );
850         OUT_RING( BR13 );
851         OUT_RING( (y << 16) | x );
852         OUT_RING( ((y+h) << 16) | (x+w) );
853
854         if ( dev_priv->current_page == 1 ) { 
855                 OUT_RING( dev_priv->front_offset );
856         } else {         
857                 OUT_RING( dev_priv->back_offset );
858         } 
859
860         OUT_RING( color );
861         ADVANCE_LP_RING();
862 }
863
864 static void i830_cp_performance_boxes( drm_device_t *dev )
865 {
866         drm_i830_private_t *dev_priv = dev->dev_private;
867
868         /* Purple box for page flipping
869          */
870         if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP ) 
871                 i830_fill_box( dev, 4, 4, 8, 8, 255, 0, 255 );
872
873         /* Red box if we have to wait for idle at any point
874          */
875         if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT ) 
876                 i830_fill_box( dev, 16, 4, 8, 8, 255, 0, 0 );
877
878         /* Blue box: lost context?
879          */
880         if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT ) 
881                 i830_fill_box( dev, 28, 4, 8, 8, 0, 0, 255 );
882
883         /* Yellow box for texture swaps
884          */
885         if ( dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD ) 
886                 i830_fill_box( dev, 40, 4, 8, 8, 255, 255, 0 );
887
888         /* Green box if hardware never idles (as far as we can tell)
889          */
890         if ( !(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY) ) 
891                 i830_fill_box( dev, 64, 4, 8, 8, 0, 255, 0 );
892
893
894         /* Draw bars indicating number of buffers allocated 
895          * (not a great measure, easily confused)
896          */
897         if (dev_priv->dma_used) {
898                 int bar = dev_priv->dma_used / 10240;
899                 if (bar > 100) bar = 100;
900                 if (bar < 1) bar = 1;
901                 i830_fill_box( dev, 4, 16, bar, 4, 196, 128, 128 );
902                 dev_priv->dma_used = 0;
903         }
904
905         dev_priv->sarea_priv->perf_boxes = 0;
906 }
907
908 static void i830_dma_dispatch_clear( drm_device_t *dev, int flags, 
909                                     unsigned int clear_color,
910                                     unsigned int clear_zval,
911                                     unsigned int clear_depthmask)
912 {
913         drm_i830_private_t *dev_priv = dev->dev_private;
914         drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
915         int nbox = sarea_priv->nbox;
916         drm_clip_rect_t *pbox = sarea_priv->boxes;
917         int pitch = dev_priv->pitch;
918         int cpp = dev_priv->cpp;
919         int i;
920         unsigned int BR13, CMD, D_CMD;
921         RING_LOCALS;
922
923
924         if ( dev_priv->current_page == 1 ) {
925                 unsigned int tmp = flags;
926
927                 flags &= ~(I830_FRONT | I830_BACK);
928                 if ( tmp & I830_FRONT ) flags |= I830_BACK;
929                 if ( tmp & I830_BACK )  flags |= I830_FRONT;
930         }
931
932         i830_kernel_lost_context(dev);
933
934         switch(cpp) {
935         case 2: 
936                 BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
937                 D_CMD = CMD = XY_COLOR_BLT_CMD;
938                 break;
939         case 4:
940                 BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
941                 CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | 
942                        XY_COLOR_BLT_WRITE_RGB);
943                 D_CMD = XY_COLOR_BLT_CMD;
944                 if(clear_depthmask & 0x00ffffff)
945                         D_CMD |= XY_COLOR_BLT_WRITE_RGB;
946                 if(clear_depthmask & 0xff000000)
947                         D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
948                 break;
949         default:
950                 BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
951                 D_CMD = CMD = XY_COLOR_BLT_CMD;
952                 break;
953         }
954
955         if (nbox > I830_NR_SAREA_CLIPRECTS)
956                 nbox = I830_NR_SAREA_CLIPRECTS;
957
958         for (i = 0 ; i < nbox ; i++, pbox++) {
959                 if (pbox->x1 > pbox->x2 ||
960                     pbox->y1 > pbox->y2 ||
961                     pbox->x2 > dev_priv->w ||
962                     pbox->y2 > dev_priv->h)
963                         continue;
964
965                 if ( flags & I830_FRONT ) {         
966                         DRM_DEBUG("clear front\n");
967                         BEGIN_LP_RING( 6 );         
968                         OUT_RING( CMD );
969                         OUT_RING( BR13 );
970                         OUT_RING( (pbox->y1 << 16) | pbox->x1 );
971                         OUT_RING( (pbox->y2 << 16) | pbox->x2 );
972                         OUT_RING( dev_priv->front_offset );
973                         OUT_RING( clear_color );
974                         ADVANCE_LP_RING();
975                 }
976
977                 if ( flags & I830_BACK ) {
978                         DRM_DEBUG("clear back\n");
979                         BEGIN_LP_RING( 6 );         
980                         OUT_RING( CMD );
981                         OUT_RING( BR13 );
982                         OUT_RING( (pbox->y1 << 16) | pbox->x1 );
983                         OUT_RING( (pbox->y2 << 16) | pbox->x2 );
984                         OUT_RING( dev_priv->back_offset );
985                         OUT_RING( clear_color );
986                         ADVANCE_LP_RING();
987                 }
988
989                 if ( flags & I830_DEPTH ) {
990                         DRM_DEBUG("clear depth\n");
991                         BEGIN_LP_RING( 6 );
992                         OUT_RING( D_CMD );
993                         OUT_RING( BR13 );
994                         OUT_RING( (pbox->y1 << 16) | pbox->x1 );
995                         OUT_RING( (pbox->y2 << 16) | pbox->x2 );
996                         OUT_RING( dev_priv->depth_offset );
997                         OUT_RING( clear_zval );
998                         ADVANCE_LP_RING();
999                 }
1000         }
1001 }
1002
1003 static void i830_dma_dispatch_swap( drm_device_t *dev )
1004 {
1005         drm_i830_private_t *dev_priv = dev->dev_private;
1006         drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
1007         int nbox = sarea_priv->nbox;
1008         drm_clip_rect_t *pbox = sarea_priv->boxes;
1009         int pitch = dev_priv->pitch;
1010         int cpp = dev_priv->cpp;
1011         int i;
1012         unsigned int CMD, BR13;
1013         RING_LOCALS;
1014
1015         DRM_DEBUG("swapbuffers\n");
1016
1017         i830_kernel_lost_context(dev);
1018
1019         if (dev_priv->do_boxes)
1020                 i830_cp_performance_boxes( dev );
1021
1022         switch(cpp) {
1023         case 2: 
1024                 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
1025                 CMD = XY_SRC_COPY_BLT_CMD;
1026                 break;
1027         case 4:
1028                 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
1029                 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
1030                        XY_SRC_COPY_BLT_WRITE_RGB);
1031                 break;
1032         default:
1033                 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
1034                 CMD = XY_SRC_COPY_BLT_CMD;
1035                 break;
1036         }
1037
1038
1039         if (nbox > I830_NR_SAREA_CLIPRECTS)
1040                 nbox = I830_NR_SAREA_CLIPRECTS;
1041
1042         for (i = 0 ; i < nbox; i++, pbox++) 
1043         {
1044                 if (pbox->x1 > pbox->x2 ||
1045                     pbox->y1 > pbox->y2 ||
1046                     pbox->x2 > dev_priv->w ||
1047                     pbox->y2 > dev_priv->h)
1048                         continue;
1049  
1050                 DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
1051                           pbox->x1, pbox->y1,
1052                           pbox->x2, pbox->y2);
1053
1054                 BEGIN_LP_RING( 8 );
1055                 OUT_RING( CMD );
1056                 OUT_RING( BR13 );
1057                 OUT_RING( (pbox->y1 << 16) | pbox->x1 );
1058                 OUT_RING( (pbox->y2 << 16) | pbox->x2 );
1059
1060                 if (dev_priv->current_page == 0) 
1061                         OUT_RING( dev_priv->front_offset );
1062                 else
1063                         OUT_RING( dev_priv->back_offset );                      
1064
1065                 OUT_RING( (pbox->y1 << 16) | pbox->x1 );
1066                 OUT_RING( BR13 & 0xffff );
1067
1068                 if (dev_priv->current_page == 0) 
1069                         OUT_RING( dev_priv->back_offset );                      
1070                 else
1071                         OUT_RING( dev_priv->front_offset );
1072
1073                 ADVANCE_LP_RING();
1074         }
1075 }
1076
1077 static void i830_dma_dispatch_flip( drm_device_t *dev )
1078 {
1079         drm_i830_private_t *dev_priv = dev->dev_private;
1080         RING_LOCALS;
1081
1082         DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", 
1083                    __FUNCTION__, 
1084                    dev_priv->current_page,
1085                    dev_priv->sarea_priv->pf_current_page);
1086
1087         i830_kernel_lost_context(dev);
1088
1089         if (dev_priv->do_boxes) {
1090                 dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
1091                 i830_cp_performance_boxes( dev );
1092         }
1093
1094
1095         BEGIN_LP_RING( 2 );
1096         OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); 
1097         OUT_RING( 0 );
1098         ADVANCE_LP_RING();
1099
1100         BEGIN_LP_RING( 6 );
1101         OUT_RING( CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP );     
1102         OUT_RING( 0 );
1103         if ( dev_priv->current_page == 0 ) {
1104                 OUT_RING( dev_priv->back_offset );
1105                 dev_priv->current_page = 1;
1106         } else {
1107                 OUT_RING( dev_priv->front_offset );
1108                 dev_priv->current_page = 0;
1109         }
1110         OUT_RING(0);
1111         ADVANCE_LP_RING();
1112
1113
1114         BEGIN_LP_RING( 2 );
1115         OUT_RING( MI_WAIT_FOR_EVENT |
1116                   MI_WAIT_FOR_PLANE_A_FLIP );
1117         OUT_RING( 0 );
1118         ADVANCE_LP_RING();
1119         
1120
1121         dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
1122 }
1123
1124 static void i830_dma_dispatch_vertex(drm_device_t *dev, 
1125                                      drm_buf_t *buf,
1126                                      int discard,
1127                                      int used)
1128 {
1129         drm_i830_private_t *dev_priv = dev->dev_private;
1130         drm_i830_buf_priv_t *buf_priv = buf->dev_private;
1131         drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
1132         drm_clip_rect_t *box = sarea_priv->boxes;
1133         int nbox = sarea_priv->nbox;
1134         unsigned long address = (unsigned long)buf->bus_address;
1135         unsigned long start = address - dev->agp->base;     
1136         int i = 0, u;
1137         RING_LOCALS;
1138
1139         i830_kernel_lost_context(dev);
1140
1141         if (nbox > I830_NR_SAREA_CLIPRECTS) 
1142                 nbox = I830_NR_SAREA_CLIPRECTS;
1143
1144         if (discard) {
1145                 u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 
1146                             I830_BUF_HARDWARE);
1147                 if(u != I830_BUF_CLIENT) {
1148                         DRM_DEBUG("xxxx 2\n");
1149                 }
1150         }
1151
1152         if (used > 4*1023) 
1153                 used = 0;
1154
1155         if (sarea_priv->dirty)
1156            i830EmitState( dev );
1157
1158         DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", 
1159                   address, used, nbox);
1160
1161         dev_priv->counter++;
1162         DRM_DEBUG(  "dispatch counter : %ld\n", dev_priv->counter);
1163         DRM_DEBUG(  "i830_dma_dispatch\n");
1164         DRM_DEBUG(  "start : %lx\n", start);
1165         DRM_DEBUG(  "used : %d\n", used);
1166         DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
1167
1168         if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
1169                 u32  __user *vp = buf_priv->virtual;
1170
1171                 put_user( (GFX_OP_PRIMITIVE |
1172                          sarea_priv->vertex_prim |
1173                           ((used/4)-2)), &vp[0]);
1174
1175                 if (dev_priv->use_mi_batchbuffer_start) {
1176                         put_user(MI_BATCH_BUFFER_END, &vp[used/4]);
1177                         used += 4; 
1178                 }
1179                 
1180                 if (used & 4) {
1181                         put_user(0, &vp[used/4]);
1182                         used += 4;
1183                 }
1184
1185                 i830_unmap_buffer(buf);
1186         }
1187                    
1188         if (used) {
1189                 do {
1190                         if (i < nbox) {
1191                                 BEGIN_LP_RING(6);
1192                                 OUT_RING( GFX_OP_DRAWRECT_INFO );
1193                                 OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR1] );
1194                                 OUT_RING( box[i].x1 | (box[i].y1<<16) );
1195                                 OUT_RING( box[i].x2 | (box[i].y2<<16) );
1196                                 OUT_RING( sarea_priv->BufferState[I830_DESTREG_DR4] );
1197                                 OUT_RING( 0 );
1198                                 ADVANCE_LP_RING();
1199                         }
1200
1201                         if (dev_priv->use_mi_batchbuffer_start) {
1202                                 BEGIN_LP_RING(2);
1203                                 OUT_RING( MI_BATCH_BUFFER_START | (2<<6) );
1204                                 OUT_RING( start | MI_BATCH_NON_SECURE );
1205                                 ADVANCE_LP_RING();
1206                         } 
1207                         else {
1208                                 BEGIN_LP_RING(4);
1209                                 OUT_RING( MI_BATCH_BUFFER );
1210                                 OUT_RING( start | MI_BATCH_NON_SECURE );
1211                                 OUT_RING( start + used - 4 );
1212                                 OUT_RING( 0 );
1213                                 ADVANCE_LP_RING();
1214                         }
1215
1216                 } while (++i < nbox);
1217         }
1218
1219         if (discard) {
1220                 dev_priv->counter++;
1221
1222                 (void) cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
1223                                I830_BUF_HARDWARE);
1224
1225                 BEGIN_LP_RING(8);
1226                 OUT_RING( CMD_STORE_DWORD_IDX );
1227                 OUT_RING( 20 );
1228                 OUT_RING( dev_priv->counter );
1229                 OUT_RING( CMD_STORE_DWORD_IDX );
1230                 OUT_RING( buf_priv->my_use_idx );
1231                 OUT_RING( I830_BUF_FREE );
1232                 OUT_RING( CMD_REPORT_HEAD );
1233                 OUT_RING( 0 );
1234                 ADVANCE_LP_RING();
1235         }
1236 }
1237
1238
1239 void i830_dma_quiescent(drm_device_t *dev)
1240 {
1241         drm_i830_private_t *dev_priv = dev->dev_private;
1242         RING_LOCALS;
1243
1244         i830_kernel_lost_context(dev);
1245
1246         BEGIN_LP_RING(4);
1247         OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
1248         OUT_RING( CMD_REPORT_HEAD );
1249         OUT_RING( 0 );
1250         OUT_RING( 0 );
1251         ADVANCE_LP_RING();
1252
1253         i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
1254 }
1255
1256 static int i830_flush_queue(drm_device_t *dev)
1257 {
1258         drm_i830_private_t *dev_priv = dev->dev_private;
1259         drm_device_dma_t *dma = dev->dma;
1260         int i, ret = 0;
1261         RING_LOCALS;
1262         
1263         i830_kernel_lost_context(dev);
1264
1265         BEGIN_LP_RING(2);
1266         OUT_RING( CMD_REPORT_HEAD );
1267         OUT_RING( 0 );
1268         ADVANCE_LP_RING();
1269
1270         i830_wait_ring( dev, dev_priv->ring.Size - 8, __FUNCTION__ );
1271
1272         for (i = 0; i < dma->buf_count; i++) {
1273                 drm_buf_t *buf = dma->buflist[ i ];
1274                 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
1275            
1276                 int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE, 
1277                                    I830_BUF_FREE);
1278
1279                 if (used == I830_BUF_HARDWARE)
1280                         DRM_DEBUG("reclaimed from HARDWARE\n");
1281                 if (used == I830_BUF_CLIENT)
1282                         DRM_DEBUG("still on client\n");
1283         }
1284
1285         return ret;
1286 }
1287
1288 /* Must be called with the lock held */
1289 void i830_reclaim_buffers( struct file *filp )
1290 {
1291         drm_file_t    *priv   = filp->private_data;
1292         drm_device_t  *dev    = priv->dev;
1293         drm_device_dma_t *dma = dev->dma;
1294         int              i;
1295
1296         if (!dma) return;
1297         if (!dev->dev_private) return;
1298         if (!dma->buflist) return;
1299
1300         i830_flush_queue(dev);
1301
1302         for (i = 0; i < dma->buf_count; i++) {
1303                 drm_buf_t *buf = dma->buflist[ i ];
1304                 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
1305            
1306                 if (buf->filp == filp && buf_priv) {
1307                         int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 
1308                                            I830_BUF_FREE);
1309
1310                         if (used == I830_BUF_CLIENT)
1311                                 DRM_DEBUG("reclaimed from client\n");
1312                         if(buf_priv->currently_mapped == I830_BUF_MAPPED)
1313                                 buf_priv->currently_mapped = I830_BUF_UNMAPPED;
1314                 }
1315         }
1316 }
1317
1318 int i830_flush_ioctl(struct inode *inode, struct file *filp, 
1319                      unsigned int cmd, unsigned long arg)
1320 {
1321         drm_file_t        *priv   = filp->private_data;
1322         drm_device_t      *dev    = priv->dev;
1323
1324         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1325                 DRM_ERROR("i830_flush_ioctl called without lock held\n");
1326                 return -EINVAL;
1327         }
1328
1329         i830_flush_queue(dev);
1330         return 0;
1331 }
1332
1333 int i830_dma_vertex(struct inode *inode, struct file *filp,
1334                unsigned int cmd, unsigned long arg)
1335 {
1336         drm_file_t *priv = filp->private_data;
1337         drm_device_t *dev = priv->dev;
1338         drm_device_dma_t *dma = dev->dma;
1339         drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
1340         u32 *hw_status = dev_priv->hw_status_page;
1341         drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
1342                                         dev_priv->sarea_priv; 
1343         drm_i830_vertex_t vertex;
1344
1345         if (copy_from_user(&vertex, (drm_i830_vertex_t __user *)arg, sizeof(vertex)))
1346                 return -EFAULT;
1347
1348         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1349                 DRM_ERROR("i830_dma_vertex called without lock held\n");
1350                 return -EINVAL;
1351         }
1352
1353         DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n",
1354                   vertex.idx, vertex.used, vertex.discard);
1355
1356         if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
1357
1358         i830_dma_dispatch_vertex( dev, 
1359                                   dma->buflist[ vertex.idx ], 
1360                                   vertex.discard, vertex.used );
1361
1362         sarea_priv->last_enqueue = dev_priv->counter-1;
1363         sarea_priv->last_dispatch = (int) hw_status[5];
1364    
1365         return 0;
1366 }
1367
1368 int i830_clear_bufs(struct inode *inode, struct file *filp,
1369                    unsigned int cmd, unsigned long arg)
1370 {
1371         drm_file_t *priv = filp->private_data;
1372         drm_device_t *dev = priv->dev;
1373         drm_i830_clear_t clear;
1374
1375         if (copy_from_user(&clear, (drm_i830_clear_t __user *)arg, sizeof(clear)))
1376                 return -EFAULT;
1377    
1378         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1379                 DRM_ERROR("i830_clear_bufs called without lock held\n");
1380                 return -EINVAL;
1381         }
1382
1383         /* GH: Someone's doing nasty things... */
1384         if (!dev->dev_private) {
1385                 return -EINVAL;
1386         }
1387
1388         i830_dma_dispatch_clear( dev, clear.flags, 
1389                                  clear.clear_color, 
1390                                  clear.clear_depth,
1391                                  clear.clear_depthmask);
1392         return 0;
1393 }
1394
1395 int i830_swap_bufs(struct inode *inode, struct file *filp,
1396                   unsigned int cmd, unsigned long arg)
1397 {
1398         drm_file_t *priv = filp->private_data;
1399         drm_device_t *dev = priv->dev;
1400    
1401         DRM_DEBUG("i830_swap_bufs\n");
1402
1403         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1404                 DRM_ERROR("i830_swap_buf called without lock held\n");
1405                 return -EINVAL;
1406         }
1407
1408         i830_dma_dispatch_swap( dev );
1409         return 0;
1410 }
1411
1412
1413
1414 /* Not sure why this isn't set all the time:
1415  */ 
1416 static void i830_do_init_pageflip( drm_device_t *dev )
1417 {
1418         drm_i830_private_t *dev_priv = dev->dev_private;
1419
1420         DRM_DEBUG("%s\n", __FUNCTION__);
1421         dev_priv->page_flipping = 1;
1422         dev_priv->current_page = 0;
1423         dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
1424 }
1425
1426 int i830_do_cleanup_pageflip( drm_device_t *dev )
1427 {
1428         drm_i830_private_t *dev_priv = dev->dev_private;
1429
1430         DRM_DEBUG("%s\n", __FUNCTION__);
1431         if (dev_priv->current_page != 0)
1432                 i830_dma_dispatch_flip( dev );
1433
1434         dev_priv->page_flipping = 0;
1435         return 0;
1436 }
1437
1438 int i830_flip_bufs(struct inode *inode, struct file *filp,
1439                    unsigned int cmd, unsigned long arg)
1440 {
1441         drm_file_t *priv = filp->private_data;
1442         drm_device_t *dev = priv->dev;
1443         drm_i830_private_t *dev_priv = dev->dev_private;
1444
1445         DRM_DEBUG("%s\n", __FUNCTION__);
1446
1447         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1448                 DRM_ERROR("i830_flip_buf called without lock held\n");
1449                 return -EINVAL;
1450         }
1451
1452         if (!dev_priv->page_flipping) 
1453                 i830_do_init_pageflip( dev );
1454
1455         i830_dma_dispatch_flip( dev );
1456         return 0;
1457 }
1458
1459 int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
1460                 unsigned long arg)
1461 {
1462         drm_file_t        *priv     = filp->private_data;
1463         drm_device_t      *dev      = priv->dev;
1464         drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
1465         u32 *hw_status = dev_priv->hw_status_page;
1466         drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
1467                                         dev_priv->sarea_priv; 
1468
1469         sarea_priv->last_dispatch = (int) hw_status[5];
1470         return 0;
1471 }
1472
1473 int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
1474                 unsigned long arg)
1475 {
1476         drm_file_t        *priv     = filp->private_data;
1477         drm_device_t      *dev      = priv->dev;
1478         int               retcode   = 0;
1479         drm_i830_dma_t    d;
1480         drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
1481         u32 *hw_status = dev_priv->hw_status_page;
1482         drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
1483                                         dev_priv->sarea_priv; 
1484
1485         DRM_DEBUG("getbuf\n");
1486         if (copy_from_user(&d, (drm_i830_dma_t __user *)arg, sizeof(d)))
1487                 return -EFAULT;
1488    
1489         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1490                 DRM_ERROR("i830_dma called without lock held\n");
1491                 return -EINVAL;
1492         }
1493         
1494         d.granted = 0;
1495
1496         retcode = i830_dma_get_buffer(dev, &d, filp);
1497
1498         DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
1499                   current->pid, retcode, d.granted);
1500
1501         if (copy_to_user((drm_dma_t __user *)arg, &d, sizeof(d)))
1502                 return -EFAULT;
1503         sarea_priv->last_dispatch = (int) hw_status[5];
1504
1505         return retcode;
1506 }
1507
1508 int i830_copybuf(struct inode *inode,
1509                  struct file *filp, 
1510                  unsigned int cmd,
1511                  unsigned long arg)
1512 {
1513         /* Never copy - 2.4.x doesn't need it */
1514         return 0;
1515 }
1516
1517 int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
1518                 unsigned long arg)
1519 {
1520         return 0;
1521 }
1522
1523
1524
1525 int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
1526                       unsigned long arg )
1527 {
1528         drm_file_t        *priv     = filp->private_data;
1529         drm_device_t      *dev      = priv->dev;
1530         drm_i830_private_t *dev_priv = dev->dev_private;
1531         drm_i830_getparam_t param;
1532         int value;
1533
1534         if ( !dev_priv ) {
1535                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1536                 return -EINVAL;
1537         }
1538
1539         if (copy_from_user(&param, (drm_i830_getparam_t __user *)arg, sizeof(param) ))
1540                 return -EFAULT;
1541
1542         switch( param.param ) {
1543         case I830_PARAM_IRQ_ACTIVE:
1544                 value = dev->irq_enabled;
1545                 break;
1546         default:
1547                 return -EINVAL;
1548         }
1549
1550         if ( copy_to_user( param.value, &value, sizeof(int) ) ) {
1551                 DRM_ERROR( "copy_to_user\n" );
1552                 return -EFAULT;
1553         }
1554         
1555         return 0;
1556 }
1557
1558
1559 int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd,
1560                    unsigned long arg )
1561 {
1562         drm_file_t        *priv     = filp->private_data;
1563         drm_device_t      *dev      = priv->dev;
1564         drm_i830_private_t *dev_priv = dev->dev_private;
1565         drm_i830_setparam_t param;
1566
1567         if ( !dev_priv ) {
1568                 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1569                 return -EINVAL;
1570         }
1571
1572         if (copy_from_user(&param, (drm_i830_setparam_t __user *)arg, sizeof(param) ))
1573                 return -EFAULT;
1574
1575         switch( param.param ) {
1576         case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
1577                 dev_priv->use_mi_batchbuffer_start = param.value;
1578                 break;
1579         default:
1580                 return -EINVAL;
1581         }
1582
1583         return 0;
1584 }