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

Configure Feed

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

at v2.6.26-rc1 1553 lines 40 kB view raw
1/* i830_dma.c -- DMA support for the I830 -*- 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 * Abraham vd Merwe <abraham@2d3d.co.za> 31 * 32 */ 33 34#include "drmP.h" 35#include "drm.h" 36#include "i830_drm.h" 37#include "i830_drv.h" 38#include <linux/interrupt.h> /* For task queue support */ 39#include <linux/pagemap.h> 40#include <linux/delay.h> 41#include <asm/uaccess.h> 42 43#define I830_BUF_FREE 2 44#define I830_BUF_CLIENT 1 45#define I830_BUF_HARDWARE 0 46 47#define I830_BUF_UNMAPPED 0 48#define I830_BUF_MAPPED 1 49 50static struct drm_buf *i830_freelist_get(struct drm_device * dev) 51{ 52 struct drm_device_dma *dma = dev->dma; 53 int i; 54 int used; 55 56 /* Linear search might not be the best solution */ 57 58 for (i = 0; i < dma->buf_count; i++) { 59 struct drm_buf *buf = dma->buflist[i]; 60 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 61 /* In use is already a pointer */ 62 used = cmpxchg(buf_priv->in_use, I830_BUF_FREE, 63 I830_BUF_CLIENT); 64 if (used == I830_BUF_FREE) { 65 return buf; 66 } 67 } 68 return NULL; 69} 70 71/* This should only be called if the buffer is not sent to the hardware 72 * yet, the hardware updates in use for us once its on the ring buffer. 73 */ 74 75static int i830_freelist_put(struct drm_device * dev, struct drm_buf * buf) 76{ 77 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 78 int used; 79 80 /* In use is already a pointer */ 81 used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE); 82 if (used != I830_BUF_CLIENT) { 83 DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx); 84 return -EINVAL; 85 } 86 87 return 0; 88} 89 90static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) 91{ 92 struct drm_file *priv = filp->private_data; 93 struct drm_device *dev; 94 drm_i830_private_t *dev_priv; 95 struct drm_buf *buf; 96 drm_i830_buf_priv_t *buf_priv; 97 98 lock_kernel(); 99 dev = priv->minor->dev; 100 dev_priv = dev->dev_private; 101 buf = dev_priv->mmap_buffer; 102 buf_priv = buf->dev_private; 103 104 vma->vm_flags |= (VM_IO | VM_DONTCOPY); 105 vma->vm_file = filp; 106 107 buf_priv->currently_mapped = I830_BUF_MAPPED; 108 unlock_kernel(); 109 110 if (io_remap_pfn_range(vma, vma->vm_start, 111 vma->vm_pgoff, 112 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 113 return -EAGAIN; 114 return 0; 115} 116 117static const struct file_operations i830_buffer_fops = { 118 .open = drm_open, 119 .release = drm_release, 120 .ioctl = drm_ioctl, 121 .mmap = i830_mmap_buffers, 122 .fasync = drm_fasync, 123}; 124 125static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) 126{ 127 struct drm_device *dev = file_priv->minor->dev; 128 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 129 drm_i830_private_t *dev_priv = dev->dev_private; 130 const struct file_operations *old_fops; 131 unsigned long virtual; 132 int retcode = 0; 133 134 if (buf_priv->currently_mapped == I830_BUF_MAPPED) 135 return -EINVAL; 136 137 down_write(&current->mm->mmap_sem); 138 old_fops = file_priv->filp->f_op; 139 file_priv->filp->f_op = &i830_buffer_fops; 140 dev_priv->mmap_buffer = buf; 141 virtual = do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE, 142 MAP_SHARED, buf->bus_address); 143 dev_priv->mmap_buffer = NULL; 144 file_priv->filp->f_op = old_fops; 145 if (IS_ERR((void *)virtual)) { /* ugh */ 146 /* Real error */ 147 DRM_ERROR("mmap error\n"); 148 retcode = PTR_ERR((void *)virtual); 149 buf_priv->virtual = NULL; 150 } else { 151 buf_priv->virtual = (void __user *)virtual; 152 } 153 up_write(&current->mm->mmap_sem); 154 155 return retcode; 156} 157 158static int i830_unmap_buffer(struct drm_buf * buf) 159{ 160 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 161 int retcode = 0; 162 163 if (buf_priv->currently_mapped != I830_BUF_MAPPED) 164 return -EINVAL; 165 166 down_write(&current->mm->mmap_sem); 167 retcode = do_munmap(current->mm, 168 (unsigned long)buf_priv->virtual, 169 (size_t) buf->total); 170 up_write(&current->mm->mmap_sem); 171 172 buf_priv->currently_mapped = I830_BUF_UNMAPPED; 173 buf_priv->virtual = NULL; 174 175 return retcode; 176} 177 178static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d, 179 struct drm_file *file_priv) 180{ 181 struct drm_buf *buf; 182 drm_i830_buf_priv_t *buf_priv; 183 int retcode = 0; 184 185 buf = i830_freelist_get(dev); 186 if (!buf) { 187 retcode = -ENOMEM; 188 DRM_DEBUG("retcode=%d\n", retcode); 189 return retcode; 190 } 191 192 retcode = i830_map_buffer(buf, file_priv); 193 if (retcode) { 194 i830_freelist_put(dev, buf); 195 DRM_ERROR("mapbuf failed, retcode %d\n", retcode); 196 return retcode; 197 } 198 buf->file_priv = file_priv; 199 buf_priv = buf->dev_private; 200 d->granted = 1; 201 d->request_idx = buf->idx; 202 d->request_size = buf->total; 203 d->virtual = buf_priv->virtual; 204 205 return retcode; 206} 207 208static int i830_dma_cleanup(struct drm_device * dev) 209{ 210 struct drm_device_dma *dma = dev->dma; 211 212 /* Make sure interrupts are disabled here because the uninstall ioctl 213 * may not have been called from userspace and after dev_private 214 * is freed, it's too late. 215 */ 216 if (dev->irq_enabled) 217 drm_irq_uninstall(dev); 218 219 if (dev->dev_private) { 220 int i; 221 drm_i830_private_t *dev_priv = 222 (drm_i830_private_t *) dev->dev_private; 223 224 if (dev_priv->ring.virtual_start) { 225 drm_core_ioremapfree(&dev_priv->ring.map, dev); 226 } 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 /* Need to rewrite hardware status page */ 232 I830_WRITE(0x02080, 0x1ffff000); 233 } 234 235 drm_free(dev->dev_private, sizeof(drm_i830_private_t), 236 DRM_MEM_DRIVER); 237 dev->dev_private = NULL; 238 239 for (i = 0; i < dma->buf_count; i++) { 240 struct drm_buf *buf = dma->buflist[i]; 241 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 242 if (buf_priv->kernel_virtual && buf->total) 243 drm_core_ioremapfree(&buf_priv->map, dev); 244 } 245 } 246 return 0; 247} 248 249int i830_wait_ring(struct drm_device * dev, int n, const char *caller) 250{ 251 drm_i830_private_t *dev_priv = dev->dev_private; 252 drm_i830_ring_buffer_t *ring = &(dev_priv->ring); 253 int iters = 0; 254 unsigned long end; 255 unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; 256 257 end = jiffies + (HZ * 3); 258 while (ring->space < n) { 259 ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; 260 ring->space = ring->head - (ring->tail + 8); 261 if (ring->space < 0) 262 ring->space += ring->Size; 263 264 if (ring->head != last_head) { 265 end = jiffies + (HZ * 3); 266 last_head = ring->head; 267 } 268 269 iters++; 270 if (time_before(end, jiffies)) { 271 DRM_ERROR("space: %d wanted %d\n", ring->space, n); 272 DRM_ERROR("lockup\n"); 273 goto out_wait_ring; 274 } 275 udelay(1); 276 dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT; 277 } 278 279 out_wait_ring: 280 return iters; 281} 282 283static void i830_kernel_lost_context(struct drm_device * dev) 284{ 285 drm_i830_private_t *dev_priv = dev->dev_private; 286 drm_i830_ring_buffer_t *ring = &(dev_priv->ring); 287 288 ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; 289 ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR; 290 ring->space = ring->head - (ring->tail + 8); 291 if (ring->space < 0) 292 ring->space += ring->Size; 293 294 if (ring->head == ring->tail) 295 dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY; 296} 297 298static int i830_freelist_init(struct drm_device * dev, drm_i830_private_t * dev_priv) 299{ 300 struct drm_device_dma *dma = dev->dma; 301 int my_idx = 36; 302 u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx); 303 int i; 304 305 if (dma->buf_count > 1019) { 306 /* Not enough space in the status page for the freelist */ 307 return -EINVAL; 308 } 309 310 for (i = 0; i < dma->buf_count; i++) { 311 struct drm_buf *buf = dma->buflist[i]; 312 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 313 314 buf_priv->in_use = hw_status++; 315 buf_priv->my_use_idx = my_idx; 316 my_idx += 4; 317 318 *buf_priv->in_use = I830_BUF_FREE; 319 320 buf_priv->map.offset = buf->bus_address; 321 buf_priv->map.size = buf->total; 322 buf_priv->map.type = _DRM_AGP; 323 buf_priv->map.flags = 0; 324 buf_priv->map.mtrr = 0; 325 326 drm_core_ioremap(&buf_priv->map, dev); 327 buf_priv->kernel_virtual = buf_priv->map.handle; 328 } 329 return 0; 330} 331 332static int i830_dma_initialize(struct drm_device * dev, 333 drm_i830_private_t * dev_priv, 334 drm_i830_init_t * init) 335{ 336 struct drm_map_list *r_list; 337 338 memset(dev_priv, 0, sizeof(drm_i830_private_t)); 339 340 list_for_each_entry(r_list, &dev->maplist, head) { 341 if (r_list->map && 342 r_list->map->type == _DRM_SHM && 343 r_list->map->flags & _DRM_CONTAINS_LOCK) { 344 dev_priv->sarea_map = r_list->map; 345 break; 346 } 347 } 348 349 if (!dev_priv->sarea_map) { 350 dev->dev_private = (void *)dev_priv; 351 i830_dma_cleanup(dev); 352 DRM_ERROR("can not find sarea!\n"); 353 return -EINVAL; 354 } 355 dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); 356 if (!dev_priv->mmio_map) { 357 dev->dev_private = (void *)dev_priv; 358 i830_dma_cleanup(dev); 359 DRM_ERROR("can not find mmio map!\n"); 360 return -EINVAL; 361 } 362 dev->agp_buffer_token = init->buffers_offset; 363 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); 364 if (!dev->agp_buffer_map) { 365 dev->dev_private = (void *)dev_priv; 366 i830_dma_cleanup(dev); 367 DRM_ERROR("can not find dma buffer map!\n"); 368 return -EINVAL; 369 } 370 371 dev_priv->sarea_priv = (drm_i830_sarea_t *) 372 ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset); 373 374 dev_priv->ring.Start = init->ring_start; 375 dev_priv->ring.End = init->ring_end; 376 dev_priv->ring.Size = init->ring_size; 377 378 dev_priv->ring.map.offset = dev->agp->base + init->ring_start; 379 dev_priv->ring.map.size = init->ring_size; 380 dev_priv->ring.map.type = _DRM_AGP; 381 dev_priv->ring.map.flags = 0; 382 dev_priv->ring.map.mtrr = 0; 383 384 drm_core_ioremap(&dev_priv->ring.map, dev); 385 386 if (dev_priv->ring.map.handle == NULL) { 387 dev->dev_private = (void *)dev_priv; 388 i830_dma_cleanup(dev); 389 DRM_ERROR("can not ioremap virtual address for" 390 " ring buffer\n"); 391 return -ENOMEM; 392 } 393 394 dev_priv->ring.virtual_start = dev_priv->ring.map.handle; 395 396 dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; 397 398 dev_priv->w = init->w; 399 dev_priv->h = init->h; 400 dev_priv->pitch = init->pitch; 401 dev_priv->back_offset = init->back_offset; 402 dev_priv->depth_offset = init->depth_offset; 403 dev_priv->front_offset = init->front_offset; 404 405 dev_priv->front_di1 = init->front_offset | init->pitch_bits; 406 dev_priv->back_di1 = init->back_offset | init->pitch_bits; 407 dev_priv->zi1 = init->depth_offset | init->pitch_bits; 408 409 DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1); 410 DRM_DEBUG("back_offset %x\n", dev_priv->back_offset); 411 DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1); 412 DRM_DEBUG("pitch_bits %x\n", init->pitch_bits); 413 414 dev_priv->cpp = init->cpp; 415 /* We are using separate values as placeholders for mechanisms for 416 * private backbuffer/depthbuffer usage. 417 */ 418 419 dev_priv->back_pitch = init->back_pitch; 420 dev_priv->depth_pitch = init->depth_pitch; 421 dev_priv->do_boxes = 0; 422 dev_priv->use_mi_batchbuffer_start = 0; 423 424 /* Program Hardware Status Page */ 425 dev_priv->hw_status_page = 426 pci_alloc_consistent(dev->pdev, PAGE_SIZE, 427 &dev_priv->dma_status_page); 428 if (!dev_priv->hw_status_page) { 429 dev->dev_private = (void *)dev_priv; 430 i830_dma_cleanup(dev); 431 DRM_ERROR("Can not allocate hardware status page\n"); 432 return -ENOMEM; 433 } 434 memset(dev_priv->hw_status_page, 0, PAGE_SIZE); 435 DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); 436 437 I830_WRITE(0x02080, dev_priv->dma_status_page); 438 DRM_DEBUG("Enabled hardware status page\n"); 439 440 /* Now we need to init our freelist */ 441 if (i830_freelist_init(dev, dev_priv) != 0) { 442 dev->dev_private = (void *)dev_priv; 443 i830_dma_cleanup(dev); 444 DRM_ERROR("Not enough space in the status page for" 445 " the freelist\n"); 446 return -ENOMEM; 447 } 448 dev->dev_private = (void *)dev_priv; 449 450 return 0; 451} 452 453static int i830_dma_init(struct drm_device *dev, void *data, 454 struct drm_file *file_priv) 455{ 456 drm_i830_private_t *dev_priv; 457 drm_i830_init_t *init = data; 458 int retcode = 0; 459 460 switch (init->func) { 461 case I830_INIT_DMA: 462 dev_priv = drm_alloc(sizeof(drm_i830_private_t), 463 DRM_MEM_DRIVER); 464 if (dev_priv == NULL) 465 return -ENOMEM; 466 retcode = i830_dma_initialize(dev, dev_priv, init); 467 break; 468 case I830_CLEANUP_DMA: 469 retcode = i830_dma_cleanup(dev); 470 break; 471 default: 472 retcode = -EINVAL; 473 break; 474 } 475 476 return retcode; 477} 478 479#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) 480#define ST1_ENABLE (1<<16) 481#define ST1_MASK (0xffff) 482 483/* Most efficient way to verify state for the i830 is as it is 484 * emitted. Non-conformant state is silently dropped. 485 */ 486static void i830EmitContextVerified(struct drm_device * dev, unsigned int *code) 487{ 488 drm_i830_private_t *dev_priv = dev->dev_private; 489 int i, j = 0; 490 unsigned int tmp; 491 RING_LOCALS; 492 493 BEGIN_LP_RING(I830_CTX_SETUP_SIZE + 4); 494 495 for (i = 0; i < I830_CTXREG_BLENDCOLR0; i++) { 496 tmp = code[i]; 497 if ((tmp & (7 << 29)) == CMD_3D && 498 (tmp & (0x1f << 24)) < (0x1d << 24)) { 499 OUT_RING(tmp); 500 j++; 501 } else { 502 DRM_ERROR("Skipping %d\n", i); 503 } 504 } 505 506 OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD); 507 OUT_RING(code[I830_CTXREG_BLENDCOLR]); 508 j += 2; 509 510 for (i = I830_CTXREG_VF; i < I830_CTXREG_MCSB0; i++) { 511 tmp = code[i]; 512 if ((tmp & (7 << 29)) == CMD_3D && 513 (tmp & (0x1f << 24)) < (0x1d << 24)) { 514 OUT_RING(tmp); 515 j++; 516 } else { 517 DRM_ERROR("Skipping %d\n", i); 518 } 519 } 520 521 OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD); 522 OUT_RING(code[I830_CTXREG_MCSB1]); 523 j += 2; 524 525 if (j & 1) 526 OUT_RING(0); 527 528 ADVANCE_LP_RING(); 529} 530 531static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code) 532{ 533 drm_i830_private_t *dev_priv = dev->dev_private; 534 int i, j = 0; 535 unsigned int tmp; 536 RING_LOCALS; 537 538 if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO || 539 (code[I830_TEXREG_MI0] & ~(0xf * LOAD_TEXTURE_MAP0)) == 540 (STATE3D_LOAD_STATE_IMMEDIATE_2 | 4)) { 541 542 BEGIN_LP_RING(I830_TEX_SETUP_SIZE); 543 544 OUT_RING(code[I830_TEXREG_MI0]); /* TM0LI */ 545 OUT_RING(code[I830_TEXREG_MI1]); /* TM0S0 */ 546 OUT_RING(code[I830_TEXREG_MI2]); /* TM0S1 */ 547 OUT_RING(code[I830_TEXREG_MI3]); /* TM0S2 */ 548 OUT_RING(code[I830_TEXREG_MI4]); /* TM0S3 */ 549 OUT_RING(code[I830_TEXREG_MI5]); /* TM0S4 */ 550 551 for (i = 6; i < I830_TEX_SETUP_SIZE; i++) { 552 tmp = code[i]; 553 OUT_RING(tmp); 554 j++; 555 } 556 557 if (j & 1) 558 OUT_RING(0); 559 560 ADVANCE_LP_RING(); 561 } else 562 printk("rejected packet %x\n", code[0]); 563} 564 565static void i830EmitTexBlendVerified(struct drm_device * dev, 566 unsigned int *code, unsigned int num) 567{ 568 drm_i830_private_t *dev_priv = dev->dev_private; 569 int i, j = 0; 570 unsigned int tmp; 571 RING_LOCALS; 572 573 if (!num) 574 return; 575 576 BEGIN_LP_RING(num + 1); 577 578 for (i = 0; i < num; i++) { 579 tmp = code[i]; 580 OUT_RING(tmp); 581 j++; 582 } 583 584 if (j & 1) 585 OUT_RING(0); 586 587 ADVANCE_LP_RING(); 588} 589 590static void i830EmitTexPalette(struct drm_device * dev, 591 unsigned int *palette, int number, int is_shared) 592{ 593 drm_i830_private_t *dev_priv = dev->dev_private; 594 int i; 595 RING_LOCALS; 596 597 return; 598 599 BEGIN_LP_RING(258); 600 601 if (is_shared == 1) { 602 OUT_RING(CMD_OP_MAP_PALETTE_LOAD | 603 MAP_PALETTE_NUM(0) | MAP_PALETTE_BOTH); 604 } else { 605 OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number)); 606 } 607 for (i = 0; i < 256; i++) { 608 OUT_RING(palette[i]); 609 } 610 OUT_RING(0); 611 /* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop! 612 */ 613} 614 615/* Need to do some additional checking when setting the dest buffer. 616 */ 617static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code) 618{ 619 drm_i830_private_t *dev_priv = dev->dev_private; 620 unsigned int tmp; 621 RING_LOCALS; 622 623 BEGIN_LP_RING(I830_DEST_SETUP_SIZE + 10); 624 625 tmp = code[I830_DESTREG_CBUFADDR]; 626 if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { 627 if (((int)outring) & 8) { 628 OUT_RING(0); 629 OUT_RING(0); 630 } 631 632 OUT_RING(CMD_OP_DESTBUFFER_INFO); 633 OUT_RING(BUF_3D_ID_COLOR_BACK | 634 BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) | 635 BUF_3D_USE_FENCE); 636 OUT_RING(tmp); 637 OUT_RING(0); 638 639 OUT_RING(CMD_OP_DESTBUFFER_INFO); 640 OUT_RING(BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE | 641 BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp)); 642 OUT_RING(dev_priv->zi1); 643 OUT_RING(0); 644 } else { 645 DRM_ERROR("bad di1 %x (allow %x or %x)\n", 646 tmp, dev_priv->front_di1, dev_priv->back_di1); 647 } 648 649 /* invarient: 650 */ 651 652 OUT_RING(GFX_OP_DESTBUFFER_VARS); 653 OUT_RING(code[I830_DESTREG_DV1]); 654 655 OUT_RING(GFX_OP_DRAWRECT_INFO); 656 OUT_RING(code[I830_DESTREG_DR1]); 657 OUT_RING(code[I830_DESTREG_DR2]); 658 OUT_RING(code[I830_DESTREG_DR3]); 659 OUT_RING(code[I830_DESTREG_DR4]); 660 661 /* Need to verify this */ 662 tmp = code[I830_DESTREG_SENABLE]; 663 if ((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) { 664 OUT_RING(tmp); 665 } else { 666 DRM_ERROR("bad scissor enable\n"); 667 OUT_RING(0); 668 } 669 670 OUT_RING(GFX_OP_SCISSOR_RECT); 671 OUT_RING(code[I830_DESTREG_SR1]); 672 OUT_RING(code[I830_DESTREG_SR2]); 673 OUT_RING(0); 674 675 ADVANCE_LP_RING(); 676} 677 678static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code) 679{ 680 drm_i830_private_t *dev_priv = dev->dev_private; 681 RING_LOCALS; 682 683 BEGIN_LP_RING(2); 684 OUT_RING(GFX_OP_STIPPLE); 685 OUT_RING(code[1]); 686 ADVANCE_LP_RING(); 687} 688 689static void i830EmitState(struct drm_device * dev) 690{ 691 drm_i830_private_t *dev_priv = dev->dev_private; 692 drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; 693 unsigned int dirty = sarea_priv->dirty; 694 695 DRM_DEBUG("%s %x\n", __func__, dirty); 696 697 if (dirty & I830_UPLOAD_BUFFERS) { 698 i830EmitDestVerified(dev, sarea_priv->BufferState); 699 sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS; 700 } 701 702 if (dirty & I830_UPLOAD_CTX) { 703 i830EmitContextVerified(dev, sarea_priv->ContextState); 704 sarea_priv->dirty &= ~I830_UPLOAD_CTX; 705 } 706 707 if (dirty & I830_UPLOAD_TEX0) { 708 i830EmitTexVerified(dev, sarea_priv->TexState[0]); 709 sarea_priv->dirty &= ~I830_UPLOAD_TEX0; 710 } 711 712 if (dirty & I830_UPLOAD_TEX1) { 713 i830EmitTexVerified(dev, sarea_priv->TexState[1]); 714 sarea_priv->dirty &= ~I830_UPLOAD_TEX1; 715 } 716 717 if (dirty & I830_UPLOAD_TEXBLEND0) { 718 i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[0], 719 sarea_priv->TexBlendStateWordsUsed[0]); 720 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0; 721 } 722 723 if (dirty & I830_UPLOAD_TEXBLEND1) { 724 i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[1], 725 sarea_priv->TexBlendStateWordsUsed[1]); 726 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1; 727 } 728 729 if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) { 730 i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1); 731 } else { 732 if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) { 733 i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0); 734 sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0); 735 } 736 if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) { 737 i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0); 738 sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1); 739 } 740 741 /* 1.3: 742 */ 743#if 0 744 if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) { 745 i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0); 746 sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2); 747 } 748 if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) { 749 i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0); 750 sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2); 751 } 752#endif 753 } 754 755 /* 1.3: 756 */ 757 if (dirty & I830_UPLOAD_STIPPLE) { 758 i830EmitStippleVerified(dev, sarea_priv->StippleState); 759 sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE; 760 } 761 762 if (dirty & I830_UPLOAD_TEX2) { 763 i830EmitTexVerified(dev, sarea_priv->TexState2); 764 sarea_priv->dirty &= ~I830_UPLOAD_TEX2; 765 } 766 767 if (dirty & I830_UPLOAD_TEX3) { 768 i830EmitTexVerified(dev, sarea_priv->TexState3); 769 sarea_priv->dirty &= ~I830_UPLOAD_TEX3; 770 } 771 772 if (dirty & I830_UPLOAD_TEXBLEND2) { 773 i830EmitTexBlendVerified(dev, 774 sarea_priv->TexBlendState2, 775 sarea_priv->TexBlendStateWordsUsed2); 776 777 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2; 778 } 779 780 if (dirty & I830_UPLOAD_TEXBLEND3) { 781 i830EmitTexBlendVerified(dev, 782 sarea_priv->TexBlendState3, 783 sarea_priv->TexBlendStateWordsUsed3); 784 sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3; 785 } 786} 787 788/* ================================================================ 789 * Performance monitoring functions 790 */ 791 792static void i830_fill_box(struct drm_device * dev, 793 int x, int y, int w, int h, int r, int g, int b) 794{ 795 drm_i830_private_t *dev_priv = dev->dev_private; 796 u32 color; 797 unsigned int BR13, CMD; 798 RING_LOCALS; 799 800 BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1 << 24); 801 CMD = XY_COLOR_BLT_CMD; 802 x += dev_priv->sarea_priv->boxes[0].x1; 803 y += dev_priv->sarea_priv->boxes[0].y1; 804 805 if (dev_priv->cpp == 4) { 806 BR13 |= (1 << 25); 807 CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB); 808 color = (((0xff) << 24) | (r << 16) | (g << 8) | b); 809 } else { 810 color = (((r & 0xf8) << 8) | 811 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); 812 } 813 814 BEGIN_LP_RING(6); 815 OUT_RING(CMD); 816 OUT_RING(BR13); 817 OUT_RING((y << 16) | x); 818 OUT_RING(((y + h) << 16) | (x + w)); 819 820 if (dev_priv->current_page == 1) { 821 OUT_RING(dev_priv->front_offset); 822 } else { 823 OUT_RING(dev_priv->back_offset); 824 } 825 826 OUT_RING(color); 827 ADVANCE_LP_RING(); 828} 829 830static void i830_cp_performance_boxes(struct drm_device * dev) 831{ 832 drm_i830_private_t *dev_priv = dev->dev_private; 833 834 /* Purple box for page flipping 835 */ 836 if (dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP) 837 i830_fill_box(dev, 4, 4, 8, 8, 255, 0, 255); 838 839 /* Red box if we have to wait for idle at any point 840 */ 841 if (dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT) 842 i830_fill_box(dev, 16, 4, 8, 8, 255, 0, 0); 843 844 /* Blue box: lost context? 845 */ 846 if (dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT) 847 i830_fill_box(dev, 28, 4, 8, 8, 0, 0, 255); 848 849 /* Yellow box for texture swaps 850 */ 851 if (dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD) 852 i830_fill_box(dev, 40, 4, 8, 8, 255, 255, 0); 853 854 /* Green box if hardware never idles (as far as we can tell) 855 */ 856 if (!(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY)) 857 i830_fill_box(dev, 64, 4, 8, 8, 0, 255, 0); 858 859 /* Draw bars indicating number of buffers allocated 860 * (not a great measure, easily confused) 861 */ 862 if (dev_priv->dma_used) { 863 int bar = dev_priv->dma_used / 10240; 864 if (bar > 100) 865 bar = 100; 866 if (bar < 1) 867 bar = 1; 868 i830_fill_box(dev, 4, 16, bar, 4, 196, 128, 128); 869 dev_priv->dma_used = 0; 870 } 871 872 dev_priv->sarea_priv->perf_boxes = 0; 873} 874 875static void i830_dma_dispatch_clear(struct drm_device * dev, int flags, 876 unsigned int clear_color, 877 unsigned int clear_zval, 878 unsigned int clear_depthmask) 879{ 880 drm_i830_private_t *dev_priv = dev->dev_private; 881 drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; 882 int nbox = sarea_priv->nbox; 883 struct drm_clip_rect *pbox = sarea_priv->boxes; 884 int pitch = dev_priv->pitch; 885 int cpp = dev_priv->cpp; 886 int i; 887 unsigned int BR13, CMD, D_CMD; 888 RING_LOCALS; 889 890 if (dev_priv->current_page == 1) { 891 unsigned int tmp = flags; 892 893 flags &= ~(I830_FRONT | I830_BACK); 894 if (tmp & I830_FRONT) 895 flags |= I830_BACK; 896 if (tmp & I830_BACK) 897 flags |= I830_FRONT; 898 } 899 900 i830_kernel_lost_context(dev); 901 902 switch (cpp) { 903 case 2: 904 BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24); 905 D_CMD = CMD = XY_COLOR_BLT_CMD; 906 break; 907 case 4: 908 BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25); 909 CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | 910 XY_COLOR_BLT_WRITE_RGB); 911 D_CMD = XY_COLOR_BLT_CMD; 912 if (clear_depthmask & 0x00ffffff) 913 D_CMD |= XY_COLOR_BLT_WRITE_RGB; 914 if (clear_depthmask & 0xff000000) 915 D_CMD |= XY_COLOR_BLT_WRITE_ALPHA; 916 break; 917 default: 918 BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24); 919 D_CMD = CMD = XY_COLOR_BLT_CMD; 920 break; 921 } 922 923 if (nbox > I830_NR_SAREA_CLIPRECTS) 924 nbox = I830_NR_SAREA_CLIPRECTS; 925 926 for (i = 0; i < nbox; i++, pbox++) { 927 if (pbox->x1 > pbox->x2 || 928 pbox->y1 > pbox->y2 || 929 pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h) 930 continue; 931 932 if (flags & I830_FRONT) { 933 DRM_DEBUG("clear front\n"); 934 BEGIN_LP_RING(6); 935 OUT_RING(CMD); 936 OUT_RING(BR13); 937 OUT_RING((pbox->y1 << 16) | pbox->x1); 938 OUT_RING((pbox->y2 << 16) | pbox->x2); 939 OUT_RING(dev_priv->front_offset); 940 OUT_RING(clear_color); 941 ADVANCE_LP_RING(); 942 } 943 944 if (flags & I830_BACK) { 945 DRM_DEBUG("clear back\n"); 946 BEGIN_LP_RING(6); 947 OUT_RING(CMD); 948 OUT_RING(BR13); 949 OUT_RING((pbox->y1 << 16) | pbox->x1); 950 OUT_RING((pbox->y2 << 16) | pbox->x2); 951 OUT_RING(dev_priv->back_offset); 952 OUT_RING(clear_color); 953 ADVANCE_LP_RING(); 954 } 955 956 if (flags & I830_DEPTH) { 957 DRM_DEBUG("clear depth\n"); 958 BEGIN_LP_RING(6); 959 OUT_RING(D_CMD); 960 OUT_RING(BR13); 961 OUT_RING((pbox->y1 << 16) | pbox->x1); 962 OUT_RING((pbox->y2 << 16) | pbox->x2); 963 OUT_RING(dev_priv->depth_offset); 964 OUT_RING(clear_zval); 965 ADVANCE_LP_RING(); 966 } 967 } 968} 969 970static void i830_dma_dispatch_swap(struct drm_device * dev) 971{ 972 drm_i830_private_t *dev_priv = dev->dev_private; 973 drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; 974 int nbox = sarea_priv->nbox; 975 struct drm_clip_rect *pbox = sarea_priv->boxes; 976 int pitch = dev_priv->pitch; 977 int cpp = dev_priv->cpp; 978 int i; 979 unsigned int CMD, BR13; 980 RING_LOCALS; 981 982 DRM_DEBUG("swapbuffers\n"); 983 984 i830_kernel_lost_context(dev); 985 986 if (dev_priv->do_boxes) 987 i830_cp_performance_boxes(dev); 988 989 switch (cpp) { 990 case 2: 991 BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); 992 CMD = XY_SRC_COPY_BLT_CMD; 993 break; 994 case 4: 995 BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25); 996 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | 997 XY_SRC_COPY_BLT_WRITE_RGB); 998 break; 999 default: 1000 BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); 1001 CMD = XY_SRC_COPY_BLT_CMD; 1002 break; 1003 } 1004 1005 if (nbox > I830_NR_SAREA_CLIPRECTS) 1006 nbox = I830_NR_SAREA_CLIPRECTS; 1007 1008 for (i = 0; i < nbox; i++, pbox++) { 1009 if (pbox->x1 > pbox->x2 || 1010 pbox->y1 > pbox->y2 || 1011 pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h) 1012 continue; 1013 1014 DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n", 1015 pbox->x1, pbox->y1, pbox->x2, pbox->y2); 1016 1017 BEGIN_LP_RING(8); 1018 OUT_RING(CMD); 1019 OUT_RING(BR13); 1020 OUT_RING((pbox->y1 << 16) | pbox->x1); 1021 OUT_RING((pbox->y2 << 16) | pbox->x2); 1022 1023 if (dev_priv->current_page == 0) 1024 OUT_RING(dev_priv->front_offset); 1025 else 1026 OUT_RING(dev_priv->back_offset); 1027 1028 OUT_RING((pbox->y1 << 16) | pbox->x1); 1029 OUT_RING(BR13 & 0xffff); 1030 1031 if (dev_priv->current_page == 0) 1032 OUT_RING(dev_priv->back_offset); 1033 else 1034 OUT_RING(dev_priv->front_offset); 1035 1036 ADVANCE_LP_RING(); 1037 } 1038} 1039 1040static void i830_dma_dispatch_flip(struct drm_device * dev) 1041{ 1042 drm_i830_private_t *dev_priv = dev->dev_private; 1043 RING_LOCALS; 1044 1045 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", 1046 __func__, 1047 dev_priv->current_page, 1048 dev_priv->sarea_priv->pf_current_page); 1049 1050 i830_kernel_lost_context(dev); 1051 1052 if (dev_priv->do_boxes) { 1053 dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP; 1054 i830_cp_performance_boxes(dev); 1055 } 1056 1057 BEGIN_LP_RING(2); 1058 OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); 1059 OUT_RING(0); 1060 ADVANCE_LP_RING(); 1061 1062 BEGIN_LP_RING(6); 1063 OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP); 1064 OUT_RING(0); 1065 if (dev_priv->current_page == 0) { 1066 OUT_RING(dev_priv->back_offset); 1067 dev_priv->current_page = 1; 1068 } else { 1069 OUT_RING(dev_priv->front_offset); 1070 dev_priv->current_page = 0; 1071 } 1072 OUT_RING(0); 1073 ADVANCE_LP_RING(); 1074 1075 BEGIN_LP_RING(2); 1076 OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); 1077 OUT_RING(0); 1078 ADVANCE_LP_RING(); 1079 1080 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; 1081} 1082 1083static void i830_dma_dispatch_vertex(struct drm_device * dev, 1084 struct drm_buf * buf, int discard, int used) 1085{ 1086 drm_i830_private_t *dev_priv = dev->dev_private; 1087 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 1088 drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv; 1089 struct drm_clip_rect *box = sarea_priv->boxes; 1090 int nbox = sarea_priv->nbox; 1091 unsigned long address = (unsigned long)buf->bus_address; 1092 unsigned long start = address - dev->agp->base; 1093 int i = 0, u; 1094 RING_LOCALS; 1095 1096 i830_kernel_lost_context(dev); 1097 1098 if (nbox > I830_NR_SAREA_CLIPRECTS) 1099 nbox = I830_NR_SAREA_CLIPRECTS; 1100 1101 if (discard) { 1102 u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 1103 I830_BUF_HARDWARE); 1104 if (u != I830_BUF_CLIENT) { 1105 DRM_DEBUG("xxxx 2\n"); 1106 } 1107 } 1108 1109 if (used > 4 * 1023) 1110 used = 0; 1111 1112 if (sarea_priv->dirty) 1113 i830EmitState(dev); 1114 1115 DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n", 1116 address, used, nbox); 1117 1118 dev_priv->counter++; 1119 DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter); 1120 DRM_DEBUG("i830_dma_dispatch\n"); 1121 DRM_DEBUG("start : %lx\n", start); 1122 DRM_DEBUG("used : %d\n", used); 1123 DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4); 1124 1125 if (buf_priv->currently_mapped == I830_BUF_MAPPED) { 1126 u32 *vp = buf_priv->kernel_virtual; 1127 1128 vp[0] = (GFX_OP_PRIMITIVE | 1129 sarea_priv->vertex_prim | ((used / 4) - 2)); 1130 1131 if (dev_priv->use_mi_batchbuffer_start) { 1132 vp[used / 4] = MI_BATCH_BUFFER_END; 1133 used += 4; 1134 } 1135 1136 if (used & 4) { 1137 vp[used / 4] = 0; 1138 used += 4; 1139 } 1140 1141 i830_unmap_buffer(buf); 1142 } 1143 1144 if (used) { 1145 do { 1146 if (i < nbox) { 1147 BEGIN_LP_RING(6); 1148 OUT_RING(GFX_OP_DRAWRECT_INFO); 1149 OUT_RING(sarea_priv-> 1150 BufferState[I830_DESTREG_DR1]); 1151 OUT_RING(box[i].x1 | (box[i].y1 << 16)); 1152 OUT_RING(box[i].x2 | (box[i].y2 << 16)); 1153 OUT_RING(sarea_priv-> 1154 BufferState[I830_DESTREG_DR4]); 1155 OUT_RING(0); 1156 ADVANCE_LP_RING(); 1157 } 1158 1159 if (dev_priv->use_mi_batchbuffer_start) { 1160 BEGIN_LP_RING(2); 1161 OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); 1162 OUT_RING(start | MI_BATCH_NON_SECURE); 1163 ADVANCE_LP_RING(); 1164 } else { 1165 BEGIN_LP_RING(4); 1166 OUT_RING(MI_BATCH_BUFFER); 1167 OUT_RING(start | MI_BATCH_NON_SECURE); 1168 OUT_RING(start + used - 4); 1169 OUT_RING(0); 1170 ADVANCE_LP_RING(); 1171 } 1172 1173 } while (++i < nbox); 1174 } 1175 1176 if (discard) { 1177 dev_priv->counter++; 1178 1179 (void)cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 1180 I830_BUF_HARDWARE); 1181 1182 BEGIN_LP_RING(8); 1183 OUT_RING(CMD_STORE_DWORD_IDX); 1184 OUT_RING(20); 1185 OUT_RING(dev_priv->counter); 1186 OUT_RING(CMD_STORE_DWORD_IDX); 1187 OUT_RING(buf_priv->my_use_idx); 1188 OUT_RING(I830_BUF_FREE); 1189 OUT_RING(CMD_REPORT_HEAD); 1190 OUT_RING(0); 1191 ADVANCE_LP_RING(); 1192 } 1193} 1194 1195static void i830_dma_quiescent(struct drm_device * dev) 1196{ 1197 drm_i830_private_t *dev_priv = dev->dev_private; 1198 RING_LOCALS; 1199 1200 i830_kernel_lost_context(dev); 1201 1202 BEGIN_LP_RING(4); 1203 OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); 1204 OUT_RING(CMD_REPORT_HEAD); 1205 OUT_RING(0); 1206 OUT_RING(0); 1207 ADVANCE_LP_RING(); 1208 1209 i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__); 1210} 1211 1212static int i830_flush_queue(struct drm_device * dev) 1213{ 1214 drm_i830_private_t *dev_priv = dev->dev_private; 1215 struct drm_device_dma *dma = dev->dma; 1216 int i, ret = 0; 1217 RING_LOCALS; 1218 1219 i830_kernel_lost_context(dev); 1220 1221 BEGIN_LP_RING(2); 1222 OUT_RING(CMD_REPORT_HEAD); 1223 OUT_RING(0); 1224 ADVANCE_LP_RING(); 1225 1226 i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__); 1227 1228 for (i = 0; i < dma->buf_count; i++) { 1229 struct drm_buf *buf = dma->buflist[i]; 1230 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 1231 1232 int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE, 1233 I830_BUF_FREE); 1234 1235 if (used == I830_BUF_HARDWARE) 1236 DRM_DEBUG("reclaimed from HARDWARE\n"); 1237 if (used == I830_BUF_CLIENT) 1238 DRM_DEBUG("still on client\n"); 1239 } 1240 1241 return ret; 1242} 1243 1244/* Must be called with the lock held */ 1245static void i830_reclaim_buffers(struct drm_device * dev, struct drm_file *file_priv) 1246{ 1247 struct drm_device_dma *dma = dev->dma; 1248 int i; 1249 1250 if (!dma) 1251 return; 1252 if (!dev->dev_private) 1253 return; 1254 if (!dma->buflist) 1255 return; 1256 1257 i830_flush_queue(dev); 1258 1259 for (i = 0; i < dma->buf_count; i++) { 1260 struct drm_buf *buf = dma->buflist[i]; 1261 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 1262 1263 if (buf->file_priv == file_priv && buf_priv) { 1264 int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, 1265 I830_BUF_FREE); 1266 1267 if (used == I830_BUF_CLIENT) 1268 DRM_DEBUG("reclaimed from client\n"); 1269 if (buf_priv->currently_mapped == I830_BUF_MAPPED) 1270 buf_priv->currently_mapped = I830_BUF_UNMAPPED; 1271 } 1272 } 1273} 1274 1275static int i830_flush_ioctl(struct drm_device *dev, void *data, 1276 struct drm_file *file_priv) 1277{ 1278 LOCK_TEST_WITH_RETURN(dev, file_priv); 1279 1280 i830_flush_queue(dev); 1281 return 0; 1282} 1283 1284static int i830_dma_vertex(struct drm_device *dev, void *data, 1285 struct drm_file *file_priv) 1286{ 1287 struct drm_device_dma *dma = dev->dma; 1288 drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; 1289 u32 *hw_status = dev_priv->hw_status_page; 1290 drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 1291 dev_priv->sarea_priv; 1292 drm_i830_vertex_t *vertex = data; 1293 1294 LOCK_TEST_WITH_RETURN(dev, file_priv); 1295 1296 DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n", 1297 vertex->idx, vertex->used, vertex->discard); 1298 1299 if (vertex->idx < 0 || vertex->idx > dma->buf_count) 1300 return -EINVAL; 1301 1302 i830_dma_dispatch_vertex(dev, 1303 dma->buflist[vertex->idx], 1304 vertex->discard, vertex->used); 1305 1306 sarea_priv->last_enqueue = dev_priv->counter - 1; 1307 sarea_priv->last_dispatch = (int)hw_status[5]; 1308 1309 return 0; 1310} 1311 1312static int i830_clear_bufs(struct drm_device *dev, void *data, 1313 struct drm_file *file_priv) 1314{ 1315 drm_i830_clear_t *clear = data; 1316 1317 LOCK_TEST_WITH_RETURN(dev, file_priv); 1318 1319 /* GH: Someone's doing nasty things... */ 1320 if (!dev->dev_private) { 1321 return -EINVAL; 1322 } 1323 1324 i830_dma_dispatch_clear(dev, clear->flags, 1325 clear->clear_color, 1326 clear->clear_depth, clear->clear_depthmask); 1327 return 0; 1328} 1329 1330static int i830_swap_bufs(struct drm_device *dev, void *data, 1331 struct drm_file *file_priv) 1332{ 1333 DRM_DEBUG("i830_swap_bufs\n"); 1334 1335 LOCK_TEST_WITH_RETURN(dev, file_priv); 1336 1337 i830_dma_dispatch_swap(dev); 1338 return 0; 1339} 1340 1341/* Not sure why this isn't set all the time: 1342 */ 1343static void i830_do_init_pageflip(struct drm_device * dev) 1344{ 1345 drm_i830_private_t *dev_priv = dev->dev_private; 1346 1347 DRM_DEBUG("%s\n", __func__); 1348 dev_priv->page_flipping = 1; 1349 dev_priv->current_page = 0; 1350 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; 1351} 1352 1353static int i830_do_cleanup_pageflip(struct drm_device * dev) 1354{ 1355 drm_i830_private_t *dev_priv = dev->dev_private; 1356 1357 DRM_DEBUG("%s\n", __func__); 1358 if (dev_priv->current_page != 0) 1359 i830_dma_dispatch_flip(dev); 1360 1361 dev_priv->page_flipping = 0; 1362 return 0; 1363} 1364 1365static int i830_flip_bufs(struct drm_device *dev, void *data, 1366 struct drm_file *file_priv) 1367{ 1368 drm_i830_private_t *dev_priv = dev->dev_private; 1369 1370 DRM_DEBUG("%s\n", __func__); 1371 1372 LOCK_TEST_WITH_RETURN(dev, file_priv); 1373 1374 if (!dev_priv->page_flipping) 1375 i830_do_init_pageflip(dev); 1376 1377 i830_dma_dispatch_flip(dev); 1378 return 0; 1379} 1380 1381static int i830_getage(struct drm_device *dev, void *data, 1382 struct drm_file *file_priv) 1383{ 1384 drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; 1385 u32 *hw_status = dev_priv->hw_status_page; 1386 drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 1387 dev_priv->sarea_priv; 1388 1389 sarea_priv->last_dispatch = (int)hw_status[5]; 1390 return 0; 1391} 1392 1393static int i830_getbuf(struct drm_device *dev, void *data, 1394 struct drm_file *file_priv) 1395{ 1396 int retcode = 0; 1397 drm_i830_dma_t *d = data; 1398 drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; 1399 u32 *hw_status = dev_priv->hw_status_page; 1400 drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 1401 dev_priv->sarea_priv; 1402 1403 DRM_DEBUG("getbuf\n"); 1404 1405 LOCK_TEST_WITH_RETURN(dev, file_priv); 1406 1407 d->granted = 0; 1408 1409 retcode = i830_dma_get_buffer(dev, d, file_priv); 1410 1411 DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n", 1412 task_pid_nr(current), retcode, d->granted); 1413 1414 sarea_priv->last_dispatch = (int)hw_status[5]; 1415 1416 return retcode; 1417} 1418 1419static int i830_copybuf(struct drm_device *dev, void *data, 1420 struct drm_file *file_priv) 1421{ 1422 /* Never copy - 2.4.x doesn't need it */ 1423 return 0; 1424} 1425 1426static int i830_docopy(struct drm_device *dev, void *data, 1427 struct drm_file *file_priv) 1428{ 1429 return 0; 1430} 1431 1432static int i830_getparam(struct drm_device *dev, void *data, 1433 struct drm_file *file_priv) 1434{ 1435 drm_i830_private_t *dev_priv = dev->dev_private; 1436 drm_i830_getparam_t *param = data; 1437 int value; 1438 1439 if (!dev_priv) { 1440 DRM_ERROR("%s called with no initialization\n", __func__); 1441 return -EINVAL; 1442 } 1443 1444 switch (param->param) { 1445 case I830_PARAM_IRQ_ACTIVE: 1446 value = dev->irq_enabled; 1447 break; 1448 default: 1449 return -EINVAL; 1450 } 1451 1452 if (copy_to_user(param->value, &value, sizeof(int))) { 1453 DRM_ERROR("copy_to_user\n"); 1454 return -EFAULT; 1455 } 1456 1457 return 0; 1458} 1459 1460static int i830_setparam(struct drm_device *dev, void *data, 1461 struct drm_file *file_priv) 1462{ 1463 drm_i830_private_t *dev_priv = dev->dev_private; 1464 drm_i830_setparam_t *param = data; 1465 1466 if (!dev_priv) { 1467 DRM_ERROR("%s called with no initialization\n", __func__); 1468 return -EINVAL; 1469 } 1470 1471 switch (param->param) { 1472 case I830_SETPARAM_USE_MI_BATCHBUFFER_START: 1473 dev_priv->use_mi_batchbuffer_start = param->value; 1474 break; 1475 default: 1476 return -EINVAL; 1477 } 1478 1479 return 0; 1480} 1481 1482int i830_driver_load(struct drm_device *dev, unsigned long flags) 1483{ 1484 /* i830 has 4 more counters */ 1485 dev->counters += 4; 1486 dev->types[6] = _DRM_STAT_IRQ; 1487 dev->types[7] = _DRM_STAT_PRIMARY; 1488 dev->types[8] = _DRM_STAT_SECONDARY; 1489 dev->types[9] = _DRM_STAT_DMA; 1490 1491 return 0; 1492} 1493 1494void i830_driver_lastclose(struct drm_device * dev) 1495{ 1496 i830_dma_cleanup(dev); 1497} 1498 1499void i830_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) 1500{ 1501 if (dev->dev_private) { 1502 drm_i830_private_t *dev_priv = dev->dev_private; 1503 if (dev_priv->page_flipping) { 1504 i830_do_cleanup_pageflip(dev); 1505 } 1506 } 1507} 1508 1509void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct drm_file *file_priv) 1510{ 1511 i830_reclaim_buffers(dev, file_priv); 1512} 1513 1514int i830_driver_dma_quiescent(struct drm_device * dev) 1515{ 1516 i830_dma_quiescent(dev); 1517 return 0; 1518} 1519 1520struct drm_ioctl_desc i830_ioctls[] = { 1521 DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1522 DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH), 1523 DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH), 1524 DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH), 1525 DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH), 1526 DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH), 1527 DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH), 1528 DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH), 1529 DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH), 1530 DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH), 1531 DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH), 1532 DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH), 1533 DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH), 1534 DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH) 1535}; 1536 1537int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); 1538 1539/** 1540 * Determine if the device really is AGP or not. 1541 * 1542 * All Intel graphics chipsets are treated as AGP, even if they are really 1543 * PCI-e. 1544 * 1545 * \param dev The device to be tested. 1546 * 1547 * \returns 1548 * A value of 1 is always retured to indictate every i8xx is AGP. 1549 */ 1550int i830_driver_device_is_agp(struct drm_device * dev) 1551{ 1552 return 1; 1553}