linux/drivers/char/drm/i915_dma.c
<<
>>
Prefs
   1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
   2 */
   3/*
   4 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
   5 * All Rights Reserved.
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a
   8 * copy of this software and associated documentation files (the
   9 * "Software"), to deal in the Software without restriction, including
  10 * without limitation the rights to use, copy, modify, merge, publish,
  11 * distribute, sub license, and/or sell copies of the Software, and to
  12 * permit persons to whom the Software is furnished to do so, subject to
  13 * the following conditions:
  14 *
  15 * The above copyright notice and this permission notice (including the
  16 * next paragraph) shall be included in all copies or substantial portions
  17 * of the Software.
  18 *
  19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26 *
  27 */
  28
  29#include "drmP.h"
  30#include "drm.h"
  31#include "i915_drm.h"
  32#include "i915_drv.h"
  33
  34#define IS_I965G(dev) (dev->pci_device == 0x2972 || \
  35                       dev->pci_device == 0x2982 || \
  36                       dev->pci_device == 0x2992 || \
  37                       dev->pci_device == 0x29A2 || \
  38                       dev->pci_device == 0x2A02 || \
  39                       dev->pci_device == 0x2A12)
  40
  41#define IS_G33(dev) (dev->pci_device == 0x29b2 || \
  42                     dev->pci_device == 0x29c2 || \
  43                     dev->pci_device == 0x29d2)
  44
  45/* Really want an OS-independent resettable timer.  Would like to have
  46 * this loop run for (eg) 3 sec, but have the timer reset every time
  47 * the head pointer changes, so that EBUSY only happens if the ring
  48 * actually stalls for (eg) 3 seconds.
  49 */
  50int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
  51{
  52        drm_i915_private_t *dev_priv = dev->dev_private;
  53        drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
  54        u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
  55        int i;
  56
  57        for (i = 0; i < 10000; i++) {
  58                ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
  59                ring->space = ring->head - (ring->tail + 8);
  60                if (ring->space < 0)
  61                        ring->space += ring->Size;
  62                if (ring->space >= n)
  63                        return 0;
  64
  65                dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
  66
  67                if (ring->head != last_head)
  68                        i = 0;
  69
  70                last_head = ring->head;
  71        }
  72
  73        return -EBUSY;
  74}
  75
  76void i915_kernel_lost_context(struct drm_device * dev)
  77{
  78        drm_i915_private_t *dev_priv = dev->dev_private;
  79        drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
  80
  81        ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
  82        ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
  83        ring->space = ring->head - (ring->tail + 8);
  84        if (ring->space < 0)
  85                ring->space += ring->Size;
  86
  87        if (ring->head == ring->tail)
  88                dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
  89}
  90
  91static int i915_dma_cleanup(struct drm_device * dev)
  92{
  93        /* Make sure interrupts are disabled here because the uninstall ioctl
  94         * may not have been called from userspace and after dev_private
  95         * is freed, it's too late.
  96         */
  97        if (dev->irq)
  98                drm_irq_uninstall(dev);
  99
 100        if (dev->dev_private) {
 101                drm_i915_private_t *dev_priv =
 102                    (drm_i915_private_t *) dev->dev_private;
 103
 104                if (dev_priv->ring.virtual_start) {
 105                        drm_core_ioremapfree(&dev_priv->ring.map, dev);
 106                }
 107
 108                if (dev_priv->status_page_dmah) {
 109                        drm_pci_free(dev, dev_priv->status_page_dmah);
 110                        /* Need to rewrite hardware status page */
 111                        I915_WRITE(0x02080, 0x1ffff000);
 112                }
 113
 114                if (dev_priv->status_gfx_addr) {
 115                        dev_priv->status_gfx_addr = 0;
 116                        drm_core_ioremapfree(&dev_priv->hws_map, dev);
 117                        I915_WRITE(0x2080, 0x1ffff000);
 118                }
 119
 120                drm_free(dev->dev_private, sizeof(drm_i915_private_t),
 121                         DRM_MEM_DRIVER);
 122
 123                dev->dev_private = NULL;
 124        }
 125
 126        return 0;
 127}
 128
 129static int i915_initialize(struct drm_device * dev,
 130                           drm_i915_private_t * dev_priv,
 131                           drm_i915_init_t * init)
 132{
 133        memset(dev_priv, 0, sizeof(drm_i915_private_t));
 134
 135        dev_priv->sarea = drm_getsarea(dev);
 136        if (!dev_priv->sarea) {
 137                DRM_ERROR("can not find sarea!\n");
 138                dev->dev_private = (void *)dev_priv;
 139                i915_dma_cleanup(dev);
 140                return -EINVAL;
 141        }
 142
 143        dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
 144        if (!dev_priv->mmio_map) {
 145                dev->dev_private = (void *)dev_priv;
 146                i915_dma_cleanup(dev);
 147                DRM_ERROR("can not find mmio map!\n");
 148                return -EINVAL;
 149        }
 150
 151        dev_priv->sarea_priv = (drm_i915_sarea_t *)
 152            ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
 153
 154        dev_priv->ring.Start = init->ring_start;
 155        dev_priv->ring.End = init->ring_end;
 156        dev_priv->ring.Size = init->ring_size;
 157        dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
 158
 159        dev_priv->ring.map.offset = init->ring_start;
 160        dev_priv->ring.map.size = init->ring_size;
 161        dev_priv->ring.map.type = 0;
 162        dev_priv->ring.map.flags = 0;
 163        dev_priv->ring.map.mtrr = 0;
 164
 165        drm_core_ioremap(&dev_priv->ring.map, dev);
 166
 167        if (dev_priv->ring.map.handle == NULL) {
 168                dev->dev_private = (void *)dev_priv;
 169                i915_dma_cleanup(dev);
 170                DRM_ERROR("can not ioremap virtual address for"
 171                          " ring buffer\n");
 172                return -ENOMEM;
 173        }
 174
 175        dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
 176
 177        dev_priv->cpp = init->cpp;
 178        dev_priv->back_offset = init->back_offset;
 179        dev_priv->front_offset = init->front_offset;
 180        dev_priv->current_page = 0;
 181        dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 182
 183        /* We are using separate values as placeholders for mechanisms for
 184         * private backbuffer/depthbuffer usage.
 185         */
 186        dev_priv->use_mi_batchbuffer_start = 0;
 187        if (IS_I965G(dev)) /* 965 doesn't support older method */
 188                dev_priv->use_mi_batchbuffer_start = 1;
 189
 190        /* Allow hardware batchbuffers unless told otherwise.
 191         */
 192        dev_priv->allow_batchbuffer = 1;
 193
 194        /* Program Hardware Status Page */
 195        if (!IS_G33(dev)) {
 196                dev_priv->status_page_dmah =
 197                        drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
 198
 199                if (!dev_priv->status_page_dmah) {
 200                        dev->dev_private = (void *)dev_priv;
 201                        i915_dma_cleanup(dev);
 202                        DRM_ERROR("Can not allocate hardware status page\n");
 203                        return -ENOMEM;
 204                }
 205                dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
 206                dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
 207
 208                memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 209                I915_WRITE(0x02080, dev_priv->dma_status_page);
 210        }
 211        DRM_DEBUG("Enabled hardware status page\n");
 212        dev->dev_private = (void *)dev_priv;
 213        return 0;
 214}
 215
 216static int i915_dma_resume(struct drm_device * dev)
 217{
 218        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 219
 220        DRM_DEBUG("%s\n", __FUNCTION__);
 221
 222        if (!dev_priv->sarea) {
 223                DRM_ERROR("can not find sarea!\n");
 224                return -EINVAL;
 225        }
 226
 227        if (!dev_priv->mmio_map) {
 228                DRM_ERROR("can not find mmio map!\n");
 229                return -EINVAL;
 230        }
 231
 232        if (dev_priv->ring.map.handle == NULL) {
 233                DRM_ERROR("can not ioremap virtual address for"
 234                          " ring buffer\n");
 235                return -ENOMEM;
 236        }
 237
 238        /* Program Hardware Status Page */
 239        if (!dev_priv->hw_status_page) {
 240                DRM_ERROR("Can not find hardware status page\n");
 241                return -EINVAL;
 242        }
 243        DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
 244
 245        if (dev_priv->status_gfx_addr != 0)
 246                I915_WRITE(0x02080, dev_priv->status_gfx_addr);
 247        else
 248                I915_WRITE(0x02080, dev_priv->dma_status_page);
 249        DRM_DEBUG("Enabled hardware status page\n");
 250
 251        return 0;
 252}
 253
 254static int i915_dma_init(struct drm_device *dev, void *data,
 255                         struct drm_file *file_priv)
 256{
 257        drm_i915_private_t *dev_priv;
 258        drm_i915_init_t *init = data;
 259        int retcode = 0;
 260
 261        switch (init->func) {
 262        case I915_INIT_DMA:
 263                dev_priv = drm_alloc(sizeof(drm_i915_private_t),
 264                                     DRM_MEM_DRIVER);
 265                if (dev_priv == NULL)
 266                        return -ENOMEM;
 267                retcode = i915_initialize(dev, dev_priv, init);
 268                break;
 269        case I915_CLEANUP_DMA:
 270                retcode = i915_dma_cleanup(dev);
 271                break;
 272        case I915_RESUME_DMA:
 273                retcode = i915_dma_resume(dev);
 274                break;
 275        default:
 276                retcode = -EINVAL;
 277                break;
 278        }
 279
 280        return retcode;
 281}
 282
 283/* Implement basically the same security restrictions as hardware does
 284 * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
 285 *
 286 * Most of the calculations below involve calculating the size of a
 287 * particular instruction.  It's important to get the size right as
 288 * that tells us where the next instruction to check is.  Any illegal
 289 * instruction detected will be given a size of zero, which is a
 290 * signal to abort the rest of the buffer.
 291 */
 292static int do_validate_cmd(int cmd)
 293{
 294        switch (((cmd >> 29) & 0x7)) {
 295        case 0x0:
 296                switch ((cmd >> 23) & 0x3f) {
 297                case 0x0:
 298                        return 1;       /* MI_NOOP */
 299                case 0x4:
 300                        return 1;       /* MI_FLUSH */
 301                default:
 302                        return 0;       /* disallow everything else */
 303                }
 304                break;
 305        case 0x1:
 306                return 0;       /* reserved */
 307        case 0x2:
 308                return (cmd & 0xff) + 2;        /* 2d commands */
 309        case 0x3:
 310                if (((cmd >> 24) & 0x1f) <= 0x18)
 311                        return 1;
 312
 313                switch ((cmd >> 24) & 0x1f) {
 314                case 0x1c:
 315                        return 1;
 316                case 0x1d:
 317                        switch ((cmd >> 16) & 0xff) {
 318                        case 0x3:
 319                                return (cmd & 0x1f) + 2;
 320                        case 0x4:
 321                                return (cmd & 0xf) + 2;
 322                        default:
 323                                return (cmd & 0xffff) + 2;
 324                        }
 325                case 0x1e:
 326                        if (cmd & (1 << 23))
 327                                return (cmd & 0xffff) + 1;
 328                        else
 329                                return 1;
 330                case 0x1f:
 331                        if ((cmd & (1 << 23)) == 0)     /* inline vertices */
 332                                return (cmd & 0x1ffff) + 2;
 333                        else if (cmd & (1 << 17))       /* indirect random */
 334                                if ((cmd & 0xffff) == 0)
 335                                        return 0;       /* unknown length, too hard */
 336                                else
 337                                        return (((cmd & 0xffff) + 1) / 2) + 1;
 338                        else
 339                                return 2;       /* indirect sequential */
 340                default:
 341                        return 0;
 342                }
 343        default:
 344                return 0;
 345        }
 346
 347        return 0;
 348}
 349
 350static int validate_cmd(int cmd)
 351{
 352        int ret = do_validate_cmd(cmd);
 353
 354/*      printk("validate_cmd( %x ): %d\n", cmd, ret); */
 355
 356        return ret;
 357}
 358
 359static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
 360{
 361        drm_i915_private_t *dev_priv = dev->dev_private;
 362        int i;
 363        RING_LOCALS;
 364
 365        if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
 366                return -EINVAL;
 367
 368        BEGIN_LP_RING((dwords+1)&~1);
 369
 370        for (i = 0; i < dwords;) {
 371                int cmd, sz;
 372
 373                if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
 374                        return -EINVAL;
 375
 376                if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
 377                        return -EINVAL;
 378
 379                OUT_RING(cmd);
 380
 381                while (++i, --sz) {
 382                        if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
 383                                                         sizeof(cmd))) {
 384                                return -EINVAL;
 385                        }
 386                        OUT_RING(cmd);
 387                }
 388        }
 389
 390        if (dwords & 1)
 391                OUT_RING(0);
 392
 393        ADVANCE_LP_RING();
 394
 395        return 0;
 396}
 397
 398static int i915_emit_box(struct drm_device * dev,
 399                         struct drm_clip_rect __user * boxes,
 400                         int i, int DR1, int DR4)
 401{
 402        drm_i915_private_t *dev_priv = dev->dev_private;
 403        struct drm_clip_rect box;
 404        RING_LOCALS;
 405
 406        if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
 407                return -EFAULT;
 408        }
 409
 410        if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
 411                DRM_ERROR("Bad box %d,%d..%d,%d\n",
 412                          box.x1, box.y1, box.x2, box.y2);
 413                return -EINVAL;
 414        }
 415
 416        if (IS_I965G(dev)) {
 417                BEGIN_LP_RING(4);
 418                OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
 419                OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
 420                OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
 421                OUT_RING(DR4);
 422                ADVANCE_LP_RING();
 423        } else {
 424                BEGIN_LP_RING(6);
 425                OUT_RING(GFX_OP_DRAWRECT_INFO);
 426                OUT_RING(DR1);
 427                OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
 428                OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
 429                OUT_RING(DR4);
 430                OUT_RING(0);
 431                ADVANCE_LP_RING();
 432        }
 433
 434        return 0;
 435}
 436
 437/* XXX: Emitting the counter should really be moved to part of the IRQ
 438 * emit. For now, do it in both places:
 439 */
 440
 441static void i915_emit_breadcrumb(struct drm_device *dev)
 442{
 443        drm_i915_private_t *dev_priv = dev->dev_private;
 444        RING_LOCALS;
 445
 446        dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
 447
 448        if (dev_priv->counter > 0x7FFFFFFFUL)
 449                dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
 450
 451        BEGIN_LP_RING(4);
 452        OUT_RING(CMD_STORE_DWORD_IDX);
 453        OUT_RING(20);
 454        OUT_RING(dev_priv->counter);
 455        OUT_RING(0);
 456        ADVANCE_LP_RING();
 457}
 458
 459static int i915_dispatch_cmdbuffer(struct drm_device * dev,
 460                                   drm_i915_cmdbuffer_t * cmd)
 461{
 462        int nbox = cmd->num_cliprects;
 463        int i = 0, count, ret;
 464
 465        if (cmd->sz & 0x3) {
 466                DRM_ERROR("alignment");
 467                return -EINVAL;
 468        }
 469
 470        i915_kernel_lost_context(dev);
 471
 472        count = nbox ? nbox : 1;
 473
 474        for (i = 0; i < count; i++) {
 475                if (i < nbox) {
 476                        ret = i915_emit_box(dev, cmd->cliprects, i,
 477                                            cmd->DR1, cmd->DR4);
 478                        if (ret)
 479                                return ret;
 480                }
 481
 482                ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
 483                if (ret)
 484                        return ret;
 485        }
 486
 487        i915_emit_breadcrumb(dev);
 488        return 0;
 489}
 490
 491static int i915_dispatch_batchbuffer(struct drm_device * dev,
 492                                     drm_i915_batchbuffer_t * batch)
 493{
 494        drm_i915_private_t *dev_priv = dev->dev_private;
 495        struct drm_clip_rect __user *boxes = batch->cliprects;
 496        int nbox = batch->num_cliprects;
 497        int i = 0, count;
 498        RING_LOCALS;
 499
 500        if ((batch->start | batch->used) & 0x7) {
 501                DRM_ERROR("alignment");
 502                return -EINVAL;
 503        }
 504
 505        i915_kernel_lost_context(dev);
 506
 507        count = nbox ? nbox : 1;
 508
 509        for (i = 0; i < count; i++) {
 510                if (i < nbox) {
 511                        int ret = i915_emit_box(dev, boxes, i,
 512                                                batch->DR1, batch->DR4);
 513                        if (ret)
 514                                return ret;
 515                }
 516
 517                if (dev_priv->use_mi_batchbuffer_start) {
 518                        BEGIN_LP_RING(2);
 519                        if (IS_I965G(dev)) {
 520                                OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
 521                                OUT_RING(batch->start);
 522                        } else {
 523                                OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
 524                                OUT_RING(batch->start | MI_BATCH_NON_SECURE);
 525                        }
 526                        ADVANCE_LP_RING();
 527                } else {
 528                        BEGIN_LP_RING(4);
 529                        OUT_RING(MI_BATCH_BUFFER);
 530                        OUT_RING(batch->start | MI_BATCH_NON_SECURE);
 531                        OUT_RING(batch->start + batch->used - 4);
 532                        OUT_RING(0);
 533                        ADVANCE_LP_RING();
 534                }
 535        }
 536
 537        i915_emit_breadcrumb(dev);
 538
 539        return 0;
 540}
 541
 542static int i915_dispatch_flip(struct drm_device * dev)
 543{
 544        drm_i915_private_t *dev_priv = dev->dev_private;
 545        RING_LOCALS;
 546
 547        DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
 548                  __FUNCTION__,
 549                  dev_priv->current_page,
 550                  dev_priv->sarea_priv->pf_current_page);
 551
 552        i915_kernel_lost_context(dev);
 553
 554        BEGIN_LP_RING(2);
 555        OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
 556        OUT_RING(0);
 557        ADVANCE_LP_RING();
 558
 559        BEGIN_LP_RING(6);
 560        OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
 561        OUT_RING(0);
 562        if (dev_priv->current_page == 0) {
 563                OUT_RING(dev_priv->back_offset);
 564                dev_priv->current_page = 1;
 565        } else {
 566                OUT_RING(dev_priv->front_offset);
 567                dev_priv->current_page = 0;
 568        }
 569        OUT_RING(0);
 570        ADVANCE_LP_RING();
 571
 572        BEGIN_LP_RING(2);
 573        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
 574        OUT_RING(0);
 575        ADVANCE_LP_RING();
 576
 577        dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
 578
 579        BEGIN_LP_RING(4);
 580        OUT_RING(CMD_STORE_DWORD_IDX);
 581        OUT_RING(20);
 582        OUT_RING(dev_priv->counter);
 583        OUT_RING(0);
 584        ADVANCE_LP_RING();
 585
 586        dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 587        return 0;
 588}
 589
 590static int i915_quiescent(struct drm_device * dev)
 591{
 592        drm_i915_private_t *dev_priv = dev->dev_private;
 593
 594        i915_kernel_lost_context(dev);
 595        return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
 596}
 597
 598static int i915_flush_ioctl(struct drm_device *dev, void *data,
 599                            struct drm_file *file_priv)
 600{
 601        LOCK_TEST_WITH_RETURN(dev, file_priv);
 602
 603        return i915_quiescent(dev);
 604}
 605
 606static int i915_batchbuffer(struct drm_device *dev, void *data,
 607                            struct drm_file *file_priv)
 608{
 609        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 610        u32 *hw_status = dev_priv->hw_status_page;
 611        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
 612            dev_priv->sarea_priv;
 613        drm_i915_batchbuffer_t *batch = data;
 614        int ret;
 615
 616        if (!dev_priv->allow_batchbuffer) {
 617                DRM_ERROR("Batchbuffer ioctl disabled\n");
 618                return -EINVAL;
 619        }
 620
 621        DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
 622                  batch->start, batch->used, batch->num_cliprects);
 623
 624        LOCK_TEST_WITH_RETURN(dev, file_priv);
 625
 626        if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
 627                                                       batch->num_cliprects *
 628                                                       sizeof(struct drm_clip_rect)))
 629                return -EFAULT;
 630
 631        ret = i915_dispatch_batchbuffer(dev, batch);
 632
 633        sarea_priv->last_dispatch = (int)hw_status[5];
 634        return ret;
 635}
 636
 637static int i915_cmdbuffer(struct drm_device *dev, void *data,
 638                          struct drm_file *file_priv)
 639{
 640        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 641        u32 *hw_status = dev_priv->hw_status_page;
 642        drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
 643            dev_priv->sarea_priv;
 644        drm_i915_cmdbuffer_t *cmdbuf = data;
 645        int ret;
 646
 647        DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
 648                  cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
 649
 650        LOCK_TEST_WITH_RETURN(dev, file_priv);
 651
 652        if (cmdbuf->num_cliprects &&
 653            DRM_VERIFYAREA_READ(cmdbuf->cliprects,
 654                                cmdbuf->num_cliprects *
 655                                sizeof(struct drm_clip_rect))) {
 656                DRM_ERROR("Fault accessing cliprects\n");
 657                return -EFAULT;
 658        }
 659
 660        ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
 661        if (ret) {
 662                DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
 663                return ret;
 664        }
 665
 666        sarea_priv->last_dispatch = (int)hw_status[5];
 667        return 0;
 668}
 669
 670static int i915_flip_bufs(struct drm_device *dev, void *data,
 671                          struct drm_file *file_priv)
 672{
 673        DRM_DEBUG("%s\n", __FUNCTION__);
 674
 675        LOCK_TEST_WITH_RETURN(dev, file_priv);
 676
 677        return i915_dispatch_flip(dev);
 678}
 679
 680static int i915_getparam(struct drm_device *dev, void *data,
 681                         struct drm_file *file_priv)
 682{
 683        drm_i915_private_t *dev_priv = dev->dev_private;
 684        drm_i915_getparam_t *param = data;
 685        int value;
 686
 687        if (!dev_priv) {
 688                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
 689                return -EINVAL;
 690        }
 691
 692        switch (param->param) {
 693        case I915_PARAM_IRQ_ACTIVE:
 694                value = dev->irq ? 1 : 0;
 695                break;
 696        case I915_PARAM_ALLOW_BATCHBUFFER:
 697                value = dev_priv->allow_batchbuffer ? 1 : 0;
 698                break;
 699        case I915_PARAM_LAST_DISPATCH:
 700                value = READ_BREADCRUMB(dev_priv);
 701                break;
 702        default:
 703                DRM_ERROR("Unknown parameter %d\n", param->param);
 704                return -EINVAL;
 705        }
 706
 707        if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
 708                DRM_ERROR("DRM_COPY_TO_USER failed\n");
 709                return -EFAULT;
 710        }
 711
 712        return 0;
 713}
 714
 715static int i915_setparam(struct drm_device *dev, void *data,
 716                         struct drm_file *file_priv)
 717{
 718        drm_i915_private_t *dev_priv = dev->dev_private;
 719        drm_i915_setparam_t *param = data;
 720
 721        if (!dev_priv) {
 722                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
 723                return -EINVAL;
 724        }
 725
 726        switch (param->param) {
 727        case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
 728                if (!IS_I965G(dev))
 729                        dev_priv->use_mi_batchbuffer_start = param->value;
 730                break;
 731        case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
 732                dev_priv->tex_lru_log_granularity = param->value;
 733                break;
 734        case I915_SETPARAM_ALLOW_BATCHBUFFER:
 735                dev_priv->allow_batchbuffer = param->value;
 736                break;
 737        default:
 738                DRM_ERROR("unknown parameter %d\n", param->param);
 739                return -EINVAL;
 740        }
 741
 742        return 0;
 743}
 744
 745static int i915_set_status_page(struct drm_device *dev, void *data,
 746                                struct drm_file *file_priv)
 747{
 748        drm_i915_private_t *dev_priv = dev->dev_private;
 749        drm_i915_hws_addr_t *hws = data;
 750
 751        if (!dev_priv) {
 752                DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
 753                return -EINVAL;
 754        }
 755
 756        printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
 757
 758        dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
 759
 760        dev_priv->hws_map.offset = dev->agp->agp_info.aper_base + hws->addr;
 761        dev_priv->hws_map.size = 4*1024;
 762        dev_priv->hws_map.type = 0;
 763        dev_priv->hws_map.flags = 0;
 764        dev_priv->hws_map.mtrr = 0;
 765
 766        drm_core_ioremap(&dev_priv->hws_map, dev);
 767        if (dev_priv->hws_map.handle == NULL) {
 768                dev->dev_private = (void *)dev_priv;
 769                i915_dma_cleanup(dev);
 770                dev_priv->status_gfx_addr = 0;
 771                DRM_ERROR("can not ioremap virtual address for"
 772                                " G33 hw status page\n");
 773                return -ENOMEM;
 774        }
 775        dev_priv->hw_status_page = dev_priv->hws_map.handle;
 776
 777        memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 778        I915_WRITE(0x02080, dev_priv->status_gfx_addr);
 779        DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
 780                        dev_priv->status_gfx_addr);
 781        DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
 782        return 0;
 783}
 784
 785int i915_driver_load(struct drm_device *dev, unsigned long flags)
 786{
 787        /* i915 has 4 more counters */
 788        dev->counters += 4;
 789        dev->types[6] = _DRM_STAT_IRQ;
 790        dev->types[7] = _DRM_STAT_PRIMARY;
 791        dev->types[8] = _DRM_STAT_SECONDARY;
 792        dev->types[9] = _DRM_STAT_DMA;
 793
 794        return 0;
 795}
 796
 797void i915_driver_lastclose(struct drm_device * dev)
 798{
 799        if (dev->dev_private) {
 800                drm_i915_private_t *dev_priv = dev->dev_private;
 801                i915_mem_takedown(&(dev_priv->agp_heap));
 802        }
 803        i915_dma_cleanup(dev);
 804}
 805
 806void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 807{
 808        if (dev->dev_private) {
 809                drm_i915_private_t *dev_priv = dev->dev_private;
 810                i915_mem_release(dev, file_priv, dev_priv->agp_heap);
 811        }
 812}
 813
 814struct drm_ioctl_desc i915_ioctls[] = {
 815        DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 816        DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
 817        DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
 818        DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
 819        DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
 820        DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
 821        DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
 822        DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 823        DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
 824        DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
 825        DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 826        DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
 827        DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
 828        DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
 829        DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
 830        DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
 831        DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
 832};
 833
 834int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
 835
 836/**
 837 * Determine if the device really is AGP or not.
 838 *
 839 * All Intel graphics chipsets are treated as AGP, even if they are really
 840 * PCI-e.
 841 *
 842 * \param dev   The device to be tested.
 843 *
 844 * \returns
 845 * A value of 1 is always retured to indictate every i9x5 is AGP.
 846 */
 847int i915_driver_device_is_agp(struct drm_device * dev)
 848{
 849        return 1;
 850}
 851