mirror of
https://github.com/X11Libre/xf86-video-mach64.git
synced 2026-03-24 01:24:33 +00:00
Performed with: `git ls-files | xargs perl -i -p -e 's{[ \t]+$}{}'`
`git diff -w` & `git diff -b` show no diffs from this change
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/driver/xf86-video-mach64/-/merge_requests/23>
1129 lines
37 KiB
C
1129 lines
37 KiB
C
/* -*- mode: c; c-basic-offset: 3 -*- */
|
|
/*
|
|
* Copyright 2000 Gareth Hughes
|
|
* All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
/*
|
|
* Authors:
|
|
* Gareth Hughes <gareth@valinux.com>
|
|
* Leif Delgass <ldelgass@retinalburn.net>
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
/* Driver data structures */
|
|
#include "ati.h"
|
|
#include "atibus.h"
|
|
#include "atidri.h"
|
|
#include "atiregs.h"
|
|
#include "atistruct.h"
|
|
|
|
#include "atimach64io.h"
|
|
#include "atimach64version.h"
|
|
#include "mach64_dri.h"
|
|
#include "mach64_common.h"
|
|
#include "mach64_sarea.h"
|
|
|
|
/* X and server generic header files */
|
|
#include "xf86.h"
|
|
#include "windowstr.h"
|
|
|
|
/* DRI/DRM definitions */
|
|
#define _XF86DRI_SERVER_
|
|
#include "sarea.h"
|
|
|
|
static char ATIKernelDriverName[] = "mach64";
|
|
static char ATIClientDriverName[] = "mach64";
|
|
|
|
/* Create the ATI-specific context information */
|
|
static Bool ATICreateContext( ScreenPtr pScreen, VisualPtr visual,
|
|
drm_context_t hwContext, void *pVisualConfigPriv,
|
|
DRIContextType contextStore )
|
|
{
|
|
/* Nothing yet */
|
|
return TRUE;
|
|
}
|
|
|
|
/* Destroy the ATI-specific context information */
|
|
static void ATIDestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
|
|
DRIContextType contextStore )
|
|
{
|
|
/* Nothing yet */
|
|
}
|
|
|
|
/* Called when the X server is woken up to allow the last client's
|
|
* context to be saved and the X server's context to be loaded.
|
|
* The client detects when it's context is not currently loaded and
|
|
* then loads it itself. The X server's context is loaded in the
|
|
* XAA Sync callback if NeedDRISync is set.
|
|
*/
|
|
static void ATIEnterServer( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
|
|
if ( pATI->directRenderingEnabled ) {
|
|
ATIDRIMarkSyncInt(pScreenInfo);
|
|
ATIDRIMarkSyncExt(pScreenInfo);
|
|
}
|
|
}
|
|
|
|
/* Called when the X server goes to sleep to allow the X server's
|
|
* context to be saved and the last client's context to be loaded.
|
|
* The client detects when it's context is not currently loaded and
|
|
* then loads it itself. The X server keeps track of it's own state.
|
|
*/
|
|
static void ATILeaveServer( ScreenPtr pScreen )
|
|
{
|
|
/* Nothing yet */
|
|
}
|
|
|
|
/* Contexts can be swapped by the X server if necessary. This callback
|
|
* is currently only used to perform any functions necessary when
|
|
* entering or leaving the X server, and in the future might not be
|
|
* necessary.
|
|
*/
|
|
static void ATIDRISwapContext( ScreenPtr pScreen,
|
|
DRISyncType syncType,
|
|
DRIContextType oldContextType,
|
|
void *oldContext,
|
|
DRIContextType newContextType,
|
|
void *newContext )
|
|
{
|
|
if ( ( syncType == DRI_3D_SYNC ) && ( oldContextType == DRI_2D_CONTEXT ) &&
|
|
( newContextType == DRI_2D_CONTEXT ) ) {
|
|
/* Entering from Wakeup */
|
|
ATIEnterServer( pScreen );
|
|
}
|
|
if ( ( syncType == DRI_2D_SYNC ) && ( oldContextType == DRI_NO_CONTEXT ) &&
|
|
( newContextType == DRI_2D_CONTEXT ) ) {
|
|
/* Exiting from Block Handler */
|
|
ATILeaveServer( pScreen );
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef USE_EXA
|
|
static void ATIDRITransitionTo2d_EXA(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
exaEnableDisableFBAccess(pScreen, FALSE);
|
|
|
|
pATI->pExa->offScreenBase = pATIDRIServer->backOffset;
|
|
|
|
exaEnableDisableFBAccess(pScreen, TRUE);
|
|
|
|
pATI->have3DWindows = FALSE;
|
|
}
|
|
|
|
static void ATIDRITransitionTo3d_EXA(ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
exaEnableDisableFBAccess(pScreen, FALSE);
|
|
|
|
pATI->pExa->offScreenBase = pATIDRIServer->textureOffset +
|
|
pATIDRIServer->textureSize;
|
|
|
|
exaEnableDisableFBAccess(pScreen, TRUE);
|
|
|
|
pATI->have3DWindows = TRUE;
|
|
}
|
|
#endif /* USE_EXA */
|
|
|
|
/* Initialize the state of the back and depth buffers. */
|
|
static void ATIDRIInitBuffers( WindowPtr pWin, RegionPtr prgn, CARD32 indx )
|
|
{
|
|
}
|
|
|
|
/* Copy the back and depth buffers when the X server moves a window.
|
|
*
|
|
* Note: this function was copied from the Radeon driver...
|
|
*
|
|
* This routine is a modified form of XAADoBitBlt with the calls to
|
|
* ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
|
|
* instead of destination. My origin is upside down so the ydir cases
|
|
* are reversed.
|
|
*/
|
|
static void ATIDRIMoveBuffers( WindowPtr pWin, DDXPointRec ptOldOrg,
|
|
RegionPtr prgnSrc, CARD32 indx )
|
|
{
|
|
}
|
|
|
|
/* Compute log base 2 of val. */
|
|
static int Mach64MinBits(int val)
|
|
{
|
|
int bits;
|
|
|
|
if (!val) return 1;
|
|
for (bits = 0; val; val >>= 1, ++bits);
|
|
return bits;
|
|
}
|
|
|
|
static Bool ATIDRISetBufSize( ScreenPtr pScreen, unsigned int maxSize )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
if (pATI->OptionBufferSize) {
|
|
if (pATI->OptionBufferSize < 1 || pATI->OptionBufferSize > maxSize ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Illegal DMA buffers size: %d MB\n",
|
|
pATI->OptionBufferSize );
|
|
return FALSE;
|
|
}
|
|
if (pATI->OptionBufferSize > 2) {
|
|
xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Illegal DMA buffers size: %d MB\n",
|
|
pATI->OptionBufferSize );
|
|
xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Clamping DMA buffers size to 2 MB\n");
|
|
pATIDRIServer->bufferSize = 2;
|
|
} else {
|
|
pATIDRIServer->bufferSize = pATI->OptionBufferSize;
|
|
xf86DrvMsg( pScreen->myNum, X_CONFIG, "[drm] Using %d MB for DMA buffers\n",
|
|
pATIDRIServer->bufferSize );
|
|
}
|
|
} else {
|
|
xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[drm] Using %d MB for DMA buffers\n",
|
|
pATIDRIServer->bufferSize );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool ATIDRISetAgpMode( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
unsigned long mode = drmAgpGetMode( pATI->drmFD ); /* Default mode */
|
|
unsigned int vendor = drmAgpVendorId( pATI->drmFD );
|
|
unsigned int device = drmAgpDeviceId( pATI->drmFD );
|
|
|
|
if (pATI->OptionAGPMode > 0 && pATI->OptionAGPMode <= ATI_AGP_MAX_MODE) {
|
|
pATIDRIServer->agpMode = pATI->OptionAGPMode;
|
|
xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using AGP %dx Mode\n",
|
|
pATIDRIServer->agpMode );
|
|
} else if (pATI->OptionAGPMode > 0) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Illegal AGP Mode: %d\n",
|
|
pATI->OptionAGPMode );
|
|
return FALSE;
|
|
} else {
|
|
/* If no mode configured, use the default mode obtained from agpgart */
|
|
if ( mode & AGP_MODE_2X ) {
|
|
pATIDRIServer->agpMode = 2;
|
|
} else if ( mode & AGP_MODE_1X ) {
|
|
pATIDRIServer->agpMode = 1;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using AGP %dx Mode\n",
|
|
pATIDRIServer->agpMode );
|
|
}
|
|
|
|
mode &= ~AGP_MODE_MASK;
|
|
switch ( pATIDRIServer->agpMode ) {
|
|
case 2: mode |= AGP_MODE_2X; /* FALLTHROUGH */
|
|
case 1: default: mode |= AGP_MODE_1X;
|
|
}
|
|
|
|
if (pATI->OptionAGPSize) {
|
|
switch (pATI->OptionAGPSize) {
|
|
case 128:
|
|
case 64:
|
|
case 32:
|
|
case 16:
|
|
case 8:
|
|
case 4:
|
|
pATIDRIServer->agpSize = pATI->OptionAGPSize;
|
|
xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using %d MB AGP aperture\n",
|
|
pATIDRIServer->agpSize );
|
|
break;
|
|
default:
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[agp] Illegal aperture size %d MB\n", pATI->OptionAGPSize );
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using %d MB AGP aperture\n",
|
|
pATIDRIServer->agpSize );
|
|
}
|
|
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
|
|
mode, vendor, device,
|
|
PCI_DEV_VENDOR_ID(pATI->PCIInfo),
|
|
PCI_DEV_DEVICE_ID(pATI->PCIInfo) );
|
|
|
|
if ( drmAgpEnable( pATI->drmFD, mode ) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
|
|
drmAgpRelease( pATI->drmFD );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Initialize the AGP state. Request memory for use in AGP space, and
|
|
* initialize the Rage Pro registers to point to that memory.
|
|
*/
|
|
static Bool ATIDRIAgpInit( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
int ret;
|
|
unsigned long cntl;
|
|
int s, l;
|
|
|
|
pATIDRIServer->agpSize = ATI_DEFAULT_AGP_SIZE;
|
|
pATIDRIServer->agpMode = ATI_DEFAULT_AGP_MODE;
|
|
pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
|
|
pATIDRIServer->ringSize = 16; /* 16 kB ring */
|
|
|
|
if ( drmAgpAcquire( pATI->drmFD ) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP not available\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
if (!ATIDRISetAgpMode( pScreen ))
|
|
return FALSE;
|
|
|
|
pATIDRIServer->agpOffset = 0;
|
|
|
|
ret = drmAgpAlloc( pATI->drmFD, pATIDRIServer->agpSize*1024*1024,
|
|
0, NULL, &pATIDRIServer->agpHandle );
|
|
if ( ret < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
|
|
drmAgpRelease( pATI->drmFD );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[agp] %d kB allocated with handle 0x%08x\n",
|
|
pATIDRIServer->agpSize*1024, pATIDRIServer->agpHandle );
|
|
|
|
if ( drmAgpBind( pATI->drmFD, pATIDRIServer->agpHandle, pATIDRIServer->agpOffset) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind\n" );
|
|
drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
|
|
drmAgpRelease( pATI->drmFD );
|
|
return FALSE;
|
|
}
|
|
|
|
xf86DrvMsg(pScreen->myNum, X_INFO,
|
|
"[agp] Using %d kB for DMA descriptor ring\n", pATIDRIServer->ringSize);
|
|
|
|
if ( !ATIDRISetBufSize( pScreen, pATIDRIServer->agpSize ) )
|
|
return FALSE;
|
|
|
|
pATIDRIServer->agpTexSize = pATIDRIServer->agpSize - pATIDRIServer->bufferSize;
|
|
|
|
/* Reserve space for the DMA descriptor ring */
|
|
pATIDRIServer->ringStart = pATIDRIServer->agpOffset;
|
|
pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */
|
|
|
|
/* Reserve space for the vertex buffer */
|
|
pATIDRIServer->bufferStart = pATIDRIServer->ringStart + pATIDRIServer->ringMapSize;
|
|
pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024;
|
|
|
|
/* Reserve the rest for AGP textures */
|
|
pATIDRIServer->agpTexStart = pATIDRIServer->bufferStart + pATIDRIServer->bufferMapSize;
|
|
s = (pATIDRIServer->agpSize*1024*1024 - pATIDRIServer->agpTexStart);
|
|
l = Mach64MinBits((s-1) / MACH64_NR_TEX_REGIONS);
|
|
if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY;
|
|
pATIDRIServer->agpTexMapSize = (s >> l) << l;
|
|
pATIDRIServer->log2AGPTexGran = l;
|
|
|
|
xf86DrvMsg(pScreen->myNum, X_INFO,
|
|
"[agp] Using %d kB for AGP textures\n", pATIDRIServer->agpTexMapSize/1024);
|
|
|
|
/* Map DMA descriptor ring */
|
|
if ( drmAddMap( pATI->drmFD, pATIDRIServer->ringStart, pATIDRIServer->ringMapSize,
|
|
DRM_AGP, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[agp] Could not add ring mapping\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[agp] ring handle = 0x%08x\n",
|
|
pATIDRIServer->ringHandle );
|
|
|
|
if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle,
|
|
pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[agp] Could not map ring\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[agp] Ring mapped at 0x%08lx\n",
|
|
(unsigned long)pATIDRIServer->ringMap );
|
|
|
|
/* Map vertex buffers */
|
|
if ( drmAddMap( pATI->drmFD, pATIDRIServer->bufferStart, pATIDRIServer->bufferMapSize,
|
|
DRM_AGP, DRM_READ_ONLY, &pATIDRIServer->bufferHandle ) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[agp] Could not add vertex buffers mapping\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[agp] vertex buffers handle = 0x%08x\n",
|
|
pATIDRIServer->bufferHandle );
|
|
|
|
if ( drmMap( pATI->drmFD, pATIDRIServer->bufferHandle,
|
|
pATIDRIServer->bufferMapSize, &pATIDRIServer->bufferMap ) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[agp] Could not map vertex buffers\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[agp] Vertex buffers mapped at 0x%08lx\n",
|
|
(unsigned long)pATIDRIServer->bufferMap );
|
|
|
|
/* Map AGP Textures */
|
|
if (drmAddMap(pATI->drmFD, pATIDRIServer->agpTexStart, pATIDRIServer->agpTexMapSize,
|
|
DRM_AGP, 0, &pATIDRIServer->agpTexHandle) < 0) {
|
|
xf86DrvMsg(pScreen->myNum, X_ERROR,
|
|
"[agp] Could not add AGP texture region mapping\n");
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg(pScreen->myNum, X_INFO,
|
|
"[agp] AGP texture region handle = 0x%08x\n",
|
|
pATIDRIServer->agpTexHandle);
|
|
|
|
if (drmMap(pATI->drmFD, pATIDRIServer->agpTexHandle, pATIDRIServer->agpTexMapSize,
|
|
&pATIDRIServer->agpTexMap) < 0) {
|
|
xf86DrvMsg(pScreen->myNum, X_ERROR,
|
|
"[agp] Could not map AGP texture region\n");
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg(pScreen->myNum, X_INFO,
|
|
"[agp] AGP Texture region mapped at 0x%08lx\n",
|
|
(unsigned long)pATIDRIServer->agpTexMap);
|
|
|
|
/* Initialize Mach64's AGP registers */
|
|
cntl = inm( AGP_CNTL );
|
|
cntl &= ~AGP_APER_SIZE_MASK;
|
|
switch ( pATIDRIServer->agpSize ) {
|
|
case 256: cntl |= AGP_APER_SIZE_256MB; break;
|
|
case 128: cntl |= AGP_APER_SIZE_128MB; break;
|
|
case 64: cntl |= AGP_APER_SIZE_64MB; break;
|
|
case 32: cntl |= AGP_APER_SIZE_32MB; break;
|
|
case 16: cntl |= AGP_APER_SIZE_16MB; break;
|
|
case 8: cntl |= AGP_APER_SIZE_8MB; break;
|
|
case 4: cntl |= AGP_APER_SIZE_4MB; break;
|
|
default:
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[agp] Illegal aperture size %d kB\n",
|
|
pATIDRIServer->agpSize*1024 );
|
|
return FALSE;
|
|
}
|
|
|
|
/* 1 = DATA comes in clock in which TRDY sampled (default) */
|
|
/* 0 = DATA comes in clock after TRDY sampled */
|
|
cntl |= AGP_TRDY_MODE;
|
|
|
|
/* 1 = generate all reads as high priority */
|
|
/* 0 = generate all reads as their default priority (default) */
|
|
/* Setting this only works for me at AGP 1x mode (LLD) */
|
|
if (pATIDRIServer->agpMode == 1) {
|
|
cntl |= HIGH_PRIORITY_READ_EN;
|
|
} else {
|
|
cntl &= ~HIGH_PRIORITY_READ_EN;
|
|
}
|
|
|
|
outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
|
|
outm( AGP_CNTL, cntl );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool ATIDRIPciInit( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
|
|
pATIDRIServer->ringSize = 16; /* 16 kB ring */
|
|
|
|
if ( !ATIDRISetBufSize( pScreen, (unsigned)(-1) ) )
|
|
return FALSE;
|
|
|
|
/* Set size of the DMA descriptor ring */
|
|
pATIDRIServer->ringStart = 0;
|
|
pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */
|
|
|
|
/* Set size of the vertex buffer */
|
|
pATIDRIServer->bufferStart = 0;
|
|
pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024;
|
|
|
|
/* Map DMA descriptor ring */
|
|
if ( drmAddMap( pATI->drmFD, 0, pATIDRIServer->ringMapSize,
|
|
DRM_CONSISTENT, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[pci] Could not add ring mapping\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO, "[pci] ring handle = 0x%08x\n",
|
|
pATIDRIServer->ringHandle );
|
|
|
|
if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle,
|
|
pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[pci] Could not map ring\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[pci] Ring mapped at 0x%08lx\n",
|
|
(unsigned long)pATIDRIServer->ringMap );
|
|
|
|
/* Disable AGP for ForcePCIMode */
|
|
if ( pATI->BusType != ATI_BUS_PCI ) {
|
|
outm( AGP_BASE, 0 );
|
|
outm( AGP_CNTL, 0 );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Add a map for the MMIO registers that will be accessed by any
|
|
* DRI-based clients.
|
|
*/
|
|
static Bool ATIDRIMapInit( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
pATIDRIServer->regsSize = getpagesize();
|
|
if ( drmAddMap( pATI->drmFD, pATI->Block1Base,
|
|
pATIDRIServer->regsSize,
|
|
DRM_REGISTERS, DRM_READ_ONLY,
|
|
&pATIDRIServer->regsHandle ) < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[drm] failed to map registers\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[drm] register handle = 0x%08x\n",
|
|
pATIDRIServer->regsHandle );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Initialize the kernel data structures. */
|
|
static Bool ATIDRIKernelInit( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
drmMach64Init info;
|
|
|
|
memset( &info, 0, sizeof(drmMach64Init) );
|
|
|
|
info.func = DRM_MACH64_INIT_DMA;
|
|
info.sarea_priv_offset = sizeof(XF86DRISAREARec);
|
|
info.is_pci = pATIDRIServer->IsPCI;
|
|
info.dma_mode = pATI->OptionDMAMode;
|
|
|
|
info.fb_bpp = pATI->bitsPerPixel;
|
|
info.front_offset = pATIDRIServer->frontOffset;
|
|
info.front_pitch = pATIDRIServer->frontPitch;
|
|
info.back_offset = pATIDRIServer->backOffset;
|
|
info.back_pitch = pATIDRIServer->backPitch;
|
|
|
|
info.depth_bpp = 16;
|
|
info.depth_offset = pATIDRIServer->depthOffset;
|
|
info.depth_pitch = pATIDRIServer->depthPitch;
|
|
|
|
info.fb_offset = pATI->LinearBase;
|
|
info.mmio_offset = pATIDRIServer->regsHandle;
|
|
info.ring_offset = pATIDRIServer->ringHandle;
|
|
info.buffers_offset = pATIDRIServer->bufferHandle;
|
|
info.agp_textures_offset = pATIDRIServer->agpTexHandle;
|
|
|
|
if ( drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
|
|
&info, sizeof(drmMach64Init) ) < 0 ) {
|
|
return FALSE;
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/* Add a map for the DMA buffers that will be accessed by any
|
|
* DRI-based clients.
|
|
*/
|
|
static Bool ATIDRIAddBuffers( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
/* Initialize vertex buffers */
|
|
if ( pATIDRIServer->IsPCI ) {
|
|
pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
|
|
pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE,
|
|
MACH64_BUFFER_SIZE,
|
|
DRM_PCI_BUFFER_RO,
|
|
0 );
|
|
} else {
|
|
pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
|
|
pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE,
|
|
MACH64_BUFFER_SIZE,
|
|
DRM_AGP_BUFFER,
|
|
pATIDRIServer->bufferStart );
|
|
}
|
|
if ( pATIDRIServer->numBuffers <= 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[drm] Could not create DMA buffers list\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[drm] Added %d %d byte DMA buffers\n",
|
|
pATIDRIServer->numBuffers, MACH64_BUFFER_SIZE );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool ATIDRIMapBuffers( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
pATIDRIServer->drmBuffers = drmMapBufs( pATI->drmFD );
|
|
if ( !pATIDRIServer->drmBuffers ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[drm] Failed to map DMA buffers list\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[drm] Mapped %d DMA buffers at 0x%08lx\n",
|
|
pATIDRIServer->drmBuffers->count,
|
|
(unsigned long)pATIDRIServer->drmBuffers->list->address );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool ATIDRIIrqInit( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
|
|
if ( pATI->irq <= 0 ) {
|
|
pATI->irq = drmGetInterruptFromBusID(pATI->drmFD,
|
|
PCI_CFG_BUS(pATI->PCIInfo),
|
|
PCI_CFG_DEV(pATI->PCIInfo),
|
|
PCI_CFG_FUNC(pATI->PCIInfo));
|
|
if ( pATI->irq <= 0 ) {
|
|
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
|
|
"[drm] Couldn't find IRQ for bus id %d:%d:%d\n",
|
|
PCI_CFG_BUS(pATI->PCIInfo),
|
|
PCI_CFG_DEV(pATI->PCIInfo),
|
|
PCI_CFG_FUNC(pATI->PCIInfo));
|
|
pATI->irq = 0;
|
|
} else if ((drmCtlInstHandler(pATI->drmFD, pATI->irq)) != 0) {
|
|
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
|
|
"[drm] Failed to initialize interrupt handler with IRQ %d\n",
|
|
pATI->irq);
|
|
pATI->irq = 0;
|
|
}
|
|
|
|
if (pATI->irq)
|
|
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
|
|
"[drm] Installed interrupt handler, using IRQ %d\n",
|
|
pATI->irq);
|
|
else {
|
|
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
|
|
"[drm] Falling back to irq-free operation\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/* Initialize the screen-specific data structures for the DRI and the
|
|
* Rage Pro. This is the main entry point to the device-specific
|
|
* initialization code. It calls device-independent DRI functions to
|
|
* create the DRI data structures and initialize the DRI state.
|
|
*/
|
|
Bool ATIDRIScreenInit( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
DRIInfoPtr pDRIInfo;
|
|
ATIDRIPtr pATIDRI;
|
|
ATIDRIServerInfoPtr pATIDRIServer;
|
|
drmVersionPtr version;
|
|
int major, minor, patch;
|
|
|
|
/* Check that the DRI, and DRM modules have been loaded by testing
|
|
* for known symbols in each module.
|
|
*/
|
|
if ( !xf86LoaderCheckSymbol("drmAvailable") ) return FALSE;
|
|
if ( !xf86LoaderCheckSymbol("DRIQueryVersion") ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[dri] ATIDRIScreenInit failed (libdri.a too old)\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Check the DRI version */
|
|
DRIQueryVersion( &major, &minor, &patch );
|
|
if ( major != DRIINFO_MAJOR_VERSION || minor < 0 ) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
|
|
"[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n"
|
|
"[dri] Disabling the DRI.\n",
|
|
major, minor, patch,
|
|
DRIINFO_MAJOR_VERSION, 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
switch ( pATI->bitsPerPixel ) {
|
|
case 8:
|
|
/* These modes are not supported (yet). */
|
|
case 15:
|
|
case 24:
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[dri] Direct rendering only supported in 16 and 32 bpp modes\n");
|
|
return FALSE;
|
|
|
|
/* Only 16 and 32 color depths are supported currently. */
|
|
case 16:
|
|
if ( pATI->depth != 16) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[dri] Direct rendering not supported for depth %d at fbbpp 16.\n", pATI->depth );
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case 32:
|
|
break;
|
|
}
|
|
|
|
/* Create the DRI data structure, and fill it in before calling the
|
|
* DRIScreenInit().
|
|
*/
|
|
pDRIInfo = DRICreateInfoRec();
|
|
if ( !pDRIInfo ) return FALSE;
|
|
|
|
pATI->pDRIInfo = pDRIInfo;
|
|
pDRIInfo->drmDriverName = ATIKernelDriverName;
|
|
pDRIInfo->clientDriverName = ATIClientDriverName;
|
|
if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
|
|
pDRIInfo->busIdString = DRICreatePCIBusID(pATI->PCIInfo);
|
|
} else {
|
|
if (asprintf(&pDRIInfo->busIdString,
|
|
"PCI:%d:%d:%d",
|
|
PCI_DEV_BUS(pATI->PCIInfo),
|
|
PCI_DEV_DEV(pATI->PCIInfo),
|
|
PCI_DEV_FUNC(pATI->PCIInfo)) == -1) {
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "malloc failed\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
pDRIInfo->ddxDriverMajorVersion = MACH64_VERSION_MAJOR;
|
|
pDRIInfo->ddxDriverMinorVersion = MACH64_VERSION_MINOR;
|
|
pDRIInfo->ddxDriverPatchVersion = MACH64_VERSION_PATCH;
|
|
pDRIInfo->frameBufferPhysicalAddress = (void *)pATI->LinearBase;
|
|
pDRIInfo->frameBufferSize = pATI->LinearSize;
|
|
pDRIInfo->frameBufferStride = (pScreenInfo->displayWidth *
|
|
pATI->FBBytesPerPixel);
|
|
pDRIInfo->ddxDrawableTableEntry = ATI_MAX_DRAWABLES;
|
|
|
|
if ( SAREA_MAX_DRAWABLES < ATI_MAX_DRAWABLES ) {
|
|
pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
|
|
} else {
|
|
pDRIInfo->maxDrawableTableEntry = ATI_MAX_DRAWABLES;
|
|
}
|
|
|
|
/* For now the mapping works by using a fixed size defined
|
|
* in the SAREA header
|
|
*/
|
|
if ( sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec) > SAREA_MAX ) {
|
|
ErrorF( "[dri] Data does not fit in SAREA\n" );
|
|
return FALSE;
|
|
}
|
|
xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %u+%u: %u\n",
|
|
(unsigned)sizeof(XF86DRISAREARec),
|
|
(unsigned)sizeof(ATISAREAPrivRec),
|
|
(unsigned)(sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec)) );
|
|
pDRIInfo->SAREASize = SAREA_MAX;
|
|
|
|
pATIDRI = (ATIDRIPtr) XNFcallocarray( sizeof(ATIDRIRec), 1 );
|
|
if ( !pATIDRI ) {
|
|
DRIDestroyInfoRec( pATI->pDRIInfo );
|
|
pATI->pDRIInfo = NULL;
|
|
xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
|
|
"[dri] Failed to allocate memory for private record\n" );
|
|
return FALSE;
|
|
}
|
|
pATIDRIServer = (ATIDRIServerInfoPtr)
|
|
XNFcallocarray( sizeof(ATIDRIServerInfoRec), 1 );
|
|
if ( !pATIDRIServer ) {
|
|
free( pATIDRI );
|
|
DRIDestroyInfoRec( pATI->pDRIInfo );
|
|
pATI->pDRIInfo = NULL;
|
|
xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
|
|
"[dri] Failed to allocate memory for private record\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
pATI->pDRIServerInfo = pATIDRIServer;
|
|
|
|
pDRIInfo->devPrivate = pATIDRI;
|
|
pDRIInfo->devPrivateSize = sizeof(ATIDRIRec);
|
|
pDRIInfo->contextSize = sizeof(ATIDRIContextRec);
|
|
|
|
pDRIInfo->CreateContext = ATICreateContext;
|
|
pDRIInfo->DestroyContext = ATIDestroyContext;
|
|
pDRIInfo->SwapContext = ATIDRISwapContext;
|
|
pDRIInfo->InitBuffers = ATIDRIInitBuffers;
|
|
pDRIInfo->MoveBuffers = ATIDRIMoveBuffers;
|
|
#ifdef USE_EXA
|
|
if (pATI->useEXA) {
|
|
pDRIInfo->TransitionTo2d = ATIDRITransitionTo2d_EXA;
|
|
pDRIInfo->TransitionTo3d = ATIDRITransitionTo3d_EXA;
|
|
}
|
|
#endif /* USE_EXA */
|
|
pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
|
|
|
|
pDRIInfo->createDummyCtx = TRUE;
|
|
pDRIInfo->createDummyCtxPriv = FALSE;
|
|
|
|
pATI->have3DWindows = FALSE;
|
|
|
|
if ( !DRIScreenInit( pScreen, pDRIInfo, &pATI->drmFD ) ) {
|
|
free( pATIDRIServer );
|
|
pATI->pDRIServerInfo = NULL;
|
|
free( pDRIInfo->devPrivate );
|
|
pDRIInfo->devPrivate = NULL;
|
|
DRIDestroyInfoRec( pDRIInfo );
|
|
pDRIInfo = NULL;
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[dri] DRIScreenInit Failed\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Check the DRM lib version.
|
|
drmGetLibVersion was not supported in version 1.0, so check for
|
|
symbol first to avoid possible crash or hang.
|
|
*/
|
|
if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
|
|
version = drmGetLibVersion(pATI->drmFD);
|
|
} else {
|
|
/* drmlib version 1.0.0 didn't have the drmGetLibVersion
|
|
entry point. Fake it by allocating a version record
|
|
via drmGetVersion and changing it to version 1.0.0
|
|
*/
|
|
version = drmGetVersion(pATI->drmFD);
|
|
version->version_major = 1;
|
|
version->version_minor = 0;
|
|
version->version_patchlevel = 0;
|
|
}
|
|
|
|
if (version) {
|
|
if (version->version_major != 1 ||
|
|
version->version_minor < 1) {
|
|
/* incompatible drm library version */
|
|
xf86DrvMsg(pScreen->myNum, X_ERROR,
|
|
"[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
|
|
"[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
|
|
"[dri] Disabling DRI.\n",
|
|
version->version_major,
|
|
version->version_minor,
|
|
version->version_patchlevel);
|
|
drmFreeVersion(version);
|
|
ATIDRICloseScreen(pScreen);
|
|
return FALSE;
|
|
}
|
|
drmFreeVersion(version);
|
|
}
|
|
|
|
/* Check the mach64 DRM version */
|
|
version = drmGetVersion( pATI->drmFD );
|
|
if ( version ) {
|
|
if ( version->version_major != 2 ||
|
|
version->version_minor < 0 ) {
|
|
/* Incompatible DRM version */
|
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
|
"[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
|
|
"[dri] mach64.o kernel module version is %d.%d.%d, but version 2.x is needed (with 2.x >= 2.0).\n"
|
|
"[dri] Disabling DRI.\n",
|
|
version->version_major,
|
|
version->version_minor,
|
|
version->version_patchlevel );
|
|
drmFreeVersion( version );
|
|
ATIDRICloseScreen( pScreen );
|
|
return FALSE;
|
|
}
|
|
drmFreeVersion( version );
|
|
}
|
|
|
|
switch ( pATI->OptionDMAMode ) {
|
|
case MACH64_MODE_DMA_ASYNC:
|
|
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request asynchronous DMA mode\n");
|
|
break;
|
|
case MACH64_MODE_DMA_SYNC:
|
|
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request synchronous DMA mode\n");
|
|
break;
|
|
case MACH64_MODE_MMIO:
|
|
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request pseudo-DMA (MMIO) mode\n");
|
|
break;
|
|
default:
|
|
xf86DrvMsg(pScreen->myNum, X_WARNING, "[drm] Unknown DMA mode\n");
|
|
}
|
|
|
|
pATIDRIServer->IsPCI = (pATI->BusType == ATI_BUS_PCI || pATI->OptionIsPCI) ? TRUE : FALSE;
|
|
|
|
if ( pATI->BusType != ATI_BUS_PCI && pATI->OptionIsPCI ) {
|
|
xf86DrvMsg(pScreen->myNum, X_CONFIG, "[dri] Forcing PCI mode\n");
|
|
}
|
|
|
|
/* Initialize AGP */
|
|
if ( !pATIDRIServer->IsPCI && !ATIDRIAgpInit( pScreen ) ) {
|
|
pATIDRIServer->IsPCI = TRUE;
|
|
xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP failed to initialize -- falling back to PCI mode.\n" );
|
|
xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] Make sure you have the agpgart kernel module loaded.\n" );
|
|
}
|
|
|
|
/* Initialize PCI */
|
|
if ( pATIDRIServer->IsPCI && !ATIDRIPciInit( pScreen ) ) {
|
|
ATIDRICloseScreen( pScreen );
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !ATIDRIMapInit( pScreen ) ) {
|
|
ATIDRICloseScreen( pScreen );
|
|
return FALSE;
|
|
}
|
|
|
|
xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
|
|
"[dri] Visual configs initialized\n" );
|
|
|
|
xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
|
|
"[dri] Block 0 base at 0x%08lx\n", pATI->Block0Base );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Finish initializing the device-dependent DRI state, and call
|
|
* DRIFinishScreenInit() to complete the device-independent DRI
|
|
* initialization.
|
|
*/
|
|
Bool ATIDRIFinishScreenInit( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATISAREAPrivPtr pSAREAPriv;
|
|
ATIDRIPtr pATIDRI;
|
|
ATIDRIServerInfoPtr pATIDRIServer;
|
|
|
|
pATI->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
|
|
|
|
/* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
|
|
* because *DRIKernelInit requires that the hardware lock is held by
|
|
* the X server, and the first time the hardware lock is grabbed is
|
|
* in DRIFinishScreenInit.
|
|
*/
|
|
if ( !DRIFinishScreenInit( pScreen ) ) {
|
|
ATIDRICloseScreen( pScreen );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Initialize the DMA buffer list */
|
|
/* Need to do this before ATIDRIKernelInit so we can init the freelist */
|
|
if ( !ATIDRIAddBuffers( pScreen ) ) {
|
|
ATIDRICloseScreen( pScreen );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Initialize the kernel data structures */
|
|
if ( !ATIDRIKernelInit( pScreen ) ) {
|
|
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
|
|
"[drm] Failed to initialize the mach64.o kernel module\n");
|
|
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
|
|
"[drm] Check the system log for more information.\n");
|
|
ATIDRICloseScreen( pScreen );
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !ATIDRIMapBuffers( pScreen ) ) {
|
|
ATIDRICloseScreen( pScreen );
|
|
return FALSE;
|
|
}
|
|
|
|
/* Initialize IRQ */
|
|
ATIDRIIrqInit( pScreen );
|
|
|
|
pSAREAPriv = (ATISAREAPrivPtr) DRIGetSAREAPrivate( pScreen );
|
|
memset( pSAREAPriv, 0, sizeof(*pSAREAPriv) );
|
|
|
|
pATIDRI = (ATIDRIPtr)pATI->pDRIInfo->devPrivate;
|
|
pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
pATIDRI->width = pScreenInfo->virtualX;
|
|
pATIDRI->height = pScreenInfo->virtualY;
|
|
pATIDRI->mem = pScreenInfo->videoRam * 1024;
|
|
pATIDRI->cpp = pScreenInfo->bitsPerPixel / 8;
|
|
|
|
pATIDRI->IsPCI = pATIDRIServer->IsPCI;
|
|
pATIDRI->AGPMode = pATIDRIServer->agpMode;
|
|
|
|
pATIDRI->frontOffset = pATIDRIServer->frontOffset;
|
|
pATIDRI->frontPitch = pATIDRIServer->frontPitch;
|
|
|
|
pATIDRI->backOffset = pATIDRIServer->backOffset;
|
|
pATIDRI->backPitch = pATIDRIServer->backPitch;
|
|
|
|
pATIDRI->depthOffset = pATIDRIServer->depthOffset;
|
|
pATIDRI->depthPitch = pATIDRIServer->depthPitch;
|
|
|
|
pATIDRI->textureOffset = pATIDRIServer->textureOffset;
|
|
pATIDRI->textureSize = pATIDRIServer->textureSize;
|
|
pATIDRI->logTextureGranularity = pATIDRIServer->logTextureGranularity;
|
|
|
|
pATIDRI->regs = pATIDRIServer->regsHandle;
|
|
pATIDRI->regsSize = pATIDRIServer->regsSize;
|
|
|
|
pATIDRI->agp = pATIDRIServer->agpTexHandle;
|
|
pATIDRI->agpSize = pATIDRIServer->agpTexMapSize;
|
|
pATIDRI->logAgpTextureGranularity = pATIDRIServer->log2AGPTexGran;
|
|
pATIDRI->agpTextureOffset = pATIDRIServer->agpTexStart;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* This function will attempt to get the Mach64 hardware back into shape
|
|
* after a resume from disc. Its an extract from ATIDRIAgpInit and ATIDRIFinishScreenInit
|
|
* This also calls a new ioctl in the mach64 DRM that in its turn is
|
|
* an extraction of the hardware-affecting bits from mach64_do_init_drm()
|
|
* (see atidrm.c)
|
|
* I am assuming here that pATI->pDRIServerInfo doesn't change
|
|
* elsewhere in incompatible ways.
|
|
* How will this code react to resuming after a failed resumeor pci based dri ?
|
|
*/
|
|
void ATIDRIResume( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
|
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
|
"[RESUME] Attempting to re-init Mach64 hardware.\n");
|
|
|
|
if (!pATIDRIServer->IsPCI) {
|
|
if (!ATIDRISetAgpMode(pScreen))
|
|
return;
|
|
|
|
outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
|
|
}
|
|
}
|
|
|
|
/* The screen is being closed, so clean up any state and free any
|
|
* resources used by the DRI.
|
|
*/
|
|
void ATIDRICloseScreen( ScreenPtr pScreen )
|
|
{
|
|
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
|
|
ATIPtr pATI = ATIPTR(pScreenInfo);
|
|
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
|
|
drmMach64Init info;
|
|
|
|
/* Stop interrupt generation and handling if used */
|
|
if ( pATI->irq > 0 ) {
|
|
if ( drmCtlUninstHandler(pATI->drmFD) != 0 ) {
|
|
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
|
|
"[drm] Error uninstalling interrupt handler for IRQ %d\n", pATI->irq);
|
|
} else {
|
|
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
|
|
"[drm] Uninstalled interrupt handler for IRQ %d\n", pATI->irq);
|
|
}
|
|
pATI->irq = 0;
|
|
}
|
|
|
|
/* De-allocate DMA buffers */
|
|
if ( pATIDRIServer->drmBuffers ) {
|
|
drmUnmapBufs( pATIDRIServer->drmBuffers );
|
|
pATIDRIServer->drmBuffers = NULL;
|
|
}
|
|
|
|
/* De-allocate all kernel resources */
|
|
memset(&info, 0, sizeof(drmMach64Init));
|
|
info.func = DRM_MACH64_CLEANUP_DMA;
|
|
drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
|
|
&info, sizeof(drmMach64Init) );
|
|
|
|
/* De-allocate all AGP resources */
|
|
if ( pATIDRIServer->agpTexMap ) {
|
|
drmUnmap( pATIDRIServer->agpTexMap, pATIDRIServer->agpTexMapSize );
|
|
pATIDRIServer->agpTexMap = NULL;
|
|
}
|
|
if ( pATIDRIServer->bufferMap ) {
|
|
drmUnmap( pATIDRIServer->bufferMap, pATIDRIServer->bufferMapSize );
|
|
pATIDRIServer->bufferMap = NULL;
|
|
}
|
|
if ( pATIDRIServer->ringMap ) {
|
|
drmUnmap( pATIDRIServer->ringMap, pATIDRIServer->ringMapSize );
|
|
pATIDRIServer->ringMap = NULL;
|
|
}
|
|
if ( pATIDRIServer->agpHandle ) {
|
|
drmAgpUnbind( pATI->drmFD, pATIDRIServer->agpHandle );
|
|
drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
|
|
pATIDRIServer->agpHandle = 0;
|
|
drmAgpRelease( pATI->drmFD );
|
|
}
|
|
|
|
/* De-allocate all PCI resources */
|
|
if ( pATIDRIServer->IsPCI && pATIDRIServer->ringHandle ) {
|
|
drmRmMap( pATI->drmFD, pATIDRIServer->ringHandle );
|
|
pATIDRIServer->ringHandle = 0;
|
|
}
|
|
|
|
/* De-allocate all DRI resources */
|
|
DRICloseScreen( pScreen );
|
|
|
|
/* De-allocate all DRI data structures */
|
|
if ( pATI->pDRIInfo ) {
|
|
if ( pATI->pDRIInfo->devPrivate ) {
|
|
free( pATI->pDRIInfo->devPrivate );
|
|
pATI->pDRIInfo->devPrivate = NULL;
|
|
}
|
|
DRIDestroyInfoRec( pATI->pDRIInfo );
|
|
pATI->pDRIInfo = NULL;
|
|
}
|
|
if ( pATI->pDRIServerInfo ) {
|
|
free( pATI->pDRIServerInfo );
|
|
pATI->pDRIServerInfo = NULL;
|
|
}
|
|
}
|