Merged mga branch with trunk
[platform/upstream/libdrm.git] / linux / 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  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  * 
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  *
26  * Authors: Jeff Hartmann <jhartmann@precisioninsight.com>
27  *          Keith Whitwell <keithw@precisioninsight.com>
28  *
29  * $XFree86$
30  *
31  */
32  
33 #define __NO_VERSION__
34 #include "drmP.h"
35 #include "mga_drv.h"
36 #include "drm.h"
37
38 static void mgaEmitClipRect( drm_mga_private_t *dev_priv, 
39                              drm_clip_rect_t *box )
40 {
41         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
42         unsigned int *regs = sarea_priv->ContextState;
43         PRIMLOCALS;
44
45         /* This takes 10 dwords */
46         PRIMGETPTR( dev_priv );
47    
48         /* Force reset of dwgctl (eliminates clip disable) */
49         PRIMOUTREG( MGAREG_DMAPAD, 0 );
50         PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 );
51         PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag - 1 );
52         PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
53
54         PRIMOUTREG( MGAREG_DMAPAD, 0 );
55         PRIMOUTREG( MGAREG_CXBNDRY, ((box->x2)<<16)|(box->x1) );
56         PRIMOUTREG( MGAREG_YTOP, box->y1 * dev_priv->stride/2 );
57         PRIMOUTREG( MGAREG_YBOT, box->y2 * dev_priv->stride/2 );
58
59         PRIMADVANCE( dev_priv );
60 }
61
62 static void mgaEmitContext(drm_mga_private_t *dev_priv )
63 {
64         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
65         unsigned int *regs = sarea_priv->ContextState;
66         PRIMLOCALS;
67         
68         /* This takes a max of 15 dwords */
69         PRIMGETPTR( dev_priv );
70
71         PRIMOUTREG( MGAREG_DSTORG, regs[MGA_CTXREG_DSTORG] );
72         PRIMOUTREG( MGAREG_MACCESS, regs[MGA_CTXREG_MACCESS] );
73         PRIMOUTREG( MGAREG_PLNWT, regs[MGA_CTXREG_PLNWT] );
74         PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
75
76         PRIMOUTREG( MGAREG_ALPHACTRL, regs[MGA_CTXREG_ALPHACTRL] );
77         PRIMOUTREG( MGAREG_FOGCOL, regs[MGA_CTXREG_FOGCOLOR] );
78         PRIMOUTREG( MGAREG_WFLAG, regs[MGA_CTXREG_WFLAG] );
79         PRIMOUTREG( MGAREG_ZORG, dev_priv->depthOffset ); /* invarient */
80
81         if (dev_priv->chipset == MGA_CARD_TYPE_G400) { 
82                 PRIMOUTREG( MGAREG_WFLAG1, regs[MGA_CTXREG_WFLAG] );
83                 PRIMOUTREG( MGAREG_TDUALSTAGE0, regs[MGA_CTXREG_TDUAL0] );
84                 PRIMOUTREG( MGAREG_TDUALSTAGE1, regs[MGA_CTXREG_TDUAL1] );      
85                 PRIMOUTREG( MGAREG_FCOL, regs[MGA_CTXREG_FCOL] );
86         } else {
87                 PRIMOUTREG( MGAREG_FCOL, regs[MGA_CTXREG_FCOL] );
88                 PRIMOUTREG( MGAREG_DMAPAD, 0);
89                 PRIMOUTREG( MGAREG_DMAPAD, 0);
90                 PRIMOUTREG( MGAREG_DMAPAD, 0);
91         }
92    
93         PRIMADVANCE( dev_priv );
94 }
95
96 static void mgaG200EmitTex( drm_mga_private_t *dev_priv )
97 {
98         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
99         unsigned int *regs = sarea_priv->TexState[0];
100         PRIMLOCALS;
101
102         PRIMGETPTR( dev_priv );
103    
104         /* This takes 20 dwords */
105
106         PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
107         PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
108         PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
109         PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
110
111         PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
112         PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
113         PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
114         PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
115
116         PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );             
117         PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
118         PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );   
119         PRIMOUTREG(0x2d00 + 24*4, regs[MGA_TEXREG_WIDTH] );
120
121         PRIMOUTREG(0x2d00 + 34*4, regs[MGA_TEXREG_HEIGHT] );
122         PRIMOUTREG( MGAREG_TEXTRANS, 0xffff );
123         PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
124         PRIMOUTREG( MGAREG_DMAPAD, 0 );
125
126         PRIMADVANCE( dev_priv );  
127 }
128
129 static void mgaG400EmitTex0( drm_mga_private_t *dev_priv )
130 {
131         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
132         unsigned int *regs = sarea_priv->TexState[0];
133         int multitex = sarea_priv->WarpPipe & MGA_T2;
134         PRIMLOCALS;
135    
136         PRIMGETPTR( dev_priv );
137    
138         /* This takes a max of 30 dwords */
139
140         PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
141         PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
142         PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
143         PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
144
145         PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
146         PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
147         PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
148         PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
149
150         PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );             
151         PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
152         PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );   
153         PRIMOUTREG(0x2d00 + 49*4, 0);
154
155         PRIMOUTREG(0x2d00 + 57*4, 0);
156         PRIMOUTREG(0x2d00 + 53*4, 0);
157         PRIMOUTREG(0x2d00 + 61*4, 0);
158         PRIMOUTREG( MGAREG_DMAPAD, 0 );
159
160         if (!multitex) {
161                 PRIMOUTREG(0x2d00 + 52*4, 0x40 ); 
162                 PRIMOUTREG(0x2d00 + 60*4, 0x40 );
163                 PRIMOUTREG( MGAREG_DMAPAD, 0 );
164                 PRIMOUTREG( MGAREG_DMAPAD, 0 );
165         } 
166
167         PRIMOUTREG( 0x2d00 + 54*4, regs[MGA_TEXREG_WIDTH] | 0x40 );
168         PRIMOUTREG( 0x2d00 + 62*4, regs[MGA_TEXREG_HEIGHT] | 0x40 );
169         PRIMOUTREG( MGAREG_TEXTRANS, 0xffff );
170         PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
171
172         PRIMADVANCE( dev_priv );  
173 }
174
175 #define TMC_map1_enable                 0x80000000      
176
177 static void mgaG400EmitTex1( drm_mga_private_t *dev_priv )
178 {
179         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
180         unsigned int *regs = sarea_priv->TexState[1];
181         PRIMLOCALS;
182    
183         PRIMGETPTR(dev_priv);
184
185         /* This takes 25 dwords */
186         PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | TMC_map1_enable);
187         PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL] );
188         PRIMOUTREG(MGAREG_TEXFILTER, regs[MGA_TEXREG_FILTER] );
189         PRIMOUTREG(MGAREG_TEXBORDERCOL, regs[MGA_TEXREG_BORDERCOL] );
190
191         PRIMOUTREG(MGAREG_TEXORG, regs[MGA_TEXREG_ORG] );
192         PRIMOUTREG(MGAREG_TEXORG1, regs[MGA_TEXREG_ORG1] );
193         PRIMOUTREG(MGAREG_TEXORG2, regs[MGA_TEXREG_ORG2] );
194         PRIMOUTREG(MGAREG_TEXORG3, regs[MGA_TEXREG_ORG3] );
195
196         PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4] );             
197         PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH] );
198         PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT] );   
199         PRIMOUTREG(0x2d00 + 49*4, 0);
200
201         PRIMOUTREG(0x2d00 + 57*4, 0);
202         PRIMOUTREG(0x2d00 + 53*4, 0);
203         PRIMOUTREG(0x2d00 + 61*4, 0);
204         PRIMOUTREG(0x2d00 + 52*4, regs[MGA_TEXREG_WIDTH] | 0x40 ); 
205
206         PRIMOUTREG(0x2d00 + 60*4, regs[MGA_TEXREG_HEIGHT] | 0x40 );
207         PRIMOUTREG( MGAREG_TEXTRANS, 0xffff );
208         PRIMOUTREG( MGAREG_TEXTRANSHIGH, 0xffff );
209         PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] );
210
211         PRIMADVANCE( dev_priv );
212 }
213
214 static void mgaG400EmitPipe(drm_mga_private_t *dev_priv )
215 {
216         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
217         unsigned int pipe = sarea_priv->WarpPipe;
218         float fParam = 12800.0f;
219         PRIMLOCALS;
220    
221         PRIMGETPTR(dev_priv);
222
223         /* This takes 25 dwords */
224    
225         /* Establish vertex size.  
226          */
227         if (pipe & MGA_T2) {
228                 PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
229                 PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
230                 PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
231                 PRIMOUTREG(MGAREG_WFLAG, 0);
232         } else {
233                 PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
234                 PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807);
235                 PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x18000000);
236                 PRIMOUTREG(MGAREG_WFLAG, 0);
237         }   
238
239         PRIMOUTREG(MGAREG_WFLAG1, 0);   
240         PRIMOUTREG(0x2d00 + 56*4, *((u32 *)(&fParam)));
241         PRIMOUTREG(MGAREG_DMAPAD, 0);
242         PRIMOUTREG(MGAREG_DMAPAD, 0);
243    
244         PRIMOUTREG(0x2d00 + 49*4, 0);  /* Tex stage 0 */
245         PRIMOUTREG(0x2d00 + 57*4, 0);  /* Tex stage 0 */
246         PRIMOUTREG(0x2d00 + 53*4, 0);  /* Tex stage 1 */
247         PRIMOUTREG(0x2d00 + 61*4, 0);  /* Tex stage 1 */
248    
249         PRIMOUTREG(0x2d00 + 54*4, 0x40); /* Tex stage 0 : w */
250         PRIMOUTREG(0x2d00 + 62*4, 0x40); /* Tex stage 0 : h */
251         PRIMOUTREG(0x2d00 + 52*4, 0x40); /* Tex stage 1 : w */
252         PRIMOUTREG(0x2d00 + 60*4, 0x40); /* Tex stage 1 : h */
253    
254         /* Dma pading required due to hw bug */
255         PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
256         PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
257         PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
258         PRIMOUTREG(MGAREG_WIADDR2, (__u32)(dev_priv->WarpIndex[pipe].phys_addr |
259                                            WIA_wmode_start | WIA_wagp_agp));
260         PRIMADVANCE(dev_priv);
261 }
262
263 static void mgaG200EmitPipe( drm_mga_private_t *dev_priv )
264 {
265         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
266         unsigned int pipe = sarea_priv->WarpPipe;
267         PRIMLOCALS;
268
269         PRIMGETPTR(dev_priv);
270    
271         /* This takes 15 dwords */
272
273         PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
274         PRIMOUTREG(MGAREG_WVRTXSZ, 7);
275         PRIMOUTREG(MGAREG_WFLAG, 0);
276         PRIMOUTREG(0x2d00 + 24*4, 0); /* tex w/h */
277    
278         PRIMOUTREG(0x2d00 + 25*4, 0x100);
279         PRIMOUTREG(0x2d00 + 34*4, 0); /* tex w/h */
280         PRIMOUTREG(0x2d00 + 42*4, 0xFFFF);
281         PRIMOUTREG(0x2d00 + 60*4, 0xFFFF);
282    
283         /* Dma pading required due to hw bug */
284         PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
285         PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
286         PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
287         PRIMOUTREG(MGAREG_WIADDR, (__u32)(dev_priv->WarpIndex[pipe].phys_addr | 
288                                           WIA_wmode_start | WIA_wagp_agp));
289
290         PRIMADVANCE(dev_priv);
291 }
292
293 static void mgaEmitState( drm_mga_private_t *dev_priv )
294 {
295         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
296         unsigned int dirty = sarea_priv->dirty;
297
298         if (dev_priv->chipset == MGA_CARD_TYPE_G400) {     
299                 int multitex = sarea_priv->WarpPipe & MGA_T2;
300
301                 if (sarea_priv->WarpPipe != dev_priv->WarpPipe) { 
302                         mgaG400EmitPipe( dev_priv );
303                         dev_priv->WarpPipe = sarea_priv->WarpPipe;
304                 }
305
306                 if (dirty & MGA_UPLOAD_CTX) {
307                         mgaEmitContext( dev_priv );
308                         sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
309                 }
310
311                 if (dirty & MGA_UPLOAD_TEX0) {
312                         mgaG400EmitTex0( dev_priv );
313                         sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
314                 }
315
316                 if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
317                         mgaG400EmitTex1( dev_priv );
318                         sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
319                 }
320         } else {
321                 if (sarea_priv->WarpPipe != dev_priv->WarpPipe) { 
322                         mgaG200EmitPipe( dev_priv );
323                         dev_priv->WarpPipe = sarea_priv->WarpPipe;
324                 }
325
326                 if (dirty & MGA_UPLOAD_CTX) {
327                         mgaEmitContext( dev_priv );
328                         sarea_priv->dirty &= ~MGA_UPLOAD_CTX;
329                 }
330
331                 if (dirty & MGA_UPLOAD_TEX0) {
332                         mgaG200EmitTex( dev_priv );
333                         sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
334                 }
335         }
336 }
337
338
339 /* Disallow all write destinations except the front and backbuffer.
340  */
341 static int mgaVerifyContext(drm_mga_private_t *dev_priv )
342 {
343         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
344         unsigned int *regs = sarea_priv->ContextState;
345
346         if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
347             regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
348                 DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n", 
349                        regs[MGA_CTXREG_DSTORG], dev_priv->frontOffset,
350                        dev_priv->backOffset);
351                 regs[MGA_CTXREG_DSTORG] = 0;
352                 return -1;
353         }
354
355         return 0;
356 }
357
358 /* Disallow texture reads from PCI space.
359  */
360 static int mgaVerifyTex(drm_mga_private_t *dev_priv, 
361                       int unit)
362 {
363         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
364
365         if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
366                 DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n", 
367                        sarea_priv->TexState[unit][MGA_TEXREG_ORG],
368                        unit);
369                 sarea_priv->TexState[unit][MGA_TEXREG_ORG] = 0;
370                 return -1;
371         } 
372
373         return 0;
374 }
375
376 static int mgaVerifyState( drm_mga_private_t *dev_priv )
377 {
378         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
379         unsigned int dirty = sarea_priv->dirty;
380         int rv = 0;
381
382         if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
383                 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
384
385         if (dirty & MGA_UPLOAD_CTX)
386                 rv |= mgaVerifyContext( dev_priv );
387
388         if (dirty & MGA_UPLOAD_TEX0)
389                 rv |= mgaVerifyTex( dev_priv, 0 );
390
391         if (dev_priv->chipset == MGA_CARD_TYPE_G400) 
392         {          
393                 if (dirty & MGA_UPLOAD_TEX1)
394                         rv |= mgaVerifyTex( dev_priv, 1 );
395            
396                 if (dirty & MGA_UPLOAD_PIPE) 
397                         rv |= (sarea_priv->WarpPipe > MGA_MAX_G400_PIPES); 
398         } 
399         else 
400         {
401                 if (dirty & MGA_UPLOAD_PIPE) 
402                         rv |= (sarea_priv->WarpPipe > MGA_MAX_G200_PIPES); 
403         }         
404
405         return rv == 0;
406 }
407
408 static int mgaVerifyIload( drm_mga_private_t *dev_priv, 
409                            unsigned long bus_address, 
410                            unsigned int dstOrg, int length )
411 {
412         if(dstOrg < dev_priv->textureOffset ||
413            dstOrg + length > 
414            (dev_priv->textureOffset + dev_priv->textureSize)) {
415                 return -EINVAL;
416         }
417         if(length % 64) {
418                 return -EINVAL;
419         }
420         return 0;
421 }
422
423 /* This copies a 64 byte aligned agp region to the frambuffer
424  * with a standard blit, the ioctl needs to do checking */
425
426 static void mga_dma_dispatch_tex_blit( drm_device_t *dev, 
427                                        unsigned long bus_address, 
428                                        int length, 
429                                        unsigned int destOrg )
430 {
431         drm_mga_private_t *dev_priv = dev->dev_private;
432         int use_agp = PDEA_pagpxfer_enable | 0x00000001;
433         u16 y2;
434         PRIMLOCALS;
435     
436         y2 = length / 64;
437  
438         PRIM_OVERFLOW(dev, dev_priv, 30);
439         PRIMGETPTR( dev_priv );
440
441         dev_priv->last_sync_tag = mga_create_sync_tag(dev);
442
443         PRIMOUTREG( MGAREG_DSTORG, destOrg);
444         PRIMOUTREG( MGAREG_MACCESS, 0x00000000);
445         DRM_DEBUG("srcorg : %lx\n", bus_address | use_agp);
446         PRIMOUTREG( MGAREG_SRCORG, (u32) bus_address | use_agp);
447         PRIMOUTREG( MGAREG_AR5, 64);  
448
449         PRIMOUTREG( MGAREG_PITCH, 64);
450         PRIMOUTREG( MGAREG_DMAPAD, 0);
451         PRIMOUTREG( MGAREG_DMAPAD, 0);
452         PRIMOUTREG( MGAREG_DWGCTL, MGA_COPY_CMD); 
453
454         PRIMOUTREG(MGAREG_AR0, 63);
455         PRIMOUTREG(MGAREG_AR3, 0);              
456         PRIMOUTREG(MGAREG_FXBNDRY, (63 << 16));
457         PRIMOUTREG(MGAREG_YDSTLEN+MGAREG_MGA_EXEC, y2);
458   
459         PRIMOUTREG( MGAREG_SRCORG, 0);
460         PRIMOUTREG( MGAREG_PITCH, dev_priv->stride / dev_priv->cpp);
461         PRIMOUTREG( MGAREG_DMAPAD, 0);
462         PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
463         PRIMADVANCE(dev_priv);
464 }
465
466 static void mga_dma_dispatch_vertex(drm_device_t *dev, 
467                                     drm_buf_t *buf)
468 {
469         drm_mga_private_t *dev_priv = dev->dev_private;
470         drm_mga_buf_priv_t *buf_priv = buf->dev_private;
471         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
472         unsigned long address = (unsigned long)buf->bus_address;
473         int length = buf->used; 
474         int use_agp = PDEA_pagpxfer_enable;
475         int i = 0;
476         int primary_needed;
477         PRIMLOCALS;
478
479         DRM_DEBUG("dispatch vertex %d addr 0x%lx, "
480                   "length 0x%x nbox %d dirty %x\n", 
481                   buf->idx, address, length, 
482                   sarea_priv->nbox, sarea_priv->dirty);
483
484
485         dev_priv->last_sync_tag = mga_create_sync_tag(dev);
486
487         if (buf_priv->discard) { 
488                 buf_priv->my_freelist->age = dev_priv->last_sync_tag;
489                 mga_freelist_put(dev, buf);
490         }
491
492
493         /* WARNING: if you change any of the state functions verify
494          * these numbers (Overestimating this doesn't hurt).  
495          */
496         primary_needed = (25+15+30+25+ 
497                           10 + 
498                           15 * MGA_NR_SAREA_CLIPRECTS);
499
500
501         PRIM_OVERFLOW(dev, dev_priv, primary_needed);
502         mgaEmitState( dev_priv );
503
504         if (buf->used) {
505                 do {
506                         if (i < sarea_priv->nbox) {
507                                 DRM_DEBUG("idx %d Emit box %d/%d:"
508                                           "%d,%d - %d,%d\n", 
509                                           buf->idx,
510                                           i, sarea_priv->nbox,
511                                           sarea_priv->boxes[i].x1, 
512                                           sarea_priv->boxes[i].y1,
513                                           sarea_priv->boxes[i].x2, 
514                                           sarea_priv->boxes[i].y2);
515                                 
516                                 mgaEmitClipRect( dev_priv, 
517                                                  &sarea_priv->boxes[i] );
518                         }
519                         
520                         PRIMGETPTR(dev_priv);
521                         PRIMOUTREG( MGAREG_DMAPAD, 0);
522                         PRIMOUTREG( MGAREG_DMAPAD, 0);
523                         PRIMOUTREG( MGAREG_SECADDRESS, 
524                                     ((__u32)address) | TT_VERTEX);
525                         PRIMOUTREG( MGAREG_SECEND, 
526                                     (((__u32)(address + length)) | 
527                                      use_agp));
528                         PRIMADVANCE( dev_priv );               
529                 }  while (++i < sarea_priv->nbox);
530         }
531
532         PRIMGETPTR( dev_priv );
533         PRIMOUTREG(MGAREG_DMAPAD, 0);
534         PRIMOUTREG(MGAREG_DMAPAD, 0);
535         PRIMOUTREG(MGAREG_DMAPAD, 0);
536         PRIMOUTREG(MGAREG_DWGSYNC, dev_priv->last_sync_tag);   
537         PRIMADVANCE( dev_priv );
538 }
539
540
541 static void mga_dma_dispatch_clear( drm_device_t *dev, int flags, 
542                                     unsigned int clear_color,
543                                     unsigned int clear_zval )
544 {
545         drm_mga_private_t *dev_priv = dev->dev_private;
546         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
547         unsigned int *regs = sarea_priv->ContextState;
548         int nbox = sarea_priv->nbox;
549         drm_clip_rect_t *pbox = sarea_priv->boxes;
550         unsigned int cmd;
551         int i;
552         int primary_needed;
553         PRIMLOCALS;
554
555         if ( dev_priv->sgram ) 
556                 cmd = MGA_CLEAR_CMD | DC_atype_blk;
557         else
558                 cmd = MGA_CLEAR_CMD | DC_atype_rstr;
559    
560         primary_needed = nbox * 70;
561         if(primary_needed == 0) primary_needed = 70;
562         PRIM_OVERFLOW(dev, dev_priv, primary_needed);
563         PRIMGETPTR( dev_priv );
564         dev_priv->last_sync_tag = mga_create_sync_tag(dev);
565    
566         for (i = 0 ; i < nbox ; i++) {
567                 unsigned int height = pbox[i].y2 - pbox[i].y1;
568
569                 DRM_DEBUG("dispatch clear %d,%d-%d,%d flags %x!\n",
570                           pbox[i].x1, pbox[i].y1, pbox[i].x2, 
571                           pbox[i].y2, flags);
572
573                 if ( flags & MGA_FRONT ) {          
574                         DRM_DEBUG("clear front\n");
575                         PRIMOUTREG( MGAREG_DMAPAD, 0);
576                         PRIMOUTREG( MGAREG_DMAPAD, 0);
577                         PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
578                         PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
579
580                         PRIMOUTREG( MGAREG_DMAPAD, 0);
581                         PRIMOUTREG(MGAREG_FCOL, clear_color);
582                         PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
583                         PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
584                 }
585
586                 if ( flags & MGA_BACK ) {
587                         DRM_DEBUG("clear back\n");
588                         PRIMOUTREG( MGAREG_DMAPAD, 0);
589                         PRIMOUTREG( MGAREG_DMAPAD, 0);
590                         PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
591                         PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
592
593                         PRIMOUTREG( MGAREG_DMAPAD, 0);
594                         PRIMOUTREG(MGAREG_FCOL, clear_color);
595                         PRIMOUTREG(MGAREG_DSTORG, dev_priv->backOffset);
596                         PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
597                 }
598
599                 if ( flags & MGA_DEPTH ) {
600                         DRM_DEBUG("clear depth\n");
601                         PRIMOUTREG( MGAREG_DMAPAD, 0);
602                         PRIMOUTREG( MGAREG_DMAPAD, 0);
603                         PRIMOUTREG(MGAREG_YDSTLEN, (pbox[i].y1<<16)|height);
604                         PRIMOUTREG(MGAREG_FXBNDRY, (pbox[i].x2<<16)|pbox[i].x1);
605
606                         PRIMOUTREG( MGAREG_DMAPAD, 0);
607                         PRIMOUTREG(MGAREG_FCOL, clear_zval);
608                         PRIMOUTREG(MGAREG_DSTORG, dev_priv->depthOffset);
609                         PRIMOUTREG(MGAREG_DWGCTL+MGAREG_MGA_EXEC, cmd );
610                 }
611         }
612
613         /* Force reset of DWGCTL */
614         PRIMOUTREG( MGAREG_DMAPAD, 0);   
615         PRIMOUTREG( MGAREG_DMAPAD, 0);   
616         PRIMOUTREG( MGAREG_DMAPAD, 0);
617         PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
618
619         PRIMOUTREG( MGAREG_DMAPAD, 0);
620         PRIMOUTREG( MGAREG_DMAPAD, 0);
621         PRIMOUTREG( MGAREG_DMAPAD, 0);
622         PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
623         PRIMADVANCE(dev_priv);
624 }
625
626 static void mga_dma_dispatch_swap( drm_device_t *dev )
627 {
628         drm_mga_private_t *dev_priv = dev->dev_private;
629         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
630         unsigned int *regs = sarea_priv->ContextState;
631         int nbox = sarea_priv->nbox;
632         drm_clip_rect_t *pbox = sarea_priv->boxes;
633         int i;
634         int primary_needed;
635         PRIMLOCALS;
636
637         primary_needed = nbox * 5;
638         primary_needed += 60;
639         PRIM_OVERFLOW(dev, dev_priv, primary_needed);
640         PRIMGETPTR( dev_priv );
641    
642         dev_priv->last_sync_tag = mga_create_sync_tag(dev);
643
644         PRIMOUTREG(MGAREG_DSTORG, dev_priv->frontOffset);
645         PRIMOUTREG(MGAREG_MACCESS, dev_priv->mAccess);
646         PRIMOUTREG(MGAREG_SRCORG, dev_priv->backOffset);
647         PRIMOUTREG(MGAREG_AR5, dev_priv->stride/2);  
648
649         PRIMOUTREG( MGAREG_DMAPAD, 0);
650         PRIMOUTREG( MGAREG_DMAPAD, 0);
651         PRIMOUTREG( MGAREG_DMAPAD, 0);
652         PRIMOUTREG(MGAREG_DWGCTL, MGA_COPY_CMD); 
653              
654         for (i = 0 ; i < nbox; i++) {
655                 unsigned int h = pbox[i].y2 - pbox[i].y1;
656                 unsigned int start = pbox[i].y1 * dev_priv->stride/2;
657                 
658                 DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
659                           pbox[i].x1, pbox[i].y1,
660                           pbox[i].x2, pbox[i].y2);
661
662                 PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
663                 PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1);             
664                 PRIMOUTREG(MGAREG_FXBNDRY, pbox[i].x1|((pbox[i].x2 - 1)<<16));
665                 PRIMOUTREG(MGAREG_YDSTLEN+MGAREG_MGA_EXEC, (pbox[i].y1<<16)|h);
666         }
667
668         /* Force reset of DWGCTL */
669         PRIMOUTREG( MGAREG_DMAPAD, 0);
670         PRIMOUTREG( MGAREG_DMAPAD, 0);
671         PRIMOUTREG( MGAREG_DMAPAD, 0);
672         PRIMOUTREG( MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL] );
673
674         PRIMOUTREG( MGAREG_SRCORG, 0);
675         PRIMOUTREG( MGAREG_DMAPAD, 0);
676         PRIMOUTREG( MGAREG_DMAPAD, 0);
677         PRIMOUTREG( MGAREG_DWGSYNC, dev_priv->last_sync_tag);
678         PRIMADVANCE(dev_priv);
679 }
680
681 int mga_clear_bufs(struct inode *inode, struct file *filp,
682                    unsigned int cmd, unsigned long arg)
683 {
684         drm_file_t *priv = filp->private_data;
685         drm_device_t *dev = priv->dev;
686         drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
687         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
688         __volatile__ unsigned int *status = 
689                 (__volatile__ unsigned int *)dev_priv->status_page;
690         drm_mga_clear_t clear;
691
692         copy_from_user_ret(&clear, (drm_mga_clear_t *)arg, sizeof(clear), 
693                            -EFAULT);
694
695         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
696                 DRM_ERROR("mga_clear_bufs called without lock held\n");
697                 return -EINVAL;
698         }
699    
700         if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
701                 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
702
703         /* Make sure we restore the 3D state next time.
704          */
705         dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
706         mga_dma_dispatch_clear( dev, clear.flags, 
707                                 clear.clear_color, 
708                                 clear.clear_depth );
709         PRIMUPDATE(dev_priv);
710         mga_dma_schedule(dev, 1);
711         sarea_priv->last_dispatch = status[1];
712         return 0;
713 }
714
715 int mga_swap_bufs(struct inode *inode, struct file *filp,
716                   unsigned int cmd, unsigned long arg)
717 {
718         drm_file_t *priv = filp->private_data;
719         drm_device_t *dev = priv->dev;
720         drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
721         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
722         __volatile__ unsigned int *status = 
723                 (__volatile__ unsigned int *)dev_priv->status_page;
724    
725         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
726                 DRM_ERROR("mga_swap_bufs called without lock held\n");
727                 return -EINVAL;
728         }
729
730         if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
731                 sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
732
733         /* Make sure we restore the 3D state next time.
734          */
735         dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CTX;
736         mga_dma_dispatch_swap( dev );
737         PRIMUPDATE(dev_priv);
738         set_bit(0, &dev_priv->current_prim->swap_pending);
739         dev_priv->current_prim->swap_pending = 1;
740         mga_dma_schedule(dev, 1);
741         sarea_priv->last_dispatch = status[1];
742         return 0;
743 }
744
745 int mga_iload(struct inode *inode, struct file *filp,
746               unsigned int cmd, unsigned long arg)
747 {
748         drm_file_t *priv = filp->private_data;
749         drm_device_t *dev = priv->dev;
750         drm_device_dma_t  *dma      = dev->dma;
751         drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
752         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
753         __volatile__ unsigned int *status = 
754                 (__volatile__ unsigned int *)dev_priv->status_page;
755         drm_buf_t *buf;
756         drm_mga_buf_priv_t *buf_priv;
757         drm_mga_iload_t iload;
758         unsigned long bus_address;
759    
760         DRM_DEBUG("Starting Iload\n");
761         copy_from_user_ret(&iload, (drm_mga_iload_t *)arg, sizeof(iload),
762                            -EFAULT);
763
764         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
765                 DRM_ERROR("mga_iload called without lock held\n");
766                 return -EINVAL;
767         }
768
769         buf = dma->buflist[ iload.idx ];
770         buf_priv = buf->dev_private;
771         bus_address = buf->bus_address;
772         DRM_DEBUG("bus_address %lx, length %d, destorg : %x\n",
773                bus_address, iload.length, iload.destOrg);
774    
775         if(mgaVerifyIload(dev_priv, 
776                           bus_address,
777                           iload.destOrg,  
778                           iload.length)) {
779                 mga_freelist_put(dev, buf);
780                 return -EINVAL;
781         }
782     
783         sarea_priv->dirty |= MGA_UPLOAD_CTX;
784
785         mga_dma_dispatch_tex_blit(dev, bus_address, iload.length, 
786                                   iload.destOrg);
787         buf_priv->my_freelist->age = dev_priv->last_sync_tag;
788         buf_priv->discard = 1;
789         mga_freelist_put(dev, buf);
790         mga_dma_schedule(dev, 1);
791         sarea_priv->last_dispatch = status[1];
792         return 0; 
793 }
794
795 int mga_vertex(struct inode *inode, struct file *filp,
796                unsigned int cmd, unsigned long arg)
797 {
798         drm_file_t *priv = filp->private_data;
799         drm_device_t *dev = priv->dev;
800         drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
801         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
802         __volatile__ unsigned int *status = 
803                 (__volatile__ unsigned int *)dev_priv->status_page;
804         drm_device_dma_t *dma = dev->dma;
805         drm_buf_t *buf;
806         drm_mga_buf_priv_t *buf_priv;
807         drm_mga_vertex_t vertex;
808
809         copy_from_user_ret(&vertex, (drm_mga_vertex_t *)arg, sizeof(vertex),
810                            -EFAULT);
811    
812         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
813                 DRM_ERROR("mga_vertex called without lock held\n");
814                 return -EINVAL;
815         }
816
817         DRM_DEBUG("mga_vertex\n");
818
819         buf = dma->buflist[ vertex.idx ];
820         buf_priv = buf->dev_private;
821
822         buf->used = vertex.used;
823         buf_priv->discard = vertex.discard;
824    
825         if (!mgaVerifyState(dev_priv)) {
826            if (vertex.discard) { 
827                 buf_priv->my_freelist->age = dev_priv->last_sync_tag;
828                 mga_freelist_put(dev, buf);
829            }
830            return -EINVAL;
831         }
832
833         mga_dma_dispatch_vertex(dev, buf);
834
835         PRIMUPDATE(dev_priv);
836         mga_dma_schedule(dev, 1);
837         sarea_priv->last_dispatch = status[1];
838         return 0;
839 }
840
841 static int mga_dma_get_buffers(drm_device_t *dev, drm_dma_t *d)
842 {
843         int i;
844         drm_buf_t *buf;
845
846         for (i = d->granted_count; i < d->request_count; i++) {
847                 buf = mga_freelist_get(dev);
848                 if (!buf) break;
849                 buf->pid = current->pid;
850                 copy_to_user_ret(&d->request_indices[i],
851                                  &buf->idx,
852                                  sizeof(buf->idx),
853                                  -EFAULT);
854                 copy_to_user_ret(&d->request_sizes[i],
855                                  &buf->total,
856                                  sizeof(buf->total),
857                                  -EFAULT);
858                 ++d->granted_count;
859         }
860         return 0;
861 }
862
863 int mga_dma(struct inode *inode, struct file *filp, unsigned int cmd,
864             unsigned long arg)
865 {
866         drm_file_t        *priv     = filp->private_data;
867         drm_device_t      *dev      = priv->dev;
868         drm_device_dma_t  *dma      = dev->dma;
869         drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
870         drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
871         __volatile__ unsigned int *status = 
872                 (__volatile__ unsigned int *)dev_priv->status_page;
873         int               retcode   = 0;
874         drm_dma_t         d;
875
876         copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
877         DRM_DEBUG("%d %d: %d send, %d req\n",
878                   current->pid, d.context, d.send_count, d.request_count);
879
880         if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
881                 DRM_ERROR("mga_dma called without lock held\n");
882                 return -EINVAL;
883         }
884
885         /* Please don't send us buffers.
886          */
887         if (d.send_count != 0) {
888                 DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
889                           current->pid, d.send_count);
890                 return -EINVAL;
891         }
892         
893         /* We'll send you buffers.
894          */
895         if (d.request_count < 0 || d.request_count > dma->buf_count) {
896                 DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
897                           current->pid, d.request_count, dma->buf_count);
898                 return -EINVAL;
899         }
900         
901         d.granted_count = 0;
902
903         if (d.request_count) {
904                 retcode = mga_dma_get_buffers(dev, &d);
905         }
906
907         DRM_DEBUG("%d returning, granted = %d\n",
908                   current->pid, d.granted_count);
909         copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
910         sarea_priv->last_dispatch = status[1];
911         return retcode;
912 }