root/drivers/gpu/drm/i810/i810_dma.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. i810_freelist_get
  2. i810_freelist_put
  3. i810_mmap_buffers
  4. i810_map_buffer
  5. i810_unmap_buffer
  6. i810_dma_get_buffer
  7. i810_dma_cleanup
  8. i810_wait_ring
  9. i810_kernel_lost_context
  10. i810_freelist_init
  11. i810_dma_initialize
  12. i810_dma_init
  13. i810EmitContextVerified
  14. i810EmitTexVerified
  15. i810EmitDestVerified
  16. i810EmitState
  17. i810_dma_dispatch_clear
  18. i810_dma_dispatch_swap
  19. i810_dma_dispatch_vertex
  20. i810_dma_dispatch_flip
  21. i810_dma_quiescent
  22. i810_flush_queue
  23. i810_driver_reclaim_buffers
  24. i810_flush_ioctl
  25. i810_dma_vertex
  26. i810_clear_bufs
  27. i810_swap_bufs
  28. i810_getage
  29. i810_getbuf
  30. i810_copybuf
  31. i810_docopy
  32. i810_dma_dispatch_mc
  33. i810_dma_mc
  34. i810_rstatus
  35. i810_ov0_info
  36. i810_fstatus
  37. i810_ov0_flip
  38. i810_do_init_pageflip
  39. i810_do_cleanup_pageflip
  40. i810_flip_bufs
  41. i810_driver_load
  42. i810_driver_lastclose
  43. i810_driver_preclose
  44. i810_driver_dma_quiescent

   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 
  36 #include <drm/drm_agpsupport.h>
  37 #include <drm/drm_device.h>
  38 #include <drm/drm_drv.h>
  39 #include <drm/drm_file.h>
  40 #include <drm/drm_ioctl.h>
  41 #include <drm/drm_irq.h>
  42 #include <drm/drm_pci.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 
  55 static 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 
  79 static 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 
  94 static 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 
 118 static 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 
 127 static 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 
 157 static 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 
 174 static 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 
 204 static 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                         pci_free_consistent(dev->pdev, 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 
 241 static 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 
 270 out_wait_ring:
 271         return iters;
 272 }
 273 
 274 static 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 
 286 static 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 
 321 static 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                 pci_zalloc_consistent(dev->pdev, PAGE_SIZE,
 402                                       &dev_priv->dma_status_page);
 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 
 427 static 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  */
 460 static 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 
 493 static 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  */
 526 static 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 
 561 static 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  */
 592 static 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 
 667 static 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 
 713 static 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 
 793 static 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 
 839 static 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 
 856 static int 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, ret = 0;
 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 ret;
 886 }
 887 
 888 /* Must be called with the lock held */
 889 void 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 
 920 static 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 
 929 static 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 
 957 static 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 
 973 static 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 
 984 static 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 
 996 static 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 
1020 static 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 
1027 static 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 
1034 static 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 
1092 static 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 
1116 static 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 
1124 static 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 
1136 static 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 
1145 static 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  */
1160 static 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 
1170 static 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 
1182 static 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 
1198 int 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 
1217 void i810_driver_lastclose(struct drm_device *dev)
1218 {
1219         i810_dma_cleanup(dev);
1220 }
1221 
1222 void 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 
1242 int i810_driver_dma_quiescent(struct drm_device *dev)
1243 {
1244         i810_dma_quiescent(dev);
1245         return 0;
1246 }
1247 
1248 const 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 
1266 int i810_max_ioctl = ARRAY_SIZE(i810_ioctls);

/* [<][>][^][v][top][bottom][index][help] */