mga_state.c revision 113995
1/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*- 2 * Created: Thu Jan 27 02:53:43 2000 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 * VA LINUX SYSTEMS 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 25 * OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * Authors: 28 * Jeff Hartmann <jhartmann@valinux.com> 29 * Keith Whitwell <keith@tungstengraphics.com> 30 * 31 * Rewritten by: 32 * Gareth Hughes <gareth@valinux.com> 33 * 34 * $FreeBSD: head/sys/dev/drm/mga_state.c 113995 2003-04-25 01:18:47Z anholt $ 35 */ 36 37#include "dev/drm/mga.h" 38#include "dev/drm/drmP.h" 39#include "dev/drm/drm.h" 40#include "dev/drm/mga_drm.h" 41#include "dev/drm/mga_drv.h" 42 43 44/* ================================================================ 45 * DMA hardware state programming functions 46 */ 47 48static void mga_emit_clip_rect( drm_mga_private_t *dev_priv, 49 drm_clip_rect_t *box ) 50{ 51 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 52 drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 53 unsigned int pitch = dev_priv->front_pitch; 54 DMA_LOCALS; 55 56 BEGIN_DMA( 2 ); 57 58 /* Force reset of DWGCTL on G400 (eliminates clip disable bit). 59 */ 60 if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) { 61 DMA_BLOCK( MGA_DWGCTL, ctx->dwgctl, 62 MGA_LEN + MGA_EXEC, 0x80000000, 63 MGA_DWGCTL, ctx->dwgctl, 64 MGA_LEN + MGA_EXEC, 0x80000000 ); 65 } 66 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 67 MGA_CXBNDRY, (box->x2 << 16) | box->x1, 68 MGA_YTOP, box->y1 * pitch, 69 MGA_YBOT, box->y2 * pitch ); 70 71 ADVANCE_DMA(); 72} 73 74static __inline__ void mga_g200_emit_context( drm_mga_private_t *dev_priv ) 75{ 76 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 77 drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 78 DMA_LOCALS; 79 80 BEGIN_DMA( 3 ); 81 82 DMA_BLOCK( MGA_DSTORG, ctx->dstorg, 83 MGA_MACCESS, ctx->maccess, 84 MGA_PLNWT, ctx->plnwt, 85 MGA_DWGCTL, ctx->dwgctl ); 86 87 DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl, 88 MGA_FOGCOL, ctx->fogcolor, 89 MGA_WFLAG, ctx->wflag, 90 MGA_ZORG, dev_priv->depth_offset ); 91 92 DMA_BLOCK( MGA_FCOL, ctx->fcol, 93 MGA_DMAPAD, 0x00000000, 94 MGA_DMAPAD, 0x00000000, 95 MGA_DMAPAD, 0x00000000 ); 96 97 ADVANCE_DMA(); 98} 99 100static __inline__ void mga_g400_emit_context( drm_mga_private_t *dev_priv ) 101{ 102 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 103 drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 104 DMA_LOCALS; 105 106 BEGIN_DMA( 4 ); 107 108 DMA_BLOCK( MGA_DSTORG, ctx->dstorg, 109 MGA_MACCESS, ctx->maccess, 110 MGA_PLNWT, ctx->plnwt, 111 MGA_DWGCTL, ctx->dwgctl ); 112 113 DMA_BLOCK( MGA_ALPHACTRL, ctx->alphactrl, 114 MGA_FOGCOL, ctx->fogcolor, 115 MGA_WFLAG, ctx->wflag, 116 MGA_ZORG, dev_priv->depth_offset ); 117 118 DMA_BLOCK( MGA_WFLAG1, ctx->wflag, 119 MGA_TDUALSTAGE0, ctx->tdualstage0, 120 MGA_TDUALSTAGE1, ctx->tdualstage1, 121 MGA_FCOL, ctx->fcol ); 122 123 DMA_BLOCK( MGA_STENCIL, ctx->stencil, 124 MGA_STENCILCTL, ctx->stencilctl, 125 MGA_DMAPAD, 0x00000000, 126 MGA_DMAPAD, 0x00000000 ); 127 128 ADVANCE_DMA(); 129} 130 131static __inline__ void mga_g200_emit_tex0( drm_mga_private_t *dev_priv ) 132{ 133 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 134 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; 135 DMA_LOCALS; 136 137 BEGIN_DMA( 4 ); 138 139 DMA_BLOCK( MGA_TEXCTL2, tex->texctl2, 140 MGA_TEXCTL, tex->texctl, 141 MGA_TEXFILTER, tex->texfilter, 142 MGA_TEXBORDERCOL, tex->texbordercol ); 143 144 DMA_BLOCK( MGA_TEXORG, tex->texorg, 145 MGA_TEXORG1, tex->texorg1, 146 MGA_TEXORG2, tex->texorg2, 147 MGA_TEXORG3, tex->texorg3 ); 148 149 DMA_BLOCK( MGA_TEXORG4, tex->texorg4, 150 MGA_TEXWIDTH, tex->texwidth, 151 MGA_TEXHEIGHT, tex->texheight, 152 MGA_WR24, tex->texwidth ); 153 154 DMA_BLOCK( MGA_WR34, tex->texheight, 155 MGA_TEXTRANS, 0x0000ffff, 156 MGA_TEXTRANSHIGH, 0x0000ffff, 157 MGA_DMAPAD, 0x00000000 ); 158 159 ADVANCE_DMA(); 160} 161 162static __inline__ void mga_g400_emit_tex0( drm_mga_private_t *dev_priv ) 163{ 164 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 165 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; 166 DMA_LOCALS; 167 168/* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */ 169/* tex->texctl, tex->texctl2); */ 170 171 BEGIN_DMA( 6 ); 172 173 DMA_BLOCK( MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC, 174 MGA_TEXCTL, tex->texctl, 175 MGA_TEXFILTER, tex->texfilter, 176 MGA_TEXBORDERCOL, tex->texbordercol ); 177 178 DMA_BLOCK( MGA_TEXORG, tex->texorg, 179 MGA_TEXORG1, tex->texorg1, 180 MGA_TEXORG2, tex->texorg2, 181 MGA_TEXORG3, tex->texorg3 ); 182 183 DMA_BLOCK( MGA_TEXORG4, tex->texorg4, 184 MGA_TEXWIDTH, tex->texwidth, 185 MGA_TEXHEIGHT, tex->texheight, 186 MGA_WR49, 0x00000000 ); 187 188 DMA_BLOCK( MGA_WR57, 0x00000000, 189 MGA_WR53, 0x00000000, 190 MGA_WR61, 0x00000000, 191 MGA_WR52, MGA_G400_WR_MAGIC ); 192 193 DMA_BLOCK( MGA_WR60, MGA_G400_WR_MAGIC, 194 MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC, 195 MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC, 196 MGA_DMAPAD, 0x00000000 ); 197 198 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 199 MGA_DMAPAD, 0x00000000, 200 MGA_TEXTRANS, 0x0000ffff, 201 MGA_TEXTRANSHIGH, 0x0000ffff ); 202 203 ADVANCE_DMA(); 204} 205 206static __inline__ void mga_g400_emit_tex1( drm_mga_private_t *dev_priv ) 207{ 208 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 209 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1]; 210 DMA_LOCALS; 211 212/* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */ 213/* tex->texctl, tex->texctl2); */ 214 215 BEGIN_DMA( 5 ); 216 217 DMA_BLOCK( MGA_TEXCTL2, (tex->texctl2 | 218 MGA_MAP1_ENABLE | 219 MGA_G400_TC2_MAGIC), 220 MGA_TEXCTL, tex->texctl, 221 MGA_TEXFILTER, tex->texfilter, 222 MGA_TEXBORDERCOL, tex->texbordercol ); 223 224 DMA_BLOCK( MGA_TEXORG, tex->texorg, 225 MGA_TEXORG1, tex->texorg1, 226 MGA_TEXORG2, tex->texorg2, 227 MGA_TEXORG3, tex->texorg3 ); 228 229 DMA_BLOCK( MGA_TEXORG4, tex->texorg4, 230 MGA_TEXWIDTH, tex->texwidth, 231 MGA_TEXHEIGHT, tex->texheight, 232 MGA_WR49, 0x00000000 ); 233 234 DMA_BLOCK( MGA_WR57, 0x00000000, 235 MGA_WR53, 0x00000000, 236 MGA_WR61, 0x00000000, 237 MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC ); 238 239 DMA_BLOCK( MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC, 240 MGA_TEXTRANS, 0x0000ffff, 241 MGA_TEXTRANSHIGH, 0x0000ffff, 242 MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC ); 243 244 ADVANCE_DMA(); 245} 246 247static __inline__ void mga_g200_emit_pipe( drm_mga_private_t *dev_priv ) 248{ 249 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 250 unsigned int pipe = sarea_priv->warp_pipe; 251 DMA_LOCALS; 252 253 BEGIN_DMA( 3 ); 254 255 DMA_BLOCK( MGA_WIADDR, MGA_WMODE_SUSPEND, 256 MGA_WVRTXSZ, 0x00000007, 257 MGA_WFLAG, 0x00000000, 258 MGA_WR24, 0x00000000 ); 259 260 DMA_BLOCK( MGA_WR25, 0x00000100, 261 MGA_WR34, 0x00000000, 262 MGA_WR42, 0x0000ffff, 263 MGA_WR60, 0x0000ffff ); 264 265 /* Padding required to to hardware bug. 266 */ 267 DMA_BLOCK( MGA_DMAPAD, 0xffffffff, 268 MGA_DMAPAD, 0xffffffff, 269 MGA_DMAPAD, 0xffffffff, 270 MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | 271 MGA_WMODE_START | 272 MGA_WAGP_ENABLE) ); 273 274 ADVANCE_DMA(); 275} 276 277static __inline__ void mga_g400_emit_pipe( drm_mga_private_t *dev_priv ) 278{ 279 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 280 unsigned int pipe = sarea_priv->warp_pipe; 281 DMA_LOCALS; 282 283/* printk("mga_g400_emit_pipe %x\n", pipe); */ 284 285 BEGIN_DMA( 10 ); 286 287 DMA_BLOCK( MGA_WIADDR2, MGA_WMODE_SUSPEND, 288 MGA_DMAPAD, 0x00000000, 289 MGA_DMAPAD, 0x00000000, 290 MGA_DMAPAD, 0x00000000 ); 291 292 if ( pipe & MGA_T2 ) { 293 DMA_BLOCK( MGA_WVRTXSZ, 0x00001e09, 294 MGA_DMAPAD, 0x00000000, 295 MGA_DMAPAD, 0x00000000, 296 MGA_DMAPAD, 0x00000000 ); 297 298 DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000, 299 MGA_WACCEPTSEQ, 0x00000000, 300 MGA_WACCEPTSEQ, 0x00000000, 301 MGA_WACCEPTSEQ, 0x1e000000 ); 302 } else { 303 if ( dev_priv->warp_pipe & MGA_T2 ) { 304 /* Flush the WARP pipe */ 305 DMA_BLOCK( MGA_YDST, 0x00000000, 306 MGA_FXLEFT, 0x00000000, 307 MGA_FXRIGHT, 0x00000001, 308 MGA_DWGCTL, MGA_DWGCTL_FLUSH ); 309 310 DMA_BLOCK( MGA_LEN + MGA_EXEC, 0x00000001, 311 MGA_DWGSYNC, 0x00007000, 312 MGA_TEXCTL2, MGA_G400_TC2_MAGIC, 313 MGA_LEN + MGA_EXEC, 0x00000000 ); 314 315 DMA_BLOCK( MGA_TEXCTL2, (MGA_DUALTEX | 316 MGA_G400_TC2_MAGIC), 317 MGA_LEN + MGA_EXEC, 0x00000000, 318 MGA_TEXCTL2, MGA_G400_TC2_MAGIC, 319 MGA_DMAPAD, 0x00000000 ); 320 } 321 322 DMA_BLOCK( MGA_WVRTXSZ, 0x00001807, 323 MGA_DMAPAD, 0x00000000, 324 MGA_DMAPAD, 0x00000000, 325 MGA_DMAPAD, 0x00000000 ); 326 327 DMA_BLOCK( MGA_WACCEPTSEQ, 0x00000000, 328 MGA_WACCEPTSEQ, 0x00000000, 329 MGA_WACCEPTSEQ, 0x00000000, 330 MGA_WACCEPTSEQ, 0x18000000 ); 331 } 332 333 DMA_BLOCK( MGA_WFLAG, 0x00000000, 334 MGA_WFLAG1, 0x00000000, 335 MGA_WR56, MGA_G400_WR56_MAGIC, 336 MGA_DMAPAD, 0x00000000 ); 337 338 DMA_BLOCK( MGA_WR49, 0x00000000, /* tex0 */ 339 MGA_WR57, 0x00000000, /* tex0 */ 340 MGA_WR53, 0x00000000, /* tex1 */ 341 MGA_WR61, 0x00000000 ); /* tex1 */ 342 343 DMA_BLOCK( MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */ 344 MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */ 345 MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */ 346 MGA_WR60, MGA_G400_WR_MAGIC ); /* tex1 height */ 347 348 /* Padding required to to hardware bug */ 349 DMA_BLOCK( MGA_DMAPAD, 0xffffffff, 350 MGA_DMAPAD, 0xffffffff, 351 MGA_DMAPAD, 0xffffffff, 352 MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | 353 MGA_WMODE_START | 354 MGA_WAGP_ENABLE) ); 355 356 ADVANCE_DMA(); 357} 358 359static void mga_g200_emit_state( drm_mga_private_t *dev_priv ) 360{ 361 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 362 unsigned int dirty = sarea_priv->dirty; 363 364 if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) { 365 mga_g200_emit_pipe( dev_priv ); 366 dev_priv->warp_pipe = sarea_priv->warp_pipe; 367 } 368 369 if ( dirty & MGA_UPLOAD_CONTEXT ) { 370 mga_g200_emit_context( dev_priv ); 371 sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; 372 } 373 374 if ( dirty & MGA_UPLOAD_TEX0 ) { 375 mga_g200_emit_tex0( dev_priv ); 376 sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; 377 } 378} 379 380static void mga_g400_emit_state( drm_mga_private_t *dev_priv ) 381{ 382 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 383 unsigned int dirty = sarea_priv->dirty; 384 int multitex = sarea_priv->warp_pipe & MGA_T2; 385 386 if ( sarea_priv->warp_pipe != dev_priv->warp_pipe ) { 387 mga_g400_emit_pipe( dev_priv ); 388 dev_priv->warp_pipe = sarea_priv->warp_pipe; 389 } 390 391 if ( dirty & MGA_UPLOAD_CONTEXT ) { 392 mga_g400_emit_context( dev_priv ); 393 sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; 394 } 395 396 if ( dirty & MGA_UPLOAD_TEX0 ) { 397 mga_g400_emit_tex0( dev_priv ); 398 sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; 399 } 400 401 if ( (dirty & MGA_UPLOAD_TEX1) && multitex ) { 402 mga_g400_emit_tex1( dev_priv ); 403 sarea_priv->dirty &= ~MGA_UPLOAD_TEX1; 404 } 405} 406 407 408/* ================================================================ 409 * SAREA state verification 410 */ 411 412/* Disallow all write destinations except the front and backbuffer. 413 */ 414static int mga_verify_context( drm_mga_private_t *dev_priv ) 415{ 416 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 417 drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 418 419 if ( ctx->dstorg != dev_priv->front_offset && 420 ctx->dstorg != dev_priv->back_offset ) { 421 DRM_ERROR( "*** bad DSTORG: %x (front %x, back %x)\n\n", 422 ctx->dstorg, dev_priv->front_offset, 423 dev_priv->back_offset ); 424 ctx->dstorg = 0; 425 return DRM_ERR(EINVAL); 426 } 427 428 return 0; 429} 430 431/* Disallow texture reads from PCI space. 432 */ 433static int mga_verify_tex( drm_mga_private_t *dev_priv, int unit ) 434{ 435 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 436 drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit]; 437 unsigned int org; 438 439 org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK); 440 441 if ( org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI) ) { 442 DRM_ERROR( "*** bad TEXORG: 0x%x, unit %d\n", 443 tex->texorg, unit ); 444 tex->texorg = 0; 445 return DRM_ERR(EINVAL); 446 } 447 448 return 0; 449} 450 451static int mga_verify_state( drm_mga_private_t *dev_priv ) 452{ 453 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 454 unsigned int dirty = sarea_priv->dirty; 455 int ret = 0; 456 457 if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS ) 458 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; 459 460 if ( dirty & MGA_UPLOAD_CONTEXT ) 461 ret |= mga_verify_context( dev_priv ); 462 463 if ( dirty & MGA_UPLOAD_TEX0 ) 464 ret |= mga_verify_tex( dev_priv, 0 ); 465 466 if ( dev_priv->chipset == MGA_CARD_TYPE_G400 ) { 467 if ( dirty & MGA_UPLOAD_TEX1 ) 468 ret |= mga_verify_tex( dev_priv, 1 ); 469 470 if ( dirty & MGA_UPLOAD_PIPE ) 471 ret |= ( sarea_priv->warp_pipe > MGA_MAX_G400_PIPES ); 472 } else { 473 if ( dirty & MGA_UPLOAD_PIPE ) 474 ret |= ( sarea_priv->warp_pipe > MGA_MAX_G200_PIPES ); 475 } 476 477 return ( ret == 0 ); 478} 479 480static int mga_verify_iload( drm_mga_private_t *dev_priv, 481 unsigned int dstorg, unsigned int length ) 482{ 483 if ( dstorg < dev_priv->texture_offset || 484 dstorg + length > (dev_priv->texture_offset + 485 dev_priv->texture_size) ) { 486 DRM_ERROR( "*** bad iload DSTORG: 0x%x\n", dstorg ); 487 return DRM_ERR(EINVAL); 488 } 489 490 if ( length & MGA_ILOAD_MASK ) { 491 DRM_ERROR( "*** bad iload length: 0x%x\n", 492 length & MGA_ILOAD_MASK ); 493 return DRM_ERR(EINVAL); 494 } 495 496 return 0; 497} 498 499static int mga_verify_blit( drm_mga_private_t *dev_priv, 500 unsigned int srcorg, unsigned int dstorg ) 501{ 502 if ( (srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) || 503 (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ) { 504 DRM_ERROR( "*** bad blit: src=0x%x dst=0x%x\n", 505 srcorg, dstorg ); 506 return DRM_ERR(EINVAL); 507 } 508 return 0; 509} 510 511 512/* ================================================================ 513 * 514 */ 515 516static void mga_dma_dispatch_clear( drm_device_t *dev, 517 drm_mga_clear_t *clear ) 518{ 519 drm_mga_private_t *dev_priv = dev->dev_private; 520 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 521 drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 522 drm_clip_rect_t *pbox = sarea_priv->boxes; 523 int nbox = sarea_priv->nbox; 524 int i; 525 DMA_LOCALS; 526 DRM_DEBUG( "\n" ); 527 528 BEGIN_DMA( 1 ); 529 530 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 531 MGA_DMAPAD, 0x00000000, 532 MGA_DWGSYNC, 0x00007100, 533 MGA_DWGSYNC, 0x00007000 ); 534 535 ADVANCE_DMA(); 536 537 for ( i = 0 ; i < nbox ; i++ ) { 538 drm_clip_rect_t *box = &pbox[i]; 539 u32 height = box->y2 - box->y1; 540 541 DRM_DEBUG( " from=%d,%d to=%d,%d\n", 542 box->x1, box->y1, box->x2, box->y2 ); 543 544 if ( clear->flags & MGA_FRONT ) { 545 BEGIN_DMA( 2 ); 546 547 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 548 MGA_PLNWT, clear->color_mask, 549 MGA_YDSTLEN, (box->y1 << 16) | height, 550 MGA_FXBNDRY, (box->x2 << 16) | box->x1 ); 551 552 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 553 MGA_FCOL, clear->clear_color, 554 MGA_DSTORG, dev_priv->front_offset, 555 MGA_DWGCTL + MGA_EXEC, 556 dev_priv->clear_cmd ); 557 558 ADVANCE_DMA(); 559 } 560 561 562 if ( clear->flags & MGA_BACK ) { 563 BEGIN_DMA( 2 ); 564 565 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 566 MGA_PLNWT, clear->color_mask, 567 MGA_YDSTLEN, (box->y1 << 16) | height, 568 MGA_FXBNDRY, (box->x2 << 16) | box->x1 ); 569 570 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 571 MGA_FCOL, clear->clear_color, 572 MGA_DSTORG, dev_priv->back_offset, 573 MGA_DWGCTL + MGA_EXEC, 574 dev_priv->clear_cmd ); 575 576 ADVANCE_DMA(); 577 } 578 579 if ( clear->flags & MGA_DEPTH ) { 580 BEGIN_DMA( 2 ); 581 582 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 583 MGA_PLNWT, clear->depth_mask, 584 MGA_YDSTLEN, (box->y1 << 16) | height, 585 MGA_FXBNDRY, (box->x2 << 16) | box->x1 ); 586 587 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 588 MGA_FCOL, clear->clear_depth, 589 MGA_DSTORG, dev_priv->depth_offset, 590 MGA_DWGCTL + MGA_EXEC, 591 dev_priv->clear_cmd ); 592 593 ADVANCE_DMA(); 594 } 595 596 } 597 598 BEGIN_DMA( 1 ); 599 600 /* Force reset of DWGCTL */ 601 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 602 MGA_DMAPAD, 0x00000000, 603 MGA_PLNWT, ctx->plnwt, 604 MGA_DWGCTL, ctx->dwgctl ); 605 606 ADVANCE_DMA(); 607 608 FLUSH_DMA(); 609} 610 611static void mga_dma_dispatch_swap( drm_device_t *dev ) 612{ 613 drm_mga_private_t *dev_priv = dev->dev_private; 614 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 615 drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 616 drm_clip_rect_t *pbox = sarea_priv->boxes; 617 int nbox = sarea_priv->nbox; 618 int i; 619 DMA_LOCALS; 620 DRM_DEBUG( "\n" ); 621 622 sarea_priv->last_frame.head = dev_priv->prim.tail; 623 sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; 624 625 BEGIN_DMA( 4 + nbox ); 626 627 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 628 MGA_DMAPAD, 0x00000000, 629 MGA_DWGSYNC, 0x00007100, 630 MGA_DWGSYNC, 0x00007000 ); 631 632 DMA_BLOCK( MGA_DSTORG, dev_priv->front_offset, 633 MGA_MACCESS, dev_priv->maccess, 634 MGA_SRCORG, dev_priv->back_offset, 635 MGA_AR5, dev_priv->front_pitch ); 636 637 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 638 MGA_DMAPAD, 0x00000000, 639 MGA_PLNWT, 0xffffffff, 640 MGA_DWGCTL, MGA_DWGCTL_COPY ); 641 642 for ( i = 0 ; i < nbox ; i++ ) { 643 drm_clip_rect_t *box = &pbox[i]; 644 u32 height = box->y2 - box->y1; 645 u32 start = box->y1 * dev_priv->front_pitch; 646 647 DRM_DEBUG( " from=%d,%d to=%d,%d\n", 648 box->x1, box->y1, box->x2, box->y2 ); 649 650 DMA_BLOCK( MGA_AR0, start + box->x2 - 1, 651 MGA_AR3, start + box->x1, 652 MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1, 653 MGA_YDSTLEN + MGA_EXEC, 654 (box->y1 << 16) | height ); 655 } 656 657 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 658 MGA_PLNWT, ctx->plnwt, 659 MGA_SRCORG, dev_priv->front_offset, 660 MGA_DWGCTL, ctx->dwgctl ); 661 662 ADVANCE_DMA(); 663 664 FLUSH_DMA(); 665 666 DRM_DEBUG( "%s... done.\n", __FUNCTION__ ); 667} 668 669static void mga_dma_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf ) 670{ 671 drm_mga_private_t *dev_priv = dev->dev_private; 672 drm_mga_buf_priv_t *buf_priv = buf->dev_private; 673 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 674 u32 address = (u32) buf->bus_address; 675 u32 length = (u32) buf->used; 676 int i = 0; 677 DMA_LOCALS; 678 DRM_DEBUG( "vertex: buf=%d used=%d\n", buf->idx, buf->used ); 679 680 if ( buf->used ) { 681 buf_priv->dispatched = 1; 682 683 MGA_EMIT_STATE( dev_priv, sarea_priv->dirty ); 684 685 do { 686 if ( i < sarea_priv->nbox ) { 687 mga_emit_clip_rect( dev_priv, 688 &sarea_priv->boxes[i] ); 689 } 690 691 BEGIN_DMA( 1 ); 692 693 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 694 MGA_DMAPAD, 0x00000000, 695 MGA_SECADDRESS, (address | 696 MGA_DMA_VERTEX), 697 MGA_SECEND, ((address + length) | 698 MGA_PAGPXFER) ); 699 700 ADVANCE_DMA(); 701 } while ( ++i < sarea_priv->nbox ); 702 } 703 704 if ( buf_priv->discard ) { 705 AGE_BUFFER( buf_priv ); 706 buf->pending = 0; 707 buf->used = 0; 708 buf_priv->dispatched = 0; 709 710 mga_freelist_put( dev, buf ); 711 } 712 713 FLUSH_DMA(); 714} 715 716static void mga_dma_dispatch_indices( drm_device_t *dev, drm_buf_t *buf, 717 unsigned int start, unsigned int end ) 718{ 719 drm_mga_private_t *dev_priv = dev->dev_private; 720 drm_mga_buf_priv_t *buf_priv = buf->dev_private; 721 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 722 u32 address = (u32) buf->bus_address; 723 int i = 0; 724 DMA_LOCALS; 725 DRM_DEBUG( "indices: buf=%d start=%d end=%d\n", buf->idx, start, end ); 726 727 if ( start != end ) { 728 buf_priv->dispatched = 1; 729 730 MGA_EMIT_STATE( dev_priv, sarea_priv->dirty ); 731 732 do { 733 if ( i < sarea_priv->nbox ) { 734 mga_emit_clip_rect( dev_priv, 735 &sarea_priv->boxes[i] ); 736 } 737 738 BEGIN_DMA( 1 ); 739 740 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 741 MGA_DMAPAD, 0x00000000, 742 MGA_SETUPADDRESS, address + start, 743 MGA_SETUPEND, ((address + end) | 744 MGA_PAGPXFER) ); 745 746 ADVANCE_DMA(); 747 } while ( ++i < sarea_priv->nbox ); 748 } 749 750 if ( buf_priv->discard ) { 751 AGE_BUFFER( buf_priv ); 752 buf->pending = 0; 753 buf->used = 0; 754 buf_priv->dispatched = 0; 755 756 mga_freelist_put( dev, buf ); 757 } 758 759 FLUSH_DMA(); 760} 761 762/* This copies a 64 byte aligned agp region to the frambuffer with a 763 * standard blit, the ioctl needs to do checking. 764 */ 765static void mga_dma_dispatch_iload( drm_device_t *dev, drm_buf_t *buf, 766 unsigned int dstorg, unsigned int length ) 767{ 768 drm_mga_private_t *dev_priv = dev->dev_private; 769 drm_mga_buf_priv_t *buf_priv = buf->dev_private; 770 drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; 771 u32 srcorg = buf->bus_address | MGA_SRCACC_AGP | MGA_SRCMAP_SYSMEM; 772 u32 y2; 773 DMA_LOCALS; 774 DRM_DEBUG( "buf=%d used=%d\n", buf->idx, buf->used ); 775 776 y2 = length / 64; 777 778 BEGIN_DMA( 5 ); 779 780 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 781 MGA_DMAPAD, 0x00000000, 782 MGA_DWGSYNC, 0x00007100, 783 MGA_DWGSYNC, 0x00007000 ); 784 785 DMA_BLOCK( MGA_DSTORG, dstorg, 786 MGA_MACCESS, 0x00000000, 787 MGA_SRCORG, srcorg, 788 MGA_AR5, 64 ); 789 790 DMA_BLOCK( MGA_PITCH, 64, 791 MGA_PLNWT, 0xffffffff, 792 MGA_DMAPAD, 0x00000000, 793 MGA_DWGCTL, MGA_DWGCTL_COPY ); 794 795 DMA_BLOCK( MGA_AR0, 63, 796 MGA_AR3, 0, 797 MGA_FXBNDRY, (63 << 16) | 0, 798 MGA_YDSTLEN + MGA_EXEC, y2 ); 799 800 DMA_BLOCK( MGA_PLNWT, ctx->plnwt, 801 MGA_SRCORG, dev_priv->front_offset, 802 MGA_PITCH, dev_priv->front_pitch, 803 MGA_DWGSYNC, 0x00007000 ); 804 805 ADVANCE_DMA(); 806 807 AGE_BUFFER( buf_priv ); 808 809 buf->pending = 0; 810 buf->used = 0; 811 buf_priv->dispatched = 0; 812 813 mga_freelist_put( dev, buf ); 814 815 FLUSH_DMA(); 816} 817 818static void mga_dma_dispatch_blit( drm_device_t *dev, 819 drm_mga_blit_t *blit ) 820{ 821 drm_mga_private_t *dev_priv = dev->dev_private; 822 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 823 drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 824 drm_clip_rect_t *pbox = sarea_priv->boxes; 825 int nbox = sarea_priv->nbox; 826 u32 scandir = 0, i; 827 DMA_LOCALS; 828 DRM_DEBUG( "\n" ); 829 830 BEGIN_DMA( 4 + nbox ); 831 832 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 833 MGA_DMAPAD, 0x00000000, 834 MGA_DWGSYNC, 0x00007100, 835 MGA_DWGSYNC, 0x00007000 ); 836 837 DMA_BLOCK( MGA_DWGCTL, MGA_DWGCTL_COPY, 838 MGA_PLNWT, blit->planemask, 839 MGA_SRCORG, blit->srcorg, 840 MGA_DSTORG, blit->dstorg ); 841 842 DMA_BLOCK( MGA_SGN, scandir, 843 MGA_MACCESS, dev_priv->maccess, 844 MGA_AR5, blit->ydir * blit->src_pitch, 845 MGA_PITCH, blit->dst_pitch ); 846 847 for ( i = 0 ; i < nbox ; i++ ) { 848 int srcx = pbox[i].x1 + blit->delta_sx; 849 int srcy = pbox[i].y1 + blit->delta_sy; 850 int dstx = pbox[i].x1 + blit->delta_dx; 851 int dsty = pbox[i].y1 + blit->delta_dy; 852 int h = pbox[i].y2 - pbox[i].y1; 853 int w = pbox[i].x2 - pbox[i].x1 - 1; 854 int start; 855 856 if ( blit->ydir == -1 ) { 857 srcy = blit->height - srcy - 1; 858 } 859 860 start = srcy * blit->src_pitch + srcx; 861 862 DMA_BLOCK( MGA_AR0, start + w, 863 MGA_AR3, start, 864 MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff), 865 MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h ); 866 } 867 868 /* Do something to flush AGP? 869 */ 870 871 /* Force reset of DWGCTL */ 872 DMA_BLOCK( MGA_DMAPAD, 0x00000000, 873 MGA_PLNWT, ctx->plnwt, 874 MGA_PITCH, dev_priv->front_pitch, 875 MGA_DWGCTL, ctx->dwgctl ); 876 877 ADVANCE_DMA(); 878} 879 880 881/* ================================================================ 882 * 883 */ 884 885int mga_dma_clear( DRM_IOCTL_ARGS ) 886{ 887 DRM_DEVICE; 888 drm_mga_private_t *dev_priv = dev->dev_private; 889 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 890 drm_mga_clear_t clear; 891 892 LOCK_TEST_WITH_RETURN( dev, filp ); 893 894 DRM_COPY_FROM_USER_IOCTL( clear, (drm_mga_clear_t *)data, sizeof(clear) ); 895 896 if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS ) 897 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; 898 899 WRAP_TEST_WITH_RETURN( dev_priv ); 900 901 mga_dma_dispatch_clear( dev, &clear ); 902 903 /* Make sure we restore the 3D state next time. 904 */ 905 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; 906 907 return 0; 908} 909 910int mga_dma_swap( DRM_IOCTL_ARGS ) 911{ 912 DRM_DEVICE; 913 drm_mga_private_t *dev_priv = dev->dev_private; 914 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 915 916 LOCK_TEST_WITH_RETURN( dev, filp ); 917 918 if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS ) 919 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; 920 921 WRAP_TEST_WITH_RETURN( dev_priv ); 922 923 mga_dma_dispatch_swap( dev ); 924 925 /* Make sure we restore the 3D state next time. 926 */ 927 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; 928 929 return 0; 930} 931 932int mga_dma_vertex( DRM_IOCTL_ARGS ) 933{ 934 DRM_DEVICE; 935 drm_mga_private_t *dev_priv = dev->dev_private; 936 drm_device_dma_t *dma = dev->dma; 937 drm_buf_t *buf; 938 drm_mga_buf_priv_t *buf_priv; 939 drm_mga_vertex_t vertex; 940 941 LOCK_TEST_WITH_RETURN( dev, filp ); 942 943 DRM_COPY_FROM_USER_IOCTL( vertex, 944 (drm_mga_vertex_t *)data, 945 sizeof(vertex) ); 946 947 if(vertex.idx < 0 || vertex.idx > dma->buf_count) return DRM_ERR(EINVAL); 948 buf = dma->buflist[vertex.idx]; 949 buf_priv = buf->dev_private; 950 951 buf->used = vertex.used; 952 buf_priv->discard = vertex.discard; 953 954 if ( !mga_verify_state( dev_priv ) ) { 955 if ( vertex.discard ) { 956 if ( buf_priv->dispatched == 1 ) 957 AGE_BUFFER( buf_priv ); 958 buf_priv->dispatched = 0; 959 mga_freelist_put( dev, buf ); 960 } 961 return DRM_ERR(EINVAL); 962 } 963 964 WRAP_TEST_WITH_RETURN( dev_priv ); 965 966 mga_dma_dispatch_vertex( dev, buf ); 967 968 return 0; 969} 970 971int mga_dma_indices( DRM_IOCTL_ARGS ) 972{ 973 DRM_DEVICE; 974 drm_mga_private_t *dev_priv = dev->dev_private; 975 drm_device_dma_t *dma = dev->dma; 976 drm_buf_t *buf; 977 drm_mga_buf_priv_t *buf_priv; 978 drm_mga_indices_t indices; 979 980 LOCK_TEST_WITH_RETURN( dev, filp ); 981 982 DRM_COPY_FROM_USER_IOCTL( indices, 983 (drm_mga_indices_t *)data, 984 sizeof(indices) ); 985 986 if(indices.idx < 0 || indices.idx > dma->buf_count) return DRM_ERR(EINVAL); 987 988 buf = dma->buflist[indices.idx]; 989 buf_priv = buf->dev_private; 990 991 buf_priv->discard = indices.discard; 992 993 if ( !mga_verify_state( dev_priv ) ) { 994 if ( indices.discard ) { 995 if ( buf_priv->dispatched == 1 ) 996 AGE_BUFFER( buf_priv ); 997 buf_priv->dispatched = 0; 998 mga_freelist_put( dev, buf ); 999 } 1000 return DRM_ERR(EINVAL); 1001 } 1002 1003 WRAP_TEST_WITH_RETURN( dev_priv ); 1004 1005 mga_dma_dispatch_indices( dev, buf, indices.start, indices.end ); 1006 1007 return 0; 1008} 1009 1010int mga_dma_iload( DRM_IOCTL_ARGS ) 1011{ 1012 DRM_DEVICE; 1013 drm_device_dma_t *dma = dev->dma; 1014 drm_mga_private_t *dev_priv = dev->dev_private; 1015 drm_buf_t *buf; 1016 drm_mga_buf_priv_t *buf_priv; 1017 drm_mga_iload_t iload; 1018 DRM_DEBUG( "\n" ); 1019 1020 LOCK_TEST_WITH_RETURN( dev, filp ); 1021 1022 DRM_COPY_FROM_USER_IOCTL( iload, (drm_mga_iload_t *)data, sizeof(iload) ); 1023 1024#if 0 1025 if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { 1026 if ( MGA_DMA_DEBUG ) 1027 DRM_INFO( "%s: -EBUSY\n", __FUNCTION__ ); 1028 return DRM_ERR(EBUSY); 1029 } 1030#endif 1031 if(iload.idx < 0 || iload.idx > dma->buf_count) return DRM_ERR(EINVAL); 1032 1033 buf = dma->buflist[iload.idx]; 1034 buf_priv = buf->dev_private; 1035 1036 if ( mga_verify_iload( dev_priv, iload.dstorg, iload.length ) ) { 1037 mga_freelist_put( dev, buf ); 1038 return DRM_ERR(EINVAL); 1039 } 1040 1041 WRAP_TEST_WITH_RETURN( dev_priv ); 1042 1043 mga_dma_dispatch_iload( dev, buf, iload.dstorg, iload.length ); 1044 1045 /* Make sure we restore the 3D state next time. 1046 */ 1047 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; 1048 1049 return 0; 1050} 1051 1052int mga_dma_blit( DRM_IOCTL_ARGS ) 1053{ 1054 DRM_DEVICE; 1055 drm_mga_private_t *dev_priv = dev->dev_private; 1056 drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 1057 drm_mga_blit_t blit; 1058 DRM_DEBUG( "\n" ); 1059 1060 LOCK_TEST_WITH_RETURN( dev, filp ); 1061 1062 DRM_COPY_FROM_USER_IOCTL( blit, (drm_mga_blit_t *)data, sizeof(blit) ); 1063 1064 if ( sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS ) 1065 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; 1066 1067 if ( mga_verify_blit( dev_priv, blit.srcorg, blit.dstorg ) ) 1068 return DRM_ERR(EINVAL); 1069 1070 WRAP_TEST_WITH_RETURN( dev_priv ); 1071 1072 mga_dma_dispatch_blit( dev, &blit ); 1073 1074 /* Make sure we restore the 3D state next time. 1075 */ 1076 dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; 1077 1078 return 0; 1079} 1080 1081int mga_getparam( DRM_IOCTL_ARGS ) 1082{ 1083 DRM_DEVICE; 1084 drm_mga_private_t *dev_priv = dev->dev_private; 1085 drm_mga_getparam_t param; 1086 int value; 1087 1088 if ( !dev_priv ) { 1089 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); 1090 return DRM_ERR(EINVAL); 1091 } 1092 1093 DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t *)data, 1094 sizeof(param) ); 1095 1096 DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); 1097 1098 switch( param.param ) { 1099 case MGA_PARAM_IRQ_NR: 1100 value = dev->irq; 1101 break; 1102 default: 1103 return DRM_ERR(EINVAL); 1104 } 1105 1106 if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { 1107 DRM_ERROR( "copy_to_user\n" ); 1108 return DRM_ERR(EFAULT); 1109 } 1110 1111 return 0; 1112} 1113