195584Sanholt/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*- 2152909Sanholt * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com 3152909Sanholt */ 4139749Simp/*- 595584Sanholt * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 695584Sanholt * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 795584Sanholt * All Rights Reserved. 895584Sanholt * 995584Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 1095584Sanholt * copy of this software and associated documentation files (the "Software"), 1195584Sanholt * to deal in the Software without restriction, including without limitation 1295584Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1395584Sanholt * and/or sell copies of the Software, and to permit persons to whom the 1495584Sanholt * Software is furnished to do so, subject to the following conditions: 1595584Sanholt * 1695584Sanholt * The above copyright notice and this permission notice (including the next 1795584Sanholt * paragraph) shall be included in all copies or substantial portions of the 1895584Sanholt * Software. 1995584Sanholt * 2095584Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2195584Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2295584Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2395584Sanholt * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2495584Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2595584Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2695584Sanholt * OTHER DEALINGS IN THE SOFTWARE. 2795584Sanholt * 2895584Sanholt * Authors: 2995584Sanholt * Jeff Hartmann <jhartmann@valinux.com> 30112015Sanholt * Keith Whitwell <keith@tungstengraphics.com> 3195584Sanholt * 3295584Sanholt * Rewritten by: 3395584Sanholt * Gareth Hughes <gareth@valinux.com> 3495584Sanholt */ 3595584Sanholt 36152909Sanholt#include <sys/cdefs.h> 37152909Sanholt__FBSDID("$FreeBSD: stable/11/sys/dev/drm/mga_state.c 330446 2018-03-05 06:59:30Z eadler $"); 38152909Sanholt 3995584Sanholt#include "dev/drm/drmP.h" 40112015Sanholt#include "dev/drm/drm.h" 4195746Sanholt#include "dev/drm/mga_drm.h" 4295584Sanholt#include "dev/drm/mga_drv.h" 4395584Sanholt 4495584Sanholt/* ================================================================ 4595584Sanholt * DMA hardware state programming functions 4695584Sanholt */ 4795584Sanholt 48145132Sanholtstatic void mga_emit_clip_rect(drm_mga_private_t * dev_priv, 49182080Srnoland struct drm_clip_rect * box) 5095584Sanholt{ 5195584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 5295584Sanholt drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 5395584Sanholt unsigned int pitch = dev_priv->front_pitch; 5495584Sanholt DMA_LOCALS; 5595584Sanholt 56145132Sanholt BEGIN_DMA(2); 5795584Sanholt 5895584Sanholt /* Force reset of DWGCTL on G400 (eliminates clip disable bit). 5995584Sanholt */ 60152909Sanholt if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { 61145132Sanholt DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl, 62145132Sanholt MGA_LEN + MGA_EXEC, 0x80000000, 63145132Sanholt MGA_DWGCTL, ctx->dwgctl, 64145132Sanholt MGA_LEN + MGA_EXEC, 0x80000000); 6595584Sanholt } 66145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 67145132Sanholt MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1, 68182080Srnoland MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch); 6995584Sanholt 7095584Sanholt ADVANCE_DMA(); 7195584Sanholt} 7295584Sanholt 73145132Sanholtstatic __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv) 7495584Sanholt{ 7595584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 7695584Sanholt drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 7795584Sanholt DMA_LOCALS; 7895584Sanholt 79145132Sanholt BEGIN_DMA(3); 8095584Sanholt 81145132Sanholt DMA_BLOCK(MGA_DSTORG, ctx->dstorg, 82145132Sanholt MGA_MACCESS, ctx->maccess, 83182080Srnoland MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); 8495584Sanholt 85145132Sanholt DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, 86145132Sanholt MGA_FOGCOL, ctx->fogcolor, 87182080Srnoland MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset); 8895584Sanholt 89145132Sanholt DMA_BLOCK(MGA_FCOL, ctx->fcol, 90145132Sanholt MGA_DMAPAD, 0x00000000, 91182080Srnoland MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); 9295584Sanholt 9395584Sanholt ADVANCE_DMA(); 9495584Sanholt} 9595584Sanholt 96145132Sanholtstatic __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv) 9795584Sanholt{ 9895584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 9995584Sanholt drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 10095584Sanholt DMA_LOCALS; 10195584Sanholt 102145132Sanholt BEGIN_DMA(4); 10395584Sanholt 104145132Sanholt DMA_BLOCK(MGA_DSTORG, ctx->dstorg, 105145132Sanholt MGA_MACCESS, ctx->maccess, 106145132Sanholt MGA_PLNWT, ctx->plnwt, 107145132Sanholt MGA_DWGCTL, ctx->dwgctl); 10895584Sanholt 109145132Sanholt DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, 110145132Sanholt MGA_FOGCOL, ctx->fogcolor, 111145132Sanholt MGA_WFLAG, ctx->wflag, 112145132Sanholt MGA_ZORG, dev_priv->depth_offset); 11395584Sanholt 114145132Sanholt DMA_BLOCK(MGA_WFLAG1, ctx->wflag, 115145132Sanholt MGA_TDUALSTAGE0, ctx->tdualstage0, 116145132Sanholt MGA_TDUALSTAGE1, ctx->tdualstage1, 117145132Sanholt MGA_FCOL, ctx->fcol); 11895584Sanholt 119145132Sanholt DMA_BLOCK(MGA_STENCIL, ctx->stencil, 120145132Sanholt MGA_STENCILCTL, ctx->stencilctl, 121145132Sanholt MGA_DMAPAD, 0x00000000, 122145132Sanholt MGA_DMAPAD, 0x00000000); 12395584Sanholt 12495584Sanholt ADVANCE_DMA(); 12595584Sanholt} 12695584Sanholt 127145132Sanholtstatic __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv) 12895584Sanholt{ 12995584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 13095584Sanholt drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; 13195584Sanholt DMA_LOCALS; 13295584Sanholt 133145132Sanholt BEGIN_DMA(4); 13495584Sanholt 135145132Sanholt DMA_BLOCK(MGA_TEXCTL2, tex->texctl2, 136145132Sanholt MGA_TEXCTL, tex->texctl, 137145132Sanholt MGA_TEXFILTER, tex->texfilter, 138145132Sanholt MGA_TEXBORDERCOL, tex->texbordercol); 13995584Sanholt 140145132Sanholt DMA_BLOCK(MGA_TEXORG, tex->texorg, 141145132Sanholt MGA_TEXORG1, tex->texorg1, 142145132Sanholt MGA_TEXORG2, tex->texorg2, 143145132Sanholt MGA_TEXORG3, tex->texorg3); 14495584Sanholt 145145132Sanholt DMA_BLOCK(MGA_TEXORG4, tex->texorg4, 146145132Sanholt MGA_TEXWIDTH, tex->texwidth, 147145132Sanholt MGA_TEXHEIGHT, tex->texheight, 148145132Sanholt MGA_WR24, tex->texwidth); 14995584Sanholt 150145132Sanholt DMA_BLOCK(MGA_WR34, tex->texheight, 151145132Sanholt MGA_TEXTRANS, 0x0000ffff, 152145132Sanholt MGA_TEXTRANSHIGH, 0x0000ffff, 153145132Sanholt MGA_DMAPAD, 0x00000000); 15495584Sanholt 15595584Sanholt ADVANCE_DMA(); 15695584Sanholt} 15795584Sanholt 158145132Sanholtstatic __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv) 15995584Sanholt{ 16095584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 16195584Sanholt drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; 16295584Sanholt DMA_LOCALS; 16395584Sanholt 164182080Srnoland/* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */ 165182080Srnoland/* tex->texctl, tex->texctl2); */ 166112015Sanholt 167145132Sanholt BEGIN_DMA(6); 16895584Sanholt 169145132Sanholt DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC, 170145132Sanholt MGA_TEXCTL, tex->texctl, 171145132Sanholt MGA_TEXFILTER, tex->texfilter, 172145132Sanholt MGA_TEXBORDERCOL, tex->texbordercol); 17395584Sanholt 174145132Sanholt DMA_BLOCK(MGA_TEXORG, tex->texorg, 175145132Sanholt MGA_TEXORG1, tex->texorg1, 176145132Sanholt MGA_TEXORG2, tex->texorg2, 177145132Sanholt MGA_TEXORG3, tex->texorg3); 17895584Sanholt 179145132Sanholt DMA_BLOCK(MGA_TEXORG4, tex->texorg4, 180145132Sanholt MGA_TEXWIDTH, tex->texwidth, 181145132Sanholt MGA_TEXHEIGHT, tex->texheight, 182145132Sanholt MGA_WR49, 0x00000000); 18395584Sanholt 184145132Sanholt DMA_BLOCK(MGA_WR57, 0x00000000, 185145132Sanholt MGA_WR53, 0x00000000, 186145132Sanholt MGA_WR61, 0x00000000, 187145132Sanholt MGA_WR52, MGA_G400_WR_MAGIC); 18895584Sanholt 189145132Sanholt DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC, 190145132Sanholt MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC, 191145132Sanholt MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC, 192145132Sanholt MGA_DMAPAD, 0x00000000); 19395584Sanholt 194145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 195145132Sanholt MGA_DMAPAD, 0x00000000, 196145132Sanholt MGA_TEXTRANS, 0x0000ffff, 197145132Sanholt MGA_TEXTRANSHIGH, 0x0000ffff); 19895584Sanholt 19995584Sanholt ADVANCE_DMA(); 20095584Sanholt} 20195584Sanholt 202145132Sanholtstatic __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv) 20395584Sanholt{ 20495584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 20595584Sanholt drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1]; 20695584Sanholt DMA_LOCALS; 20795584Sanholt 208182080Srnoland/* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */ 209182080Srnoland/* tex->texctl, tex->texctl2); */ 210112015Sanholt 211145132Sanholt BEGIN_DMA(5); 21295584Sanholt 213145132Sanholt DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 | 214145132Sanholt MGA_MAP1_ENABLE | 215145132Sanholt MGA_G400_TC2_MAGIC), 216145132Sanholt MGA_TEXCTL, tex->texctl, 217145132Sanholt MGA_TEXFILTER, tex->texfilter, 218145132Sanholt MGA_TEXBORDERCOL, tex->texbordercol); 21995584Sanholt 220145132Sanholt DMA_BLOCK(MGA_TEXORG, tex->texorg, 221145132Sanholt MGA_TEXORG1, tex->texorg1, 222145132Sanholt MGA_TEXORG2, tex->texorg2, 223145132Sanholt MGA_TEXORG3, tex->texorg3); 22495584Sanholt 225145132Sanholt DMA_BLOCK(MGA_TEXORG4, tex->texorg4, 226145132Sanholt MGA_TEXWIDTH, tex->texwidth, 227145132Sanholt MGA_TEXHEIGHT, tex->texheight, 228145132Sanholt MGA_WR49, 0x00000000); 22995584Sanholt 230145132Sanholt DMA_BLOCK(MGA_WR57, 0x00000000, 231145132Sanholt MGA_WR53, 0x00000000, 232145132Sanholt MGA_WR61, 0x00000000, 233145132Sanholt MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC); 23495584Sanholt 235145132Sanholt DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC, 236145132Sanholt MGA_TEXTRANS, 0x0000ffff, 237145132Sanholt MGA_TEXTRANSHIGH, 0x0000ffff, 238145132Sanholt MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC); 23995584Sanholt 24095584Sanholt ADVANCE_DMA(); 24195584Sanholt} 24295584Sanholt 243145132Sanholtstatic __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv) 24495584Sanholt{ 24595584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 24695584Sanholt unsigned int pipe = sarea_priv->warp_pipe; 24795584Sanholt DMA_LOCALS; 24895584Sanholt 249145132Sanholt BEGIN_DMA(3); 25095584Sanholt 251145132Sanholt DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND, 252145132Sanholt MGA_WVRTXSZ, 0x00000007, 253145132Sanholt MGA_WFLAG, 0x00000000, 254145132Sanholt MGA_WR24, 0x00000000); 25595584Sanholt 256145132Sanholt DMA_BLOCK(MGA_WR25, 0x00000100, 257145132Sanholt MGA_WR34, 0x00000000, 258145132Sanholt MGA_WR42, 0x0000ffff, 259145132Sanholt MGA_WR60, 0x0000ffff); 26095584Sanholt 261330446Seadler /* Padding required due to hardware bug. 26295584Sanholt */ 263145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0xffffffff, 264145132Sanholt MGA_DMAPAD, 0xffffffff, 265145132Sanholt MGA_DMAPAD, 0xffffffff, 266145132Sanholt MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | 267152909Sanholt MGA_WMODE_START | dev_priv->wagp_enable)); 26895584Sanholt 26995584Sanholt ADVANCE_DMA(); 27095584Sanholt} 27195584Sanholt 272145132Sanholtstatic __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv) 27395584Sanholt{ 27495584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 27595584Sanholt unsigned int pipe = sarea_priv->warp_pipe; 27695584Sanholt DMA_LOCALS; 27795584Sanholt 278182080Srnoland/* printk("mga_g400_emit_pipe %x\n", pipe); */ 279112015Sanholt 280145132Sanholt BEGIN_DMA(10); 28195584Sanholt 282145132Sanholt DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND, 283145132Sanholt MGA_DMAPAD, 0x00000000, 284145132Sanholt MGA_DMAPAD, 0x00000000, 285145132Sanholt MGA_DMAPAD, 0x00000000); 28695584Sanholt 287145132Sanholt if (pipe & MGA_T2) { 288145132Sanholt DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09, 289145132Sanholt MGA_DMAPAD, 0x00000000, 290145132Sanholt MGA_DMAPAD, 0x00000000, 291145132Sanholt MGA_DMAPAD, 0x00000000); 29295584Sanholt 293145132Sanholt DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, 294145132Sanholt MGA_WACCEPTSEQ, 0x00000000, 295145132Sanholt MGA_WACCEPTSEQ, 0x00000000, 296145132Sanholt MGA_WACCEPTSEQ, 0x1e000000); 29795584Sanholt } else { 298145132Sanholt if (dev_priv->warp_pipe & MGA_T2) { 29995584Sanholt /* Flush the WARP pipe */ 300145132Sanholt DMA_BLOCK(MGA_YDST, 0x00000000, 301145132Sanholt MGA_FXLEFT, 0x00000000, 302145132Sanholt MGA_FXRIGHT, 0x00000001, 303145132Sanholt MGA_DWGCTL, MGA_DWGCTL_FLUSH); 30495584Sanholt 305145132Sanholt DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001, 306145132Sanholt MGA_DWGSYNC, 0x00007000, 307145132Sanholt MGA_TEXCTL2, MGA_G400_TC2_MAGIC, 308145132Sanholt MGA_LEN + MGA_EXEC, 0x00000000); 30995584Sanholt 310145132Sanholt DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX | 311145132Sanholt MGA_G400_TC2_MAGIC), 312145132Sanholt MGA_LEN + MGA_EXEC, 0x00000000, 313145132Sanholt MGA_TEXCTL2, MGA_G400_TC2_MAGIC, 314145132Sanholt MGA_DMAPAD, 0x00000000); 31595584Sanholt } 31695584Sanholt 317145132Sanholt DMA_BLOCK(MGA_WVRTXSZ, 0x00001807, 318145132Sanholt MGA_DMAPAD, 0x00000000, 319145132Sanholt MGA_DMAPAD, 0x00000000, 320145132Sanholt MGA_DMAPAD, 0x00000000); 32195584Sanholt 322145132Sanholt DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, 323145132Sanholt MGA_WACCEPTSEQ, 0x00000000, 324145132Sanholt MGA_WACCEPTSEQ, 0x00000000, 325145132Sanholt MGA_WACCEPTSEQ, 0x18000000); 32695584Sanholt } 32795584Sanholt 328145132Sanholt DMA_BLOCK(MGA_WFLAG, 0x00000000, 329145132Sanholt MGA_WFLAG1, 0x00000000, 330145132Sanholt MGA_WR56, MGA_G400_WR56_MAGIC, 331145132Sanholt MGA_DMAPAD, 0x00000000); 33295584Sanholt 333145132Sanholt DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0 */ 334145132Sanholt MGA_WR57, 0x00000000, /* tex0 */ 335145132Sanholt MGA_WR53, 0x00000000, /* tex1 */ 336145132Sanholt MGA_WR61, 0x00000000); /* tex1 */ 33795584Sanholt 338145132Sanholt DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */ 339145132Sanholt MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */ 340145132Sanholt MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */ 341145132Sanholt MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height */ 34295584Sanholt 343330446Seadler /* Padding required due to hardware bug */ 344145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0xffffffff, 345145132Sanholt MGA_DMAPAD, 0xffffffff, 346145132Sanholt MGA_DMAPAD, 0xffffffff, 347145132Sanholt MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | 348152909Sanholt MGA_WMODE_START | dev_priv->wagp_enable)); 34995584Sanholt 35095584Sanholt ADVANCE_DMA(); 35195584Sanholt} 35295584Sanholt 353145132Sanholtstatic void mga_g200_emit_state(drm_mga_private_t * dev_priv) 35495584Sanholt{ 35595584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 35695584Sanholt unsigned int dirty = sarea_priv->dirty; 35795584Sanholt 358145132Sanholt if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { 359145132Sanholt mga_g200_emit_pipe(dev_priv); 36095584Sanholt dev_priv->warp_pipe = sarea_priv->warp_pipe; 36195584Sanholt } 36295584Sanholt 363145132Sanholt if (dirty & MGA_UPLOAD_CONTEXT) { 364145132Sanholt mga_g200_emit_context(dev_priv); 36595584Sanholt sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; 36695584Sanholt } 36795584Sanholt 368145132Sanholt if (dirty & MGA_UPLOAD_TEX0) { 369145132Sanholt mga_g200_emit_tex0(dev_priv); 37095584Sanholt sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; 37195584Sanholt } 37295584Sanholt} 37395584Sanholt 374145132Sanholtstatic void mga_g400_emit_state(drm_mga_private_t * dev_priv) 37595584Sanholt{ 37695584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 37795584Sanholt unsigned int dirty = sarea_priv->dirty; 37895584Sanholt int multitex = sarea_priv->warp_pipe & MGA_T2; 37995584Sanholt 380145132Sanholt if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { 381145132Sanholt mga_g400_emit_pipe(dev_priv); 38295584Sanholt dev_priv->warp_pipe = sarea_priv->warp_pipe; 38395584Sanholt } 38495584Sanholt 385145132Sanholt if (dirty & MGA_UPLOAD_CONTEXT) { 386145132Sanholt mga_g400_emit_context(dev_priv); 38795584Sanholt sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; 38895584Sanholt } 38995584Sanholt 390145132Sanholt if (dirty & MGA_UPLOAD_TEX0) { 391145132Sanholt mga_g400_emit_tex0(dev_priv); 39295584Sanholt sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; 39395584Sanholt } 39495584Sanholt 395145132Sanholt if ((dirty & MGA_UPLOAD_TEX1) && multitex) { 396145132Sanholt mga_g400_emit_tex1(dev_priv); 39795584Sanholt sarea_priv->dirty &= ~MGA_UPLOAD_TEX1; 39895584Sanholt } 39995584Sanholt} 40095584Sanholt 40195584Sanholt/* ================================================================ 40295584Sanholt * SAREA state verification 40395584Sanholt */ 40495584Sanholt 40595584Sanholt/* Disallow all write destinations except the front and backbuffer. 40695584Sanholt */ 407145132Sanholtstatic int mga_verify_context(drm_mga_private_t * dev_priv) 40895584Sanholt{ 40995584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 41095584Sanholt drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 41195584Sanholt 412145132Sanholt if (ctx->dstorg != dev_priv->front_offset && 413145132Sanholt ctx->dstorg != dev_priv->back_offset) { 414145132Sanholt DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n", 415145132Sanholt ctx->dstorg, dev_priv->front_offset, 416145132Sanholt dev_priv->back_offset); 41795584Sanholt ctx->dstorg = 0; 418182080Srnoland return -EINVAL; 41995584Sanholt } 42095584Sanholt 42195584Sanholt return 0; 42295584Sanholt} 42395584Sanholt 42495584Sanholt/* Disallow texture reads from PCI space. 42595584Sanholt */ 426145132Sanholtstatic int mga_verify_tex(drm_mga_private_t * dev_priv, int unit) 42795584Sanholt{ 42895584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 42995584Sanholt drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit]; 43095584Sanholt unsigned int org; 43195584Sanholt 43295584Sanholt org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK); 43395584Sanholt 434145132Sanholt if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) { 435145132Sanholt DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit); 43695584Sanholt tex->texorg = 0; 437182080Srnoland return -EINVAL; 43895584Sanholt } 43995584Sanholt 44095584Sanholt return 0; 44195584Sanholt} 44295584Sanholt 443145132Sanholtstatic int mga_verify_state(drm_mga_private_t * dev_priv) 44495584Sanholt{ 44595584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 44695584Sanholt unsigned int dirty = sarea_priv->dirty; 44795584Sanholt int ret = 0; 44895584Sanholt 449145132Sanholt if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) 45095584Sanholt sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; 45195584Sanholt 452145132Sanholt if (dirty & MGA_UPLOAD_CONTEXT) 453145132Sanholt ret |= mga_verify_context(dev_priv); 45495584Sanholt 455145132Sanholt if (dirty & MGA_UPLOAD_TEX0) 456145132Sanholt ret |= mga_verify_tex(dev_priv, 0); 45795584Sanholt 458152909Sanholt if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { 459145132Sanholt if (dirty & MGA_UPLOAD_TEX1) 460145132Sanholt ret |= mga_verify_tex(dev_priv, 1); 46195584Sanholt 462145132Sanholt if (dirty & MGA_UPLOAD_PIPE) 463145132Sanholt ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES); 46495584Sanholt } else { 465145132Sanholt if (dirty & MGA_UPLOAD_PIPE) 466145132Sanholt ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES); 46795584Sanholt } 46895584Sanholt 469145132Sanholt return (ret == 0); 47095584Sanholt} 47195584Sanholt 472145132Sanholtstatic int mga_verify_iload(drm_mga_private_t * dev_priv, 473145132Sanholt unsigned int dstorg, unsigned int length) 47495584Sanholt{ 475145132Sanholt if (dstorg < dev_priv->texture_offset || 476145132Sanholt dstorg + length > (dev_priv->texture_offset + 477145132Sanholt dev_priv->texture_size)) { 478145132Sanholt DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg); 479182080Srnoland return -EINVAL; 48095584Sanholt } 48195584Sanholt 482145132Sanholt if (length & MGA_ILOAD_MASK) { 483145132Sanholt DRM_ERROR("*** bad iload length: 0x%x\n", 484145132Sanholt length & MGA_ILOAD_MASK); 485182080Srnoland return -EINVAL; 48695584Sanholt } 48795584Sanholt 48895584Sanholt return 0; 48995584Sanholt} 49095584Sanholt 491145132Sanholtstatic int mga_verify_blit(drm_mga_private_t * dev_priv, 492145132Sanholt unsigned int srcorg, unsigned int dstorg) 49395584Sanholt{ 494145132Sanholt if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) || 495145132Sanholt (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) { 496145132Sanholt DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg); 497182080Srnoland return -EINVAL; 49895584Sanholt } 49995584Sanholt return 0; 50095584Sanholt} 50195584Sanholt 50295584Sanholt/* ================================================================ 50395584Sanholt * 50495584Sanholt */ 50595584Sanholt 506182080Srnolandstatic void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * clear) 50795584Sanholt{ 50895584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 50995584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 51095584Sanholt drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 511182080Srnoland struct drm_clip_rect *pbox = sarea_priv->boxes; 51295584Sanholt int nbox = sarea_priv->nbox; 51395584Sanholt int i; 51495584Sanholt DMA_LOCALS; 515145132Sanholt DRM_DEBUG("\n"); 51695584Sanholt 517145132Sanholt BEGIN_DMA(1); 51895584Sanholt 519145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 520145132Sanholt MGA_DMAPAD, 0x00000000, 521145132Sanholt MGA_DWGSYNC, 0x00007100, 522145132Sanholt MGA_DWGSYNC, 0x00007000); 52395584Sanholt 52495584Sanholt ADVANCE_DMA(); 52595584Sanholt 526145132Sanholt for (i = 0; i < nbox; i++) { 527182080Srnoland struct drm_clip_rect *box = &pbox[i]; 52895584Sanholt u32 height = box->y2 - box->y1; 52995584Sanholt 530145132Sanholt DRM_DEBUG(" from=%d,%d to=%d,%d\n", 531145132Sanholt box->x1, box->y1, box->x2, box->y2); 53295584Sanholt 533145132Sanholt if (clear->flags & MGA_FRONT) { 534145132Sanholt BEGIN_DMA(2); 53595584Sanholt 536145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 537145132Sanholt MGA_PLNWT, clear->color_mask, 538145132Sanholt MGA_YDSTLEN, (box->y1 << 16) | height, 539145132Sanholt MGA_FXBNDRY, (box->x2 << 16) | box->x1); 54095584Sanholt 541145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 542145132Sanholt MGA_FCOL, clear->clear_color, 543145132Sanholt MGA_DSTORG, dev_priv->front_offset, 544145132Sanholt MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); 54595584Sanholt 54695584Sanholt ADVANCE_DMA(); 54795584Sanholt } 54895584Sanholt 549145132Sanholt if (clear->flags & MGA_BACK) { 550145132Sanholt BEGIN_DMA(2); 55195584Sanholt 552145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 553145132Sanholt MGA_PLNWT, clear->color_mask, 554145132Sanholt MGA_YDSTLEN, (box->y1 << 16) | height, 555145132Sanholt MGA_FXBNDRY, (box->x2 << 16) | box->x1); 55695584Sanholt 557145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 558145132Sanholt MGA_FCOL, clear->clear_color, 559145132Sanholt MGA_DSTORG, dev_priv->back_offset, 560145132Sanholt MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); 56195584Sanholt 56295584Sanholt ADVANCE_DMA(); 56395584Sanholt } 56495584Sanholt 565145132Sanholt if (clear->flags & MGA_DEPTH) { 566145132Sanholt BEGIN_DMA(2); 56795584Sanholt 568145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 569145132Sanholt MGA_PLNWT, clear->depth_mask, 570145132Sanholt MGA_YDSTLEN, (box->y1 << 16) | height, 571145132Sanholt MGA_FXBNDRY, (box->x2 << 16) | box->x1); 57295584Sanholt 573145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 574145132Sanholt MGA_FCOL, clear->clear_depth, 575145132Sanholt MGA_DSTORG, dev_priv->depth_offset, 576145132Sanholt MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); 57795584Sanholt 57895584Sanholt ADVANCE_DMA(); 57995584Sanholt } 58095584Sanholt 58195584Sanholt } 58295584Sanholt 583145132Sanholt BEGIN_DMA(1); 58495584Sanholt 58595584Sanholt /* Force reset of DWGCTL */ 586145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 587145132Sanholt MGA_DMAPAD, 0x00000000, 588145132Sanholt MGA_PLNWT, ctx->plnwt, 589145132Sanholt MGA_DWGCTL, ctx->dwgctl); 59095584Sanholt 59195584Sanholt ADVANCE_DMA(); 59295584Sanholt 59395584Sanholt FLUSH_DMA(); 59495584Sanholt} 59595584Sanholt 596182080Srnolandstatic void mga_dma_dispatch_swap(struct drm_device * dev) 59795584Sanholt{ 59895584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 59995584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 60095584Sanholt drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 601182080Srnoland struct drm_clip_rect *pbox = sarea_priv->boxes; 60295584Sanholt int nbox = sarea_priv->nbox; 60395584Sanholt int i; 60495584Sanholt DMA_LOCALS; 605145132Sanholt DRM_DEBUG("\n"); 60695584Sanholt 60795584Sanholt sarea_priv->last_frame.head = dev_priv->prim.tail; 60895584Sanholt sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; 60995584Sanholt 610145132Sanholt BEGIN_DMA(4 + nbox); 61195584Sanholt 612145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 613145132Sanholt MGA_DMAPAD, 0x00000000, 614145132Sanholt MGA_DWGSYNC, 0x00007100, 615145132Sanholt MGA_DWGSYNC, 0x00007000); 61695584Sanholt 617145132Sanholt DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset, 618145132Sanholt MGA_MACCESS, dev_priv->maccess, 619145132Sanholt MGA_SRCORG, dev_priv->back_offset, 620145132Sanholt MGA_AR5, dev_priv->front_pitch); 62195584Sanholt 622145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 623145132Sanholt MGA_DMAPAD, 0x00000000, 624145132Sanholt MGA_PLNWT, 0xffffffff, 625145132Sanholt MGA_DWGCTL, MGA_DWGCTL_COPY); 62695584Sanholt 627145132Sanholt for (i = 0; i < nbox; i++) { 628182080Srnoland struct drm_clip_rect *box = &pbox[i]; 62995584Sanholt u32 height = box->y2 - box->y1; 63095584Sanholt u32 start = box->y1 * dev_priv->front_pitch; 63195584Sanholt 632145132Sanholt DRM_DEBUG(" from=%d,%d to=%d,%d\n", 633145132Sanholt box->x1, box->y1, box->x2, box->y2); 63495584Sanholt 635145132Sanholt DMA_BLOCK(MGA_AR0, start + box->x2 - 1, 636145132Sanholt MGA_AR3, start + box->x1, 637145132Sanholt MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1, 638145132Sanholt MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height); 63995584Sanholt } 64095584Sanholt 641145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 642145132Sanholt MGA_PLNWT, ctx->plnwt, 643145132Sanholt MGA_SRCORG, dev_priv->front_offset, 644145132Sanholt MGA_DWGCTL, ctx->dwgctl); 64595584Sanholt 64695584Sanholt ADVANCE_DMA(); 64795584Sanholt 64895584Sanholt FLUSH_DMA(); 64995584Sanholt 650182080Srnoland DRM_DEBUG("... done.\n"); 65195584Sanholt} 65295584Sanholt 653182080Srnolandstatic void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf) 65495584Sanholt{ 65595584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 65695584Sanholt drm_mga_buf_priv_t *buf_priv = buf->dev_private; 65795584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 65895584Sanholt u32 address = (u32) buf->bus_address; 65995584Sanholt u32 length = (u32) buf->used; 66095584Sanholt int i = 0; 66195584Sanholt DMA_LOCALS; 662182080Srnoland DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); 66395584Sanholt 664145132Sanholt if (buf->used) { 66595584Sanholt buf_priv->dispatched = 1; 66695584Sanholt 667145132Sanholt MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); 66895584Sanholt 66995584Sanholt do { 670145132Sanholt if (i < sarea_priv->nbox) { 671145132Sanholt mga_emit_clip_rect(dev_priv, 672145132Sanholt &sarea_priv->boxes[i]); 67395584Sanholt } 67495584Sanholt 675145132Sanholt BEGIN_DMA(1); 67695584Sanholt 677145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 678145132Sanholt MGA_DMAPAD, 0x00000000, 679145132Sanholt MGA_SECADDRESS, (address | 680145132Sanholt MGA_DMA_VERTEX), 681145132Sanholt MGA_SECEND, ((address + length) | 682152909Sanholt dev_priv->dma_access)); 68395584Sanholt 68495584Sanholt ADVANCE_DMA(); 685145132Sanholt } while (++i < sarea_priv->nbox); 68695584Sanholt } 68795584Sanholt 688145132Sanholt if (buf_priv->discard) { 689145132Sanholt AGE_BUFFER(buf_priv); 69095584Sanholt buf->pending = 0; 69195584Sanholt buf->used = 0; 69295584Sanholt buf_priv->dispatched = 0; 69395584Sanholt 694145132Sanholt mga_freelist_put(dev, buf); 69595584Sanholt } 69695584Sanholt 69795584Sanholt FLUSH_DMA(); 69895584Sanholt} 69995584Sanholt 700182080Srnolandstatic void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * buf, 701145132Sanholt unsigned int start, unsigned int end) 70295584Sanholt{ 70395584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 70495584Sanholt drm_mga_buf_priv_t *buf_priv = buf->dev_private; 70595584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 70695584Sanholt u32 address = (u32) buf->bus_address; 70795584Sanholt int i = 0; 70895584Sanholt DMA_LOCALS; 709182080Srnoland DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end); 71095584Sanholt 711145132Sanholt if (start != end) { 71295584Sanholt buf_priv->dispatched = 1; 71395584Sanholt 714145132Sanholt MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); 71595584Sanholt 71695584Sanholt do { 717145132Sanholt if (i < sarea_priv->nbox) { 718145132Sanholt mga_emit_clip_rect(dev_priv, 719145132Sanholt &sarea_priv->boxes[i]); 72095584Sanholt } 72195584Sanholt 722145132Sanholt BEGIN_DMA(1); 72395584Sanholt 724145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 725145132Sanholt MGA_DMAPAD, 0x00000000, 726145132Sanholt MGA_SETUPADDRESS, address + start, 727145132Sanholt MGA_SETUPEND, ((address + end) | 728152909Sanholt dev_priv->dma_access)); 72995584Sanholt 73095584Sanholt ADVANCE_DMA(); 731145132Sanholt } while (++i < sarea_priv->nbox); 73295584Sanholt } 73395584Sanholt 734145132Sanholt if (buf_priv->discard) { 735145132Sanholt AGE_BUFFER(buf_priv); 73695584Sanholt buf->pending = 0; 73795584Sanholt buf->used = 0; 73895584Sanholt buf_priv->dispatched = 0; 73995584Sanholt 740145132Sanholt mga_freelist_put(dev, buf); 74195584Sanholt } 74295584Sanholt 74395584Sanholt FLUSH_DMA(); 74495584Sanholt} 74595584Sanholt 74695584Sanholt/* This copies a 64 byte aligned agp region to the frambuffer with a 74795584Sanholt * standard blit, the ioctl needs to do checking. 74895584Sanholt */ 749182080Srnolandstatic void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf, 750145132Sanholt unsigned int dstorg, unsigned int length) 75195584Sanholt{ 75295584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 75395584Sanholt drm_mga_buf_priv_t *buf_priv = buf->dev_private; 75495584Sanholt drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; 755152909Sanholt u32 srcorg = buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM; 75695584Sanholt u32 y2; 75795584Sanholt DMA_LOCALS; 758145132Sanholt DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); 75995584Sanholt 76095584Sanholt y2 = length / 64; 76195584Sanholt 762145132Sanholt BEGIN_DMA(5); 76395584Sanholt 764145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 765145132Sanholt MGA_DMAPAD, 0x00000000, 766145132Sanholt MGA_DWGSYNC, 0x00007100, 767145132Sanholt MGA_DWGSYNC, 0x00007000); 76895584Sanholt 769145132Sanholt DMA_BLOCK(MGA_DSTORG, dstorg, 770145132Sanholt MGA_MACCESS, 0x00000000, 771145132Sanholt MGA_SRCORG, srcorg, 772145132Sanholt MGA_AR5, 64); 77395584Sanholt 774145132Sanholt DMA_BLOCK(MGA_PITCH, 64, 775145132Sanholt MGA_PLNWT, 0xffffffff, 776145132Sanholt MGA_DMAPAD, 0x00000000, 777145132Sanholt MGA_DWGCTL, MGA_DWGCTL_COPY); 77895584Sanholt 779145132Sanholt DMA_BLOCK(MGA_AR0, 63, 780145132Sanholt MGA_AR3, 0, 781145132Sanholt MGA_FXBNDRY, (63 << 16) | 0, 782145132Sanholt MGA_YDSTLEN + MGA_EXEC, y2); 78395584Sanholt 784145132Sanholt DMA_BLOCK(MGA_PLNWT, ctx->plnwt, 785145132Sanholt MGA_SRCORG, dev_priv->front_offset, 786145132Sanholt MGA_PITCH, dev_priv->front_pitch, 787145132Sanholt MGA_DWGSYNC, 0x00007000); 78895584Sanholt 78995584Sanholt ADVANCE_DMA(); 79095584Sanholt 791145132Sanholt AGE_BUFFER(buf_priv); 79295584Sanholt 79395584Sanholt buf->pending = 0; 79495584Sanholt buf->used = 0; 79595584Sanholt buf_priv->dispatched = 0; 79695584Sanholt 797145132Sanholt mga_freelist_put(dev, buf); 79895584Sanholt 79995584Sanholt FLUSH_DMA(); 80095584Sanholt} 80195584Sanholt 802182080Srnolandstatic void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit) 80395584Sanholt{ 80495584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 80595584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 80695584Sanholt drm_mga_context_regs_t *ctx = &sarea_priv->context_state; 807182080Srnoland struct drm_clip_rect *pbox = sarea_priv->boxes; 80895584Sanholt int nbox = sarea_priv->nbox; 80995584Sanholt u32 scandir = 0, i; 81095584Sanholt DMA_LOCALS; 811145132Sanholt DRM_DEBUG("\n"); 81295584Sanholt 813145132Sanholt BEGIN_DMA(4 + nbox); 81495584Sanholt 815145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 816145132Sanholt MGA_DMAPAD, 0x00000000, 817145132Sanholt MGA_DWGSYNC, 0x00007100, 818145132Sanholt MGA_DWGSYNC, 0x00007000); 81995584Sanholt 820145132Sanholt DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY, 821145132Sanholt MGA_PLNWT, blit->planemask, 822145132Sanholt MGA_SRCORG, blit->srcorg, 823145132Sanholt MGA_DSTORG, blit->dstorg); 82495584Sanholt 825145132Sanholt DMA_BLOCK(MGA_SGN, scandir, 826145132Sanholt MGA_MACCESS, dev_priv->maccess, 827145132Sanholt MGA_AR5, blit->ydir * blit->src_pitch, 828145132Sanholt MGA_PITCH, blit->dst_pitch); 82995584Sanholt 830145132Sanholt for (i = 0; i < nbox; i++) { 83195584Sanholt int srcx = pbox[i].x1 + blit->delta_sx; 83295584Sanholt int srcy = pbox[i].y1 + blit->delta_sy; 83395584Sanholt int dstx = pbox[i].x1 + blit->delta_dx; 83495584Sanholt int dsty = pbox[i].y1 + blit->delta_dy; 83595584Sanholt int h = pbox[i].y2 - pbox[i].y1; 83695584Sanholt int w = pbox[i].x2 - pbox[i].x1 - 1; 83795584Sanholt int start; 83895584Sanholt 839145132Sanholt if (blit->ydir == -1) { 84095584Sanholt srcy = blit->height - srcy - 1; 84195584Sanholt } 84295584Sanholt 84395584Sanholt start = srcy * blit->src_pitch + srcx; 84495584Sanholt 845145132Sanholt DMA_BLOCK(MGA_AR0, start + w, 846145132Sanholt MGA_AR3, start, 847145132Sanholt MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff), 848145132Sanholt MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h); 84995584Sanholt } 85095584Sanholt 85195584Sanholt /* Do something to flush AGP? 85295584Sanholt */ 85395584Sanholt 85495584Sanholt /* Force reset of DWGCTL */ 855145132Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 856145132Sanholt MGA_PLNWT, ctx->plnwt, 857145132Sanholt MGA_PITCH, dev_priv->front_pitch, 858145132Sanholt MGA_DWGCTL, ctx->dwgctl); 85995584Sanholt 86095584Sanholt ADVANCE_DMA(); 86195584Sanholt} 86295584Sanholt 86395584Sanholt/* ================================================================ 86495584Sanholt * 86595584Sanholt */ 86695584Sanholt 867182080Srnolandstatic int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) 86895584Sanholt{ 86995584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 87095584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 871182080Srnoland drm_mga_clear_t *clear = data; 87295584Sanholt 873182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 87495584Sanholt 875145132Sanholt if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) 87695584Sanholt sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; 87795584Sanholt 878145132Sanholt WRAP_TEST_WITH_RETURN(dev_priv); 87995584Sanholt 880182080Srnoland mga_dma_dispatch_clear(dev, clear); 88195584Sanholt 88295584Sanholt /* Make sure we restore the 3D state next time. 88395584Sanholt */ 88495584Sanholt dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; 88595584Sanholt 88695584Sanholt return 0; 88795584Sanholt} 88895584Sanholt 889182080Srnolandstatic int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) 89095584Sanholt{ 89195584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 89295584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 89395584Sanholt 894182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 89595584Sanholt 896145132Sanholt if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) 89795584Sanholt sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; 89895584Sanholt 899145132Sanholt WRAP_TEST_WITH_RETURN(dev_priv); 90095584Sanholt 901145132Sanholt mga_dma_dispatch_swap(dev); 90295584Sanholt 90395584Sanholt /* Make sure we restore the 3D state next time. 90495584Sanholt */ 90595584Sanholt dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; 90695584Sanholt 90795584Sanholt return 0; 90895584Sanholt} 90995584Sanholt 910182080Srnolandstatic int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) 91195584Sanholt{ 91295584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 913182080Srnoland struct drm_device_dma *dma = dev->dma; 914182080Srnoland struct drm_buf *buf; 91595584Sanholt drm_mga_buf_priv_t *buf_priv; 916182080Srnoland drm_mga_vertex_t *vertex = data; 91795584Sanholt 918182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 91995584Sanholt 920182080Srnoland if (vertex->idx < 0 || vertex->idx > dma->buf_count) 921182080Srnoland return -EINVAL; 922182080Srnoland buf = dma->buflist[vertex->idx]; 92395584Sanholt buf_priv = buf->dev_private; 92495584Sanholt 925182080Srnoland buf->used = vertex->used; 926182080Srnoland buf_priv->discard = vertex->discard; 92795584Sanholt 928145132Sanholt if (!mga_verify_state(dev_priv)) { 929182080Srnoland if (vertex->discard) { 930145132Sanholt if (buf_priv->dispatched == 1) 931145132Sanholt AGE_BUFFER(buf_priv); 93295584Sanholt buf_priv->dispatched = 0; 933145132Sanholt mga_freelist_put(dev, buf); 93495584Sanholt } 935182080Srnoland return -EINVAL; 93695584Sanholt } 93795584Sanholt 938145132Sanholt WRAP_TEST_WITH_RETURN(dev_priv); 93995584Sanholt 940145132Sanholt mga_dma_dispatch_vertex(dev, buf); 94195584Sanholt 94295584Sanholt return 0; 94395584Sanholt} 94495584Sanholt 945182080Srnolandstatic int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) 94695584Sanholt{ 94795584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 948182080Srnoland struct drm_device_dma *dma = dev->dma; 949182080Srnoland struct drm_buf *buf; 95095584Sanholt drm_mga_buf_priv_t *buf_priv; 951182080Srnoland drm_mga_indices_t *indices = data; 95295584Sanholt 953182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 95495584Sanholt 955182080Srnoland if (indices->idx < 0 || indices->idx > dma->buf_count) 956182080Srnoland return -EINVAL; 95795584Sanholt 958182080Srnoland buf = dma->buflist[indices->idx]; 95995584Sanholt buf_priv = buf->dev_private; 96095584Sanholt 961182080Srnoland buf_priv->discard = indices->discard; 96295584Sanholt 963145132Sanholt if (!mga_verify_state(dev_priv)) { 964182080Srnoland if (indices->discard) { 965145132Sanholt if (buf_priv->dispatched == 1) 966145132Sanholt AGE_BUFFER(buf_priv); 96795584Sanholt buf_priv->dispatched = 0; 968145132Sanholt mga_freelist_put(dev, buf); 96995584Sanholt } 970182080Srnoland return -EINVAL; 97195584Sanholt } 97295584Sanholt 973145132Sanholt WRAP_TEST_WITH_RETURN(dev_priv); 97495584Sanholt 975182080Srnoland mga_dma_dispatch_indices(dev, buf, indices->start, indices->end); 97695584Sanholt 97795584Sanholt return 0; 97895584Sanholt} 97995584Sanholt 980182080Srnolandstatic int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv) 98195584Sanholt{ 982182080Srnoland struct drm_device_dma *dma = dev->dma; 98395584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 984182080Srnoland struct drm_buf *buf; 98595584Sanholt drm_mga_buf_priv_t *buf_priv; 986182080Srnoland drm_mga_iload_t *iload = data; 987145132Sanholt DRM_DEBUG("\n"); 98895584Sanholt 989182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 99095584Sanholt 99195584Sanholt#if 0 992145132Sanholt if (mga_do_wait_for_idle(dev_priv) < 0) { 993145132Sanholt if (MGA_DMA_DEBUG) 994182080Srnoland DRM_INFO("-EBUSY\n"); 995182080Srnoland return -EBUSY; 99695584Sanholt } 99795584Sanholt#endif 998182080Srnoland if (iload->idx < 0 || iload->idx > dma->buf_count) 999182080Srnoland return -EINVAL; 100095584Sanholt 1001182080Srnoland buf = dma->buflist[iload->idx]; 100295584Sanholt buf_priv = buf->dev_private; 100395584Sanholt 1004182080Srnoland if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) { 1005145132Sanholt mga_freelist_put(dev, buf); 1006182080Srnoland return -EINVAL; 100795584Sanholt } 100895584Sanholt 1009145132Sanholt WRAP_TEST_WITH_RETURN(dev_priv); 101095584Sanholt 1011182080Srnoland mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length); 101295584Sanholt 101395584Sanholt /* Make sure we restore the 3D state next time. 101495584Sanholt */ 101595584Sanholt dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; 101695584Sanholt 101795584Sanholt return 0; 101895584Sanholt} 101995584Sanholt 1020182080Srnolandstatic int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) 102195584Sanholt{ 102295584Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 102395584Sanholt drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; 1024182080Srnoland drm_mga_blit_t *blit = data; 1025145132Sanholt DRM_DEBUG("\n"); 102695584Sanholt 1027182080Srnoland LOCK_TEST_WITH_RETURN(dev, file_priv); 102895584Sanholt 1029145132Sanholt if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) 103095584Sanholt sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; 103195584Sanholt 1032182080Srnoland if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg)) 1033182080Srnoland return -EINVAL; 103495584Sanholt 1035145132Sanholt WRAP_TEST_WITH_RETURN(dev_priv); 103695584Sanholt 1037182080Srnoland mga_dma_dispatch_blit(dev, blit); 103895584Sanholt 103995584Sanholt /* Make sure we restore the 3D state next time. 104095584Sanholt */ 104195584Sanholt dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; 104295584Sanholt 104395584Sanholt return 0; 104495584Sanholt} 1045112015Sanholt 1046182080Srnolandstatic int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) 1047112015Sanholt{ 1048112015Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 1049182080Srnoland drm_mga_getparam_t *param = data; 1050112015Sanholt int value; 1051112015Sanholt 1052145132Sanholt if (!dev_priv) { 1053182080Srnoland DRM_ERROR("called with no initialization\n"); 1054182080Srnoland return -EINVAL; 1055112015Sanholt } 1056112015Sanholt 1057145132Sanholt DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); 1058112015Sanholt 1059182080Srnoland switch (param->param) { 1060112015Sanholt case MGA_PARAM_IRQ_NR: 1061112015Sanholt value = dev->irq; 1062112015Sanholt break; 1063152909Sanholt case MGA_PARAM_CARD_TYPE: 1064152909Sanholt value = dev_priv->chipset; 1065152909Sanholt break; 1066112015Sanholt default: 1067182080Srnoland return -EINVAL; 1068112015Sanholt } 1069112015Sanholt 1070182080Srnoland if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { 1071145132Sanholt DRM_ERROR("copy_to_user\n"); 1072182080Srnoland return -EFAULT; 1073112015Sanholt } 1074145132Sanholt 1075112015Sanholt return 0; 1076112015Sanholt} 1077145132Sanholt 1078182080Srnolandstatic int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv) 1079152909Sanholt{ 1080152909Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 1081182080Srnoland u32 *fence = data; 1082152909Sanholt DMA_LOCALS; 1083152909Sanholt 1084152909Sanholt if (!dev_priv) { 1085182080Srnoland DRM_ERROR("called with no initialization\n"); 1086182080Srnoland return -EINVAL; 1087152909Sanholt } 1088152909Sanholt 1089152909Sanholt DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); 1090152909Sanholt 1091182080Srnoland /* I would normal do this assignment in the declaration of fence, 1092152909Sanholt * but dev_priv may be NULL. 1093152909Sanholt */ 1094152909Sanholt 1095182080Srnoland *fence = dev_priv->next_fence_to_post; 1096152909Sanholt dev_priv->next_fence_to_post++; 1097152909Sanholt 1098152909Sanholt BEGIN_DMA(1); 1099152909Sanholt DMA_BLOCK(MGA_DMAPAD, 0x00000000, 1100152909Sanholt MGA_DMAPAD, 0x00000000, 1101152909Sanholt MGA_DMAPAD, 0x00000000, 1102152909Sanholt MGA_SOFTRAP, 0x00000000); 1103152909Sanholt ADVANCE_DMA(); 1104152909Sanholt 1105152909Sanholt return 0; 1106152909Sanholt} 1107152909Sanholt 1108182080Srnolandstatic int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *file_priv) 1109152909Sanholt{ 1110152909Sanholt drm_mga_private_t *dev_priv = dev->dev_private; 1111182080Srnoland u32 *fence = data; 1112152909Sanholt 1113152909Sanholt if (!dev_priv) { 1114182080Srnoland DRM_ERROR("called with no initialization\n"); 1115182080Srnoland return -EINVAL; 1116152909Sanholt } 1117152909Sanholt 1118152909Sanholt DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); 1119152909Sanholt 1120182080Srnoland mga_driver_fence_wait(dev, fence); 1121152909Sanholt 1122152909Sanholt return 0; 1123152909Sanholt} 1124152909Sanholt 1125182080Srnolandstruct drm_ioctl_desc mga_ioctls[] = { 1126182080Srnoland DRM_IOCTL_DEF(DRM_MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1127182080Srnoland DRM_IOCTL_DEF(DRM_MGA_FLUSH, mga_dma_flush, DRM_AUTH), 1128182080Srnoland DRM_IOCTL_DEF(DRM_MGA_RESET, mga_dma_reset, DRM_AUTH), 1129182080Srnoland DRM_IOCTL_DEF(DRM_MGA_SWAP, mga_dma_swap, DRM_AUTH), 1130182080Srnoland DRM_IOCTL_DEF(DRM_MGA_CLEAR, mga_dma_clear, DRM_AUTH), 1131182080Srnoland DRM_IOCTL_DEF(DRM_MGA_VERTEX, mga_dma_vertex, DRM_AUTH), 1132182080Srnoland DRM_IOCTL_DEF(DRM_MGA_INDICES, mga_dma_indices, DRM_AUTH), 1133182080Srnoland DRM_IOCTL_DEF(DRM_MGA_ILOAD, mga_dma_iload, DRM_AUTH), 1134182080Srnoland DRM_IOCTL_DEF(DRM_MGA_BLIT, mga_dma_blit, DRM_AUTH), 1135182080Srnoland DRM_IOCTL_DEF(DRM_MGA_GETPARAM, mga_getparam, DRM_AUTH), 1136182080Srnoland DRM_IOCTL_DEF(DRM_MGA_SET_FENCE, mga_set_fence, DRM_AUTH), 1137182080Srnoland DRM_IOCTL_DEF(DRM_MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH), 1138182080Srnoland DRM_IOCTL_DEF(DRM_MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1139152909Sanholt 1140145132Sanholt}; 1141145132Sanholt 1142145132Sanholtint mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); 1143