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) do { \ 67 *vb++ = (w1); \ 68 *vb++ = (w2); \ 69 dev_priv->dma_low += 8; \ 70} while (0) 71 72static void via_cmdbuf_start(drm_via_private_t *dev_priv); 73static void via_cmdbuf_pause(drm_via_private_t *dev_priv); 74static void via_cmdbuf_reset(drm_via_private_t *dev_priv); 75static void via_cmdbuf_rewind(drm_via_private_t *dev_priv); 76static int via_wait_idle(drm_via_private_t *dev_priv); 77static void via_pad_cache(drm_via_private_t *dev_priv, int qwords); 78 79/* 80 * Free space in command buffer. 81 */ 82 83static uint32_t via_cmdbuf_space(drm_via_private_t *dev_priv) 84{ 85 uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 86 uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; 87 88 return ((hw_addr <= dev_priv->dma_low) ? 89 (dev_priv->dma_high + hw_addr - dev_priv->dma_low) : 90 (hw_addr - dev_priv->dma_low)); 91} 92 93/* 94 * How much does the command regulator lag behind? 95 */ 96 97static uint32_t via_cmdbuf_lag(drm_via_private_t *dev_priv) 98{ 99 uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 100 uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base; 101 102 return ((hw_addr <= dev_priv->dma_low) ? 103 (dev_priv->dma_low - hw_addr) : 104 (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr)); 105} 106 107/* 108 * Check that the given size fits in the buffer, otherwise wait. 109 */ 110 111static inline int 112via_cmdbuf_wait(drm_via_private_t *dev_priv, unsigned int size) 113{ 114 uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 115 uint32_t cur_addr, hw_addr, next_addr; 116 volatile uint32_t *hw_addr_ptr; 117 uint32_t count; 118 hw_addr_ptr = dev_priv->hw_addr_ptr; 119 cur_addr = dev_priv->dma_low; 120 next_addr = cur_addr + size + 512 * 1024; 121 count = 1000000; 122 do { 123 hw_addr = *hw_addr_ptr - agp_base; 124 if (count-- == 0) { 125 DRM_ERROR 126 ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n", 127 hw_addr, cur_addr, next_addr); 128 return -1; 129 } 130 if ((cur_addr < hw_addr) && (next_addr >= hw_addr)) 131 msleep(1); 132 } while ((cur_addr < hw_addr) && (next_addr >= hw_addr)); 133 return 0; 134} 135 136/* 137 * Checks whether buffer head has reach the end. Rewind the ring buffer 138 * when necessary. 139 * 140 * Returns virtual pointer to ring buffer. 141 */ 142 143static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv, 144 unsigned int size) 145{ 146 if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) > 147 dev_priv->dma_high) { 148 via_cmdbuf_rewind(dev_priv); 149 } 150 if (via_cmdbuf_wait(dev_priv, size) != 0) 151 return NULL; 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 if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) 278 return -EFAULT; 279 280 /* 281 * Running this function on AGP memory is dead slow. Therefore 282 * we run it on a temporary cacheable system memory buffer and 283 * copy it to AGP memory when ready. 284 */ 285 286 if ((ret = 287 via_verify_command_stream((uint32_t *) dev_priv->pci_buf, 288 cmd->size, dev, 1))) { 289 return ret; 290 } 291 292 vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size); 293 if (vb == NULL) 294 return -EAGAIN; 295 296 memcpy(vb, dev_priv->pci_buf, cmd->size); 297 298 dev_priv->dma_low += cmd->size; 299 300 /* 301 * Small submissions somehow stalls the CPU. (AGP cache effects?) 302 * pad to greater size. 303 */ 304 305 if (cmd->size < 0x100) 306 via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3); 307 via_cmdbuf_pause(dev_priv); 308 309 return 0; 310} 311 312int via_driver_dma_quiescent(struct drm_device *dev) 313{ 314 drm_via_private_t *dev_priv = dev->dev_private; 315 316 if (!via_wait_idle(dev_priv)) 317 return -EBUSY; 318 return 0; 319} 320 321static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) 322{ 323 324 LOCK_TEST_WITH_RETURN(dev, file_priv); 325 326 return via_driver_dma_quiescent(dev); 327} 328 329static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) 330{ 331 drm_via_cmdbuffer_t *cmdbuf = data; 332 int ret; 333 334 LOCK_TEST_WITH_RETURN(dev, file_priv); 335 336 DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); 337 338 ret = via_dispatch_cmdbuffer(dev, cmdbuf); 339 return ret; 340} 341 342static int via_dispatch_pci_cmdbuffer(struct drm_device *dev, 343 drm_via_cmdbuffer_t *cmd) 344{ 345 drm_via_private_t *dev_priv = dev->dev_private; 346 int ret; 347 348 if (cmd->size > VIA_PCI_BUF_SIZE) 349 return -ENOMEM; 350 if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) 351 return -EFAULT; 352 353 if ((ret = 354 via_verify_command_stream((uint32_t *) dev_priv->pci_buf, 355 cmd->size, dev, 0))) { 356 return ret; 357 } 358 359 ret = 360 via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf, 361 cmd->size); 362 return ret; 363} 364 365static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) 366{ 367 drm_via_cmdbuffer_t *cmdbuf = data; 368 int ret; 369 370 LOCK_TEST_WITH_RETURN(dev, file_priv); 371 372 DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size); 373 374 ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf); 375 return ret; 376} 377 378static inline uint32_t *via_align_buffer(drm_via_private_t *dev_priv, 379 uint32_t * vb, int qw_count) 380{ 381 for (; qw_count > 0; --qw_count) 382 VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY); 383 return vb; 384} 385 386/* 387 * This function is used internally by ring buffer management code. 388 * 389 * Returns virtual pointer to ring buffer. 390 */ 391static inline uint32_t *via_get_dma(drm_via_private_t *dev_priv) 392{ 393 return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low); 394} 395 396/* 397 * Hooks a segment of data into the tail of the ring-buffer by 398 * modifying the pause address stored in the buffer itself. If 399 * the regulator has already paused, restart it. 400 */ 401static int via_hook_segment(drm_via_private_t *dev_priv, 402 uint32_t pause_addr_hi, uint32_t pause_addr_lo, 403 int no_pci_fire) 404{ 405 int paused, count; 406 volatile uint32_t *paused_at = dev_priv->last_pause_ptr; 407 uint32_t reader, ptr; 408 uint32_t diff; 409 410 paused = 0; 411 via_flush_write_combine(); 412 (void) *(volatile uint32_t *)(via_get_dma(dev_priv) - 1); 413 414 *paused_at = pause_addr_lo; 415 via_flush_write_combine(); 416 (void) *paused_at; 417 418 reader = *(dev_priv->hw_addr_ptr); 419 ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + 420 dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; 421 422 dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; 423 424 /* 425 * If there is a possibility that the command reader will 426 * miss the new pause address and pause on the old one, 427 * In that case we need to program the new start address 428 * using PCI. 429 */ 430 431 diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; 432 count = 10000000; 433 while (diff == 0 && count--) { 434 paused = (VIA_READ(0x41c) & 0x80000000); 435 if (paused) 436 break; 437 reader = *(dev_priv->hw_addr_ptr); 438 diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; 439 } 440 441 paused = VIA_READ(0x41c) & 0x80000000; 442 443 if (paused && !no_pci_fire) { 444 reader = *(dev_priv->hw_addr_ptr); 445 diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; 446 diff &= (dev_priv->dma_high - 1); 447 if (diff != 0 && diff < (dev_priv->dma_high >> 1)) { 448 DRM_ERROR("Paused at incorrect address. " 449 "0x%08x, 0x%08x 0x%08x\n", 450 ptr, reader, dev_priv->dma_diff); 451 } else if (diff == 0) { 452 /* 453 * There is a concern that these writes may stall the PCI bus 454 * if the GPU is not idle. However, idling the GPU first 455 * doesn't make a difference. 456 */ 457 458 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); 459 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); 460 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); 461 VIA_READ(VIA_REG_TRANSPACE); 462 } 463 } 464 return paused; 465} 466 467static int via_wait_idle(drm_via_private_t *dev_priv) 468{ 469 int count = 10000000; 470 471 while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count) 472 ; 473 474 while (count && (VIA_READ(VIA_REG_STATUS) & 475 (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | 476 VIA_3D_ENG_BUSY))) 477 --count; 478 return count; 479} 480 481static uint32_t *via_align_cmd(drm_via_private_t *dev_priv, uint32_t cmd_type, 482 uint32_t addr, uint32_t *cmd_addr_hi, 483 uint32_t *cmd_addr_lo, int skip_wait) 484{ 485 uint32_t agp_base; 486 uint32_t cmd_addr, addr_lo, addr_hi; 487 uint32_t *vb; 488 uint32_t qw_pad_count; 489 490 if (!skip_wait) 491 via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE); 492 493 vb = via_get_dma(dev_priv); 494 VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) | 495 (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16); 496 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 497 qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) - 498 ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3); 499 500 cmd_addr = (addr) ? addr : 501 agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3); 502 addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) | 503 (cmd_addr & HC_HAGPBpL_MASK)); 504 addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24)); 505 506 vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1); 507 VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo); 508 return vb; 509} 510 511static void via_cmdbuf_start(drm_via_private_t *dev_priv) 512{ 513 uint32_t pause_addr_lo, pause_addr_hi; 514 uint32_t start_addr, start_addr_lo; 515 uint32_t end_addr, end_addr_lo; 516 uint32_t command; 517 uint32_t agp_base; 518 uint32_t ptr; 519 uint32_t reader; 520 int count; 521 522 dev_priv->dma_low = 0; 523 524 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 525 start_addr = agp_base; 526 end_addr = agp_base + dev_priv->dma_high; 527 528 start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF)); 529 end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF)); 530 command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) | 531 ((end_addr & 0xff000000) >> 16)); 532 533 dev_priv->last_pause_ptr = 534 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, 535 &pause_addr_hi, &pause_addr_lo, 1) - 1; 536 537 via_flush_write_combine(); 538 (void) *(volatile uint32_t *)dev_priv->last_pause_ptr; 539 540 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); 541 VIA_WRITE(VIA_REG_TRANSPACE, command); 542 VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo); 543 VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo); 544 545 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); 546 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); 547 DRM_WRITEMEMORYBARRIER(); 548 VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); 549 VIA_READ(VIA_REG_TRANSPACE); 550 551 dev_priv->dma_diff = 0; 552 553 count = 10000000; 554 while (!(VIA_READ(0x41c) & 0x80000000) && count--); 555 556 reader = *(dev_priv->hw_addr_ptr); 557 ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + 558 dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; 559 560 /* 561 * This is the difference between where we tell the 562 * command reader to pause and where it actually pauses. 563 * This differs between hw implementation so we need to 564 * detect it. 565 */ 566 567 dev_priv->dma_diff = ptr - reader; 568} 569 570static void via_pad_cache(drm_via_private_t *dev_priv, int qwords) 571{ 572 uint32_t *vb; 573 574 via_cmdbuf_wait(dev_priv, qwords + 2); 575 vb = via_get_dma(dev_priv); 576 VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16); 577 via_align_buffer(dev_priv, vb, qwords); 578} 579 580static inline void via_dummy_bitblt(drm_via_private_t *dev_priv) 581{ 582 uint32_t *vb = via_get_dma(dev_priv); 583 SetReg2DAGP(0x0C, (0 | (0 << 16))); 584 SetReg2DAGP(0x10, 0 | (0 << 16)); 585 SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000); 586} 587 588static void via_cmdbuf_jump(drm_via_private_t *dev_priv) 589{ 590 uint32_t agp_base; 591 uint32_t pause_addr_lo, pause_addr_hi; 592 uint32_t jump_addr_lo, jump_addr_hi; 593 volatile uint32_t *last_pause_ptr; 594 uint32_t dma_low_save1, dma_low_save2; 595 596 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; 597 via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, 598 &jump_addr_lo, 0); 599 600 dev_priv->dma_wrap = dev_priv->dma_low; 601 602 /* 603 * Wrap command buffer to the beginning. 604 */ 605 606 dev_priv->dma_low = 0; 607 if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) 608 DRM_ERROR("via_cmdbuf_jump failed\n"); 609 610 via_dummy_bitblt(dev_priv); 611 via_dummy_bitblt(dev_priv); 612 613 last_pause_ptr = 614 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 615 &pause_addr_lo, 0) - 1; 616 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 617 &pause_addr_lo, 0); 618 619 *last_pause_ptr = pause_addr_lo; 620 dma_low_save1 = dev_priv->dma_low; 621 622 /* 623 * Now, set a trap that will pause the regulator if it tries to rerun the old 624 * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause 625 * and reissues the jump command over PCI, while the regulator has already taken the jump 626 * and actually paused at the current buffer end). 627 * There appears to be no other way to detect this condition, since the hw_addr_pointer 628 * does not seem to get updated immediately when a jump occurs. 629 */ 630 631 last_pause_ptr = 632 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 633 &pause_addr_lo, 0) - 1; 634 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 635 &pause_addr_lo, 0); 636 *last_pause_ptr = pause_addr_lo; 637 638 dma_low_save2 = dev_priv->dma_low; 639 dev_priv->dma_low = dma_low_save1; 640 via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); 641 dev_priv->dma_low = dma_low_save2; 642 via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); 643} 644 645 646static void via_cmdbuf_rewind(drm_via_private_t *dev_priv) 647{ 648 via_cmdbuf_jump(dev_priv); 649} 650 651static void via_cmdbuf_flush(drm_via_private_t *dev_priv, uint32_t cmd_type) 652{ 653 uint32_t pause_addr_lo, pause_addr_hi; 654 655 via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0); 656 via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); 657} 658 659static void via_cmdbuf_pause(drm_via_private_t *dev_priv) 660{ 661 via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE); 662} 663 664static void via_cmdbuf_reset(drm_via_private_t *dev_priv) 665{ 666 via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP); 667 via_wait_idle(dev_priv); 668} 669 670/* 671 * User interface to the space and lag functions. 672 */ 673 674static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv) 675{ 676 drm_via_cmdbuf_size_t *d_siz = data; 677 int ret = 0; 678 uint32_t tmp_size, count; 679 drm_via_private_t *dev_priv; 680 681 DRM_DEBUG("\n"); 682 LOCK_TEST_WITH_RETURN(dev, file_priv); 683 684 dev_priv = (drm_via_private_t *) dev->dev_private; 685 686 if (dev_priv->ring.virtual_start == NULL) { 687 DRM_ERROR("called without initializing AGP ring buffer.\n"); 688 return -EFAULT; 689 } 690 691 count = 1000000; 692 tmp_size = d_siz->size; 693 switch (d_siz->func) { 694 case VIA_CMDBUF_SPACE: 695 while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size) 696 && --count) { 697 if (!d_siz->wait) 698 break; 699 } 700 if (!count) { 701 DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n"); 702 ret = -EAGAIN; 703 } 704 break; 705 case VIA_CMDBUF_LAG: 706 while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size) 707 && --count) { 708 if (!d_siz->wait) 709 break; 710 } 711 if (!count) { 712 DRM_ERROR("VIA_CMDBUF_LAG timed out.\n"); 713 ret = -EAGAIN; 714 } 715 break; 716 default: 717 ret = -EFAULT; 718 } 719 d_siz->size = tmp_size; 720 721 return ret; 722} 723 724struct drm_ioctl_desc via_ioctls[] = { 725 DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH), 726 DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH), 727 DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER), 728 DRM_IOCTL_DEF_DRV(VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER), 729 DRM_IOCTL_DEF_DRV(VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER), 730 DRM_IOCTL_DEF_DRV(VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH), 731 DRM_IOCTL_DEF_DRV(VIA_DMA_INIT, via_dma_init, DRM_AUTH), 732 DRM_IOCTL_DEF_DRV(VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH), 733 DRM_IOCTL_DEF_DRV(VIA_FLUSH, via_flush_ioctl, DRM_AUTH), 734 DRM_IOCTL_DEF_DRV(VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH), 735 DRM_IOCTL_DEF_DRV(VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH), 736 DRM_IOCTL_DEF_DRV(VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH), 737 DRM_IOCTL_DEF_DRV(VIA_DMA_BLIT, via_dma_blit, DRM_AUTH), 738 DRM_IOCTL_DEF_DRV(VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH) 739}; 740 741int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls); 742