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.31-rc2 757 lines 21 kB view raw
1/* via_dma.c -- DMA support for the VIA Unichrome/Pro 2 * 3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A. 7 * All Rights Reserved. 8 * 9 * Copyright 2004 The Unichrome project. 10 * All Rights Reserved. 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a 13 * copy of this software and associated documentation files (the "Software"), 14 * to deal in the Software without restriction, including without limitation 15 * the rights to use, copy, modify, merge, publish, distribute, sub license, 16 * and/or sell copies of the Software, and to permit persons to whom the 17 * Software is furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice (including the 20 * next paragraph) shall be included in all copies or substantial portions 21 * of the Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 26 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 27 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 28 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 29 * USE OR OTHER DEALINGS IN THE SOFTWARE. 30 * 31 * Authors: 32 * Tungsten Graphics, 33 * Erdi Chen, 34 * Thomas Hellstrom. 35 */ 36 37#include "drmP.h" 38#include "drm.h" 39#include "via_drm.h" 40#include "via_drv.h" 41#include "via_3d_reg.h" 42 43#define CMDBUF_ALIGNMENT_SIZE (0x100) 44#define CMDBUF_ALIGNMENT_MASK (0x0ff) 45 46/* defines for VIA 3D registers */ 47#define VIA_REG_STATUS 0x400 48#define VIA_REG_TRANSET 0x43C 49#define VIA_REG_TRANSPACE 0x440 50 51/* VIA_REG_STATUS(0x400): Engine Status */ 52#define VIA_CMD_RGTR_BUSY 0x00000080 /* Command Regulator is busy */ 53#define VIA_2D_ENG_BUSY 0x00000001 /* 2D Engine is busy */ 54#define VIA_3D_ENG_BUSY 0x00000002 /* 3D Engine is busy */ 55#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */ 56 57#define SetReg2DAGP(nReg, nData) { \ 58 *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \ 59 *((uint32_t *)(vb) + 1) = (nData); \ 60 vb = ((uint32_t *)vb) + 2; \ 61 dev_priv->dma_low +=8; \ 62} 63 64#define via_flush_write_combine() DRM_MEMORYBARRIER() 65 66#define VIA_OUT_RING_QW(w1,w2) \ 67 *vb++ = (w1); \ 68 *vb++ = (w2); \ 69 dev_priv->dma_low += 8; 70 71static void via_cmdbuf_start(drm_via_private_t * dev_priv); 72static void via_cmdbuf_pause(drm_via_private_t * dev_priv); 73static void via_cmdbuf_reset(drm_via_private_t * dev_priv); 74static void via_cmdbuf_rewind(drm_via_private_t * dev_priv); 75static int via_wait_idle(drm_via_private_t * dev_priv); 76static void via_pad_cache(drm_via_private_t * dev_priv, int qwords); 77 78/* 79 * Free space in command buffer. 80 */ 81 82static uint32_t via_cmdbuf_space(drm_via_private_t * dev_priv) 83{ 84 uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 85 uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; 86 87 return ((hw_addr <= dev_priv->dma_low) ? 88 (dev_priv->dma_high + hw_addr - dev_priv->dma_low) : 89 (hw_addr - dev_priv->dma_low)); 90} 91 92/* 93 * How much does the command regulator lag behind? 94 */ 95 96static uint32_t via_cmdbuf_lag(drm_via_private_t * dev_priv) 97{ 98 uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 99 uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; 100 101 return ((hw_addr <= dev_priv->dma_low) ? 102 (dev_priv->dma_low - hw_addr) : 103 (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr)); 104} 105 106/* 107 * Check that the given size fits in the buffer, otherwise wait. 108 */ 109 110static inline int 111via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size) 112{ 113 uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 114 uint32_t cur_addr, hw_addr, next_addr; 115 volatile uint32_t *hw_addr_ptr; 116 uint32_t count; 117 hw_addr_ptr = dev_priv->hw_addr_ptr; 118 cur_addr = dev_priv->dma_low; 119 next_addr = cur_addr + size + 512 * 1024; 120 count = 1000000; 121 do { 122 hw_addr = *hw_addr_ptr - agp_base; 123 if (count-- == 0) { 124 DRM_ERROR 125 ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n", 126 hw_addr, cur_addr, next_addr); 127 return -1; 128 } 129 if ((cur_addr < hw_addr) && (next_addr >= hw_addr)) 130 msleep(1); 131 } while ((cur_addr < hw_addr) && (next_addr >= hw_addr)); 132 return 0; 133} 134 135/* 136 * Checks whether buffer head has reach the end. Rewind the ring buffer 137 * when necessary. 138 * 139 * Returns virtual pointer to ring buffer. 140 */ 141 142static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv, 143 unsigned int size) 144{ 145 if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) > 146 dev_priv->dma_high) { 147 via_cmdbuf_rewind(dev_priv); 148 } 149 if (via_cmdbuf_wait(dev_priv, size) != 0) { 150 return NULL; 151 } 152 153 return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low); 154} 155 156int via_dma_cleanup(struct drm_device * dev) 157{ 158 if (dev->dev_private) { 159 drm_via_private_t *dev_priv = 160 (drm_via_private_t *) dev->dev_private; 161 162 if (dev_priv->ring.virtual_start) { 163 via_cmdbuf_reset(dev_priv); 164 165 drm_core_ioremapfree(&dev_priv->ring.map, dev); 166 dev_priv->ring.virtual_start = NULL; 167 } 168 169 } 170 171 return 0; 172} 173 174static int via_initialize(struct drm_device * dev, 175 drm_via_private_t * dev_priv, 176 drm_via_dma_init_t * init) 177{ 178 if (!dev_priv || !dev_priv->mmio) { 179 DRM_ERROR("via_dma_init called before via_map_init\n"); 180 return -EFAULT; 181 } 182 183 if (dev_priv->ring.virtual_start != NULL) { 184 DRM_ERROR("called again without calling cleanup\n"); 185 return -EFAULT; 186 } 187 188 if (!dev->agp || !dev->agp->base) { 189 DRM_ERROR("called with no agp memory available\n"); 190 return -EFAULT; 191 } 192 193 if (dev_priv->chipset == VIA_DX9_0) { 194 DRM_ERROR("AGP DMA is not supported on this chip\n"); 195 return -EINVAL; 196 } 197 198 dev_priv->ring.map.offset = dev->agp->base + init->offset; 199 dev_priv->ring.map.size = init->size; 200 dev_priv->ring.map.type = 0; 201 dev_priv->ring.map.flags = 0; 202 dev_priv->ring.map.mtrr = 0; 203 204 drm_core_ioremap(&dev_priv->ring.map, dev); 205 206 if (dev_priv->ring.map.handle == NULL) { 207 via_dma_cleanup(dev); 208 DRM_ERROR("can not ioremap virtual address for" 209 " ring buffer\n"); 210 return -ENOMEM; 211 } 212 213 dev_priv->ring.virtual_start = dev_priv->ring.map.handle; 214 215 dev_priv->dma_ptr = dev_priv->ring.virtual_start; 216 dev_priv->dma_low = 0; 217 dev_priv->dma_high = init->size; 218 dev_priv->dma_wrap = init->size; 219 dev_priv->dma_offset = init->offset; 220 dev_priv->last_pause_ptr = NULL; 221 dev_priv->hw_addr_ptr = 222 (volatile uint32_t *)((char *)dev_priv->mmio->handle + 223 init->reg_pause_addr); 224 225 via_cmdbuf_start(dev_priv); 226 227 return 0; 228} 229 230static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv) 231{ 232 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; 233 drm_via_dma_init_t *init = data; 234 int retcode = 0; 235 236 switch (init->func) { 237 case VIA_INIT_DMA: 238 if (!DRM_SUSER(DRM_CURPROC)) 239 retcode = -EPERM; 240 else 241 retcode = via_initialize(dev, dev_priv, init); 242 break; 243 case VIA_CLEANUP_DMA: 244 if (!DRM_SUSER(DRM_CURPROC)) 245 retcode = -EPERM; 246 else 247 retcode = via_dma_cleanup(dev); 248 break; 249 case VIA_DMA_INITIALIZED: 250 retcode = (dev_priv->ring.virtual_start != NULL) ? 251 0 : -EFAULT; 252 break; 253 default: 254 retcode = -EINVAL; 255 break; 256 } 257 258 return retcode; 259} 260 261static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * cmd) 262{ 263 drm_via_private_t *dev_priv; 264 uint32_t *vb; 265 int ret; 266 267 dev_priv = (drm_via_private_t *) dev->dev_private; 268 269 if (dev_priv->ring.virtual_start == NULL) { 270 DRM_ERROR("called without initializing AGP ring buffer.\n"); 271 return -EFAULT; 272 } 273 274 if (cmd->size > VIA_PCI_BUF_SIZE) { 275 return -ENOMEM; 276 } 277 278 if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) 279 return -EFAULT; 280 281 /* 282 * Running this function on AGP memory is dead slow. Therefore 283 * we run it on a temporary cacheable system memory buffer and 284 * copy it to AGP memory when ready. 285 */ 286 287 if ((ret = 288 via_verify_command_stream((uint32_t *) dev_priv->pci_buf, 289 cmd->size, dev, 1))) { 290 return ret; 291 } 292 293 vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size); 294 if (vb == NULL) { 295 return -EAGAIN; 296 } 297 298 memcpy(vb, dev_priv->pci_buf, cmd->size); 299 300 dev_priv->dma_low += cmd->size; 301 302 /* 303 * Small submissions somehow stalls the CPU. (AGP cache effects?) 304 * pad to greater size. 305 */ 306 307 if (cmd->size < 0x100) 308 via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3); 309 via_cmdbuf_pause(dev_priv); 310 311 return 0; 312} 313 314int via_driver_dma_quiescent(struct drm_device * dev) 315{ 316 drm_via_private_t *dev_priv = dev->dev_private; 317 318 if (!via_wait_idle(dev_priv)) { 319 return -EBUSY; 320 } 321 return 0; 322} 323 324static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) 325{ 326 327 LOCK_TEST_WITH_RETURN(dev, file_priv); 328 329 return via_driver_dma_quiescent(dev); 330} 331 332static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) 333{ 334 drm_via_cmdbuffer_t *cmdbuf = data; 335 int ret; 336 337 LOCK_TEST_WITH_RETURN(dev, file_priv); 338 339 DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); 340 341 ret = via_dispatch_cmdbuffer(dev, cmdbuf); 342 if (ret) { 343 return ret; 344 } 345 346 return 0; 347} 348 349static int via_dispatch_pci_cmdbuffer(struct drm_device * dev, 350 drm_via_cmdbuffer_t * cmd) 351{ 352 drm_via_private_t *dev_priv = dev->dev_private; 353 int ret; 354 355 if (cmd->size > VIA_PCI_BUF_SIZE) { 356 return -ENOMEM; 357 } 358 if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) 359 return -EFAULT; 360 361 if ((ret = 362 via_verify_command_stream((uint32_t *) dev_priv->pci_buf, 363 cmd->size, dev, 0))) { 364 return ret; 365 } 366 367 ret = 368 via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf, 369 cmd->size); 370 return ret; 371} 372 373static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) 374{ 375 drm_via_cmdbuffer_t *cmdbuf = data; 376 int ret; 377 378 LOCK_TEST_WITH_RETURN(dev, file_priv); 379 380 DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); 381 382 ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf); 383 if (ret) { 384 return ret; 385 } 386 387 return 0; 388} 389 390static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv, 391 uint32_t * vb, int qw_count) 392{ 393 for (; qw_count > 0; --qw_count) { 394 VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY); 395 } 396 return vb; 397} 398 399/* 400 * This function is used internally by ring buffer management code. 401 * 402 * Returns virtual pointer to ring buffer. 403 */ 404static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv) 405{ 406 return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low); 407} 408 409/* 410 * Hooks a segment of data into the tail of the ring-buffer by 411 * modifying the pause address stored in the buffer itself. If 412 * the regulator has already paused, restart it. 413 */ 414static int via_hook_segment(drm_via_private_t * dev_priv, 415 uint32_t pause_addr_hi, uint32_t pause_addr_lo, 416 int no_pci_fire) 417{ 418 int paused, count; 419 volatile uint32_t *paused_at = dev_priv->last_pause_ptr; 420 uint32_t reader,ptr; 421 uint32_t diff; 422 423 paused = 0; 424 via_flush_write_combine(); 425 (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1); 426 427 *paused_at = pause_addr_lo; 428 via_flush_write_combine(); 429 (void) *paused_at; 430 431 reader = *(dev_priv->hw_addr_ptr); 432 ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + 433 dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; 434 435 dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; 436 437 /* 438 * If there is a possibility that the command reader will 439 * miss the new pause address and pause on the old one, 440 * In that case we need to program the new start address 441 * using PCI. 442 */ 443 444 diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; 445 count = 10000000; 446 while(diff == 0 && count--) { 447 paused = (VIA_READ(0x41c) & 0x80000000); 448 if (paused) 449 break; 450 reader = *(dev_priv->hw_addr_ptr); 451 diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; 452 } 453 454 paused = VIA_READ(0x41c) & 0x80000000; 455 456 if (paused && !no_pci_fire) { 457 reader = *(dev_priv->hw_addr_ptr); 458 diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; 459 diff &= (dev_priv->dma_high - 1); 460 if (diff != 0 && diff < (dev_priv->dma_high >> 1)) { 461 DRM_ERROR("Paused at incorrect address. " 462 "0x%08x, 0x%08x 0x%08x\n", 463 ptr, reader, dev_priv->dma_diff); 464 } else if (diff == 0) { 465 /* 466 * There is a concern that these writes may stall the PCI bus 467 * if the GPU is not idle. However, idling the GPU first 468 * doesn't make a difference. 469 */ 470 471 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); 472 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); 473 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); 474 VIA_READ(VIA_REG_TRANSPACE); 475 } 476 } 477 return paused; 478} 479 480static int via_wait_idle(drm_via_private_t * dev_priv) 481{ 482 int count = 10000000; 483 484 while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count) 485 ; 486 487 while (count && (VIA_READ(VIA_REG_STATUS) & 488 (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | 489 VIA_3D_ENG_BUSY))) 490 --count; 491 return count; 492} 493 494static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type, 495 uint32_t addr, uint32_t * cmd_addr_hi, 496 uint32_t * cmd_addr_lo, int skip_wait) 497{ 498 uint32_t agp_base; 499 uint32_t cmd_addr, addr_lo, addr_hi; 500 uint32_t *vb; 501 uint32_t qw_pad_count; 502 503 if (!skip_wait) 504 via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE); 505 506 vb = via_get_dma(dev_priv); 507 VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) | 508 (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16); 509 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 510 qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) - 511 ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3); 512 513 cmd_addr = (addr) ? addr : 514 agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3); 515 addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) | 516 (cmd_addr & HC_HAGPBpL_MASK)); 517 addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24)); 518 519 vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1); 520 VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo); 521 return vb; 522} 523 524static void via_cmdbuf_start(drm_via_private_t * dev_priv) 525{ 526 uint32_t pause_addr_lo, pause_addr_hi; 527 uint32_t start_addr, start_addr_lo; 528 uint32_t end_addr, end_addr_lo; 529 uint32_t command; 530 uint32_t agp_base; 531 uint32_t ptr; 532 uint32_t reader; 533 int count; 534 535 dev_priv->dma_low = 0; 536 537 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 538 start_addr = agp_base; 539 end_addr = agp_base + dev_priv->dma_high; 540 541 start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF)); 542 end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF)); 543 command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) | 544 ((end_addr & 0xff000000) >> 16)); 545 546 dev_priv->last_pause_ptr = 547 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, 548 &pause_addr_hi, &pause_addr_lo, 1) - 1; 549 550 via_flush_write_combine(); 551 (void) *(volatile uint32_t *)dev_priv->last_pause_ptr; 552 553 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); 554 VIA_WRITE(VIA_REG_TRANSPACE, command); 555 VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo); 556 VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo); 557 558 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); 559 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); 560 DRM_WRITEMEMORYBARRIER(); 561 VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); 562 VIA_READ(VIA_REG_TRANSPACE); 563 564 dev_priv->dma_diff = 0; 565 566 count = 10000000; 567 while (!(VIA_READ(0x41c) & 0x80000000) && count--); 568 569 reader = *(dev_priv->hw_addr_ptr); 570 ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + 571 dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; 572 573 /* 574 * This is the difference between where we tell the 575 * command reader to pause and where it actually pauses. 576 * This differs between hw implementation so we need to 577 * detect it. 578 */ 579 580 dev_priv->dma_diff = ptr - reader; 581} 582 583static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) 584{ 585 uint32_t *vb; 586 587 via_cmdbuf_wait(dev_priv, qwords + 2); 588 vb = via_get_dma(dev_priv); 589 VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16); 590 via_align_buffer(dev_priv, vb, qwords); 591} 592 593static inline void via_dummy_bitblt(drm_via_private_t * dev_priv) 594{ 595 uint32_t *vb = via_get_dma(dev_priv); 596 SetReg2DAGP(0x0C, (0 | (0 << 16))); 597 SetReg2DAGP(0x10, 0 | (0 << 16)); 598 SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000); 599} 600 601static void via_cmdbuf_jump(drm_via_private_t * dev_priv) 602{ 603 uint32_t agp_base; 604 uint32_t pause_addr_lo, pause_addr_hi; 605 uint32_t jump_addr_lo, jump_addr_hi; 606 volatile uint32_t *last_pause_ptr; 607 uint32_t dma_low_save1, dma_low_save2; 608 609 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 610 via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, 611 &jump_addr_lo, 0); 612 613 dev_priv->dma_wrap = dev_priv->dma_low; 614 615 /* 616 * Wrap command buffer to the beginning. 617 */ 618 619 dev_priv->dma_low = 0; 620 if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) { 621 DRM_ERROR("via_cmdbuf_jump failed\n"); 622 } 623 624 via_dummy_bitblt(dev_priv); 625 via_dummy_bitblt(dev_priv); 626 627 last_pause_ptr = 628 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 629 &pause_addr_lo, 0) - 1; 630 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 631 &pause_addr_lo, 0); 632 633 *last_pause_ptr = pause_addr_lo; 634 dma_low_save1 = dev_priv->dma_low; 635 636 /* 637 * Now, set a trap that will pause the regulator if it tries to rerun the old 638 * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause 639 * and reissues the jump command over PCI, while the regulator has already taken the jump 640 * and actually paused at the current buffer end). 641 * There appears to be no other way to detect this condition, since the hw_addr_pointer 642 * does not seem to get updated immediately when a jump occurs. 643 */ 644 645 last_pause_ptr = 646 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 647 &pause_addr_lo, 0) - 1; 648 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 649 &pause_addr_lo, 0); 650 *last_pause_ptr = pause_addr_lo; 651 652 dma_low_save2 = dev_priv->dma_low; 653 dev_priv->dma_low = dma_low_save1; 654 via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); 655 dev_priv->dma_low = dma_low_save2; 656 via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); 657} 658 659 660static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) 661{ 662 via_cmdbuf_jump(dev_priv); 663} 664 665static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type) 666{ 667 uint32_t pause_addr_lo, pause_addr_hi; 668 669 via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0); 670 via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); 671} 672 673static void via_cmdbuf_pause(drm_via_private_t * dev_priv) 674{ 675 via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE); 676} 677 678static void via_cmdbuf_reset(drm_via_private_t * dev_priv) 679{ 680 via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP); 681 via_wait_idle(dev_priv); 682} 683 684/* 685 * User interface to the space and lag functions. 686 */ 687 688static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv) 689{ 690 drm_via_cmdbuf_size_t *d_siz = data; 691 int ret = 0; 692 uint32_t tmp_size, count; 693 drm_via_private_t *dev_priv; 694 695 DRM_DEBUG("\n"); 696 LOCK_TEST_WITH_RETURN(dev, file_priv); 697 698 dev_priv = (drm_via_private_t *) dev->dev_private; 699 700 if (dev_priv->ring.virtual_start == NULL) { 701 DRM_ERROR("called without initializing AGP ring buffer.\n"); 702 return -EFAULT; 703 } 704 705 count = 1000000; 706 tmp_size = d_siz->size; 707 switch (d_siz->func) { 708 case VIA_CMDBUF_SPACE: 709 while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size) 710 && --count) { 711 if (!d_siz->wait) { 712 break; 713 } 714 } 715 if (!count) { 716 DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n"); 717 ret = -EAGAIN; 718 } 719 break; 720 case VIA_CMDBUF_LAG: 721 while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size) 722 && --count) { 723 if (!d_siz->wait) { 724 break; 725 } 726 } 727 if (!count) { 728 DRM_ERROR("VIA_CMDBUF_LAG timed out.\n"); 729 ret = -EAGAIN; 730 } 731 break; 732 default: 733 ret = -EFAULT; 734 } 735 d_siz->size = tmp_size; 736 737 return ret; 738} 739 740struct drm_ioctl_desc via_ioctls[] = { 741 DRM_IOCTL_DEF(DRM_VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH), 742 DRM_IOCTL_DEF(DRM_VIA_FREEMEM, via_mem_free, DRM_AUTH), 743 DRM_IOCTL_DEF(DRM_VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER), 744 DRM_IOCTL_DEF(DRM_VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER), 745 DRM_IOCTL_DEF(DRM_VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER), 746 DRM_IOCTL_DEF(DRM_VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH), 747 DRM_IOCTL_DEF(DRM_VIA_DMA_INIT, via_dma_init, DRM_AUTH), 748 DRM_IOCTL_DEF(DRM_VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH), 749 DRM_IOCTL_DEF(DRM_VIA_FLUSH, via_flush_ioctl, DRM_AUTH), 750 DRM_IOCTL_DEF(DRM_VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH), 751 DRM_IOCTL_DEF(DRM_VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH), 752 DRM_IOCTL_DEF(DRM_VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH), 753 DRM_IOCTL_DEF(DRM_VIA_DMA_BLIT, via_dma_blit, DRM_AUTH), 754 DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH) 755}; 756 757int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);