File: /usr/src/linux/drivers/char/drm/mga_state.c

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