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 550b0ce0bfSmrg/* DRI/DRM definitions */ 5632b578d3Smrg#define _XF86DRI_SERVER_ 5732b578d3Smrg#include "sarea.h" 5832b578d3Smrg 5932b578d3Smrgstatic char ATIKernelDriverName[] = "mach64"; 6032b578d3Smrgstatic char ATIClientDriverName[] = "mach64"; 6132b578d3Smrg 6232b578d3Smrg/* Create the ATI-specific context information */ 6332b578d3Smrgstatic Bool ATICreateContext( ScreenPtr pScreen, VisualPtr visual, 6432b578d3Smrg drm_context_t hwContext, void *pVisualConfigPriv, 6532b578d3Smrg DRIContextType contextStore ) 6632b578d3Smrg{ 6732b578d3Smrg /* Nothing yet */ 6832b578d3Smrg return TRUE; 6932b578d3Smrg} 7032b578d3Smrg 7132b578d3Smrg/* Destroy the ATI-specific context information */ 7232b578d3Smrgstatic void ATIDestroyContext( ScreenPtr pScreen, drm_context_t hwContext, 7332b578d3Smrg DRIContextType contextStore ) 7432b578d3Smrg{ 7532b578d3Smrg /* Nothing yet */ 7632b578d3Smrg} 7732b578d3Smrg 7832b578d3Smrg/* Called when the X server is woken up to allow the last client's 7932b578d3Smrg * context to be saved and the X server's context to be loaded. 8032b578d3Smrg * The client detects when it's context is not currently loaded and 8132b578d3Smrg * then loads it itself. The X server's context is loaded in the 8232b578d3Smrg * XAA Sync callback if NeedDRISync is set. 8332b578d3Smrg */ 8432b578d3Smrgstatic void ATIEnterServer( ScreenPtr pScreen ) 8532b578d3Smrg{ 86e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 8732b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 8832b578d3Smrg 8932b578d3Smrg if ( pATI->directRenderingEnabled ) { 9032b578d3Smrg ATIDRIMarkSyncInt(pScreenInfo); 9132b578d3Smrg ATIDRIMarkSyncExt(pScreenInfo); 9232b578d3Smrg } 9332b578d3Smrg} 9432b578d3Smrg 9532b578d3Smrg/* Called when the X server goes to sleep to allow the X server's 9632b578d3Smrg * context to be saved and the last client's context to be loaded. 9732b578d3Smrg * The client detects when it's context is not currently loaded and 9832b578d3Smrg * then loads it itself. The X server keeps track of it's own state. 9932b578d3Smrg */ 10032b578d3Smrgstatic void ATILeaveServer( ScreenPtr pScreen ) 10132b578d3Smrg{ 10232b578d3Smrg /* Nothing yet */ 10332b578d3Smrg} 10432b578d3Smrg 10532b578d3Smrg/* Contexts can be swapped by the X server if necessary. This callback 10632b578d3Smrg * is currently only used to perform any functions necessary when 10732b578d3Smrg * entering or leaving the X server, and in the future might not be 10832b578d3Smrg * necessary. 10932b578d3Smrg */ 11032b578d3Smrgstatic void ATIDRISwapContext( ScreenPtr pScreen, 11132b578d3Smrg DRISyncType syncType, 11232b578d3Smrg DRIContextType oldContextType, 11332b578d3Smrg void *oldContext, 11432b578d3Smrg DRIContextType newContextType, 11532b578d3Smrg void *newContext ) 11632b578d3Smrg{ 11732b578d3Smrg if ( ( syncType == DRI_3D_SYNC ) && ( oldContextType == DRI_2D_CONTEXT ) && 11832b578d3Smrg ( newContextType == DRI_2D_CONTEXT ) ) { 11932b578d3Smrg /* Entering from Wakeup */ 12032b578d3Smrg ATIEnterServer( pScreen ); 12132b578d3Smrg } 12232b578d3Smrg if ( ( syncType == DRI_2D_SYNC ) && ( oldContextType == DRI_NO_CONTEXT ) && 12332b578d3Smrg ( newContextType == DRI_2D_CONTEXT ) ) { 12432b578d3Smrg /* Exiting from Block Handler */ 12532b578d3Smrg ATILeaveServer( pScreen ); 12632b578d3Smrg } 12732b578d3Smrg} 12832b578d3Smrg 12932b578d3Smrg#ifdef USE_XAA 13032b578d3Smrgstatic void ATIDRITransitionTo2d(ScreenPtr pScreen) 13132b578d3Smrg{ 132e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 13332b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 13432b578d3Smrg 13532b578d3Smrg if (pATI->backArea) { 13632b578d3Smrg xf86FreeOffscreenArea(pATI->backArea); 13732b578d3Smrg pATI->backArea = NULL; 13832b578d3Smrg } 13932b578d3Smrg if (pATI->depthTexArea) { 14032b578d3Smrg xf86FreeOffscreenArea(pATI->depthTexArea); 14132b578d3Smrg pATI->depthTexArea = NULL; 14232b578d3Smrg } 14332b578d3Smrg pATI->have3DWindows = FALSE; 14432b578d3Smrg} 14532b578d3Smrg 14632b578d3Smrgstatic void ATIDRITransitionTo3d(ScreenPtr pScreen) 14732b578d3Smrg{ 148e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 14932b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 15032b578d3Smrg FBAreaPtr fbArea; 15132b578d3Smrg int width, height; 15232b578d3Smrg 15332b578d3Smrg xf86PurgeUnlockedOffscreenAreas(pScreen); 15432b578d3Smrg 15532b578d3Smrg xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0); 15632b578d3Smrg 15732b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 15832b578d3Smrg "Largest offscreen area available: %d x %d\n", 15932b578d3Smrg width, height); 16032b578d3Smrg 16132b578d3Smrg fbArea = xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth, 16232b578d3Smrg height - pATI->depthTexLines - 16332b578d3Smrg pATI->backLines, 16432b578d3Smrg pScreenInfo->displayWidth, NULL, NULL, NULL); 16532b578d3Smrg 16632b578d3Smrg if (!fbArea) 16732b578d3Smrg xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve placeholder " 16832b578d3Smrg "offscreen area, you might experience screen corruption\n"); 16932b578d3Smrg 17032b578d3Smrg if (!pATI->backArea) { 17132b578d3Smrg pATI->backArea = 17232b578d3Smrg xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth, 17332b578d3Smrg pATI->backLines, 17432b578d3Smrg pScreenInfo->displayWidth, 17532b578d3Smrg NULL, NULL, NULL); 17632b578d3Smrg } 17732b578d3Smrg if (!pATI->backArea) 17832b578d3Smrg xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area " 17932b578d3Smrg "for back buffer, you might experience screen corruption\n"); 18032b578d3Smrg 18132b578d3Smrg if (!pATI->depthTexArea) { 18232b578d3Smrg pATI->depthTexArea = 18332b578d3Smrg xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth, 18432b578d3Smrg pATI->depthTexLines, 18532b578d3Smrg pScreenInfo->displayWidth, 18632b578d3Smrg NULL, NULL, NULL); 18732b578d3Smrg } 18832b578d3Smrg if (!pATI->depthTexArea) 18932b578d3Smrg xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area " 19032b578d3Smrg "for depth buffer and textures, you might experience screen corruption\n"); 19132b578d3Smrg 19232b578d3Smrg if (fbArea) 19332b578d3Smrg xf86FreeOffscreenArea(fbArea); 19432b578d3Smrg 19532b578d3Smrg pATI->have3DWindows = TRUE; 19632b578d3Smrg} 19732b578d3Smrg#endif /* USE_XAA */ 19832b578d3Smrg 19932b578d3Smrg#ifdef USE_EXA 20032b578d3Smrgstatic void ATIDRITransitionTo2d_EXA(ScreenPtr pScreen) 20132b578d3Smrg{ 202e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 20332b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 20432b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 20532b578d3Smrg 206e35d4d8eSmrg exaEnableDisableFBAccess(SCREEN_ARG(pScreen), FALSE); 20732b578d3Smrg 20832b578d3Smrg pATI->pExa->offScreenBase = pATIDRIServer->backOffset; 20932b578d3Smrg 210e35d4d8eSmrg exaEnableDisableFBAccess(SCREEN_ARG(pScreen), TRUE); 21132b578d3Smrg 21232b578d3Smrg pATI->have3DWindows = FALSE; 21332b578d3Smrg} 21432b578d3Smrg 21532b578d3Smrgstatic void ATIDRITransitionTo3d_EXA(ScreenPtr pScreen) 21632b578d3Smrg{ 217e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 21832b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 21932b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 22032b578d3Smrg 221e35d4d8eSmrg exaEnableDisableFBAccess(SCREEN_ARG(pScreen), FALSE); 22232b578d3Smrg 22332b578d3Smrg pATI->pExa->offScreenBase = pATIDRIServer->textureOffset + 22432b578d3Smrg pATIDRIServer->textureSize; 22532b578d3Smrg 226e35d4d8eSmrg exaEnableDisableFBAccess(SCREEN_ARG(pScreen), TRUE); 22732b578d3Smrg 22832b578d3Smrg pATI->have3DWindows = TRUE; 22932b578d3Smrg} 23032b578d3Smrg#endif /* USE_EXA */ 23132b578d3Smrg 23232b578d3Smrg/* Initialize the state of the back and depth buffers. */ 23332b578d3Smrgstatic void ATIDRIInitBuffers( WindowPtr pWin, RegionPtr prgn, CARD32 indx ) 23432b578d3Smrg{ 23532b578d3Smrg#ifdef USE_XAA 23632b578d3Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 237e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 23832b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 23932b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 24032b578d3Smrg XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; 24132b578d3Smrg BoxPtr pbox, pboxSave; 24232b578d3Smrg int nbox, nboxSave; 24332b578d3Smrg int depth; 24432b578d3Smrg 24532b578d3Smrg depth = 0x0000ffff; 24632b578d3Smrg 24732b578d3Smrg if (!pXAAInfo) 24832b578d3Smrg return; 24932b578d3Smrg 25032b578d3Smrg if (!pXAAInfo->SetupForSolidFill) 25132b578d3Smrg return; 25232b578d3Smrg 25332b578d3Smrg /* FIXME: Only initialize the back and depth buffers for contexts 25432b578d3Smrg that request them */ 25532b578d3Smrg 25632b578d3Smrg /* FIXME: Use drm clear? (see Radeon driver) */ 25732b578d3Smrg 25832b578d3Smrg pboxSave = pbox = REGION_RECTS(prgn); 25932b578d3Smrg nboxSave = nbox = REGION_NUM_RECTS(prgn); 26032b578d3Smrg 26132b578d3Smrg (*pXAAInfo->SetupForSolidFill)(pScreenInfo, 0, GXcopy, (CARD32)(-1)); 26232b578d3Smrg for (; nbox; nbox--, pbox++) { 26332b578d3Smrg (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, 26432b578d3Smrg pbox->x1 + pATIDRIServer->fbX, 26532b578d3Smrg pbox->y1 + pATIDRIServer->fbY, 26632b578d3Smrg pbox->x2 - pbox->x1, 26732b578d3Smrg pbox->y2 - pbox->y1); 26832b578d3Smrg (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, 26932b578d3Smrg pbox->x1 + pATIDRIServer->backX, 27032b578d3Smrg pbox->y1 + pATIDRIServer->backY, 27132b578d3Smrg pbox->x2 - pbox->x1, 27232b578d3Smrg pbox->y2 - pbox->y1); 27332b578d3Smrg } 27432b578d3Smrg 27532b578d3Smrg pbox = pboxSave; 27632b578d3Smrg nbox = nboxSave; 27732b578d3Smrg 27832b578d3Smrg (*pXAAInfo->SetupForSolidFill)(pScreenInfo, depth, GXcopy, (CARD32)(-1)); 27932b578d3Smrg for (; nbox; nbox--, pbox++) 28032b578d3Smrg (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, 28132b578d3Smrg pbox->x1 + pATIDRIServer->depthX, 28232b578d3Smrg pbox->y1 + pATIDRIServer->depthY, 28332b578d3Smrg pbox->x2 - pbox->x1, 28432b578d3Smrg pbox->y2 - pbox->y1); 28532b578d3Smrg 28632b578d3Smrg ATIDRIMarkSyncInt(pScreenInfo); 28732b578d3Smrg#endif 28832b578d3Smrg} 28932b578d3Smrg 29032b578d3Smrg/* Copy the back and depth buffers when the X server moves a window. 29132b578d3Smrg * 29232b578d3Smrg * Note: this function was copied from the Radeon driver... 29332b578d3Smrg * 29432b578d3Smrg * This routine is a modified form of XAADoBitBlt with the calls to 29532b578d3Smrg * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source 29632b578d3Smrg * instead of destination. My origin is upside down so the ydir cases 29732b578d3Smrg * are reversed. 29832b578d3Smrg */ 29932b578d3Smrgstatic void ATIDRIMoveBuffers( WindowPtr pWin, DDXPointRec ptOldOrg, 30032b578d3Smrg RegionPtr prgnSrc, CARD32 indx ) 30132b578d3Smrg{ 30232b578d3Smrg#ifdef USE_XAA 30332b578d3Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 304e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 30532b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 30632b578d3Smrg XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; 30732b578d3Smrg 30832b578d3Smrg int backOffsetPitch = (((pATI->pDRIServerInfo->backPitch/8) << 22) | 30932b578d3Smrg (pATI->pDRIServerInfo->backOffset >> 3)); 31032b578d3Smrg#if 0 31132b578d3Smrg int depthOffsetPitch = (((pATI->pDRIServerInfo->depthPitch/8) << 22) | 31232b578d3Smrg (pATI->pDRIServerInfo->depthOffset >> 3)); 31332b578d3Smrg#endif 31432b578d3Smrg BoxPtr pboxTmp, pboxNext, pboxBase; 31532b578d3Smrg DDXPointPtr pptTmp; 31632b578d3Smrg int xdir, ydir; 31732b578d3Smrg 31832b578d3Smrg int screenwidth = pScreenInfo->virtualX; 31932b578d3Smrg int screenheight = pScreenInfo->virtualY; 32032b578d3Smrg 32132b578d3Smrg BoxPtr pbox = REGION_RECTS(prgnSrc); 32232b578d3Smrg int nbox = REGION_NUM_RECTS(prgnSrc); 32332b578d3Smrg 32432b578d3Smrg BoxPtr pboxNew1 = NULL; 32532b578d3Smrg BoxPtr pboxNew2 = NULL; 32632b578d3Smrg DDXPointPtr pptNew1 = NULL; 32732b578d3Smrg DDXPointPtr pptNew2 = NULL; 32832b578d3Smrg DDXPointPtr pptSrc = &ptOldOrg; 32932b578d3Smrg 33032b578d3Smrg int dx = pWin->drawable.x - ptOldOrg.x; 33132b578d3Smrg int dy = pWin->drawable.y - ptOldOrg.y; 33232b578d3Smrg 33332b578d3Smrg if (!pXAAInfo) 33432b578d3Smrg return; 33532b578d3Smrg 33632b578d3Smrg if (!pXAAInfo->SetupForScreenToScreenCopy) 33732b578d3Smrg return; 33832b578d3Smrg 33932b578d3Smrg /* FIXME: Only move the back and depth buffers for contexts 34032b578d3Smrg * that request them. 34132b578d3Smrg */ 34232b578d3Smrg 34332b578d3Smrg /* If the copy will overlap in Y, reverse the order */ 34432b578d3Smrg if (dy > 0) { 34532b578d3Smrg ydir = -1; 34632b578d3Smrg 34732b578d3Smrg if (nbox > 1) { 34832b578d3Smrg /* Keep ordering in each band, reverse order of bands */ 3491b12faf6Smrg pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec)*nbox); 35032b578d3Smrg if (!pboxNew1) return; 3511b12faf6Smrg pptNew1 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox); 35232b578d3Smrg if (!pptNew1) { 3531b12faf6Smrg free(pboxNew1); 35432b578d3Smrg return; 35532b578d3Smrg } 35632b578d3Smrg pboxBase = pboxNext = pbox+nbox-1; 35732b578d3Smrg while (pboxBase >= pbox) { 35832b578d3Smrg while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) 35932b578d3Smrg pboxNext--; 36032b578d3Smrg pboxTmp = pboxNext+1; 36132b578d3Smrg pptTmp = pptSrc + (pboxTmp - pbox); 36232b578d3Smrg while (pboxTmp <= pboxBase) { 36332b578d3Smrg *pboxNew1++ = *pboxTmp++; 36432b578d3Smrg *pptNew1++ = *pptTmp++; 36532b578d3Smrg } 36632b578d3Smrg pboxBase = pboxNext; 36732b578d3Smrg } 36832b578d3Smrg pboxNew1 -= nbox; 36932b578d3Smrg pbox = pboxNew1; 37032b578d3Smrg pptNew1 -= nbox; 37132b578d3Smrg pptSrc = pptNew1; 37232b578d3Smrg } 37332b578d3Smrg } else { 37432b578d3Smrg /* No changes required */ 37532b578d3Smrg ydir = 1; 37632b578d3Smrg } 37732b578d3Smrg 37832b578d3Smrg /* If the regions will overlap in X, reverse the order */ 37932b578d3Smrg if (dx > 0) { 38032b578d3Smrg xdir = -1; 38132b578d3Smrg 38232b578d3Smrg if (nbox > 1) { 38332b578d3Smrg /* reverse order of rects in each band */ 3841b12faf6Smrg pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec)*nbox); 3851b12faf6Smrg pptNew2 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox); 38632b578d3Smrg if (!pboxNew2 || !pptNew2) { 3871b12faf6Smrg free(pptNew2); 3881b12faf6Smrg free(pboxNew2); 3891b12faf6Smrg free(pptNew1); 3901b12faf6Smrg free(pboxNew1); 39132b578d3Smrg return; 39232b578d3Smrg } 39332b578d3Smrg pboxBase = pboxNext = pbox; 39432b578d3Smrg while (pboxBase < pbox+nbox) { 39532b578d3Smrg while ((pboxNext < pbox+nbox) 39632b578d3Smrg && (pboxNext->y1 == pboxBase->y1)) 39732b578d3Smrg pboxNext++; 39832b578d3Smrg pboxTmp = pboxNext; 39932b578d3Smrg pptTmp = pptSrc + (pboxTmp - pbox); 40032b578d3Smrg while (pboxTmp != pboxBase) { 40132b578d3Smrg *pboxNew2++ = *--pboxTmp; 40232b578d3Smrg *pptNew2++ = *--pptTmp; 40332b578d3Smrg } 40432b578d3Smrg pboxBase = pboxNext; 40532b578d3Smrg } 40632b578d3Smrg pboxNew2 -= nbox; 40732b578d3Smrg pbox = pboxNew2; 40832b578d3Smrg pptNew2 -= nbox; 40932b578d3Smrg pptSrc = pptNew2; 41032b578d3Smrg } 41132b578d3Smrg } else { 41232b578d3Smrg /* No changes are needed */ 41332b578d3Smrg xdir = 1; 41432b578d3Smrg } 41532b578d3Smrg 41632b578d3Smrg (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, xdir, ydir, GXcopy, 41732b578d3Smrg (CARD32)(-1), -1); 41832b578d3Smrg 41932b578d3Smrg for (; nbox-- ; pbox++) { 42032b578d3Smrg int xa = pbox->x1; 42132b578d3Smrg int ya = pbox->y1; 42232b578d3Smrg int destx = xa + dx; 42332b578d3Smrg int desty = ya + dy; 42432b578d3Smrg int w = pbox->x2 - xa + 1; 42532b578d3Smrg int h = pbox->y2 - ya + 1; 42632b578d3Smrg 42732b578d3Smrg if (destx < 0) xa -= destx, w += destx, destx = 0; 42832b578d3Smrg if (desty < 0) ya -= desty, h += desty, desty = 0; 42932b578d3Smrg if (destx + w > screenwidth) w = screenwidth - destx; 43032b578d3Smrg if (desty + h > screenheight) h = screenheight - desty; 43132b578d3Smrg 43232b578d3Smrg if (w <= 0) continue; 43332b578d3Smrg if (h <= 0) continue; 43432b578d3Smrg 43532b578d3Smrg ATIMach64WaitForFIFO(pATI, 2); 43632b578d3Smrg outf(SRC_OFF_PITCH, backOffsetPitch); 43732b578d3Smrg outf(DST_OFF_PITCH, backOffsetPitch); 43832b578d3Smrg 43932b578d3Smrg (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo, 44032b578d3Smrg xa, ya, 44132b578d3Smrg destx, desty, 44232b578d3Smrg w, h); 44332b578d3Smrg#if 0 44432b578d3Smrg /* FIXME: Move depth buffers? */ 44532b578d3Smrg ATIMach64WaitForFIFO(pATI, 2); 44632b578d3Smrg outf(SRC_OFF_PITCH, depthOffsetPitch); 44732b578d3Smrg outf(DST_OFF_PITCH, depthOffsetPitch); 44832b578d3Smrg 44932b578d3Smrg if (pATI->depthMoves) 45032b578d3Smrg ATIScreenToScreenCopyDepth(pScreenInfo, 45132b578d3Smrg xa, ya, 45232b578d3Smrg destx, desty, 45332b578d3Smrg w, h); 45432b578d3Smrg#endif 45532b578d3Smrg } 45632b578d3Smrg 45732b578d3Smrg ATIMach64WaitForFIFO(pATI, 2); 45832b578d3Smrg outf(SRC_OFF_PITCH, pATI->NewHW.dst_off_pitch); 45932b578d3Smrg outf(DST_OFF_PITCH, pATI->NewHW.src_off_pitch); 46032b578d3Smrg 4611b12faf6Smrg free(pptNew2); 4621b12faf6Smrg free(pboxNew2); 4631b12faf6Smrg free(pptNew1); 4641b12faf6Smrg free(pboxNew1); 46532b578d3Smrg 46632b578d3Smrg ATIDRIMarkSyncInt(pScreenInfo); 46732b578d3Smrg#endif 46832b578d3Smrg} 46932b578d3Smrg 47032b578d3Smrg/* Compute log base 2 of val. */ 47132b578d3Smrgstatic int Mach64MinBits(int val) 47232b578d3Smrg{ 47332b578d3Smrg int bits; 47432b578d3Smrg 47532b578d3Smrg if (!val) return 1; 47632b578d3Smrg for (bits = 0; val; val >>= 1, ++bits); 47732b578d3Smrg return bits; 47832b578d3Smrg} 47932b578d3Smrg 48032b578d3Smrgstatic Bool ATIDRISetBufSize( ScreenPtr pScreen, unsigned int maxSize ) 48132b578d3Smrg{ 482e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 48332b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 48432b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 48532b578d3Smrg 48632b578d3Smrg if (pATI->OptionBufferSize) { 48732b578d3Smrg if (pATI->OptionBufferSize < 1 || pATI->OptionBufferSize > maxSize ) { 48832b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Illegal DMA buffers size: %d MB\n", 48932b578d3Smrg pATI->OptionBufferSize ); 49032b578d3Smrg return FALSE; 49132b578d3Smrg } 49232b578d3Smrg if (pATI->OptionBufferSize > 2) { 49332b578d3Smrg xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Illegal DMA buffers size: %d MB\n", 49432b578d3Smrg pATI->OptionBufferSize ); 49532b578d3Smrg xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Clamping DMA buffers size to 2 MB\n"); 49632b578d3Smrg pATIDRIServer->bufferSize = 2; 49732b578d3Smrg } else { 49832b578d3Smrg pATIDRIServer->bufferSize = pATI->OptionBufferSize; 49932b578d3Smrg xf86DrvMsg( pScreen->myNum, X_CONFIG, "[drm] Using %d MB for DMA buffers\n", 50032b578d3Smrg pATIDRIServer->bufferSize ); 50132b578d3Smrg } 50232b578d3Smrg } else { 50332b578d3Smrg xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[drm] Using %d MB for DMA buffers\n", 50432b578d3Smrg pATIDRIServer->bufferSize ); 50532b578d3Smrg } 50632b578d3Smrg 50732b578d3Smrg return TRUE; 50832b578d3Smrg} 50932b578d3Smrg 51032b578d3Smrgstatic Bool ATIDRISetAgpMode( ScreenPtr pScreen ) 51132b578d3Smrg{ 512e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 51332b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 51432b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 51532b578d3Smrg 51632b578d3Smrg unsigned long mode = drmAgpGetMode( pATI->drmFD ); /* Default mode */ 51732b578d3Smrg unsigned int vendor = drmAgpVendorId( pATI->drmFD ); 51832b578d3Smrg unsigned int device = drmAgpDeviceId( pATI->drmFD ); 51932b578d3Smrg 52032b578d3Smrg if (pATI->OptionAGPMode > 0 && pATI->OptionAGPMode <= ATI_AGP_MAX_MODE) { 52132b578d3Smrg pATIDRIServer->agpMode = pATI->OptionAGPMode; 52232b578d3Smrg xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using AGP %dx Mode\n", 52332b578d3Smrg pATIDRIServer->agpMode ); 52432b578d3Smrg } else if (pATI->OptionAGPMode > 0) { 52532b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Illegal AGP Mode: %d\n", 52632b578d3Smrg pATI->OptionAGPMode ); 52732b578d3Smrg return FALSE; 52832b578d3Smrg } else { 52932b578d3Smrg /* If no mode configured, use the default mode obtained from agpgart */ 53032b578d3Smrg if ( mode & AGP_MODE_2X ) { 53132b578d3Smrg pATIDRIServer->agpMode = 2; 53232b578d3Smrg } else if ( mode & AGP_MODE_1X ) { 53332b578d3Smrg pATIDRIServer->agpMode = 1; 53432b578d3Smrg } 53532b578d3Smrg xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using AGP %dx Mode\n", 53632b578d3Smrg pATIDRIServer->agpMode ); 53732b578d3Smrg } 53832b578d3Smrg 53932b578d3Smrg mode &= ~AGP_MODE_MASK; 54032b578d3Smrg switch ( pATIDRIServer->agpMode ) { 54132b578d3Smrg case 2: mode |= AGP_MODE_2X; 54232b578d3Smrg case 1: default: mode |= AGP_MODE_1X; 54332b578d3Smrg } 54432b578d3Smrg 54532b578d3Smrg if (pATI->OptionAGPSize) { 54632b578d3Smrg switch (pATI->OptionAGPSize) { 54732b578d3Smrg case 128: 54832b578d3Smrg case 64: 54932b578d3Smrg case 32: 55032b578d3Smrg case 16: 55132b578d3Smrg case 8: 55232b578d3Smrg case 4: 55332b578d3Smrg pATIDRIServer->agpSize = pATI->OptionAGPSize; 55432b578d3Smrg xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using %d MB AGP aperture\n", 55532b578d3Smrg pATIDRIServer->agpSize ); 55632b578d3Smrg break; 55732b578d3Smrg default: 55832b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 55932b578d3Smrg "[agp] Illegal aperture size %d MB\n", pATI->OptionAGPSize ); 56032b578d3Smrg return FALSE; 56132b578d3Smrg } 56232b578d3Smrg } else { 56332b578d3Smrg xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using %d MB AGP aperture\n", 56432b578d3Smrg pATIDRIServer->agpSize ); 56532b578d3Smrg } 56632b578d3Smrg 56732b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 56832b578d3Smrg "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", 56932b578d3Smrg mode, vendor, device, 57032b578d3Smrg PCI_DEV_VENDOR_ID(pATI->PCIInfo), 57132b578d3Smrg PCI_DEV_DEVICE_ID(pATI->PCIInfo) ); 57232b578d3Smrg 57332b578d3Smrg if ( drmAgpEnable( pATI->drmFD, mode ) < 0 ) { 57432b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" ); 57532b578d3Smrg drmAgpRelease( pATI->drmFD ); 57632b578d3Smrg return FALSE; 57732b578d3Smrg } 57832b578d3Smrg 57932b578d3Smrg return TRUE; 58032b578d3Smrg} 58132b578d3Smrg 58232b578d3Smrg/* Initialize the AGP state. Request memory for use in AGP space, and 58332b578d3Smrg * initialize the Rage Pro registers to point to that memory. 58432b578d3Smrg */ 58532b578d3Smrgstatic Bool ATIDRIAgpInit( ScreenPtr pScreen ) 58632b578d3Smrg{ 587e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 58832b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 58932b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 59032b578d3Smrg 59132b578d3Smrg int ret; 59232b578d3Smrg unsigned long cntl; 59332b578d3Smrg int s, l; 59432b578d3Smrg 59532b578d3Smrg pATIDRIServer->agpSize = ATI_DEFAULT_AGP_SIZE; 59632b578d3Smrg pATIDRIServer->agpMode = ATI_DEFAULT_AGP_MODE; 59732b578d3Smrg pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE; 59832b578d3Smrg pATIDRIServer->ringSize = 16; /* 16 kB ring */ 59932b578d3Smrg 60032b578d3Smrg if ( drmAgpAcquire( pATI->drmFD ) < 0 ) { 60132b578d3Smrg xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP not available\n" ); 60232b578d3Smrg return FALSE; 60332b578d3Smrg } 60432b578d3Smrg 60532b578d3Smrg if (!ATIDRISetAgpMode( pScreen )) 60632b578d3Smrg return FALSE; 60732b578d3Smrg 60832b578d3Smrg pATIDRIServer->agpOffset = 0; 60932b578d3Smrg 61032b578d3Smrg ret = drmAgpAlloc( pATI->drmFD, pATIDRIServer->agpSize*1024*1024, 61132b578d3Smrg 0, NULL, &pATIDRIServer->agpHandle ); 61232b578d3Smrg if ( ret < 0 ) { 61332b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret ); 61432b578d3Smrg drmAgpRelease( pATI->drmFD ); 61532b578d3Smrg return FALSE; 61632b578d3Smrg } 61732b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 61832b578d3Smrg "[agp] %d kB allocated with handle 0x%08x\n", 61932b578d3Smrg pATIDRIServer->agpSize*1024, pATIDRIServer->agpHandle ); 62032b578d3Smrg 62132b578d3Smrg if ( drmAgpBind( pATI->drmFD, pATIDRIServer->agpHandle, pATIDRIServer->agpOffset) < 0 ) { 62232b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind\n" ); 62332b578d3Smrg drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle ); 62432b578d3Smrg drmAgpRelease( pATI->drmFD ); 62532b578d3Smrg return FALSE; 62632b578d3Smrg } 62732b578d3Smrg 62832b578d3Smrg xf86DrvMsg(pScreen->myNum, X_INFO, 62932b578d3Smrg "[agp] Using %d kB for DMA descriptor ring\n", pATIDRIServer->ringSize); 63032b578d3Smrg 63132b578d3Smrg if ( !ATIDRISetBufSize( pScreen, pATIDRIServer->agpSize ) ) 63232b578d3Smrg return FALSE; 63332b578d3Smrg 63432b578d3Smrg pATIDRIServer->agpTexSize = pATIDRIServer->agpSize - pATIDRIServer->bufferSize; 63532b578d3Smrg 63632b578d3Smrg /* Reserve space for the DMA descriptor ring */ 63732b578d3Smrg pATIDRIServer->ringStart = pATIDRIServer->agpOffset; 63832b578d3Smrg pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */ 63932b578d3Smrg 64032b578d3Smrg /* Reserve space for the vertex buffer */ 64132b578d3Smrg pATIDRIServer->bufferStart = pATIDRIServer->ringStart + pATIDRIServer->ringMapSize; 64232b578d3Smrg pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024; 64332b578d3Smrg 64432b578d3Smrg /* Reserve the rest for AGP textures */ 64532b578d3Smrg pATIDRIServer->agpTexStart = pATIDRIServer->bufferStart + pATIDRIServer->bufferMapSize; 64632b578d3Smrg s = (pATIDRIServer->agpSize*1024*1024 - pATIDRIServer->agpTexStart); 64732b578d3Smrg l = Mach64MinBits((s-1) / MACH64_NR_TEX_REGIONS); 64832b578d3Smrg if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY; 64932b578d3Smrg pATIDRIServer->agpTexMapSize = (s >> l) << l; 65032b578d3Smrg pATIDRIServer->log2AGPTexGran = l; 65132b578d3Smrg 65232b578d3Smrg xf86DrvMsg(pScreen->myNum, X_INFO, 65332b578d3Smrg "[agp] Using %d kB for AGP textures\n", pATIDRIServer->agpTexMapSize/1024); 65432b578d3Smrg 65532b578d3Smrg /* Map DMA descriptor ring */ 65632b578d3Smrg if ( drmAddMap( pATI->drmFD, pATIDRIServer->ringStart, pATIDRIServer->ringMapSize, 65732b578d3Smrg DRM_AGP, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) { 65832b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 65932b578d3Smrg "[agp] Could not add ring mapping\n" ); 66032b578d3Smrg return FALSE; 66132b578d3Smrg } 66232b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 66332b578d3Smrg "[agp] ring handle = 0x%08x\n", 66432b578d3Smrg pATIDRIServer->ringHandle ); 66532b578d3Smrg 66632b578d3Smrg if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle, 66732b578d3Smrg pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) { 66832b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 66932b578d3Smrg "[agp] Could not map ring\n" ); 67032b578d3Smrg return FALSE; 67132b578d3Smrg } 67232b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 67332b578d3Smrg "[agp] Ring mapped at 0x%08lx\n", 67432b578d3Smrg (unsigned long)pATIDRIServer->ringMap ); 67532b578d3Smrg 67632b578d3Smrg /* Map vertex buffers */ 67732b578d3Smrg if ( drmAddMap( pATI->drmFD, pATIDRIServer->bufferStart, pATIDRIServer->bufferMapSize, 67832b578d3Smrg DRM_AGP, DRM_READ_ONLY, &pATIDRIServer->bufferHandle ) < 0 ) { 67932b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 68032b578d3Smrg "[agp] Could not add vertex buffers mapping\n" ); 68132b578d3Smrg return FALSE; 68232b578d3Smrg } 68332b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 68432b578d3Smrg "[agp] vertex buffers handle = 0x%08x\n", 68532b578d3Smrg pATIDRIServer->bufferHandle ); 68632b578d3Smrg 68732b578d3Smrg if ( drmMap( pATI->drmFD, pATIDRIServer->bufferHandle, 68832b578d3Smrg pATIDRIServer->bufferMapSize, &pATIDRIServer->bufferMap ) < 0 ) { 68932b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 69032b578d3Smrg "[agp] Could not map vertex buffers\n" ); 69132b578d3Smrg return FALSE; 69232b578d3Smrg } 69332b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 69432b578d3Smrg "[agp] Vertex buffers mapped at 0x%08lx\n", 69532b578d3Smrg (unsigned long)pATIDRIServer->bufferMap ); 69632b578d3Smrg 69732b578d3Smrg /* Map AGP Textures */ 69832b578d3Smrg if (drmAddMap(pATI->drmFD, pATIDRIServer->agpTexStart, pATIDRIServer->agpTexMapSize, 69932b578d3Smrg DRM_AGP, 0, &pATIDRIServer->agpTexHandle) < 0) { 70032b578d3Smrg xf86DrvMsg(pScreen->myNum, X_ERROR, 70132b578d3Smrg "[agp] Could not add AGP texture region mapping\n"); 70232b578d3Smrg return FALSE; 70332b578d3Smrg } 70432b578d3Smrg xf86DrvMsg(pScreen->myNum, X_INFO, 70532b578d3Smrg "[agp] AGP texture region handle = 0x%08x\n", 70632b578d3Smrg pATIDRIServer->agpTexHandle); 70732b578d3Smrg 70832b578d3Smrg if (drmMap(pATI->drmFD, pATIDRIServer->agpTexHandle, pATIDRIServer->agpTexMapSize, 70932b578d3Smrg &pATIDRIServer->agpTexMap) < 0) { 71032b578d3Smrg xf86DrvMsg(pScreen->myNum, X_ERROR, 71132b578d3Smrg "[agp] Could not map AGP texture region\n"); 71232b578d3Smrg return FALSE; 71332b578d3Smrg } 71432b578d3Smrg xf86DrvMsg(pScreen->myNum, X_INFO, 71532b578d3Smrg "[agp] AGP Texture region mapped at 0x%08lx\n", 71632b578d3Smrg (unsigned long)pATIDRIServer->agpTexMap); 71732b578d3Smrg 71832b578d3Smrg /* Initialize Mach64's AGP registers */ 71932b578d3Smrg cntl = inm( AGP_CNTL ); 72032b578d3Smrg cntl &= ~AGP_APER_SIZE_MASK; 72132b578d3Smrg switch ( pATIDRIServer->agpSize ) { 72232b578d3Smrg case 256: cntl |= AGP_APER_SIZE_256MB; break; 72332b578d3Smrg case 128: cntl |= AGP_APER_SIZE_128MB; break; 72432b578d3Smrg case 64: cntl |= AGP_APER_SIZE_64MB; break; 72532b578d3Smrg case 32: cntl |= AGP_APER_SIZE_32MB; break; 72632b578d3Smrg case 16: cntl |= AGP_APER_SIZE_16MB; break; 72732b578d3Smrg case 8: cntl |= AGP_APER_SIZE_8MB; break; 72832b578d3Smrg case 4: cntl |= AGP_APER_SIZE_4MB; break; 72932b578d3Smrg default: 73032b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 73132b578d3Smrg "[agp] Illegal aperture size %d kB\n", 73232b578d3Smrg pATIDRIServer->agpSize*1024 ); 73332b578d3Smrg return FALSE; 73432b578d3Smrg } 73532b578d3Smrg 73632b578d3Smrg /* 1 = DATA comes in clock in which TRDY sampled (default) */ 73732b578d3Smrg /* 0 = DATA comes in clock after TRDY sampled */ 73832b578d3Smrg cntl |= AGP_TRDY_MODE; 73932b578d3Smrg 74032b578d3Smrg /* 1 = generate all reads as high priority */ 74132b578d3Smrg /* 0 = generate all reads as their default priority (default) */ 74232b578d3Smrg /* Setting this only works for me at AGP 1x mode (LLD) */ 74332b578d3Smrg if (pATIDRIServer->agpMode == 1) { 74432b578d3Smrg cntl |= HIGH_PRIORITY_READ_EN; 74532b578d3Smrg } else { 74632b578d3Smrg cntl &= ~HIGH_PRIORITY_READ_EN; 74732b578d3Smrg } 74832b578d3Smrg 74932b578d3Smrg outm( AGP_BASE, drmAgpBase(pATI->drmFD) ); 75032b578d3Smrg outm( AGP_CNTL, cntl ); 75132b578d3Smrg 75232b578d3Smrg return TRUE; 75332b578d3Smrg} 75432b578d3Smrg 75532b578d3Smrgstatic Bool ATIDRIPciInit( ScreenPtr pScreen ) 75632b578d3Smrg{ 757e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 75832b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 75932b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 76032b578d3Smrg 76132b578d3Smrg pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE; 76232b578d3Smrg pATIDRIServer->ringSize = 16; /* 16 kB ring */ 76332b578d3Smrg 76432b578d3Smrg if ( !ATIDRISetBufSize( pScreen, (unsigned)(-1) ) ) 76532b578d3Smrg return FALSE; 76632b578d3Smrg 76732b578d3Smrg /* Set size of the DMA descriptor ring */ 76832b578d3Smrg pATIDRIServer->ringStart = 0; 76932b578d3Smrg pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */ 77032b578d3Smrg 77132b578d3Smrg /* Set size of the vertex buffer */ 77232b578d3Smrg pATIDRIServer->bufferStart = 0; 77332b578d3Smrg pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024; 77432b578d3Smrg 77532b578d3Smrg /* Map DMA descriptor ring */ 77632b578d3Smrg if ( drmAddMap( pATI->drmFD, 0, pATIDRIServer->ringMapSize, 77732b578d3Smrg DRM_CONSISTENT, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) { 77832b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 77932b578d3Smrg "[pci] Could not add ring mapping\n" ); 78032b578d3Smrg return FALSE; 78132b578d3Smrg } 78232b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, "[pci] ring handle = 0x%08x\n", 78332b578d3Smrg pATIDRIServer->ringHandle ); 78432b578d3Smrg 78532b578d3Smrg if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle, 78632b578d3Smrg pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) { 78732b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 78832b578d3Smrg "[pci] Could not map ring\n" ); 78932b578d3Smrg return FALSE; 79032b578d3Smrg } 79132b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 79232b578d3Smrg "[pci] Ring mapped at 0x%08lx\n", 79332b578d3Smrg (unsigned long)pATIDRIServer->ringMap ); 79432b578d3Smrg 79532b578d3Smrg /* Disable AGP for ForcePCIMode */ 79632b578d3Smrg if ( pATI->BusType != ATI_BUS_PCI ) { 79732b578d3Smrg outm( AGP_BASE, 0 ); 79832b578d3Smrg outm( AGP_CNTL, 0 ); 79932b578d3Smrg } 80032b578d3Smrg 80132b578d3Smrg return TRUE; 80232b578d3Smrg} 80332b578d3Smrg 80432b578d3Smrg/* Add a map for the MMIO registers that will be accessed by any 80532b578d3Smrg * DRI-based clients. 80632b578d3Smrg */ 80732b578d3Smrgstatic Bool ATIDRIMapInit( ScreenPtr pScreen ) 80832b578d3Smrg{ 809e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 81032b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 81132b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 81232b578d3Smrg 81332b578d3Smrg pATIDRIServer->regsSize = getpagesize(); 81432b578d3Smrg if ( drmAddMap( pATI->drmFD, pATI->Block1Base, 81532b578d3Smrg pATIDRIServer->regsSize, 81632b578d3Smrg DRM_REGISTERS, DRM_READ_ONLY, 81732b578d3Smrg &pATIDRIServer->regsHandle ) < 0 ) { 81832b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 81932b578d3Smrg "[drm] failed to map registers\n" ); 82032b578d3Smrg return FALSE; 82132b578d3Smrg } 82232b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 82332b578d3Smrg "[drm] register handle = 0x%08x\n", 82432b578d3Smrg pATIDRIServer->regsHandle ); 82532b578d3Smrg 82632b578d3Smrg return TRUE; 82732b578d3Smrg} 82832b578d3Smrg 82932b578d3Smrg/* Initialize the kernel data structures. */ 83032b578d3Smrgstatic Bool ATIDRIKernelInit( ScreenPtr pScreen ) 83132b578d3Smrg{ 832e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 83332b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 83432b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 83532b578d3Smrg drmMach64Init info; 83632b578d3Smrg 83732b578d3Smrg memset( &info, 0, sizeof(drmMach64Init) ); 83832b578d3Smrg 83932b578d3Smrg info.func = DRM_MACH64_INIT_DMA; 84032b578d3Smrg info.sarea_priv_offset = sizeof(XF86DRISAREARec); 84132b578d3Smrg info.is_pci = pATIDRIServer->IsPCI; 84232b578d3Smrg info.dma_mode = pATI->OptionDMAMode; 84332b578d3Smrg 84432b578d3Smrg info.fb_bpp = pATI->bitsPerPixel; 84532b578d3Smrg info.front_offset = pATIDRIServer->frontOffset; 84632b578d3Smrg info.front_pitch = pATIDRIServer->frontPitch; 84732b578d3Smrg info.back_offset = pATIDRIServer->backOffset; 84832b578d3Smrg info.back_pitch = pATIDRIServer->backPitch; 84932b578d3Smrg 85032b578d3Smrg info.depth_bpp = 16; 85132b578d3Smrg info.depth_offset = pATIDRIServer->depthOffset; 85232b578d3Smrg info.depth_pitch = pATIDRIServer->depthPitch; 85332b578d3Smrg 85432b578d3Smrg info.fb_offset = pATI->LinearBase; 85532b578d3Smrg info.mmio_offset = pATIDRIServer->regsHandle; 85632b578d3Smrg info.ring_offset = pATIDRIServer->ringHandle; 85732b578d3Smrg info.buffers_offset = pATIDRIServer->bufferHandle; 85832b578d3Smrg info.agp_textures_offset = pATIDRIServer->agpTexHandle; 85932b578d3Smrg 86032b578d3Smrg if ( drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT, 86132b578d3Smrg &info, sizeof(drmMach64Init) ) < 0 ) { 86232b578d3Smrg return FALSE; 86332b578d3Smrg } else { 86432b578d3Smrg return TRUE; 86532b578d3Smrg } 86632b578d3Smrg} 86732b578d3Smrg 86832b578d3Smrg/* Add a map for the DMA buffers that will be accessed by any 86932b578d3Smrg * DRI-based clients. 87032b578d3Smrg */ 87132b578d3Smrgstatic Bool ATIDRIAddBuffers( ScreenPtr pScreen ) 87232b578d3Smrg{ 873e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 87432b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 87532b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 87632b578d3Smrg 87732b578d3Smrg /* Initialize vertex buffers */ 87832b578d3Smrg if ( pATIDRIServer->IsPCI ) { 87932b578d3Smrg pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD, 88032b578d3Smrg pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE, 88132b578d3Smrg MACH64_BUFFER_SIZE, 88232b578d3Smrg DRM_PCI_BUFFER_RO, 88332b578d3Smrg 0 ); 88432b578d3Smrg } else { 88532b578d3Smrg pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD, 88632b578d3Smrg pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE, 88732b578d3Smrg MACH64_BUFFER_SIZE, 88832b578d3Smrg DRM_AGP_BUFFER, 88932b578d3Smrg pATIDRIServer->bufferStart ); 89032b578d3Smrg } 89132b578d3Smrg if ( pATIDRIServer->numBuffers <= 0 ) { 89232b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 89332b578d3Smrg "[drm] Could not create DMA buffers list\n" ); 89432b578d3Smrg return FALSE; 89532b578d3Smrg } 89632b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 89732b578d3Smrg "[drm] Added %d %d byte DMA buffers\n", 89832b578d3Smrg pATIDRIServer->numBuffers, MACH64_BUFFER_SIZE ); 89932b578d3Smrg 90032b578d3Smrg return TRUE; 90132b578d3Smrg} 90232b578d3Smrg 90332b578d3Smrgstatic Bool ATIDRIMapBuffers( ScreenPtr pScreen ) 90432b578d3Smrg{ 905e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 90632b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 90732b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 90832b578d3Smrg 90932b578d3Smrg pATIDRIServer->drmBuffers = drmMapBufs( pATI->drmFD ); 91032b578d3Smrg if ( !pATIDRIServer->drmBuffers ) { 91132b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 91232b578d3Smrg "[drm] Failed to map DMA buffers list\n" ); 91332b578d3Smrg return FALSE; 91432b578d3Smrg } 91532b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 91632b578d3Smrg "[drm] Mapped %d DMA buffers at 0x%08lx\n", 91732b578d3Smrg pATIDRIServer->drmBuffers->count, 91832b578d3Smrg (unsigned long)pATIDRIServer->drmBuffers->list->address ); 91932b578d3Smrg 92032b578d3Smrg return TRUE; 92132b578d3Smrg} 92232b578d3Smrg 92332b578d3Smrgstatic Bool ATIDRIIrqInit( ScreenPtr pScreen ) 92432b578d3Smrg{ 925e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 92632b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 92732b578d3Smrg 92832b578d3Smrg if ( pATI->irq <= 0 ) { 92932b578d3Smrg pATI->irq = drmGetInterruptFromBusID(pATI->drmFD, 93032b578d3Smrg PCI_CFG_BUS(pATI->PCIInfo), 93132b578d3Smrg PCI_CFG_DEV(pATI->PCIInfo), 93232b578d3Smrg PCI_CFG_FUNC(pATI->PCIInfo)); 93332b578d3Smrg if ( pATI->irq <= 0 ) { 93432b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 93532b578d3Smrg "[drm] Couldn't find IRQ for bus id %d:%d:%d\n", 93632b578d3Smrg PCI_CFG_BUS(pATI->PCIInfo), 93732b578d3Smrg PCI_CFG_DEV(pATI->PCIInfo), 93832b578d3Smrg PCI_CFG_FUNC(pATI->PCIInfo)); 93932b578d3Smrg pATI->irq = 0; 94032b578d3Smrg } else if ((drmCtlInstHandler(pATI->drmFD, pATI->irq)) != 0) { 94132b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 94232b578d3Smrg "[drm] Failed to initialize interrupt handler with IRQ %d\n", 94332b578d3Smrg pATI->irq); 94432b578d3Smrg pATI->irq = 0; 94532b578d3Smrg } 94632b578d3Smrg 94732b578d3Smrg if (pATI->irq) 94832b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 94932b578d3Smrg "[drm] Installed interrupt handler, using IRQ %d\n", 95032b578d3Smrg pATI->irq); 95132b578d3Smrg else { 95232b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 95332b578d3Smrg "[drm] Falling back to irq-free operation\n"); 95432b578d3Smrg return FALSE; 95532b578d3Smrg } 95632b578d3Smrg } 95732b578d3Smrg 95832b578d3Smrg return TRUE; 95932b578d3Smrg 96032b578d3Smrg} 96132b578d3Smrg 96232b578d3Smrg/* Initialize the screen-specific data structures for the DRI and the 96332b578d3Smrg * Rage Pro. This is the main entry point to the device-specific 96432b578d3Smrg * initialization code. It calls device-independent DRI functions to 96532b578d3Smrg * create the DRI data structures and initialize the DRI state. 96632b578d3Smrg */ 96732b578d3SmrgBool ATIDRIScreenInit( ScreenPtr pScreen ) 96832b578d3Smrg{ 969e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 97032b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 97132b578d3Smrg DRIInfoPtr pDRIInfo; 97232b578d3Smrg ATIDRIPtr pATIDRI; 97332b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer; 97432b578d3Smrg drmVersionPtr version; 97532b578d3Smrg int major, minor, patch; 97632b578d3Smrg 9770b0ce0bfSmrg /* Check that the DRI, and DRM modules have been loaded by testing 97832b578d3Smrg * for known symbols in each module. 97932b578d3Smrg */ 98032b578d3Smrg if ( !xf86LoaderCheckSymbol("drmAvailable") ) return FALSE; 98132b578d3Smrg if ( !xf86LoaderCheckSymbol("DRIQueryVersion") ) { 98232b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 98332b578d3Smrg "[dri] ATIDRIScreenInit failed (libdri.a too old)\n" ); 98432b578d3Smrg return FALSE; 98532b578d3Smrg } 98632b578d3Smrg 98732b578d3Smrg /* Check the DRI version */ 98832b578d3Smrg DRIQueryVersion( &major, &minor, &patch ); 98932b578d3Smrg if ( major != DRIINFO_MAJOR_VERSION || minor < 0 ) { 99032b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 99132b578d3Smrg "[dri] ATIDRIScreenInit failed because of a version mismatch.\n" 99232b578d3Smrg "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n" 99332b578d3Smrg "[dri] Disabling the DRI.\n", 99432b578d3Smrg major, minor, patch, 99532b578d3Smrg DRIINFO_MAJOR_VERSION, 0 ); 99632b578d3Smrg return FALSE; 99732b578d3Smrg } 99832b578d3Smrg 99932b578d3Smrg switch ( pATI->bitsPerPixel ) { 100032b578d3Smrg case 8: 100132b578d3Smrg /* These modes are not supported (yet). */ 100232b578d3Smrg case 15: 100332b578d3Smrg case 24: 100432b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 100532b578d3Smrg "[dri] Direct rendering only supported in 16 and 32 bpp modes\n"); 100632b578d3Smrg return FALSE; 100732b578d3Smrg 100832b578d3Smrg /* Only 16 and 32 color depths are supported currently. */ 100932b578d3Smrg case 16: 101032b578d3Smrg if ( pATI->depth != 16) { 101132b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 101232b578d3Smrg "[dri] Direct rendering not supported for depth %d at fbbpp 16.\n", pATI->depth ); 101332b578d3Smrg return FALSE; 101432b578d3Smrg } 101532b578d3Smrg break; 101632b578d3Smrg case 32: 101732b578d3Smrg break; 101832b578d3Smrg } 101932b578d3Smrg 102032b578d3Smrg /* Create the DRI data structure, and fill it in before calling the 102132b578d3Smrg * DRIScreenInit(). 102232b578d3Smrg */ 102332b578d3Smrg pDRIInfo = DRICreateInfoRec(); 102432b578d3Smrg if ( !pDRIInfo ) return FALSE; 102532b578d3Smrg 102632b578d3Smrg pATI->pDRIInfo = pDRIInfo; 102732b578d3Smrg pDRIInfo->drmDriverName = ATIKernelDriverName; 102832b578d3Smrg pDRIInfo->clientDriverName = ATIClientDriverName; 102932b578d3Smrg if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 103032b578d3Smrg pDRIInfo->busIdString = DRICreatePCIBusID(pATI->PCIInfo); 103132b578d3Smrg } else { 10321b12faf6Smrg pDRIInfo->busIdString = malloc( 64 ); 103332b578d3Smrg sprintf( pDRIInfo->busIdString, 103432b578d3Smrg "PCI:%d:%d:%d", 103532b578d3Smrg PCI_DEV_BUS(pATI->PCIInfo), 103632b578d3Smrg PCI_DEV_DEV(pATI->PCIInfo), 103732b578d3Smrg PCI_DEV_FUNC(pATI->PCIInfo) ); 103832b578d3Smrg } 103932b578d3Smrg pDRIInfo->ddxDriverMajorVersion = MACH64_VERSION_MAJOR; 104032b578d3Smrg pDRIInfo->ddxDriverMinorVersion = MACH64_VERSION_MINOR; 104132b578d3Smrg pDRIInfo->ddxDriverPatchVersion = MACH64_VERSION_PATCH; 104232b578d3Smrg pDRIInfo->frameBufferPhysicalAddress = (void *)pATI->LinearBase; 104332b578d3Smrg pDRIInfo->frameBufferSize = pATI->LinearSize; 104432b578d3Smrg pDRIInfo->frameBufferStride = (pScreenInfo->displayWidth * 104532b578d3Smrg pATI->FBBytesPerPixel); 104632b578d3Smrg pDRIInfo->ddxDrawableTableEntry = ATI_MAX_DRAWABLES; 104732b578d3Smrg 104832b578d3Smrg if ( SAREA_MAX_DRAWABLES < ATI_MAX_DRAWABLES ) { 104932b578d3Smrg pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; 105032b578d3Smrg } else { 105132b578d3Smrg pDRIInfo->maxDrawableTableEntry = ATI_MAX_DRAWABLES; 105232b578d3Smrg } 105332b578d3Smrg 105432b578d3Smrg /* For now the mapping works by using a fixed size defined 105532b578d3Smrg * in the SAREA header 105632b578d3Smrg */ 105732b578d3Smrg if ( sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec) > SAREA_MAX ) { 105832b578d3Smrg ErrorF( "[dri] Data does not fit in SAREA\n" ); 105932b578d3Smrg return FALSE; 106032b578d3Smrg } 106132b578d3Smrg xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %u+%u: %u\n", 106232b578d3Smrg (unsigned)sizeof(XF86DRISAREARec), 106332b578d3Smrg (unsigned)sizeof(ATISAREAPrivRec), 106432b578d3Smrg (unsigned)(sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec)) ); 106532b578d3Smrg pDRIInfo->SAREASize = SAREA_MAX; 106632b578d3Smrg 106732b578d3Smrg pATIDRI = (ATIDRIPtr) xnfcalloc( sizeof(ATIDRIRec), 1 ); 106832b578d3Smrg if ( !pATIDRI ) { 106932b578d3Smrg DRIDestroyInfoRec( pATI->pDRIInfo ); 107032b578d3Smrg pATI->pDRIInfo = NULL; 107132b578d3Smrg xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR, 107232b578d3Smrg "[dri] Failed to allocate memory for private record\n" ); 107332b578d3Smrg return FALSE; 107432b578d3Smrg } 107532b578d3Smrg pATIDRIServer = (ATIDRIServerInfoPtr) 107632b578d3Smrg xnfcalloc( sizeof(ATIDRIServerInfoRec), 1 ); 107732b578d3Smrg if ( !pATIDRIServer ) { 10781b12faf6Smrg free( pATIDRI ); 107932b578d3Smrg DRIDestroyInfoRec( pATI->pDRIInfo ); 108032b578d3Smrg pATI->pDRIInfo = NULL; 108132b578d3Smrg xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR, 108232b578d3Smrg "[dri] Failed to allocate memory for private record\n" ); 108332b578d3Smrg return FALSE; 108432b578d3Smrg } 108532b578d3Smrg 108632b578d3Smrg pATI->pDRIServerInfo = pATIDRIServer; 108732b578d3Smrg 108832b578d3Smrg pDRIInfo->devPrivate = pATIDRI; 108932b578d3Smrg pDRIInfo->devPrivateSize = sizeof(ATIDRIRec); 109032b578d3Smrg pDRIInfo->contextSize = sizeof(ATIDRIContextRec); 109132b578d3Smrg 109232b578d3Smrg pDRIInfo->CreateContext = ATICreateContext; 109332b578d3Smrg pDRIInfo->DestroyContext = ATIDestroyContext; 109432b578d3Smrg pDRIInfo->SwapContext = ATIDRISwapContext; 109532b578d3Smrg pDRIInfo->InitBuffers = ATIDRIInitBuffers; 109632b578d3Smrg pDRIInfo->MoveBuffers = ATIDRIMoveBuffers; 109732b578d3Smrg#ifdef USE_XAA 109832b578d3Smrg if (!pATI->useEXA) { 109932b578d3Smrg pDRIInfo->TransitionTo2d = ATIDRITransitionTo2d; 110032b578d3Smrg pDRIInfo->TransitionTo3d = ATIDRITransitionTo3d; 110132b578d3Smrg } 110232b578d3Smrg#endif /* USE_XAA */ 110332b578d3Smrg#ifdef USE_EXA 110432b578d3Smrg if (pATI->useEXA) { 110532b578d3Smrg pDRIInfo->TransitionTo2d = ATIDRITransitionTo2d_EXA; 110632b578d3Smrg pDRIInfo->TransitionTo3d = ATIDRITransitionTo3d_EXA; 110732b578d3Smrg } 110832b578d3Smrg#endif /* USE_EXA */ 110932b578d3Smrg pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 111032b578d3Smrg 111132b578d3Smrg pDRIInfo->createDummyCtx = TRUE; 111232b578d3Smrg pDRIInfo->createDummyCtxPriv = FALSE; 111332b578d3Smrg 111432b578d3Smrg pATI->have3DWindows = FALSE; 111532b578d3Smrg 111632b578d3Smrg if ( !DRIScreenInit( pScreen, pDRIInfo, &pATI->drmFD ) ) { 11171b12faf6Smrg free( pATIDRIServer ); 111832b578d3Smrg pATI->pDRIServerInfo = NULL; 11191b12faf6Smrg free( pDRIInfo->devPrivate ); 112032b578d3Smrg pDRIInfo->devPrivate = NULL; 112132b578d3Smrg DRIDestroyInfoRec( pDRIInfo ); 112232b578d3Smrg pDRIInfo = NULL; 112332b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 112432b578d3Smrg "[dri] DRIScreenInit Failed\n" ); 112532b578d3Smrg return FALSE; 112632b578d3Smrg } 112732b578d3Smrg 112832b578d3Smrg /* Check the DRM lib version. 112932b578d3Smrg drmGetLibVersion was not supported in version 1.0, so check for 113032b578d3Smrg symbol first to avoid possible crash or hang. 113132b578d3Smrg */ 113232b578d3Smrg if (xf86LoaderCheckSymbol("drmGetLibVersion")) { 113332b578d3Smrg version = drmGetLibVersion(pATI->drmFD); 113432b578d3Smrg } else { 113532b578d3Smrg /* drmlib version 1.0.0 didn't have the drmGetLibVersion 113632b578d3Smrg entry point. Fake it by allocating a version record 113732b578d3Smrg via drmGetVersion and changing it to version 1.0.0 113832b578d3Smrg */ 113932b578d3Smrg version = drmGetVersion(pATI->drmFD); 114032b578d3Smrg version->version_major = 1; 114132b578d3Smrg version->version_minor = 0; 114232b578d3Smrg version->version_patchlevel = 0; 114332b578d3Smrg } 114432b578d3Smrg 114532b578d3Smrg if (version) { 114632b578d3Smrg if (version->version_major != 1 || 114732b578d3Smrg version->version_minor < 1) { 114832b578d3Smrg /* incompatible drm library version */ 114932b578d3Smrg xf86DrvMsg(pScreen->myNum, X_ERROR, 115032b578d3Smrg "[dri] ATIDRIScreenInit failed because of a version mismatch.\n" 115132b578d3Smrg "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n" 115232b578d3Smrg "[dri] Disabling DRI.\n", 115332b578d3Smrg version->version_major, 115432b578d3Smrg version->version_minor, 115532b578d3Smrg version->version_patchlevel); 115632b578d3Smrg drmFreeVersion(version); 115732b578d3Smrg ATIDRICloseScreen(pScreen); 115832b578d3Smrg return FALSE; 115932b578d3Smrg } 116032b578d3Smrg drmFreeVersion(version); 116132b578d3Smrg } 116232b578d3Smrg 116332b578d3Smrg /* Check the mach64 DRM version */ 116432b578d3Smrg version = drmGetVersion( pATI->drmFD ); 116532b578d3Smrg if ( version ) { 116632b578d3Smrg if ( version->version_major != 2 || 116732b578d3Smrg version->version_minor < 0 ) { 116832b578d3Smrg /* Incompatible DRM version */ 116932b578d3Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 117032b578d3Smrg "[dri] ATIDRIScreenInit failed because of a version mismatch.\n" 117132b578d3Smrg "[dri] mach64.o kernel module version is %d.%d.%d, but version 2.x is needed (with 2.x >= 2.0).\n" 117232b578d3Smrg "[dri] Disabling DRI.\n", 117332b578d3Smrg version->version_major, 117432b578d3Smrg version->version_minor, 117532b578d3Smrg version->version_patchlevel ); 117632b578d3Smrg drmFreeVersion( version ); 117732b578d3Smrg ATIDRICloseScreen( pScreen ); 117832b578d3Smrg return FALSE; 117932b578d3Smrg } 118032b578d3Smrg drmFreeVersion( version ); 118132b578d3Smrg } 118232b578d3Smrg 118332b578d3Smrg switch ( pATI->OptionDMAMode ) { 118432b578d3Smrg case MACH64_MODE_DMA_ASYNC: 118532b578d3Smrg xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request asynchronous DMA mode\n"); 118632b578d3Smrg break; 118732b578d3Smrg case MACH64_MODE_DMA_SYNC: 118832b578d3Smrg xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request synchronous DMA mode\n"); 118932b578d3Smrg break; 119032b578d3Smrg case MACH64_MODE_MMIO: 119132b578d3Smrg xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request pseudo-DMA (MMIO) mode\n"); 119232b578d3Smrg break; 119332b578d3Smrg default: 119432b578d3Smrg xf86DrvMsg(pScreen->myNum, X_WARNING, "[drm] Unknown DMA mode\n"); 119532b578d3Smrg } 119632b578d3Smrg 119732b578d3Smrg pATIDRIServer->IsPCI = (pATI->BusType == ATI_BUS_PCI || pATI->OptionIsPCI) ? TRUE : FALSE; 119832b578d3Smrg 119932b578d3Smrg if ( pATI->BusType != ATI_BUS_PCI && pATI->OptionIsPCI ) { 120032b578d3Smrg xf86DrvMsg(pScreen->myNum, X_CONFIG, "[dri] Forcing PCI mode\n"); 120132b578d3Smrg } 120232b578d3Smrg 120332b578d3Smrg /* Initialize AGP */ 120432b578d3Smrg if ( !pATIDRIServer->IsPCI && !ATIDRIAgpInit( pScreen ) ) { 120532b578d3Smrg pATIDRIServer->IsPCI = TRUE; 120632b578d3Smrg xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP failed to initialize -- falling back to PCI mode.\n" ); 120732b578d3Smrg xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] Make sure you have the agpgart kernel module loaded.\n" ); 120832b578d3Smrg } 120932b578d3Smrg 121032b578d3Smrg /* Initialize PCI */ 121132b578d3Smrg if ( pATIDRIServer->IsPCI && !ATIDRIPciInit( pScreen ) ) { 121232b578d3Smrg ATIDRICloseScreen( pScreen ); 121332b578d3Smrg return FALSE; 121432b578d3Smrg } 121532b578d3Smrg 121632b578d3Smrg if ( !ATIDRIMapInit( pScreen ) ) { 121732b578d3Smrg ATIDRICloseScreen( pScreen ); 121832b578d3Smrg return FALSE; 121932b578d3Smrg } 122032b578d3Smrg 122132b578d3Smrg xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, 122232b578d3Smrg "[dri] Visual configs initialized\n" ); 122332b578d3Smrg 122432b578d3Smrg xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, 122532b578d3Smrg "[dri] Block 0 base at 0x%08lx\n", pATI->Block0Base ); 122632b578d3Smrg 122732b578d3Smrg return TRUE; 122832b578d3Smrg} 122932b578d3Smrg 123032b578d3Smrg/* Finish initializing the device-dependent DRI state, and call 123132b578d3Smrg * DRIFinishScreenInit() to complete the device-independent DRI 123232b578d3Smrg * initialization. 123332b578d3Smrg */ 123432b578d3SmrgBool ATIDRIFinishScreenInit( ScreenPtr pScreen ) 123532b578d3Smrg{ 1236e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 123732b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 123832b578d3Smrg ATISAREAPrivPtr pSAREAPriv; 123932b578d3Smrg ATIDRIPtr pATIDRI; 124032b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer; 124132b578d3Smrg 124232b578d3Smrg pATI->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 124332b578d3Smrg 124432b578d3Smrg /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit 124532b578d3Smrg * because *DRIKernelInit requires that the hardware lock is held by 124632b578d3Smrg * the X server, and the first time the hardware lock is grabbed is 124732b578d3Smrg * in DRIFinishScreenInit. 124832b578d3Smrg */ 124932b578d3Smrg if ( !DRIFinishScreenInit( pScreen ) ) { 125032b578d3Smrg ATIDRICloseScreen( pScreen ); 125132b578d3Smrg return FALSE; 125232b578d3Smrg } 125332b578d3Smrg 125432b578d3Smrg /* Initialize the DMA buffer list */ 125532b578d3Smrg /* Need to do this before ATIDRIKernelInit so we can init the freelist */ 125632b578d3Smrg if ( !ATIDRIAddBuffers( pScreen ) ) { 125732b578d3Smrg ATIDRICloseScreen( pScreen ); 125832b578d3Smrg return FALSE; 125932b578d3Smrg } 126032b578d3Smrg 126132b578d3Smrg /* Initialize the kernel data structures */ 126232b578d3Smrg if ( !ATIDRIKernelInit( pScreen ) ) { 126332b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 126432b578d3Smrg "[drm] Failed to initialize the mach64.o kernel module\n"); 126532b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 126632b578d3Smrg "[drm] Check the system log for more information.\n"); 126732b578d3Smrg ATIDRICloseScreen( pScreen ); 126832b578d3Smrg return FALSE; 126932b578d3Smrg } 127032b578d3Smrg 127132b578d3Smrg if ( !ATIDRIMapBuffers( pScreen ) ) { 127232b578d3Smrg ATIDRICloseScreen( pScreen ); 127332b578d3Smrg return FALSE; 127432b578d3Smrg } 127532b578d3Smrg 127632b578d3Smrg /* Initialize IRQ */ 127732b578d3Smrg ATIDRIIrqInit( pScreen ); 127832b578d3Smrg 127932b578d3Smrg pSAREAPriv = (ATISAREAPrivPtr) DRIGetSAREAPrivate( pScreen ); 128032b578d3Smrg memset( pSAREAPriv, 0, sizeof(*pSAREAPriv) ); 128132b578d3Smrg 128232b578d3Smrg pATIDRI = (ATIDRIPtr)pATI->pDRIInfo->devPrivate; 128332b578d3Smrg pATIDRIServer = pATI->pDRIServerInfo; 128432b578d3Smrg 128532b578d3Smrg pATIDRI->width = pScreenInfo->virtualX; 128632b578d3Smrg pATIDRI->height = pScreenInfo->virtualY; 128732b578d3Smrg pATIDRI->mem = pScreenInfo->videoRam * 1024; 128832b578d3Smrg pATIDRI->cpp = pScreenInfo->bitsPerPixel / 8; 128932b578d3Smrg 129032b578d3Smrg pATIDRI->IsPCI = pATIDRIServer->IsPCI; 129132b578d3Smrg pATIDRI->AGPMode = pATIDRIServer->agpMode; 129232b578d3Smrg 129332b578d3Smrg pATIDRI->frontOffset = pATIDRIServer->frontOffset; 129432b578d3Smrg pATIDRI->frontPitch = pATIDRIServer->frontPitch; 129532b578d3Smrg 129632b578d3Smrg pATIDRI->backOffset = pATIDRIServer->backOffset; 129732b578d3Smrg pATIDRI->backPitch = pATIDRIServer->backPitch; 129832b578d3Smrg 129932b578d3Smrg pATIDRI->depthOffset = pATIDRIServer->depthOffset; 130032b578d3Smrg pATIDRI->depthPitch = pATIDRIServer->depthPitch; 130132b578d3Smrg 130232b578d3Smrg pATIDRI->textureOffset = pATIDRIServer->textureOffset; 130332b578d3Smrg pATIDRI->textureSize = pATIDRIServer->textureSize; 130432b578d3Smrg pATIDRI->logTextureGranularity = pATIDRIServer->logTextureGranularity; 130532b578d3Smrg 130632b578d3Smrg pATIDRI->regs = pATIDRIServer->regsHandle; 130732b578d3Smrg pATIDRI->regsSize = pATIDRIServer->regsSize; 130832b578d3Smrg 130932b578d3Smrg pATIDRI->agp = pATIDRIServer->agpTexHandle; 131032b578d3Smrg pATIDRI->agpSize = pATIDRIServer->agpTexMapSize; 131132b578d3Smrg pATIDRI->logAgpTextureGranularity = pATIDRIServer->log2AGPTexGran; 131232b578d3Smrg pATIDRI->agpTextureOffset = pATIDRIServer->agpTexStart; 131332b578d3Smrg 131432b578d3Smrg return TRUE; 131532b578d3Smrg} 131632b578d3Smrg 131732b578d3Smrg/* 131832b578d3Smrg * This function will attempt to get the Mach64 hardware back into shape 131932b578d3Smrg * after a resume from disc. Its an extract from ATIDRIAgpInit and ATIDRIFinishScreenInit 132032b578d3Smrg * This also calls a new ioctl in the mach64 DRM that in its turn is 132132b578d3Smrg * an extraction of the hardware-affecting bits from mach64_do_init_drm() 132232b578d3Smrg * (see atidrm.c) 132332b578d3Smrg * I am assuming here that pATI->pDRIServerInfo doesn't change 13240b0ce0bfSmrg * elsewhere in incompatible ways. 132532b578d3Smrg * How will this code react to resuming after a failed resumeor pci based dri ? 132632b578d3Smrg */ 132732b578d3Smrgvoid ATIDRIResume( ScreenPtr pScreen ) 132832b578d3Smrg{ 1329e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 133032b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 133132b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 133232b578d3Smrg 133332b578d3Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 133432b578d3Smrg "[RESUME] Attempting to re-init Mach64 hardware.\n"); 133532b578d3Smrg 133632b578d3Smrg if (!pATIDRIServer->IsPCI) { 133732b578d3Smrg if (!ATIDRISetAgpMode(pScreen)) 133832b578d3Smrg return; 133932b578d3Smrg 134032b578d3Smrg outm( AGP_BASE, drmAgpBase(pATI->drmFD) ); 134132b578d3Smrg } 134232b578d3Smrg} 134332b578d3Smrg 134432b578d3Smrg/* The screen is being closed, so clean up any state and free any 134532b578d3Smrg * resources used by the DRI. 134632b578d3Smrg */ 134732b578d3Smrgvoid ATIDRICloseScreen( ScreenPtr pScreen ) 134832b578d3Smrg{ 1349e35d4d8eSmrg ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen); 135032b578d3Smrg ATIPtr pATI = ATIPTR(pScreenInfo); 135132b578d3Smrg ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 135232b578d3Smrg drmMach64Init info; 135332b578d3Smrg 135432b578d3Smrg /* Stop interrupt generation and handling if used */ 135532b578d3Smrg if ( pATI->irq > 0 ) { 135632b578d3Smrg if ( drmCtlUninstHandler(pATI->drmFD) != 0 ) { 135732b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 135832b578d3Smrg "[drm] Error uninstalling interrupt handler for IRQ %d\n", pATI->irq); 135932b578d3Smrg } else { 136032b578d3Smrg xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 136132b578d3Smrg "[drm] Uninstalled interrupt handler for IRQ %d\n", pATI->irq); 136232b578d3Smrg } 136332b578d3Smrg pATI->irq = 0; 136432b578d3Smrg } 136532b578d3Smrg 136632b578d3Smrg /* De-allocate DMA buffers */ 136732b578d3Smrg if ( pATIDRIServer->drmBuffers ) { 136832b578d3Smrg drmUnmapBufs( pATIDRIServer->drmBuffers ); 136932b578d3Smrg pATIDRIServer->drmBuffers = NULL; 137032b578d3Smrg } 137132b578d3Smrg 137232b578d3Smrg /* De-allocate all kernel resources */ 137332b578d3Smrg memset(&info, 0, sizeof(drmMach64Init)); 137432b578d3Smrg info.func = DRM_MACH64_CLEANUP_DMA; 137532b578d3Smrg drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT, 137632b578d3Smrg &info, sizeof(drmMach64Init) ); 137732b578d3Smrg 137832b578d3Smrg /* De-allocate all AGP resources */ 137932b578d3Smrg if ( pATIDRIServer->agpTexMap ) { 138032b578d3Smrg drmUnmap( pATIDRIServer->agpTexMap, pATIDRIServer->agpTexMapSize ); 138132b578d3Smrg pATIDRIServer->agpTexMap = NULL; 138232b578d3Smrg } 138332b578d3Smrg if ( pATIDRIServer->bufferMap ) { 138432b578d3Smrg drmUnmap( pATIDRIServer->bufferMap, pATIDRIServer->bufferMapSize ); 138532b578d3Smrg pATIDRIServer->bufferMap = NULL; 138632b578d3Smrg } 138732b578d3Smrg if ( pATIDRIServer->ringMap ) { 138832b578d3Smrg drmUnmap( pATIDRIServer->ringMap, pATIDRIServer->ringMapSize ); 138932b578d3Smrg pATIDRIServer->ringMap = NULL; 139032b578d3Smrg } 139132b578d3Smrg if ( pATIDRIServer->agpHandle ) { 139232b578d3Smrg drmAgpUnbind( pATI->drmFD, pATIDRIServer->agpHandle ); 139332b578d3Smrg drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle ); 139432b578d3Smrg pATIDRIServer->agpHandle = 0; 139532b578d3Smrg drmAgpRelease( pATI->drmFD ); 139632b578d3Smrg } 139732b578d3Smrg 139832b578d3Smrg /* De-allocate all PCI resources */ 139932b578d3Smrg if ( pATIDRIServer->IsPCI && pATIDRIServer->ringHandle ) { 140032b578d3Smrg drmRmMap( pATI->drmFD, pATIDRIServer->ringHandle ); 140132b578d3Smrg pATIDRIServer->ringHandle = 0; 140232b578d3Smrg } 140332b578d3Smrg 140432b578d3Smrg /* De-allocate all DRI resources */ 140532b578d3Smrg DRICloseScreen( pScreen ); 140632b578d3Smrg 140732b578d3Smrg /* De-allocate all DRI data structures */ 140832b578d3Smrg if ( pATI->pDRIInfo ) { 140932b578d3Smrg if ( pATI->pDRIInfo->devPrivate ) { 14101b12faf6Smrg free( pATI->pDRIInfo->devPrivate ); 141132b578d3Smrg pATI->pDRIInfo->devPrivate = NULL; 141232b578d3Smrg } 141332b578d3Smrg DRIDestroyInfoRec( pATI->pDRIInfo ); 141432b578d3Smrg pATI->pDRIInfo = NULL; 141532b578d3Smrg } 141632b578d3Smrg if ( pATI->pDRIServerInfo ) { 14171b12faf6Smrg free( pATI->pDRIServerInfo ); 141832b578d3Smrg pATI->pDRIServerInfo = NULL; 141932b578d3Smrg } 142032b578d3Smrg} 1421