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