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