Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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