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