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