atidri.c revision 1b12faf6
132b578d3Smrg/* -*- mode: c; c-basic-offset: 3 -*- */
232b578d3Smrg/*
332b578d3Smrg * Copyright 2000 Gareth Hughes
432b578d3Smrg * All Rights Reserved.
532b578d3Smrg *
632b578d3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
732b578d3Smrg * copy of this software and associated documentation files (the "Software"),
832b578d3Smrg * to deal in the Software without restriction, including without limitation
932b578d3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1032b578d3Smrg * and/or sell copies of the Software, and to permit persons to whom the
1132b578d3Smrg * Software is furnished to do so, subject to the following conditions:
1232b578d3Smrg *
1332b578d3Smrg * The above copyright notice and this permission notice (including the next
1432b578d3Smrg * paragraph) shall be included in all copies or substantial portions of the
1532b578d3Smrg * Software.
1632b578d3Smrg *
1732b578d3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1832b578d3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1932b578d3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2032b578d3Smrg * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
2132b578d3Smrg * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2232b578d3Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2332b578d3Smrg */
2432b578d3Smrg
2532b578d3Smrg#ifdef HAVE_CONFIG_H
2632b578d3Smrg#include "config.h"
2732b578d3Smrg#endif
2832b578d3Smrg/*
2932b578d3Smrg * Authors:
3032b578d3Smrg *   Gareth Hughes <gareth@valinux.com>
3132b578d3Smrg *   Leif Delgass <ldelgass@retinalburn.net>
3232b578d3Smrg */
3332b578d3Smrg
3432b578d3Smrg#include <string.h>
3532b578d3Smrg#include <stdio.h>
3632b578d3Smrg#include <unistd.h>
3732b578d3Smrg
3832b578d3Smrg/* Driver data structures */
3932b578d3Smrg#include "ati.h"
4032b578d3Smrg#include "atibus.h"
4132b578d3Smrg#include "atidri.h"
4232b578d3Smrg#include "atiregs.h"
4332b578d3Smrg#include "atistruct.h"
4432b578d3Smrg
4532b578d3Smrg#include "atimach64io.h"
4632b578d3Smrg#include "atimach64version.h"
4732b578d3Smrg#include "mach64_dri.h"
4832b578d3Smrg#include "mach64_common.h"
4932b578d3Smrg#include "mach64_sarea.h"
5032b578d3Smrg
5132b578d3Smrg/* X and server generic header files */
5232b578d3Smrg#include "xf86.h"
5332b578d3Smrg#include "windowstr.h"
5432b578d3Smrg
5532b578d3Smrg/* GLX/DRI/DRM definitions */
5632b578d3Smrg#define _XF86DRI_SERVER_
5732b578d3Smrg#include "GL/glxtokens.h"
5832b578d3Smrg#include "sarea.h"
5932b578d3Smrg
6032b578d3Smrgstatic char ATIKernelDriverName[] = "mach64";
6132b578d3Smrgstatic char ATIClientDriverName[] = "mach64";
6232b578d3Smrg
6332b578d3Smrg/* Initialize the visual configs that are supported by the hardware.
6432b578d3Smrg * These are combined with the visual configs that the indirect
6532b578d3Smrg * rendering core supports, and the intersection is exported to the
6632b578d3Smrg * client.
6732b578d3Smrg */
6832b578d3Smrgstatic Bool ATIInitVisualConfigs( ScreenPtr pScreen )
6932b578d3Smrg{
7032b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
7132b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
7232b578d3Smrg   int numConfigs = 0;
7332b578d3Smrg   __GLXvisualConfig *pConfigs = NULL;
7432b578d3Smrg   ATIConfigPrivPtr pATIConfigs = NULL;
7532b578d3Smrg   ATIConfigPrivPtr *pATIConfigPtrs = NULL;
7632b578d3Smrg   int i, accum, stencil, db;
7732b578d3Smrg
7832b578d3Smrg   switch ( pATI->bitsPerPixel ) {
7932b578d3Smrg   case 8:  /* 8bpp mode is not support */
8032b578d3Smrg   case 15: /* FIXME */
8132b578d3Smrg   case 24: /* FIXME */
8232b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
8332b578d3Smrg		 "[dri] ATIInitVisualConfigs failed (%d bpp not supported).  "
8432b578d3Smrg		 "Disabling DRI.\n", pATI->bitsPerPixel);
8532b578d3Smrg      return FALSE;
8632b578d3Smrg
8732b578d3Smrg#define ATI_USE_ACCUM   1
8832b578d3Smrg#define ATI_USE_STENCIL 1
8932b578d3Smrg
9032b578d3Smrg   case 16:
9132b578d3Smrg
9232b578d3Smrg      if ( pATI->depth != 16) {
9332b578d3Smrg	 xf86DrvMsg(pScreen->myNum, X_ERROR,
9432b578d3Smrg		    "[dri] ATIInitVisualConfigs failed (depth %d at 16 bpp not supported).  "
9532b578d3Smrg		     "Disabling DRI.\n", pATI->depth);
9632b578d3Smrg	 return FALSE;
9732b578d3Smrg      }
9832b578d3Smrg
9932b578d3Smrg      numConfigs = 1;
10032b578d3Smrg      if ( ATI_USE_ACCUM )   numConfigs *= 2;
10132b578d3Smrg      if ( ATI_USE_STENCIL ) numConfigs *= 2;
10232b578d3Smrg      numConfigs *= 2; /* single- and double-buffered */
10332b578d3Smrg
10432b578d3Smrg      pConfigs = (__GLXvisualConfig*)
10532b578d3Smrg	 xnfcalloc( sizeof(__GLXvisualConfig), numConfigs );
10632b578d3Smrg      if ( !pConfigs ) {
10732b578d3Smrg	 return FALSE;
10832b578d3Smrg      }
10932b578d3Smrg      pATIConfigs = (ATIConfigPrivPtr)
11032b578d3Smrg	 xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs );
11132b578d3Smrg      if ( !pATIConfigs ) {
1121b12faf6Smrg	 free( pConfigs );
11332b578d3Smrg	 return FALSE;
11432b578d3Smrg      }
11532b578d3Smrg      pATIConfigPtrs = (ATIConfigPrivPtr*)
11632b578d3Smrg	 xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs );
11732b578d3Smrg      if ( !pATIConfigPtrs ) {
1181b12faf6Smrg	 free( pConfigs );
1191b12faf6Smrg	 free( pATIConfigs );
12032b578d3Smrg	 return FALSE;
12132b578d3Smrg      }
12232b578d3Smrg
12332b578d3Smrg      i = 0;
12432b578d3Smrg      for (db = 1; db >= 0; db--) {
12532b578d3Smrg	 for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) {
12632b578d3Smrg	    for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) {
12732b578d3Smrg	       pATIConfigPtrs[i] = &pATIConfigs[i];
12832b578d3Smrg
12932b578d3Smrg	       pConfigs[i].vid			= -1;
13032b578d3Smrg	       pConfigs[i].class		= -1;
13132b578d3Smrg	       pConfigs[i].rgba			= TRUE;
13232b578d3Smrg	       pConfigs[i].redSize		= 5;
13332b578d3Smrg	       pConfigs[i].greenSize		= 6;
13432b578d3Smrg	       pConfigs[i].blueSize		= 5;
13532b578d3Smrg	       pConfigs[i].alphaSize		= 0;
13632b578d3Smrg	       pConfigs[i].redMask		= 0x0000F800;
13732b578d3Smrg	       pConfigs[i].greenMask		= 0x000007E0;
13832b578d3Smrg	       pConfigs[i].blueMask		= 0x0000001F;
13932b578d3Smrg	       pConfigs[i].alphaMask		= 0x00000000;
14032b578d3Smrg	       if ( accum ) {	/* Simulated in software */
14132b578d3Smrg		  pConfigs[i].accumRedSize	= 16;
14232b578d3Smrg		  pConfigs[i].accumGreenSize	= 16;
14332b578d3Smrg		  pConfigs[i].accumBlueSize	= 16;
14432b578d3Smrg		  pConfigs[i].accumAlphaSize	= 0;
14532b578d3Smrg	       } else {
14632b578d3Smrg		  pConfigs[i].accumRedSize	= 0;
14732b578d3Smrg		  pConfigs[i].accumGreenSize	= 0;
14832b578d3Smrg		  pConfigs[i].accumBlueSize	= 0;
14932b578d3Smrg		  pConfigs[i].accumAlphaSize	= 0;
15032b578d3Smrg	       }
15132b578d3Smrg	       pConfigs[i].doubleBuffer		= db ? TRUE : FALSE;
15232b578d3Smrg	       pConfigs[i].stereo		= FALSE;
15332b578d3Smrg	       pConfigs[i].bufferSize		= 16;
15432b578d3Smrg	       pConfigs[i].depthSize		= 16;
15532b578d3Smrg	       if ( stencil ) {	/* Simulated in software */
15632b578d3Smrg		  pConfigs[i].stencilSize	= 8;
15732b578d3Smrg	       } else {
15832b578d3Smrg		  pConfigs[i].stencilSize	= 0;
15932b578d3Smrg	       }
16032b578d3Smrg	       pConfigs[i].auxBuffers		= 0;
16132b578d3Smrg	       pConfigs[i].level		= 0;
16232b578d3Smrg	       if ( accum || stencil ) {
16332b578d3Smrg		  pConfigs[i].visualRating	= GLX_SLOW_CONFIG;
16432b578d3Smrg	       } else {
16532b578d3Smrg		  pConfigs[i].visualRating	= GLX_NONE;
16632b578d3Smrg	       }
16732b578d3Smrg	       pConfigs[i].transparentPixel	= GLX_NONE;
16832b578d3Smrg	       pConfigs[i].transparentRed	= 0;
16932b578d3Smrg	       pConfigs[i].transparentGreen	= 0;
17032b578d3Smrg	       pConfigs[i].transparentBlue	= 0;
17132b578d3Smrg	       pConfigs[i].transparentAlpha	= 0;
17232b578d3Smrg	       pConfigs[i].transparentIndex	= 0;
17332b578d3Smrg	       i++;
17432b578d3Smrg	    }
17532b578d3Smrg	 }
17632b578d3Smrg      }
17732b578d3Smrg      break;
17832b578d3Smrg
17932b578d3Smrg   case 32:
18032b578d3Smrg      numConfigs = 1;
18132b578d3Smrg      if ( ATI_USE_ACCUM )   numConfigs *= 2;
18232b578d3Smrg      if ( ATI_USE_STENCIL ) numConfigs *= 2;
18332b578d3Smrg      numConfigs *= 2; /* single- and double-buffered */
18432b578d3Smrg
18532b578d3Smrg      pConfigs = (__GLXvisualConfig*)
18632b578d3Smrg	 xnfcalloc( sizeof(__GLXvisualConfig), numConfigs );
18732b578d3Smrg      if ( !pConfigs ) {
18832b578d3Smrg	 return FALSE;
18932b578d3Smrg      }
19032b578d3Smrg      pATIConfigs = (ATIConfigPrivPtr)
19132b578d3Smrg	 xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs );
19232b578d3Smrg      if ( !pATIConfigs ) {
1931b12faf6Smrg	 free( pConfigs );
19432b578d3Smrg	 return FALSE;
19532b578d3Smrg      }
19632b578d3Smrg      pATIConfigPtrs = (ATIConfigPrivPtr*)
19732b578d3Smrg	 xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs );
19832b578d3Smrg      if ( !pATIConfigPtrs ) {
1991b12faf6Smrg	 free( pConfigs );
2001b12faf6Smrg	 free( pATIConfigs );
20132b578d3Smrg	 return FALSE;
20232b578d3Smrg      }
20332b578d3Smrg
20432b578d3Smrg      i = 0;
20532b578d3Smrg      for (db = 1; db >= 0; db--) {
20632b578d3Smrg	 for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) {
20732b578d3Smrg	    for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) {
20832b578d3Smrg	       pATIConfigPtrs[i] = &pATIConfigs[i];
20932b578d3Smrg
21032b578d3Smrg	       pConfigs[i].vid			= -1;
21132b578d3Smrg	       pConfigs[i].class		= -1;
21232b578d3Smrg	       pConfigs[i].rgba			= TRUE;
21332b578d3Smrg	       pConfigs[i].redSize		= 8;
21432b578d3Smrg	       pConfigs[i].greenSize		= 8;
21532b578d3Smrg	       pConfigs[i].blueSize		= 8;
21632b578d3Smrg	       pConfigs[i].alphaSize		= 0;
21732b578d3Smrg	       pConfigs[i].redMask		= 0x00FF0000;
21832b578d3Smrg	       pConfigs[i].greenMask		= 0x0000FF00;
21932b578d3Smrg	       pConfigs[i].blueMask		= 0x000000FF;
22032b578d3Smrg	       pConfigs[i].alphaMask		= 0x00000000;
22132b578d3Smrg	       if ( accum ) {	/* Simulated in software */
22232b578d3Smrg		  pConfigs[i].accumRedSize	= 16;
22332b578d3Smrg		  pConfigs[i].accumGreenSize	= 16;
22432b578d3Smrg		  pConfigs[i].accumBlueSize	= 16;
22532b578d3Smrg		  pConfigs[i].accumAlphaSize	= 0;
22632b578d3Smrg	       } else {
22732b578d3Smrg		  pConfigs[i].accumRedSize	= 0;
22832b578d3Smrg		  pConfigs[i].accumGreenSize	= 0;
22932b578d3Smrg		  pConfigs[i].accumBlueSize	= 0;
23032b578d3Smrg		  pConfigs[i].accumAlphaSize	= 0;
23132b578d3Smrg	       }
23232b578d3Smrg	       pConfigs[i].doubleBuffer		= db ? TRUE : FALSE;
23332b578d3Smrg	       pConfigs[i].stereo		= FALSE;
23432b578d3Smrg	       pConfigs[i].bufferSize		= 24;
23532b578d3Smrg	       if ( stencil ) {	/* Simulated in software */
23632b578d3Smrg		  pConfigs[i].depthSize		= 16;
23732b578d3Smrg		  pConfigs[i].stencilSize	= 8;
23832b578d3Smrg	       } else {
23932b578d3Smrg		  pConfigs[i].depthSize		= 16;
24032b578d3Smrg		  pConfigs[i].stencilSize	= 0;
24132b578d3Smrg	    }
24232b578d3Smrg	       pConfigs[i].auxBuffers		= 0;
24332b578d3Smrg	       pConfigs[i].level		= 0;
24432b578d3Smrg	       if ( accum || stencil ) {
24532b578d3Smrg		  pConfigs[i].visualRating	= GLX_SLOW_CONFIG;
24632b578d3Smrg	       } else {
24732b578d3Smrg		  pConfigs[i].visualRating	= GLX_NONE;
24832b578d3Smrg	    }
24932b578d3Smrg	       pConfigs[i].transparentPixel	= GLX_NONE;
25032b578d3Smrg	       pConfigs[i].transparentRed	= 0;
25132b578d3Smrg	       pConfigs[i].transparentGreen	= 0;
25232b578d3Smrg	       pConfigs[i].transparentBlue	= 0;
25332b578d3Smrg	       pConfigs[i].transparentAlpha	= 0;
25432b578d3Smrg	       pConfigs[i].transparentIndex	= 0;
25532b578d3Smrg	       i++;
25632b578d3Smrg	    }
25732b578d3Smrg	 }
25832b578d3Smrg      }
25932b578d3Smrg      break;
26032b578d3Smrg   }
26132b578d3Smrg
26232b578d3Smrg   pATI->numVisualConfigs = numConfigs;
26332b578d3Smrg   pATI->pVisualConfigs = pConfigs;
26432b578d3Smrg   pATI->pVisualConfigsPriv = pATIConfigs;
26532b578d3Smrg   GlxSetVisualConfigs( numConfigs, pConfigs, (void**)pATIConfigPtrs );
26632b578d3Smrg   return TRUE;
26732b578d3Smrg}
26832b578d3Smrg
26932b578d3Smrg/* Create the ATI-specific context information */
27032b578d3Smrgstatic Bool ATICreateContext( ScreenPtr pScreen, VisualPtr visual,
27132b578d3Smrg			      drm_context_t hwContext, void *pVisualConfigPriv,
27232b578d3Smrg			      DRIContextType contextStore )
27332b578d3Smrg{
27432b578d3Smrg   /* Nothing yet */
27532b578d3Smrg   return TRUE;
27632b578d3Smrg}
27732b578d3Smrg
27832b578d3Smrg/* Destroy the ATI-specific context information */
27932b578d3Smrgstatic void ATIDestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
28032b578d3Smrg			       DRIContextType contextStore )
28132b578d3Smrg{
28232b578d3Smrg   /* Nothing yet */
28332b578d3Smrg}
28432b578d3Smrg
28532b578d3Smrg/* Called when the X server is woken up to allow the last client's
28632b578d3Smrg * context to be saved and the X server's context to be loaded.
28732b578d3Smrg * The client detects when it's context is not currently loaded and
28832b578d3Smrg * then loads it itself.  The X server's context is loaded in the
28932b578d3Smrg * XAA Sync callback if NeedDRISync is set.
29032b578d3Smrg */
29132b578d3Smrgstatic void ATIEnterServer( ScreenPtr pScreen )
29232b578d3Smrg{
29332b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
29432b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
29532b578d3Smrg
29632b578d3Smrg   if ( pATI->directRenderingEnabled ) {
29732b578d3Smrg      ATIDRIMarkSyncInt(pScreenInfo);
29832b578d3Smrg      ATIDRIMarkSyncExt(pScreenInfo);
29932b578d3Smrg   }
30032b578d3Smrg}
30132b578d3Smrg
30232b578d3Smrg/* Called when the X server goes to sleep to allow the X server's
30332b578d3Smrg * context to be saved and the last client's context to be loaded.
30432b578d3Smrg * The client detects when it's context is not currently loaded and
30532b578d3Smrg * then loads it itself.  The X server keeps track of it's own state.
30632b578d3Smrg */
30732b578d3Smrgstatic void ATILeaveServer( ScreenPtr pScreen )
30832b578d3Smrg{
30932b578d3Smrg   /* Nothing yet */
31032b578d3Smrg}
31132b578d3Smrg
31232b578d3Smrg/* Contexts can be swapped by the X server if necessary.  This callback
31332b578d3Smrg * is currently only used to perform any functions necessary when
31432b578d3Smrg * entering or leaving the X server, and in the future might not be
31532b578d3Smrg * necessary.
31632b578d3Smrg */
31732b578d3Smrgstatic void ATIDRISwapContext( ScreenPtr pScreen,
31832b578d3Smrg			       DRISyncType syncType,
31932b578d3Smrg			       DRIContextType oldContextType,
32032b578d3Smrg			       void *oldContext,
32132b578d3Smrg			       DRIContextType newContextType,
32232b578d3Smrg			       void *newContext )
32332b578d3Smrg{
32432b578d3Smrg   if ( ( syncType == DRI_3D_SYNC ) && ( oldContextType == DRI_2D_CONTEXT ) &&
32532b578d3Smrg	( newContextType == DRI_2D_CONTEXT ) ) {
32632b578d3Smrg      /* Entering from Wakeup */
32732b578d3Smrg      ATIEnterServer( pScreen );
32832b578d3Smrg   }
32932b578d3Smrg   if ( ( syncType == DRI_2D_SYNC ) && ( oldContextType == DRI_NO_CONTEXT ) &&
33032b578d3Smrg	( newContextType == DRI_2D_CONTEXT ) ) {
33132b578d3Smrg      /* Exiting from Block Handler */
33232b578d3Smrg      ATILeaveServer( pScreen );
33332b578d3Smrg   }
33432b578d3Smrg}
33532b578d3Smrg
33632b578d3Smrg#ifdef USE_XAA
33732b578d3Smrgstatic void ATIDRITransitionTo2d(ScreenPtr pScreen)
33832b578d3Smrg{
33932b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
34032b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
34132b578d3Smrg
34232b578d3Smrg   if (pATI->backArea) {
34332b578d3Smrg      xf86FreeOffscreenArea(pATI->backArea);
34432b578d3Smrg      pATI->backArea = NULL;
34532b578d3Smrg   }
34632b578d3Smrg   if (pATI->depthTexArea) {
34732b578d3Smrg      xf86FreeOffscreenArea(pATI->depthTexArea);
34832b578d3Smrg      pATI->depthTexArea = NULL;
34932b578d3Smrg   }
35032b578d3Smrg   pATI->have3DWindows = FALSE;
35132b578d3Smrg}
35232b578d3Smrg
35332b578d3Smrgstatic void ATIDRITransitionTo3d(ScreenPtr pScreen)
35432b578d3Smrg{
35532b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
35632b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
35732b578d3Smrg   FBAreaPtr fbArea;
35832b578d3Smrg   int width, height;
35932b578d3Smrg
36032b578d3Smrg   xf86PurgeUnlockedOffscreenAreas(pScreen);
36132b578d3Smrg
36232b578d3Smrg   xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0);
36332b578d3Smrg
36432b578d3Smrg   xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
36532b578d3Smrg	      "Largest offscreen area available: %d x %d\n",
36632b578d3Smrg	      width, height);
36732b578d3Smrg
36832b578d3Smrg   fbArea = xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
36932b578d3Smrg				      height - pATI->depthTexLines -
37032b578d3Smrg				      pATI->backLines,
37132b578d3Smrg				      pScreenInfo->displayWidth, NULL, NULL, NULL);
37232b578d3Smrg
37332b578d3Smrg   if (!fbArea)
37432b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve placeholder "
37532b578d3Smrg		 "offscreen area, you might experience screen corruption\n");
37632b578d3Smrg
37732b578d3Smrg   if (!pATI->backArea) {
37832b578d3Smrg      pATI->backArea =
37932b578d3Smrg	 xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
38032b578d3Smrg				   pATI->backLines,
38132b578d3Smrg				   pScreenInfo->displayWidth,
38232b578d3Smrg				   NULL, NULL, NULL);
38332b578d3Smrg   }
38432b578d3Smrg   if (!pATI->backArea)
38532b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area "
38632b578d3Smrg		 "for back buffer, you might experience screen corruption\n");
38732b578d3Smrg
38832b578d3Smrg   if (!pATI->depthTexArea) {
38932b578d3Smrg      pATI->depthTexArea =
39032b578d3Smrg	 xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
39132b578d3Smrg				   pATI->depthTexLines,
39232b578d3Smrg				   pScreenInfo->displayWidth,
39332b578d3Smrg				   NULL, NULL, NULL);
39432b578d3Smrg   }
39532b578d3Smrg   if (!pATI->depthTexArea)
39632b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area "
39732b578d3Smrg		 "for depth buffer and textures, you might experience screen corruption\n");
39832b578d3Smrg
39932b578d3Smrg   if (fbArea)
40032b578d3Smrg      xf86FreeOffscreenArea(fbArea);
40132b578d3Smrg
40232b578d3Smrg   pATI->have3DWindows = TRUE;
40332b578d3Smrg}
40432b578d3Smrg#endif /* USE_XAA */
40532b578d3Smrg
40632b578d3Smrg#ifdef USE_EXA
40732b578d3Smrgstatic void ATIDRITransitionTo2d_EXA(ScreenPtr pScreen)
40832b578d3Smrg{
40932b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
41032b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
41132b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
41232b578d3Smrg
41332b578d3Smrg   exaEnableDisableFBAccess(pScreen->myNum, FALSE);
41432b578d3Smrg
41532b578d3Smrg   pATI->pExa->offScreenBase = pATIDRIServer->backOffset;
41632b578d3Smrg
41732b578d3Smrg   exaEnableDisableFBAccess(pScreen->myNum, TRUE);
41832b578d3Smrg
41932b578d3Smrg   pATI->have3DWindows = FALSE;
42032b578d3Smrg}
42132b578d3Smrg
42232b578d3Smrgstatic void ATIDRITransitionTo3d_EXA(ScreenPtr pScreen)
42332b578d3Smrg{
42432b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
42532b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
42632b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
42732b578d3Smrg
42832b578d3Smrg   exaEnableDisableFBAccess(pScreen->myNum, FALSE);
42932b578d3Smrg
43032b578d3Smrg   pATI->pExa->offScreenBase = pATIDRIServer->textureOffset +
43132b578d3Smrg			       pATIDRIServer->textureSize;
43232b578d3Smrg
43332b578d3Smrg   exaEnableDisableFBAccess(pScreen->myNum, TRUE);
43432b578d3Smrg
43532b578d3Smrg   pATI->have3DWindows = TRUE;
43632b578d3Smrg}
43732b578d3Smrg#endif /* USE_EXA */
43832b578d3Smrg
43932b578d3Smrg/* Initialize the state of the back and depth buffers. */
44032b578d3Smrgstatic void ATIDRIInitBuffers( WindowPtr pWin, RegionPtr prgn, CARD32 indx )
44132b578d3Smrg{
44232b578d3Smrg#ifdef USE_XAA
44332b578d3Smrg   ScreenPtr   pScreen = pWin->drawable.pScreen;
44432b578d3Smrg   ScrnInfoPtr pScreenInfo   = xf86Screens[pScreen->myNum];
44532b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
44632b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
44732b578d3Smrg   XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
44832b578d3Smrg   BoxPtr      pbox, pboxSave;
44932b578d3Smrg   int         nbox, nboxSave;
45032b578d3Smrg   int         depth;
45132b578d3Smrg
45232b578d3Smrg   depth = 0x0000ffff;
45332b578d3Smrg
45432b578d3Smrg   if (!pXAAInfo)
45532b578d3Smrg      return;
45632b578d3Smrg
45732b578d3Smrg   if (!pXAAInfo->SetupForSolidFill)
45832b578d3Smrg      return;
45932b578d3Smrg
46032b578d3Smrg   /* FIXME: Only initialize the back and depth buffers for contexts
46132b578d3Smrg      that request them */
46232b578d3Smrg
46332b578d3Smrg   /* FIXME: Use drm clear? (see Radeon driver) */
46432b578d3Smrg
46532b578d3Smrg   pboxSave = pbox = REGION_RECTS(prgn);
46632b578d3Smrg   nboxSave = nbox = REGION_NUM_RECTS(prgn);
46732b578d3Smrg
46832b578d3Smrg   (*pXAAInfo->SetupForSolidFill)(pScreenInfo, 0, GXcopy, (CARD32)(-1));
46932b578d3Smrg   for (; nbox; nbox--, pbox++) {
47032b578d3Smrg      (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
47132b578d3Smrg					      pbox->x1 + pATIDRIServer->fbX,
47232b578d3Smrg					      pbox->y1 + pATIDRIServer->fbY,
47332b578d3Smrg					      pbox->x2 - pbox->x1,
47432b578d3Smrg					      pbox->y2 - pbox->y1);
47532b578d3Smrg      (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
47632b578d3Smrg					      pbox->x1 + pATIDRIServer->backX,
47732b578d3Smrg					      pbox->y1 + pATIDRIServer->backY,
47832b578d3Smrg					      pbox->x2 - pbox->x1,
47932b578d3Smrg					      pbox->y2 - pbox->y1);
48032b578d3Smrg   }
48132b578d3Smrg
48232b578d3Smrg   pbox = pboxSave;
48332b578d3Smrg   nbox = nboxSave;
48432b578d3Smrg
48532b578d3Smrg   (*pXAAInfo->SetupForSolidFill)(pScreenInfo, depth, GXcopy, (CARD32)(-1));
48632b578d3Smrg   for (; nbox; nbox--, pbox++)
48732b578d3Smrg      (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
48832b578d3Smrg					      pbox->x1 + pATIDRIServer->depthX,
48932b578d3Smrg					      pbox->y1 + pATIDRIServer->depthY,
49032b578d3Smrg					      pbox->x2 - pbox->x1,
49132b578d3Smrg					      pbox->y2 - pbox->y1);
49232b578d3Smrg
49332b578d3Smrg   ATIDRIMarkSyncInt(pScreenInfo);
49432b578d3Smrg#endif
49532b578d3Smrg}
49632b578d3Smrg
49732b578d3Smrg/* Copy the back and depth buffers when the X server moves a window.
49832b578d3Smrg *
49932b578d3Smrg * Note: this function was copied from the Radeon driver...
50032b578d3Smrg *
50132b578d3Smrg * This routine is a modified form of XAADoBitBlt with the calls to
50232b578d3Smrg * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
50332b578d3Smrg * instead of destination. My origin is upside down so the ydir cases
50432b578d3Smrg * are reversed.
50532b578d3Smrg */
50632b578d3Smrgstatic void ATIDRIMoveBuffers( WindowPtr pWin, DDXPointRec ptOldOrg,
50732b578d3Smrg			       RegionPtr prgnSrc, CARD32 indx )
50832b578d3Smrg{
50932b578d3Smrg#ifdef USE_XAA
51032b578d3Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
51132b578d3Smrg    ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
51232b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
51332b578d3Smrg    XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
51432b578d3Smrg
51532b578d3Smrg    int backOffsetPitch =  (((pATI->pDRIServerInfo->backPitch/8) << 22) |
51632b578d3Smrg					   (pATI->pDRIServerInfo->backOffset >> 3));
51732b578d3Smrg#if 0
51832b578d3Smrg    int depthOffsetPitch = (((pATI->pDRIServerInfo->depthPitch/8) << 22) |
51932b578d3Smrg					   (pATI->pDRIServerInfo->depthOffset >> 3));
52032b578d3Smrg#endif
52132b578d3Smrg    BoxPtr        pboxTmp, pboxNext, pboxBase;
52232b578d3Smrg    DDXPointPtr   pptTmp;
52332b578d3Smrg    int           xdir, ydir;
52432b578d3Smrg
52532b578d3Smrg    int           screenwidth = pScreenInfo->virtualX;
52632b578d3Smrg    int           screenheight = pScreenInfo->virtualY;
52732b578d3Smrg
52832b578d3Smrg    BoxPtr        pbox     = REGION_RECTS(prgnSrc);
52932b578d3Smrg    int           nbox     = REGION_NUM_RECTS(prgnSrc);
53032b578d3Smrg
53132b578d3Smrg    BoxPtr        pboxNew1 = NULL;
53232b578d3Smrg    BoxPtr        pboxNew2 = NULL;
53332b578d3Smrg    DDXPointPtr   pptNew1  = NULL;
53432b578d3Smrg    DDXPointPtr   pptNew2  = NULL;
53532b578d3Smrg    DDXPointPtr   pptSrc   = &ptOldOrg;
53632b578d3Smrg
53732b578d3Smrg    int           dx       = pWin->drawable.x - ptOldOrg.x;
53832b578d3Smrg    int           dy       = pWin->drawable.y - ptOldOrg.y;
53932b578d3Smrg
54032b578d3Smrg   if (!pXAAInfo)
54132b578d3Smrg      return;
54232b578d3Smrg
54332b578d3Smrg   if (!pXAAInfo->SetupForScreenToScreenCopy)
54432b578d3Smrg      return;
54532b578d3Smrg
54632b578d3Smrg    /* FIXME: Only move the back and depth buffers for contexts
54732b578d3Smrg     * that request them.
54832b578d3Smrg     */
54932b578d3Smrg
55032b578d3Smrg    /* If the copy will overlap in Y, reverse the order */
55132b578d3Smrg    if (dy > 0) {
55232b578d3Smrg	ydir = -1;
55332b578d3Smrg
55432b578d3Smrg	if (nbox > 1) {
55532b578d3Smrg	    /* Keep ordering in each band, reverse order of bands */
5561b12faf6Smrg	    pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec)*nbox);
55732b578d3Smrg	    if (!pboxNew1) return;
5581b12faf6Smrg	    pptNew1 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox);
55932b578d3Smrg	    if (!pptNew1) {
5601b12faf6Smrg		free(pboxNew1);
56132b578d3Smrg		return;
56232b578d3Smrg	    }
56332b578d3Smrg	    pboxBase = pboxNext = pbox+nbox-1;
56432b578d3Smrg	    while (pboxBase >= pbox) {
56532b578d3Smrg		while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
56632b578d3Smrg		    pboxNext--;
56732b578d3Smrg		pboxTmp = pboxNext+1;
56832b578d3Smrg		pptTmp  = pptSrc + (pboxTmp - pbox);
56932b578d3Smrg		while (pboxTmp <= pboxBase) {
57032b578d3Smrg		    *pboxNew1++ = *pboxTmp++;
57132b578d3Smrg		    *pptNew1++  = *pptTmp++;
57232b578d3Smrg		}
57332b578d3Smrg		pboxBase = pboxNext;
57432b578d3Smrg	    }
57532b578d3Smrg	    pboxNew1 -= nbox;
57632b578d3Smrg	    pbox      = pboxNew1;
57732b578d3Smrg	    pptNew1  -= nbox;
57832b578d3Smrg	    pptSrc    = pptNew1;
57932b578d3Smrg	}
58032b578d3Smrg    } else {
58132b578d3Smrg	/* No changes required */
58232b578d3Smrg	ydir = 1;
58332b578d3Smrg    }
58432b578d3Smrg
58532b578d3Smrg    /* If the regions will overlap in X, reverse the order */
58632b578d3Smrg    if (dx > 0) {
58732b578d3Smrg	xdir = -1;
58832b578d3Smrg
58932b578d3Smrg	if (nbox > 1) {
59032b578d3Smrg	    /* reverse order of rects in each band */
5911b12faf6Smrg	    pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec)*nbox);
5921b12faf6Smrg	    pptNew2  = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox);
59332b578d3Smrg	    if (!pboxNew2 || !pptNew2) {
5941b12faf6Smrg		free(pptNew2);
5951b12faf6Smrg		free(pboxNew2);
5961b12faf6Smrg		free(pptNew1);
5971b12faf6Smrg		free(pboxNew1);
59832b578d3Smrg		return;
59932b578d3Smrg	    }
60032b578d3Smrg	    pboxBase = pboxNext = pbox;
60132b578d3Smrg	    while (pboxBase < pbox+nbox) {
60232b578d3Smrg		while ((pboxNext < pbox+nbox)
60332b578d3Smrg		       && (pboxNext->y1 == pboxBase->y1))
60432b578d3Smrg		    pboxNext++;
60532b578d3Smrg		pboxTmp = pboxNext;
60632b578d3Smrg		pptTmp  = pptSrc + (pboxTmp - pbox);
60732b578d3Smrg		while (pboxTmp != pboxBase) {
60832b578d3Smrg		    *pboxNew2++ = *--pboxTmp;
60932b578d3Smrg		    *pptNew2++  = *--pptTmp;
61032b578d3Smrg		}
61132b578d3Smrg		pboxBase = pboxNext;
61232b578d3Smrg	    }
61332b578d3Smrg	    pboxNew2 -= nbox;
61432b578d3Smrg	    pbox      = pboxNew2;
61532b578d3Smrg	    pptNew2  -= nbox;
61632b578d3Smrg	    pptSrc    = pptNew2;
61732b578d3Smrg	}
61832b578d3Smrg    } else {
61932b578d3Smrg	/* No changes are needed */
62032b578d3Smrg	xdir = 1;
62132b578d3Smrg    }
62232b578d3Smrg
62332b578d3Smrg    (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, xdir, ydir, GXcopy,
62432b578d3Smrg					       (CARD32)(-1), -1);
62532b578d3Smrg
62632b578d3Smrg    for (; nbox-- ; pbox++) {
62732b578d3Smrg	int xa    = pbox->x1;
62832b578d3Smrg	int ya    = pbox->y1;
62932b578d3Smrg	int destx = xa + dx;
63032b578d3Smrg	int desty = ya + dy;
63132b578d3Smrg	int w     = pbox->x2 - xa + 1;
63232b578d3Smrg	int h     = pbox->y2 - ya + 1;
63332b578d3Smrg
63432b578d3Smrg	if (destx < 0)                xa -= destx, w += destx, destx = 0;
63532b578d3Smrg	if (desty < 0)                ya -= desty, h += desty, desty = 0;
63632b578d3Smrg	if (destx + w > screenwidth)  w = screenwidth  - destx;
63732b578d3Smrg	if (desty + h > screenheight) h = screenheight - desty;
63832b578d3Smrg
63932b578d3Smrg	if (w <= 0) continue;
64032b578d3Smrg	if (h <= 0) continue;
64132b578d3Smrg
64232b578d3Smrg	ATIMach64WaitForFIFO(pATI, 2);
64332b578d3Smrg	outf(SRC_OFF_PITCH, backOffsetPitch);
64432b578d3Smrg	outf(DST_OFF_PITCH, backOffsetPitch);
64532b578d3Smrg
64632b578d3Smrg	(*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo,
64732b578d3Smrg						     xa, ya,
64832b578d3Smrg						     destx, desty,
64932b578d3Smrg						     w, h);
65032b578d3Smrg#if 0
65132b578d3Smrg	/* FIXME: Move depth buffers? */
65232b578d3Smrg	ATIMach64WaitForFIFO(pATI, 2);
65332b578d3Smrg	outf(SRC_OFF_PITCH, depthOffsetPitch);
65432b578d3Smrg	outf(DST_OFF_PITCH, depthOffsetPitch);
65532b578d3Smrg
65632b578d3Smrg	if (pATI->depthMoves)
65732b578d3Smrg	    ATIScreenToScreenCopyDepth(pScreenInfo,
65832b578d3Smrg					  xa, ya,
65932b578d3Smrg					  destx, desty,
66032b578d3Smrg					  w, h);
66132b578d3Smrg#endif
66232b578d3Smrg    }
66332b578d3Smrg
66432b578d3Smrg    ATIMach64WaitForFIFO(pATI, 2);
66532b578d3Smrg    outf(SRC_OFF_PITCH, pATI->NewHW.dst_off_pitch);
66632b578d3Smrg    outf(DST_OFF_PITCH, pATI->NewHW.src_off_pitch);
66732b578d3Smrg
6681b12faf6Smrg    free(pptNew2);
6691b12faf6Smrg    free(pboxNew2);
6701b12faf6Smrg    free(pptNew1);
6711b12faf6Smrg    free(pboxNew1);
67232b578d3Smrg
67332b578d3Smrg    ATIDRIMarkSyncInt(pScreenInfo);
67432b578d3Smrg#endif
67532b578d3Smrg}
67632b578d3Smrg
67732b578d3Smrg/* Compute log base 2 of val. */
67832b578d3Smrgstatic int Mach64MinBits(int val)
67932b578d3Smrg{
68032b578d3Smrg    int bits;
68132b578d3Smrg
68232b578d3Smrg    if (!val) return 1;
68332b578d3Smrg    for (bits = 0; val; val >>= 1, ++bits);
68432b578d3Smrg    return bits;
68532b578d3Smrg}
68632b578d3Smrg
68732b578d3Smrgstatic Bool ATIDRISetBufSize( ScreenPtr pScreen, unsigned int maxSize )
68832b578d3Smrg{
68932b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
69032b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
69132b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
69232b578d3Smrg
69332b578d3Smrg   if (pATI->OptionBufferSize) {
69432b578d3Smrg      if (pATI->OptionBufferSize < 1 || pATI->OptionBufferSize > maxSize  ) {
69532b578d3Smrg	 xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Illegal DMA buffers size: %d MB\n",
69632b578d3Smrg		     pATI->OptionBufferSize );
69732b578d3Smrg	 return FALSE;
69832b578d3Smrg      }
69932b578d3Smrg      if (pATI->OptionBufferSize > 2) {
70032b578d3Smrg	 xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Illegal DMA buffers size: %d MB\n",
70132b578d3Smrg		     pATI->OptionBufferSize );
70232b578d3Smrg	 xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Clamping DMA buffers size to 2 MB\n");
70332b578d3Smrg	 pATIDRIServer->bufferSize = 2;
70432b578d3Smrg      } else {
70532b578d3Smrg	 pATIDRIServer->bufferSize = pATI->OptionBufferSize;
70632b578d3Smrg	 xf86DrvMsg( pScreen->myNum, X_CONFIG, "[drm] Using %d MB for DMA buffers\n",
70732b578d3Smrg		     pATIDRIServer->bufferSize );
70832b578d3Smrg      }
70932b578d3Smrg   } else {
71032b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[drm] Using %d MB for DMA buffers\n",
71132b578d3Smrg		  pATIDRIServer->bufferSize );
71232b578d3Smrg   }
71332b578d3Smrg
71432b578d3Smrg   return TRUE;
71532b578d3Smrg}
71632b578d3Smrg
71732b578d3Smrgstatic Bool ATIDRISetAgpMode( ScreenPtr pScreen )
71832b578d3Smrg{
71932b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
72032b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
72132b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
72232b578d3Smrg
72332b578d3Smrg   unsigned long mode   = drmAgpGetMode( pATI->drmFD );        /* Default mode */
72432b578d3Smrg   unsigned int vendor = drmAgpVendorId( pATI->drmFD );
72532b578d3Smrg   unsigned int device = drmAgpDeviceId( pATI->drmFD );
72632b578d3Smrg
72732b578d3Smrg   if (pATI->OptionAGPMode > 0 && pATI->OptionAGPMode <= ATI_AGP_MAX_MODE) {
72832b578d3Smrg      pATIDRIServer->agpMode = pATI->OptionAGPMode;
72932b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using AGP %dx Mode\n",
73032b578d3Smrg		  pATIDRIServer->agpMode );
73132b578d3Smrg   } else if (pATI->OptionAGPMode > 0) {
73232b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Illegal AGP Mode: %d\n",
73332b578d3Smrg		  pATI->OptionAGPMode );
73432b578d3Smrg      return FALSE;
73532b578d3Smrg   } else {
73632b578d3Smrg      /* If no mode configured, use the default mode obtained from agpgart */
73732b578d3Smrg      if ( mode & AGP_MODE_2X ) {
73832b578d3Smrg	 pATIDRIServer->agpMode = 2;
73932b578d3Smrg      } else if ( mode & AGP_MODE_1X ) {
74032b578d3Smrg	 pATIDRIServer->agpMode = 1;
74132b578d3Smrg      }
74232b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using AGP %dx Mode\n",
74332b578d3Smrg		  pATIDRIServer->agpMode );
74432b578d3Smrg   }
74532b578d3Smrg
74632b578d3Smrg   mode &= ~AGP_MODE_MASK;
74732b578d3Smrg   switch ( pATIDRIServer->agpMode ) {
74832b578d3Smrg   case 2:          mode |= AGP_MODE_2X;
74932b578d3Smrg   case 1: default: mode |= AGP_MODE_1X;
75032b578d3Smrg   }
75132b578d3Smrg
75232b578d3Smrg   if (pATI->OptionAGPSize) {
75332b578d3Smrg      switch (pATI->OptionAGPSize) {
75432b578d3Smrg      case 128:
75532b578d3Smrg      case  64:
75632b578d3Smrg      case  32:
75732b578d3Smrg      case  16:
75832b578d3Smrg      case   8:
75932b578d3Smrg      case   4:
76032b578d3Smrg	 pATIDRIServer->agpSize = pATI->OptionAGPSize;
76132b578d3Smrg	 xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using %d MB AGP aperture\n",
76232b578d3Smrg		     pATIDRIServer->agpSize );
76332b578d3Smrg	 break;
76432b578d3Smrg      default:
76532b578d3Smrg	 xf86DrvMsg( pScreen->myNum, X_ERROR,
76632b578d3Smrg		     "[agp] Illegal aperture size %d MB\n", pATI->OptionAGPSize );
76732b578d3Smrg	 return FALSE;
76832b578d3Smrg      }
76932b578d3Smrg   } else {
77032b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using %d MB AGP aperture\n",
77132b578d3Smrg		  pATIDRIServer->agpSize );
77232b578d3Smrg   }
77332b578d3Smrg
77432b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
77532b578d3Smrg	       "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
77632b578d3Smrg	       mode, vendor, device,
77732b578d3Smrg	       PCI_DEV_VENDOR_ID(pATI->PCIInfo),
77832b578d3Smrg	       PCI_DEV_DEVICE_ID(pATI->PCIInfo) );
77932b578d3Smrg
78032b578d3Smrg   if ( drmAgpEnable( pATI->drmFD, mode ) < 0 ) {
78132b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
78232b578d3Smrg      drmAgpRelease( pATI->drmFD );
78332b578d3Smrg      return FALSE;
78432b578d3Smrg   }
78532b578d3Smrg
78632b578d3Smrg   return TRUE;
78732b578d3Smrg}
78832b578d3Smrg
78932b578d3Smrg/* Initialize the AGP state.  Request memory for use in AGP space, and
79032b578d3Smrg * initialize the Rage Pro registers to point to that memory.
79132b578d3Smrg */
79232b578d3Smrgstatic Bool ATIDRIAgpInit( ScreenPtr pScreen )
79332b578d3Smrg{
79432b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
79532b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
79632b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
79732b578d3Smrg
79832b578d3Smrg   int ret;
79932b578d3Smrg   unsigned long cntl;
80032b578d3Smrg   int s, l;
80132b578d3Smrg
80232b578d3Smrg   pATIDRIServer->agpSize = ATI_DEFAULT_AGP_SIZE;
80332b578d3Smrg   pATIDRIServer->agpMode = ATI_DEFAULT_AGP_MODE;
80432b578d3Smrg   pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
80532b578d3Smrg   pATIDRIServer->ringSize = 16; /* 16 kB ring */
80632b578d3Smrg
80732b578d3Smrg   if ( drmAgpAcquire( pATI->drmFD ) < 0 ) {
80832b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP not available\n" );
80932b578d3Smrg      return FALSE;
81032b578d3Smrg   }
81132b578d3Smrg
81232b578d3Smrg   if (!ATIDRISetAgpMode( pScreen ))
81332b578d3Smrg      return FALSE;
81432b578d3Smrg
81532b578d3Smrg   pATIDRIServer->agpOffset = 0;
81632b578d3Smrg
81732b578d3Smrg   ret = drmAgpAlloc( pATI->drmFD, pATIDRIServer->agpSize*1024*1024,
81832b578d3Smrg		      0, NULL, &pATIDRIServer->agpHandle );
81932b578d3Smrg   if ( ret < 0 ) {
82032b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
82132b578d3Smrg      drmAgpRelease( pATI->drmFD );
82232b578d3Smrg      return FALSE;
82332b578d3Smrg   }
82432b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
82532b578d3Smrg	       "[agp] %d kB allocated with handle 0x%08x\n",
82632b578d3Smrg	       pATIDRIServer->agpSize*1024, pATIDRIServer->agpHandle );
82732b578d3Smrg
82832b578d3Smrg   if ( drmAgpBind( pATI->drmFD, pATIDRIServer->agpHandle, pATIDRIServer->agpOffset) < 0 ) {
82932b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind\n" );
83032b578d3Smrg      drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
83132b578d3Smrg      drmAgpRelease( pATI->drmFD );
83232b578d3Smrg      return FALSE;
83332b578d3Smrg   }
83432b578d3Smrg
83532b578d3Smrg   xf86DrvMsg(pScreen->myNum, X_INFO,
83632b578d3Smrg	      "[agp] Using %d kB for DMA descriptor ring\n", pATIDRIServer->ringSize);
83732b578d3Smrg
83832b578d3Smrg   if ( !ATIDRISetBufSize( pScreen, pATIDRIServer->agpSize ) )
83932b578d3Smrg      return FALSE;
84032b578d3Smrg
84132b578d3Smrg   pATIDRIServer->agpTexSize    = pATIDRIServer->agpSize - pATIDRIServer->bufferSize;
84232b578d3Smrg
84332b578d3Smrg   /* Reserve space for the DMA descriptor ring */
84432b578d3Smrg   pATIDRIServer->ringStart   = pATIDRIServer->agpOffset;
84532b578d3Smrg   pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */
84632b578d3Smrg
84732b578d3Smrg   /* Reserve space for the vertex buffer */
84832b578d3Smrg   pATIDRIServer->bufferStart   = pATIDRIServer->ringStart + pATIDRIServer->ringMapSize;
84932b578d3Smrg   pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024;
85032b578d3Smrg
85132b578d3Smrg   /* Reserve the rest for AGP textures */
85232b578d3Smrg   pATIDRIServer->agpTexStart = pATIDRIServer->bufferStart + pATIDRIServer->bufferMapSize;
85332b578d3Smrg   s = (pATIDRIServer->agpSize*1024*1024 - pATIDRIServer->agpTexStart);
85432b578d3Smrg   l = Mach64MinBits((s-1) / MACH64_NR_TEX_REGIONS);
85532b578d3Smrg   if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY;
85632b578d3Smrg   pATIDRIServer->agpTexMapSize   = (s >> l) << l;
85732b578d3Smrg   pATIDRIServer->log2AGPTexGran  = l;
85832b578d3Smrg
85932b578d3Smrg   xf86DrvMsg(pScreen->myNum, X_INFO,
86032b578d3Smrg	      "[agp] Using %d kB for AGP textures\n", pATIDRIServer->agpTexMapSize/1024);
86132b578d3Smrg
86232b578d3Smrg   /* Map DMA descriptor ring */
86332b578d3Smrg   if ( drmAddMap( pATI->drmFD, pATIDRIServer->ringStart, pATIDRIServer->ringMapSize,
86432b578d3Smrg		   DRM_AGP, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) {
86532b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
86632b578d3Smrg		  "[agp] Could not add ring mapping\n" );
86732b578d3Smrg      return FALSE;
86832b578d3Smrg   }
86932b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
87032b578d3Smrg	       "[agp] ring handle = 0x%08x\n",
87132b578d3Smrg	       pATIDRIServer->ringHandle );
87232b578d3Smrg
87332b578d3Smrg   if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle,
87432b578d3Smrg		pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) {
87532b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
87632b578d3Smrg		  "[agp] Could not map ring\n" );
87732b578d3Smrg      return FALSE;
87832b578d3Smrg   }
87932b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
88032b578d3Smrg	       "[agp] Ring mapped at 0x%08lx\n",
88132b578d3Smrg	       (unsigned long)pATIDRIServer->ringMap );
88232b578d3Smrg
88332b578d3Smrg   /* Map vertex buffers */
88432b578d3Smrg   if ( drmAddMap( pATI->drmFD, pATIDRIServer->bufferStart, pATIDRIServer->bufferMapSize,
88532b578d3Smrg		   DRM_AGP, DRM_READ_ONLY, &pATIDRIServer->bufferHandle ) < 0 ) {
88632b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
88732b578d3Smrg		  "[agp] Could not add vertex buffers mapping\n" );
88832b578d3Smrg      return FALSE;
88932b578d3Smrg   }
89032b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
89132b578d3Smrg	       "[agp] vertex buffers handle = 0x%08x\n",
89232b578d3Smrg	       pATIDRIServer->bufferHandle );
89332b578d3Smrg
89432b578d3Smrg   if ( drmMap( pATI->drmFD, pATIDRIServer->bufferHandle,
89532b578d3Smrg		pATIDRIServer->bufferMapSize, &pATIDRIServer->bufferMap ) < 0 ) {
89632b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
89732b578d3Smrg		  "[agp] Could not map vertex buffers\n" );
89832b578d3Smrg      return FALSE;
89932b578d3Smrg   }
90032b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
90132b578d3Smrg	       "[agp] Vertex buffers mapped at 0x%08lx\n",
90232b578d3Smrg	       (unsigned long)pATIDRIServer->bufferMap );
90332b578d3Smrg
90432b578d3Smrg   /* Map AGP Textures */
90532b578d3Smrg   if (drmAddMap(pATI->drmFD, pATIDRIServer->agpTexStart, pATIDRIServer->agpTexMapSize,
90632b578d3Smrg		 DRM_AGP, 0, &pATIDRIServer->agpTexHandle) < 0) {
90732b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
90832b578d3Smrg		 "[agp] Could not add AGP texture region mapping\n");
90932b578d3Smrg      return FALSE;
91032b578d3Smrg   }
91132b578d3Smrg   xf86DrvMsg(pScreen->myNum, X_INFO,
91232b578d3Smrg	      "[agp] AGP texture region handle = 0x%08x\n",
91332b578d3Smrg	      pATIDRIServer->agpTexHandle);
91432b578d3Smrg
91532b578d3Smrg   if (drmMap(pATI->drmFD, pATIDRIServer->agpTexHandle, pATIDRIServer->agpTexMapSize,
91632b578d3Smrg	      &pATIDRIServer->agpTexMap) < 0) {
91732b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_ERROR,
91832b578d3Smrg		 "[agp] Could not map AGP texture region\n");
91932b578d3Smrg      return FALSE;
92032b578d3Smrg   }
92132b578d3Smrg   xf86DrvMsg(pScreen->myNum, X_INFO,
92232b578d3Smrg	      "[agp] AGP Texture region mapped at 0x%08lx\n",
92332b578d3Smrg	      (unsigned long)pATIDRIServer->agpTexMap);
92432b578d3Smrg
92532b578d3Smrg   /* Initialize Mach64's AGP registers */
92632b578d3Smrg   cntl  = inm( AGP_CNTL );
92732b578d3Smrg   cntl &= ~AGP_APER_SIZE_MASK;
92832b578d3Smrg   switch ( pATIDRIServer->agpSize ) {
92932b578d3Smrg   case 256: cntl |= AGP_APER_SIZE_256MB; break;
93032b578d3Smrg   case 128: cntl |= AGP_APER_SIZE_128MB; break;
93132b578d3Smrg   case  64: cntl |= AGP_APER_SIZE_64MB;  break;
93232b578d3Smrg   case  32: cntl |= AGP_APER_SIZE_32MB;  break;
93332b578d3Smrg   case  16: cntl |= AGP_APER_SIZE_16MB;  break;
93432b578d3Smrg   case   8: cntl |= AGP_APER_SIZE_8MB;   break;
93532b578d3Smrg   case   4: cntl |= AGP_APER_SIZE_4MB;   break;
93632b578d3Smrg   default:
93732b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
93832b578d3Smrg		  "[agp] Illegal aperture size %d kB\n",
93932b578d3Smrg		  pATIDRIServer->agpSize*1024 );
94032b578d3Smrg      return FALSE;
94132b578d3Smrg   }
94232b578d3Smrg
94332b578d3Smrg   /* 1 = DATA comes in clock in which TRDY sampled (default) */
94432b578d3Smrg   /* 0 = DATA comes in clock after TRDY sampled */
94532b578d3Smrg   cntl |= AGP_TRDY_MODE;
94632b578d3Smrg
94732b578d3Smrg   /* 1 = generate all reads as high priority */
94832b578d3Smrg   /* 0 = generate all reads as their default priority (default) */
94932b578d3Smrg   /* Setting this only works for me at AGP 1x mode (LLD) */
95032b578d3Smrg   if (pATIDRIServer->agpMode == 1) {
95132b578d3Smrg      cntl |= HIGH_PRIORITY_READ_EN;
95232b578d3Smrg   } else {
95332b578d3Smrg      cntl &= ~HIGH_PRIORITY_READ_EN;
95432b578d3Smrg   }
95532b578d3Smrg
95632b578d3Smrg   outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
95732b578d3Smrg   outm( AGP_CNTL, cntl );
95832b578d3Smrg
95932b578d3Smrg   return TRUE;
96032b578d3Smrg}
96132b578d3Smrg
96232b578d3Smrgstatic Bool ATIDRIPciInit( ScreenPtr pScreen )
96332b578d3Smrg{
96432b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
96532b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
96632b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
96732b578d3Smrg
96832b578d3Smrg   pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
96932b578d3Smrg   pATIDRIServer->ringSize = 16; /* 16 kB ring */
97032b578d3Smrg
97132b578d3Smrg   if ( !ATIDRISetBufSize( pScreen, (unsigned)(-1) ) )
97232b578d3Smrg      return FALSE;
97332b578d3Smrg
97432b578d3Smrg   /* Set size of the DMA descriptor ring */
97532b578d3Smrg   pATIDRIServer->ringStart   = 0;
97632b578d3Smrg   pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */
97732b578d3Smrg
97832b578d3Smrg   /* Set size of the vertex buffer */
97932b578d3Smrg   pATIDRIServer->bufferStart   = 0;
98032b578d3Smrg   pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024;
98132b578d3Smrg
98232b578d3Smrg   /* Map DMA descriptor ring */
98332b578d3Smrg   if ( drmAddMap( pATI->drmFD, 0, pATIDRIServer->ringMapSize,
98432b578d3Smrg		   DRM_CONSISTENT, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) {
98532b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
98632b578d3Smrg		  "[pci] Could not add ring mapping\n" );
98732b578d3Smrg      return FALSE;
98832b578d3Smrg   }
98932b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO, "[pci] ring handle = 0x%08x\n",
99032b578d3Smrg	       pATIDRIServer->ringHandle );
99132b578d3Smrg
99232b578d3Smrg   if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle,
99332b578d3Smrg		pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) {
99432b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
99532b578d3Smrg		  "[pci] Could not map ring\n" );
99632b578d3Smrg      return FALSE;
99732b578d3Smrg   }
99832b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
99932b578d3Smrg	       "[pci] Ring mapped at 0x%08lx\n",
100032b578d3Smrg	       (unsigned long)pATIDRIServer->ringMap );
100132b578d3Smrg
100232b578d3Smrg   /* Disable AGP for ForcePCIMode */
100332b578d3Smrg   if ( pATI->BusType != ATI_BUS_PCI ) {
100432b578d3Smrg       outm( AGP_BASE, 0 );
100532b578d3Smrg       outm( AGP_CNTL, 0 );
100632b578d3Smrg   }
100732b578d3Smrg
100832b578d3Smrg   return TRUE;
100932b578d3Smrg}
101032b578d3Smrg
101132b578d3Smrg/* Add a map for the MMIO registers that will be accessed by any
101232b578d3Smrg * DRI-based clients.
101332b578d3Smrg */
101432b578d3Smrgstatic Bool ATIDRIMapInit( ScreenPtr pScreen )
101532b578d3Smrg{
101632b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
101732b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
101832b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
101932b578d3Smrg
102032b578d3Smrg   pATIDRIServer->regsSize = getpagesize();
102132b578d3Smrg   if ( drmAddMap( pATI->drmFD, pATI->Block1Base,
102232b578d3Smrg		   pATIDRIServer->regsSize,
102332b578d3Smrg		   DRM_REGISTERS, DRM_READ_ONLY,
102432b578d3Smrg		   &pATIDRIServer->regsHandle ) < 0 ) {
102532b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
102632b578d3Smrg		  "[drm] failed to map registers\n" );
102732b578d3Smrg      return FALSE;
102832b578d3Smrg   }
102932b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
103032b578d3Smrg	       "[drm] register handle = 0x%08x\n",
103132b578d3Smrg	       pATIDRIServer->regsHandle );
103232b578d3Smrg
103332b578d3Smrg   return TRUE;
103432b578d3Smrg}
103532b578d3Smrg
103632b578d3Smrg/* Initialize the kernel data structures. */
103732b578d3Smrgstatic Bool ATIDRIKernelInit( ScreenPtr pScreen )
103832b578d3Smrg{
103932b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
104032b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
104132b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
104232b578d3Smrg   drmMach64Init info;
104332b578d3Smrg
104432b578d3Smrg   memset( &info, 0, sizeof(drmMach64Init) );
104532b578d3Smrg
104632b578d3Smrg   info.func 			= DRM_MACH64_INIT_DMA;
104732b578d3Smrg   info.sarea_priv_offset	= sizeof(XF86DRISAREARec);
104832b578d3Smrg   info.is_pci			= pATIDRIServer->IsPCI;
104932b578d3Smrg   info.dma_mode                = pATI->OptionDMAMode;
105032b578d3Smrg
105132b578d3Smrg   info.fb_bpp			= pATI->bitsPerPixel;
105232b578d3Smrg   info.front_offset		= pATIDRIServer->frontOffset;
105332b578d3Smrg   info.front_pitch		= pATIDRIServer->frontPitch;
105432b578d3Smrg   info.back_offset		= pATIDRIServer->backOffset;
105532b578d3Smrg   info.back_pitch		= pATIDRIServer->backPitch;
105632b578d3Smrg
105732b578d3Smrg   info.depth_bpp		= 16;
105832b578d3Smrg   info.depth_offset		= pATIDRIServer->depthOffset;
105932b578d3Smrg   info.depth_pitch		= pATIDRIServer->depthPitch;
106032b578d3Smrg
106132b578d3Smrg   info.fb_offset		= pATI->LinearBase;
106232b578d3Smrg   info.mmio_offset		= pATIDRIServer->regsHandle;
106332b578d3Smrg   info.ring_offset		= pATIDRIServer->ringHandle;
106432b578d3Smrg   info.buffers_offset		= pATIDRIServer->bufferHandle;
106532b578d3Smrg   info.agp_textures_offset	= pATIDRIServer->agpTexHandle;
106632b578d3Smrg
106732b578d3Smrg   if ( drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
106832b578d3Smrg			 &info, sizeof(drmMach64Init) ) < 0 ) {
106932b578d3Smrg      return FALSE;
107032b578d3Smrg   } else {
107132b578d3Smrg      return TRUE;
107232b578d3Smrg   }
107332b578d3Smrg}
107432b578d3Smrg
107532b578d3Smrg/* Add a map for the DMA buffers that will be accessed by any
107632b578d3Smrg * DRI-based clients.
107732b578d3Smrg */
107832b578d3Smrgstatic Bool ATIDRIAddBuffers( ScreenPtr pScreen )
107932b578d3Smrg{
108032b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
108132b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
108232b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
108332b578d3Smrg
108432b578d3Smrg   /* Initialize vertex buffers */
108532b578d3Smrg   if ( pATIDRIServer->IsPCI ) {
108632b578d3Smrg      pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
108732b578d3Smrg					      pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE,
108832b578d3Smrg					      MACH64_BUFFER_SIZE,
108932b578d3Smrg					      DRM_PCI_BUFFER_RO,
109032b578d3Smrg					      0 );
109132b578d3Smrg   } else {
109232b578d3Smrg      pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
109332b578d3Smrg					      pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE,
109432b578d3Smrg					      MACH64_BUFFER_SIZE,
109532b578d3Smrg					      DRM_AGP_BUFFER,
109632b578d3Smrg					      pATIDRIServer->bufferStart );
109732b578d3Smrg   }
109832b578d3Smrg   if ( pATIDRIServer->numBuffers <= 0 ) {
109932b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
110032b578d3Smrg		  "[drm] Could not create DMA buffers list\n" );
110132b578d3Smrg      return FALSE;
110232b578d3Smrg   }
110332b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
110432b578d3Smrg	       "[drm] Added %d %d byte DMA buffers\n",
110532b578d3Smrg	       pATIDRIServer->numBuffers, MACH64_BUFFER_SIZE );
110632b578d3Smrg
110732b578d3Smrg    return TRUE;
110832b578d3Smrg}
110932b578d3Smrg
111032b578d3Smrgstatic Bool ATIDRIMapBuffers( ScreenPtr pScreen )
111132b578d3Smrg{
111232b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
111332b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
111432b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
111532b578d3Smrg
111632b578d3Smrg   pATIDRIServer->drmBuffers = drmMapBufs( pATI->drmFD );
111732b578d3Smrg   if ( !pATIDRIServer->drmBuffers ) {
111832b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
111932b578d3Smrg		  "[drm] Failed to map DMA buffers list\n" );
112032b578d3Smrg      return FALSE;
112132b578d3Smrg   }
112232b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
112332b578d3Smrg	       "[drm] Mapped %d DMA buffers at 0x%08lx\n",
112432b578d3Smrg	       pATIDRIServer->drmBuffers->count,
112532b578d3Smrg	       (unsigned long)pATIDRIServer->drmBuffers->list->address );
112632b578d3Smrg
112732b578d3Smrg   return TRUE;
112832b578d3Smrg}
112932b578d3Smrg
113032b578d3Smrgstatic Bool ATIDRIIrqInit( ScreenPtr pScreen )
113132b578d3Smrg{
113232b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
113332b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
113432b578d3Smrg
113532b578d3Smrg   if ( pATI->irq <= 0 ) {
113632b578d3Smrg      pATI->irq = drmGetInterruptFromBusID(pATI->drmFD,
113732b578d3Smrg					   PCI_CFG_BUS(pATI->PCIInfo),
113832b578d3Smrg					   PCI_CFG_DEV(pATI->PCIInfo),
113932b578d3Smrg					   PCI_CFG_FUNC(pATI->PCIInfo));
114032b578d3Smrg      if ( pATI->irq <= 0 ) {
114132b578d3Smrg	 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
114232b578d3Smrg		    "[drm] Couldn't find IRQ for bus id %d:%d:%d\n",
114332b578d3Smrg		    PCI_CFG_BUS(pATI->PCIInfo),
114432b578d3Smrg		    PCI_CFG_DEV(pATI->PCIInfo),
114532b578d3Smrg		    PCI_CFG_FUNC(pATI->PCIInfo));
114632b578d3Smrg	 pATI->irq = 0;
114732b578d3Smrg      } else if ((drmCtlInstHandler(pATI->drmFD, pATI->irq)) != 0) {
114832b578d3Smrg 	 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
114932b578d3Smrg		    "[drm] Failed to initialize interrupt handler with IRQ %d\n",
115032b578d3Smrg		    pATI->irq);
115132b578d3Smrg	 pATI->irq = 0;
115232b578d3Smrg      }
115332b578d3Smrg
115432b578d3Smrg      if (pATI->irq)
115532b578d3Smrg	 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
115632b578d3Smrg		    "[drm] Installed interrupt handler, using IRQ %d\n",
115732b578d3Smrg		    pATI->irq);
115832b578d3Smrg      else {
115932b578d3Smrg	 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
116032b578d3Smrg		    "[drm] Falling back to irq-free operation\n");
116132b578d3Smrg	 return FALSE;
116232b578d3Smrg      }
116332b578d3Smrg   }
116432b578d3Smrg
116532b578d3Smrg   return TRUE;
116632b578d3Smrg
116732b578d3Smrg}
116832b578d3Smrg
116932b578d3Smrg/* Initialize the screen-specific data structures for the DRI and the
117032b578d3Smrg * Rage Pro.  This is the main entry point to the device-specific
117132b578d3Smrg * initialization code.  It calls device-independent DRI functions to
117232b578d3Smrg * create the DRI data structures and initialize the DRI state.
117332b578d3Smrg */
117432b578d3SmrgBool ATIDRIScreenInit( ScreenPtr pScreen )
117532b578d3Smrg{
117632b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
117732b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
117832b578d3Smrg   DRIInfoPtr pDRIInfo;
117932b578d3Smrg   ATIDRIPtr pATIDRI;
118032b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer;
118132b578d3Smrg   drmVersionPtr version;
118232b578d3Smrg   int major, minor, patch;
118332b578d3Smrg
118432b578d3Smrg   /* Check that the GLX, DRI, and DRM modules have been loaded by testing
118532b578d3Smrg    * for known symbols in each module.
118632b578d3Smrg    */
118732b578d3Smrg   if ( !xf86LoaderCheckSymbol("GlxSetVisualConfigs") ) return FALSE;
118832b578d3Smrg   if ( !xf86LoaderCheckSymbol("drmAvailable") ) return FALSE;
118932b578d3Smrg   if ( !xf86LoaderCheckSymbol("DRIQueryVersion") ) {
119032b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
119132b578d3Smrg		  "[dri] ATIDRIScreenInit failed (libdri.a too old)\n" );
119232b578d3Smrg      return FALSE;
119332b578d3Smrg   }
119432b578d3Smrg
119532b578d3Smrg   /* Check the DRI version */
119632b578d3Smrg   DRIQueryVersion( &major, &minor, &patch );
119732b578d3Smrg   if ( major != DRIINFO_MAJOR_VERSION || minor < 0 ) {
119832b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
119932b578d3Smrg		  "[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
120032b578d3Smrg		  "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n"
120132b578d3Smrg		  "[dri] Disabling the DRI.\n",
120232b578d3Smrg		  major, minor, patch,
120332b578d3Smrg                  DRIINFO_MAJOR_VERSION, 0 );
120432b578d3Smrg      return FALSE;
120532b578d3Smrg   }
120632b578d3Smrg
120732b578d3Smrg   switch ( pATI->bitsPerPixel ) {
120832b578d3Smrg   case 8:
120932b578d3Smrg      /* These modes are not supported (yet). */
121032b578d3Smrg   case 15:
121132b578d3Smrg   case 24:
121232b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
121332b578d3Smrg		  "[dri] Direct rendering only supported in 16 and 32 bpp modes\n");
121432b578d3Smrg      return FALSE;
121532b578d3Smrg
121632b578d3Smrg      /* Only 16 and 32 color depths are supported currently. */
121732b578d3Smrg   case 16:
121832b578d3Smrg      if ( pATI->depth != 16) {
121932b578d3Smrg	 xf86DrvMsg( pScreen->myNum, X_ERROR,
122032b578d3Smrg		  "[dri] Direct rendering not supported for depth %d at fbbpp 16.\n", pATI->depth );
122132b578d3Smrg	 return FALSE;
122232b578d3Smrg      }
122332b578d3Smrg      break;
122432b578d3Smrg   case 32:
122532b578d3Smrg      break;
122632b578d3Smrg   }
122732b578d3Smrg
122832b578d3Smrg   /* Create the DRI data structure, and fill it in before calling the
122932b578d3Smrg    * DRIScreenInit().
123032b578d3Smrg    */
123132b578d3Smrg   pDRIInfo = DRICreateInfoRec();
123232b578d3Smrg   if ( !pDRIInfo ) return FALSE;
123332b578d3Smrg
123432b578d3Smrg   pATI->pDRIInfo = pDRIInfo;
123532b578d3Smrg   pDRIInfo->drmDriverName = ATIKernelDriverName;
123632b578d3Smrg   pDRIInfo->clientDriverName = ATIClientDriverName;
123732b578d3Smrg   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
123832b578d3Smrg      pDRIInfo->busIdString = DRICreatePCIBusID(pATI->PCIInfo);
123932b578d3Smrg   } else {
12401b12faf6Smrg      pDRIInfo->busIdString = malloc( 64 );
124132b578d3Smrg      sprintf( pDRIInfo->busIdString,
124232b578d3Smrg	       "PCI:%d:%d:%d",
124332b578d3Smrg	       PCI_DEV_BUS(pATI->PCIInfo),
124432b578d3Smrg	       PCI_DEV_DEV(pATI->PCIInfo),
124532b578d3Smrg	       PCI_DEV_FUNC(pATI->PCIInfo) );
124632b578d3Smrg   }
124732b578d3Smrg   pDRIInfo->ddxDriverMajorVersion = MACH64_VERSION_MAJOR;
124832b578d3Smrg   pDRIInfo->ddxDriverMinorVersion = MACH64_VERSION_MINOR;
124932b578d3Smrg   pDRIInfo->ddxDriverPatchVersion = MACH64_VERSION_PATCH;
125032b578d3Smrg   pDRIInfo->frameBufferPhysicalAddress = (void *)pATI->LinearBase;
125132b578d3Smrg   pDRIInfo->frameBufferSize = pATI->LinearSize;
125232b578d3Smrg   pDRIInfo->frameBufferStride = (pScreenInfo->displayWidth *
125332b578d3Smrg				  pATI->FBBytesPerPixel);
125432b578d3Smrg   pDRIInfo->ddxDrawableTableEntry = ATI_MAX_DRAWABLES;
125532b578d3Smrg
125632b578d3Smrg   if ( SAREA_MAX_DRAWABLES < ATI_MAX_DRAWABLES ) {
125732b578d3Smrg      pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
125832b578d3Smrg   } else {
125932b578d3Smrg      pDRIInfo->maxDrawableTableEntry = ATI_MAX_DRAWABLES;
126032b578d3Smrg   }
126132b578d3Smrg
126232b578d3Smrg   /* For now the mapping works by using a fixed size defined
126332b578d3Smrg    * in the SAREA header
126432b578d3Smrg    */
126532b578d3Smrg   if ( sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec) > SAREA_MAX ) {
126632b578d3Smrg      ErrorF( "[dri] Data does not fit in SAREA\n" );
126732b578d3Smrg      return FALSE;
126832b578d3Smrg   }
126932b578d3Smrg   xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %u+%u: %u\n",
127032b578d3Smrg	       (unsigned)sizeof(XF86DRISAREARec),
127132b578d3Smrg	       (unsigned)sizeof(ATISAREAPrivRec),
127232b578d3Smrg	       (unsigned)(sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec)) );
127332b578d3Smrg   pDRIInfo->SAREASize = SAREA_MAX;
127432b578d3Smrg
127532b578d3Smrg   pATIDRI = (ATIDRIPtr) xnfcalloc( sizeof(ATIDRIRec), 1 );
127632b578d3Smrg   if ( !pATIDRI ) {
127732b578d3Smrg      DRIDestroyInfoRec( pATI->pDRIInfo );
127832b578d3Smrg      pATI->pDRIInfo = NULL;
127932b578d3Smrg      xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
128032b578d3Smrg		  "[dri] Failed to allocate memory for private record\n" );
128132b578d3Smrg      return FALSE;
128232b578d3Smrg   }
128332b578d3Smrg   pATIDRIServer = (ATIDRIServerInfoPtr)
128432b578d3Smrg      xnfcalloc( sizeof(ATIDRIServerInfoRec), 1 );
128532b578d3Smrg   if ( !pATIDRIServer ) {
12861b12faf6Smrg      free( pATIDRI );
128732b578d3Smrg      DRIDestroyInfoRec( pATI->pDRIInfo );
128832b578d3Smrg      pATI->pDRIInfo = NULL;
128932b578d3Smrg      xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
129032b578d3Smrg		  "[dri] Failed to allocate memory for private record\n" );
129132b578d3Smrg      return FALSE;
129232b578d3Smrg   }
129332b578d3Smrg
129432b578d3Smrg   pATI->pDRIServerInfo = pATIDRIServer;
129532b578d3Smrg
129632b578d3Smrg   pDRIInfo->devPrivate		= pATIDRI;
129732b578d3Smrg   pDRIInfo->devPrivateSize	= sizeof(ATIDRIRec);
129832b578d3Smrg   pDRIInfo->contextSize	= sizeof(ATIDRIContextRec);
129932b578d3Smrg
130032b578d3Smrg   pDRIInfo->CreateContext	= ATICreateContext;
130132b578d3Smrg   pDRIInfo->DestroyContext	= ATIDestroyContext;
130232b578d3Smrg   pDRIInfo->SwapContext	= ATIDRISwapContext;
130332b578d3Smrg   pDRIInfo->InitBuffers	= ATIDRIInitBuffers;
130432b578d3Smrg   pDRIInfo->MoveBuffers	= ATIDRIMoveBuffers;
130532b578d3Smrg#ifdef USE_XAA
130632b578d3Smrg   if (!pATI->useEXA) {
130732b578d3Smrg      pDRIInfo->TransitionTo2d  = ATIDRITransitionTo2d;
130832b578d3Smrg      pDRIInfo->TransitionTo3d  = ATIDRITransitionTo3d;
130932b578d3Smrg   }
131032b578d3Smrg#endif /* USE_XAA */
131132b578d3Smrg#ifdef USE_EXA
131232b578d3Smrg   if (pATI->useEXA) {
131332b578d3Smrg      pDRIInfo->TransitionTo2d  = ATIDRITransitionTo2d_EXA;
131432b578d3Smrg      pDRIInfo->TransitionTo3d  = ATIDRITransitionTo3d_EXA;
131532b578d3Smrg   }
131632b578d3Smrg#endif /* USE_EXA */
131732b578d3Smrg   pDRIInfo->bufferRequests	= DRI_ALL_WINDOWS;
131832b578d3Smrg
131932b578d3Smrg   pDRIInfo->createDummyCtx     = TRUE;
132032b578d3Smrg   pDRIInfo->createDummyCtxPriv = FALSE;
132132b578d3Smrg
132232b578d3Smrg   pATI->have3DWindows = FALSE;
132332b578d3Smrg
132432b578d3Smrg   if ( !DRIScreenInit( pScreen, pDRIInfo, &pATI->drmFD ) ) {
13251b12faf6Smrg      free( pATIDRIServer );
132632b578d3Smrg      pATI->pDRIServerInfo = NULL;
13271b12faf6Smrg      free( pDRIInfo->devPrivate );
132832b578d3Smrg      pDRIInfo->devPrivate = NULL;
132932b578d3Smrg      DRIDestroyInfoRec( pDRIInfo );
133032b578d3Smrg      pDRIInfo = NULL;
133132b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
133232b578d3Smrg		  "[dri] DRIScreenInit Failed\n" );
133332b578d3Smrg      return FALSE;
133432b578d3Smrg   }
133532b578d3Smrg
133632b578d3Smrg   /* Check the DRM lib version.
133732b578d3Smrg      drmGetLibVersion was not supported in version 1.0, so check for
133832b578d3Smrg      symbol first to avoid possible crash or hang.
133932b578d3Smrg   */
134032b578d3Smrg   if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
134132b578d3Smrg      version = drmGetLibVersion(pATI->drmFD);
134232b578d3Smrg   } else {
134332b578d3Smrg      /* drmlib version 1.0.0 didn't have the drmGetLibVersion
134432b578d3Smrg	 entry point.  Fake it by allocating a version record
134532b578d3Smrg	 via drmGetVersion and changing it to version 1.0.0
134632b578d3Smrg      */
134732b578d3Smrg      version = drmGetVersion(pATI->drmFD);
134832b578d3Smrg      version->version_major      = 1;
134932b578d3Smrg      version->version_minor      = 0;
135032b578d3Smrg      version->version_patchlevel = 0;
135132b578d3Smrg   }
135232b578d3Smrg
135332b578d3Smrg   if (version) {
135432b578d3Smrg      if (version->version_major != 1 ||
135532b578d3Smrg	  version->version_minor < 1) {
135632b578d3Smrg	 /* incompatible drm library version */
135732b578d3Smrg	 xf86DrvMsg(pScreen->myNum, X_ERROR,
135832b578d3Smrg		    "[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
135932b578d3Smrg		    "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
136032b578d3Smrg		    "[dri] Disabling DRI.\n",
136132b578d3Smrg		    version->version_major,
136232b578d3Smrg		    version->version_minor,
136332b578d3Smrg		    version->version_patchlevel);
136432b578d3Smrg	 drmFreeVersion(version);
136532b578d3Smrg	 ATIDRICloseScreen(pScreen);
136632b578d3Smrg	 return FALSE;
136732b578d3Smrg      }
136832b578d3Smrg      drmFreeVersion(version);
136932b578d3Smrg   }
137032b578d3Smrg
137132b578d3Smrg   /* Check the mach64 DRM version */
137232b578d3Smrg   version = drmGetVersion( pATI->drmFD );
137332b578d3Smrg   if ( version ) {
137432b578d3Smrg      if ( version->version_major != 2 ||
137532b578d3Smrg	   version->version_minor < 0 ) {
137632b578d3Smrg	 /* Incompatible DRM version */
137732b578d3Smrg	 xf86DrvMsg( pScreen->myNum, X_ERROR,
137832b578d3Smrg		     "[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
137932b578d3Smrg		     "[dri] mach64.o kernel module version is %d.%d.%d, but version 2.x is needed (with 2.x >= 2.0).\n"
138032b578d3Smrg		     "[dri] Disabling DRI.\n",
138132b578d3Smrg		     version->version_major,
138232b578d3Smrg		     version->version_minor,
138332b578d3Smrg		     version->version_patchlevel );
138432b578d3Smrg	 drmFreeVersion( version );
138532b578d3Smrg	 ATIDRICloseScreen( pScreen );
138632b578d3Smrg	 return FALSE;
138732b578d3Smrg      }
138832b578d3Smrg      drmFreeVersion( version );
138932b578d3Smrg   }
139032b578d3Smrg
139132b578d3Smrg   switch ( pATI->OptionDMAMode ) {
139232b578d3Smrg   case MACH64_MODE_DMA_ASYNC:
139332b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request asynchronous DMA mode\n");
139432b578d3Smrg      break;
139532b578d3Smrg   case MACH64_MODE_DMA_SYNC:
139632b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request synchronous DMA mode\n");
139732b578d3Smrg      break;
139832b578d3Smrg   case MACH64_MODE_MMIO:
139932b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request pseudo-DMA (MMIO) mode\n");
140032b578d3Smrg      break;
140132b578d3Smrg   default:
140232b578d3Smrg      xf86DrvMsg(pScreen->myNum, X_WARNING, "[drm] Unknown DMA mode\n");
140332b578d3Smrg   }
140432b578d3Smrg
140532b578d3Smrg   pATIDRIServer->IsPCI = (pATI->BusType == ATI_BUS_PCI || pATI->OptionIsPCI) ? TRUE : FALSE;
140632b578d3Smrg
140732b578d3Smrg   if ( pATI->BusType != ATI_BUS_PCI && pATI->OptionIsPCI ) {
140832b578d3Smrg       xf86DrvMsg(pScreen->myNum, X_CONFIG, "[dri] Forcing PCI mode\n");
140932b578d3Smrg   }
141032b578d3Smrg
141132b578d3Smrg   /* Initialize AGP */
141232b578d3Smrg   if ( !pATIDRIServer->IsPCI && !ATIDRIAgpInit( pScreen ) ) {
141332b578d3Smrg      pATIDRIServer->IsPCI = TRUE;
141432b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP failed to initialize -- falling back to PCI mode.\n" );
141532b578d3Smrg      xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] Make sure you have the agpgart kernel module loaded.\n" );
141632b578d3Smrg   }
141732b578d3Smrg
141832b578d3Smrg   /* Initialize PCI */
141932b578d3Smrg   if ( pATIDRIServer->IsPCI && !ATIDRIPciInit( pScreen ) ) {
142032b578d3Smrg      ATIDRICloseScreen( pScreen );
142132b578d3Smrg      return FALSE;
142232b578d3Smrg   }
142332b578d3Smrg
142432b578d3Smrg   if ( !ATIDRIMapInit( pScreen ) ) {
142532b578d3Smrg      ATIDRICloseScreen( pScreen );
142632b578d3Smrg      return FALSE;
142732b578d3Smrg   }
142832b578d3Smrg
142932b578d3Smrg   if ( !ATIInitVisualConfigs( pScreen ) ) {
143032b578d3Smrg      ATIDRICloseScreen( pScreen );
143132b578d3Smrg      return FALSE;
143232b578d3Smrg   }
143332b578d3Smrg   xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
143432b578d3Smrg	       "[dri] Visual configs initialized\n" );
143532b578d3Smrg
143632b578d3Smrg   xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
143732b578d3Smrg	       "[dri] Block 0 base at 0x%08lx\n", pATI->Block0Base );
143832b578d3Smrg
143932b578d3Smrg   return TRUE;
144032b578d3Smrg}
144132b578d3Smrg
144232b578d3Smrg/* Finish initializing the device-dependent DRI state, and call
144332b578d3Smrg * DRIFinishScreenInit() to complete the device-independent DRI
144432b578d3Smrg * initialization.
144532b578d3Smrg */
144632b578d3SmrgBool ATIDRIFinishScreenInit( ScreenPtr pScreen )
144732b578d3Smrg{
144832b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
144932b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
145032b578d3Smrg   ATISAREAPrivPtr pSAREAPriv;
145132b578d3Smrg   ATIDRIPtr pATIDRI;
145232b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer;
145332b578d3Smrg
145432b578d3Smrg   pATI->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
145532b578d3Smrg
145632b578d3Smrg   /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
145732b578d3Smrg    * because *DRIKernelInit requires that the hardware lock is held by
145832b578d3Smrg    * the X server, and the first time the hardware lock is grabbed is
145932b578d3Smrg    * in DRIFinishScreenInit.
146032b578d3Smrg    */
146132b578d3Smrg   if ( !DRIFinishScreenInit( pScreen ) ) {
146232b578d3Smrg      ATIDRICloseScreen( pScreen );
146332b578d3Smrg      return FALSE;
146432b578d3Smrg   }
146532b578d3Smrg
146632b578d3Smrg   /* Initialize the DMA buffer list */
146732b578d3Smrg   /* Need to do this before ATIDRIKernelInit so we can init the freelist */
146832b578d3Smrg   if ( !ATIDRIAddBuffers( pScreen ) ) {
146932b578d3Smrg      ATIDRICloseScreen( pScreen );
147032b578d3Smrg      return FALSE;
147132b578d3Smrg   }
147232b578d3Smrg
147332b578d3Smrg   /* Initialize the kernel data structures */
147432b578d3Smrg   if ( !ATIDRIKernelInit( pScreen ) ) {
147532b578d3Smrg      xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
147632b578d3Smrg		 "[drm] Failed to initialize the mach64.o kernel module\n");
147732b578d3Smrg      xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
147832b578d3Smrg		 "[drm] Check the system log for more information.\n");
147932b578d3Smrg      ATIDRICloseScreen( pScreen );
148032b578d3Smrg      return FALSE;
148132b578d3Smrg   }
148232b578d3Smrg
148332b578d3Smrg   if ( !ATIDRIMapBuffers( pScreen ) ) {
148432b578d3Smrg      ATIDRICloseScreen( pScreen );
148532b578d3Smrg      return FALSE;
148632b578d3Smrg   }
148732b578d3Smrg
148832b578d3Smrg   /* Initialize IRQ */
148932b578d3Smrg   ATIDRIIrqInit( pScreen );
149032b578d3Smrg
149132b578d3Smrg   pSAREAPriv = (ATISAREAPrivPtr) DRIGetSAREAPrivate( pScreen );
149232b578d3Smrg   memset( pSAREAPriv, 0, sizeof(*pSAREAPriv) );
149332b578d3Smrg
149432b578d3Smrg   pATIDRI = (ATIDRIPtr)pATI->pDRIInfo->devPrivate;
149532b578d3Smrg   pATIDRIServer = pATI->pDRIServerInfo;
149632b578d3Smrg
149732b578d3Smrg   pATIDRI->width = pScreenInfo->virtualX;
149832b578d3Smrg   pATIDRI->height = pScreenInfo->virtualY;
149932b578d3Smrg   pATIDRI->mem = pScreenInfo->videoRam * 1024;
150032b578d3Smrg   pATIDRI->cpp = pScreenInfo->bitsPerPixel / 8;
150132b578d3Smrg
150232b578d3Smrg   pATIDRI->IsPCI = pATIDRIServer->IsPCI;
150332b578d3Smrg   pATIDRI->AGPMode = pATIDRIServer->agpMode;
150432b578d3Smrg
150532b578d3Smrg   pATIDRI->frontOffset = pATIDRIServer->frontOffset;
150632b578d3Smrg   pATIDRI->frontPitch = pATIDRIServer->frontPitch;
150732b578d3Smrg
150832b578d3Smrg   pATIDRI->backOffset = pATIDRIServer->backOffset;
150932b578d3Smrg   pATIDRI->backPitch = pATIDRIServer->backPitch;
151032b578d3Smrg
151132b578d3Smrg   pATIDRI->depthOffset = pATIDRIServer->depthOffset;
151232b578d3Smrg   pATIDRI->depthPitch = pATIDRIServer->depthPitch;
151332b578d3Smrg
151432b578d3Smrg   pATIDRI->textureOffset = pATIDRIServer->textureOffset;
151532b578d3Smrg   pATIDRI->textureSize	= pATIDRIServer->textureSize;
151632b578d3Smrg   pATIDRI->logTextureGranularity = pATIDRIServer->logTextureGranularity;
151732b578d3Smrg
151832b578d3Smrg   pATIDRI->regs = pATIDRIServer->regsHandle;
151932b578d3Smrg   pATIDRI->regsSize = pATIDRIServer->regsSize;
152032b578d3Smrg
152132b578d3Smrg   pATIDRI->agp = pATIDRIServer->agpTexHandle;
152232b578d3Smrg   pATIDRI->agpSize = pATIDRIServer->agpTexMapSize;
152332b578d3Smrg   pATIDRI->logAgpTextureGranularity = pATIDRIServer->log2AGPTexGran;
152432b578d3Smrg   pATIDRI->agpTextureOffset = pATIDRIServer->agpTexStart;
152532b578d3Smrg
152632b578d3Smrg   return TRUE;
152732b578d3Smrg}
152832b578d3Smrg
152932b578d3Smrg/*
153032b578d3Smrg * This function will attempt to get the Mach64 hardware back into shape
153132b578d3Smrg * after a resume from disc. Its an extract from ATIDRIAgpInit and ATIDRIFinishScreenInit
153232b578d3Smrg * This also calls a new ioctl in the mach64 DRM that in its turn is
153332b578d3Smrg * an extraction of the hardware-affecting bits from mach64_do_init_drm()
153432b578d3Smrg * (see atidrm.c)
153532b578d3Smrg * I am assuming here that pATI->pDRIServerInfo doesn't change
153632b578d3Smrg * elsewhere in incomaptible ways.
153732b578d3Smrg * How will this code react to resuming after a failed resumeor pci based dri ?
153832b578d3Smrg */
153932b578d3Smrgvoid ATIDRIResume( ScreenPtr pScreen )
154032b578d3Smrg{
154132b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
154232b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
154332b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
154432b578d3Smrg
154532b578d3Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
154632b578d3Smrg		 "[RESUME] Attempting to re-init Mach64 hardware.\n");
154732b578d3Smrg
154832b578d3Smrg   if (!pATIDRIServer->IsPCI) {
154932b578d3Smrg      if (!ATIDRISetAgpMode(pScreen))
155032b578d3Smrg      return;
155132b578d3Smrg
155232b578d3Smrg      outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
155332b578d3Smrg   }
155432b578d3Smrg}
155532b578d3Smrg
155632b578d3Smrg/* The screen is being closed, so clean up any state and free any
155732b578d3Smrg * resources used by the DRI.
155832b578d3Smrg */
155932b578d3Smrgvoid ATIDRICloseScreen( ScreenPtr pScreen )
156032b578d3Smrg{
156132b578d3Smrg   ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
156232b578d3Smrg   ATIPtr pATI = ATIPTR(pScreenInfo);
156332b578d3Smrg   ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
156432b578d3Smrg   drmMach64Init info;
156532b578d3Smrg
156632b578d3Smrg   /* Stop interrupt generation and handling if used */
156732b578d3Smrg   if ( pATI->irq > 0 ) {
156832b578d3Smrg      if ( drmCtlUninstHandler(pATI->drmFD) != 0 ) {
156932b578d3Smrg	 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
157032b578d3Smrg		    "[drm] Error uninstalling interrupt handler for IRQ %d\n", pATI->irq);
157132b578d3Smrg      } else {
157232b578d3Smrg	 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
157332b578d3Smrg		    "[drm] Uninstalled interrupt handler for IRQ %d\n", pATI->irq);
157432b578d3Smrg      }
157532b578d3Smrg      pATI->irq = 0;
157632b578d3Smrg   }
157732b578d3Smrg
157832b578d3Smrg   /* De-allocate DMA buffers */
157932b578d3Smrg   if ( pATIDRIServer->drmBuffers ) {
158032b578d3Smrg      drmUnmapBufs( pATIDRIServer->drmBuffers );
158132b578d3Smrg      pATIDRIServer->drmBuffers = NULL;
158232b578d3Smrg   }
158332b578d3Smrg
158432b578d3Smrg   /* De-allocate all kernel resources */
158532b578d3Smrg   memset(&info, 0, sizeof(drmMach64Init));
158632b578d3Smrg   info.func = DRM_MACH64_CLEANUP_DMA;
158732b578d3Smrg   drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
158832b578d3Smrg		    &info, sizeof(drmMach64Init) );
158932b578d3Smrg
159032b578d3Smrg   /* De-allocate all AGP resources */
159132b578d3Smrg   if ( pATIDRIServer->agpTexMap ) {
159232b578d3Smrg      drmUnmap( pATIDRIServer->agpTexMap, pATIDRIServer->agpTexMapSize );
159332b578d3Smrg      pATIDRIServer->agpTexMap = NULL;
159432b578d3Smrg   }
159532b578d3Smrg   if ( pATIDRIServer->bufferMap ) {
159632b578d3Smrg      drmUnmap( pATIDRIServer->bufferMap, pATIDRIServer->bufferMapSize );
159732b578d3Smrg      pATIDRIServer->bufferMap = NULL;
159832b578d3Smrg   }
159932b578d3Smrg   if ( pATIDRIServer->ringMap ) {
160032b578d3Smrg      drmUnmap( pATIDRIServer->ringMap, pATIDRIServer->ringMapSize );
160132b578d3Smrg      pATIDRIServer->ringMap = NULL;
160232b578d3Smrg   }
160332b578d3Smrg   if ( pATIDRIServer->agpHandle ) {
160432b578d3Smrg      drmAgpUnbind( pATI->drmFD, pATIDRIServer->agpHandle );
160532b578d3Smrg      drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
160632b578d3Smrg      pATIDRIServer->agpHandle = 0;
160732b578d3Smrg      drmAgpRelease( pATI->drmFD );
160832b578d3Smrg   }
160932b578d3Smrg
161032b578d3Smrg   /* De-allocate all PCI resources */
161132b578d3Smrg   if ( pATIDRIServer->IsPCI && pATIDRIServer->ringHandle ) {
161232b578d3Smrg      drmRmMap( pATI->drmFD, pATIDRIServer->ringHandle );
161332b578d3Smrg      pATIDRIServer->ringHandle = 0;
161432b578d3Smrg   }
161532b578d3Smrg
161632b578d3Smrg   /* De-allocate all DRI resources */
161732b578d3Smrg   DRICloseScreen( pScreen );
161832b578d3Smrg
161932b578d3Smrg   /* De-allocate all DRI data structures */
162032b578d3Smrg   if ( pATI->pDRIInfo ) {
162132b578d3Smrg      if ( pATI->pDRIInfo->devPrivate ) {
16221b12faf6Smrg	 free( pATI->pDRIInfo->devPrivate );
162332b578d3Smrg	 pATI->pDRIInfo->devPrivate = NULL;
162432b578d3Smrg      }
162532b578d3Smrg      DRIDestroyInfoRec( pATI->pDRIInfo );
162632b578d3Smrg      pATI->pDRIInfo = NULL;
162732b578d3Smrg   }
162832b578d3Smrg   if ( pATI->pDRIServerInfo ) {
16291b12faf6Smrg      free( pATI->pDRIServerInfo );
163032b578d3Smrg      pATI->pDRIServerInfo = NULL;
163132b578d3Smrg   }
163232b578d3Smrg   if ( pATI->pVisualConfigs ) {
16331b12faf6Smrg      free( pATI->pVisualConfigs );
163432b578d3Smrg      pATI->pVisualConfigs = NULL;
163532b578d3Smrg   }
163632b578d3Smrg   if ( pATI->pVisualConfigsPriv ) {
16371b12faf6Smrg      free( pATI->pVisualConfigsPriv );
163832b578d3Smrg      pATI->pVisualConfigsPriv = NULL;
163932b578d3Smrg   }
164032b578d3Smrg}
1641