mga_dri.c revision fe5e51b7
1fe5e51b7Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c,v 1.31tsi Exp $ */
2fe5e51b7Smrg
3fe5e51b7Smrg/*
4fe5e51b7Smrg * Copyright 2000 VA Linux Systems Inc., Fremont, California.
5fe5e51b7Smrg * All Rights Reserved.
6fe5e51b7Smrg *
7fe5e51b7Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8fe5e51b7Smrg * copy of this software and associated documentation files (the "Software"),
9fe5e51b7Smrg * to deal in the Software without restriction, including without limitation
10fe5e51b7Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11fe5e51b7Smrg * and/or sell copies of the Software, and to permit persons to whom the
12fe5e51b7Smrg * Software is furnished to do so, subject to the following conditions:
13fe5e51b7Smrg *
14fe5e51b7Smrg * The above copyright notice and this permission notice (including the next
15fe5e51b7Smrg * paragraph) shall be included in all copies or substantial portions of the
16fe5e51b7Smrg * Software.
17fe5e51b7Smrg *
18fe5e51b7Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19fe5e51b7Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20fe5e51b7Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21fe5e51b7Smrg * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES
22fe5e51b7Smrg * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23fe5e51b7Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24fe5e51b7Smrg * OTHER DEALINGS IN THE SOFTWARE.
25fe5e51b7Smrg *
26fe5e51b7Smrg * Authors:
27fe5e51b7Smrg *    Keith Whitwell <keith@tungstengraphics.com>
28fe5e51b7Smrg *    Gareth Hughes <gareth@valinux.com>
29fe5e51b7Smrg */
30fe5e51b7Smrg
31fe5e51b7Smrg#ifdef HAVE_CONFIG_H
32fe5e51b7Smrg#include "config.h"
33fe5e51b7Smrg#endif
34fe5e51b7Smrg
35fe5e51b7Smrg#include "xf86.h"
36fe5e51b7Smrg#include "xf86_OSproc.h"
37fe5e51b7Smrg#include "xf86Priv.h"
38fe5e51b7Smrg
39fe5e51b7Smrg#include "xf86PciInfo.h"
40fe5e51b7Smrg#include "xf86Pci.h"
41fe5e51b7Smrg#define PSZ 8
42fe5e51b7Smrg#include "cfb.h"
43fe5e51b7Smrg#undef PSZ
44fe5e51b7Smrg#include "cfb16.h"
45fe5e51b7Smrg#include "cfb32.h"
46fe5e51b7Smrg
47fe5e51b7Smrg#include "miline.h"
48fe5e51b7Smrg
49fe5e51b7Smrg#include <errno.h>
50fe5e51b7Smrg
51fe5e51b7Smrg#include <inttypes.h>
52fe5e51b7Smrg#include "mga_reg.h"
53fe5e51b7Smrg#include "mga.h"
54fe5e51b7Smrg#include "mga_macros.h"
55fe5e51b7Smrg#include "mga_dri.h"
56fe5e51b7Smrg#include "mga_sarea.h"
57fe5e51b7Smrg#include "mga_drm.h"
58fe5e51b7Smrg
59fe5e51b7Smrg#define _XF86DRI_SERVER_
60fe5e51b7Smrg#include "GL/glxtokens.h"
61fe5e51b7Smrg#include "sarea.h"
62fe5e51b7Smrg
63fe5e51b7Smrg
64fe5e51b7Smrg
65fe5e51b7Smrg
66fe5e51b7Smrg
67fe5e51b7Smrg#include "GL/glxtokens.h"
68fe5e51b7Smrg
69fe5e51b7Smrg#include "mga_reg.h"
70fe5e51b7Smrg#include "mga.h"
71fe5e51b7Smrg#include "mga_macros.h"
72fe5e51b7Smrg#include "mga_dri.h"
73fe5e51b7Smrg
74fe5e51b7Smrg#define  DRM_MGA_IDLE_RETRY          2048
75fe5e51b7Smrg
76fe5e51b7Smrgstatic char MGAKernelDriverName[] = "mga";
77fe5e51b7Smrgstatic char MGAClientDriverName[] = "mga";
78fe5e51b7Smrg
79fe5e51b7Smrg/* Initialize the visual configs that are supported by the hardware.
80fe5e51b7Smrg * These are combined with the visual configs that the indirect
81fe5e51b7Smrg * rendering core supports, and the intersection is exported to the
82fe5e51b7Smrg * client.
83fe5e51b7Smrg */
84fe5e51b7Smrgstatic Bool MGAInitVisualConfigs( ScreenPtr pScreen )
85fe5e51b7Smrg{
86fe5e51b7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
87fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
88fe5e51b7Smrg   int numConfigs = 0;
89fe5e51b7Smrg   __GLXvisualConfig *pConfigs = 0;
90fe5e51b7Smrg   MGAConfigPrivPtr pMGAConfigs = 0;
91fe5e51b7Smrg   MGAConfigPrivPtr *pMGAConfigPtrs = 0;
92fe5e51b7Smrg   int i, db, depth, stencil, accum;
93fe5e51b7Smrg
94fe5e51b7Smrg   switch ( pScrn->bitsPerPixel ) {
95fe5e51b7Smrg   case 8:
96fe5e51b7Smrg   case 24:
97fe5e51b7Smrg      break;
98fe5e51b7Smrg
99fe5e51b7Smrg   case 16:
100fe5e51b7Smrg      numConfigs = 8;
101fe5e51b7Smrg
102fe5e51b7Smrg      pConfigs = (__GLXvisualConfig*)xcalloc( sizeof(__GLXvisualConfig),
103fe5e51b7Smrg						numConfigs );
104fe5e51b7Smrg      if ( !pConfigs ) {
105fe5e51b7Smrg	 return FALSE;
106fe5e51b7Smrg      }
107fe5e51b7Smrg
108fe5e51b7Smrg      pMGAConfigs = (MGAConfigPrivPtr)xcalloc( sizeof(MGAConfigPrivRec),
109fe5e51b7Smrg						 numConfigs );
110fe5e51b7Smrg      if ( !pMGAConfigs ) {
111fe5e51b7Smrg	 xfree( pConfigs );
112fe5e51b7Smrg	 return FALSE;
113fe5e51b7Smrg      }
114fe5e51b7Smrg
115fe5e51b7Smrg      pMGAConfigPtrs = (MGAConfigPrivPtr*)xcalloc( sizeof(MGAConfigPrivPtr),
116fe5e51b7Smrg						     numConfigs );
117fe5e51b7Smrg      if ( !pMGAConfigPtrs ) {
118fe5e51b7Smrg	 xfree( pConfigs );
119fe5e51b7Smrg	 xfree( pMGAConfigs );
120fe5e51b7Smrg	 return FALSE;
121fe5e51b7Smrg      }
122fe5e51b7Smrg
123fe5e51b7Smrg      for ( i = 0 ; i < numConfigs ; i++ ) {
124fe5e51b7Smrg	 pMGAConfigPtrs[i] = &pMGAConfigs[i];
125fe5e51b7Smrg      }
126fe5e51b7Smrg
127fe5e51b7Smrg      i = 0;
128fe5e51b7Smrg      for ( accum = 0 ; accum <= 1 ; accum++ ) {
129fe5e51b7Smrg         for ( stencil = 0 ; stencil <= 1 ; stencil++ ) {
130fe5e51b7Smrg            for ( db = 1 ; db >= 0 ; db-- ) {
131fe5e51b7Smrg               pConfigs[i].vid			= -1;
132fe5e51b7Smrg               pConfigs[i].class		= -1;
133fe5e51b7Smrg               pConfigs[i].rgba			= TRUE;
134fe5e51b7Smrg               pConfigs[i].redSize		= 5;
135fe5e51b7Smrg               pConfigs[i].greenSize		= 6;
136fe5e51b7Smrg               pConfigs[i].blueSize		= 5;
137fe5e51b7Smrg               pConfigs[i].alphaSize		= 0;
138fe5e51b7Smrg               pConfigs[i].redMask		= 0x0000F800;
139fe5e51b7Smrg               pConfigs[i].greenMask		= 0x000007E0;
140fe5e51b7Smrg               pConfigs[i].blueMask		= 0x0000001F;
141fe5e51b7Smrg               pConfigs[i].alphaMask		= 0;
142fe5e51b7Smrg               if ( accum ) {
143fe5e51b7Smrg                  pConfigs[i].accumRedSize	= 16;
144fe5e51b7Smrg                  pConfigs[i].accumGreenSize	= 16;
145fe5e51b7Smrg                  pConfigs[i].accumBlueSize	= 16;
146fe5e51b7Smrg                  pConfigs[i].accumAlphaSize	= 0;
147fe5e51b7Smrg               } else {
148fe5e51b7Smrg                  pConfigs[i].accumRedSize	= 0;
149fe5e51b7Smrg                  pConfigs[i].accumGreenSize	= 0;
150fe5e51b7Smrg                  pConfigs[i].accumBlueSize	= 0;
151fe5e51b7Smrg                  pConfigs[i].accumAlphaSize	= 0;
152fe5e51b7Smrg               }
153fe5e51b7Smrg               if ( db ) {
154fe5e51b7Smrg                  pConfigs[i].doubleBuffer	= TRUE;
155fe5e51b7Smrg               } else {
156fe5e51b7Smrg                  pConfigs[i].doubleBuffer	= FALSE;
157fe5e51b7Smrg	       }
158fe5e51b7Smrg               pConfigs[i].stereo		= FALSE;
159fe5e51b7Smrg               pConfigs[i].bufferSize		= 16;
160fe5e51b7Smrg               pConfigs[i].depthSize		= 16;
161fe5e51b7Smrg               if ( stencil ) {
162fe5e51b7Smrg                  pConfigs[i].stencilSize	= 8;
163fe5e51b7Smrg               } else {
164fe5e51b7Smrg                  pConfigs[i].stencilSize	= 0;
165fe5e51b7Smrg	       }
166fe5e51b7Smrg               pConfigs[i].auxBuffers		= 0;
167fe5e51b7Smrg               pConfigs[i].level		= 0;
168fe5e51b7Smrg               if ( accum || stencil ) {
169fe5e51b7Smrg                  pConfigs[i].visualRating	= GLX_SLOW_CONFIG;
170fe5e51b7Smrg               } else {
171fe5e51b7Smrg                  pConfigs[i].visualRating	= GLX_NONE;
172fe5e51b7Smrg	       }
173fe5e51b7Smrg               pConfigs[i].transparentPixel	= GLX_NONE;
174fe5e51b7Smrg               pConfigs[i].transparentRed	= 0;
175fe5e51b7Smrg               pConfigs[i].transparentGreen	= 0;
176fe5e51b7Smrg               pConfigs[i].transparentBlue	= 0;
177fe5e51b7Smrg               pConfigs[i].transparentAlpha	= 0;
178fe5e51b7Smrg               pConfigs[i].transparentIndex	= 0;
179fe5e51b7Smrg               i++;
180fe5e51b7Smrg            }
181fe5e51b7Smrg         }
182fe5e51b7Smrg      }
183fe5e51b7Smrg      if ( i != numConfigs ) {
184fe5e51b7Smrg         xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
185fe5e51b7Smrg		     "[drm] Incorrect initialization of visuals\n" );
186fe5e51b7Smrg         return FALSE;
187fe5e51b7Smrg      }
188fe5e51b7Smrg      break;
189fe5e51b7Smrg
190fe5e51b7Smrg   case 32:
191fe5e51b7Smrg      numConfigs = 8;
192fe5e51b7Smrg
193fe5e51b7Smrg      pConfigs = (__GLXvisualConfig*)xcalloc( sizeof(__GLXvisualConfig),
194fe5e51b7Smrg						numConfigs );
195fe5e51b7Smrg      if ( !pConfigs ) {
196fe5e51b7Smrg	 return FALSE;
197fe5e51b7Smrg      }
198fe5e51b7Smrg
199fe5e51b7Smrg      pMGAConfigs = (MGAConfigPrivPtr)xcalloc( sizeof(MGAConfigPrivRec),
200fe5e51b7Smrg						 numConfigs );
201fe5e51b7Smrg      if ( !pMGAConfigs ) {
202fe5e51b7Smrg	 xfree( pConfigs );
203fe5e51b7Smrg	 return FALSE;
204fe5e51b7Smrg      }
205fe5e51b7Smrg
206fe5e51b7Smrg      pMGAConfigPtrs = (MGAConfigPrivPtr*)xcalloc( sizeof(MGAConfigPrivPtr),
207fe5e51b7Smrg						     numConfigs );
208fe5e51b7Smrg      if ( !pMGAConfigPtrs ) {
209fe5e51b7Smrg	 xfree( pConfigs );
210fe5e51b7Smrg	 xfree( pMGAConfigs );
211fe5e51b7Smrg	 return FALSE;
212fe5e51b7Smrg      }
213fe5e51b7Smrg
214fe5e51b7Smrg      for ( i = 0 ; i < numConfigs ; i++ ) {
215fe5e51b7Smrg	 pMGAConfigPtrs[i] = &pMGAConfigs[i];
216fe5e51b7Smrg      }
217fe5e51b7Smrg
218fe5e51b7Smrg      i = 0;
219fe5e51b7Smrg      for ( accum = 0 ; accum <= 1 ; accum++ ) {
220fe5e51b7Smrg         for ( depth = 0 ; depth <= 1 ; depth++ ) { /* and stencil */
221fe5e51b7Smrg            for ( db = 1 ; db >= 0 ; db-- ) {
222fe5e51b7Smrg               pConfigs[i].vid			= -1;
223fe5e51b7Smrg               pConfigs[i].class		= -1;
224fe5e51b7Smrg               pConfigs[i].rgba			= TRUE;
225fe5e51b7Smrg               pConfigs[i].redSize		= 8;
226fe5e51b7Smrg               pConfigs[i].greenSize		= 8;
227fe5e51b7Smrg               pConfigs[i].blueSize		= 8;
228fe5e51b7Smrg               pConfigs[i].alphaSize		= 0;
229fe5e51b7Smrg               pConfigs[i].redMask		= 0x00FF0000;
230fe5e51b7Smrg               pConfigs[i].greenMask		= 0x0000FF00;
231fe5e51b7Smrg               pConfigs[i].blueMask		= 0x000000FF;
232fe5e51b7Smrg               pConfigs[i].alphaMask		= 0x0;
233fe5e51b7Smrg               if ( accum ) {
234fe5e51b7Smrg                  pConfigs[i].accumRedSize	= 16;
235fe5e51b7Smrg                  pConfigs[i].accumGreenSize	= 16;
236fe5e51b7Smrg                  pConfigs[i].accumBlueSize	= 16;
237fe5e51b7Smrg                  pConfigs[i].accumAlphaSize	= 0;
238fe5e51b7Smrg               } else {
239fe5e51b7Smrg                  pConfigs[i].accumRedSize	= 0;
240fe5e51b7Smrg                  pConfigs[i].accumGreenSize	= 0;
241fe5e51b7Smrg                  pConfigs[i].accumBlueSize	= 0;
242fe5e51b7Smrg                  pConfigs[i].accumAlphaSize	= 0;
243fe5e51b7Smrg               }
244fe5e51b7Smrg               if ( db ) {
245fe5e51b7Smrg                  pConfigs[i].doubleBuffer	= TRUE;
246fe5e51b7Smrg               } else {
247fe5e51b7Smrg                  pConfigs[i].doubleBuffer	= FALSE;
248fe5e51b7Smrg	       }
249fe5e51b7Smrg               pConfigs[i].stereo		= FALSE;
250fe5e51b7Smrg               pConfigs[i].bufferSize		= 24;
251fe5e51b7Smrg               if ( depth ) {
252fe5e51b7Smrg		     pConfigs[i].depthSize	= 24;
253fe5e51b7Smrg                     pConfigs[i].stencilSize	= 8;
254fe5e51b7Smrg               }
255fe5e51b7Smrg               else {
256fe5e51b7Smrg                     pConfigs[i].depthSize	= 0;
257fe5e51b7Smrg                     pConfigs[i].stencilSize	= 0;
258fe5e51b7Smrg               }
259fe5e51b7Smrg               pConfigs[i].auxBuffers		= 0;
260fe5e51b7Smrg               pConfigs[i].level		= 0;
261fe5e51b7Smrg               if ( accum ) {
262fe5e51b7Smrg                  pConfigs[i].visualRating	= GLX_SLOW_CONFIG;
263fe5e51b7Smrg               } else {
264fe5e51b7Smrg                  pConfigs[i].visualRating	= GLX_NONE;
265fe5e51b7Smrg	       }
266fe5e51b7Smrg               pConfigs[i].transparentPixel	= GLX_NONE;
267fe5e51b7Smrg               pConfigs[i].transparentRed	= 0;
268fe5e51b7Smrg               pConfigs[i].transparentGreen	= 0;
269fe5e51b7Smrg               pConfigs[i].transparentBlue	= 0;
270fe5e51b7Smrg               pConfigs[i].transparentAlpha	= 0;
271fe5e51b7Smrg               pConfigs[i].transparentIndex	= 0;
272fe5e51b7Smrg               i++;
273fe5e51b7Smrg            }
274fe5e51b7Smrg         }
275fe5e51b7Smrg      }
276fe5e51b7Smrg      if ( i != numConfigs ) {
277fe5e51b7Smrg         xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
278fe5e51b7Smrg		     "[drm] Incorrect initialization of visuals\n" );
279fe5e51b7Smrg         return FALSE;
280fe5e51b7Smrg      }
281fe5e51b7Smrg      break;
282fe5e51b7Smrg
283fe5e51b7Smrg   default:
284fe5e51b7Smrg      /* Unexpected bits/pixels */
285fe5e51b7Smrg      break;
286fe5e51b7Smrg   }
287fe5e51b7Smrg
288fe5e51b7Smrg   pMga->numVisualConfigs = numConfigs;
289fe5e51b7Smrg   pMga->pVisualConfigs = pConfigs;
290fe5e51b7Smrg   pMga->pVisualConfigsPriv = pMGAConfigs;
291fe5e51b7Smrg
292fe5e51b7Smrg   GlxSetVisualConfigs( numConfigs, pConfigs, (void **)pMGAConfigPtrs );
293fe5e51b7Smrg
294fe5e51b7Smrg   return TRUE;
295fe5e51b7Smrg}
296fe5e51b7Smrg
297fe5e51b7Smrgstatic Bool MGACreateContext( ScreenPtr pScreen, VisualPtr visual,
298fe5e51b7Smrg			      drm_context_t hwContext, void *pVisualConfigPriv,
299fe5e51b7Smrg			      DRIContextType contextStore )
300fe5e51b7Smrg{
301fe5e51b7Smrg   /* Nothing yet */
302fe5e51b7Smrg   return TRUE;
303fe5e51b7Smrg}
304fe5e51b7Smrg
305fe5e51b7Smrgstatic void MGADestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
306fe5e51b7Smrg			       DRIContextType contextStore )
307fe5e51b7Smrg{
308fe5e51b7Smrg   /* Nothing yet */
309fe5e51b7Smrg}
310fe5e51b7Smrg
311fe5e51b7Smrg
312fe5e51b7Smrg/* Quiescence, locking
313fe5e51b7Smrg */
314fe5e51b7Smrg#define MGA_TIMEOUT		2048
315fe5e51b7Smrg
316fe5e51b7Smrgstatic void MGAWaitForIdleDMA( ScrnInfoPtr pScrn )
317fe5e51b7Smrg{
318fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
319fe5e51b7Smrg   drm_lock_t lock;
320fe5e51b7Smrg   int ret;
321fe5e51b7Smrg   int i = 0;
322fe5e51b7Smrg
323fe5e51b7Smrg   memset( &lock, 0, sizeof(drm_lock_t) );
324fe5e51b7Smrg
325fe5e51b7Smrg   for (;;) {
326fe5e51b7Smrg      do {
327fe5e51b7Smrg         /* first ask for quiescent and flush */
328fe5e51b7Smrg         lock.flags = DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH;
329fe5e51b7Smrg         do {
330fe5e51b7Smrg	    ret = drmCommandWrite( pMga->drmFD, DRM_MGA_FLUSH,
331fe5e51b7Smrg                                   &lock, sizeof( drm_lock_t ) );
332fe5e51b7Smrg         } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
333fe5e51b7Smrg
334fe5e51b7Smrg         /* if it's still busy just try quiescent */
335fe5e51b7Smrg         if ( ret == -EBUSY ) {
336fe5e51b7Smrg            lock.flags = DRM_LOCK_QUIESCENT;
337fe5e51b7Smrg            do {
338fe5e51b7Smrg	       ret = drmCommandWrite( pMga->drmFD, DRM_MGA_FLUSH,
339fe5e51b7Smrg                                      &lock, sizeof( drm_lock_t ) );
340fe5e51b7Smrg            } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
341fe5e51b7Smrg         }
342fe5e51b7Smrg      } while ( ( ret == -EBUSY ) && ( i++ < MGA_TIMEOUT ) );
343fe5e51b7Smrg
344fe5e51b7Smrg      if ( ret == 0 )
345fe5e51b7Smrg	 return;
346fe5e51b7Smrg
347fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
348fe5e51b7Smrg		  "[dri] Idle timed out, resetting engine...\n" );
349fe5e51b7Smrg
350fe5e51b7Smrg      drmCommandNone( pMga->drmFD, DRM_MGA_RESET );
351fe5e51b7Smrg   }
352fe5e51b7Smrg}
353fe5e51b7Smrg
354fe5e51b7Smrg
355fe5e51b7Smrgvoid MGAGetQuiescence( ScrnInfoPtr pScrn )
356fe5e51b7Smrg{
357fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
358fe5e51b7Smrg
359fe5e51b7Smrg   pMga->haveQuiescense = 1;
360fe5e51b7Smrg
361fe5e51b7Smrg   if ( pMga->directRenderingEnabled ) {
362fe5e51b7Smrg      MGAFBLayout *pLayout = &pMga->CurrentLayout;
363fe5e51b7Smrg
364fe5e51b7Smrg      MGAWaitForIdleDMA( pScrn );
365fe5e51b7Smrg
366fe5e51b7Smrg        /* FIXME what about EXA? */
367fe5e51b7Smrg#ifdef USE_XAA
368fe5e51b7Smrg        if (!pMga->Exa && pMga->AccelInfoRec) {
369fe5e51b7Smrg      WAITFIFO( 11 );
370fe5e51b7Smrg      OUTREG( MGAREG_MACCESS, pMga->MAccess );
371fe5e51b7Smrg      OUTREG( MGAREG_PITCH, pLayout->displayWidth );
372fe5e51b7Smrg
373fe5e51b7Smrg      pMga->PlaneMask = ~0;
374fe5e51b7Smrg      OUTREG( MGAREG_PLNWT, pMga->PlaneMask );
375fe5e51b7Smrg
376fe5e51b7Smrg      pMga->BgColor = 0;
377fe5e51b7Smrg      pMga->FgColor = 0;
378fe5e51b7Smrg      OUTREG( MGAREG_BCOL, pMga->BgColor );
379fe5e51b7Smrg      OUTREG( MGAREG_FCOL, pMga->FgColor );
380fe5e51b7Smrg      OUTREG( MGAREG_SRCORG, pMga->realSrcOrg );
381fe5e51b7Smrg
382fe5e51b7Smrg      pMga->SrcOrg = 0;
383fe5e51b7Smrg      OUTREG( MGAREG_DSTORG, pMga->DstOrg );
384fe5e51b7Smrg      OUTREG( MGAREG_OPMODE, MGAOPM_DMA_BLIT );
385fe5e51b7Smrg      OUTREG( MGAREG_CXBNDRY, 0xFFFF0000 ); /* (maxX << 16) | minX */
386fe5e51b7Smrg      OUTREG( MGAREG_YTOP, 0x00000000 );    /* minPixelPointer */
387fe5e51b7Smrg      OUTREG( MGAREG_YBOT, 0x007FFFFF );    /* maxPixelPointer */
388fe5e51b7Smrg
389fe5e51b7Smrg            pMga->AccelFlags &= ~CLIPPER_ON;
390fe5e51b7Smrg        }
391fe5e51b7Smrg#endif
392fe5e51b7Smrg   }
393fe5e51b7Smrg}
394fe5e51b7Smrg
395fe5e51b7Smrgvoid MGAGetQuiescenceShared( ScrnInfoPtr pScrn )
396fe5e51b7Smrg{
397fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
398fe5e51b7Smrg   MGAEntPtr pMGAEnt = pMga->entityPrivate;
399fe5e51b7Smrg   MGAPtr pMGA2 = MGAPTR(pMGAEnt->pScrn_2);
400fe5e51b7Smrg
401fe5e51b7Smrg   pMga = MGAPTR(pMGAEnt->pScrn_1);
402fe5e51b7Smrg   pMga->haveQuiescense = 1;
403fe5e51b7Smrg   pMGA2->haveQuiescense = 1;
404fe5e51b7Smrg
405fe5e51b7Smrg   if ( pMGAEnt->directRenderingEnabled ) {
406fe5e51b7Smrg      MGAWaitForIdleDMA( pMGAEnt->pScrn_1 );
407fe5e51b7Smrg
408fe5e51b7Smrg        /* FIXME what about EXA? */
409fe5e51b7Smrg#ifdef USE_XAA
410fe5e51b7Smrg        if (!pMga->Exa && pMga->AccelInfoRec)
411fe5e51b7Smrg            pMga->RestoreAccelState( pScrn );
412fe5e51b7Smrg#endif
413fe5e51b7Smrg      xf86SetLastScrnFlag( pScrn->entityList[0], pScrn->scrnIndex );
414fe5e51b7Smrg   }
415fe5e51b7Smrg}
416fe5e51b7Smrg
417fe5e51b7Smrgstatic void MGASwapContext( ScreenPtr pScreen )
418fe5e51b7Smrg{
419fe5e51b7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
420fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
421fe5e51b7Smrg
422fe5e51b7Smrg   /* Arrange for dma_quiescence and xaa sync to be called as
423fe5e51b7Smrg    * appropriate.
424fe5e51b7Smrg    */
425fe5e51b7Smrg   pMga->haveQuiescense = 0;
426fe5e51b7Smrg
427fe5e51b7Smrg   MGA_MARK_SYNC(pMga, pScrn);
428fe5e51b7Smrg}
429fe5e51b7Smrg
430fe5e51b7Smrgstatic void MGASwapContextShared( ScreenPtr pScreen )
431fe5e51b7Smrg{
432fe5e51b7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
433fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
434fe5e51b7Smrg   MGAEntPtr pMGAEnt = pMga->entityPrivate;
435fe5e51b7Smrg   MGAPtr pMGA2 = MGAPTR(pMGAEnt->pScrn_2);
436fe5e51b7Smrg
437fe5e51b7Smrg   pMga = MGAPTR(pMGAEnt->pScrn_1);
438fe5e51b7Smrg
439fe5e51b7Smrg   pMga->haveQuiescense = pMGA2->haveQuiescense = 0;
440fe5e51b7Smrg
441fe5e51b7Smrg   MGA_MARK_SYNC(pMga, pScrn);
442fe5e51b7Smrg   MGA_MARK_SYNC(pMGA2, pMGAEnt->pScrn_2);
443fe5e51b7Smrg}
444fe5e51b7Smrg
445fe5e51b7Smrg/* FIXME: This comment is out of date, since we aren't overriding
446fe5e51b7Smrg * Block/Wakeuphandler anymore.
447fe5e51b7Smrg *
448fe5e51b7Smrg *
449fe5e51b7Smrg * This is really only called from validate/postvalidate as we
450fe5e51b7Smrg * override the dri lock/unlock.  Want to remove validate/postvalidate
451fe5e51b7Smrg * processing, but need to remove all client-side use of drawable lock
452fe5e51b7Smrg * first (otherwise there is noone recover when a client dies holding
453fe5e51b7Smrg * the drawable lock).
454fe5e51b7Smrg *
455fe5e51b7Smrg * What does this mean?
456fe5e51b7Smrg *
457fe5e51b7Smrg *   - The above code gets executed every time a
458fe5e51b7Smrg *     window changes shape or the focus changes, which isn't really
459fe5e51b7Smrg *     optimal.
460fe5e51b7Smrg *   - The X server therefore believes it needs to do an XAA sync
461fe5e51b7Smrg *     *and* a dma quiescense ioctl each time that happens.
462fe5e51b7Smrg *
463fe5e51b7Smrg * We don't wrap wakeuphandler any longer, so at least we can say that
464fe5e51b7Smrg * this doesn't happen *every time the mouse moves*...
465fe5e51b7Smrg */
466fe5e51b7Smrgstatic void
467fe5e51b7SmrgMGADRISwapContext( ScreenPtr pScreen, DRISyncType syncType,
468fe5e51b7Smrg		   DRIContextType oldContextType, void *oldContext,
469fe5e51b7Smrg		   DRIContextType newContextType, void *newContext )
470fe5e51b7Smrg{
471fe5e51b7Smrg   if ( syncType == DRI_3D_SYNC &&
472fe5e51b7Smrg	oldContextType == DRI_2D_CONTEXT &&
473fe5e51b7Smrg	newContextType == DRI_2D_CONTEXT )
474fe5e51b7Smrg   {
475fe5e51b7Smrg      MGASwapContext( pScreen );
476fe5e51b7Smrg   }
477fe5e51b7Smrg}
478fe5e51b7Smrg
479fe5e51b7Smrgstatic void
480fe5e51b7SmrgMGADRISwapContextShared( ScreenPtr pScreen, DRISyncType syncType,
481fe5e51b7Smrg			  DRIContextType oldContextType, void *oldContext,
482fe5e51b7Smrg			  DRIContextType newContextType, void *newContext )
483fe5e51b7Smrg{
484fe5e51b7Smrg   if ( syncType == DRI_3D_SYNC &&
485fe5e51b7Smrg	oldContextType == DRI_2D_CONTEXT &&
486fe5e51b7Smrg	newContextType == DRI_2D_CONTEXT )
487fe5e51b7Smrg   {
488fe5e51b7Smrg      MGASwapContextShared( pScreen );
489fe5e51b7Smrg   }
490fe5e51b7Smrg}
491fe5e51b7Smrg
492fe5e51b7Smrgvoid MGASelectBuffer( ScrnInfoPtr pScrn, int which )
493fe5e51b7Smrg{
494fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
495fe5e51b7Smrg   MGADRIPtr pMGADRI = (MGADRIPtr)pMga->pDRIInfo->devPrivate;
496fe5e51b7Smrg
497fe5e51b7Smrg   switch ( which ) {
498fe5e51b7Smrg   case MGA_BACK:
499fe5e51b7Smrg      OUTREG( MGAREG_DSTORG, pMGADRI->backOffset );
500fe5e51b7Smrg      OUTREG( MGAREG_SRCORG, pMGADRI->backOffset );
501fe5e51b7Smrg      break;
502fe5e51b7Smrg   case MGA_DEPTH:
503fe5e51b7Smrg      OUTREG( MGAREG_DSTORG, pMGADRI->depthOffset );
504fe5e51b7Smrg      OUTREG( MGAREG_SRCORG, pMGADRI->depthOffset );
505fe5e51b7Smrg      break;
506fe5e51b7Smrg   default:
507fe5e51b7Smrg   case MGA_FRONT:
508fe5e51b7Smrg      OUTREG( MGAREG_DSTORG, pMGADRI->frontOffset );
509fe5e51b7Smrg      OUTREG( MGAREG_SRCORG, pMGADRI->frontOffset );
510fe5e51b7Smrg      break;
511fe5e51b7Smrg   }
512fe5e51b7Smrg}
513fe5e51b7Smrg
514fe5e51b7Smrgstatic unsigned int mylog2( unsigned int n )
515fe5e51b7Smrg{
516fe5e51b7Smrg   unsigned int log2 = 1;
517fe5e51b7Smrg   while ( n > 1 ) n >>= 1, log2++;
518fe5e51b7Smrg   return log2;
519fe5e51b7Smrg}
520fe5e51b7Smrg
521fe5e51b7Smrg/**
522fe5e51b7Smrg * Initialize DMA and secondary texture memory
523fe5e51b7Smrg *
524fe5e51b7Smrg * \todo
525fe5e51b7Smrg * The sizes used for the primary DMA buffer and the bin size and count for
526fe5e51b7Smrg * the secondary DMA buffers should be configurable from the xorg.conf.
527fe5e51b7Smrg *
528fe5e51b7Smrg * \todo
529fe5e51b7Smrg * This routine should use \c mga_bios_values::host_interface to limit the
530fe5e51b7Smrg * AGP mode.  It the card is PCI, \c MGARec::agpSize should be forced to 0.
531fe5e51b7Smrg */
532fe5e51b7Smrgstatic Bool MGADRIBootstrapDMA(ScreenPtr pScreen)
533fe5e51b7Smrg{
534fe5e51b7Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
535fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
536fe5e51b7Smrg    MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
537fe5e51b7Smrg    int ret;
538fe5e51b7Smrg    int requested_agp_mode;
539fe5e51b7Smrg    int count;
540fe5e51b7Smrg
541fe5e51b7Smrg
542fe5e51b7Smrg    if(pMga->agpSize < 12)pMga->agpSize = 12;
543fe5e51b7Smrg    if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */
544fe5e51b7Smrg
545fe5e51b7Smrg
546fe5e51b7Smrg    requested_agp_mode = 0;
547fe5e51b7Smrg    switch ( pMga->agpMode ) {
548fe5e51b7Smrg    case 4:
549fe5e51b7Smrg	requested_agp_mode |= MGA_AGP_4X_MODE;
550fe5e51b7Smrg    case 2:
551fe5e51b7Smrg	requested_agp_mode |= MGA_AGP_2X_MODE;
552fe5e51b7Smrg    case 1:
553fe5e51b7Smrg    default:
554fe5e51b7Smrg	requested_agp_mode |= MGA_AGP_1X_MODE;
555fe5e51b7Smrg    }
556fe5e51b7Smrg
557fe5e51b7Smrg
558fe5e51b7Smrg    if ( (pMGADRIServer->drm_version_minor >= 2) && !pMga->useOldDmaInit ) {
559fe5e51b7Smrg	drm_mga_dma_bootstrap_t dma_bs;
560fe5e51b7Smrg
561fe5e51b7Smrg
562fe5e51b7Smrg	(void) memset( & dma_bs, 0, sizeof( dma_bs ) );
563fe5e51b7Smrg	dma_bs.primary_size = 1024 * 1024;
564fe5e51b7Smrg	dma_bs.secondary_bin_count = MGA_NUM_BUFFERS;
565fe5e51b7Smrg	dma_bs.secondary_bin_size = MGA_BUFFER_SIZE;
566fe5e51b7Smrg	dma_bs.agp_size = pMga->agpSize;
567fe5e51b7Smrg	dma_bs.agp_mode = (pMga->forcePciDma) ? 0 : requested_agp_mode;
568fe5e51b7Smrg
569fe5e51b7Smrg	ret = drmCommandWriteRead( pMga->drmFD, DRM_MGA_DMA_BOOTSTRAP,
570fe5e51b7Smrg				   & dma_bs, sizeof( dma_bs ) );
571fe5e51b7Smrg	if ( ret ) {
572fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Could not boot-strap DMA (%d)\n", ret );
573fe5e51b7Smrg	    return FALSE;
574fe5e51b7Smrg	}
575fe5e51b7Smrg
576fe5e51b7Smrg	pMga->agpMode = dma_bs.agp_mode;
577fe5e51b7Smrg	pMGADRIServer->agp.size = dma_bs.agp_size;
578fe5e51b7Smrg
579fe5e51b7Smrg	pMGADRIServer->agpTextures.handle = dma_bs.texture_handle;
580fe5e51b7Smrg	pMGADRIServer->agpTextures.size   = dma_bs.texture_size;
581fe5e51b7Smrg    }
582fe5e51b7Smrg    else {
583fe5e51b7Smrg	unsigned long mode;
584fe5e51b7Smrg	unsigned int vendor, device;
585fe5e51b7Smrg	int i;
586fe5e51b7Smrg
587fe5e51b7Smrg
588fe5e51b7Smrg	if ( pMga->forcePciDma ) {
589fe5e51b7Smrg	    const char * const msg = (pMGADRIServer->drm_version_minor < 2)
590fe5e51b7Smrg	      ? "DRM version is too old (3.2 or later required)"
591fe5e51b7Smrg	      : "old DMA init path was requested";
592fe5e51b7Smrg
593fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_WARNING,
594fe5e51b7Smrg			"[agp] Cannot force PCI DMA because %s\n", msg );
595fe5e51b7Smrg	}
596fe5e51b7Smrg
597fe5e51b7Smrg	if ( drmAgpAcquire( pMga->drmFD ) < 0 ) {
598fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not available\n" );
599fe5e51b7Smrg	    return FALSE;
600fe5e51b7Smrg	}
601fe5e51b7Smrg
602fe5e51b7Smrg	mode   = drmAgpGetMode( pMga->drmFD );        /* Default mode */
603fe5e51b7Smrg	vendor = drmAgpVendorId( pMga->drmFD );
604fe5e51b7Smrg	device = drmAgpDeviceId( pMga->drmFD );
605fe5e51b7Smrg
606fe5e51b7Smrg	mode = (mode & ~MGA_AGP_MODE_MASK) | requested_agp_mode;
607fe5e51b7Smrg
608fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
609fe5e51b7Smrg		    "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
610fe5e51b7Smrg		    mode, vendor, device,
611fe5e51b7Smrg		    VENDOR_ID(pMga->PciInfo),
612fe5e51b7Smrg		    DEVICE_ID(pMga->PciInfo));
613fe5e51b7Smrg
614fe5e51b7Smrg	if ( drmAgpEnable( pMga->drmFD, mode ) < 0 ) {
615fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
616fe5e51b7Smrg	    drmAgpRelease( pMga->drmFD );
617fe5e51b7Smrg	    return FALSE;
618fe5e51b7Smrg	}
619fe5e51b7Smrg
620fe5e51b7Smrg	if ( pMga->Chipset == PCI_CHIP_MGAG200 ) {
621fe5e51b7Smrg	    switch ( pMga->agpMode ) {
622fe5e51b7Smrg	    case 2:
623fe5e51b7Smrg		xf86DrvMsg( pScreen->myNum, X_INFO,
624fe5e51b7Smrg			    "[drm] Enabling AGP 2x PLL encoding\n" );
625fe5e51b7Smrg		OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE );
626fe5e51b7Smrg		break;
627fe5e51b7Smrg
628fe5e51b7Smrg	    case 1:
629fe5e51b7Smrg	    default:
630fe5e51b7Smrg		xf86DrvMsg( pScreen->myNum, X_INFO,
631fe5e51b7Smrg			    "[drm] Disabling AGP 2x PLL encoding\n" );
632fe5e51b7Smrg		OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE );
633fe5e51b7Smrg		pMga->agpMode = 1;
634fe5e51b7Smrg		break;
635fe5e51b7Smrg	    }
636fe5e51b7Smrg	}
637fe5e51b7Smrg
638fe5e51b7Smrg	pMGADRIServer->agp.size = pMga->agpSize * 1024 * 1024;
639fe5e51b7Smrg
640fe5e51b7Smrg	pMGADRIServer->warp.offset = 0;
641fe5e51b7Smrg	pMGADRIServer->warp.size = MGA_WARP_UCODE_SIZE;
642fe5e51b7Smrg
643fe5e51b7Smrg	pMGADRIServer->primary.offset = (pMGADRIServer->warp.offset +
644fe5e51b7Smrg					 pMGADRIServer->warp.size);
645fe5e51b7Smrg	pMGADRIServer->primary.size = 1024 * 1024;
646fe5e51b7Smrg
647fe5e51b7Smrg	pMGADRIServer->buffers.offset = (pMGADRIServer->primary.offset +
648fe5e51b7Smrg					 pMGADRIServer->primary.size);
649fe5e51b7Smrg	pMGADRIServer->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE;
650fe5e51b7Smrg
651fe5e51b7Smrg
652fe5e51b7Smrg	pMGADRIServer->agpTextures.offset = (pMGADRIServer->buffers.offset +
653fe5e51b7Smrg					     pMGADRIServer->buffers.size);
654fe5e51b7Smrg
655fe5e51b7Smrg	pMGADRIServer->agpTextures.size = (pMGADRIServer->agp.size -
656fe5e51b7Smrg					   pMGADRIServer->agpTextures.offset);
657fe5e51b7Smrg
658fe5e51b7Smrg	ret = drmAgpAlloc( pMga->drmFD, pMGADRIServer->agp.size,
659fe5e51b7Smrg			   0, NULL, &pMGADRIServer->agp.handle );
660fe5e51b7Smrg	if ( ret < 0 ) {
661fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
662fe5e51b7Smrg	    drmAgpRelease( pMga->drmFD );
663fe5e51b7Smrg	    return FALSE;
664fe5e51b7Smrg	}
665fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
666fe5e51b7Smrg 		    "[agp] %d kB allocated with handle 0x%08x\n",
667fe5e51b7Smrg		    pMGADRIServer->agp.size/1024,
668fe5e51b7Smrg		    (unsigned int) pMGADRIServer->agp.handle );
669fe5e51b7Smrg
670fe5e51b7Smrg	if ( drmAgpBind( pMga->drmFD, pMGADRIServer->agp.handle, 0 ) < 0 ) {
671fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind memory\n" );
672fe5e51b7Smrg	    drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle );
673fe5e51b7Smrg	    drmAgpRelease( pMga->drmFD );
674fe5e51b7Smrg	    return FALSE;
675fe5e51b7Smrg	}
676fe5e51b7Smrg
677fe5e51b7Smrg	/* WARP microcode space
678fe5e51b7Smrg	 */
679fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
680fe5e51b7Smrg			pMGADRIServer->warp.offset,
681fe5e51b7Smrg			pMGADRIServer->warp.size,
682fe5e51b7Smrg			DRM_AGP, DRM_READ_ONLY,
683fe5e51b7Smrg			&pMGADRIServer->warp.handle ) < 0 ) {
684fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
685fe5e51b7Smrg			"[agp] Could not add WARP microcode mapping\n" );
686fe5e51b7Smrg	    return FALSE;
687fe5e51b7Smrg	}
688fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
689fe5e51b7Smrg 		    "[agp] WARP microcode handle = 0x%08x\n",
690fe5e51b7Smrg		    (unsigned int) pMGADRIServer->warp.handle );
691fe5e51b7Smrg
692fe5e51b7Smrg	/* Primary DMA space
693fe5e51b7Smrg	 */
694fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
695fe5e51b7Smrg			pMGADRIServer->primary.offset,
696fe5e51b7Smrg			pMGADRIServer->primary.size,
697fe5e51b7Smrg			DRM_AGP, DRM_READ_ONLY,
698fe5e51b7Smrg			&pMGADRIServer->primary.handle ) < 0 ) {
699fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
700fe5e51b7Smrg			"[agp] Could not add primary DMA mapping\n" );
701fe5e51b7Smrg	    return FALSE;
702fe5e51b7Smrg	}
703fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
704fe5e51b7Smrg 		    "[agp] Primary DMA handle = 0x%08x\n",
705fe5e51b7Smrg		    (unsigned int) pMGADRIServer->primary.handle );
706fe5e51b7Smrg
707fe5e51b7Smrg	/* DMA buffers
708fe5e51b7Smrg	 */
709fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
710fe5e51b7Smrg			pMGADRIServer->buffers.offset,
711fe5e51b7Smrg			pMGADRIServer->buffers.size,
712fe5e51b7Smrg			DRM_AGP, 0,
713fe5e51b7Smrg			&pMGADRIServer->buffers.handle ) < 0 ) {
714fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
715fe5e51b7Smrg			"[agp] Could not add DMA buffers mapping\n" );
716fe5e51b7Smrg	    return FALSE;
717fe5e51b7Smrg	}
718fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
719fe5e51b7Smrg 		    "[agp] DMA buffers handle = 0x%08x\n",
720fe5e51b7Smrg		    (unsigned int) pMGADRIServer->buffers.handle );
721fe5e51b7Smrg
722fe5e51b7Smrg	count = drmAddBufs( pMga->drmFD,
723fe5e51b7Smrg			    MGA_NUM_BUFFERS, MGA_BUFFER_SIZE,
724fe5e51b7Smrg			    DRM_AGP_BUFFER, pMGADRIServer->buffers.offset );
725fe5e51b7Smrg	if ( count <= 0 ) {
726fe5e51b7Smrg	    xf86DrvMsg( pScrn->scrnIndex, X_INFO,
727fe5e51b7Smrg			"[drm] failure adding %d %d byte DMA buffers\n",
728fe5e51b7Smrg			MGA_NUM_BUFFERS, MGA_BUFFER_SIZE );
729fe5e51b7Smrg	    return FALSE;
730fe5e51b7Smrg	}
731fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
732fe5e51b7Smrg		    "[drm] Added %d %d byte DMA buffers\n",
733fe5e51b7Smrg		    count, MGA_BUFFER_SIZE );
734fe5e51b7Smrg
735fe5e51b7Smrg	i = mylog2(pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS);
736fe5e51b7Smrg	if(i < MGA_LOG_MIN_TEX_REGION_SIZE)
737fe5e51b7Smrg	  i = MGA_LOG_MIN_TEX_REGION_SIZE;
738fe5e51b7Smrg	pMGADRIServer->agpTextures.size = (pMGADRIServer->agpTextures.size >> i) << i;
739fe5e51b7Smrg
740fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
741fe5e51b7Smrg			pMGADRIServer->agpTextures.offset,
742fe5e51b7Smrg			pMGADRIServer->agpTextures.size,
743fe5e51b7Smrg			DRM_AGP, 0,
744fe5e51b7Smrg			&pMGADRIServer->agpTextures.handle ) < 0 ) {
745fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
746fe5e51b7Smrg			"[agp] Could not add agpTexture mapping\n" );
747fe5e51b7Smrg	    return FALSE;
748fe5e51b7Smrg	}
749fe5e51b7Smrg
750fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
751fe5e51b7Smrg 		    "[agp] agpTexture handle = 0x%08x\n",
752fe5e51b7Smrg		    (unsigned int) pMGADRIServer->agpTextures.handle );
753fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
754fe5e51b7Smrg		    "[agp] agpTexture size: %d kb\n", pMGADRIServer->agpTextures.size/1024 );
755fe5e51b7Smrg
756fe5e51b7Smrg	pMGADRIServer->registers.size = MGAIOMAPSIZE;
757fe5e51b7Smrg
758fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
759fe5e51b7Smrg			(drm_handle_t) MGA_IO_ADDRESS(pMga),
760fe5e51b7Smrg			pMGADRIServer->registers.size,
761fe5e51b7Smrg			DRM_REGISTERS, DRM_READ_ONLY,
762fe5e51b7Smrg			&pMGADRIServer->registers.handle ) < 0 ) {
763fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
764fe5e51b7Smrg			"[drm] Could not add MMIO registers mapping\n" );
765fe5e51b7Smrg	    return FALSE;
766fe5e51b7Smrg	}
767fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
768fe5e51b7Smrg 		    "[drm] Registers handle = 0x%08x\n",
769fe5e51b7Smrg		    (unsigned int) pMGADRIServer->registers.handle );
770fe5e51b7Smrg
771fe5e51b7Smrg	pMGADRIServer->status.size = SAREA_MAX;
772fe5e51b7Smrg
773fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD, 0, pMGADRIServer->status.size,
774fe5e51b7Smrg			DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL,
775fe5e51b7Smrg			&pMGADRIServer->status.handle ) < 0 ) {
776fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
777fe5e51b7Smrg			"[drm] Could not add status page mapping\n" );
778fe5e51b7Smrg	    return FALSE;
779fe5e51b7Smrg	}
780fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
781fe5e51b7Smrg 		    "[drm] Status handle = 0x%08x\n",
782fe5e51b7Smrg		    (unsigned int) pMGADRIServer->status.handle );
783fe5e51b7Smrg    }
784fe5e51b7Smrg
785fe5e51b7Smrg    return TRUE;
786fe5e51b7Smrg}
787fe5e51b7Smrg
788fe5e51b7Smrgstatic Bool MGADRIKernelInit( ScreenPtr pScreen )
789fe5e51b7Smrg{
790fe5e51b7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
791fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
792fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
793fe5e51b7Smrg   drm_mga_init_t init;
794fe5e51b7Smrg   int ret;
795fe5e51b7Smrg
796fe5e51b7Smrg
797fe5e51b7Smrg   if (!pMga->chip_attribs->dri_capable) {
798fe5e51b7Smrg       return FALSE;
799fe5e51b7Smrg   }
800fe5e51b7Smrg
801fe5e51b7Smrg   memset( &init, 0, sizeof(drm_mga_init_t) );
802fe5e51b7Smrg
803fe5e51b7Smrg   init.func = MGA_INIT_DMA;
804fe5e51b7Smrg   init.sarea_priv_offset = sizeof(XF86DRISAREARec);
805fe5e51b7Smrg   init.chipset = pMga->chip_attribs->dri_chipset;
806fe5e51b7Smrg   init.sgram = !pMga->HasSDRAM;
807fe5e51b7Smrg
808fe5e51b7Smrg   init.maccess = pMga->MAccess;
809fe5e51b7Smrg
810fe5e51b7Smrg   init.fb_cpp		= pScrn->bitsPerPixel / 8;
811fe5e51b7Smrg   init.front_offset	= pMGADRIServer->frontOffset;
812fe5e51b7Smrg   init.front_pitch	= pMGADRIServer->frontPitch / init.fb_cpp;
813fe5e51b7Smrg   init.back_offset	= pMGADRIServer->backOffset;
814fe5e51b7Smrg   init.back_pitch	= pMGADRIServer->backPitch / init.fb_cpp;
815fe5e51b7Smrg
816fe5e51b7Smrg   init.depth_cpp	= pScrn->bitsPerPixel / 8;
817fe5e51b7Smrg   init.depth_offset	= pMGADRIServer->depthOffset;
818fe5e51b7Smrg   init.depth_pitch	= pMGADRIServer->depthPitch / init.depth_cpp;
819fe5e51b7Smrg
820fe5e51b7Smrg   init.texture_offset[0] = pMGADRIServer->textureOffset;
821fe5e51b7Smrg   init.texture_size[0] = pMGADRIServer->textureSize;
822fe5e51b7Smrg
823fe5e51b7Smrg   init.fb_offset = pMGADRIServer->fb.handle;
824fe5e51b7Smrg   init.mmio_offset = pMGADRIServer->registers.handle;
825fe5e51b7Smrg   init.status_offset = pMGADRIServer->status.handle;
826fe5e51b7Smrg
827fe5e51b7Smrg   init.warp_offset = pMGADRIServer->warp.handle;
828fe5e51b7Smrg   init.primary_offset = pMGADRIServer->primary.handle;
829fe5e51b7Smrg   init.buffers_offset = pMGADRIServer->buffers.handle;
830fe5e51b7Smrg
831fe5e51b7Smrg   init.texture_offset[1] = pMGADRIServer->agpTextures.handle;
832fe5e51b7Smrg   init.texture_size[1] = pMGADRIServer->agpTextures.size;
833fe5e51b7Smrg
834fe5e51b7Smrg   ret = drmCommandWrite( pMga->drmFD, DRM_MGA_INIT, &init, sizeof(drm_mga_init_t));
835fe5e51b7Smrg   if ( ret < 0 ) {
836fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
837fe5e51b7Smrg		  "[drm] Failed to initialize DMA! (%d)\n", ret );
838fe5e51b7Smrg      return FALSE;
839fe5e51b7Smrg   }
840fe5e51b7Smrg
841fe5e51b7Smrg
842fe5e51b7Smrg   return TRUE;
843fe5e51b7Smrg}
844fe5e51b7Smrg
845fe5e51b7Smrg/* FIXME: This function uses the DRM to get the IRQ, but the pci_device
846fe5e51b7Smrg * FIXME: structure (PciInfo) already has that information.
847fe5e51b7Smrg */
848fe5e51b7Smrgstatic void MGADRIIrqInit(MGAPtr pMga, ScreenPtr pScreen)
849fe5e51b7Smrg{
850fe5e51b7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
851fe5e51b7Smrg
852fe5e51b7Smrg   if (!pMga->irq) {
853fe5e51b7Smrg      pMga->irq = drmGetInterruptFromBusID(pMga->drmFD,
854fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
855fe5e51b7Smrg					   ((pMga->PciInfo->domain << 8) |
856fe5e51b7Smrg					    pMga->PciInfo->bus),
857fe5e51b7Smrg					   pMga->PciInfo->dev,
858fe5e51b7Smrg					   pMga->PciInfo->func
859fe5e51b7Smrg#else
860fe5e51b7Smrg	 ((pciConfigPtr)pMga->PciInfo->thisCard)->busnum,
861fe5e51b7Smrg	 ((pciConfigPtr)pMga->PciInfo->thisCard)->devnum,
862fe5e51b7Smrg	 ((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum
863fe5e51b7Smrg#endif
864fe5e51b7Smrg					   );
865fe5e51b7Smrg
866fe5e51b7Smrg      if((drmCtlInstHandler(pMga->drmFD, pMga->irq)) != 0) {
867fe5e51b7Smrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
868fe5e51b7Smrg		    "[drm] failure adding irq handler, "
869fe5e51b7Smrg		    "there is a device already using that irq\n"
870fe5e51b7Smrg		    "[drm] falling back to irq-free operation\n");
871fe5e51b7Smrg	 pMga->irq = 0;
872fe5e51b7Smrg      } else {
873fe5e51b7Smrg          pMga->reg_ien = INREG( MGAREG_IEN );
874fe5e51b7Smrg      }
875fe5e51b7Smrg   }
876fe5e51b7Smrg
877fe5e51b7Smrg   if (pMga->irq)
878fe5e51b7Smrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
879fe5e51b7Smrg		 "[drm] dma control initialized, using IRQ %d\n",
880fe5e51b7Smrg		 pMga->irq);
881fe5e51b7Smrg}
882fe5e51b7Smrg
883fe5e51b7Smrgstatic Bool MGADRIBuffersInit( ScreenPtr pScreen )
884fe5e51b7Smrg{
885fe5e51b7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
886fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
887fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
888fe5e51b7Smrg
889fe5e51b7Smrg
890fe5e51b7Smrg   pMGADRIServer->drmBuffers = drmMapBufs( pMga->drmFD );
891fe5e51b7Smrg   if ( !pMGADRIServer->drmBuffers ) {
892fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_ERROR,
893fe5e51b7Smrg		    "[drm] Failed to map DMA buffers list\n" );
894fe5e51b7Smrg	return FALSE;
895fe5e51b7Smrg    }
896fe5e51b7Smrg    xf86DrvMsg( pScreen->myNum, X_INFO,
897fe5e51b7Smrg		"[drm] Mapped %d DMA buffers\n",
898fe5e51b7Smrg		pMGADRIServer->drmBuffers->count );
899fe5e51b7Smrg
900fe5e51b7Smrg    return TRUE;
901fe5e51b7Smrg}
902fe5e51b7Smrg
903fe5e51b7Smrg#ifdef USE_XAA
904fe5e51b7Smrgstatic void MGADRIInitBuffersXAA(WindowPtr pWin, RegionPtr prgn,
905fe5e51b7Smrg                                 CARD32 index)
906fe5e51b7Smrg{
907fe5e51b7Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
908fe5e51b7Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
909fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
910fe5e51b7Smrg    BoxPtr pbox = REGION_RECTS(prgn);
911fe5e51b7Smrg    int nbox  = REGION_NUM_RECTS(prgn);
912fe5e51b7Smrg    XAAInfoRecPtr xaa = pMga->AccelInfoRec;
913fe5e51b7Smrg
914fe5e51b7Smrg    CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn);
915fe5e51b7Smrg
916fe5e51b7Smrg    xaa->SetupForSolidFill(pScrn, 0, GXcopy, -1);
917fe5e51b7Smrg
918fe5e51b7Smrg    while (nbox--) {
919fe5e51b7Smrg        MGASelectBuffer(pScrn, MGA_BACK);
920fe5e51b7Smrg        xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
921fe5e51b7Smrg                                     pbox->x2-pbox->x1, pbox->y2-pbox->y1);
922fe5e51b7Smrg        MGASelectBuffer(pScrn, MGA_DEPTH);
923fe5e51b7Smrg        xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
924fe5e51b7Smrg                                     pbox->x2-pbox->x1, pbox->y2-pbox->y1);
925fe5e51b7Smrg        pbox++;
926fe5e51b7Smrg    }
927fe5e51b7Smrg
928fe5e51b7Smrg    MGASelectBuffer(pScrn, MGA_FRONT);
929fe5e51b7Smrg
930fe5e51b7Smrg    pMga->AccelInfoRec->NeedToSync = TRUE;
931fe5e51b7Smrg}
932fe5e51b7Smrg#endif
933fe5e51b7Smrg
934fe5e51b7Smrg#ifdef USE_EXA
935fe5e51b7Smrgstatic void MGADRIInitBuffersEXA(WindowPtr pWin, RegionPtr prgn,
936fe5e51b7Smrg                                 CARD32 index)
937fe5e51b7Smrg{
938fe5e51b7Smrg    /* FIXME */
939fe5e51b7Smrg}
940fe5e51b7Smrg#endif
941fe5e51b7Smrg
942fe5e51b7Smrg#ifdef USE_XAA
943fe5e51b7Smrg/*
944fe5e51b7Smrg  This routine is a modified form of XAADoBitBlt with the calls to
945fe5e51b7Smrg  ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
946fe5e51b7Smrg  instead of destination. My origin is upside down so the ydir cases
947fe5e51b7Smrg  are reversed.
948fe5e51b7Smrg*/
949fe5e51b7Smrgstatic void MGADRIMoveBuffersXAA(WindowPtr pParent, DDXPointRec ptOldOrg,
950fe5e51b7Smrg                                 RegionPtr prgnSrc, CARD32 index)
951fe5e51b7Smrg{
952fe5e51b7Smrg    ScreenPtr pScreen = pParent->drawable.pScreen;
953fe5e51b7Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
954fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
955fe5e51b7Smrg    int nbox;
956fe5e51b7Smrg    BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
957fe5e51b7Smrg    DDXPointPtr pptTmp, pptNew1, pptNew2;
958fe5e51b7Smrg    int xdir, ydir;
959fe5e51b7Smrg    int dx, dy;
960fe5e51b7Smrg    DDXPointPtr pptSrc;
961fe5e51b7Smrg    int screenwidth = pScrn->virtualX;
962fe5e51b7Smrg    int screenheight = pScrn->virtualY;
963fe5e51b7Smrg    XAAInfoRecPtr xaa = pMga->AccelInfoRec;
964fe5e51b7Smrg
965fe5e51b7Smrg    CHECK_DMA_QUIESCENT(pMga, pScrn);
966fe5e51b7Smrg
967fe5e51b7Smrg    pbox = REGION_RECTS(prgnSrc);
968fe5e51b7Smrg    nbox = REGION_NUM_RECTS(prgnSrc);
969fe5e51b7Smrg    pboxNew1 = 0;
970fe5e51b7Smrg    pptNew1 = 0;
971fe5e51b7Smrg    pboxNew2 = 0;
972fe5e51b7Smrg    pboxNew2 = 0;
973fe5e51b7Smrg    pptSrc = &ptOldOrg;
974fe5e51b7Smrg
975fe5e51b7Smrg    dx = pParent->drawable.x - ptOldOrg.x;
976fe5e51b7Smrg    dy = pParent->drawable.y - ptOldOrg.y;
977fe5e51b7Smrg
978fe5e51b7Smrg    /* If the copy will overlap in Y, reverse the order */
979fe5e51b7Smrg    if (dy>0) {
980fe5e51b7Smrg        ydir = -1;
981fe5e51b7Smrg
982fe5e51b7Smrg        if (nbox>1) {
983fe5e51b7Smrg	    /* Keep ordering in each band, reverse order of bands */
984fe5e51b7Smrg	    pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
985fe5e51b7Smrg	    if (!pboxNew1) return;
986fe5e51b7Smrg	    pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
987fe5e51b7Smrg	    if (!pptNew1) {
988fe5e51b7Smrg	        DEALLOCATE_LOCAL(pboxNew1);
989fe5e51b7Smrg	        return;
990fe5e51b7Smrg	    }
991fe5e51b7Smrg	    pboxBase = pboxNext = pbox+nbox-1;
992fe5e51b7Smrg	    while (pboxBase >= pbox) {
993fe5e51b7Smrg	        while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
994fe5e51b7Smrg		  pboxNext--;
995fe5e51b7Smrg	        pboxTmp = pboxNext+1;
996fe5e51b7Smrg	        pptTmp = pptSrc + (pboxTmp - pbox);
997fe5e51b7Smrg	        while (pboxTmp <= pboxBase) {
998fe5e51b7Smrg		    *pboxNew1++ = *pboxTmp++;
999fe5e51b7Smrg		    *pptNew1++ = *pptTmp++;
1000fe5e51b7Smrg		}
1001fe5e51b7Smrg	        pboxBase = pboxNext;
1002fe5e51b7Smrg	    }
1003fe5e51b7Smrg	    pboxNew1 -= nbox;
1004fe5e51b7Smrg	    pbox = pboxNew1;
1005fe5e51b7Smrg	    pptNew1 -= nbox;
1006fe5e51b7Smrg	    pptSrc = pptNew1;
1007fe5e51b7Smrg	}
1008fe5e51b7Smrg    } else {
1009fe5e51b7Smrg        /* No changes required */
1010fe5e51b7Smrg        ydir = 1;
1011fe5e51b7Smrg    }
1012fe5e51b7Smrg
1013fe5e51b7Smrg    /* If the regions will overlap in X, reverse the order */
1014fe5e51b7Smrg    if (dx>0) {
1015fe5e51b7Smrg        xdir = -1;
1016fe5e51b7Smrg
1017fe5e51b7Smrg        if (nbox > 1) {
1018fe5e51b7Smrg	    /*reverse orderof rects in each band */
1019fe5e51b7Smrg	    pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
1020fe5e51b7Smrg	    pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
1021fe5e51b7Smrg	    if (!pboxNew2 || !pptNew2) {
1022fe5e51b7Smrg	        if (pptNew2) DEALLOCATE_LOCAL(pptNew2);
1023fe5e51b7Smrg	        if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2);
1024fe5e51b7Smrg	        if (pboxNew1) {
1025fe5e51b7Smrg		    DEALLOCATE_LOCAL(pptNew1);
1026fe5e51b7Smrg		    DEALLOCATE_LOCAL(pboxNew1);
1027fe5e51b7Smrg		}
1028fe5e51b7Smrg	       return;
1029fe5e51b7Smrg	    }
1030fe5e51b7Smrg	    pboxBase = pboxNext = pbox;
1031fe5e51b7Smrg	    while (pboxBase < pbox+nbox) {
1032fe5e51b7Smrg	        while ((pboxNext < pbox+nbox) &&
1033fe5e51b7Smrg		       (pboxNext->y1 == pboxBase->y1))
1034fe5e51b7Smrg		  pboxNext++;
1035fe5e51b7Smrg	        pboxTmp = pboxNext;
1036fe5e51b7Smrg	        pptTmp = pptSrc + (pboxTmp - pbox);
1037fe5e51b7Smrg	        while (pboxTmp != pboxBase) {
1038fe5e51b7Smrg		    *pboxNew2++ = *--pboxTmp;
1039fe5e51b7Smrg		    *pptNew2++ = *--pptTmp;
1040fe5e51b7Smrg		}
1041fe5e51b7Smrg	        pboxBase = pboxNext;
1042fe5e51b7Smrg	    }
1043fe5e51b7Smrg	    pboxNew2 -= nbox;
1044fe5e51b7Smrg	    pbox = pboxNew2;
1045fe5e51b7Smrg	    pptNew2 -= nbox;
1046fe5e51b7Smrg	    pptSrc = pptNew2;
1047fe5e51b7Smrg	}
1048fe5e51b7Smrg    } else {
1049fe5e51b7Smrg        /* No changes are needed */
1050fe5e51b7Smrg        xdir = 1;
1051fe5e51b7Smrg    }
1052fe5e51b7Smrg
1053fe5e51b7Smrg    xaa->SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);
1054fe5e51b7Smrg    for ( ; nbox-- ; pbox++) {
1055fe5e51b7Smrg	 int x1 = pbox->x1;
1056fe5e51b7Smrg	 int y1 = pbox->y1;
1057fe5e51b7Smrg	 int destx = x1 + dx;
1058fe5e51b7Smrg	 int desty = y1 + dy;
1059fe5e51b7Smrg	 int w = pbox->x2 - x1 + 1;
1060fe5e51b7Smrg	 int h = pbox->y2 - y1 + 1;
1061fe5e51b7Smrg
1062fe5e51b7Smrg	 if ( destx < 0 ) x1 -= destx, w += destx, destx = 0;
1063fe5e51b7Smrg	 if ( desty < 0 ) y1 -= desty, h += desty, desty = 0;
1064fe5e51b7Smrg	 if ( destx + w > screenwidth ) w = screenwidth - destx;
1065fe5e51b7Smrg	 if ( desty + h > screenheight ) h = screenheight - desty;
1066fe5e51b7Smrg	 if ( w <= 0 ) continue;
1067fe5e51b7Smrg	 if ( h <= 0 ) continue;
1068fe5e51b7Smrg
1069fe5e51b7Smrg	 MGASelectBuffer(pScrn, MGA_BACK);
1070fe5e51b7Smrg	 xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
1071fe5e51b7Smrg	 MGASelectBuffer(pScrn, MGA_DEPTH);
1072fe5e51b7Smrg	 xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
1073fe5e51b7Smrg    }
1074fe5e51b7Smrg    MGASelectBuffer(pScrn, MGA_FRONT);
1075fe5e51b7Smrg
1076fe5e51b7Smrg    if (pboxNew2) {
1077fe5e51b7Smrg        DEALLOCATE_LOCAL(pptNew2);
1078fe5e51b7Smrg        DEALLOCATE_LOCAL(pboxNew2);
1079fe5e51b7Smrg    }
1080fe5e51b7Smrg    if (pboxNew1) {
1081fe5e51b7Smrg        DEALLOCATE_LOCAL(pptNew1);
1082fe5e51b7Smrg        DEALLOCATE_LOCAL(pboxNew1);
1083fe5e51b7Smrg    }
1084fe5e51b7Smrg
1085fe5e51b7Smrg    pMga->AccelInfoRec->NeedToSync = TRUE;
1086fe5e51b7Smrg
1087fe5e51b7Smrg}
1088fe5e51b7Smrg#endif
1089fe5e51b7Smrg
1090fe5e51b7Smrg#ifdef USE_EXA
1091fe5e51b7Smrgstatic void MGADRIMoveBuffersEXA(WindowPtr pParent, DDXPointRec ptOldOrg,
1092fe5e51b7Smrg                                 RegionPtr prgnSrc, CARD32 index)
1093fe5e51b7Smrg{
1094fe5e51b7Smrg    /* FIXME */
1095fe5e51b7Smrg}
1096fe5e51b7Smrg#endif
1097fe5e51b7Smrg
1098fe5e51b7SmrgBool MGADRIScreenInit( ScreenPtr pScreen )
1099fe5e51b7Smrg{
1100fe5e51b7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1101fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
1102fe5e51b7Smrg   DRIInfoPtr pDRIInfo;
1103fe5e51b7Smrg   MGADRIPtr pMGADRI;
1104fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer;
1105fe5e51b7Smrg
1106fe5e51b7Smrg   if (!pMga->chip_attribs->dri_capable) {
1107fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] Direct rendering only supported with G200/G400/G450/G550.\n");
1108fe5e51b7Smrg       return FALSE;
1109fe5e51b7Smrg   }
1110fe5e51b7Smrg
1111fe5e51b7Smrg   /* Check that the GLX, DRI, and DRM modules have been loaded by testing
1112fe5e51b7Smrg    * for canonical symbols in each module.
1113fe5e51b7Smrg    */
1114fe5e51b7Smrg   if ( !xf86LoaderCheckSymbol( "GlxSetVisualConfigs" ) )	return FALSE;
1115fe5e51b7Smrg   if ( !xf86LoaderCheckSymbol( "drmAvailable" ) )		return FALSE;
1116fe5e51b7Smrg   if ( !xf86LoaderCheckSymbol( "DRIQueryVersion" ) ) {
1117fe5e51b7Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
1118fe5e51b7Smrg		  "[dri] MGADRIScreenInit failed (libdri.a too old)\n" );
1119fe5e51b7Smrg      return FALSE;
1120fe5e51b7Smrg   }
1121fe5e51b7Smrg
1122fe5e51b7Smrg   /* Check the DRI version */
1123fe5e51b7Smrg   {
1124fe5e51b7Smrg      int major, minor, patch;
1125fe5e51b7Smrg      DRIQueryVersion( &major, &minor, &patch );
1126fe5e51b7Smrg      if ( major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ) {
1127fe5e51b7Smrg         xf86DrvMsg( pScreen->myNum, X_ERROR,
1128fe5e51b7Smrg		     "[dri] MGADRIScreenInit failed because of a version mismatch.\n"
1129fe5e51b7Smrg		     "[dri] libdri version = %d.%d.%d but version %d.%d.x is needed.\n"
1130fe5e51b7Smrg		     "[dri] Disabling the DRI.\n",
1131fe5e51b7Smrg		     major, minor, patch,
1132fe5e51b7Smrg                     DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION );
1133fe5e51b7Smrg         return FALSE;
1134fe5e51b7Smrg      }
1135fe5e51b7Smrg   }
1136fe5e51b7Smrg
1137fe5e51b7Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
1138fe5e51b7Smrg	       "[drm] bpp: %d depth: %d\n",
1139fe5e51b7Smrg	       pScrn->bitsPerPixel, pScrn->depth );
1140fe5e51b7Smrg
1141fe5e51b7Smrg   if ( (pScrn->bitsPerPixel / 8) != 2 &&
1142fe5e51b7Smrg	(pScrn->bitsPerPixel / 8) != 4 ) {
1143fe5e51b7Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
1144fe5e51b7Smrg		  "[dri] Direct rendering only supported in 16 and 32 bpp modes\n" );
1145fe5e51b7Smrg      return FALSE;
1146fe5e51b7Smrg   }
1147fe5e51b7Smrg
1148fe5e51b7Smrg   pDRIInfo = DRICreateInfoRec();
1149fe5e51b7Smrg   if ( !pDRIInfo ) {
1150fe5e51b7Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
1151fe5e51b7Smrg		  "[dri] DRICreateInfoRec() failed\n" );
1152fe5e51b7Smrg      return FALSE;
1153fe5e51b7Smrg   }
1154fe5e51b7Smrg   pMga->pDRIInfo = pDRIInfo;
1155fe5e51b7Smrg
1156fe5e51b7Smrg   pDRIInfo->drmDriverName = MGAKernelDriverName;
1157fe5e51b7Smrg   pDRIInfo->clientDriverName = MGAClientDriverName;
1158fe5e51b7Smrg   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
1159fe5e51b7Smrg      pDRIInfo->busIdString = DRICreatePCIBusID(pMga->PciInfo);
1160fe5e51b7Smrg   } else {
1161fe5e51b7Smrg      pDRIInfo->busIdString = xalloc(64);
1162fe5e51b7Smrg      sprintf( pDRIInfo->busIdString, "PCI:%d:%d:%d",
1163fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1164fe5e51b7Smrg	       ((pMga->PciInfo->domain << 8) | pMga->PciInfo->bus),
1165fe5e51b7Smrg	       pMga->PciInfo->dev, pMga->PciInfo->func
1166fe5e51b7Smrg#else
1167fe5e51b7Smrg	       ((pciConfigPtr)pMga->PciInfo->thisCard)->busnum,
1168fe5e51b7Smrg	       ((pciConfigPtr)pMga->PciInfo->thisCard)->devnum,
1169fe5e51b7Smrg	       ((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum
1170fe5e51b7Smrg#endif
1171fe5e51b7Smrg	       );
1172fe5e51b7Smrg   }
1173fe5e51b7Smrg   pDRIInfo->ddxDriverMajorVersion = PACKAGE_VERSION_MAJOR;
1174fe5e51b7Smrg   pDRIInfo->ddxDriverMinorVersion = PACKAGE_VERSION_MINOR;
1175fe5e51b7Smrg   pDRIInfo->ddxDriverPatchVersion = PACKAGE_VERSION_PATCHLEVEL;
1176fe5e51b7Smrg   pDRIInfo->frameBufferPhysicalAddress = (void *) pMga->FbAddress;
1177fe5e51b7Smrg   pDRIInfo->frameBufferSize = pMga->FbMapSize;
1178fe5e51b7Smrg   pDRIInfo->frameBufferStride = pScrn->displayWidth*(pScrn->bitsPerPixel/8);
1179fe5e51b7Smrg   pDRIInfo->ddxDrawableTableEntry = MGA_MAX_DRAWABLES;
1180fe5e51b7Smrg
1181fe5e51b7Smrg   pDRIInfo->wrap.ValidateTree = NULL;
1182fe5e51b7Smrg   pDRIInfo->wrap.PostValidateTree = NULL;
1183fe5e51b7Smrg
1184fe5e51b7Smrg   pDRIInfo->createDummyCtx = TRUE;
1185fe5e51b7Smrg   pDRIInfo->createDummyCtxPriv = FALSE;
1186fe5e51b7Smrg
1187fe5e51b7Smrg   if ( SAREA_MAX_DRAWABLES < MGA_MAX_DRAWABLES ) {
1188fe5e51b7Smrg      pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
1189fe5e51b7Smrg   } else {
1190fe5e51b7Smrg      pDRIInfo->maxDrawableTableEntry = MGA_MAX_DRAWABLES;
1191fe5e51b7Smrg   }
1192fe5e51b7Smrg
1193fe5e51b7Smrg   /* For now the mapping works by using a fixed size defined
1194fe5e51b7Smrg    * in the SAREA header.
1195fe5e51b7Smrg    */
1196fe5e51b7Smrg   if ( sizeof(XF86DRISAREARec) + sizeof(MGASAREAPrivRec) > SAREA_MAX ) {
1197fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
1198fe5e51b7Smrg		  "[drm] Data does not fit in SAREA\n" );
1199fe5e51b7Smrg      return FALSE;
1200fe5e51b7Smrg   }
1201fe5e51b7Smrg
1202fe5e51b7Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1203fe5e51b7Smrg	       "[drm] Sarea %d+%d: %d\n",
1204fe5e51b7Smrg	       (int)sizeof(XF86DRISAREARec), (int)sizeof(MGASAREAPrivRec),
1205fe5e51b7Smrg	       (int)sizeof(XF86DRISAREARec) + (int)sizeof(MGASAREAPrivRec) );
1206fe5e51b7Smrg
1207fe5e51b7Smrg   pDRIInfo->SAREASize = SAREA_MAX;
1208fe5e51b7Smrg
1209fe5e51b7Smrg   pMGADRI = (MGADRIPtr)xcalloc( sizeof(MGADRIRec), 1 );
1210fe5e51b7Smrg   if ( !pMGADRI ) {
1211fe5e51b7Smrg      DRIDestroyInfoRec( pMga->pDRIInfo );
1212fe5e51b7Smrg      pMga->pDRIInfo = 0;
1213fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
1214fe5e51b7Smrg		  "[drm] Failed to allocate memory for private record\n" );
1215fe5e51b7Smrg      return FALSE;
1216fe5e51b7Smrg   }
1217fe5e51b7Smrg
1218fe5e51b7Smrg   pMGADRIServer = (MGADRIServerPrivatePtr)
1219fe5e51b7Smrg      xcalloc( sizeof(MGADRIServerPrivateRec), 1 );
1220fe5e51b7Smrg   if ( !pMGADRIServer ) {
1221fe5e51b7Smrg      xfree( pMGADRI );
1222fe5e51b7Smrg      DRIDestroyInfoRec( pMga->pDRIInfo );
1223fe5e51b7Smrg      pMga->pDRIInfo = 0;
1224fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
1225fe5e51b7Smrg		  "[drm] Failed to allocate memory for private record\n" );
1226fe5e51b7Smrg      return FALSE;
1227fe5e51b7Smrg   }
1228fe5e51b7Smrg   pMga->DRIServerInfo = pMGADRIServer;
1229fe5e51b7Smrg
1230fe5e51b7Smrg   pDRIInfo->devPrivate = pMGADRI;
1231fe5e51b7Smrg   pDRIInfo->devPrivateSize = sizeof(MGADRIRec);
1232fe5e51b7Smrg   pDRIInfo->contextSize = sizeof(MGADRIContextRec);
1233fe5e51b7Smrg
1234fe5e51b7Smrg   pDRIInfo->CreateContext = MGACreateContext;
1235fe5e51b7Smrg   pDRIInfo->DestroyContext = MGADestroyContext;
1236fe5e51b7Smrg   if ( xf86IsEntityShared( pScrn->entityList[0] )
1237fe5e51b7Smrg		&& pMga->DualHeadEnabled) {
1238fe5e51b7Smrg      pDRIInfo->SwapContext = MGADRISwapContextShared;
1239fe5e51b7Smrg   } else {
1240fe5e51b7Smrg      pDRIInfo->SwapContext = MGADRISwapContext;
1241fe5e51b7Smrg   }
1242fe5e51b7Smrg
1243fe5e51b7Smrg#ifdef USE_EXA
1244fe5e51b7Smrg    if (pMga->Exa) {
1245fe5e51b7Smrg        pDRIInfo->InitBuffers = MGADRIInitBuffersEXA;
1246fe5e51b7Smrg        pDRIInfo->MoveBuffers = MGADRIMoveBuffersEXA;
1247fe5e51b7Smrg    } else {
1248fe5e51b7Smrg#endif
1249fe5e51b7Smrg#ifdef USE_XAA
1250fe5e51b7Smrg        pDRIInfo->InitBuffers = MGADRIInitBuffersXAA;
1251fe5e51b7Smrg        pDRIInfo->MoveBuffers = MGADRIMoveBuffersXAA;
1252fe5e51b7Smrg#endif
1253fe5e51b7Smrg#ifdef USE_EXA
1254fe5e51b7Smrg    }
1255fe5e51b7Smrg#endif
1256fe5e51b7Smrg
1257fe5e51b7Smrg   pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
1258fe5e51b7Smrg
1259fe5e51b7Smrg   if ( !DRIScreenInit( pScreen, pDRIInfo, &pMga->drmFD ) ) {
1260fe5e51b7Smrg      xfree( pMGADRIServer );
1261fe5e51b7Smrg      pMga->DRIServerInfo = 0;
1262fe5e51b7Smrg      xfree( pDRIInfo->devPrivate );
1263fe5e51b7Smrg      pDRIInfo->devPrivate = 0;
1264fe5e51b7Smrg      DRIDestroyInfoRec( pMga->pDRIInfo );
1265fe5e51b7Smrg      pMga->pDRIInfo = 0;
1266fe5e51b7Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
1267fe5e51b7Smrg		  "[drm] DRIScreenInit failed.  Disabling DRI.\n" );
1268fe5e51b7Smrg      return FALSE;
1269fe5e51b7Smrg   }
1270fe5e51b7Smrg
1271fe5e51b7Smrg   /* Check the DRM versioning */
1272fe5e51b7Smrg   {
1273fe5e51b7Smrg      drmVersionPtr version;
1274fe5e51b7Smrg
1275fe5e51b7Smrg      /* Check the DRM lib version.
1276fe5e51b7Smrg	 drmGetLibVersion was not supported in version 1.0, so check for
1277fe5e51b7Smrg	 symbol first to avoid possible crash or hang.
1278fe5e51b7Smrg       */
1279fe5e51b7Smrg      if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
1280fe5e51b7Smrg         version = drmGetLibVersion(pMga->drmFD);
1281fe5e51b7Smrg      }
1282fe5e51b7Smrg      else {
1283fe5e51b7Smrg	 /* drmlib version 1.0.0 didn't have the drmGetLibVersion
1284fe5e51b7Smrg	    entry point.  Fake it by allocating a version record
1285fe5e51b7Smrg	    via drmGetVersion and changing it to version 1.0.0
1286fe5e51b7Smrg	  */
1287fe5e51b7Smrg	 version = drmGetVersion(pMga->drmFD);
1288fe5e51b7Smrg	 version->version_major      = 1;
1289fe5e51b7Smrg	 version->version_minor      = 0;
1290fe5e51b7Smrg	 version->version_patchlevel = 0;
1291fe5e51b7Smrg      }
1292fe5e51b7Smrg
1293fe5e51b7Smrg      if (version) {
1294fe5e51b7Smrg	 if (version->version_major != 1 ||
1295fe5e51b7Smrg	     version->version_minor < 1) {
1296fe5e51b7Smrg	     /* incompatible drm library version */
1297fe5e51b7Smrg	    xf86DrvMsg(pScreen->myNum, X_ERROR,
1298fe5e51b7Smrg		       "[dri] MGADRIScreenInit failed because of a version mismatch.\n"
1299fe5e51b7Smrg		       "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
1300fe5e51b7Smrg		       "[dri] Disabling DRI.\n",
1301fe5e51b7Smrg		       version->version_major,
1302fe5e51b7Smrg		       version->version_minor,
1303fe5e51b7Smrg		       version->version_patchlevel);
1304fe5e51b7Smrg	    drmFreeVersion(version);
1305fe5e51b7Smrg	    MGADRICloseScreen( pScreen );		/* FIXME: ??? */
1306fe5e51b7Smrg	    return FALSE;
1307fe5e51b7Smrg	 }
1308fe5e51b7Smrg	 drmFreeVersion(version);
1309fe5e51b7Smrg      }
1310fe5e51b7Smrg
1311fe5e51b7Smrg      /* Check the MGA DRM version */
1312fe5e51b7Smrg      version = drmGetVersion(pMga->drmFD);
1313fe5e51b7Smrg      if ( version ) {
1314fe5e51b7Smrg         if ( version->version_major != 3 ||
1315fe5e51b7Smrg	      version->version_minor < 0 ) {
1316fe5e51b7Smrg            /* incompatible drm version */
1317fe5e51b7Smrg            xf86DrvMsg( pScreen->myNum, X_ERROR,
1318fe5e51b7Smrg			"[dri] MGADRIScreenInit failed because of a version mismatch.\n"
1319fe5e51b7Smrg			"[dri] mga.o kernel module version is %d.%d.%d but version 3.0.x is needed.\n"
1320fe5e51b7Smrg			"[dri] Disabling DRI.\n",
1321fe5e51b7Smrg			version->version_major,
1322fe5e51b7Smrg			version->version_minor,
1323fe5e51b7Smrg			version->version_patchlevel );
1324fe5e51b7Smrg            drmFreeVersion( version );
1325fe5e51b7Smrg	    MGADRICloseScreen( pScreen );		/* FIXME: ??? */
1326fe5e51b7Smrg            return FALSE;
1327fe5e51b7Smrg         }
1328fe5e51b7Smrg	 pMGADRIServer->drm_version_major = version->version_major;
1329fe5e51b7Smrg	 pMGADRIServer->drm_version_minor = version->version_minor;
1330fe5e51b7Smrg
1331fe5e51b7Smrg         drmFreeVersion( version );
1332fe5e51b7Smrg      }
1333fe5e51b7Smrg   }
1334fe5e51b7Smrg
1335fe5e51b7Smrg   if ( (pMga->bios.host_interface == MGA_HOST_PCI) &&
1336fe5e51b7Smrg	((pMGADRIServer->drm_version_minor < 2) || pMga->useOldDmaInit) ) {
1337fe5e51b7Smrg       /* PCI cards are supported if the DRM version is at least 3.2 and the
1338fe5e51b7Smrg	* user has not explicitly disabled the new DMA init path (i.e., to
1339fe5e51b7Smrg	* support old version of the client-side driver that don't use the
1340fe5e51b7Smrg	* new features of the 3.2 DRM).
1341fe5e51b7Smrg	*/
1342fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1343fe5e51b7Smrg		  "[drm] Direct rendering on PCI cards requires DRM version 3.2 or higher\n");
1344fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1345fe5e51b7Smrg		  "[drm] and a recent client-side driver.  Also make sure that 'OldDmaInit'\n");
1346fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1347fe5e51b7Smrg		  "[drm] is not selected in xorg.conf.'\n");
1348fe5e51b7Smrg       return FALSE;
1349fe5e51b7Smrg   }
1350fe5e51b7Smrg
1351fe5e51b7Smrg
1352fe5e51b7Smrg   if ( !MGADRIBootstrapDMA( pScreen ) ) {
1353fe5e51b7Smrg      DRICloseScreen( pScreen );
1354fe5e51b7Smrg      return FALSE;
1355fe5e51b7Smrg   }
1356fe5e51b7Smrg
1357fe5e51b7Smrg   {
1358fe5e51b7Smrg       void *scratch_ptr;
1359fe5e51b7Smrg       int scratch_int;
1360fe5e51b7Smrg
1361fe5e51b7Smrg       DRIGetDeviceInfo(pScreen, &pMGADRIServer->fb.handle,
1362fe5e51b7Smrg			&scratch_int, &scratch_int,
1363fe5e51b7Smrg			&scratch_int, &scratch_int,
1364fe5e51b7Smrg			&scratch_ptr);
1365fe5e51b7Smrg   }
1366fe5e51b7Smrg
1367fe5e51b7Smrg   if ( !MGAInitVisualConfigs( pScreen ) ) {
1368fe5e51b7Smrg      DRICloseScreen( pScreen );
1369fe5e51b7Smrg      return FALSE;
1370fe5e51b7Smrg   }
1371fe5e51b7Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n" );
1372fe5e51b7Smrg
1373fe5e51b7Smrg   return TRUE;
1374fe5e51b7Smrg}
1375fe5e51b7Smrg
1376fe5e51b7Smrg
1377fe5e51b7SmrgBool MGADRIFinishScreenInit( ScreenPtr pScreen )
1378fe5e51b7Smrg{
1379fe5e51b7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1380fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
1381fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
1382fe5e51b7Smrg   MGADRIPtr pMGADRI;
1383fe5e51b7Smrg   int i;
1384fe5e51b7Smrg
1385fe5e51b7Smrg   if ( !pMga->pDRIInfo )
1386fe5e51b7Smrg      return FALSE;
1387fe5e51b7Smrg
1388fe5e51b7Smrg   pMGADRI = (MGADRIPtr)pMga->pDRIInfo->devPrivate;
1389fe5e51b7Smrg
1390fe5e51b7Smrg   pMga->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
1391fe5e51b7Smrg
1392fe5e51b7Smrg   /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
1393fe5e51b7Smrg    * because *DRIKernelInit requires that the hardware lock is held by
1394fe5e51b7Smrg    * the X server, and the first time the hardware lock is grabbed is
1395fe5e51b7Smrg    * in DRIFinishScreenInit.
1396fe5e51b7Smrg    */
1397fe5e51b7Smrg   if ( !DRIFinishScreenInit( pScreen ) ) {
1398fe5e51b7Smrg      MGADRICloseScreen( pScreen );
1399fe5e51b7Smrg      return FALSE;
1400fe5e51b7Smrg   }
1401fe5e51b7Smrg
1402fe5e51b7Smrg   if ( !MGADRIKernelInit( pScreen ) ) {
1403fe5e51b7Smrg      MGADRICloseScreen( pScreen );
1404fe5e51b7Smrg      return FALSE;
1405fe5e51b7Smrg   }
1406fe5e51b7Smrg
1407fe5e51b7Smrg   if ( !MGADRIBuffersInit( pScreen ) ) {
1408fe5e51b7Smrg      MGADRICloseScreen( pScreen );
1409fe5e51b7Smrg      return FALSE;
1410fe5e51b7Smrg   }
1411fe5e51b7Smrg
1412fe5e51b7Smrg   MGADRIIrqInit(pMga, pScreen);
1413fe5e51b7Smrg
1414fe5e51b7Smrg   pMGADRI->chipset		= pMga->chip_attribs->dri_chipset;
1415fe5e51b7Smrg   pMGADRI->width		= pScrn->virtualX;
1416fe5e51b7Smrg   pMGADRI->height		= pScrn->virtualY;
1417fe5e51b7Smrg   pMGADRI->cpp			= pScrn->bitsPerPixel / 8;
1418fe5e51b7Smrg
1419fe5e51b7Smrg   pMGADRI->agpMode		= pMga->agpMode;
1420fe5e51b7Smrg
1421fe5e51b7Smrg   pMGADRI->frontOffset		= pMGADRIServer->frontOffset;
1422fe5e51b7Smrg   pMGADRI->frontPitch		= pMGADRIServer->frontPitch;
1423fe5e51b7Smrg   pMGADRI->backOffset		= pMGADRIServer->backOffset;
1424fe5e51b7Smrg   pMGADRI->backPitch		= pMGADRIServer->backPitch;
1425fe5e51b7Smrg   pMGADRI->depthOffset		= pMGADRIServer->depthOffset;
1426fe5e51b7Smrg   pMGADRI->depthPitch		= pMGADRIServer->depthPitch;
1427fe5e51b7Smrg   pMGADRI->textureOffset	= pMGADRIServer->textureOffset;
1428fe5e51b7Smrg   pMGADRI->textureSize		= pMGADRIServer->textureSize;
1429fe5e51b7Smrg
1430fe5e51b7Smrg   pMGADRI->agpTextureOffset = (unsigned int)pMGADRIServer->agpTextures.handle;
1431fe5e51b7Smrg   pMGADRI->agpTextureSize = (unsigned int)pMGADRIServer->agpTextures.size;
1432fe5e51b7Smrg
1433fe5e51b7Smrg   pMGADRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
1434fe5e51b7Smrg
1435fe5e51b7Smrg
1436fe5e51b7Smrg   /* Newer versions of the client-side driver do not need these if the
1437fe5e51b7Smrg    * kernel version is high enough to support interrupt based waiting.
1438fe5e51b7Smrg    */
1439fe5e51b7Smrg
1440fe5e51b7Smrg   pMGADRI->registers.handle	= pMGADRIServer->registers.handle;
1441fe5e51b7Smrg   pMGADRI->registers.size	= pMGADRIServer->registers.size;
1442fe5e51b7Smrg   pMGADRI->primary.handle	= pMGADRIServer->primary.handle;
1443fe5e51b7Smrg   pMGADRI->primary.size	= pMGADRIServer->primary.size;
1444fe5e51b7Smrg
1445fe5e51b7Smrg
1446fe5e51b7Smrg   /* These are no longer used by the client-side DRI driver.  They should
1447fe5e51b7Smrg    * be removed in the next release (i.e., 6.9 / 7.0).
1448fe5e51b7Smrg    */
1449fe5e51b7Smrg
1450fe5e51b7Smrg   pMGADRI->status.handle	= pMGADRIServer->status.handle;
1451fe5e51b7Smrg   pMGADRI->status.size		= pMGADRIServer->status.size;
1452fe5e51b7Smrg   pMGADRI->buffers.handle	= pMGADRIServer->buffers.handle;
1453fe5e51b7Smrg   pMGADRI->buffers.size	= pMGADRIServer->buffers.size;
1454fe5e51b7Smrg
1455fe5e51b7Smrg   i = mylog2( pMGADRI->textureSize / MGA_NR_TEX_REGIONS );
1456fe5e51b7Smrg   if ( i < MGA_LOG_MIN_TEX_REGION_SIZE )
1457fe5e51b7Smrg      i = MGA_LOG_MIN_TEX_REGION_SIZE;
1458fe5e51b7Smrg
1459fe5e51b7Smrg   pMGADRI->logTextureGranularity = i;
1460fe5e51b7Smrg   pMGADRI->textureSize = (pMGADRI->textureSize >> i) << i; /* truncate */
1461fe5e51b7Smrg
1462fe5e51b7Smrg   i = mylog2( pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS );
1463fe5e51b7Smrg   if ( i < MGA_LOG_MIN_TEX_REGION_SIZE )
1464fe5e51b7Smrg      i = MGA_LOG_MIN_TEX_REGION_SIZE;
1465fe5e51b7Smrg
1466fe5e51b7Smrg   pMGADRI->logAgpTextureGranularity = i;
1467fe5e51b7Smrg
1468fe5e51b7Smrg   return TRUE;
1469fe5e51b7Smrg}
1470fe5e51b7Smrg
1471fe5e51b7Smrg
1472fe5e51b7Smrgvoid MGADRICloseScreen( ScreenPtr pScreen )
1473fe5e51b7Smrg{
1474fe5e51b7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1475fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
1476fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
1477fe5e51b7Smrg   drm_mga_init_t init;
1478fe5e51b7Smrg
1479fe5e51b7Smrg   if ( pMGADRIServer->drmBuffers ) {
1480fe5e51b7Smrg      drmUnmapBufs( pMGADRIServer->drmBuffers );
1481fe5e51b7Smrg      pMGADRIServer->drmBuffers = NULL;
1482fe5e51b7Smrg   }
1483fe5e51b7Smrg
1484fe5e51b7Smrg   if (pMga->irq) {
1485fe5e51b7Smrg      drmCtlUninstHandler(pMga->drmFD);
1486fe5e51b7Smrg      pMga->irq = 0;
1487fe5e51b7Smrg      pMga->reg_ien = 0;
1488fe5e51b7Smrg   }
1489fe5e51b7Smrg
1490fe5e51b7Smrg   /* Cleanup DMA */
1491fe5e51b7Smrg   memset( &init, 0, sizeof(drm_mga_init_t) );
1492fe5e51b7Smrg   init.func = MGA_CLEANUP_DMA;
1493fe5e51b7Smrg   drmCommandWrite( pMga->drmFD, DRM_MGA_INIT, &init, sizeof(drm_mga_init_t) );
1494fe5e51b7Smrg
1495fe5e51b7Smrg   if ( pMGADRIServer->agp.handle != DRM_AGP_NO_HANDLE ) {
1496fe5e51b7Smrg      drmAgpUnbind( pMga->drmFD, pMGADRIServer->agp.handle );
1497fe5e51b7Smrg      drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle );
1498fe5e51b7Smrg      pMGADRIServer->agp.handle = DRM_AGP_NO_HANDLE;
1499fe5e51b7Smrg      drmAgpRelease( pMga->drmFD );
1500fe5e51b7Smrg   }
1501fe5e51b7Smrg
1502fe5e51b7Smrg   DRICloseScreen( pScreen );
1503fe5e51b7Smrg
1504fe5e51b7Smrg   if ( pMga->pDRIInfo ) {
1505fe5e51b7Smrg      if ( pMga->pDRIInfo->devPrivate ) {
1506fe5e51b7Smrg	 xfree( pMga->pDRIInfo->devPrivate );
1507fe5e51b7Smrg	 pMga->pDRIInfo->devPrivate = 0;
1508fe5e51b7Smrg      }
1509fe5e51b7Smrg      DRIDestroyInfoRec( pMga->pDRIInfo );
1510fe5e51b7Smrg      pMga->pDRIInfo = 0;
1511fe5e51b7Smrg   }
1512fe5e51b7Smrg   if ( pMga->DRIServerInfo ) {
1513fe5e51b7Smrg      xfree( pMga->DRIServerInfo );
1514fe5e51b7Smrg      pMga->DRIServerInfo = 0;
1515fe5e51b7Smrg   }
1516fe5e51b7Smrg   if ( pMga->pVisualConfigs ) {
1517fe5e51b7Smrg      xfree( pMga->pVisualConfigs );
1518fe5e51b7Smrg   }
1519fe5e51b7Smrg   if ( pMga->pVisualConfigsPriv ) {
1520fe5e51b7Smrg      xfree( pMga->pVisualConfigsPriv );
1521fe5e51b7Smrg   }
1522fe5e51b7Smrg}
1523