linux-old/drivers/char/drm/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 <keith@tungstengraphics.com>
  30 *
  31 */
  32
  33#include <linux/config.h>
  34#include "i810.h"
  35#include "drmP.h"
  36#include "drm.h"
  37#include "i810_drm.h"
  38#include "i810_drv.h"
  39#include <linux/interrupt.h>    /* For task queue support */
  40#include <linux/delay.h>
  41
  42#define DO_MUNMAP(m, a, l)      do_munmap(m, a, l)
  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 RING_LOCALS     unsigned int outring, ringmask; volatile char *virt;
  52
  53#define BEGIN_LP_RING(n) do {                                           \
  54        if (0) DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", n, __FUNCTION__); \
  55        if (dev_priv->ring.space < n*4)                                 \
  56                i810_wait_ring(dev, n*4);                               \
  57        dev_priv->ring.space -= n*4;                                    \
  58        outring = dev_priv->ring.tail;                                  \
  59        ringmask = dev_priv->ring.tail_mask;                            \
  60        virt = dev_priv->ring.virtual_start;                            \
  61} while (0)
  62
  63#define ADVANCE_LP_RING() do {                          \
  64        if (0) DRM_DEBUG("ADVANCE_LP_RING\n");                  \
  65        dev_priv->ring.tail = outring;                  \
  66        I810_WRITE(LP_RING + RING_TAIL, outring);       \
  67} while(0)
  68
  69#define OUT_RING(n) do {                                \
  70        if (0) DRM_DEBUG("   OUT_RING %x\n", (int)(n)); \
  71        *(volatile unsigned int *)(virt + outring) = n; \
  72        outring += 4;                                   \
  73        outring &= ringmask;                            \
  74} while (0)
  75
  76static inline void i810_print_status_page(drm_device_t *dev)
  77{
  78        drm_device_dma_t *dma = dev->dma;
  79        drm_i810_private_t *dev_priv = dev->dev_private;
  80        u32 *temp = (u32 *)dev_priv->hw_status_page;
  81        int i;
  82
  83        DRM_DEBUG(  "hw_status: Interrupt Status : %x\n", temp[0]);
  84        DRM_DEBUG(  "hw_status: LpRing Head ptr : %x\n", temp[1]);
  85        DRM_DEBUG(  "hw_status: IRing Head ptr : %x\n", temp[2]);
  86        DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
  87        DRM_DEBUG(  "hw_status: Last Render: %x\n", temp[4]);
  88        DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
  89        for(i = 6; i < dma->buf_count + 6; i++) {
  90                DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 6, temp[i]);
  91        }
  92}
  93
  94static drm_buf_t *i810_freelist_get(drm_device_t *dev)
  95{
  96        drm_device_dma_t *dma = dev->dma;
  97        int              i;
  98        int              used;
  99
 100        /* Linear search might not be the best solution */
 101
 102        for (i = 0; i < dma->buf_count; i++) {
 103                drm_buf_t *buf = dma->buflist[ i ];
 104                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 105                /* In use is already a pointer */
 106                used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
 107                               I810_BUF_CLIENT);
 108                if(used == I810_BUF_FREE) {
 109                        return buf;
 110                }
 111        }
 112        return NULL;
 113}
 114
 115/* This should only be called if the buffer is not sent to the hardware
 116 * yet, the hardware updates in use for us once its on the ring buffer.
 117 */
 118
 119static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
 120{
 121        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 122        int used;
 123
 124        /* In use is already a pointer */
 125        used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
 126        if(used != I810_BUF_CLIENT) {
 127                DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
 128                return -EINVAL;
 129        }
 130
 131        return 0;
 132}
 133
 134static struct file_operations i810_buffer_fops = {
 135        .open    = DRM(open),
 136        .flush   = DRM(flush),
 137        .release = DRM(release),
 138        .ioctl   = DRM(ioctl),
 139        .mmap    = i810_mmap_buffers,
 140        .read    = DRM(read),
 141        .fasync  = DRM(fasync),
 142        .poll    = DRM(poll),
 143};
 144
 145int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 146{
 147        drm_file_t          *priv         = filp->private_data;
 148        drm_device_t        *dev;
 149        drm_i810_private_t  *dev_priv;
 150        drm_buf_t           *buf;
 151        drm_i810_buf_priv_t *buf_priv;
 152
 153        lock_kernel();
 154        dev      = priv->dev;
 155        dev_priv = dev->dev_private;
 156        buf      = dev_priv->mmap_buffer;
 157        buf_priv = buf->dev_private;
 158
 159        vma->vm_flags |= (VM_IO | VM_DONTCOPY);
 160        vma->vm_file = filp;
 161
 162        buf_priv->currently_mapped = I810_BUF_MAPPED;
 163        unlock_kernel();
 164
 165        if (remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
 166                             VM_OFFSET(vma),
 167                             vma->vm_end - vma->vm_start,
 168                             vma->vm_page_prot)) return -EAGAIN;
 169        return 0;
 170}
 171
 172static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
 173{
 174        drm_file_t        *priv   = filp->private_data;
 175        drm_device_t      *dev    = priv->dev;
 176        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 177        drm_i810_private_t *dev_priv = dev->dev_private;
 178        struct file_operations *old_fops;
 179        int retcode = 0;
 180
 181        if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
 182
 183
 184
 185
 186        down_write( &current->mm->mmap_sem );
 187
 188        old_fops = filp->f_op;
 189        filp->f_op = &i810_buffer_fops;
 190        dev_priv->mmap_buffer = buf;
 191        buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
 192                                            PROT_READ|PROT_WRITE,
 193                                            MAP_SHARED,
 194                                            buf->bus_address);
 195        dev_priv->mmap_buffer = NULL;
 196        filp->f_op = old_fops;
 197        if ((unsigned long)buf_priv->virtual > -1024UL) {
 198                /* Real error */
 199                DRM_DEBUG("mmap error\n");
 200                retcode = (signed int)buf_priv->virtual;
 201                buf_priv->virtual = 0;
 202        }
 203
 204
 205
 206        up_write( &current->mm->mmap_sem );
 207
 208        return retcode;
 209}
 210
 211static int i810_unmap_buffer(drm_buf_t *buf)
 212{
 213        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 214        int retcode = 0;
 215
 216        if(buf_priv->currently_mapped != I810_BUF_MAPPED)
 217                return -EINVAL;
 218
 219
 220
 221        down_write( &current->mm->mmap_sem );
 222
 223        retcode = DO_MUNMAP(current->mm,
 224                            (unsigned long)buf_priv->virtual,
 225                            (size_t) buf->total);
 226
 227
 228
 229        up_write( &current->mm->mmap_sem );
 230
 231        buf_priv->currently_mapped = I810_BUF_UNMAPPED;
 232        buf_priv->virtual = 0;
 233
 234        return retcode;
 235}
 236
 237static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
 238                               struct file *filp)
 239{
 240        drm_file_t        *priv   = filp->private_data;
 241        drm_buf_t         *buf;
 242        drm_i810_buf_priv_t *buf_priv;
 243        int retcode = 0;
 244
 245        buf = i810_freelist_get(dev);
 246        if (!buf) {
 247                retcode = -ENOMEM;
 248                DRM_DEBUG("retcode=%d\n", retcode);
 249                return retcode;
 250        }
 251
 252        retcode = i810_map_buffer(buf, filp);
 253        if(retcode) {
 254                i810_freelist_put(dev, buf);
 255                DRM_DEBUG("mapbuf failed, retcode %d\n", retcode);
 256                return retcode;
 257        }
 258        buf->pid     = priv->pid;
 259        buf_priv = buf->dev_private;
 260        d->granted = 1;
 261        d->request_idx = buf->idx;
 262        d->request_size = buf->total;
 263        d->virtual = buf_priv->virtual;
 264
 265        return retcode;
 266}
 267
 268static int i810_dma_cleanup(drm_device_t *dev)
 269{
 270        drm_device_dma_t *dma = dev->dma;
 271
 272        if(dev->dev_private) {
 273                int i;
 274                drm_i810_private_t *dev_priv =
 275                        (drm_i810_private_t *) dev->dev_private;
 276
 277                if(dev_priv->ring.virtual_start) {
 278                        DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
 279                                         dev_priv->ring.Size, dev);
 280                }
 281                if(dev_priv->hw_status_page != 0UL) {
 282                        pci_free_consistent(dev->pdev, PAGE_SIZE,
 283                                            (void *)dev_priv->hw_status_page,
 284                                            dev_priv->dma_status_page);
 285                        /* Need to rewrite hardware status page */
 286                        I810_WRITE(0x02080, 0x1ffff000);
 287                }
 288                DRM(free)(dev->dev_private, sizeof(drm_i810_private_t),
 289                         DRM_MEM_DRIVER);
 290                dev->dev_private = NULL;
 291
 292                for (i = 0; i < dma->buf_count; i++) {
 293                        drm_buf_t *buf = dma->buflist[ i ];
 294                        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 295                        DRM(ioremapfree)(buf_priv->kernel_virtual, buf->total, dev);
 296                }
 297        }
 298        return 0;
 299}
 300
 301static int i810_wait_ring(drm_device_t *dev, int n)
 302{
 303        drm_i810_private_t *dev_priv = dev->dev_private;
 304        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
 305        int iters = 0;
 306        unsigned long end;
 307        unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 308
 309        end = jiffies + (HZ*3);
 310        while (ring->space < n) {
 311                ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 312                ring->space = ring->head - (ring->tail+8);
 313                if (ring->space < 0) ring->space += ring->Size;
 314
 315                if (ring->head != last_head)
 316                   end = jiffies + (HZ*3);
 317
 318                iters++;
 319                if(time_before(end, jiffies)) {
 320                        DRM_ERROR("space: %d wanted %d\n", ring->space, n);
 321                        DRM_ERROR("lockup\n");
 322                        goto out_wait_ring;
 323                }
 324                udelay(1);
 325        }
 326
 327out_wait_ring:
 328        return iters;
 329}
 330
 331static void i810_kernel_lost_context(drm_device_t *dev)
 332{
 333        drm_i810_private_t *dev_priv = dev->dev_private;
 334        drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
 335
 336        ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 337        ring->tail = I810_READ(LP_RING + RING_TAIL);
 338        ring->space = ring->head - (ring->tail+8);
 339        if (ring->space < 0) ring->space += ring->Size;
 340}
 341
 342static int i810_freelist_init(drm_device_t *dev, drm_i810_private_t *dev_priv)
 343{
 344        drm_device_dma_t *dma = dev->dma;
 345        int my_idx = 24;
 346        u32 *hw_status = (u32 *)(dev_priv->hw_status_page + my_idx);
 347        int i;
 348
 349        if(dma->buf_count > 1019) {
 350                /* Not enough space in the status page for the freelist */
 351                return -EINVAL;
 352        }
 353
 354        for (i = 0; i < dma->buf_count; i++) {
 355                drm_buf_t *buf = dma->buflist[ i ];
 356                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 357
 358                buf_priv->in_use = hw_status++;
 359                buf_priv->my_use_idx = my_idx;
 360                my_idx += 4;
 361
 362                *buf_priv->in_use = I810_BUF_FREE;
 363
 364                buf_priv->kernel_virtual = DRM(ioremap)(buf->bus_address,
 365                                                        buf->total, dev);
 366        }
 367        return 0;
 368}
 369
 370static int i810_dma_initialize(drm_device_t *dev,
 371                               drm_i810_private_t *dev_priv,
 372                               drm_i810_init_t *init)
 373{
 374        struct list_head *list;
 375
 376        memset(dev_priv, 0, sizeof(drm_i810_private_t));
 377
 378        list_for_each(list, &dev->maplist->head) {
 379                drm_map_list_t *r_list = (drm_map_list_t *)list;
 380                if( r_list->map &&
 381                    r_list->map->type == _DRM_SHM &&
 382                    r_list->map->flags & _DRM_CONTAINS_LOCK ) {
 383                        dev_priv->sarea_map = r_list->map;
 384                        break;
 385                }
 386        }
 387        if(!dev_priv->sarea_map) {
 388                dev->dev_private = (void *)dev_priv;
 389                i810_dma_cleanup(dev);
 390                DRM_ERROR("can not find sarea!\n");
 391                return -EINVAL;
 392        }
 393        DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
 394        if(!dev_priv->mmio_map) {
 395                dev->dev_private = (void *)dev_priv;
 396                i810_dma_cleanup(dev);
 397                DRM_ERROR("can not find mmio map!\n");
 398                return -EINVAL;
 399        }
 400        DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
 401        if(!dev_priv->buffer_map) {
 402                dev->dev_private = (void *)dev_priv;
 403                i810_dma_cleanup(dev);
 404                DRM_ERROR("can not find dma buffer map!\n");
 405                return -EINVAL;
 406        }
 407
 408        dev_priv->sarea_priv = (drm_i810_sarea_t *)
 409                ((u8 *)dev_priv->sarea_map->handle +
 410                 init->sarea_priv_offset);
 411
 412        dev_priv->ring.Start = init->ring_start;
 413        dev_priv->ring.End = init->ring_end;
 414        dev_priv->ring.Size = init->ring_size;
 415
 416        dev_priv->ring.virtual_start = DRM(ioremap)(dev->agp->base +
 417                                                    init->ring_start,
 418                                                    init->ring_size, dev);
 419
 420        if (dev_priv->ring.virtual_start == NULL) {
 421                dev->dev_private = (void *) dev_priv;
 422                i810_dma_cleanup(dev);
 423                DRM_ERROR("can not ioremap virtual address for"
 424                          " ring buffer\n");
 425                return -ENOMEM;
 426        }
 427
 428        dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
 429
 430        dev_priv->w = init->w;
 431        dev_priv->h = init->h;
 432        dev_priv->pitch = init->pitch;
 433        dev_priv->back_offset = init->back_offset;
 434        dev_priv->depth_offset = init->depth_offset;
 435
 436        dev_priv->overlay_offset = init->overlay_offset;
 437        dev_priv->overlay_physical = init->overlay_physical;
 438
 439        dev_priv->front_di1 = init->front_offset | init->pitch_bits;
 440        dev_priv->back_di1 = init->back_offset | init->pitch_bits;
 441        dev_priv->zi1 = init->depth_offset | init->pitch_bits;
 442
 443        /* Program Hardware Status Page */
 444        dev_priv->hw_status_page =
 445                (unsigned long) pci_alloc_consistent(dev->pdev, PAGE_SIZE,
 446                                                &dev_priv->dma_status_page);
 447        if(dev_priv->hw_status_page == 0UL) {
 448                dev->dev_private = (void *)dev_priv;
 449                i810_dma_cleanup(dev);
 450                DRM_ERROR("Can not allocate hardware status page\n");
 451                return -ENOMEM;
 452        }
 453        memset((void *) dev_priv->hw_status_page, 0, PAGE_SIZE);
 454        DRM_DEBUG("hw status page @ %lx\n", dev_priv->hw_status_page);
 455
 456        I810_WRITE(0x02080, dev_priv->dma_status_page);
 457        DRM_DEBUG("Enabled hardware status page\n");
 458
 459        /* Now we need to init our freelist */
 460        if(i810_freelist_init(dev, dev_priv) != 0) {
 461                dev->dev_private = (void *)dev_priv;
 462                i810_dma_cleanup(dev);
 463                DRM_ERROR("Not enough space in the status page for"
 464                          " the freelist\n");
 465                return -ENOMEM;
 466        }
 467        dev->dev_private = (void *)dev_priv;
 468
 469        return 0;
 470}
 471
 472#ifdef CONFIG_DRM_I810_XFREE_41
 473int xfreeversion = 41;
 474#else
 475int xfreeversion = -1;
 476#endif
 477
 478MODULE_PARM(xfreeversion, "i");
 479MODULE_PARM_DESC(xfreeversion, "The version of XFree86 that needs to be supported");
 480
 481int i810_dma_init(struct inode *inode, struct file *filp,
 482                  unsigned int cmd, unsigned long arg)
 483{
 484        drm_file_t *priv = filp->private_data;
 485        drm_device_t *dev = priv->dev;
 486        drm_i810_private_t *dev_priv;
 487        drm_i810_init_t init;
 488        int retcode = 0;
 489
 490        if (copy_from_user(&init, (drm_i810_init_t *)arg, sizeof(init)))
 491                return -EFAULT;
 492                
 493        if ((xfreeversion == 41) ||
 494            ((xfreeversion == -1) && (init.pitch == 0))) {
 495                /*
 496                 * Ok we have a problem here.  Someone decided it was
 497                 * funny to add two fields in the middle of the
 498                 * drm_i810_init_it structure in the transition between
 499                 * XFree86 4.1.0 and 4.2.0.
 500                 *
 501                 * The code below tries to fix this ABI breakage up as
 502                 * good as possible, unfortionatly it's impossible to
 503                 * autodetect which interface the user wants, hence the
 504                 * module parameter -- Arjan
 505                 */
 506
 507                init.pitch_bits = init.h;
 508                init.pitch = init.w;
 509                init.h = init.overlay_physical;
 510                init.w = init.overlay_offset;
 511                init.overlay_physical = 0;
 512                init.overlay_offset = 0;
 513        }
 514
 515        switch(init.func) {
 516                case I810_INIT_DMA:
 517                        dev_priv = DRM(alloc)(sizeof(drm_i810_private_t),
 518                                             DRM_MEM_DRIVER);
 519                        if(dev_priv == NULL) return -ENOMEM;
 520                        retcode = i810_dma_initialize(dev, dev_priv, &init);
 521                break;
 522                case I810_CLEANUP_DMA:
 523                        retcode = i810_dma_cleanup(dev);
 524                break;
 525                default:
 526                        retcode = -EINVAL;
 527                break;
 528        }
 529
 530        return retcode;
 531}
 532
 533
 534
 535/* Most efficient way to verify state for the i810 is as it is
 536 * emitted.  Non-conformant state is silently dropped.
 537 */
 538static void i810EmitContextVerified( drm_device_t *dev,
 539                                     unsigned int *code )
 540{
 541        drm_i810_private_t *dev_priv = dev->dev_private;
 542        int i, j = 0;
 543        RING_LOCALS;
 544
 545        BEGIN_LP_RING( I810_CTX_SETUP_SIZE );
 546
 547        OUT_RING( GFX_OP_COLOR_FACTOR );
 548        OUT_RING( code[I810_CTXREG_CF1] );
 549
 550        OUT_RING( GFX_OP_STIPPLE );
 551        OUT_RING( code[I810_CTXREG_ST1] );
 552
 553        for ( i = 4 ; i < I810_CTX_SETUP_SIZE ; i++ ) {
 554                if ((code[i] & (7<<29)) == (3<<29) &&
 555                    (code[i] & (0x1f<<24)) < (0x1d<<24))
 556                {
 557                        OUT_RING( code[i] );
 558                        j++;
 559                }
 560                else printk("constext state dropped!!!\n");
 561        }
 562
 563        if (j & 1)
 564                OUT_RING( 0 );
 565
 566        ADVANCE_LP_RING();
 567}
 568
 569static void i810EmitTexVerified( drm_device_t *dev,
 570                                 volatile unsigned int *code )
 571{
 572        drm_i810_private_t *dev_priv = dev->dev_private;
 573        int i, j = 0;
 574        RING_LOCALS;
 575
 576        BEGIN_LP_RING( I810_TEX_SETUP_SIZE );
 577
 578        OUT_RING( GFX_OP_MAP_INFO );
 579        OUT_RING( code[I810_TEXREG_MI1] );
 580        OUT_RING( code[I810_TEXREG_MI2] );
 581        OUT_RING( code[I810_TEXREG_MI3] );
 582
 583        for ( i = 4 ; i < I810_TEX_SETUP_SIZE ; i++ ) {
 584
 585                if ((code[i] & (7<<29)) == (3<<29) &&
 586                    (code[i] & (0x1f<<24)) < (0x1d<<24))
 587                {
 588                        OUT_RING( code[i] );
 589                        j++;
 590                }
 591                else printk("texture state dropped!!!\n");
 592        }
 593
 594        if (j & 1)
 595                OUT_RING( 0 );
 596
 597        ADVANCE_LP_RING();
 598}
 599
 600
 601/* Need to do some additional checking when setting the dest buffer.
 602 */
 603static void i810EmitDestVerified( drm_device_t *dev,
 604                                  volatile unsigned int *code )
 605{
 606        drm_i810_private_t *dev_priv = dev->dev_private;
 607        unsigned int tmp;
 608        RING_LOCALS;
 609
 610        BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
 611
 612        tmp = code[I810_DESTREG_DI1];
 613        if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
 614                OUT_RING( CMD_OP_DESTBUFFER_INFO );
 615                OUT_RING( tmp );
 616        } 
 617        else
 618           printk("buffer state dropped\n");
 619
 620        /* invarient:
 621         */
 622        OUT_RING( CMD_OP_Z_BUFFER_INFO );
 623        OUT_RING( dev_priv->zi1 );
 624
 625        OUT_RING( GFX_OP_DESTBUFFER_VARS );
 626        OUT_RING( code[I810_DESTREG_DV1] );
 627
 628        OUT_RING( GFX_OP_DRAWRECT_INFO );
 629        OUT_RING( code[I810_DESTREG_DR1] );
 630        OUT_RING( code[I810_DESTREG_DR2] );
 631        OUT_RING( code[I810_DESTREG_DR3] );
 632        OUT_RING( code[I810_DESTREG_DR4] );
 633        OUT_RING( 0 );
 634
 635        ADVANCE_LP_RING();
 636}
 637
 638
 639
 640static void i810EmitState( drm_device_t *dev )
 641{
 642        drm_i810_private_t *dev_priv = dev->dev_private;
 643        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 644        unsigned int dirty = sarea_priv->dirty;
 645
 646        if (dirty & I810_UPLOAD_BUFFERS) {
 647                i810EmitDestVerified( dev, sarea_priv->BufferState );
 648                sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
 649        }
 650
 651        if (dirty & I810_UPLOAD_CTX) {
 652                i810EmitContextVerified( dev, sarea_priv->ContextState );
 653                sarea_priv->dirty &= ~I810_UPLOAD_CTX;
 654        }
 655
 656        if (dirty & I810_UPLOAD_TEX0) {
 657                i810EmitTexVerified( dev, sarea_priv->TexState[0] );
 658                sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
 659        }
 660
 661        if (dirty & I810_UPLOAD_TEX1) {
 662                i810EmitTexVerified( dev, sarea_priv->TexState[1] );
 663                sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
 664        }
 665}
 666
 667
 668
 669/* need to verify
 670 */
 671static void i810_dma_dispatch_clear( drm_device_t *dev, int flags,
 672                                     unsigned int clear_color,
 673                                     unsigned int clear_zval )
 674{
 675        drm_i810_private_t *dev_priv = dev->dev_private;
 676        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 677        int nbox = sarea_priv->nbox;
 678        drm_clip_rect_t *pbox = sarea_priv->boxes;
 679        int pitch = dev_priv->pitch;
 680        int cpp = 2;
 681        int i;
 682        RING_LOCALS;
 683
 684        i810_kernel_lost_context(dev);
 685
 686        if (nbox > I810_NR_SAREA_CLIPRECTS)
 687                nbox = I810_NR_SAREA_CLIPRECTS;
 688
 689        for (i = 0 ; i < nbox ; i++, pbox++) {
 690                unsigned int x = pbox->x1;
 691                unsigned int y = pbox->y1;
 692                unsigned int width = (pbox->x2 - x) * cpp;
 693                unsigned int height = pbox->y2 - y;
 694                unsigned int start = y * pitch + x * cpp;
 695
 696                if (pbox->x1 > pbox->x2 ||
 697                    pbox->y1 > pbox->y2 ||
 698                    pbox->x2 > dev_priv->w ||
 699                    pbox->y2 > dev_priv->h)
 700                        continue;
 701
 702                if ( flags & I810_FRONT ) {
 703                        BEGIN_LP_RING( 6 );
 704                        OUT_RING( BR00_BITBLT_CLIENT |
 705                                  BR00_OP_COLOR_BLT | 0x3 );
 706                        OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
 707                        OUT_RING( (height << 16) | width );
 708                        OUT_RING( start );
 709                        OUT_RING( clear_color );
 710                        OUT_RING( 0 );
 711                        ADVANCE_LP_RING();
 712                }
 713
 714                if ( flags & I810_BACK ) {
 715                        BEGIN_LP_RING( 6 );
 716                        OUT_RING( BR00_BITBLT_CLIENT |
 717                                  BR00_OP_COLOR_BLT | 0x3 );
 718                        OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
 719                        OUT_RING( (height << 16) | width );
 720                        OUT_RING( dev_priv->back_offset + start );
 721                        OUT_RING( clear_color );
 722                        OUT_RING( 0 );
 723                        ADVANCE_LP_RING();
 724                }
 725
 726                if ( flags & I810_DEPTH ) {
 727                        BEGIN_LP_RING( 6 );
 728                        OUT_RING( BR00_BITBLT_CLIENT |
 729                                  BR00_OP_COLOR_BLT | 0x3 );
 730                        OUT_RING( BR13_SOLID_PATTERN | (0xF0 << 16) | pitch );
 731                        OUT_RING( (height << 16) | width );
 732                        OUT_RING( dev_priv->depth_offset + start );
 733                        OUT_RING( clear_zval );
 734                        OUT_RING( 0 );
 735                        ADVANCE_LP_RING();
 736                }
 737        }
 738}
 739
 740static void i810_dma_dispatch_swap( drm_device_t *dev )
 741{
 742        drm_i810_private_t *dev_priv = dev->dev_private;
 743        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 744        int nbox = sarea_priv->nbox;
 745        drm_clip_rect_t *pbox = sarea_priv->boxes;
 746        int pitch = dev_priv->pitch;
 747        int cpp = 2;
 748        int ofs = dev_priv->back_offset;
 749        int i;
 750        RING_LOCALS;
 751
 752        i810_kernel_lost_context(dev);
 753
 754        if (nbox > I810_NR_SAREA_CLIPRECTS)
 755                nbox = I810_NR_SAREA_CLIPRECTS;
 756
 757        for (i = 0 ; i < nbox; i++, pbox++)
 758        {
 759                unsigned int w = pbox->x2 - pbox->x1;
 760                unsigned int h = pbox->y2 - pbox->y1;
 761                unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
 762                unsigned int start = ofs + dst;
 763
 764                if (pbox->x1 > pbox->x2 ||
 765                    pbox->y1 > pbox->y2 ||
 766                    pbox->x2 > dev_priv->w ||
 767                    pbox->y2 > dev_priv->h)
 768                        continue;
 769
 770                BEGIN_LP_RING( 6 );
 771                OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
 772                OUT_RING( pitch | (0xCC << 16));
 773                OUT_RING( (h << 16) | (w * cpp));
 774                OUT_RING( dst );
 775                OUT_RING( pitch );
 776                OUT_RING( start );
 777                ADVANCE_LP_RING();
 778        }
 779}
 780
 781
 782static void i810_dma_dispatch_vertex(drm_device_t *dev,
 783                                     drm_buf_t *buf,
 784                                     int discard,
 785                                     int used)
 786{
 787        drm_i810_private_t *dev_priv = dev->dev_private;
 788        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 789        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 790        drm_clip_rect_t *box = sarea_priv->boxes;
 791        int nbox = sarea_priv->nbox;
 792        unsigned long address = (unsigned long)buf->bus_address;
 793        unsigned long start = address - dev->agp->base;
 794        int i = 0;
 795        RING_LOCALS;
 796
 797        i810_kernel_lost_context(dev);
 798
 799        if (nbox > I810_NR_SAREA_CLIPRECTS)
 800                nbox = I810_NR_SAREA_CLIPRECTS;
 801
 802        if (used > 4*1024)
 803                used = 0;
 804
 805        if (sarea_priv->dirty)
 806           i810EmitState( dev );
 807
 808        if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
 809                unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
 810
 811                *(u32 *)buf_priv->virtual = (GFX_OP_PRIMITIVE | prim | 
 812                                             ((used/4)-2));
 813
 814                if (used & 4) {
 815                        *(u32 *)((u32)buf_priv->virtual + used) = 0;
 816                        used += 4;
 817                }
 818
 819                i810_unmap_buffer(buf);
 820        }
 821
 822        if (used) {
 823                do {
 824                        if (i < nbox) {
 825                                BEGIN_LP_RING(4);
 826                                OUT_RING( GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
 827                                          SC_ENABLE );
 828                                OUT_RING( GFX_OP_SCISSOR_INFO );
 829                                OUT_RING( box[i].x1 | (box[i].y1<<16) );
 830                                OUT_RING( (box[i].x2-1) | ((box[i].y2-1)<<16) );
 831                                ADVANCE_LP_RING();
 832                        }
 833
 834                        BEGIN_LP_RING(4);
 835                        OUT_RING( CMD_OP_BATCH_BUFFER );
 836                        OUT_RING( start | BB1_PROTECTED );
 837                        OUT_RING( start + used - 4 );
 838                        OUT_RING( 0 );
 839                        ADVANCE_LP_RING();
 840
 841                } while (++i < nbox);
 842        }
 843
 844        if (discard) {
 845                dev_priv->counter++;
 846
 847                (void) cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
 848                               I810_BUF_HARDWARE);
 849
 850                BEGIN_LP_RING(8);
 851                OUT_RING( CMD_STORE_DWORD_IDX );
 852                OUT_RING( 20 );
 853                OUT_RING( dev_priv->counter );
 854                OUT_RING( CMD_STORE_DWORD_IDX );
 855                OUT_RING( buf_priv->my_use_idx );
 856                OUT_RING( I810_BUF_FREE );
 857                OUT_RING( CMD_REPORT_HEAD );
 858                OUT_RING( 0 );
 859                ADVANCE_LP_RING();
 860        }
 861}
 862
 863
 864void i810_dma_quiescent(drm_device_t *dev)
 865{
 866        drm_i810_private_t *dev_priv = dev->dev_private;
 867        RING_LOCALS;
 868
 869/*      printk("%s\n", __FUNCTION__); */
 870
 871        i810_kernel_lost_context(dev);
 872
 873        BEGIN_LP_RING(4);
 874        OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE );
 875        OUT_RING( CMD_REPORT_HEAD );
 876        OUT_RING( 0 );
 877        OUT_RING( 0 );
 878        ADVANCE_LP_RING();
 879
 880        i810_wait_ring( dev, dev_priv->ring.Size - 8 );
 881}
 882
 883static int i810_flush_queue(drm_device_t *dev)
 884{
 885        drm_i810_private_t *dev_priv = dev->dev_private;
 886        drm_device_dma_t *dma = dev->dma;
 887        int i, ret = 0;
 888        RING_LOCALS;
 889        
 890/*      printk("%s\n", __FUNCTION__); */
 891
 892        i810_kernel_lost_context(dev);
 893
 894        BEGIN_LP_RING(2);
 895        OUT_RING( CMD_REPORT_HEAD );
 896        OUT_RING( 0 );
 897        ADVANCE_LP_RING();
 898
 899        i810_wait_ring( dev, dev_priv->ring.Size - 8 );
 900
 901        for (i = 0; i < dma->buf_count; i++) {
 902                drm_buf_t *buf = dma->buflist[ i ];
 903                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 904
 905                int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
 906                                   I810_BUF_FREE);
 907
 908                if (used == I810_BUF_HARDWARE)
 909                        DRM_DEBUG("reclaimed from HARDWARE\n");
 910                if (used == I810_BUF_CLIENT)
 911                        DRM_DEBUG("still on client\n");
 912        }
 913
 914        return ret;
 915}
 916
 917/* Must be called with the lock held */
 918void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
 919{
 920        drm_device_dma_t *dma = dev->dma;
 921        int              i;
 922
 923        if (!dma) return;
 924        if (!dev->dev_private) return;
 925        if (!dma->buflist) return;
 926
 927        i810_flush_queue(dev);
 928
 929        for (i = 0; i < dma->buf_count; i++) {
 930                drm_buf_t *buf = dma->buflist[ i ];
 931                drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 932
 933                if (buf->pid == pid && buf_priv) {
 934                        int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
 935                                           I810_BUF_FREE);
 936
 937                        if (used == I810_BUF_CLIENT)
 938                                DRM_DEBUG("reclaimed from client\n");
 939                        if(buf_priv->currently_mapped == I810_BUF_MAPPED)
 940                                buf_priv->currently_mapped = I810_BUF_UNMAPPED;
 941                }
 942        }
 943}
 944
 945int i810_flush_ioctl(struct inode *inode, struct file *filp,
 946                     unsigned int cmd, unsigned long arg)
 947{
 948        drm_file_t        *priv   = filp->private_data;
 949        drm_device_t      *dev    = priv->dev;
 950
 951        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
 952                DRM_ERROR("i810_flush_ioctl called without lock held\n");
 953                return -EINVAL;
 954        }
 955
 956        i810_flush_queue(dev);
 957        return 0;
 958}
 959
 960
 961int i810_dma_vertex(struct inode *inode, struct file *filp,
 962               unsigned int cmd, unsigned long arg)
 963{
 964        drm_file_t *priv = filp->private_data;
 965        drm_device_t *dev = priv->dev;
 966        drm_device_dma_t *dma = dev->dma;
 967        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 968        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
 969        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
 970                                        dev_priv->sarea_priv;
 971        drm_i810_vertex_t vertex;
 972
 973        if (copy_from_user(&vertex, (drm_i810_vertex_t *)arg, sizeof(vertex)))
 974                return -EFAULT;
 975
 976        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
 977                DRM_ERROR("i810_dma_vertex called without lock held\n");
 978                return -EINVAL;
 979        }
 980
 981        if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
 982
 983        i810_dma_dispatch_vertex( dev,
 984                                  dma->buflist[ vertex.idx ],
 985                                  vertex.discard, vertex.used );
 986
 987        atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]);
 988        atomic_inc(&dev->counts[_DRM_STAT_DMA]);
 989        sarea_priv->last_enqueue = dev_priv->counter-1;
 990        sarea_priv->last_dispatch = (int) hw_status[5];
 991
 992        return 0;
 993}
 994
 995
 996
 997int i810_clear_bufs(struct inode *inode, struct file *filp,
 998                   unsigned int cmd, unsigned long arg)
 999{
1000        drm_file_t *priv = filp->private_data;
1001        drm_device_t *dev = priv->dev;
1002        drm_i810_clear_t clear;
1003
1004        if (copy_from_user(&clear, (drm_i810_clear_t *)arg, sizeof(clear)))
1005                return -EFAULT;
1006
1007        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1008                DRM_ERROR("i810_clear_bufs called without lock held\n");
1009                return -EINVAL;
1010        }
1011
1012        /* GH: Someone's doing nasty things... */
1013        if (!dev->dev_private) {
1014                return -EINVAL;
1015        }
1016
1017        i810_dma_dispatch_clear( dev, clear.flags,
1018                                 clear.clear_color,
1019                                 clear.clear_depth );
1020        return 0;
1021}
1022
1023int i810_swap_bufs(struct inode *inode, struct file *filp,
1024                  unsigned int cmd, unsigned long arg)
1025{
1026        drm_file_t *priv = filp->private_data;
1027        drm_device_t *dev = priv->dev;
1028
1029        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1030                DRM_ERROR("i810_swap_buf called without lock held\n");
1031                return -EINVAL;
1032        }
1033
1034        i810_dma_dispatch_swap( dev );
1035        return 0;
1036}
1037
1038int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
1039                unsigned long arg)
1040{
1041        drm_file_t        *priv     = filp->private_data;
1042        drm_device_t      *dev      = priv->dev;
1043        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1044        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1045        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1046                                        dev_priv->sarea_priv;
1047
1048        sarea_priv->last_dispatch = (int) hw_status[5];
1049        return 0;
1050}
1051
1052int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
1053                unsigned long arg)
1054{
1055        drm_file_t        *priv     = filp->private_data;
1056        drm_device_t      *dev      = priv->dev;
1057        int               retcode   = 0;
1058        drm_i810_dma_t    d;
1059        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1060        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1061        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1062                                        dev_priv->sarea_priv;
1063
1064        if (copy_from_user(&d, (drm_i810_dma_t *)arg, sizeof(d)))
1065                return -EFAULT;
1066
1067        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1068                DRM_ERROR("i810_dma called without lock held\n");
1069                return -EINVAL;
1070        }
1071
1072        d.granted = 0;
1073
1074        retcode = i810_dma_get_buffer(dev, &d, filp);
1075
1076        if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
1077                return -EFAULT;
1078        sarea_priv->last_dispatch = (int) hw_status[5];
1079
1080        return retcode;
1081}
1082
1083int i810_copybuf(struct inode *inode,
1084                 struct file *filp, 
1085                 unsigned int cmd,
1086                 unsigned long arg)
1087{
1088        /* Never copy - 2.4.x doesn't need it */
1089        return 0;
1090}
1091
1092int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
1093                unsigned long arg)
1094{
1095        /* Never copy - 2.4.x doesn't need it */
1096        return 0;
1097}
1098
1099static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,
1100                unsigned int last_render)
1101{
1102        drm_i810_private_t *dev_priv = dev->dev_private;
1103        drm_i810_buf_priv_t *buf_priv = buf->dev_private;
1104        drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
1105        unsigned long address = (unsigned long)buf->bus_address;
1106        unsigned long start = address - dev->agp->base;
1107        int u;
1108        RING_LOCALS;
1109
1110        i810_kernel_lost_context(dev);
1111
1112        u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
1113                I810_BUF_HARDWARE);
1114        if(u != I810_BUF_CLIENT) {
1115                DRM_DEBUG("MC found buffer that isn't mine!\n");
1116        }
1117
1118        if (used > 4*1024)
1119                used = 0;
1120
1121        sarea_priv->dirty = 0x7f;
1122
1123        DRM_DEBUG("dispatch mc addr 0x%lx, used 0x%x\n",
1124                address, used);
1125
1126        dev_priv->counter++;
1127        DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
1128        DRM_DEBUG("i810_dma_dispatch_mc\n");
1129        DRM_DEBUG("start : %lx\n", start);
1130        DRM_DEBUG("used : %d\n", used);
1131        DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
1132
1133        if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
1134                if (used & 4) {
1135                        *(u32 *)((u32)buf_priv->virtual + used) = 0;
1136                        used += 4;
1137                }
1138
1139                i810_unmap_buffer(buf);
1140        }
1141        BEGIN_LP_RING(4);
1142        OUT_RING( CMD_OP_BATCH_BUFFER );
1143        OUT_RING( start | BB1_PROTECTED );
1144        OUT_RING( start + used - 4 );
1145        OUT_RING( 0 );
1146        ADVANCE_LP_RING();
1147
1148
1149        BEGIN_LP_RING(8);
1150        OUT_RING( CMD_STORE_DWORD_IDX );
1151        OUT_RING( buf_priv->my_use_idx );
1152        OUT_RING( I810_BUF_FREE );
1153        OUT_RING( 0 );
1154
1155        OUT_RING( CMD_STORE_DWORD_IDX );
1156        OUT_RING( 16 );
1157        OUT_RING( last_render );
1158        OUT_RING( 0 );
1159        ADVANCE_LP_RING();
1160}
1161
1162int i810_dma_mc(struct inode *inode, struct file *filp,
1163        unsigned int cmd, unsigned long arg)
1164{
1165        drm_file_t *priv = filp->private_data;
1166        drm_device_t *dev = priv->dev;
1167        drm_device_dma_t *dma = dev->dma;
1168        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1169        u32 *hw_status = (u32 *)dev_priv->hw_status_page;
1170        drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
1171                dev_priv->sarea_priv;
1172        drm_i810_mc_t mc;
1173
1174        if (copy_from_user(&mc, (drm_i810_mc_t *)arg, sizeof(mc)))
1175                return -EFAULT;
1176
1177
1178        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1179                DRM_ERROR("i810_dma_mc called without lock held\n");
1180                return -EINVAL;
1181        }
1182
1183        i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used,
1184                mc.last_render );
1185
1186        atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]);
1187        atomic_inc(&dev->counts[_DRM_STAT_DMA]);
1188        sarea_priv->last_enqueue = dev_priv->counter-1;
1189        sarea_priv->last_dispatch = (int) hw_status[5];
1190
1191        return 0;
1192}
1193
1194int i810_rstatus(struct inode *inode, struct file *filp,
1195                unsigned int cmd, unsigned long arg)
1196{
1197        drm_file_t *priv = filp->private_data;
1198        drm_device_t *dev = priv->dev;
1199        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1200
1201        return (int)(((u32 *)(dev_priv->hw_status_page))[4]);
1202}
1203
1204int i810_ov0_info(struct inode *inode, struct file *filp,
1205                unsigned int cmd, unsigned long arg)
1206{
1207        drm_file_t *priv = filp->private_data;
1208        drm_device_t *dev = priv->dev;
1209        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1210        drm_i810_overlay_t data;
1211
1212        data.offset = dev_priv->overlay_offset;
1213        data.physical = dev_priv->overlay_physical;
1214        if (copy_to_user((drm_i810_overlay_t *)arg,&data,sizeof(data)))
1215                return -EFAULT;
1216        return 0;
1217}
1218
1219int i810_fstatus(struct inode *inode, struct file *filp,
1220                unsigned int cmd, unsigned long arg)
1221{
1222        drm_file_t *priv = filp->private_data;
1223        drm_device_t *dev = priv->dev;
1224        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1225
1226        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1227                DRM_ERROR("i810_fstatus called without lock held\n");
1228                return -EINVAL;
1229        }
1230        return I810_READ(0x30008);
1231}
1232
1233int i810_ov0_flip(struct inode *inode, struct file *filp,
1234                unsigned int cmd, unsigned long arg)
1235{
1236        drm_file_t *priv = filp->private_data;
1237        drm_device_t *dev = priv->dev;
1238        drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
1239
1240        if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
1241                DRM_ERROR("i810_ov0_flip called without lock held\n");
1242                return -EINVAL;
1243        }
1244
1245        //Tell the overlay to update
1246        I810_WRITE(0x30000,dev_priv->overlay_physical | 0x80000000);
1247
1248        return 0;
1249}
1250
1251
1252
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.