atidri.c revision 32b578d3
1/* -*- mode: c; c-basic-offset: 3 -*- */
2/*
3 * Copyright 2000 Gareth Hughes
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28/*
29 * Authors:
30 *   Gareth Hughes <gareth@valinux.com>
31 *   Leif Delgass <ldelgass@retinalburn.net>
32 */
33
34#include <string.h>
35#include <stdio.h>
36#include <unistd.h>
37
38/* Driver data structures */
39#include "ati.h"
40#include "atibus.h"
41#include "atidri.h"
42#include "atiregs.h"
43#include "atistruct.h"
44
45#include "atimach64io.h"
46#include "atimach64version.h"
47#include "mach64_dri.h"
48#include "mach64_common.h"
49#include "mach64_sarea.h"
50
51/* X and server generic header files */
52#include "xf86.h"
53#include "windowstr.h"
54
55/* GLX/DRI/DRM definitions */
56#define _XF86DRI_SERVER_
57#include "GL/glxtokens.h"
58#include "sarea.h"
59
60static char ATIKernelDriverName[] = "mach64";
61static char ATIClientDriverName[] = "mach64";
62
63/* Initialize the visual configs that are supported by the hardware.
64 * These are combined with the visual configs that the indirect
65 * rendering core supports, and the intersection is exported to the
66 * client.
67 */
68static Bool ATIInitVisualConfigs( ScreenPtr pScreen )
69{
70   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
71   ATIPtr pATI = ATIPTR(pScreenInfo);
72   int numConfigs = 0;
73   __GLXvisualConfig *pConfigs = NULL;
74   ATIConfigPrivPtr pATIConfigs = NULL;
75   ATIConfigPrivPtr *pATIConfigPtrs = NULL;
76   int i, accum, stencil, db;
77
78   switch ( pATI->bitsPerPixel ) {
79   case 8:  /* 8bpp mode is not support */
80   case 15: /* FIXME */
81   case 24: /* FIXME */
82      xf86DrvMsg(pScreen->myNum, X_ERROR,
83		 "[dri] ATIInitVisualConfigs failed (%d bpp not supported).  "
84		 "Disabling DRI.\n", pATI->bitsPerPixel);
85      return FALSE;
86
87#define ATI_USE_ACCUM   1
88#define ATI_USE_STENCIL 1
89
90   case 16:
91
92      if ( pATI->depth != 16) {
93	 xf86DrvMsg(pScreen->myNum, X_ERROR,
94		    "[dri] ATIInitVisualConfigs failed (depth %d at 16 bpp not supported).  "
95		     "Disabling DRI.\n", pATI->depth);
96	 return FALSE;
97      }
98
99      numConfigs = 1;
100      if ( ATI_USE_ACCUM )   numConfigs *= 2;
101      if ( ATI_USE_STENCIL ) numConfigs *= 2;
102      numConfigs *= 2; /* single- and double-buffered */
103
104      pConfigs = (__GLXvisualConfig*)
105	 xnfcalloc( sizeof(__GLXvisualConfig), numConfigs );
106      if ( !pConfigs ) {
107	 return FALSE;
108      }
109      pATIConfigs = (ATIConfigPrivPtr)
110	 xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs );
111      if ( !pATIConfigs ) {
112	 xfree( pConfigs );
113	 return FALSE;
114      }
115      pATIConfigPtrs = (ATIConfigPrivPtr*)
116	 xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs );
117      if ( !pATIConfigPtrs ) {
118	 xfree( pConfigs );
119	 xfree( pATIConfigs );
120	 return FALSE;
121      }
122
123      i = 0;
124      for (db = 1; db >= 0; db--) {
125	 for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) {
126	    for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) {
127	       pATIConfigPtrs[i] = &pATIConfigs[i];
128
129	       pConfigs[i].vid			= -1;
130	       pConfigs[i].class		= -1;
131	       pConfigs[i].rgba			= TRUE;
132	       pConfigs[i].redSize		= 5;
133	       pConfigs[i].greenSize		= 6;
134	       pConfigs[i].blueSize		= 5;
135	       pConfigs[i].alphaSize		= 0;
136	       pConfigs[i].redMask		= 0x0000F800;
137	       pConfigs[i].greenMask		= 0x000007E0;
138	       pConfigs[i].blueMask		= 0x0000001F;
139	       pConfigs[i].alphaMask		= 0x00000000;
140	       if ( accum ) {	/* Simulated in software */
141		  pConfigs[i].accumRedSize	= 16;
142		  pConfigs[i].accumGreenSize	= 16;
143		  pConfigs[i].accumBlueSize	= 16;
144		  pConfigs[i].accumAlphaSize	= 0;
145	       } else {
146		  pConfigs[i].accumRedSize	= 0;
147		  pConfigs[i].accumGreenSize	= 0;
148		  pConfigs[i].accumBlueSize	= 0;
149		  pConfigs[i].accumAlphaSize	= 0;
150	       }
151	       pConfigs[i].doubleBuffer		= db ? TRUE : FALSE;
152	       pConfigs[i].stereo		= FALSE;
153	       pConfigs[i].bufferSize		= 16;
154	       pConfigs[i].depthSize		= 16;
155	       if ( stencil ) {	/* Simulated in software */
156		  pConfigs[i].stencilSize	= 8;
157	       } else {
158		  pConfigs[i].stencilSize	= 0;
159	       }
160	       pConfigs[i].auxBuffers		= 0;
161	       pConfigs[i].level		= 0;
162	       if ( accum || stencil ) {
163		  pConfigs[i].visualRating	= GLX_SLOW_CONFIG;
164	       } else {
165		  pConfigs[i].visualRating	= GLX_NONE;
166	       }
167	       pConfigs[i].transparentPixel	= GLX_NONE;
168	       pConfigs[i].transparentRed	= 0;
169	       pConfigs[i].transparentGreen	= 0;
170	       pConfigs[i].transparentBlue	= 0;
171	       pConfigs[i].transparentAlpha	= 0;
172	       pConfigs[i].transparentIndex	= 0;
173	       i++;
174	    }
175	 }
176      }
177      break;
178
179   case 32:
180      numConfigs = 1;
181      if ( ATI_USE_ACCUM )   numConfigs *= 2;
182      if ( ATI_USE_STENCIL ) numConfigs *= 2;
183      numConfigs *= 2; /* single- and double-buffered */
184
185      pConfigs = (__GLXvisualConfig*)
186	 xnfcalloc( sizeof(__GLXvisualConfig), numConfigs );
187      if ( !pConfigs ) {
188	 return FALSE;
189      }
190      pATIConfigs = (ATIConfigPrivPtr)
191	 xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs );
192      if ( !pATIConfigs ) {
193	 xfree( pConfigs );
194	 return FALSE;
195      }
196      pATIConfigPtrs = (ATIConfigPrivPtr*)
197	 xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs );
198      if ( !pATIConfigPtrs ) {
199	 xfree( pConfigs );
200	 xfree( pATIConfigs );
201	 return FALSE;
202      }
203
204      i = 0;
205      for (db = 1; db >= 0; db--) {
206	 for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) {
207	    for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) {
208	       pATIConfigPtrs[i] = &pATIConfigs[i];
209
210	       pConfigs[i].vid			= -1;
211	       pConfigs[i].class		= -1;
212	       pConfigs[i].rgba			= TRUE;
213	       pConfigs[i].redSize		= 8;
214	       pConfigs[i].greenSize		= 8;
215	       pConfigs[i].blueSize		= 8;
216	       pConfigs[i].alphaSize		= 0;
217	       pConfigs[i].redMask		= 0x00FF0000;
218	       pConfigs[i].greenMask		= 0x0000FF00;
219	       pConfigs[i].blueMask		= 0x000000FF;
220	       pConfigs[i].alphaMask		= 0x00000000;
221	       if ( accum ) {	/* Simulated in software */
222		  pConfigs[i].accumRedSize	= 16;
223		  pConfigs[i].accumGreenSize	= 16;
224		  pConfigs[i].accumBlueSize	= 16;
225		  pConfigs[i].accumAlphaSize	= 0;
226	       } else {
227		  pConfigs[i].accumRedSize	= 0;
228		  pConfigs[i].accumGreenSize	= 0;
229		  pConfigs[i].accumBlueSize	= 0;
230		  pConfigs[i].accumAlphaSize	= 0;
231	       }
232	       pConfigs[i].doubleBuffer		= db ? TRUE : FALSE;
233	       pConfigs[i].stereo		= FALSE;
234	       pConfigs[i].bufferSize		= 24;
235	       if ( stencil ) {	/* Simulated in software */
236		  pConfigs[i].depthSize		= 16;
237		  pConfigs[i].stencilSize	= 8;
238	       } else {
239		  pConfigs[i].depthSize		= 16;
240		  pConfigs[i].stencilSize	= 0;
241	    }
242	       pConfigs[i].auxBuffers		= 0;
243	       pConfigs[i].level		= 0;
244	       if ( accum || stencil ) {
245		  pConfigs[i].visualRating	= GLX_SLOW_CONFIG;
246	       } else {
247		  pConfigs[i].visualRating	= GLX_NONE;
248	    }
249	       pConfigs[i].transparentPixel	= GLX_NONE;
250	       pConfigs[i].transparentRed	= 0;
251	       pConfigs[i].transparentGreen	= 0;
252	       pConfigs[i].transparentBlue	= 0;
253	       pConfigs[i].transparentAlpha	= 0;
254	       pConfigs[i].transparentIndex	= 0;
255	       i++;
256	    }
257	 }
258      }
259      break;
260   }
261
262   pATI->numVisualConfigs = numConfigs;
263   pATI->pVisualConfigs = pConfigs;
264   pATI->pVisualConfigsPriv = pATIConfigs;
265   GlxSetVisualConfigs( numConfigs, pConfigs, (void**)pATIConfigPtrs );
266   return TRUE;
267}
268
269/* Create the ATI-specific context information */
270static Bool ATICreateContext( ScreenPtr pScreen, VisualPtr visual,
271			      drm_context_t hwContext, void *pVisualConfigPriv,
272			      DRIContextType contextStore )
273{
274   /* Nothing yet */
275   return TRUE;
276}
277
278/* Destroy the ATI-specific context information */
279static void ATIDestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
280			       DRIContextType contextStore )
281{
282   /* Nothing yet */
283}
284
285/* Called when the X server is woken up to allow the last client's
286 * context to be saved and the X server's context to be loaded.
287 * The client detects when it's context is not currently loaded and
288 * then loads it itself.  The X server's context is loaded in the
289 * XAA Sync callback if NeedDRISync is set.
290 */
291static void ATIEnterServer( ScreenPtr pScreen )
292{
293   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
294   ATIPtr pATI = ATIPTR(pScreenInfo);
295
296   if ( pATI->directRenderingEnabled ) {
297      ATIDRIMarkSyncInt(pScreenInfo);
298      ATIDRIMarkSyncExt(pScreenInfo);
299   }
300}
301
302/* Called when the X server goes to sleep to allow the X server's
303 * context to be saved and the last client's context to be loaded.
304 * The client detects when it's context is not currently loaded and
305 * then loads it itself.  The X server keeps track of it's own state.
306 */
307static void ATILeaveServer( ScreenPtr pScreen )
308{
309   /* Nothing yet */
310}
311
312/* Contexts can be swapped by the X server if necessary.  This callback
313 * is currently only used to perform any functions necessary when
314 * entering or leaving the X server, and in the future might not be
315 * necessary.
316 */
317static void ATIDRISwapContext( ScreenPtr pScreen,
318			       DRISyncType syncType,
319			       DRIContextType oldContextType,
320			       void *oldContext,
321			       DRIContextType newContextType,
322			       void *newContext )
323{
324   if ( ( syncType == DRI_3D_SYNC ) && ( oldContextType == DRI_2D_CONTEXT ) &&
325	( newContextType == DRI_2D_CONTEXT ) ) {
326      /* Entering from Wakeup */
327      ATIEnterServer( pScreen );
328   }
329   if ( ( syncType == DRI_2D_SYNC ) && ( oldContextType == DRI_NO_CONTEXT ) &&
330	( newContextType == DRI_2D_CONTEXT ) ) {
331      /* Exiting from Block Handler */
332      ATILeaveServer( pScreen );
333   }
334}
335
336#ifdef USE_XAA
337static void ATIDRITransitionTo2d(ScreenPtr pScreen)
338{
339   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
340   ATIPtr pATI = ATIPTR(pScreenInfo);
341
342   if (pATI->backArea) {
343      xf86FreeOffscreenArea(pATI->backArea);
344      pATI->backArea = NULL;
345   }
346   if (pATI->depthTexArea) {
347      xf86FreeOffscreenArea(pATI->depthTexArea);
348      pATI->depthTexArea = NULL;
349   }
350   pATI->have3DWindows = FALSE;
351}
352
353static void ATIDRITransitionTo3d(ScreenPtr pScreen)
354{
355   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
356   ATIPtr pATI = ATIPTR(pScreenInfo);
357   FBAreaPtr fbArea;
358   int width, height;
359
360   xf86PurgeUnlockedOffscreenAreas(pScreen);
361
362   xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0);
363
364   xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
365	      "Largest offscreen area available: %d x %d\n",
366	      width, height);
367
368   fbArea = xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
369				      height - pATI->depthTexLines -
370				      pATI->backLines,
371				      pScreenInfo->displayWidth, NULL, NULL, NULL);
372
373   if (!fbArea)
374      xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve placeholder "
375		 "offscreen area, you might experience screen corruption\n");
376
377   if (!pATI->backArea) {
378      pATI->backArea =
379	 xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
380				   pATI->backLines,
381				   pScreenInfo->displayWidth,
382				   NULL, NULL, NULL);
383   }
384   if (!pATI->backArea)
385      xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area "
386		 "for back buffer, you might experience screen corruption\n");
387
388   if (!pATI->depthTexArea) {
389      pATI->depthTexArea =
390	 xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
391				   pATI->depthTexLines,
392				   pScreenInfo->displayWidth,
393				   NULL, NULL, NULL);
394   }
395   if (!pATI->depthTexArea)
396      xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area "
397		 "for depth buffer and textures, you might experience screen corruption\n");
398
399   if (fbArea)
400      xf86FreeOffscreenArea(fbArea);
401
402   pATI->have3DWindows = TRUE;
403}
404#endif /* USE_XAA */
405
406#ifdef USE_EXA
407static void ATIDRITransitionTo2d_EXA(ScreenPtr pScreen)
408{
409   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
410   ATIPtr pATI = ATIPTR(pScreenInfo);
411   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
412
413   exaEnableDisableFBAccess(pScreen->myNum, FALSE);
414
415   pATI->pExa->offScreenBase = pATIDRIServer->backOffset;
416
417   exaEnableDisableFBAccess(pScreen->myNum, TRUE);
418
419   pATI->have3DWindows = FALSE;
420}
421
422static void ATIDRITransitionTo3d_EXA(ScreenPtr pScreen)
423{
424   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
425   ATIPtr pATI = ATIPTR(pScreenInfo);
426   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
427
428   exaEnableDisableFBAccess(pScreen->myNum, FALSE);
429
430   pATI->pExa->offScreenBase = pATIDRIServer->textureOffset +
431			       pATIDRIServer->textureSize;
432
433   exaEnableDisableFBAccess(pScreen->myNum, TRUE);
434
435   pATI->have3DWindows = TRUE;
436}
437#endif /* USE_EXA */
438
439/* Initialize the state of the back and depth buffers. */
440static void ATIDRIInitBuffers( WindowPtr pWin, RegionPtr prgn, CARD32 indx )
441{
442#ifdef USE_XAA
443   ScreenPtr   pScreen = pWin->drawable.pScreen;
444   ScrnInfoPtr pScreenInfo   = xf86Screens[pScreen->myNum];
445   ATIPtr pATI = ATIPTR(pScreenInfo);
446   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
447   XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
448   BoxPtr      pbox, pboxSave;
449   int         nbox, nboxSave;
450   int         depth;
451
452   depth = 0x0000ffff;
453
454   if (!pXAAInfo)
455      return;
456
457   if (!pXAAInfo->SetupForSolidFill)
458      return;
459
460   /* FIXME: Only initialize the back and depth buffers for contexts
461      that request them */
462
463   /* FIXME: Use drm clear? (see Radeon driver) */
464
465   pboxSave = pbox = REGION_RECTS(prgn);
466   nboxSave = nbox = REGION_NUM_RECTS(prgn);
467
468   (*pXAAInfo->SetupForSolidFill)(pScreenInfo, 0, GXcopy, (CARD32)(-1));
469   for (; nbox; nbox--, pbox++) {
470      (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
471					      pbox->x1 + pATIDRIServer->fbX,
472					      pbox->y1 + pATIDRIServer->fbY,
473					      pbox->x2 - pbox->x1,
474					      pbox->y2 - pbox->y1);
475      (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
476					      pbox->x1 + pATIDRIServer->backX,
477					      pbox->y1 + pATIDRIServer->backY,
478					      pbox->x2 - pbox->x1,
479					      pbox->y2 - pbox->y1);
480   }
481
482   pbox = pboxSave;
483   nbox = nboxSave;
484
485   (*pXAAInfo->SetupForSolidFill)(pScreenInfo, depth, GXcopy, (CARD32)(-1));
486   for (; nbox; nbox--, pbox++)
487      (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
488					      pbox->x1 + pATIDRIServer->depthX,
489					      pbox->y1 + pATIDRIServer->depthY,
490					      pbox->x2 - pbox->x1,
491					      pbox->y2 - pbox->y1);
492
493   ATIDRIMarkSyncInt(pScreenInfo);
494#endif
495}
496
497/* Copy the back and depth buffers when the X server moves a window.
498 *
499 * Note: this function was copied from the Radeon driver...
500 *
501 * This routine is a modified form of XAADoBitBlt with the calls to
502 * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
503 * instead of destination. My origin is upside down so the ydir cases
504 * are reversed.
505 */
506static void ATIDRIMoveBuffers( WindowPtr pWin, DDXPointRec ptOldOrg,
507			       RegionPtr prgnSrc, CARD32 indx )
508{
509#ifdef USE_XAA
510    ScreenPtr pScreen = pWin->drawable.pScreen;
511    ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
512    ATIPtr pATI = ATIPTR(pScreenInfo);
513    XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
514
515    int backOffsetPitch =  (((pATI->pDRIServerInfo->backPitch/8) << 22) |
516					   (pATI->pDRIServerInfo->backOffset >> 3));
517#if 0
518    int depthOffsetPitch = (((pATI->pDRIServerInfo->depthPitch/8) << 22) |
519					   (pATI->pDRIServerInfo->depthOffset >> 3));
520#endif
521    BoxPtr        pboxTmp, pboxNext, pboxBase;
522    DDXPointPtr   pptTmp;
523    int           xdir, ydir;
524
525    int           screenwidth = pScreenInfo->virtualX;
526    int           screenheight = pScreenInfo->virtualY;
527
528    BoxPtr        pbox     = REGION_RECTS(prgnSrc);
529    int           nbox     = REGION_NUM_RECTS(prgnSrc);
530
531    BoxPtr        pboxNew1 = NULL;
532    BoxPtr        pboxNew2 = NULL;
533    DDXPointPtr   pptNew1  = NULL;
534    DDXPointPtr   pptNew2  = NULL;
535    DDXPointPtr   pptSrc   = &ptOldOrg;
536
537    int           dx       = pWin->drawable.x - ptOldOrg.x;
538    int           dy       = pWin->drawable.y - ptOldOrg.y;
539
540   if (!pXAAInfo)
541      return;
542
543   if (!pXAAInfo->SetupForScreenToScreenCopy)
544      return;
545
546    /* FIXME: Only move the back and depth buffers for contexts
547     * that request them.
548     */
549
550    /* If the copy will overlap in Y, reverse the order */
551    if (dy > 0) {
552	ydir = -1;
553
554	if (nbox > 1) {
555	    /* Keep ordering in each band, reverse order of bands */
556	    pboxNew1 = (BoxPtr)xalloc(sizeof(BoxRec)*nbox);
557	    if (!pboxNew1) return;
558	    pptNew1 = (DDXPointPtr)xalloc(sizeof(DDXPointRec)*nbox);
559	    if (!pptNew1) {
560		xfree(pboxNew1);
561		return;
562	    }
563	    pboxBase = pboxNext = pbox+nbox-1;
564	    while (pboxBase >= pbox) {
565		while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
566		    pboxNext--;
567		pboxTmp = pboxNext+1;
568		pptTmp  = pptSrc + (pboxTmp - pbox);
569		while (pboxTmp <= pboxBase) {
570		    *pboxNew1++ = *pboxTmp++;
571		    *pptNew1++  = *pptTmp++;
572		}
573		pboxBase = pboxNext;
574	    }
575	    pboxNew1 -= nbox;
576	    pbox      = pboxNew1;
577	    pptNew1  -= nbox;
578	    pptSrc    = pptNew1;
579	}
580    } else {
581	/* No changes required */
582	ydir = 1;
583    }
584
585    /* If the regions will overlap in X, reverse the order */
586    if (dx > 0) {
587	xdir = -1;
588
589	if (nbox > 1) {
590	    /* reverse order of rects in each band */
591	    pboxNew2 = (BoxPtr)xalloc(sizeof(BoxRec)*nbox);
592	    pptNew2  = (DDXPointPtr)xalloc(sizeof(DDXPointRec)*nbox);
593	    if (!pboxNew2 || !pptNew2) {
594		xfree(pptNew2);
595		xfree(pboxNew2);
596		xfree(pptNew1);
597		xfree(pboxNew1);
598		return;
599	    }
600	    pboxBase = pboxNext = pbox;
601	    while (pboxBase < pbox+nbox) {
602		while ((pboxNext < pbox+nbox)
603		       && (pboxNext->y1 == pboxBase->y1))
604		    pboxNext++;
605		pboxTmp = pboxNext;
606		pptTmp  = pptSrc + (pboxTmp - pbox);
607		while (pboxTmp != pboxBase) {
608		    *pboxNew2++ = *--pboxTmp;
609		    *pptNew2++  = *--pptTmp;
610		}
611		pboxBase = pboxNext;
612	    }
613	    pboxNew2 -= nbox;
614	    pbox      = pboxNew2;
615	    pptNew2  -= nbox;
616	    pptSrc    = pptNew2;
617	}
618    } else {
619	/* No changes are needed */
620	xdir = 1;
621    }
622
623    (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, xdir, ydir, GXcopy,
624					       (CARD32)(-1), -1);
625
626    for (; nbox-- ; pbox++) {
627	int xa    = pbox->x1;
628	int ya    = pbox->y1;
629	int destx = xa + dx;
630	int desty = ya + dy;
631	int w     = pbox->x2 - xa + 1;
632	int h     = pbox->y2 - ya + 1;
633
634	if (destx < 0)                xa -= destx, w += destx, destx = 0;
635	if (desty < 0)                ya -= desty, h += desty, desty = 0;
636	if (destx + w > screenwidth)  w = screenwidth  - destx;
637	if (desty + h > screenheight) h = screenheight - desty;
638
639	if (w <= 0) continue;
640	if (h <= 0) continue;
641
642	ATIMach64WaitForFIFO(pATI, 2);
643	outf(SRC_OFF_PITCH, backOffsetPitch);
644	outf(DST_OFF_PITCH, backOffsetPitch);
645
646	(*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo,
647						     xa, ya,
648						     destx, desty,
649						     w, h);
650#if 0
651	/* FIXME: Move depth buffers? */
652	ATIMach64WaitForFIFO(pATI, 2);
653	outf(SRC_OFF_PITCH, depthOffsetPitch);
654	outf(DST_OFF_PITCH, depthOffsetPitch);
655
656	if (pATI->depthMoves)
657	    ATIScreenToScreenCopyDepth(pScreenInfo,
658					  xa, ya,
659					  destx, desty,
660					  w, h);
661#endif
662    }
663
664    ATIMach64WaitForFIFO(pATI, 2);
665    outf(SRC_OFF_PITCH, pATI->NewHW.dst_off_pitch);
666    outf(DST_OFF_PITCH, pATI->NewHW.src_off_pitch);
667
668    xfree(pptNew2);
669    xfree(pboxNew2);
670    xfree(pptNew1);
671    xfree(pboxNew1);
672
673    ATIDRIMarkSyncInt(pScreenInfo);
674#endif
675}
676
677/* Compute log base 2 of val. */
678static int Mach64MinBits(int val)
679{
680    int bits;
681
682    if (!val) return 1;
683    for (bits = 0; val; val >>= 1, ++bits);
684    return bits;
685}
686
687static Bool ATIDRISetBufSize( ScreenPtr pScreen, unsigned int maxSize )
688{
689   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
690   ATIPtr pATI = ATIPTR(pScreenInfo);
691   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
692
693   if (pATI->OptionBufferSize) {
694      if (pATI->OptionBufferSize < 1 || pATI->OptionBufferSize > maxSize  ) {
695	 xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Illegal DMA buffers size: %d MB\n",
696		     pATI->OptionBufferSize );
697	 return FALSE;
698      }
699      if (pATI->OptionBufferSize > 2) {
700	 xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Illegal DMA buffers size: %d MB\n",
701		     pATI->OptionBufferSize );
702	 xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Clamping DMA buffers size to 2 MB\n");
703	 pATIDRIServer->bufferSize = 2;
704      } else {
705	 pATIDRIServer->bufferSize = pATI->OptionBufferSize;
706	 xf86DrvMsg( pScreen->myNum, X_CONFIG, "[drm] Using %d MB for DMA buffers\n",
707		     pATIDRIServer->bufferSize );
708      }
709   } else {
710      xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[drm] Using %d MB for DMA buffers\n",
711		  pATIDRIServer->bufferSize );
712   }
713
714   return TRUE;
715}
716
717static Bool ATIDRISetAgpMode( ScreenPtr pScreen )
718{
719   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
720   ATIPtr pATI = ATIPTR(pScreenInfo);
721   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
722
723   unsigned long mode   = drmAgpGetMode( pATI->drmFD );        /* Default mode */
724   unsigned int vendor = drmAgpVendorId( pATI->drmFD );
725   unsigned int device = drmAgpDeviceId( pATI->drmFD );
726
727   if (pATI->OptionAGPMode > 0 && pATI->OptionAGPMode <= ATI_AGP_MAX_MODE) {
728      pATIDRIServer->agpMode = pATI->OptionAGPMode;
729      xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using AGP %dx Mode\n",
730		  pATIDRIServer->agpMode );
731   } else if (pATI->OptionAGPMode > 0) {
732      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Illegal AGP Mode: %d\n",
733		  pATI->OptionAGPMode );
734      return FALSE;
735   } else {
736      /* If no mode configured, use the default mode obtained from agpgart */
737      if ( mode & AGP_MODE_2X ) {
738	 pATIDRIServer->agpMode = 2;
739      } else if ( mode & AGP_MODE_1X ) {
740	 pATIDRIServer->agpMode = 1;
741      }
742      xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using AGP %dx Mode\n",
743		  pATIDRIServer->agpMode );
744   }
745
746   mode &= ~AGP_MODE_MASK;
747   switch ( pATIDRIServer->agpMode ) {
748   case 2:          mode |= AGP_MODE_2X;
749   case 1: default: mode |= AGP_MODE_1X;
750   }
751
752   if (pATI->OptionAGPSize) {
753      switch (pATI->OptionAGPSize) {
754      case 128:
755      case  64:
756      case  32:
757      case  16:
758      case   8:
759      case   4:
760	 pATIDRIServer->agpSize = pATI->OptionAGPSize;
761	 xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using %d MB AGP aperture\n",
762		     pATIDRIServer->agpSize );
763	 break;
764      default:
765	 xf86DrvMsg( pScreen->myNum, X_ERROR,
766		     "[agp] Illegal aperture size %d MB\n", pATI->OptionAGPSize );
767	 return FALSE;
768      }
769   } else {
770      xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using %d MB AGP aperture\n",
771		  pATIDRIServer->agpSize );
772   }
773
774   xf86DrvMsg( pScreen->myNum, X_INFO,
775	       "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
776	       mode, vendor, device,
777	       PCI_DEV_VENDOR_ID(pATI->PCIInfo),
778	       PCI_DEV_DEVICE_ID(pATI->PCIInfo) );
779
780   if ( drmAgpEnable( pATI->drmFD, mode ) < 0 ) {
781      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
782      drmAgpRelease( pATI->drmFD );
783      return FALSE;
784   }
785
786   return TRUE;
787}
788
789/* Initialize the AGP state.  Request memory for use in AGP space, and
790 * initialize the Rage Pro registers to point to that memory.
791 */
792static Bool ATIDRIAgpInit( ScreenPtr pScreen )
793{
794   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
795   ATIPtr pATI = ATIPTR(pScreenInfo);
796   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
797
798   int ret;
799   unsigned long cntl;
800   int s, l;
801
802   pATIDRIServer->agpSize = ATI_DEFAULT_AGP_SIZE;
803   pATIDRIServer->agpMode = ATI_DEFAULT_AGP_MODE;
804   pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
805   pATIDRIServer->ringSize = 16; /* 16 kB ring */
806
807   if ( drmAgpAcquire( pATI->drmFD ) < 0 ) {
808      xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP not available\n" );
809      return FALSE;
810   }
811
812   if (!ATIDRISetAgpMode( pScreen ))
813      return FALSE;
814
815   pATIDRIServer->agpOffset = 0;
816
817   ret = drmAgpAlloc( pATI->drmFD, pATIDRIServer->agpSize*1024*1024,
818		      0, NULL, &pATIDRIServer->agpHandle );
819   if ( ret < 0 ) {
820      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
821      drmAgpRelease( pATI->drmFD );
822      return FALSE;
823   }
824   xf86DrvMsg( pScreen->myNum, X_INFO,
825	       "[agp] %d kB allocated with handle 0x%08x\n",
826	       pATIDRIServer->agpSize*1024, pATIDRIServer->agpHandle );
827
828   if ( drmAgpBind( pATI->drmFD, pATIDRIServer->agpHandle, pATIDRIServer->agpOffset) < 0 ) {
829      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind\n" );
830      drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
831      drmAgpRelease( pATI->drmFD );
832      return FALSE;
833   }
834
835   xf86DrvMsg(pScreen->myNum, X_INFO,
836	      "[agp] Using %d kB for DMA descriptor ring\n", pATIDRIServer->ringSize);
837
838   if ( !ATIDRISetBufSize( pScreen, pATIDRIServer->agpSize ) )
839      return FALSE;
840
841   pATIDRIServer->agpTexSize    = pATIDRIServer->agpSize - pATIDRIServer->bufferSize;
842
843   /* Reserve space for the DMA descriptor ring */
844   pATIDRIServer->ringStart   = pATIDRIServer->agpOffset;
845   pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */
846
847   /* Reserve space for the vertex buffer */
848   pATIDRIServer->bufferStart   = pATIDRIServer->ringStart + pATIDRIServer->ringMapSize;
849   pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024;
850
851   /* Reserve the rest for AGP textures */
852   pATIDRIServer->agpTexStart = pATIDRIServer->bufferStart + pATIDRIServer->bufferMapSize;
853   s = (pATIDRIServer->agpSize*1024*1024 - pATIDRIServer->agpTexStart);
854   l = Mach64MinBits((s-1) / MACH64_NR_TEX_REGIONS);
855   if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY;
856   pATIDRIServer->agpTexMapSize   = (s >> l) << l;
857   pATIDRIServer->log2AGPTexGran  = l;
858
859   xf86DrvMsg(pScreen->myNum, X_INFO,
860	      "[agp] Using %d kB for AGP textures\n", pATIDRIServer->agpTexMapSize/1024);
861
862   /* Map DMA descriptor ring */
863   if ( drmAddMap( pATI->drmFD, pATIDRIServer->ringStart, pATIDRIServer->ringMapSize,
864		   DRM_AGP, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) {
865      xf86DrvMsg( pScreen->myNum, X_ERROR,
866		  "[agp] Could not add ring mapping\n" );
867      return FALSE;
868   }
869   xf86DrvMsg( pScreen->myNum, X_INFO,
870	       "[agp] ring handle = 0x%08x\n",
871	       pATIDRIServer->ringHandle );
872
873   if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle,
874		pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) {
875      xf86DrvMsg( pScreen->myNum, X_ERROR,
876		  "[agp] Could not map ring\n" );
877      return FALSE;
878   }
879   xf86DrvMsg( pScreen->myNum, X_INFO,
880	       "[agp] Ring mapped at 0x%08lx\n",
881	       (unsigned long)pATIDRIServer->ringMap );
882
883   /* Map vertex buffers */
884   if ( drmAddMap( pATI->drmFD, pATIDRIServer->bufferStart, pATIDRIServer->bufferMapSize,
885		   DRM_AGP, DRM_READ_ONLY, &pATIDRIServer->bufferHandle ) < 0 ) {
886      xf86DrvMsg( pScreen->myNum, X_ERROR,
887		  "[agp] Could not add vertex buffers mapping\n" );
888      return FALSE;
889   }
890   xf86DrvMsg( pScreen->myNum, X_INFO,
891	       "[agp] vertex buffers handle = 0x%08x\n",
892	       pATIDRIServer->bufferHandle );
893
894   if ( drmMap( pATI->drmFD, pATIDRIServer->bufferHandle,
895		pATIDRIServer->bufferMapSize, &pATIDRIServer->bufferMap ) < 0 ) {
896      xf86DrvMsg( pScreen->myNum, X_ERROR,
897		  "[agp] Could not map vertex buffers\n" );
898      return FALSE;
899   }
900   xf86DrvMsg( pScreen->myNum, X_INFO,
901	       "[agp] Vertex buffers mapped at 0x%08lx\n",
902	       (unsigned long)pATIDRIServer->bufferMap );
903
904   /* Map AGP Textures */
905   if (drmAddMap(pATI->drmFD, pATIDRIServer->agpTexStart, pATIDRIServer->agpTexMapSize,
906		 DRM_AGP, 0, &pATIDRIServer->agpTexHandle) < 0) {
907      xf86DrvMsg(pScreen->myNum, X_ERROR,
908		 "[agp] Could not add AGP texture region mapping\n");
909      return FALSE;
910   }
911   xf86DrvMsg(pScreen->myNum, X_INFO,
912	      "[agp] AGP texture region handle = 0x%08x\n",
913	      pATIDRIServer->agpTexHandle);
914
915   if (drmMap(pATI->drmFD, pATIDRIServer->agpTexHandle, pATIDRIServer->agpTexMapSize,
916	      &pATIDRIServer->agpTexMap) < 0) {
917      xf86DrvMsg(pScreen->myNum, X_ERROR,
918		 "[agp] Could not map AGP texture region\n");
919      return FALSE;
920   }
921   xf86DrvMsg(pScreen->myNum, X_INFO,
922	      "[agp] AGP Texture region mapped at 0x%08lx\n",
923	      (unsigned long)pATIDRIServer->agpTexMap);
924
925   /* Initialize Mach64's AGP registers */
926   cntl  = inm( AGP_CNTL );
927   cntl &= ~AGP_APER_SIZE_MASK;
928   switch ( pATIDRIServer->agpSize ) {
929   case 256: cntl |= AGP_APER_SIZE_256MB; break;
930   case 128: cntl |= AGP_APER_SIZE_128MB; break;
931   case  64: cntl |= AGP_APER_SIZE_64MB;  break;
932   case  32: cntl |= AGP_APER_SIZE_32MB;  break;
933   case  16: cntl |= AGP_APER_SIZE_16MB;  break;
934   case   8: cntl |= AGP_APER_SIZE_8MB;   break;
935   case   4: cntl |= AGP_APER_SIZE_4MB;   break;
936   default:
937      xf86DrvMsg( pScreen->myNum, X_ERROR,
938		  "[agp] Illegal aperture size %d kB\n",
939		  pATIDRIServer->agpSize*1024 );
940      return FALSE;
941   }
942
943   /* 1 = DATA comes in clock in which TRDY sampled (default) */
944   /* 0 = DATA comes in clock after TRDY sampled */
945   cntl |= AGP_TRDY_MODE;
946
947   /* 1 = generate all reads as high priority */
948   /* 0 = generate all reads as their default priority (default) */
949   /* Setting this only works for me at AGP 1x mode (LLD) */
950   if (pATIDRIServer->agpMode == 1) {
951      cntl |= HIGH_PRIORITY_READ_EN;
952   } else {
953      cntl &= ~HIGH_PRIORITY_READ_EN;
954   }
955
956   outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
957   outm( AGP_CNTL, cntl );
958
959   return TRUE;
960}
961
962static Bool ATIDRIPciInit( ScreenPtr pScreen )
963{
964   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
965   ATIPtr pATI = ATIPTR(pScreenInfo);
966   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
967
968   pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
969   pATIDRIServer->ringSize = 16; /* 16 kB ring */
970
971   if ( !ATIDRISetBufSize( pScreen, (unsigned)(-1) ) )
972      return FALSE;
973
974   /* Set size of the DMA descriptor ring */
975   pATIDRIServer->ringStart   = 0;
976   pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */
977
978   /* Set size of the vertex buffer */
979   pATIDRIServer->bufferStart   = 0;
980   pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024;
981
982   /* Map DMA descriptor ring */
983   if ( drmAddMap( pATI->drmFD, 0, pATIDRIServer->ringMapSize,
984		   DRM_CONSISTENT, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) {
985      xf86DrvMsg( pScreen->myNum, X_ERROR,
986		  "[pci] Could not add ring mapping\n" );
987      return FALSE;
988   }
989   xf86DrvMsg( pScreen->myNum, X_INFO, "[pci] ring handle = 0x%08x\n",
990	       pATIDRIServer->ringHandle );
991
992   if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle,
993		pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) {
994      xf86DrvMsg( pScreen->myNum, X_ERROR,
995		  "[pci] Could not map ring\n" );
996      return FALSE;
997   }
998   xf86DrvMsg( pScreen->myNum, X_INFO,
999	       "[pci] Ring mapped at 0x%08lx\n",
1000	       (unsigned long)pATIDRIServer->ringMap );
1001
1002   /* Disable AGP for ForcePCIMode */
1003   if ( pATI->BusType != ATI_BUS_PCI ) {
1004       outm( AGP_BASE, 0 );
1005       outm( AGP_CNTL, 0 );
1006   }
1007
1008   return TRUE;
1009}
1010
1011/* Add a map for the MMIO registers that will be accessed by any
1012 * DRI-based clients.
1013 */
1014static Bool ATIDRIMapInit( ScreenPtr pScreen )
1015{
1016   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
1017   ATIPtr pATI = ATIPTR(pScreenInfo);
1018   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1019
1020   pATIDRIServer->regsSize = getpagesize();
1021   if ( drmAddMap( pATI->drmFD, pATI->Block1Base,
1022		   pATIDRIServer->regsSize,
1023		   DRM_REGISTERS, DRM_READ_ONLY,
1024		   &pATIDRIServer->regsHandle ) < 0 ) {
1025      xf86DrvMsg( pScreen->myNum, X_ERROR,
1026		  "[drm] failed to map registers\n" );
1027      return FALSE;
1028   }
1029   xf86DrvMsg( pScreen->myNum, X_INFO,
1030	       "[drm] register handle = 0x%08x\n",
1031	       pATIDRIServer->regsHandle );
1032
1033   return TRUE;
1034}
1035
1036/* Initialize the kernel data structures. */
1037static Bool ATIDRIKernelInit( ScreenPtr pScreen )
1038{
1039   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
1040   ATIPtr pATI = ATIPTR(pScreenInfo);
1041   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1042   drmMach64Init info;
1043
1044   memset( &info, 0, sizeof(drmMach64Init) );
1045
1046   info.func 			= DRM_MACH64_INIT_DMA;
1047   info.sarea_priv_offset	= sizeof(XF86DRISAREARec);
1048   info.is_pci			= pATIDRIServer->IsPCI;
1049   info.dma_mode                = pATI->OptionDMAMode;
1050
1051   info.fb_bpp			= pATI->bitsPerPixel;
1052   info.front_offset		= pATIDRIServer->frontOffset;
1053   info.front_pitch		= pATIDRIServer->frontPitch;
1054   info.back_offset		= pATIDRIServer->backOffset;
1055   info.back_pitch		= pATIDRIServer->backPitch;
1056
1057   info.depth_bpp		= 16;
1058   info.depth_offset		= pATIDRIServer->depthOffset;
1059   info.depth_pitch		= pATIDRIServer->depthPitch;
1060
1061   info.fb_offset		= pATI->LinearBase;
1062   info.mmio_offset		= pATIDRIServer->regsHandle;
1063   info.ring_offset		= pATIDRIServer->ringHandle;
1064   info.buffers_offset		= pATIDRIServer->bufferHandle;
1065   info.agp_textures_offset	= pATIDRIServer->agpTexHandle;
1066
1067   if ( drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
1068			 &info, sizeof(drmMach64Init) ) < 0 ) {
1069      return FALSE;
1070   } else {
1071      return TRUE;
1072   }
1073}
1074
1075/* Add a map for the DMA buffers that will be accessed by any
1076 * DRI-based clients.
1077 */
1078static Bool ATIDRIAddBuffers( ScreenPtr pScreen )
1079{
1080   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
1081   ATIPtr pATI = ATIPTR(pScreenInfo);
1082   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1083
1084   /* Initialize vertex buffers */
1085   if ( pATIDRIServer->IsPCI ) {
1086      pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
1087					      pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE,
1088					      MACH64_BUFFER_SIZE,
1089					      DRM_PCI_BUFFER_RO,
1090					      0 );
1091   } else {
1092      pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
1093					      pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE,
1094					      MACH64_BUFFER_SIZE,
1095					      DRM_AGP_BUFFER,
1096					      pATIDRIServer->bufferStart );
1097   }
1098   if ( pATIDRIServer->numBuffers <= 0 ) {
1099      xf86DrvMsg( pScreen->myNum, X_ERROR,
1100		  "[drm] Could not create DMA buffers list\n" );
1101      return FALSE;
1102   }
1103   xf86DrvMsg( pScreen->myNum, X_INFO,
1104	       "[drm] Added %d %d byte DMA buffers\n",
1105	       pATIDRIServer->numBuffers, MACH64_BUFFER_SIZE );
1106
1107    return TRUE;
1108}
1109
1110static Bool ATIDRIMapBuffers( ScreenPtr pScreen )
1111{
1112   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
1113   ATIPtr pATI = ATIPTR(pScreenInfo);
1114   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1115
1116   pATIDRIServer->drmBuffers = drmMapBufs( pATI->drmFD );
1117   if ( !pATIDRIServer->drmBuffers ) {
1118      xf86DrvMsg( pScreen->myNum, X_ERROR,
1119		  "[drm] Failed to map DMA buffers list\n" );
1120      return FALSE;
1121   }
1122   xf86DrvMsg( pScreen->myNum, X_INFO,
1123	       "[drm] Mapped %d DMA buffers at 0x%08lx\n",
1124	       pATIDRIServer->drmBuffers->count,
1125	       (unsigned long)pATIDRIServer->drmBuffers->list->address );
1126
1127   return TRUE;
1128}
1129
1130static Bool ATIDRIIrqInit( ScreenPtr pScreen )
1131{
1132   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
1133   ATIPtr pATI = ATIPTR(pScreenInfo);
1134
1135   if ( pATI->irq <= 0 ) {
1136      pATI->irq = drmGetInterruptFromBusID(pATI->drmFD,
1137					   PCI_CFG_BUS(pATI->PCIInfo),
1138					   PCI_CFG_DEV(pATI->PCIInfo),
1139					   PCI_CFG_FUNC(pATI->PCIInfo));
1140      if ( pATI->irq <= 0 ) {
1141	 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1142		    "[drm] Couldn't find IRQ for bus id %d:%d:%d\n",
1143		    PCI_CFG_BUS(pATI->PCIInfo),
1144		    PCI_CFG_DEV(pATI->PCIInfo),
1145		    PCI_CFG_FUNC(pATI->PCIInfo));
1146	 pATI->irq = 0;
1147      } else if ((drmCtlInstHandler(pATI->drmFD, pATI->irq)) != 0) {
1148 	 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1149		    "[drm] Failed to initialize interrupt handler with IRQ %d\n",
1150		    pATI->irq);
1151	 pATI->irq = 0;
1152      }
1153
1154      if (pATI->irq)
1155	 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1156		    "[drm] Installed interrupt handler, using IRQ %d\n",
1157		    pATI->irq);
1158      else {
1159	 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1160		    "[drm] Falling back to irq-free operation\n");
1161	 return FALSE;
1162      }
1163   }
1164
1165   return TRUE;
1166
1167}
1168
1169/* Initialize the screen-specific data structures for the DRI and the
1170 * Rage Pro.  This is the main entry point to the device-specific
1171 * initialization code.  It calls device-independent DRI functions to
1172 * create the DRI data structures and initialize the DRI state.
1173 */
1174Bool ATIDRIScreenInit( ScreenPtr pScreen )
1175{
1176   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
1177   ATIPtr pATI = ATIPTR(pScreenInfo);
1178   DRIInfoPtr pDRIInfo;
1179   ATIDRIPtr pATIDRI;
1180   ATIDRIServerInfoPtr pATIDRIServer;
1181   drmVersionPtr version;
1182   int major, minor, patch;
1183
1184   /* Check that the GLX, DRI, and DRM modules have been loaded by testing
1185    * for known symbols in each module.
1186    */
1187   if ( !xf86LoaderCheckSymbol("GlxSetVisualConfigs") ) return FALSE;
1188   if ( !xf86LoaderCheckSymbol("drmAvailable") ) return FALSE;
1189   if ( !xf86LoaderCheckSymbol("DRIQueryVersion") ) {
1190      xf86DrvMsg( pScreen->myNum, X_ERROR,
1191		  "[dri] ATIDRIScreenInit failed (libdri.a too old)\n" );
1192      return FALSE;
1193   }
1194
1195   /* Check the DRI version */
1196   DRIQueryVersion( &major, &minor, &patch );
1197   if ( major != DRIINFO_MAJOR_VERSION || minor < 0 ) {
1198      xf86DrvMsg( pScreen->myNum, X_ERROR,
1199		  "[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
1200		  "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n"
1201		  "[dri] Disabling the DRI.\n",
1202		  major, minor, patch,
1203                  DRIINFO_MAJOR_VERSION, 0 );
1204      return FALSE;
1205   }
1206
1207   switch ( pATI->bitsPerPixel ) {
1208   case 8:
1209      /* These modes are not supported (yet). */
1210   case 15:
1211   case 24:
1212      xf86DrvMsg( pScreen->myNum, X_ERROR,
1213		  "[dri] Direct rendering only supported in 16 and 32 bpp modes\n");
1214      return FALSE;
1215
1216      /* Only 16 and 32 color depths are supported currently. */
1217   case 16:
1218      if ( pATI->depth != 16) {
1219	 xf86DrvMsg( pScreen->myNum, X_ERROR,
1220		  "[dri] Direct rendering not supported for depth %d at fbbpp 16.\n", pATI->depth );
1221	 return FALSE;
1222      }
1223      break;
1224   case 32:
1225      break;
1226   }
1227
1228   /* Create the DRI data structure, and fill it in before calling the
1229    * DRIScreenInit().
1230    */
1231   pDRIInfo = DRICreateInfoRec();
1232   if ( !pDRIInfo ) return FALSE;
1233
1234   pATI->pDRIInfo = pDRIInfo;
1235   pDRIInfo->drmDriverName = ATIKernelDriverName;
1236   pDRIInfo->clientDriverName = ATIClientDriverName;
1237   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
1238      pDRIInfo->busIdString = DRICreatePCIBusID(pATI->PCIInfo);
1239   } else {
1240      pDRIInfo->busIdString = xalloc( 64 );
1241      sprintf( pDRIInfo->busIdString,
1242	       "PCI:%d:%d:%d",
1243	       PCI_DEV_BUS(pATI->PCIInfo),
1244	       PCI_DEV_DEV(pATI->PCIInfo),
1245	       PCI_DEV_FUNC(pATI->PCIInfo) );
1246   }
1247   pDRIInfo->ddxDriverMajorVersion = MACH64_VERSION_MAJOR;
1248   pDRIInfo->ddxDriverMinorVersion = MACH64_VERSION_MINOR;
1249   pDRIInfo->ddxDriverPatchVersion = MACH64_VERSION_PATCH;
1250   pDRIInfo->frameBufferPhysicalAddress = (void *)pATI->LinearBase;
1251   pDRIInfo->frameBufferSize = pATI->LinearSize;
1252   pDRIInfo->frameBufferStride = (pScreenInfo->displayWidth *
1253				  pATI->FBBytesPerPixel);
1254   pDRIInfo->ddxDrawableTableEntry = ATI_MAX_DRAWABLES;
1255
1256   if ( SAREA_MAX_DRAWABLES < ATI_MAX_DRAWABLES ) {
1257      pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
1258   } else {
1259      pDRIInfo->maxDrawableTableEntry = ATI_MAX_DRAWABLES;
1260   }
1261
1262   /* For now the mapping works by using a fixed size defined
1263    * in the SAREA header
1264    */
1265   if ( sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec) > SAREA_MAX ) {
1266      ErrorF( "[dri] Data does not fit in SAREA\n" );
1267      return FALSE;
1268   }
1269   xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %u+%u: %u\n",
1270	       (unsigned)sizeof(XF86DRISAREARec),
1271	       (unsigned)sizeof(ATISAREAPrivRec),
1272	       (unsigned)(sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec)) );
1273   pDRIInfo->SAREASize = SAREA_MAX;
1274
1275   pATIDRI = (ATIDRIPtr) xnfcalloc( sizeof(ATIDRIRec), 1 );
1276   if ( !pATIDRI ) {
1277      DRIDestroyInfoRec( pATI->pDRIInfo );
1278      pATI->pDRIInfo = NULL;
1279      xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
1280		  "[dri] Failed to allocate memory for private record\n" );
1281      return FALSE;
1282   }
1283   pATIDRIServer = (ATIDRIServerInfoPtr)
1284      xnfcalloc( sizeof(ATIDRIServerInfoRec), 1 );
1285   if ( !pATIDRIServer ) {
1286      xfree( pATIDRI );
1287      DRIDestroyInfoRec( pATI->pDRIInfo );
1288      pATI->pDRIInfo = NULL;
1289      xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
1290		  "[dri] Failed to allocate memory for private record\n" );
1291      return FALSE;
1292   }
1293
1294   pATI->pDRIServerInfo = pATIDRIServer;
1295
1296   pDRIInfo->devPrivate		= pATIDRI;
1297   pDRIInfo->devPrivateSize	= sizeof(ATIDRIRec);
1298   pDRIInfo->contextSize	= sizeof(ATIDRIContextRec);
1299
1300   pDRIInfo->CreateContext	= ATICreateContext;
1301   pDRIInfo->DestroyContext	= ATIDestroyContext;
1302   pDRIInfo->SwapContext	= ATIDRISwapContext;
1303   pDRIInfo->InitBuffers	= ATIDRIInitBuffers;
1304   pDRIInfo->MoveBuffers	= ATIDRIMoveBuffers;
1305#ifdef USE_XAA
1306   if (!pATI->useEXA) {
1307      pDRIInfo->TransitionTo2d  = ATIDRITransitionTo2d;
1308      pDRIInfo->TransitionTo3d  = ATIDRITransitionTo3d;
1309   }
1310#endif /* USE_XAA */
1311#ifdef USE_EXA
1312   if (pATI->useEXA) {
1313      pDRIInfo->TransitionTo2d  = ATIDRITransitionTo2d_EXA;
1314      pDRIInfo->TransitionTo3d  = ATIDRITransitionTo3d_EXA;
1315   }
1316#endif /* USE_EXA */
1317   pDRIInfo->bufferRequests	= DRI_ALL_WINDOWS;
1318
1319   pDRIInfo->createDummyCtx     = TRUE;
1320   pDRIInfo->createDummyCtxPriv = FALSE;
1321
1322   pATI->have3DWindows = FALSE;
1323
1324   if ( !DRIScreenInit( pScreen, pDRIInfo, &pATI->drmFD ) ) {
1325      xfree( pATIDRIServer );
1326      pATI->pDRIServerInfo = NULL;
1327      xfree( pDRIInfo->devPrivate );
1328      pDRIInfo->devPrivate = NULL;
1329      DRIDestroyInfoRec( pDRIInfo );
1330      pDRIInfo = NULL;
1331      xf86DrvMsg( pScreen->myNum, X_ERROR,
1332		  "[dri] DRIScreenInit Failed\n" );
1333      return FALSE;
1334   }
1335
1336   /* Check the DRM lib version.
1337      drmGetLibVersion was not supported in version 1.0, so check for
1338      symbol first to avoid possible crash or hang.
1339   */
1340   if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
1341      version = drmGetLibVersion(pATI->drmFD);
1342   } else {
1343      /* drmlib version 1.0.0 didn't have the drmGetLibVersion
1344	 entry point.  Fake it by allocating a version record
1345	 via drmGetVersion and changing it to version 1.0.0
1346      */
1347      version = drmGetVersion(pATI->drmFD);
1348      version->version_major      = 1;
1349      version->version_minor      = 0;
1350      version->version_patchlevel = 0;
1351   }
1352
1353   if (version) {
1354      if (version->version_major != 1 ||
1355	  version->version_minor < 1) {
1356	 /* incompatible drm library version */
1357	 xf86DrvMsg(pScreen->myNum, X_ERROR,
1358		    "[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
1359		    "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
1360		    "[dri] Disabling DRI.\n",
1361		    version->version_major,
1362		    version->version_minor,
1363		    version->version_patchlevel);
1364	 drmFreeVersion(version);
1365	 ATIDRICloseScreen(pScreen);
1366	 return FALSE;
1367      }
1368      drmFreeVersion(version);
1369   }
1370
1371   /* Check the mach64 DRM version */
1372   version = drmGetVersion( pATI->drmFD );
1373   if ( version ) {
1374      if ( version->version_major != 2 ||
1375	   version->version_minor < 0 ) {
1376	 /* Incompatible DRM version */
1377	 xf86DrvMsg( pScreen->myNum, X_ERROR,
1378		     "[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
1379		     "[dri] mach64.o kernel module version is %d.%d.%d, but version 2.x is needed (with 2.x >= 2.0).\n"
1380		     "[dri] Disabling DRI.\n",
1381		     version->version_major,
1382		     version->version_minor,
1383		     version->version_patchlevel );
1384	 drmFreeVersion( version );
1385	 ATIDRICloseScreen( pScreen );
1386	 return FALSE;
1387      }
1388      drmFreeVersion( version );
1389   }
1390
1391   switch ( pATI->OptionDMAMode ) {
1392   case MACH64_MODE_DMA_ASYNC:
1393      xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request asynchronous DMA mode\n");
1394      break;
1395   case MACH64_MODE_DMA_SYNC:
1396      xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request synchronous DMA mode\n");
1397      break;
1398   case MACH64_MODE_MMIO:
1399      xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request pseudo-DMA (MMIO) mode\n");
1400      break;
1401   default:
1402      xf86DrvMsg(pScreen->myNum, X_WARNING, "[drm] Unknown DMA mode\n");
1403   }
1404
1405   pATIDRIServer->IsPCI = (pATI->BusType == ATI_BUS_PCI || pATI->OptionIsPCI) ? TRUE : FALSE;
1406
1407   if ( pATI->BusType != ATI_BUS_PCI && pATI->OptionIsPCI ) {
1408       xf86DrvMsg(pScreen->myNum, X_CONFIG, "[dri] Forcing PCI mode\n");
1409   }
1410
1411   /* Initialize AGP */
1412   if ( !pATIDRIServer->IsPCI && !ATIDRIAgpInit( pScreen ) ) {
1413      pATIDRIServer->IsPCI = TRUE;
1414      xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP failed to initialize -- falling back to PCI mode.\n" );
1415      xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] Make sure you have the agpgart kernel module loaded.\n" );
1416   }
1417
1418   /* Initialize PCI */
1419   if ( pATIDRIServer->IsPCI && !ATIDRIPciInit( pScreen ) ) {
1420      ATIDRICloseScreen( pScreen );
1421      return FALSE;
1422   }
1423
1424   if ( !ATIDRIMapInit( pScreen ) ) {
1425      ATIDRICloseScreen( pScreen );
1426      return FALSE;
1427   }
1428
1429   if ( !ATIInitVisualConfigs( pScreen ) ) {
1430      ATIDRICloseScreen( pScreen );
1431      return FALSE;
1432   }
1433   xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
1434	       "[dri] Visual configs initialized\n" );
1435
1436   xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
1437	       "[dri] Block 0 base at 0x%08lx\n", pATI->Block0Base );
1438
1439   return TRUE;
1440}
1441
1442/* Finish initializing the device-dependent DRI state, and call
1443 * DRIFinishScreenInit() to complete the device-independent DRI
1444 * initialization.
1445 */
1446Bool ATIDRIFinishScreenInit( ScreenPtr pScreen )
1447{
1448   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
1449   ATIPtr pATI = ATIPTR(pScreenInfo);
1450   ATISAREAPrivPtr pSAREAPriv;
1451   ATIDRIPtr pATIDRI;
1452   ATIDRIServerInfoPtr pATIDRIServer;
1453
1454   pATI->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
1455
1456   /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
1457    * because *DRIKernelInit requires that the hardware lock is held by
1458    * the X server, and the first time the hardware lock is grabbed is
1459    * in DRIFinishScreenInit.
1460    */
1461   if ( !DRIFinishScreenInit( pScreen ) ) {
1462      ATIDRICloseScreen( pScreen );
1463      return FALSE;
1464   }
1465
1466   /* Initialize the DMA buffer list */
1467   /* Need to do this before ATIDRIKernelInit so we can init the freelist */
1468   if ( !ATIDRIAddBuffers( pScreen ) ) {
1469      ATIDRICloseScreen( pScreen );
1470      return FALSE;
1471   }
1472
1473   /* Initialize the kernel data structures */
1474   if ( !ATIDRIKernelInit( pScreen ) ) {
1475      xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1476		 "[drm] Failed to initialize the mach64.o kernel module\n");
1477      xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1478		 "[drm] Check the system log for more information.\n");
1479      ATIDRICloseScreen( pScreen );
1480      return FALSE;
1481   }
1482
1483   if ( !ATIDRIMapBuffers( pScreen ) ) {
1484      ATIDRICloseScreen( pScreen );
1485      return FALSE;
1486   }
1487
1488   /* Initialize IRQ */
1489   ATIDRIIrqInit( pScreen );
1490
1491   pSAREAPriv = (ATISAREAPrivPtr) DRIGetSAREAPrivate( pScreen );
1492   memset( pSAREAPriv, 0, sizeof(*pSAREAPriv) );
1493
1494   pATIDRI = (ATIDRIPtr)pATI->pDRIInfo->devPrivate;
1495   pATIDRIServer = pATI->pDRIServerInfo;
1496
1497   pATIDRI->width = pScreenInfo->virtualX;
1498   pATIDRI->height = pScreenInfo->virtualY;
1499   pATIDRI->mem = pScreenInfo->videoRam * 1024;
1500   pATIDRI->cpp = pScreenInfo->bitsPerPixel / 8;
1501
1502   pATIDRI->IsPCI = pATIDRIServer->IsPCI;
1503   pATIDRI->AGPMode = pATIDRIServer->agpMode;
1504
1505   pATIDRI->frontOffset = pATIDRIServer->frontOffset;
1506   pATIDRI->frontPitch = pATIDRIServer->frontPitch;
1507
1508   pATIDRI->backOffset = pATIDRIServer->backOffset;
1509   pATIDRI->backPitch = pATIDRIServer->backPitch;
1510
1511   pATIDRI->depthOffset = pATIDRIServer->depthOffset;
1512   pATIDRI->depthPitch = pATIDRIServer->depthPitch;
1513
1514   pATIDRI->textureOffset = pATIDRIServer->textureOffset;
1515   pATIDRI->textureSize	= pATIDRIServer->textureSize;
1516   pATIDRI->logTextureGranularity = pATIDRIServer->logTextureGranularity;
1517
1518   pATIDRI->regs = pATIDRIServer->regsHandle;
1519   pATIDRI->regsSize = pATIDRIServer->regsSize;
1520
1521   pATIDRI->agp = pATIDRIServer->agpTexHandle;
1522   pATIDRI->agpSize = pATIDRIServer->agpTexMapSize;
1523   pATIDRI->logAgpTextureGranularity = pATIDRIServer->log2AGPTexGran;
1524   pATIDRI->agpTextureOffset = pATIDRIServer->agpTexStart;
1525
1526   return TRUE;
1527}
1528
1529/*
1530 * This function will attempt to get the Mach64 hardware back into shape
1531 * after a resume from disc. Its an extract from ATIDRIAgpInit and ATIDRIFinishScreenInit
1532 * This also calls a new ioctl in the mach64 DRM that in its turn is
1533 * an extraction of the hardware-affecting bits from mach64_do_init_drm()
1534 * (see atidrm.c)
1535 * I am assuming here that pATI->pDRIServerInfo doesn't change
1536 * elsewhere in incomaptible ways.
1537 * How will this code react to resuming after a failed resumeor pci based dri ?
1538 */
1539void ATIDRIResume( ScreenPtr pScreen )
1540{
1541   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
1542   ATIPtr pATI = ATIPTR(pScreenInfo);
1543   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1544
1545   xf86DrvMsg( pScreen->myNum, X_INFO,
1546		 "[RESUME] Attempting to re-init Mach64 hardware.\n");
1547
1548   if (!pATIDRIServer->IsPCI) {
1549      if (!ATIDRISetAgpMode(pScreen))
1550      return;
1551
1552      outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
1553   }
1554}
1555
1556/* The screen is being closed, so clean up any state and free any
1557 * resources used by the DRI.
1558 */
1559void ATIDRICloseScreen( ScreenPtr pScreen )
1560{
1561   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
1562   ATIPtr pATI = ATIPTR(pScreenInfo);
1563   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1564   drmMach64Init info;
1565
1566   /* Stop interrupt generation and handling if used */
1567   if ( pATI->irq > 0 ) {
1568      if ( drmCtlUninstHandler(pATI->drmFD) != 0 ) {
1569	 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1570		    "[drm] Error uninstalling interrupt handler for IRQ %d\n", pATI->irq);
1571      } else {
1572	 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1573		    "[drm] Uninstalled interrupt handler for IRQ %d\n", pATI->irq);
1574      }
1575      pATI->irq = 0;
1576   }
1577
1578   /* De-allocate DMA buffers */
1579   if ( pATIDRIServer->drmBuffers ) {
1580      drmUnmapBufs( pATIDRIServer->drmBuffers );
1581      pATIDRIServer->drmBuffers = NULL;
1582   }
1583
1584   /* De-allocate all kernel resources */
1585   memset(&info, 0, sizeof(drmMach64Init));
1586   info.func = DRM_MACH64_CLEANUP_DMA;
1587   drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
1588		    &info, sizeof(drmMach64Init) );
1589
1590   /* De-allocate all AGP resources */
1591   if ( pATIDRIServer->agpTexMap ) {
1592      drmUnmap( pATIDRIServer->agpTexMap, pATIDRIServer->agpTexMapSize );
1593      pATIDRIServer->agpTexMap = NULL;
1594   }
1595   if ( pATIDRIServer->bufferMap ) {
1596      drmUnmap( pATIDRIServer->bufferMap, pATIDRIServer->bufferMapSize );
1597      pATIDRIServer->bufferMap = NULL;
1598   }
1599   if ( pATIDRIServer->ringMap ) {
1600      drmUnmap( pATIDRIServer->ringMap, pATIDRIServer->ringMapSize );
1601      pATIDRIServer->ringMap = NULL;
1602   }
1603   if ( pATIDRIServer->agpHandle ) {
1604      drmAgpUnbind( pATI->drmFD, pATIDRIServer->agpHandle );
1605      drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
1606      pATIDRIServer->agpHandle = 0;
1607      drmAgpRelease( pATI->drmFD );
1608   }
1609
1610   /* De-allocate all PCI resources */
1611   if ( pATIDRIServer->IsPCI && pATIDRIServer->ringHandle ) {
1612      drmRmMap( pATI->drmFD, pATIDRIServer->ringHandle );
1613      pATIDRIServer->ringHandle = 0;
1614   }
1615
1616   /* De-allocate all DRI resources */
1617   DRICloseScreen( pScreen );
1618
1619   /* De-allocate all DRI data structures */
1620   if ( pATI->pDRIInfo ) {
1621      if ( pATI->pDRIInfo->devPrivate ) {
1622	 xfree( pATI->pDRIInfo->devPrivate );
1623	 pATI->pDRIInfo->devPrivate = NULL;
1624      }
1625      DRIDestroyInfoRec( pATI->pDRIInfo );
1626      pATI->pDRIInfo = NULL;
1627   }
1628   if ( pATI->pDRIServerInfo ) {
1629      xfree( pATI->pDRIServerInfo );
1630      pATI->pDRIServerInfo = NULL;
1631   }
1632   if ( pATI->pVisualConfigs ) {
1633      xfree( pATI->pVisualConfigs );
1634      pATI->pVisualConfigs = NULL;
1635   }
1636   if ( pATI->pVisualConfigsPriv ) {
1637      xfree( pATI->pVisualConfigsPriv );
1638      pATI->pVisualConfigsPriv = NULL;
1639   }
1640}
1641