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