linux-old/drivers/char/drm-4.0/i810_dma.c
<<
>>
Prefs
   1/* i810_dma.c -- DMA support for the i810 -*- 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 <keithw@valinux.com>
  30 *
  31 */
  32
  33#define __NO_VERSION__
  34#include "drmP.h"
  35#include "i810_drv.h"
  36#include <linux/interrupt.h>    /* For task queue support */
  37#include <linux/pagemap.h>
  38
  39/* in case we don't have a 2.3.99-pre6 kernel or later: */
  40#ifndef VM_DONTCOPY
  41#define VM_DONTCOPY 0
  42#endif
  43
  44#define I810_BUF_FREE           2
  45#define I810_BUF_CLIENT         1
  46#define I810_BUF_HARDWARE       0
  47
  48#define I810_BUF_UNMAPPED 0
  49#define I810_BUF_MAPPED   1
  50
  51#define I810_REG(reg)           2
  52#define I810_BASE(reg)          ((unsigned long) \
  53                                dev->maplist[I810_REG(reg)]->handle)
  54#define I810_ADDR(reg)          (I810_BASE(reg) + reg)
  55#define I810_DEREF(reg)         *(__volatile__ int *)I810_ADDR(reg)
  56#define I810_READ(reg)          I810_DEREF(reg)
  57#define I810_WRITE(reg,val)     do { I810_DEREF(reg) = val; } while (0)
  58#define I810_DEREF16(reg)       *(__volatile__ u16 *)I810_ADDR(reg)
  59#define I810_READ16(reg)        I810_DEREF16(reg)
  60#define I810_WRITE16(reg,val)   do { I810_DEREF16(reg) = val; } while (0)
  61
  62#define RING_LOCALS     unsigned int outring, ringmask; volatile char *virt;
  63
  64#define BEGIN_LP_RING(n) do {                           \
  65        if (I810_VERBOSE)                               \
  66                DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n",  \
  67                          n, __FUNCTION__);             \
  68        if (dev_priv->ring.space < n*4)                 \
  69                i810_wait_ring(dev, n*4);               \
  70        dev_priv->ring.space -= n*4;                    \
  71        outring = dev_priv->ring.tail;                  \
  72        ringmask = dev_priv->ring.tail_mask;            \
  73        virt = dev_priv->ring.virtual_start;            \
  74} while (0)
  75
  76#define ADVANCE_LP_RING() do {                                  \
  77        if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n");       \
  78        dev_priv->ring.tail = outring;                          \
  79        I810_WRITE(LP_RING + RING_TAIL, outring);               \
  80} while(0)
  81
  82#define OUT_RING(n) do {                                                \
  83        if (I810_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
  84        *(volatile unsigned int *)(virt + outring) = n;                 \
  85        outring += 4;                                                   \
  86        outring &= ringmask;                                            \
  87} while (0)
  88
  89static inline void i810_print_status_page(drm_device_t *dev)
  90{
  91        drm_device_dma_t *dma = dev->dma;
  92        drm_i810_private_t *dev_priv = dev->dev_private;
  93        u32 *temp = (u32 *)dev_priv->hw_status_page;
  94        int i;
  95
  96        DRM_DEBUG(  "hw_status: Interrupt Status : %x\n", temp[0]);
  97        DRM_DEBUG(  "hw_status: LpRing Head ptr : %x\n", temp[1]);
  98        DRM_DEBUG(  "hw_status: IRing Head ptr : %x\n", temp[2]);
  99        DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
 100        DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
 101        for(i = 6; i < dma->buf_count + 6; i++) {
 102                DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]);
 103        }
 104}
 105
 106static drm_buf_t *i810_freelist_get(drm_device_t *dev)
 107{
 108        drm_device_dma_t *dma = dev->dma;
 109        int              i;
 110        int              used;
 111   
 112        /* Linear search might not be the best solution */
 113
 114        for (i = 0; i < dma->buf_count; i++) {
 115                drm_buf_t *buf = dma->buflist[ i ];
 116                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 117                /* In use is already a pointer */
 118                used = cmpxchg(buf_priv->in_use, I810_BUF_FREE, 
 119                               I810_BUF_CLIENT);
 120                if(used == I810_BUF_FREE) {
 121                        return buf;
 122                }
 123        }
 124        return NULL;
 125}
 126
 127/* This should only be called if the buffer is not sent to the hardware
 128 * yet, the hardware updates in use for us once its on the ring buffer.
 129 */
 130
 131static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
 132{
 133        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 134        int used;
 135   
 136        /* In use is already a pointer */
 137        used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
 138        if(used != I810_BUF_CLIENT) {
 139                DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
 140                return -EINVAL;
 141        }
 142   
 143        return 0;
 144}
 145
 146static struct file_operations i810_buffer_fops = {
 147        open:    i810_open,
 148        flush:   drm_flush,
 149        release: i810_release,
 150        ioctl:   i810_ioctl,
 151        mmap:    i810_mmap_buffers,
 152        read:    drm_read,
 153        fasync:  drm_fasync,
 154        poll:    drm_poll,
 155};
 156
 157int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 158{
 159        drm_file_t          *priv         = filp->private_data;
 160        drm_device_t        *dev;
 161        drm_i810_private_t  *dev_priv;
 162        drm_buf_t           *buf;
 163        drm_i810_buf_priv_t *buf_priv;
 164
 165        lock_kernel();
 166        dev      = priv->dev;
 167        dev_priv = dev->dev_private;
 168        buf      = dev_priv->mmap_buffer;
 169        buf_priv = buf->dev_private;
 170   
 171        vma->vm_flags |= (VM_IO | VM_DONTCOPY);
 172        vma->vm_file = filp;
 173   
 174        buf_priv->currently_mapped = I810_BUF_MAPPED;
 175        unlock_kernel();
 176
 177        if (remap_page_range(vma->vm_start,
 178                             VM_OFFSET(vma),
 179                             vma->vm_end - vma->vm_start,
 180                             vma->vm_page_prot)) return -EAGAIN;
 181        return 0;
 182}
 183
 184static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
 185{
 186        drm_file_t        *priv   = filp->private_data;
 187        drm_device_t      *dev    = priv->dev;
 188        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 189        drm_i810_private_t *dev_priv = dev->dev_private;
 190        struct file_operations *old_fops;
 191        int retcode = 0;
 192
 193        if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
 194
 195        if(VM_DONTCOPY != 0) {
 196                down_write(&current->mm->mmap_sem);
 197                old_fops = filp->f_op;
 198                filp->f_op = &i810_buffer_fops;
 199                dev_priv->mmap_buffer = buf;
 200                buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, 
 201                                                    PROT_READ|PROT_WRITE,
 202                                                    MAP_SHARED, 
 203                                                    buf->bus_address);
 204                dev_priv->mmap_buffer = NULL;
 205                filp->f_op = old_fops;
 206                if ((unsigned long)buf_priv->virtual > -1024UL) {
 207                        /* Real error */
 208                        DRM_DEBUG("mmap error\n");
 209                        retcode = (signed int)buf_priv->virtual;
 210                        buf_priv->virtual = 0;
 211                }
 212                up_write(&current->mm->mmap_sem);
 213        } else {
 214                buf_priv->virtual = buf_priv->kernel_virtual;
 215                buf_priv->currently_mapped = I810_BUF_MAPPED;
 216        }
 217        return retcode;
 218}
 219
 220static int i810_unmap_buffer(drm_buf_t *buf)
 221{
 222        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 223        int retcode = 0;
 224
 225        if(VM_DONTCOPY != 0) {
 226                if(buf_priv->currently_mapped != I810_BUF_MAPPED) 
 227                        return -EINVAL;
 228                down_write(&current->mm->mmap_sem);
 229                retcode = do_munmap(current->mm,
 230                                    (unsigned long)buf_priv->virtual, 
 231                                    (size_t) buf->total);
 232                up_write(&current->mm->mmap_sem);
 233        }
 234        buf_priv->currently_mapped = I810_BUF_UNMAPPED;
 235        buf_priv->virtual = 0;
 236
 237        return retcode;
 238}
 239
 240static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, 
 241                               struct file *filp)
 242{
 243        drm_file_t        *priv   = filp->private_data;
 244        drm_buf_t         *buf;
 245        drm_i810_buf_priv_t *buf_priv;
 246        int retcode = 0;
 247
 248        buf = i810_freelist_get(dev);
 249        if (!buf) {
 250                retcode = -ENOMEM;
 251                DRM_DEBUG("retcode=%d\n", retcode);
 252                return retcode;
 253        }
 254   
 255        retcode = i810_map_buffer(buf, filp);
 256        if(retcode) {
 257                i810_freelist_put(dev, buf);
 258                DRM_DEBUG("mapbuf failed, retcode %d\n", retcode);
 259                return retcode;
 260        }
 261        buf->pid     = priv->pid;
 262        buf_priv = buf->dev_private;    
 263        d->granted = 1;
 264        d->request_idx = buf->idx;
 265        d->request_size = buf->total;
 266        d->virtual = buf_priv->virtual;
 267
 268        return retcode;
 269}
 270
 271static unsigned long i810_alloc_page(drm_device_t *dev)
 272{
 273        unsigned long address;
 274   
 275        address = __get_free_page(GFP_KERNEL);
 276        if(address == 0UL) 
 277                return 0;
 278
 279        get_page(virt_to_page(address));
 280        LockPage(virt_to_page(address));
 281   
 282        return address;
 283}
 284
 285static void i810_free_page(drm_device_t *dev, unsigned long page)
 286{
 287        struct page * p = virt_to_page(page);
 288        if(page == 0UL) 
 289                return;
 290        
 291        put_page(p);
 292        UnlockPage(p);
 293        free_page(page);
 294        return;
 295}
 296
 297static int i810_dma_cleanup(drm_device_t *dev)
 298{
 299        drm_device_dma_t *dma = dev->dma;
 300
 301        if(dev->dev_private) {
 302                int i;
 303                drm_i810_private_t *dev_priv = 
 304                        (drm_i810_private_t *) dev->dev_private;
 305           
 306                if(dev_priv->ring.virtual_start) {
 307                        drm_ioremapfree((void *) dev_priv->ring.virtual_start,
 308                                        dev_priv->ring.Size, dev);
 309                }
 310                if(dev_priv->hw_status_page != 0UL) {
 311                        i810_free_page(dev, dev_priv->hw_status_page);
 312                        /* Need to rewrite hardware status page */
 313                        I810_WRITE(0x02080, 0x1ffff000);
 314                }
 315                drm_free(dev->dev_private, sizeof(drm_i810_private_t), 
 316                         DRM_MEM_DRIVER);
 317                dev->dev_private = NULL;
 318
 319                for (i = 0; i < dma->buf_count; i++) {
 320                        drm_buf_t *buf = dma->buflist[ i ];
 321                        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 322                        drm_ioremapfree(buf_priv->kernel_virtual, buf->total, dev);
 323                }
 324        }
 325        return 0;
 326}
 327
 328static int i810_wait_ring(drm_device_t *dev, int n)
 329{
 330        drm_i810_private_t *dev_priv = dev->dev_private;
 331        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
 332        int iters = 0;
 333        unsigned long end;
 334        unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 335
 336        end = jiffies + (HZ*3);
 337        while (ring->space < n) {
 338                int i;
 339        
 340                ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 341                ring->space = ring->head - (ring->tail+8);
 342                if (ring->space < 0) ring->space += ring->Size;
 343           
 344                if (ring->head != last_head)
 345                   end = jiffies + (HZ*3);
 346          
 347                iters++;
 348                if((signed)(end - jiffies) <= 0) {
 349                        DRM_ERROR("space: %d wanted %d\n", ring->space, n);
 350                        DRM_ERROR("lockup\n");
 351                        goto out_wait_ring;
 352                }
 353
 354                for (i = 0 ; i < 2000 ; i++) ;
 355        }
 356
 357out_wait_ring:   
 358        return iters;
 359}
 360
 361static void i810_kernel_lost_context(drm_device_t *dev)
 362{
 363        drm_i810_private_t *dev_priv = dev->dev_private;
 364        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
 365      
 366        ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 367        ring->tail = I810_READ(LP_RING + RING_TAIL);
 368        ring->space = ring->head - (ring->tail+8);
 369        if (ring->space < 0) ring->space += ring->Size;
 370}
 371
 372static int i810_freelist_init(drm_device_t *dev)
 373{
 374        drm_device_dma_t *dma = dev->dma;
 375        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 376        int my_idx = 24;
 377        u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
 378        int i;
 379   
 380        if(dma->buf_count > 1019) {
 381                /* Not enough space in the status page for the freelist */
 382                return -EINVAL;
 383        }
 384
 385        for (i = 0; i < dma->buf_count; i++) {
 386                drm_buf_t *buf = dma->buflist[ i ];
 387                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 388           
 389                buf_priv->in_use = hw_status++;
 390                buf_priv->my_use_idx = my_idx;
 391                my_idx += 4;
 392
 393                *buf_priv->in_use = I810_BUF_FREE;
 394
 395                buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, 
 396                                                       buf->total, dev);
 397        }
 398        return 0;
 399}
 400
 401static int i810_dma_initialize(drm_device_t *dev, 
 402                               drm_i810_private_t *dev_priv,
 403                               drm_i810_init_t *init)
 404{
 405        drm_map_t *sarea_map;
 406
 407        dev->dev_private = (void *) dev_priv;
 408        memset(dev_priv, 0, sizeof(drm_i810_private_t));
 409
 410        if (init->ring_map_idx >= dev->map_count ||
 411            init->buffer_map_idx >= dev->map_count) {
 412                i810_dma_cleanup(dev);
 413                DRM_ERROR("ring_map or buffer_map are invalid\n");
 414                return -EINVAL;
 415        }
 416   
 417        dev_priv->ring_map_idx = init->ring_map_idx;
 418        dev_priv->buffer_map_idx = init->buffer_map_idx;
 419        sarea_map = dev->maplist[0];
 420        dev_priv->sarea_priv = (drm_i810_sarea_t *) 
 421                ((u8 *)sarea_map->handle + 
 422                 init->sarea_priv_offset);
 423
 424        atomic_set(&dev_priv->flush_done, 0);
 425        init_waitqueue_head(&dev_priv->flush_queue);
 426        
 427        dev_priv->ring.Start = init->ring_start;
 428        dev_priv->ring.End = init->ring_end;
 429        dev_priv->ring.Size = init->ring_size;
 430
 431        dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + 
 432                                                   init->ring_start, 
 433                                                   init->ring_size, dev);
 434
 435        dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
 436   
 437        if (dev_priv->ring.virtual_start == NULL) {
 438                i810_dma_cleanup(dev);
 439                DRM_ERROR("can not ioremap virtual address for"
 440                          " ring buffer\n");
 441                return -ENOMEM;
 442        }
 443
 444        dev_priv->w = init->w;
 445        dev_priv->h = init->h;
 446        dev_priv->pitch = init->pitch;
 447        dev_priv->back_offset = init->back_offset;
 448        dev_priv->depth_offset = init->depth_offset;
 449
 450        dev_priv->front_di1 = init->front_offset | init->pitch_bits;
 451        dev_priv->back_di1 = init->back_offset | init->pitch_bits;
 452        dev_priv->zi1 = init->depth_offset | init->pitch_bits;
 453        
 454   
 455        /* Program Hardware Status Page */
 456        dev_priv->hw_status_page = i810_alloc_page(dev);
 457        memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
 458        if(dev_priv->hw_status_page == 0UL) {
 459                i810_dma_cleanup(dev);
 460                DRM_ERROR("Can not allocate hardware status page\n");
 461                return -ENOMEM;
 462        }
 463        DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
 464   
 465        I810_WRITE(0x02080, virt_to_bus((void *)dev_priv->hw_status_page));
 466        DRM_DEBUG("Enabled hardware status page\n");
 467   
 468        /* Now we need to init our freelist */
 469        if(i810_freelist_init(dev) != 0) {
 470                i810_dma_cleanup(dev);
 471                DRM_ERROR("Not enough space in the status page for"
 472                          " the freelist\n");
 473                return -ENOMEM;
 474        }
 475        return 0;
 476}
 477
 478int i810_dma_init(struct inode *inode, struct file *filp,
 479                  unsigned int cmd, unsigned long arg)
 480{
 481        drm_file_t *priv = filp->private_data;
 482        drm_device_t *dev = priv->dev;
 483        drm_i810_private_t *dev_priv;
 484        drm_i810_init_t init;
 485        int retcode = 0;
 486        
 487        if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init)))
 488                return -EFAULT;
 489        
 490        switch(init.func) {
 491                case I810_INIT_DMA:
 492                        dev_priv = drm_alloc(sizeof(drm_i810_private_t), 
 493                                             DRM_MEM_DRIVER);
 494                        if(dev_priv == NULL) return -ENOMEM;
 495                        retcode = i810_dma_initialize(dev, dev_priv, &init);
 496                break;
 497                case I810_CLEANUP_DMA:
 498                        retcode = i810_dma_cleanup(dev);
 499                break;
 500                default:
 501                        retcode = -EINVAL;
 502                break;
 503        }
 504   
 505        return retcode;
 506}
 507
 508
 509
 510/* Most efficient way to verify state for the i810 is as it is
 511 * emitted.  Non-conformant state is silently dropped.
 512 *
 513 * Use 'volatile' & local var tmp to force the emitted values to be
 514 * identical to the verified ones.
 515 */
 516static void i810EmitContextVerified( drm_device_t *dev, 
 517                                     volatile unsigned int *code ) 
 518{       
 519        drm_i810_private_t *dev_priv = dev->dev_private;
 520        int i, j = 0;
 521        unsigned int tmp;
 522        RING_LOCALS;
 523
 524        BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
 525
 526        OUT_RING( GFX_OP_COLOR_FACTOR );
 527        OUT_RING( code[I810_CTXREG_CF1] );
 528
 529        OUT_RING( GFX_OP_STIPPLE );
 530        OUT_RING( code[I810_CTXREG_ST1] );
 531
 532        for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
 533                tmp = code[i];
 534
 535                if ((tmp & (7<<29)) == (3<<29) &&
 536                    (tmp & (0x1f<<24)) < (0x1d<<24)) 
 537                {
 538                        OUT_RING( tmp ); 
 539                        j++;
 540                } 
 541        }
 542
 543        if (j & 1) 
 544                OUT_RING( 0 ); 
 545
 546        ADVANCE_LP_RING();
 547}
 548
 549static void i810EmitTexVerified( drm_device_t *dev, 
 550                                 volatile unsigned int *code ) 
 551{       
 552        drm_i810_private_t *dev_priv = dev->dev_private;
 553        int i, j = 0;
 554        unsigned int tmp;
 555        RING_LOCALS;
 556
 557        BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
 558
 559        OUT_RING( GFX_OP_MAP_INFO );
 560        OUT_RING( code[I810_TEXREG_MI1] );
 561        OUT_RING( code[I810_TEXREG_MI2] );
 562        OUT_RING( code[I810_TEXREG_MI3] );
 563
 564        for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
 565                tmp = code[i];
 566
 567                if ((tmp & (7<<29)) == (3<<29) &&
 568                    (tmp & (0x1f<<24)) < (0x1d<<24)) 
 569                {
 570                        OUT_RING( tmp ); 
 571                        j++;
 572                }
 573        } 
 574                
 575        if (j & 1) 
 576                OUT_RING( 0 ); 
 577
 578        ADVANCE_LP_RING();
 579}
 580
 581
 582/* Need to do some additional checking when setting the dest buffer.
 583 */
 584static void i810EmitDestVerified( drm_device_t *dev, 
 585                                  volatile unsigned int *code ) 
 586{       
 587        drm_i810_private_t *dev_priv = dev->dev_private;
 588        unsigned int tmp;
 589        RING_LOCALS;
 590
 591        BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
 592
 593        tmp = code[I810_DESTREG_DI1];
 594        if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
 595                OUT_RING( CMD_OP_DESTBUFFER_INFO );
 596                OUT_RING( tmp );
 597        } else
 598           DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
 599                     tmp, dev_priv->front_di1, dev_priv->back_di1);
 600
 601        /* invarient:
 602         */
 603        OUT_RING( CMD_OP_Z_BUFFER_INFO );
 604        OUT_RING( dev_priv->zi1 );
 605
 606        OUT_RING( GFX_OP_DESTBUFFER_VARS );
 607        OUT_RING( code[I810_DESTREG_DV1] );
 608
 609        OUT_RING( GFX_OP_DRAWRECT_INFO );
 610        OUT_RING( code[I810_DESTREG_DR1] );
 611        OUT_RING( code[I810_DESTREG_DR2] );
 612        OUT_RING( code[I810_DESTREG_DR3] );
 613        OUT_RING( code[I810_DESTREG_DR4] );
 614        OUT_RING( 0 );
 615
 616        ADVANCE_LP_RING();
 617}
 618
 619
 620
 621static void i810EmitState( drm_device_t *dev )
 622{
 623        drm_i810_private_t *dev_priv = dev->dev_private;
 624        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 625        unsigned int dirty = sarea_priv->dirty;
 626
 627        if (dirty & I810_UPLOAD_BUFFERS) {
 628                i810EmitDestVerified( dev, sarea_priv->BufferState );
 629                sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
 630        }
 631
 632        if (dirty & I810_UPLOAD_CTX) {
 633                i810EmitContextVerified( dev, sarea_priv->ContextState );
 634                sarea_priv->dirty &= ~I810_UPLOAD_CTX;
 635        }
 636
 637        if (dirty & I810_UPLOAD_TEX0) {
 638                i810EmitTexVerified( dev, sarea_priv->TexState[0] );
 639                sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
 640        }
 641
 642        if (dirty & I810_UPLOAD_TEX1) {
 643                i810EmitTexVerified( dev, sarea_priv->TexState[1] );
 644                sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
 645        }
 646}
 647
 648
 649
 650/* need to verify 
 651 */
 652static void i810_dma_dispatch_clear( drm_device_t *dev, int flags, 
 653                                     unsigned int clear_color,
 654                                     unsigned int clear_zval )
 655{
 656        drm_i810_private_t *dev_priv = dev->dev_private;
 657        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 658        int nbox = sarea_priv->nbox;
 659        drm_clip_rect_t *pbox = sarea_priv->boxes;
 660        int pitch = dev_priv->pitch;
 661        int cpp = 2;
 662        int i;
 663        RING_LOCALS;
 664
 665        i810_kernel_lost_context(dev);
 666
 667        if (nbox > I810_NR_SAREA_CLIPRECTS)
 668                nbox = I810_NR_SAREA_CLIPRECTS;
 669
 670        for (i = 0 ; i < nbox ; i++, pbox++) {
 671                unsigned int x = pbox->x1;
 672                unsigned int y = pbox->y1;
 673                unsigned int width = (pbox->x2 - x) * cpp;
 674                unsigned int height = pbox->y2 - y;
 675                unsigned int start = y * pitch + x * cpp;
 676
 677                if (pbox->x1 > pbox->x2 ||
 678                    pbox->y1 > pbox->y2 ||
 679                    pbox->x2 > dev_priv->w ||
 680                    pbox->y2 > dev_priv->h)
 681                        continue;
 682
 683                if ( flags & I810_FRONT ) {         
 684                        DRM_DEBUG("clear front\n");
 685                        BEGIN_LP_RING( 6 );         
 686                        OUT_RING( BR00_BITBLT_CLIENT | 
 687                                  BR00_OP_COLOR_BLT | 0x3 );
 688                        OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
 689                        OUT_RING( (height << 16) | width );
 690                        OUT_RING( start );
 691                        OUT_RING( clear_color );
 692                        OUT_RING( 0 );
 693                        ADVANCE_LP_RING();
 694                }
 695
 696                if ( flags & I810_BACK ) {
 697                        DRM_DEBUG("clear back\n");
 698                        BEGIN_LP_RING( 6 );         
 699                        OUT_RING( BR00_BITBLT_CLIENT | 
 700                                  BR00_OP_COLOR_BLT | 0x3 );
 701                        OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
 702                        OUT_RING( (height << 16) | width );
 703                        OUT_RING( dev_priv->back_offset + start );
 704                        OUT_RING( clear_color );
 705                        OUT_RING( 0 );
 706                        ADVANCE_LP_RING();
 707                }
 708
 709                if ( flags & I810_DEPTH ) {
 710                        DRM_DEBUG("clear depth\n");
 711                        BEGIN_LP_RING( 6 );         
 712                        OUT_RING( BR00_BITBLT_CLIENT | 
 713                                  BR00_OP_COLOR_BLT | 0x3 );
 714                        OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
 715                        OUT_RING( (height << 16) | width );
 716                        OUT_RING( dev_priv->depth_offset + start );
 717                        OUT_RING( clear_zval );
 718                        OUT_RING( 0 );
 719                        ADVANCE_LP_RING();
 720                }
 721        }
 722}
 723
 724static void i810_dma_dispatch_swap( drm_device_t *dev )
 725{
 726        drm_i810_private_t *dev_priv = dev->dev_private;
 727        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 728        int nbox = sarea_priv->nbox;
 729        drm_clip_rect_t *pbox = sarea_priv->boxes;
 730        int pitch = dev_priv->pitch;
 731        int cpp = 2;
 732        int ofs = dev_priv->back_offset;
 733        int i;
 734        RING_LOCALS;
 735
 736        DRM_DEBUG("swapbuffers\n");
 737
 738        i810_kernel_lost_context(dev);
 739
 740        if (nbox > I810_NR_SAREA_CLIPRECTS)
 741                nbox = I810_NR_SAREA_CLIPRECTS;
 742
 743        for (i = 0 ; i < nbox; i++, pbox++) 
 744        {
 745                unsigned int w = pbox->x2 - pbox->x1;
 746                unsigned int h = pbox->y2 - pbox->y1;
 747                unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
 748                unsigned int start = ofs + dst;
 749
 750                if (pbox->x1 > pbox->x2 ||
 751                    pbox->y1 > pbox->y2 ||
 752                    pbox->x2 > dev_priv->w ||
 753                    pbox->y2 > dev_priv->h)
 754                        continue;
 755 
 756                DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
 757                          pbox[i].x1, pbox[i].y1,
 758                          pbox[i].x2, pbox[i].y2);
 759
 760                BEGIN_LP_RING( 6 );
 761                OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
 762                OUT_RING( pitch | (0xCC << 16));
 763                OUT_RING( (h << 16) | (w * cpp));
 764                OUT_RING( dst );
 765                OUT_RING( pitch );      
 766                OUT_RING( start );
 767                ADVANCE_LP_RING();
 768        }
 769}
 770
 771
 772static void i810_dma_dispatch_vertex(drm_device_t *dev, 
 773                                     drm_buf_t *buf,
 774                                     int discard,
 775                                     int used)
 776{
 777        drm_i810_private_t *dev_priv = dev->dev_private;
 778        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 779        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 780        drm_clip_rect_t *box = sarea_priv->boxes;
 781        int nbox = sarea_priv->nbox;
 782        unsigned long address = (unsigned long)buf->bus_address;
 783        unsigned long start = address - dev->agp->base;     
 784        int i = 0, u;
 785        RING_LOCALS;
 786
 787        i810_kernel_lost_context(dev);
 788
 789        if (nbox > I810_NR_SAREA_CLIPRECTS) 
 790                nbox = I810_NR_SAREA_CLIPRECTS;
 791
 792        if (discard) {
 793                u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, 
 794                            I810_BUF_HARDWARE);
 795                if(u != I810_BUF_CLIENT) {
 796                        DRM_DEBUG("xxxx 2\n");
 797                }
 798        }
 799
 800        if (used > 4*1024) 
 801                used = 0;
 802
 803        if (sarea_priv->dirty)
 804           i810EmitState( dev );
 805
 806        DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", 
 807                  address, used, nbox);
 808
 809        dev_priv->counter++;
 810        DRM_DEBUG(  "dispatch counter : %ld\n", dev_priv->counter);
 811        DRM_DEBUG(  "i810_dma_dispatch\n");
 812        DRM_DEBUG(  "start : %lx\n", start);
 813        DRM_DEBUG(  "used : %d\n", used);
 814        DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
 815
 816        if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
 817                *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE |
 818                                             sarea_priv->vertex_prim |
 819                                             ((used/4)-2));
 820                
 821                if (used & 4) {
 822                        *(u32 *)((u32)buf_priv->virtual + used) = 0;
 823                        used += 4;
 824                }
 825
 826                i810_unmap_buffer(buf);
 827        }
 828                   
 829        if (used) {
 830                do {
 831                        if (i < nbox) {
 832                                BEGIN_LP_RING(4);
 833                                OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | 
 834                                          SC_ENABLE );
 835                                OUT_RING( GFX_OP_SCISSOR_INFO );
 836                                OUT_RING( box[i].x1 | (box[i].y1<<16) );
 837                                OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
 838                                ADVANCE_LP_RING();
 839                        }
 840                        
 841                        BEGIN_LP_RING(4);
 842                        OUT_RING( CMD_OP_BATCH_BUFFER );
 843                        OUT_RING( start | BB1_PROTECTED );
 844                        OUT_RING( start + used - 4 );
 845                        OUT_RING( 0 );
 846                        ADVANCE_LP_RING();
 847                        
 848                } while (++i < nbox);
 849        }
 850
 851        BEGIN_LP_RING(10);
 852        OUT_RING( CMD_STORE_DWORD_IDX );
 853        OUT_RING( 20 );
 854        OUT_RING( dev_priv->counter );
 855        OUT_RING( 0 );
 856
 857        if (discard) {
 858                OUT_RING( CMD_STORE_DWORD_IDX );
 859                OUT_RING( buf_priv->my_use_idx );
 860                OUT_RING( I810_BUF_FREE );
 861                OUT_RING( 0 );
 862        }
 863
 864        OUT_RING( CMD_REPORT_HEAD );
 865        OUT_RING( 0 );
 866        ADVANCE_LP_RING();
 867}
 868
 869
 870/* Interrupts are only for flushing */
 871static void i810_dma_service(int irq, void *device, struct pt_regs *regs)
 872{
 873        drm_device_t     *dev = (drm_device_t *)device;
 874        u16 temp;
 875   
 876        atomic_inc(&dev->total_irq);
 877        temp = I810_READ16(I810REG_INT_IDENTITY_R);
 878        temp = temp & ~(0x6000);
 879        if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, 
 880                                   temp); /* Clear all interrupts */
 881        else
 882           return;
 883 
 884        queue_task(&dev->tq, &tq_immediate);
 885        mark_bh(IMMEDIATE_BH);
 886}
 887
 888static void i810_dma_task_queue(void *device)
 889{
 890        drm_device_t *dev = (drm_device_t *) device;
 891        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 892
 893        atomic_set(&dev_priv->flush_done, 1);
 894        wake_up_interruptible(&dev_priv->flush_queue);
 895}
 896
 897int i810_irq_install(drm_device_t *dev, int irq)
 898{
 899        int retcode;
 900        u16 temp;
 901   
 902        if (!irq)     return -EINVAL;
 903        
 904        down(&dev->struct_sem);
 905        if (dev->irq) {
 906                up(&dev->struct_sem);
 907                return -EBUSY;
 908        }
 909        dev->irq = irq;
 910        up(&dev->struct_sem);
 911        
 912        DRM_DEBUG(  "Interrupt Install : %d\n", irq);
 913        DRM_DEBUG("%d\n", irq);
 914
 915        dev->context_flag     = 0;
 916        dev->interrupt_flag   = 0;
 917        dev->dma_flag         = 0;
 918        
 919        dev->dma->next_buffer = NULL;
 920        dev->dma->next_queue  = NULL;
 921        dev->dma->this_buffer = NULL;
 922
 923        INIT_LIST_HEAD(&dev->tq.list);
 924        dev->tq.sync          = 0;
 925        dev->tq.routine       = i810_dma_task_queue;
 926        dev->tq.data          = dev;
 927
 928                                /* Before installing handler */
 929        temp = I810_READ16(I810REG_HWSTAM);
 930        temp = temp & 0x6000;
 931        I810_WRITE16(I810REG_HWSTAM, temp);
 932        
 933        temp = I810_READ16(I810REG_INT_MASK_R);
 934        temp = temp & 0x6000;
 935        I810_WRITE16(I810REG_INT_MASK_R, temp); /* Unmask interrupts */
 936        temp = I810_READ16(I810REG_INT_ENABLE_R);
 937        temp = temp & 0x6000;
 938        I810_WRITE16(I810REG_INT_ENABLE_R, temp); /* Disable all interrupts */
 939
 940                                /* Install handler */
 941        if ((retcode = request_irq(dev->irq,
 942                                   i810_dma_service,
 943                                   SA_SHIRQ,
 944                                   dev->devname,
 945                                   dev))) {
 946                down(&dev->struct_sem);
 947                dev->irq = 0;
 948                up(&dev->struct_sem);
 949                return retcode;
 950        }
 951        temp = I810_READ16(I810REG_INT_ENABLE_R);
 952        temp = temp & 0x6000;
 953        temp = temp | 0x0003;
 954        I810_WRITE16(I810REG_INT_ENABLE_R, 
 955                     temp); /* Enable bp & user interrupts */
 956        return 0;
 957}
 958
 959int i810_irq_uninstall(drm_device_t *dev)
 960{
 961        int irq;
 962        u16 temp;
 963
 964
 965/*      return 0; */
 966
 967        down(&dev->struct_sem);
 968        irq      = dev->irq;
 969        dev->irq = 0;
 970        up(&dev->struct_sem);
 971        
 972        if (!irq) return -EINVAL;
 973
 974        DRM_DEBUG(  "Interrupt UnInstall: %d\n", irq);  
 975        DRM_DEBUG("%d\n", irq);
 976   
 977        temp = I810_READ16(I810REG_INT_IDENTITY_R);
 978        temp = temp & ~(0x6000);
 979        if(temp != 0) I810_WRITE16(I810REG_INT_IDENTITY_R, 
 980                                   temp); /* Clear all interrupts */
 981   
 982        temp = I810_READ16(I810REG_INT_ENABLE_R);
 983        temp = temp & 0x6000;
 984        I810_WRITE16(I810REG_INT_ENABLE_R, 
 985                     temp);                     /* Disable all interrupts */
 986
 987        free_irq(irq, dev);
 988
 989        return 0;
 990}
 991
 992int i810_control(struct inode *inode, struct file *filp, unsigned int cmd,
 993                  unsigned long arg)
 994{
 995        drm_file_t      *priv   = filp->private_data;
 996        drm_device_t    *dev    = priv->dev;
 997        drm_control_t   ctl;
 998        int             retcode;
 999   
1000        DRM_DEBUG(  "i810_control\n");
1001
1002        if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
1003                return -EFAULT;
1004        
1005        switch (ctl.func) {
1006        case DRM_INST_HANDLER:
1007                if ((retcode = i810_irq_install(dev, ctl.irq)))
1008                        return retcode;
1009                break;
1010        case DRM_UNINST_HANDLER:
1011                if ((retcode = i810_irq_uninstall(dev)))
1012                        return retcode;
1013                break;
1014        default:
1015                return -EINVAL;
1016        }
1017        return 0;
1018}
1019
1020static inline void i810_dma_emit_flush(drm_device_t *dev)
1021{
1022        drm_i810_private_t *dev_priv = dev->dev_private;
1023        RING_LOCALS;
1024
1025        i810_kernel_lost_context(dev);
1026
1027        BEGIN_LP_RING(2);
1028        OUT_RING( CMD_REPORT_HEAD );
1029        OUT_RING( GFX_OP_USER_INTERRUPT );
1030        ADVANCE_LP_RING();
1031
1032/*      i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
1033/*      atomic_set(&dev_priv->flush_done, 1); */
1034/*      wake_up_interruptible(&dev_priv->flush_queue); */
1035}
1036
1037static inline void i810_dma_quiescent_emit(drm_device_t *dev)
1038{
1039        drm_i810_private_t *dev_priv = dev->dev_private;
1040        RING_LOCALS;
1041
1042        i810_kernel_lost_context(dev);
1043
1044        BEGIN_LP_RING(4);
1045        OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
1046        OUT_RING( CMD_REPORT_HEAD );
1047        OUT_RING( 0 );
1048        OUT_RING( GFX_OP_USER_INTERRUPT );
1049        ADVANCE_LP_RING();
1050
1051/*      i810_wait_ring( dev, dev_priv->ring.Size - 8 ); */
1052/*      atomic_set(&dev_priv->flush_done, 1); */
1053/*      wake_up_interruptible(&dev_priv->flush_queue); */
1054}
1055
1056static void i810_dma_quiescent(drm_device_t *dev)
1057{
1058        DECLARE_WAITQUEUE(entry, current);
1059        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1060        unsigned long end;      
1061
1062        if(dev_priv == NULL) {
1063                return;
1064        }
1065        atomic_set(&dev_priv->flush_done, 0);
1066        add_wait_queue(&dev_priv->flush_queue, &entry);
1067        end = jiffies + (HZ*3);
1068   
1069        for (;;) {
1070                current->state = TASK_INTERRUPTIBLE;
1071                i810_dma_quiescent_emit(dev);
1072                if (atomic_read(&dev_priv->flush_done) == 1) break;
1073                if((signed)(end - jiffies) <= 0) {
1074                        DRM_ERROR("lockup\n");
1075                        break;
1076                }          
1077                schedule_timeout(HZ*3);
1078                if (signal_pending(current)) {
1079                        break;
1080                }
1081        }
1082   
1083        current->state = TASK_RUNNING;
1084        remove_wait_queue(&dev_priv->flush_queue, &entry);
1085   
1086        return;
1087}
1088
1089static int i810_flush_queue(drm_device_t *dev)
1090{
1091        DECLARE_WAITQUEUE(entry, current);
1092        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1093        drm_device_dma_t *dma = dev->dma;
1094        unsigned long end;
1095        int i, ret = 0;      
1096
1097        if(dev_priv == NULL) {
1098                return 0;
1099        }
1100        atomic_set(&dev_priv->flush_done, 0);
1101        add_wait_queue(&dev_priv->flush_queue, &entry);
1102        end = jiffies + (HZ*3);
1103        for (;;) {
1104                current->state = TASK_INTERRUPTIBLE;
1105                i810_dma_emit_flush(dev);
1106                if (atomic_read(&dev_priv->flush_done) == 1) break;
1107                if((signed)(end - jiffies) <= 0) {
1108                        DRM_ERROR("lockup\n");
1109                        break;
1110                }          
1111                schedule_timeout(HZ*3);
1112                if (signal_pending(current)) {
1113                        ret = -EINTR; /* Can't restart */
1114                        break;
1115                }
1116        }
1117   
1118        current->state = TASK_RUNNING;
1119        remove_wait_queue(&dev_priv->flush_queue, &entry);
1120
1121
1122        for (i = 0; i < dma->buf_count; i++) {
1123                drm_buf_t *buf = dma->buflist[ i ];
1124                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
1125           
1126                int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE, 
1127                                   I810_BUF_FREE);
1128
1129                if (used == I810_BUF_HARDWARE)
1130                        DRM_DEBUG("reclaimed from HARDWARE\n");
1131                if (used == I810_BUF_CLIENT)
1132                        DRM_DEBUG("still on client HARDWARE\n");
1133        }
1134
1135        return ret;
1136}
1137
1138/* Must be called with the lock held */
1139void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
1140{
1141        drm_device_dma_t *dma = dev->dma;
1142        int              i;
1143
1144        if (!dma) return;
1145        if (!dev->dev_private) return;
1146        if (!dma->buflist) return;
1147
1148        i810_flush_queue(dev);
1149
1150        for (i = 0; i < dma->buf_count; i++) {
1151                drm_buf_t *buf = dma->buflist[ i ];
1152                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
1153           
1154                if (buf->pid == pid && buf_priv) {
1155                        int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, 
1156                                           I810_BUF_FREE);
1157
1158                        if (used == I810_BUF_CLIENT)
1159                                DRM_DEBUG("reclaimed from client\n");
1160                        if(buf_priv->currently_mapped == I810_BUF_MAPPED)
1161                                buf_priv->currently_mapped = I810_BUF_UNMAPPED;
1162                }
1163        }
1164}
1165
1166int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
1167               unsigned long arg)
1168{
1169        drm_file_t        *priv   = filp->private_data;
1170        drm_device_t      *dev    = priv->dev;
1171
1172        DECLARE_WAITQUEUE(entry, current);
1173        int               ret   = 0;
1174        drm_lock_t        lock;
1175
1176        if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
1177                return -EFAULT;
1178
1179        if (lock.context == DRM_KERNEL_CONTEXT) {
1180                DRM_ERROR("Process %d using kernel context %d\n",
1181                          current->pid, lock.context);
1182                return -EINVAL;
1183        }
1184   
1185        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
1186                  lock.context, current->pid, dev->lock.hw_lock->lock,
1187                  lock.flags);
1188
1189        if (lock.context < 0) {
1190                return -EINVAL;
1191        }
1192        /* Only one queue:
1193         */
1194
1195        if (!ret) {
1196                add_wait_queue(&dev->lock.lock_queue, &entry);
1197                for (;;) {
1198                        current->state = TASK_INTERRUPTIBLE;
1199                        if (!dev->lock.hw_lock) {
1200                                /* Device has been unregistered */
1201                                ret = -EINTR;
1202                                break;
1203                        }
1204                        if (drm_lock_take(&dev->lock.hw_lock->lock,
1205                                          lock.context)) {
1206                                dev->lock.pid       = current->pid;
1207                                dev->lock.lock_time = jiffies;
1208                                atomic_inc(&dev->total_locks);
1209                                break;  /* Got lock */
1210                        }
1211                        
1212                                /* Contention */
1213                        atomic_inc(&dev->total_sleeps);
1214                        DRM_DEBUG("Calling lock schedule\n");
1215                        schedule();
1216                        if (signal_pending(current)) {
1217                                ret = -ERESTARTSYS;
1218                                break;
1219                        }
1220                }
1221                current->state = TASK_RUNNING;
1222                remove_wait_queue(&dev->lock.lock_queue, &entry);
1223        }
1224        
1225        if (!ret) {
1226                sigemptyset(&dev->sigmask);
1227                sigaddset(&dev->sigmask, SIGSTOP);
1228                sigaddset(&dev->sigmask, SIGTSTP);
1229                sigaddset(&dev->sigmask, SIGTTIN);
1230                sigaddset(&dev->sigmask, SIGTTOU);
1231                dev->sigdata.context = lock.context;
1232                dev->sigdata.lock    = dev->lock.hw_lock;
1233                block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
1234
1235                if (lock.flags & _DRM_LOCK_QUIESCENT) {
1236                   DRM_DEBUG("_DRM_LOCK_QUIESCENT\n");
1237                   DRM_DEBUG("fred\n");
1238                   i810_dma_quiescent(dev);
1239                }
1240        }
1241        DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
1242        return ret;
1243}
1244
1245int i810_flush_ioctl(struct inode *inode, struct file *filp, 
1246                     unsigned int cmd, unsigned long arg)
1247{
1248        drm_file_t        *priv   = filp->private_data;
1249        drm_device_t      *dev    = priv->dev;
1250   
1251        DRM_DEBUG("i810_flush_ioctl\n");
1252        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1253                DRM_ERROR("i810_flush_ioctl called without lock held\n");
1254                return -EINVAL;
1255        }
1256
1257        i810_flush_queue(dev);
1258        return 0;
1259}
1260
1261
1262int i810_dma_vertex(struct inode *inode, struct file *filp,
1263               unsigned int cmd, unsigned long arg)
1264{
1265        drm_file_t *priv = filp->private_data;
1266        drm_device_t *dev = priv->dev;
1267        drm_device_dma_t *dma = dev->dma;
1268        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1269        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1270        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
1271                                        dev_priv->sarea_priv; 
1272        drm_i810_vertex_t vertex;
1273
1274        if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex)))
1275                return -EFAULT;
1276
1277        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1278                DRM_ERROR("i810_dma_vertex called without lock held\n");
1279                return -EINVAL;
1280        }
1281
1282        DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n",
1283                  vertex.idx, vertex.used, vertex.discard);
1284
1285        if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
1286
1287        i810_dma_dispatch_vertex( dev, 
1288                                  dma->buflist[ vertex.idx ], 
1289                                  vertex.discard, vertex.used );
1290
1291        atomic_add(vertex.used, &dma->total_bytes);
1292        atomic_inc(&dma->total_dmas);
1293        sarea_priv->last_enqueue = dev_priv->counter-1;
1294        sarea_priv->last_dispatch = (int) hw_status[5];
1295   
1296        return 0;
1297}
1298
1299
1300
1301int i810_clear_bufs(struct inode *inode, struct file *filp,
1302                   unsigned int cmd, unsigned long arg)
1303{
1304        drm_file_t *priv = filp->private_data;
1305        drm_device_t *dev = priv->dev;
1306        drm_i810_clear_t clear;
1307
1308        if (copy_from_user(&clear, (drm_i810_clear_t *)arg, sizeof(clear)))
1309                return -EFAULT;
1310   
1311        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1312                DRM_ERROR("i810_clear_bufs called without lock held\n");
1313                return -EINVAL;
1314        }
1315
1316        i810_dma_dispatch_clear( dev, clear.flags, 
1317                                 clear.clear_color, 
1318                                 clear.clear_depth );
1319        return 0;
1320}
1321
1322int i810_swap_bufs(struct inode *inode, struct file *filp,
1323                  unsigned int cmd, unsigned long arg)
1324{
1325        drm_file_t *priv = filp->private_data;
1326        drm_device_t *dev = priv->dev;
1327   
1328        DRM_DEBUG("i810_swap_bufs\n");
1329
1330        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1331                DRM_ERROR("i810_swap_buf called without lock held\n");
1332                return -EINVAL;
1333        }
1334
1335        i810_dma_dispatch_swap( dev );
1336        return 0;
1337}
1338
1339int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
1340                unsigned long arg)
1341{
1342        drm_file_t        *priv     = filp->private_data;
1343        drm_device_t      *dev      = priv->dev;
1344        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1345        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1346        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
1347                                        dev_priv->sarea_priv; 
1348
1349        sarea_priv->last_dispatch = (int) hw_status[5];
1350        return 0;
1351}
1352
1353int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
1354                unsigned long arg)
1355{
1356        drm_file_t        *priv     = filp->private_data;
1357        drm_device_t      *dev      = priv->dev;
1358        int               retcode   = 0;
1359        drm_i810_dma_t    d;
1360        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1361        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1362        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
1363                                        dev_priv->sarea_priv; 
1364
1365        DRM_DEBUG("getbuf\n");
1366        if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d)))
1367                return -EFAULT;
1368   
1369        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1370                DRM_ERROR("i810_dma called without lock held\n");
1371                return -EINVAL;
1372        }
1373        
1374        d.granted = 0;
1375
1376        retcode = i810_dma_get_buffer(dev, &d, filp);
1377
1378        DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
1379                  current->pid, retcode, d.granted);
1380
1381        if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
1382                return -EFAULT;
1383        sarea_priv->last_dispatch = (int) hw_status[5];
1384
1385        return retcode;
1386}
1387
1388int i810_copybuf(struct inode *inode, struct file *filp, unsigned int cmd,
1389                unsigned long arg)
1390{
1391        drm_file_t        *priv     = filp->private_data;
1392        drm_device_t      *dev      = priv->dev;
1393        drm_i810_copy_t   d;
1394        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1395        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1396        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) 
1397                                        dev_priv->sarea_priv; 
1398        drm_buf_t *buf;
1399        drm_i810_buf_priv_t *buf_priv;
1400        drm_device_dma_t *dma = dev->dma;
1401
1402        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1403                DRM_ERROR("i810_dma called without lock held\n");
1404                return -EINVAL;
1405        }
1406   
1407        if (copy_from_user(&d, (drm_i810_copy_t *)arg, sizeof(d)))
1408                return -EFAULT;
1409
1410        if(d.idx < 0 || d.idx > dma->buf_count) return -EINVAL;
1411        buf = dma->buflist[ d.idx ];
1412        buf_priv = buf->dev_private;
1413        if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM;
1414
1415        /* Stopping end users copying their data to the entire kernel
1416           is good.. */
1417        if (d.used < 0 || d.used > buf->total)
1418                return -EINVAL;
1419                
1420        if (copy_from_user(buf_priv->virtual, d.address, d.used))
1421                return -EFAULT;
1422
1423        sarea_priv->last_dispatch = (int) hw_status[5];
1424
1425        return 0;
1426}
1427
1428int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
1429                unsigned long arg)
1430{
1431        if(VM_DONTCOPY == 0) return 1;
1432        return 0;
1433}
1434
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.