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