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