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