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  * PRECISION INSIGHT 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 OTHER
25  * DEALINGS IN THE SOFTWARE.
26  *
27  * Authors: Jeff Hartmann <jhartmann@valinux.com>
28  * 	    Keith Whitwell <keithw@valinux.com>
29  *
30  */
31 
32 #define __NO_VERSION__
33 #include "drmP.h"
34 #include "mga_drv.h"
35 #include "drm.h"
36 
37 /* If you change the functions to set state, PLEASE
38  * change these values
39  */
40 
41 #define MGAEMITCLIP_SIZE	10
42 #define MGAEMITCTX_SIZE		20
43 #define MGAG200EMITTEX_SIZE 	20
44 #define MGAG400EMITTEX0_SIZE	30
45 #define MGAG400EMITTEX1_SIZE	25
46 #define MGAG400EMITPIPE_SIZE	50
47 #define MGAG200EMITPIPE_SIZE	15
48 
49 #define MAX_STATE_SIZE ((MGAEMITCLIP_SIZE * MGA_NR_SAREA_CLIPRECTS) + \
50 			MGAEMITCTX_SIZE + MGAG400EMITTEX0_SIZE + \
51 			MGAG400EMITTEX1_SIZE + MGAG400EMITPIPE_SIZE)
52 
mgaEmitClipRect(drm_mga_private_t * dev_priv,drm_clip_rect_t * box)53 static void mgaEmitClipRect(drm_mga_private_t * dev_priv,
54 			    drm_clip_rect_t * box)
55 {
56 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
57 	unsigned int *regs = sarea_priv->ContextState;
58 	PRIMLOCALS;
59 
60 	/* This takes 10 dwords */
61 	PRIMGETPTR(dev_priv);
62 
63 	/* Force reset of dwgctl on G400 (eliminates clip disable bit) */
64 	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
65 #if 0
66 		PRIMOUTREG(MGAREG_DMAPAD, 0);
67 		PRIMOUTREG(MGAREG_DWGSYNC, 0);
68 		PRIMOUTREG(MGAREG_DWGSYNC, 0);
69 		PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
70 #else
71 		PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
72 		PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
73 		PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
74 		PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
75 #endif
76 	}
77 	PRIMOUTREG(MGAREG_DMAPAD, 0);
78 	PRIMOUTREG(MGAREG_CXBNDRY, ((box->x2) << 16) | (box->x1));
79 	PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / dev_priv->cpp);
80 	PRIMOUTREG(MGAREG_YBOT, box->y2 * dev_priv->stride / dev_priv->cpp);
81 
82 	PRIMADVANCE(dev_priv);
83 }
84 
mgaEmitContext(drm_mga_private_t * dev_priv)85 static void mgaEmitContext(drm_mga_private_t * dev_priv)
86 {
87 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
88 	unsigned int *regs = sarea_priv->ContextState;
89 	PRIMLOCALS;
90 
91 	/* This takes a max of 20 dwords */
92 	PRIMGETPTR(dev_priv);
93 
94 	PRIMOUTREG(MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG]);
95 	PRIMOUTREG(MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS]);
96 	PRIMOUTREG(MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT]);
97 	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
98 
99 	PRIMOUTREG(MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL]);
100 	PRIMOUTREG(MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR]);
101 	PRIMOUTREG(MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG]);
102 	PRIMOUTREG(MGAREG_ZORG, dev_priv->depthOffset);	/* invarient */
103 
104 	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
105 		PRIMOUTREG(MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG]);
106 		PRIMOUTREG(MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0]);
107 		PRIMOUTREG(MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1]);
108 		PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);
109 
110 		PRIMOUTREG(MGAREG_STENCIL, regs[MGA_CTXREG_STENCIL]);
111 		PRIMOUTREG(MGAREG_STENCILCTL, regs[MGA_CTXREG_STENCILCTL]);
112 		PRIMOUTREG(MGAREG_DMAPAD, 0);
113 		PRIMOUTREG(MGAREG_DMAPAD, 0);
114 	} else {
115 		PRIMOUTREG(MGAREG_FCOL, regs[MGA_CTXREG_FCOL]);
116 		PRIMOUTREG(MGAREG_DMAPAD, 0);
117 		PRIMOUTREG(MGAREG_DMAPAD, 0);
118 		PRIMOUTREG(MGAREG_DMAPAD, 0);
119 	}
120 
121 	PRIMADVANCE(dev_priv);
122 }
123 
mgaG200EmitTex(drm_mga_private_t * dev_priv)124 static void mgaG200EmitTex(drm_mga_private_t * dev_priv)
125 {
126 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
127 	unsigned int *regs = sarea_priv->TexState[0];
128 	PRIMLOCALS;
129 
130 	PRIMGETPTR(dev_priv);
131 
132 	/* This takes 20 dwords */
133 
134 	PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2]);
135 	PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
136 	PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
137 	PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
138 
139 	PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
140 	PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
141 	PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
142 	PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
143 
144 	PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
145 	PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
146 	PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
147 	PRIMOUTREG(MGAREG_WR24, regs[MGA_TEXREG_WIDTH]);
148 
149 	PRIMOUTREG(MGAREG_WR34, regs[MGA_TEXREG_HEIGHT]);
150 	PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
151 	PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
152 	PRIMOUTREG(MGAREG_DMAPAD, 0);
153 
154 	PRIMADVANCE(dev_priv);
155 }
156 
157 #define TMC_dualtex_enable 		0x80
158 
mgaG400EmitTex0(drm_mga_private_t * dev_priv)159 static void mgaG400EmitTex0(drm_mga_private_t * dev_priv)
160 {
161 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
162 	unsigned int *regs = sarea_priv->TexState[0];
163 	PRIMLOCALS;
164 
165 	PRIMGETPTR(dev_priv);
166 
167 	/* This takes 30 dwords */
168 
169 	PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
170 	PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
171 	PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
172 	PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
173 
174 	PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
175 	PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
176 	PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
177 	PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
178 
179 	PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
180 	PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
181 	PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
182 	PRIMOUTREG(MGAREG_WR49, 0);
183 
184 	PRIMOUTREG(MGAREG_WR57, 0);
185 	PRIMOUTREG(MGAREG_WR53, 0);
186 	PRIMOUTREG(MGAREG_WR61, 0);
187 	PRIMOUTREG(MGAREG_WR52, 0x40);
188 
189 	PRIMOUTREG(MGAREG_WR60, 0x40);
190 	PRIMOUTREG(MGAREG_WR54, regs[MGA_TEXREG_WIDTH] | 0x40);
191 	PRIMOUTREG(MGAREG_WR62, regs[MGA_TEXREG_HEIGHT] | 0x40);
192 	PRIMOUTREG(MGAREG_DMAPAD, 0);
193 
194 	PRIMOUTREG(MGAREG_DMAPAD, 0);
195 	PRIMOUTREG(MGAREG_DMAPAD, 0);
196 	PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
197 	PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
198 
199 	PRIMADVANCE(dev_priv);
200 }
201 
202 #define TMC_map1_enable 		0x80000000
203 
mgaG400EmitTex1(drm_mga_private_t * dev_priv)204 static void mgaG400EmitTex1(drm_mga_private_t * dev_priv)
205 {
206 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
207 	unsigned int *regs = sarea_priv->TexState[1];
208 	PRIMLOCALS;
209 
210 	PRIMGETPTR(dev_priv);
211 
212 	/* This takes 25 dwords */
213 
214 	PRIMOUTREG(MGAREG_TEXCTL2,
215 		   regs[MGA_TEXREG_CTL2] | TMC_map1_enable | 0x00008000);
216 	PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
217 	PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER]);
218 	PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL]);
219 
220 	PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG]);
221 	PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1]);
222 	PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2]);
223 	PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3]);
224 
225 	PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
226 	PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
227 	PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
228 	PRIMOUTREG(MGAREG_WR49, 0);
229 
230 	PRIMOUTREG(MGAREG_WR57, 0);
231 	PRIMOUTREG(MGAREG_WR53, 0);
232 	PRIMOUTREG(MGAREG_WR61, 0);
233 	PRIMOUTREG(MGAREG_WR52, regs[MGA_TEXREG_WIDTH] | 0x40);
234 
235 	PRIMOUTREG(MGAREG_WR60, regs[MGA_TEXREG_HEIGHT] | 0x40);
236 	PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
237 	PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
238 	PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
239 
240 	PRIMADVANCE(dev_priv);
241 }
242 
243 #define MAGIC_FPARAM_HEX_VALUE 0x46480000
244 /* This is the hex value of 12800.0f which is a magic value we must
245  * set in wr56.
246  */
247 
mgaG400EmitPipe(drm_mga_private_t * dev_priv)248 static void mgaG400EmitPipe(drm_mga_private_t * dev_priv)
249 {
250 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
251 	unsigned int pipe = sarea_priv->WarpPipe;
252 	PRIMLOCALS;
253 
254 	PRIMGETPTR(dev_priv);
255 
256 	/* This takes 50 dwords */
257 
258 	/* Establish vertex size.
259 	 */
260 	PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
261 	PRIMOUTREG(MGAREG_DMAPAD, 0);
262 	PRIMOUTREG(MGAREG_DMAPAD, 0);
263 	PRIMOUTREG(MGAREG_DMAPAD, 0);
264 
265 	if (pipe & MGA_T2) {
266 		PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
267 		PRIMOUTREG(MGAREG_DMAPAD, 0);
268 		PRIMOUTREG(MGAREG_DMAPAD, 0);
269 		PRIMOUTREG(MGAREG_DMAPAD, 0);
270 
271 		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
272 		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
273 		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
274 		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
275 	} else {
276 		if (dev_priv->WarpPipe & MGA_T2) {
277 			/* Flush the WARP pipe */
278 			PRIMOUTREG(MGAREG_YDST, 0);
279 			PRIMOUTREG(MGAREG_FXLEFT, 0);
280 			PRIMOUTREG(MGAREG_FXRIGHT, 1);
281 			PRIMOUTREG(MGAREG_DWGCTL, MGA_FLUSH_CMD);
282 
283 			PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 1);
284 			PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
285 			PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
286 			PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
287 
288 			PRIMOUTREG(MGAREG_TEXCTL2, 0x80 | 0x00008000);
289 			PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
290 			PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
291 			PRIMOUTREG(MGAREG_DMAPAD, 0);
292 		}
293 
294 		PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807);
295 		PRIMOUTREG(MGAREG_DMAPAD, 0);
296 		PRIMOUTREG(MGAREG_DMAPAD, 0);
297 		PRIMOUTREG(MGAREG_DMAPAD, 0);
298 
299 		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
300 		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
301 		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
302 		PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
303 	}
304 
305 	PRIMOUTREG(MGAREG_WFLAG, 0);
306 	PRIMOUTREG(MGAREG_WFLAG1, 0);
307 	PRIMOUTREG(MGAREG_WR56, MAGIC_FPARAM_HEX_VALUE);
308 	PRIMOUTREG(MGAREG_DMAPAD, 0);
309 
310 	PRIMOUTREG(MGAREG_WR49, 0);	/* Tex stage 0 */
311 	PRIMOUTREG(MGAREG_WR57, 0);	/* Tex stage 0 */
312 	PRIMOUTREG(MGAREG_WR53, 0);	/* Tex stage 1 */
313 	PRIMOUTREG(MGAREG_WR61, 0);	/* Tex stage 1 */
314 
315 	PRIMOUTREG(MGAREG_WR54, 0x40);	/* Tex stage 0 : w */
316 	PRIMOUTREG(MGAREG_WR62, 0x40);	/* Tex stage 0 : h */
317 	PRIMOUTREG(MGAREG_WR52, 0x40);	/* Tex stage 1 : w */
318 	PRIMOUTREG(MGAREG_WR60, 0x40);	/* Tex stage 1 : h */
319 
320 	/* Dma pading required due to hw bug */
321 	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
322 	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
323 	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
324 	PRIMOUTREG(MGAREG_WIADDR2,
325 		   (u32) (dev_priv->WarpIndex[pipe].
326 			  phys_addr | WIA_wmode_start | WIA_wagp_agp));
327 	PRIMADVANCE(dev_priv);
328 }
329 
mgaG200EmitPipe(drm_mga_private_t * dev_priv)330 static void mgaG200EmitPipe(drm_mga_private_t * dev_priv)
331 {
332 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
333 	unsigned int pipe = sarea_priv->WarpPipe;
334 	PRIMLOCALS;
335 
336 	PRIMGETPTR(dev_priv);
337 
338 	/* This takes 15 dwords */
339 
340 	PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
341 	PRIMOUTREG(MGAREG_WVRTXSZ, 7);
342 	PRIMOUTREG(MGAREG_WFLAG, 0);
343 	PRIMOUTREG(MGAREG_WR24, 0);	/* tex w/h */
344 
345 	PRIMOUTREG(MGAREG_WR25, 0x100);
346 	PRIMOUTREG(MGAREG_WR34, 0);	/* tex w/h */
347 	PRIMOUTREG(MGAREG_WR42, 0xFFFF);
348 	PRIMOUTREG(MGAREG_WR60, 0xFFFF);
349 
350 	/* Dma pading required due to hw bug */
351 	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
352 	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
353 	PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
354 	PRIMOUTREG(MGAREG_WIADDR,
355 		   (u32) (dev_priv->WarpIndex[pipe].
356 			  phys_addr | WIA_wmode_start | WIA_wagp_agp));
357 
358 	PRIMADVANCE( dev_priv );
359 }
360 
mgaEmitState(drm_mga_private_t * dev_priv)361 static void mgaEmitState(drm_mga_private_t * dev_priv)
362 {
363 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
364 	unsigned int dirty = sarea_priv->dirty;
365 
366 	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
367 		int multitex = sarea_priv->WarpPipe & MGA_T2;
368 
369 		if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
370 			mgaG400EmitPipe(dev_priv);
371 			dev_priv->WarpPipe = sarea_priv->WarpPipe;
372 		}
373 
374 		if (dirty & MGA_UPLOAD_CTX) {
375 			mgaEmitContext(dev_priv);
376 			sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
377 		}
378 
379 		if (dirty & MGA_UPLOAD_TEX0) {
380 			mgaG400EmitTex0(dev_priv);
381 			sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
382 		}
383 
384 		if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
385 			mgaG400EmitTex1(dev_priv);
386 			sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
387 		}
388 	} else {
389 		if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
390 			mgaG200EmitPipe(dev_priv);
391 			dev_priv->WarpPipe = sarea_priv->WarpPipe;
392 		}
393 
394 		if (dirty & MGA_UPLOAD_CTX) {
395 			mgaEmitContext(dev_priv);
396 			sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
397 		}
398 
399 		if (dirty & MGA_UPLOAD_TEX0) {
400 			mgaG200EmitTex(dev_priv);
401 			sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
402 		}
403 	}
404 }
405 
406 /* Disallow all write destinations except the front and backbuffer.
407  */
mgaVerifyContext(drm_mga_private_t * dev_priv)408 static int mgaVerifyContext(drm_mga_private_t * dev_priv)
409 {
410 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
411 	unsigned int *regs = sarea_priv->ContextState;
412 
413 	if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
414 	    regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
415 		DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n",
416 			  regs[MGA_CTXREG_DSTORG], dev_priv->frontOffset,
417 			  dev_priv->backOffset);
418 		regs[MGA_CTXREG_DSTORG] = 0;
419 		return -1;
420 	}
421 
422 	return 0;
423 }
424 
425 /* Disallow texture reads from PCI space.
426  */
mgaVerifyTex(drm_mga_private_t * dev_priv,int unit)427 static int mgaVerifyTex(drm_mga_private_t * dev_priv, int unit)
428 {
429 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
430 
431 	if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
432 		DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n",
433 			  sarea_priv->TexState[unit][MGA_TEXREG_ORG],
434 			  unit);
435 		sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
436 		return -1;
437 	}
438 
439 	return 0;
440 }
441 
mgaVerifyState(drm_mga_private_t * dev_priv)442 static int mgaVerifyState(drm_mga_private_t * dev_priv)
443 {
444 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
445 	unsigned int dirty = sarea_priv->dirty;
446 	int rv = 0;
447 
448 	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
449 		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
450 
451 	if (dirty & MGA_UPLOAD_CTX)
452 		rv |= mgaVerifyContext(dev_priv);
453 
454 	if (dirty & MGA_UPLOAD_TEX0)
455 		rv |= mgaVerifyTex(dev_priv, 0);
456 
457 	if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
458 		if (dirty & MGA_UPLOAD_TEX1)
459 			rv |= mgaVerifyTex(dev_priv, 1);
460 
461 		if (dirty & MGA_UPLOAD_PIPE)
462 			rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES);
463 	} else {
464 		if (dirty & MGA_UPLOAD_PIPE)
465 			rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES);
466 	}
467 
468 	return rv == 0;
469 }
470 
mgaVerifyIload(drm_mga_private_t * dev_priv,unsigned long bus_address,unsigned int dstOrg,int length)471 static int mgaVerifyIload(drm_mga_private_t * dev_priv,
472 			  unsigned long bus_address,
473 			  unsigned int dstOrg, int length)
474 {
475 	if (dstOrg < dev_priv->textureOffset ||
476 	    dstOrg + length >
477 	    (dev_priv->textureOffset + dev_priv->textureSize)) {
478 		return -EINVAL;
479 	}
480 	if (length % 64) {
481 		return -EINVAL;
482 	}
483 	return 0;
484 }
485 
486 /* This copies a 64 byte aligned agp region to the frambuffer
487  * with a standard blit, the ioctl needs to do checking */
488 
mga_dma_dispatch_tex_blit(drm_device_t * dev,unsigned long bus_address,int length,unsigned int destOrg)489 static void mga_dma_dispatch_tex_blit(drm_device_t * dev,
490 				      unsigned long bus_address,
491 				      int length, unsigned int destOrg)
492 {
493 	drm_mga_private_t *dev_priv = dev->dev_private;
494 	int use_agp = PDEA_pagpxfer_enable | 0x00000001;
495 	u16 y2;
496 	PRIMLOCALS;
497 
498 	y2 = length / 64;
499 
500 	PRIM_OVERFLOW(dev, dev_priv, 30);
501 
502 	PRIMOUTREG(MGAREG_DSTORG, destOrg);
503 	PRIMOUTREG(MGAREG_MACCESS, 0x00000000);
504 	PRIMOUTREG(MGAREG_SRCORG, (u32) bus_address | use_agp);
505 	PRIMOUTREG(MGAREG_AR5, 64);
506 
507 	PRIMOUTREG(MGAREG_PITCH, 64);
508 	PRIMOUTREG(MGAREG_DMAPAD, 0);
509 	PRIMOUTREG(MGAREG_DMAPAD, 0);
510 	PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
511 
512 	PRIMOUTREG(MGAREG_AR0, 63);
513 	PRIMOUTREG(MGAREG_AR3, 0);
514 	PRIMOUTREG(MGAREG_FXBNDRY, (63 << 16));
515 	PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC, y2);
516 
517 	PRIMOUTREG(MGAREG_DMAPAD, 0);
518 	PRIMOUTREG(MGAREG_SRCORG, 0);
519 	PRIMOUTREG(MGAREG_PITCH, dev_priv->stride / dev_priv->cpp);
520 	PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
521 	PRIMADVANCE(dev_priv);
522 }
523 
mga_dma_dispatch_vertex(drm_device_t * dev,drm_buf_t * buf)524 static void mga_dma_dispatch_vertex(drm_device_t * dev, drm_buf_t * buf)
525 {
526 	drm_mga_private_t *dev_priv = dev->dev_private;
527 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
528 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
529 	unsigned long address = (unsigned long) buf->bus_address;
530 	int length = buf->used;
531 	int use_agp = PDEA_pagpxfer_enable;
532 	int i = 0;
533 	PRIMLOCALS;
534 
535 	if (buf->used) {
536 		/* WARNING: if you change any of the state functions verify
537 		 * these numbers (Overestimating this doesn't hurt).
538 		 */
539 		buf_priv->dispatched = 1;
540 		PRIM_OVERFLOW(dev, dev_priv,
541 			      (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
542 		mgaEmitState(dev_priv);
543 
544 #if 0
545 		length = dev_priv->vertexsize * 3 * 4;
546 #endif
547 
548 		do {
549 			if (i < sarea_priv->nbox) {
550 				mgaEmitClipRect(dev_priv,
551 						&sarea_priv->boxes[i]);
552 			}
553 
554 			PRIMGETPTR(dev_priv);
555 			PRIMOUTREG(MGAREG_DMAPAD, 0);
556 			PRIMOUTREG(MGAREG_DMAPAD, 0);
557 			PRIMOUTREG(MGAREG_SECADDRESS,
558 				   ((u32) address) | TT_VERTEX);
559 			PRIMOUTREG(MGAREG_SECEND,
560 				   (((u32) (address + length)) | use_agp));
561 			PRIMADVANCE(dev_priv);
562 		} while (++i < sarea_priv->nbox);
563 	}
564 	if (buf_priv->discard) {
565 		if (buf_priv->dispatched == 1)
566 			AGEBUF(dev_priv, buf_priv);
567 		buf_priv->dispatched = 0;
568 		mga_freelist_put(dev, buf);
569 	}
570 
571 
572 }
573 
574 
mga_dma_dispatch_indices(drm_device_t * dev,drm_buf_t * buf,unsigned int start,unsigned int end)575 static void mga_dma_dispatch_indices(drm_device_t * dev,
576 				     drm_buf_t * buf,
577 				     unsigned int start, unsigned int end)
578 {
579 	drm_mga_private_t *dev_priv = dev->dev_private;
580 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
581 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
582 	unsigned int address = (unsigned int) buf->bus_address;
583 	int use_agp = PDEA_pagpxfer_enable;
584 	int i = 0;
585 	PRIMLOCALS;
586 
587 	if (start != end) {
588 		/* WARNING: if you change any of the state functions verify
589 		 * these numbers (Overestimating this doesn't hurt).
590 		 */
591 		buf_priv->dispatched = 1;
592 		PRIM_OVERFLOW(dev, dev_priv,
593 			      (MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
594 		mgaEmitState(dev_priv);
595 
596 		do {
597 			if (i < sarea_priv->nbox) {
598 				mgaEmitClipRect(dev_priv,
599 						&sarea_priv->boxes[i]);
600 			}
601 
602 			PRIMGETPTR(dev_priv);
603 			PRIMOUTREG(MGAREG_DMAPAD, 0);
604 			PRIMOUTREG(MGAREG_DMAPAD, 0);
605 			PRIMOUTREG(MGAREG_SETUPADDRESS,
606 				   ((address + start) |
607 				    SETADD_mode_vertlist));
608 			PRIMOUTREG(MGAREG_SETUPEND,
609 				   ((address + end) | use_agp));
610 /*  				   ((address + start + 12) | use_agp)); */
611 			PRIMADVANCE(dev_priv);
612 		} while (++i < sarea_priv->nbox);
613 	}
614 	if (buf_priv->discard) {
615 		if (buf_priv->dispatched == 1)
616 			AGEBUF(dev_priv, buf_priv);
617 		buf_priv->dispatched = 0;
618 		mga_freelist_put(dev, buf);
619 	}
620 }
621 
622 
mga_dma_dispatch_clear(drm_device_t * dev,int flags,unsigned int clear_color,unsigned int clear_zval,unsigned int clear_colormask,unsigned int clear_depthmask)623 static void mga_dma_dispatch_clear(drm_device_t * dev, int flags,
624 				   unsigned int clear_color,
625 				   unsigned int clear_zval,
626 				   unsigned int clear_colormask,
627 				   unsigned int clear_depthmask)
628 {
629 	drm_mga_private_t *dev_priv = dev->dev_private;
630 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
631 	unsigned int *regs = sarea_priv->ContextState;
632 	int nbox = sarea_priv->nbox;
633 	drm_clip_rect_t *pbox = sarea_priv->boxes;
634 	unsigned int cmd;
635 	int i;
636 	PRIMLOCALS;
637 
638 	if (dev_priv->sgram)
639 		cmd = MGA_CLEAR_CMD | DC_atype_blk;
640 	else
641 		cmd = MGA_CLEAR_CMD | DC_atype_rstr;
642 
643 	PRIM_OVERFLOW(dev, dev_priv, 35 * MGA_NR_SAREA_CLIPRECTS);
644 
645 	for (i = 0; i < nbox; i++) {
646 		unsigned int height = pbox[i].y2 - pbox[i].y1;
647 
648 		if (flags & MGA_FRONT) {
649 			PRIMOUTREG(MGAREG_DMAPAD, 0);
650 			PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
651 			PRIMOUTREG(MGAREG_YDSTLEN,
652 				   (pbox[i].y1 << 16) | height);
653 			PRIMOUTREG(MGAREG_FXBNDRY,
654 				   (pbox[i].x2 << 16) | pbox[i].x1);
655 
656 			PRIMOUTREG(MGAREG_DMAPAD, 0);
657 			PRIMOUTREG(MGAREG_FCOL, clear_color);
658 			PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
659 			PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
660 		}
661 
662 		if (flags & MGA_BACK) {
663 			PRIMOUTREG(MGAREG_DMAPAD, 0);
664 			PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
665 			PRIMOUTREG(MGAREG_YDSTLEN,
666 				   (pbox[i].y1 << 16) | height);
667 			PRIMOUTREG(MGAREG_FXBNDRY,
668 				   (pbox[i].x2 << 16) | pbox[i].x1);
669 
670 			PRIMOUTREG(MGAREG_DMAPAD, 0);
671 			PRIMOUTREG(MGAREG_FCOL, clear_color);
672 			PRIMOUTREG(MGAREG_DSTORG, dev_priv->backOffset);
673 			PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
674 		}
675 
676 		if (flags & MGA_DEPTH) {
677 			PRIMOUTREG(MGAREG_DMAPAD, 0);
678 			PRIMOUTREG(MGAREG_PLNWT, clear_depthmask);
679 			PRIMOUTREG(MGAREG_YDSTLEN,
680 				   (pbox[i].y1 << 16) | height);
681 			PRIMOUTREG(MGAREG_FXBNDRY,
682 				   (pbox[i].x2 << 16) | pbox[i].x1);
683 
684 			PRIMOUTREG(MGAREG_DMAPAD, 0);
685 			PRIMOUTREG(MGAREG_FCOL, clear_zval);
686 			PRIMOUTREG(MGAREG_DSTORG, dev_priv->depthOffset);
687 			PRIMOUTREG(MGAREG_DWGCTL + MGAREG_MGA_EXEC, cmd);
688 		}
689 	}
690 
691 	/* Force reset of DWGCTL */
692 	PRIMOUTREG(MGAREG_DMAPAD, 0);
693 	PRIMOUTREG(MGAREG_DMAPAD, 0);
694 	PRIMOUTREG(MGAREG_DMAPAD, 0);
695 	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
696 	PRIMADVANCE(dev_priv);
697 }
698 
mga_dma_dispatch_swap(drm_device_t * dev)699 static void mga_dma_dispatch_swap(drm_device_t * dev)
700 {
701 	drm_mga_private_t *dev_priv = dev->dev_private;
702 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
703 	unsigned int *regs = sarea_priv->ContextState;
704 	int nbox = sarea_priv->nbox;
705 	drm_clip_rect_t *pbox = sarea_priv->boxes;
706 	int i;
707 	int pixel_stride = dev_priv->stride / dev_priv->cpp;
708 
709 	PRIMLOCALS;
710 
711 	PRIM_OVERFLOW(dev, dev_priv, (MGA_NR_SAREA_CLIPRECTS * 5) + 20);
712 
713 	PRIMOUTREG(MGAREG_DMAPAD, 0);
714 	PRIMOUTREG(MGAREG_DMAPAD, 0);
715 	PRIMOUTREG(MGAREG_DWGSYNC, 0x7100);
716 	PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
717 
718 	PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
719 	PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
720 	PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
721 	PRIMOUTREG(MGAREG_AR5, pixel_stride);
722 
723 	PRIMOUTREG(MGAREG_DMAPAD, 0);
724 	PRIMOUTREG(MGAREG_DMAPAD, 0);
725 	PRIMOUTREG(MGAREG_DMAPAD, 0);
726 	PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD);
727 
728 	for (i = 0; i < nbox; i++) {
729 		unsigned int h = pbox[i].y2 - pbox[i].y1;
730 		unsigned int start = pbox[i].y1 * pixel_stride;
731 
732 		PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
733 		PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1);
734 		PRIMOUTREG(MGAREG_FXBNDRY,
735 			   pbox[i].x1 | ((pbox[i].x2 - 1) << 16));
736 		PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC,
737 			   (pbox[i].y1 << 16) | h);
738 	}
739 
740 	/* Force reset of DWGCTL */
741 	PRIMOUTREG(MGAREG_DMAPAD, 0);
742 	PRIMOUTREG(MGAREG_DMAPAD, 0);
743 	PRIMOUTREG(MGAREG_SRCORG, 0);
744 	PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
745 
746 	PRIMADVANCE(dev_priv);
747 }
748 
mga_clear_bufs(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)749 int mga_clear_bufs(struct inode *inode, struct file *filp,
750 		   unsigned int cmd, unsigned long arg)
751 {
752 	drm_file_t *priv = filp->private_data;
753 	drm_device_t *dev = priv->dev;
754 	drm_mga_private_t *dev_priv =
755 	    (drm_mga_private_t *) dev->dev_private;
756 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
757 	drm_mga_clear_t clear;
758 
759 	if (copy_from_user(&clear, (drm_mga_clear_t *) arg, sizeof(clear)))
760 		return -EFAULT;
761 
762 	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
763 		DRM_ERROR("mga_clear_bufs called without lock held\n");
764 		return -EINVAL;
765 	}
766 
767 	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
768 		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
769 
770 	/* Make sure we restore the 3D state next time.
771 	 */
772 	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
773 	mga_dma_dispatch_clear(dev, clear.flags,
774 			       clear.clear_color,
775 			       clear.clear_depth,
776 			       clear.clear_color_mask,
777 			       clear.clear_depth_mask);
778 	PRIMUPDATE(dev_priv);
779 	mga_flush_write_combine();
780 	mga_dma_schedule(dev, 1);
781 	return 0;
782 }
783 
mga_swap_bufs(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)784 int mga_swap_bufs(struct inode *inode, struct file *filp,
785 		  unsigned int cmd, unsigned long arg)
786 {
787 	drm_file_t *priv = filp->private_data;
788 	drm_device_t *dev = priv->dev;
789 	drm_mga_private_t *dev_priv =
790 	    (drm_mga_private_t *) dev->dev_private;
791 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
792 
793 	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
794 		DRM_ERROR("mga_swap_bufs called without lock held\n");
795 		return -EINVAL;
796 	}
797 
798 	if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
799 		sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
800 
801 	/* Make sure we restore the 3D state next time.
802 	 */
803 	dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
804 	mga_dma_dispatch_swap(dev);
805 	PRIMUPDATE(dev_priv);
806 	set_bit(MGA_BUF_SWAP_PENDING,
807 		&dev_priv->current_prim->buffer_status);
808 	mga_flush_write_combine();
809 	mga_dma_schedule(dev, 1);
810 	return 0;
811 }
812 
mga_iload(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)813 int mga_iload(struct inode *inode, struct file *filp,
814 	      unsigned int cmd, unsigned long arg)
815 {
816 	drm_file_t *priv = filp->private_data;
817 	drm_device_t *dev = priv->dev;
818 	drm_device_dma_t *dma = dev->dma;
819 	drm_mga_private_t *dev_priv =
820 	    (drm_mga_private_t *) dev->dev_private;
821 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
822 	drm_buf_t *buf;
823 	drm_mga_buf_priv_t *buf_priv;
824 	drm_mga_iload_t iload;
825 	unsigned long bus_address;
826 
827 	if (copy_from_user(&iload, (drm_mga_iload_t *) arg, sizeof(iload)))
828 		return -EFAULT;
829 
830 	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
831 		DRM_ERROR("mga_iload called without lock held\n");
832 		return -EINVAL;
833 	}
834 
835 	if(iload.idx < 0 || iload.idx > dma->buf_count) return -EINVAL;
836 	buf = dma->buflist[iload.idx];
837 	buf_priv = buf->dev_private;
838 	bus_address = buf->bus_address;
839 
840 	if (mgaVerifyIload(dev_priv,
841 			   bus_address, iload.destOrg, iload.length)) {
842 		mga_freelist_put(dev, buf);
843 		return -EINVAL;
844 	}
845 
846 	sarea_priv->dirty |= MGA_UPLOAD_CTX;
847 
848 	mga_dma_dispatch_tex_blit(dev, bus_address, iload.length,
849 				  iload.destOrg);
850 	AGEBUF(dev_priv, buf_priv);
851 	buf_priv->discard = 1;
852 	mga_freelist_put(dev, buf);
853 	mga_flush_write_combine();
854 	mga_dma_schedule(dev, 1);
855 	return 0;
856 }
857 
mga_vertex(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)858 int mga_vertex(struct inode *inode, struct file *filp,
859 	       unsigned int cmd, unsigned long arg)
860 {
861 	drm_file_t *priv = filp->private_data;
862 	drm_device_t *dev = priv->dev;
863 	drm_mga_private_t *dev_priv =
864 	    (drm_mga_private_t *) dev->dev_private;
865 	drm_device_dma_t *dma = dev->dma;
866 	drm_buf_t *buf;
867 	drm_mga_buf_priv_t *buf_priv;
868 	drm_mga_vertex_t vertex;
869 
870 	if (copy_from_user(&vertex, (drm_mga_vertex_t *) arg, sizeof(vertex)))
871 		return -EFAULT;
872 
873 	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
874 		DRM_ERROR("mga_vertex called without lock held\n");
875 		return -EINVAL;
876 	}
877 
878 	if(vertex.idx < 0 || vertex.idx > dma->buf_count) return -EINVAL;
879 
880 	buf = dma->buflist[vertex.idx];
881 	buf_priv = buf->dev_private;
882 
883 	buf->used = vertex.used;
884 	buf_priv->discard = vertex.discard;
885 
886 	if (!mgaVerifyState(dev_priv)) {
887 		if (vertex.discard) {
888 			if (buf_priv->dispatched == 1)
889 				AGEBUF(dev_priv, buf_priv);
890 			buf_priv->dispatched = 0;
891 			mga_freelist_put(dev, buf);
892 		}
893 		return -EINVAL;
894 	}
895 
896 	mga_dma_dispatch_vertex(dev, buf);
897 
898 	PRIMUPDATE(dev_priv);
899 	mga_flush_write_combine();
900 	mga_dma_schedule(dev, 1);
901 	return 0;
902 }
903 
904 
mga_indices(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)905 int mga_indices(struct inode *inode, struct file *filp,
906 		unsigned int cmd, unsigned long arg)
907 {
908 	drm_file_t *priv = filp->private_data;
909 	drm_device_t *dev = priv->dev;
910 	drm_mga_private_t *dev_priv =
911 	    (drm_mga_private_t *) dev->dev_private;
912 	drm_device_dma_t *dma = dev->dma;
913 	drm_buf_t *buf;
914 	drm_mga_buf_priv_t *buf_priv;
915 	drm_mga_indices_t indices;
916 
917 	if (copy_from_user(&indices,
918 			   (drm_mga_indices_t *)arg, sizeof(indices)))
919 		return -EFAULT;
920 
921 	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
922 		DRM_ERROR("mga_indices called without lock held\n");
923 		return -EINVAL;
924 	}
925 
926 	if(indices.idx < 0 || indices.idx > dma->buf_count) return -EINVAL;
927 	buf = dma->buflist[indices.idx];
928 	buf_priv = buf->dev_private;
929 
930 	buf_priv->discard = indices.discard;
931 
932 	if (!mgaVerifyState(dev_priv)) {
933 		if (indices.discard) {
934 			if (buf_priv->dispatched == 1)
935 				AGEBUF(dev_priv, buf_priv);
936 			buf_priv->dispatched = 0;
937 			mga_freelist_put(dev, buf);
938 		}
939 		return -EINVAL;
940 	}
941 
942 	mga_dma_dispatch_indices(dev, buf, indices.start, indices.end);
943 
944 	PRIMUPDATE(dev_priv);
945 	mga_flush_write_combine();
946 	mga_dma_schedule(dev, 1);
947 	return 0;
948 }
949 
950 
951 
mga_dma_get_buffers(drm_device_t * dev,drm_dma_t * d)952 static int mga_dma_get_buffers(drm_device_t * dev, drm_dma_t * d)
953 {
954 	int i;
955 	drm_buf_t *buf;
956 
957 	for (i = d->granted_count; i < d->request_count; i++) {
958 		buf = mga_freelist_get(dev);
959 		if (!buf)
960 			break;
961 		buf->pid = current->pid;
962 		if (copy_to_user(&d->request_indices[i],
963 				 &buf->idx, sizeof(buf->idx)))
964 			return -EFAULT;
965 		if (copy_to_user(&d->request_sizes[i],
966 				 &buf->total, sizeof(buf->total)))
967 			return -EFAULT;
968 		++d->granted_count;
969 	}
970 	return 0;
971 }
972 
mga_dma(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long arg)973 int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
974 	    unsigned long arg)
975 {
976 	drm_file_t *priv = filp->private_data;
977 	drm_device_t *dev = priv->dev;
978 	drm_device_dma_t *dma = dev->dma;
979 	int retcode = 0;
980 	drm_dma_t d;
981 
982 	if (copy_from_user(&d, (drm_dma_t *) arg, sizeof(d)))
983 		return -EFAULT;
984 
985 	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
986 		DRM_ERROR("mga_dma called without lock held\n");
987 		return -EINVAL;
988 	}
989 
990 	/* Please don't send us buffers.
991 	 */
992 	if (d.send_count != 0) {
993 		DRM_ERROR
994 		    ("Process %d trying to send %d buffers via drmDMA\n",
995 		     current->pid, d.send_count);
996 		return -EINVAL;
997 	}
998 
999 	/* We'll send you buffers.
1000 	 */
1001 	if (d.request_count < 0 || d.request_count > dma->buf_count) {
1002 		DRM_ERROR
1003 		    ("Process %d trying to get %d buffers (of %d max)\n",
1004 		     current->pid, d.request_count, dma->buf_count);
1005 		return -EINVAL;
1006 	}
1007 
1008 	d.granted_count = 0;
1009 
1010 	if (d.request_count) {
1011 		retcode = mga_dma_get_buffers(dev, &d);
1012 	}
1013 
1014 	if (copy_to_user((drm_dma_t *) arg, &d, sizeof(d)))
1015 		return -EFAULT;
1016 	return retcode;
1017 }
1018