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