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