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