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