1270 lines
37 KiB
C
1270 lines
37 KiB
C
|
/*
|
||
|
* Copyright 2000 VA Linux Systems Inc., Fremont, California.
|
||
|
* 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
|
||
|
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
|
||
|
*
|
||
|
* Authors:
|
||
|
* Keith Whitwell <keith@tungstengraphics.com>
|
||
|
* Gareth Hughes <gareth@valinux.com>
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include "config.h"
|
||
|
#endif
|
||
|
|
||
|
#include "xf86.h"
|
||
|
#include "xf86_OSproc.h"
|
||
|
|
||
|
#include "xf86Pci.h"
|
||
|
|
||
|
#include "miline.h"
|
||
|
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include <inttypes.h>
|
||
|
#include "mga_reg.h"
|
||
|
#include "mga.h"
|
||
|
#include "mga_macros.h"
|
||
|
#include "mga_dri.h"
|
||
|
#include "mga_sarea.h"
|
||
|
#include "mga_drm.h"
|
||
|
|
||
|
#define _XF86DRI_SERVER_
|
||
|
#include "sarea.h"
|
||
|
|
||
|
#include "mga_reg.h"
|
||
|
#include "mga.h"
|
||
|
#include "mga_macros.h"
|
||
|
#include "mga_dri.h"
|
||
|
|
||
|
#define DRM_MGA_IDLE_RETRY 2048
|
||
|
|
||
|
static char MGAKernelDriverName[] = "mga";
|
||
|
static char MGAClientDriverName[] = "mga";
|
||
|
|
||
|
static Bool MGACreateContext( ScreenPtr pScreen, VisualPtr visual,
|
||
|
drm_context_t hwContext, void *pVisualConfigPriv,
|
||
|
DRIContextType contextStore )
|
||
|
{
|
||
|
/* Nothing yet */
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void MGADestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
|
||
|
DRIContextType contextStore )
|
||
|
{
|
||
|
/* Nothing yet */
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Quiescence, locking
|
||
|
*/
|
||
|
#define MGA_TIMEOUT 2048
|
||
|
|
||
|
static void MGAWaitForIdleDMA( ScrnInfoPtr pScrn )
|
||
|
{
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
drm_lock_t lock;
|
||
|
int ret;
|
||
|
int i = 0;
|
||
|
|
||
|
memset( &lock, 0, sizeof(drm_lock_t) );
|
||
|
|
||
|
for (;;) {
|
||
|
do {
|
||
|
/* first ask for quiescent and flush */
|
||
|
lock.flags = DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH;
|
||
|
do {
|
||
|
ret = drmCommandWrite( pMga->drmFD, DRM_MGA_FLUSH,
|
||
|
&lock, sizeof( drm_lock_t ) );
|
||
|
} while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
|
||
|
|
||
|
/* if it's still busy just try quiescent */
|
||
|
if ( ret == -EBUSY ) {
|
||
|
lock.flags = DRM_LOCK_QUIESCENT;
|
||
|
do {
|
||
|
ret = drmCommandWrite( pMga->drmFD, DRM_MGA_FLUSH,
|
||
|
&lock, sizeof( drm_lock_t ) );
|
||
|
} while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
|
||
|
}
|
||
|
} while ( ( ret == -EBUSY ) && ( i++ < MGA_TIMEOUT ) );
|
||
|
|
||
|
if ( ret == 0 )
|
||
|
return;
|
||
|
|
||
|
xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
|
||
|
"[dri] Idle timed out, resetting engine...\n" );
|
||
|
|
||
|
drmCommandNone( pMga->drmFD, DRM_MGA_RESET );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void MGAGetQuiescence( ScrnInfoPtr pScrn )
|
||
|
{
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
#ifdef USE_XAA
|
||
|
MGAFBLayout *pLayout = &pMga->CurrentLayout;
|
||
|
#endif /* USE_XAA */
|
||
|
|
||
|
pMga->haveQuiescense = 1;
|
||
|
|
||
|
if ( pMga->directRenderingEnabled ) {
|
||
|
MGAWaitForIdleDMA( pScrn );
|
||
|
|
||
|
/* FIXME what about EXA? */
|
||
|
#ifdef USE_XAA
|
||
|
if (!pMga->Exa && pMga->AccelInfoRec) {
|
||
|
WAITFIFO( 11 );
|
||
|
OUTREG( MGAREG_MACCESS, pMga->MAccess );
|
||
|
OUTREG( MGAREG_PITCH, pLayout->displayWidth );
|
||
|
|
||
|
pMga->PlaneMask = ~0;
|
||
|
OUTREG( MGAREG_PLNWT, pMga->PlaneMask );
|
||
|
|
||
|
pMga->BgColor = 0;
|
||
|
pMga->FgColor = 0;
|
||
|
OUTREG( MGAREG_BCOL, pMga->BgColor );
|
||
|
OUTREG( MGAREG_FCOL, pMga->FgColor );
|
||
|
OUTREG( MGAREG_SRCORG, pMga->realSrcOrg );
|
||
|
|
||
|
pMga->SrcOrg = 0;
|
||
|
OUTREG( MGAREG_DSTORG, pMga->DstOrg );
|
||
|
OUTREG( MGAREG_OPMODE, MGAOPM_DMA_BLIT );
|
||
|
OUTREG( MGAREG_CXBNDRY, 0xFFFF0000 ); /* (maxX << 16) | minX */
|
||
|
OUTREG( MGAREG_YTOP, 0x00000000 ); /* minPixelPointer */
|
||
|
OUTREG( MGAREG_YBOT, 0x007FFFFF ); /* maxPixelPointer */
|
||
|
|
||
|
pMga->AccelFlags &= ~CLIPPER_ON;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MGAGetQuiescenceShared( ScrnInfoPtr pScrn )
|
||
|
{
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
MGAEntPtr pMGAEnt = pMga->entityPrivate;
|
||
|
MGAPtr pMGA2 = MGAPTR(pMGAEnt->pScrn_2);
|
||
|
|
||
|
pMga = MGAPTR(pMGAEnt->pScrn_1);
|
||
|
pMga->haveQuiescense = 1;
|
||
|
pMGA2->haveQuiescense = 1;
|
||
|
|
||
|
if ( pMGAEnt->directRenderingEnabled ) {
|
||
|
MGAWaitForIdleDMA( pMGAEnt->pScrn_1 );
|
||
|
|
||
|
/* FIXME what about EXA? */
|
||
|
#ifdef USE_XAA
|
||
|
if (!pMga->Exa && pMga->AccelInfoRec)
|
||
|
pMga->RestoreAccelState( pScrn );
|
||
|
#endif
|
||
|
xf86SetLastScrnFlag( pScrn->entityList[0], pScrn->scrnIndex );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void MGASwapContext( ScreenPtr pScreen )
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
|
||
|
/* Arrange for dma_quiescence and xaa sync to be called as
|
||
|
* appropriate.
|
||
|
*/
|
||
|
pMga->haveQuiescense = 0;
|
||
|
|
||
|
MGA_MARK_SYNC(pMga, pScrn);
|
||
|
}
|
||
|
|
||
|
static void MGASwapContextShared( ScreenPtr pScreen )
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
MGAEntPtr pMGAEnt = pMga->entityPrivate;
|
||
|
MGAPtr pMGA2 = MGAPTR(pMGAEnt->pScrn_2);
|
||
|
|
||
|
pMga = MGAPTR(pMGAEnt->pScrn_1);
|
||
|
|
||
|
pMga->haveQuiescense = pMGA2->haveQuiescense = 0;
|
||
|
|
||
|
MGA_MARK_SYNC(pMga, pScrn);
|
||
|
MGA_MARK_SYNC(pMGA2, pMGAEnt->pScrn_2);
|
||
|
}
|
||
|
|
||
|
/* FIXME: This comment is out of date, since we aren't overriding
|
||
|
* Block/Wakeuphandler anymore.
|
||
|
*
|
||
|
*
|
||
|
* This is really only called from validate/postvalidate as we
|
||
|
* override the dri lock/unlock. Want to remove validate/postvalidate
|
||
|
* processing, but need to remove all client-side use of drawable lock
|
||
|
* first (otherwise there is no one recover when a client dies holding
|
||
|
* the drawable lock).
|
||
|
*
|
||
|
* What does this mean?
|
||
|
*
|
||
|
* - The above code gets executed every time a
|
||
|
* window changes shape or the focus changes, which isn't really
|
||
|
* optimal.
|
||
|
* - The X server therefore believes it needs to do an XAA sync
|
||
|
* *and* a dma quiescense ioctl each time that happens.
|
||
|
*
|
||
|
* We don't wrap wakeuphandler any longer, so at least we can say that
|
||
|
* this doesn't happen *every time the mouse moves*...
|
||
|
*/
|
||
|
static void
|
||
|
MGADRISwapContext( 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 )
|
||
|
{
|
||
|
MGASwapContext( pScreen );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
MGADRISwapContextShared( 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 )
|
||
|
{
|
||
|
MGASwapContextShared( pScreen );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MGASelectBuffer( ScrnInfoPtr pScrn, int which )
|
||
|
{
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
MGADRIPtr pMGADRI = (MGADRIPtr)pMga->pDRIInfo->devPrivate;
|
||
|
|
||
|
switch ( which ) {
|
||
|
case MGA_BACK:
|
||
|
OUTREG( MGAREG_DSTORG, pMGADRI->backOffset );
|
||
|
OUTREG( MGAREG_SRCORG, pMGADRI->backOffset );
|
||
|
break;
|
||
|
case MGA_DEPTH:
|
||
|
OUTREG( MGAREG_DSTORG, pMGADRI->depthOffset );
|
||
|
OUTREG( MGAREG_SRCORG, pMGADRI->depthOffset );
|
||
|
break;
|
||
|
default:
|
||
|
case MGA_FRONT:
|
||
|
OUTREG( MGAREG_DSTORG, pMGADRI->frontOffset );
|
||
|
OUTREG( MGAREG_SRCORG, pMGADRI->frontOffset );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static unsigned int mylog2( unsigned int n )
|
||
|
{
|
||
|
unsigned int log2 = 1;
|
||
|
while ( n > 1 ) n >>= 1, log2++;
|
||
|
return log2;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initialize DMA and secondary texture memory
|
||
|
*
|
||
|
* \todo
|
||
|
* The sizes used for the primary DMA buffer and the bin size and count for
|
||
|
* the secondary DMA buffers should be configurable from the xorg.conf.
|
||
|
*
|
||
|
* \todo
|
||
|
* This routine should use \c mga_bios_values::host_interface to limit the
|
||
|
* AGP mode. It the card is PCI, \c MGARec::agpSize should be forced to 0.
|
||
|
*/
|
||
|
static Bool MGADRIBootstrapDMA(ScreenPtr pScreen)
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
|
||
|
int ret;
|
||
|
int requested_agp_mode;
|
||
|
int count;
|
||
|
|
||
|
|
||
|
if(pMga->agpSize < 12)pMga->agpSize = 12;
|
||
|
if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */
|
||
|
|
||
|
|
||
|
requested_agp_mode = 0;
|
||
|
switch ( pMga->agpMode ) {
|
||
|
case 4:
|
||
|
requested_agp_mode |= MGA_AGP_4X_MODE;
|
||
|
case 2:
|
||
|
requested_agp_mode |= MGA_AGP_2X_MODE;
|
||
|
case 1:
|
||
|
default:
|
||
|
requested_agp_mode |= MGA_AGP_1X_MODE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( (pMGADRIServer->drm_version_minor >= 2) && !pMga->useOldDmaInit ) {
|
||
|
drm_mga_dma_bootstrap_t dma_bs;
|
||
|
|
||
|
|
||
|
(void) memset( & dma_bs, 0, sizeof( dma_bs ) );
|
||
|
dma_bs.primary_size = 1024 * 1024;
|
||
|
dma_bs.secondary_bin_count = MGA_NUM_BUFFERS;
|
||
|
dma_bs.secondary_bin_size = MGA_BUFFER_SIZE;
|
||
|
dma_bs.agp_size = pMga->agpSize;
|
||
|
dma_bs.agp_mode = (pMga->forcePciDma) ? 0 : requested_agp_mode;
|
||
|
|
||
|
ret = drmCommandWriteRead( pMga->drmFD, DRM_MGA_DMA_BOOTSTRAP,
|
||
|
& dma_bs, sizeof( dma_bs ) );
|
||
|
if ( ret ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Could not boot-strap DMA (%d)\n", ret );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pMga->agpMode = dma_bs.agp_mode;
|
||
|
pMGADRIServer->agp.size = dma_bs.agp_size;
|
||
|
|
||
|
pMGADRIServer->agpTextures.handle = dma_bs.texture_handle;
|
||
|
pMGADRIServer->agpTextures.size = dma_bs.texture_size;
|
||
|
}
|
||
|
else {
|
||
|
unsigned long mode;
|
||
|
unsigned int vendor, device;
|
||
|
int i;
|
||
|
|
||
|
|
||
|
if ( pMga->forcePciDma ) {
|
||
|
const char * const msg = (pMGADRIServer->drm_version_minor < 2)
|
||
|
? "DRM version is too old (3.2 or later required)"
|
||
|
: "old DMA init path was requested";
|
||
|
|
||
|
xf86DrvMsg( pScreen->myNum, X_WARNING,
|
||
|
"[agp] Cannot force PCI DMA because %s\n", msg );
|
||
|
}
|
||
|
|
||
|
if ( drmAgpAcquire( pMga->drmFD ) < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not available\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
mode = drmAgpGetMode( pMga->drmFD ); /* Default mode */
|
||
|
vendor = drmAgpVendorId( pMga->drmFD );
|
||
|
device = drmAgpDeviceId( pMga->drmFD );
|
||
|
|
||
|
mode = (mode & ~MGA_AGP_MODE_MASK) | requested_agp_mode;
|
||
|
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
|
||
|
mode, vendor, device,
|
||
|
VENDOR_ID(pMga->PciInfo),
|
||
|
DEVICE_ID(pMga->PciInfo));
|
||
|
|
||
|
if ( drmAgpEnable( pMga->drmFD, mode ) < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
|
||
|
drmAgpRelease( pMga->drmFD );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( pMga->Chipset == PCI_CHIP_MGAG200 ) {
|
||
|
switch ( pMga->agpMode ) {
|
||
|
case 2:
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[drm] Enabling AGP 2x PLL encoding\n" );
|
||
|
OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE );
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
default:
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[drm] Disabling AGP 2x PLL encoding\n" );
|
||
|
OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE );
|
||
|
pMga->agpMode = 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pMGADRIServer->agp.size = pMga->agpSize * 1024 * 1024;
|
||
|
|
||
|
pMGADRIServer->warp.offset = 0;
|
||
|
pMGADRIServer->warp.size = MGA_WARP_UCODE_SIZE;
|
||
|
|
||
|
pMGADRIServer->primary.offset = (pMGADRIServer->warp.offset +
|
||
|
pMGADRIServer->warp.size);
|
||
|
pMGADRIServer->primary.size = 1024 * 1024;
|
||
|
|
||
|
pMGADRIServer->buffers.offset = (pMGADRIServer->primary.offset +
|
||
|
pMGADRIServer->primary.size);
|
||
|
pMGADRIServer->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE;
|
||
|
|
||
|
|
||
|
pMGADRIServer->agpTextures.offset = (pMGADRIServer->buffers.offset +
|
||
|
pMGADRIServer->buffers.size);
|
||
|
|
||
|
pMGADRIServer->agpTextures.size = (pMGADRIServer->agp.size -
|
||
|
pMGADRIServer->agpTextures.offset);
|
||
|
|
||
|
ret = drmAgpAlloc( pMga->drmFD, pMGADRIServer->agp.size,
|
||
|
0, NULL, &pMGADRIServer->agp.handle );
|
||
|
if ( ret < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
|
||
|
drmAgpRelease( pMga->drmFD );
|
||
|
return FALSE;
|
||
|
}
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[agp] %d kB allocated with handle 0x%08x\n",
|
||
|
pMGADRIServer->agp.size/1024,
|
||
|
(unsigned int) pMGADRIServer->agp.handle );
|
||
|
|
||
|
if ( drmAgpBind( pMga->drmFD, pMGADRIServer->agp.handle, 0 ) < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind memory\n" );
|
||
|
drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle );
|
||
|
drmAgpRelease( pMga->drmFD );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/* WARP microcode space
|
||
|
*/
|
||
|
if ( drmAddMap( pMga->drmFD,
|
||
|
pMGADRIServer->warp.offset,
|
||
|
pMGADRIServer->warp.size,
|
||
|
DRM_AGP, DRM_READ_ONLY,
|
||
|
&pMGADRIServer->warp.handle ) < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[agp] Could not add WARP microcode mapping\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[agp] WARP microcode handle = 0x%08x\n",
|
||
|
(unsigned int) pMGADRIServer->warp.handle );
|
||
|
|
||
|
/* Primary DMA space
|
||
|
*/
|
||
|
if ( drmAddMap( pMga->drmFD,
|
||
|
pMGADRIServer->primary.offset,
|
||
|
pMGADRIServer->primary.size,
|
||
|
DRM_AGP, DRM_READ_ONLY,
|
||
|
&pMGADRIServer->primary.handle ) < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[agp] Could not add primary DMA mapping\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[agp] Primary DMA handle = 0x%08x\n",
|
||
|
(unsigned int) pMGADRIServer->primary.handle );
|
||
|
|
||
|
/* DMA buffers
|
||
|
*/
|
||
|
if ( drmAddMap( pMga->drmFD,
|
||
|
pMGADRIServer->buffers.offset,
|
||
|
pMGADRIServer->buffers.size,
|
||
|
DRM_AGP, 0,
|
||
|
&pMGADRIServer->buffers.handle ) < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[agp] Could not add DMA buffers mapping\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[agp] DMA buffers handle = 0x%08x\n",
|
||
|
(unsigned int) pMGADRIServer->buffers.handle );
|
||
|
|
||
|
count = drmAddBufs( pMga->drmFD,
|
||
|
MGA_NUM_BUFFERS, MGA_BUFFER_SIZE,
|
||
|
DRM_AGP_BUFFER, pMGADRIServer->buffers.offset );
|
||
|
if ( count <= 0 ) {
|
||
|
xf86DrvMsg( pScrn->scrnIndex, X_INFO,
|
||
|
"[drm] failure adding %d %d byte DMA buffers\n",
|
||
|
MGA_NUM_BUFFERS, MGA_BUFFER_SIZE );
|
||
|
return FALSE;
|
||
|
}
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[drm] Added %d %d byte DMA buffers\n",
|
||
|
count, MGA_BUFFER_SIZE );
|
||
|
|
||
|
i = mylog2(pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS);
|
||
|
if(i < MGA_LOG_MIN_TEX_REGION_SIZE)
|
||
|
i = MGA_LOG_MIN_TEX_REGION_SIZE;
|
||
|
pMGADRIServer->agpTextures.size = (pMGADRIServer->agpTextures.size >> i) << i;
|
||
|
|
||
|
if ( drmAddMap( pMga->drmFD,
|
||
|
pMGADRIServer->agpTextures.offset,
|
||
|
pMGADRIServer->agpTextures.size,
|
||
|
DRM_AGP, 0,
|
||
|
&pMGADRIServer->agpTextures.handle ) < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[agp] Could not add agpTexture mapping\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[agp] agpTexture handle = 0x%08x\n",
|
||
|
(unsigned int) pMGADRIServer->agpTextures.handle );
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[agp] agpTexture size: %d kb\n", pMGADRIServer->agpTextures.size/1024 );
|
||
|
|
||
|
pMGADRIServer->registers.size = MGAIOMAPSIZE;
|
||
|
|
||
|
if ( drmAddMap( pMga->drmFD,
|
||
|
(drm_handle_t) MGA_IO_ADDRESS(pMga),
|
||
|
pMGADRIServer->registers.size,
|
||
|
DRM_REGISTERS, DRM_READ_ONLY,
|
||
|
&pMGADRIServer->registers.handle ) < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[drm] Could not add MMIO registers mapping\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[drm] Registers handle = 0x%08x\n",
|
||
|
(unsigned int) pMGADRIServer->registers.handle );
|
||
|
|
||
|
pMGADRIServer->status.size = SAREA_MAX;
|
||
|
|
||
|
if ( drmAddMap( pMga->drmFD, 0, pMGADRIServer->status.size,
|
||
|
DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL,
|
||
|
&pMGADRIServer->status.handle ) < 0 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[drm] Could not add status page mapping\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[drm] Status handle = 0x%08x\n",
|
||
|
(unsigned int) pMGADRIServer->status.handle );
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static Bool MGADRIKernelInit( ScreenPtr pScreen )
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
|
||
|
drm_mga_init_t init;
|
||
|
int ret;
|
||
|
|
||
|
|
||
|
if (!pMga->chip_attribs->dri_capable) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
memset( &init, 0, sizeof(drm_mga_init_t) );
|
||
|
|
||
|
init.func = MGA_INIT_DMA;
|
||
|
init.sarea_priv_offset = sizeof(XF86DRISAREARec);
|
||
|
init.chipset = pMga->chip_attribs->dri_chipset;
|
||
|
init.sgram = !pMga->HasSDRAM;
|
||
|
|
||
|
init.maccess = pMga->MAccess;
|
||
|
|
||
|
init.fb_cpp = pScrn->bitsPerPixel / 8;
|
||
|
init.front_offset = pMGADRIServer->frontOffset;
|
||
|
init.front_pitch = pMGADRIServer->frontPitch / init.fb_cpp;
|
||
|
init.back_offset = pMGADRIServer->backOffset;
|
||
|
init.back_pitch = pMGADRIServer->backPitch / init.fb_cpp;
|
||
|
|
||
|
init.depth_cpp = pScrn->bitsPerPixel / 8;
|
||
|
init.depth_offset = pMGADRIServer->depthOffset;
|
||
|
init.depth_pitch = pMGADRIServer->depthPitch / init.depth_cpp;
|
||
|
|
||
|
init.texture_offset[0] = pMGADRIServer->textureOffset;
|
||
|
init.texture_size[0] = pMGADRIServer->textureSize;
|
||
|
|
||
|
init.fb_offset = pMGADRIServer->fb.handle;
|
||
|
init.mmio_offset = pMGADRIServer->registers.handle;
|
||
|
init.status_offset = pMGADRIServer->status.handle;
|
||
|
|
||
|
init.warp_offset = pMGADRIServer->warp.handle;
|
||
|
init.primary_offset = pMGADRIServer->primary.handle;
|
||
|
init.buffers_offset = pMGADRIServer->buffers.handle;
|
||
|
|
||
|
init.texture_offset[1] = pMGADRIServer->agpTextures.handle;
|
||
|
init.texture_size[1] = pMGADRIServer->agpTextures.size;
|
||
|
|
||
|
ret = drmCommandWrite( pMga->drmFD, DRM_MGA_INIT, &init, sizeof(drm_mga_init_t));
|
||
|
if ( ret < 0 ) {
|
||
|
xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
|
||
|
"[drm] Failed to initialize DMA! (%d)\n", ret );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/* FIXME: This function uses the DRM to get the IRQ, but the pci_device
|
||
|
* FIXME: structure (PciInfo) already has that information.
|
||
|
*/
|
||
|
static void MGADRIIrqInit(MGAPtr pMga, ScreenPtr pScreen)
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
|
||
|
if (!pMga->irq) {
|
||
|
pMga->irq = drmGetInterruptFromBusID(pMga->drmFD,
|
||
|
#ifdef XSERVER_LIBPCIACCESS
|
||
|
((pMga->PciInfo->domain << 8) |
|
||
|
pMga->PciInfo->bus),
|
||
|
pMga->PciInfo->dev,
|
||
|
pMga->PciInfo->func
|
||
|
#else
|
||
|
((pciConfigPtr)pMga->PciInfo->thisCard)->busnum,
|
||
|
((pciConfigPtr)pMga->PciInfo->thisCard)->devnum,
|
||
|
((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum
|
||
|
#endif
|
||
|
);
|
||
|
|
||
|
if((drmCtlInstHandler(pMga->drmFD, pMga->irq)) != 0) {
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"[drm] failure adding irq handler, "
|
||
|
"there is a device already using that irq\n"
|
||
|
"[drm] falling back to irq-free operation\n");
|
||
|
pMga->irq = 0;
|
||
|
} else {
|
||
|
pMga->reg_ien = INREG( MGAREG_IEN );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pMga->irq)
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"[drm] dma control initialized, using IRQ %d\n",
|
||
|
pMga->irq);
|
||
|
}
|
||
|
|
||
|
static Bool MGADRIBuffersInit( ScreenPtr pScreen )
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
|
||
|
|
||
|
|
||
|
pMGADRIServer->drmBuffers = drmMapBufs( pMga->drmFD );
|
||
|
if ( !pMGADRIServer->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\n",
|
||
|
pMGADRIServer->drmBuffers->count );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
#ifdef USE_XAA
|
||
|
static void MGADRIInitBuffersXAA(WindowPtr pWin, RegionPtr prgn,
|
||
|
CARD32 index)
|
||
|
{
|
||
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
BoxPtr pbox = REGION_RECTS(prgn);
|
||
|
int nbox = REGION_NUM_RECTS(prgn);
|
||
|
XAAInfoRecPtr xaa = pMga->AccelInfoRec;
|
||
|
|
||
|
CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn);
|
||
|
|
||
|
xaa->SetupForSolidFill(pScrn, 0, GXcopy, -1);
|
||
|
|
||
|
while (nbox--) {
|
||
|
MGASelectBuffer(pScrn, MGA_BACK);
|
||
|
xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
|
||
|
pbox->x2-pbox->x1, pbox->y2-pbox->y1);
|
||
|
MGASelectBuffer(pScrn, MGA_DEPTH);
|
||
|
xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
|
||
|
pbox->x2-pbox->x1, pbox->y2-pbox->y1);
|
||
|
pbox++;
|
||
|
}
|
||
|
|
||
|
MGASelectBuffer(pScrn, MGA_FRONT);
|
||
|
|
||
|
pMga->AccelInfoRec->NeedToSync = TRUE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void MGADRIInitBuffersEXA(WindowPtr pWin, RegionPtr prgn,
|
||
|
CARD32 index)
|
||
|
{
|
||
|
/* FIXME */
|
||
|
}
|
||
|
|
||
|
#ifdef USE_XAA
|
||
|
/*
|
||
|
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 MGADRIMoveBuffersXAA(WindowPtr pParent, DDXPointRec ptOldOrg,
|
||
|
RegionPtr prgnSrc, CARD32 index)
|
||
|
{
|
||
|
ScreenPtr pScreen = pParent->drawable.pScreen;
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
int nbox;
|
||
|
BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
|
||
|
DDXPointPtr pptTmp, pptNew1, pptNew2;
|
||
|
int xdir, ydir;
|
||
|
int dx, dy;
|
||
|
DDXPointPtr pptSrc;
|
||
|
int screenwidth = pScrn->virtualX;
|
||
|
int screenheight = pScrn->virtualY;
|
||
|
XAAInfoRecPtr xaa = pMga->AccelInfoRec;
|
||
|
|
||
|
CHECK_DMA_QUIESCENT(pMga, pScrn);
|
||
|
|
||
|
pbox = REGION_RECTS(prgnSrc);
|
||
|
nbox = REGION_NUM_RECTS(prgnSrc);
|
||
|
pboxNew1 = 0;
|
||
|
pptNew1 = 0;
|
||
|
pboxNew2 = 0;
|
||
|
pptNew2 = 0;
|
||
|
pptSrc = &ptOldOrg;
|
||
|
|
||
|
dx = pParent->drawable.x - ptOldOrg.x;
|
||
|
dy = pParent->drawable.y - ptOldOrg.y;
|
||
|
|
||
|
/* If the copy will overlap in Y, reverse the order */
|
||
|
if (dy>0) {
|
||
|
ydir = -1;
|
||
|
|
||
|
if (nbox>1) {
|
||
|
/* Keep ordering in each band, reverse order of bands */
|
||
|
pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec)*nbox);
|
||
|
if (!pboxNew1) return;
|
||
|
pptNew1 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox);
|
||
|
if (!pptNew1) {
|
||
|
free(pboxNew1);
|
||
|
return;
|
||
|
}
|
||
|
pboxBase = pboxNext = pbox+nbox-1;
|
||
|
while (pboxBase >= pbox) {
|
||
|
while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
|
||
|
pboxNext--;
|
||
|
pboxTmp = pboxNext+1;
|
||
|
pptTmp = pptSrc + (pboxTmp - pbox);
|
||
|
while (pboxTmp <= pboxBase) {
|
||
|
*pboxNew1++ = *pboxTmp++;
|
||
|
*pptNew1++ = *pptTmp++;
|
||
|
}
|
||
|
pboxBase = pboxNext;
|
||
|
}
|
||
|
pboxNew1 -= nbox;
|
||
|
pbox = pboxNew1;
|
||
|
pptNew1 -= nbox;
|
||
|
pptSrc = pptNew1;
|
||
|
}
|
||
|
} else {
|
||
|
/* No changes required */
|
||
|
ydir = 1;
|
||
|
}
|
||
|
|
||
|
/* If the regions will overlap in X, reverse the order */
|
||
|
if (dx>0) {
|
||
|
xdir = -1;
|
||
|
|
||
|
if (nbox > 1) {
|
||
|
/*reverse orderof rects in each band */
|
||
|
pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec)*nbox);
|
||
|
pptNew2 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox);
|
||
|
if (!pboxNew2 || !pptNew2) {
|
||
|
free(pptNew2);
|
||
|
free(pboxNew2);
|
||
|
if (pboxNew1) {
|
||
|
free(pptNew1);
|
||
|
free(pboxNew1);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
pboxBase = pboxNext = pbox;
|
||
|
while (pboxBase < pbox+nbox) {
|
||
|
while ((pboxNext < pbox+nbox) &&
|
||
|
(pboxNext->y1 == pboxBase->y1))
|
||
|
pboxNext++;
|
||
|
pboxTmp = pboxNext;
|
||
|
pptTmp = pptSrc + (pboxTmp - pbox);
|
||
|
while (pboxTmp != pboxBase) {
|
||
|
*pboxNew2++ = *--pboxTmp;
|
||
|
*pptNew2++ = *--pptTmp;
|
||
|
}
|
||
|
pboxBase = pboxNext;
|
||
|
}
|
||
|
pboxNew2 -= nbox;
|
||
|
pbox = pboxNew2;
|
||
|
pptNew2 -= nbox;
|
||
|
pptSrc = pptNew2;
|
||
|
}
|
||
|
} else {
|
||
|
/* No changes are needed */
|
||
|
xdir = 1;
|
||
|
}
|
||
|
|
||
|
xaa->SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);
|
||
|
for ( ; nbox-- ; pbox++) {
|
||
|
int x1 = pbox->x1;
|
||
|
int y1 = pbox->y1;
|
||
|
int destx = x1 + dx;
|
||
|
int desty = y1 + dy;
|
||
|
int w = pbox->x2 - x1 + 1;
|
||
|
int h = pbox->y2 - y1 + 1;
|
||
|
|
||
|
if ( destx < 0 ) x1 -= destx, w += destx, destx = 0;
|
||
|
if ( desty < 0 ) y1 -= desty, h += desty, desty = 0;
|
||
|
if ( destx + w > screenwidth ) w = screenwidth - destx;
|
||
|
if ( desty + h > screenheight ) h = screenheight - desty;
|
||
|
if ( w <= 0 ) continue;
|
||
|
if ( h <= 0 ) continue;
|
||
|
|
||
|
MGASelectBuffer(pScrn, MGA_BACK);
|
||
|
xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
|
||
|
MGASelectBuffer(pScrn, MGA_DEPTH);
|
||
|
xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
|
||
|
}
|
||
|
MGASelectBuffer(pScrn, MGA_FRONT);
|
||
|
|
||
|
if (pboxNew2) {
|
||
|
free(pptNew2);
|
||
|
free(pboxNew2);
|
||
|
}
|
||
|
if (pboxNew1) {
|
||
|
free(pptNew1);
|
||
|
free(pboxNew1);
|
||
|
}
|
||
|
|
||
|
pMga->AccelInfoRec->NeedToSync = TRUE;
|
||
|
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void MGADRIMoveBuffersEXA(WindowPtr pParent, DDXPointRec ptOldOrg,
|
||
|
RegionPtr prgnSrc, CARD32 index)
|
||
|
{
|
||
|
/* FIXME */
|
||
|
}
|
||
|
|
||
|
Bool MGADRIScreenInit( ScreenPtr pScreen )
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
DRIInfoPtr pDRIInfo;
|
||
|
MGADRIPtr pMGADRI;
|
||
|
MGADRIServerPrivatePtr pMGADRIServer;
|
||
|
|
||
|
if (!pMga->chip_attribs->dri_capable) {
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] Direct rendering only supported with G200/G400/G450/G550.\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/* Check that the DRI, and DRM modules have been loaded by testing
|
||
|
* for canonical symbols in each module.
|
||
|
*/
|
||
|
if ( !xf86LoaderCheckSymbol( "drmAvailable" ) ) return FALSE;
|
||
|
if ( !xf86LoaderCheckSymbol( "DRIQueryVersion" ) ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[dri] MGADRIScreenInit failed (libdri.a too old)\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/* Check the DRI version */
|
||
|
{
|
||
|
int major, minor, patch;
|
||
|
DRIQueryVersion( &major, &minor, &patch );
|
||
|
if ( major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[dri] MGADRIScreenInit failed because of a version mismatch.\n"
|
||
|
"[dri] libdri version = %d.%d.%d but version %d.%d.x is needed.\n"
|
||
|
"[dri] Disabling the DRI.\n",
|
||
|
major, minor, patch,
|
||
|
DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION );
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
xf86DrvMsg( pScreen->myNum, X_INFO,
|
||
|
"[drm] bpp: %d depth: %d\n",
|
||
|
pScrn->bitsPerPixel, pScrn->depth );
|
||
|
|
||
|
if ( (pScrn->bitsPerPixel / 8) != 2 &&
|
||
|
(pScrn->bitsPerPixel / 8) != 4 ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[dri] Direct rendering only supported in 16 and 32 bpp modes\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pDRIInfo = DRICreateInfoRec();
|
||
|
if ( !pDRIInfo ) {
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[dri] DRICreateInfoRec() failed\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
pMga->pDRIInfo = pDRIInfo;
|
||
|
|
||
|
pDRIInfo->drmDriverName = MGAKernelDriverName;
|
||
|
pDRIInfo->clientDriverName = MGAClientDriverName;
|
||
|
if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
|
||
|
pDRIInfo->busIdString = DRICreatePCIBusID(pMga->PciInfo);
|
||
|
} else {
|
||
|
pDRIInfo->busIdString = malloc(64);
|
||
|
sprintf( pDRIInfo->busIdString, "PCI:%d:%d:%d",
|
||
|
#ifdef XSERVER_LIBPCIACCESS
|
||
|
((pMga->PciInfo->domain << 8) | pMga->PciInfo->bus),
|
||
|
pMga->PciInfo->dev, pMga->PciInfo->func
|
||
|
#else
|
||
|
((pciConfigPtr)pMga->PciInfo->thisCard)->busnum,
|
||
|
((pciConfigPtr)pMga->PciInfo->thisCard)->devnum,
|
||
|
((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum
|
||
|
#endif
|
||
|
);
|
||
|
}
|
||
|
pDRIInfo->ddxDriverMajorVersion = PACKAGE_VERSION_MAJOR;
|
||
|
pDRIInfo->ddxDriverMinorVersion = PACKAGE_VERSION_MINOR;
|
||
|
pDRIInfo->ddxDriverPatchVersion = PACKAGE_VERSION_PATCHLEVEL;
|
||
|
pDRIInfo->frameBufferPhysicalAddress = (void *) pMga->FbAddress;
|
||
|
pDRIInfo->frameBufferSize = pMga->FbMapSize;
|
||
|
pDRIInfo->frameBufferStride = pScrn->displayWidth*(pScrn->bitsPerPixel/8);
|
||
|
pDRIInfo->ddxDrawableTableEntry = MGA_MAX_DRAWABLES;
|
||
|
|
||
|
pDRIInfo->createDummyCtx = TRUE;
|
||
|
pDRIInfo->createDummyCtxPriv = FALSE;
|
||
|
|
||
|
if ( SAREA_MAX_DRAWABLES < MGA_MAX_DRAWABLES ) {
|
||
|
pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
|
||
|
} else {
|
||
|
pDRIInfo->maxDrawableTableEntry = MGA_MAX_DRAWABLES;
|
||
|
}
|
||
|
|
||
|
/* For now the mapping works by using a fixed size defined
|
||
|
* in the SAREA header.
|
||
|
*/
|
||
|
if ( sizeof(XF86DRISAREARec) + sizeof(MGASAREAPrivRec) > SAREA_MAX ) {
|
||
|
xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
|
||
|
"[drm] Data does not fit in SAREA\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
xf86DrvMsg( pScrn->scrnIndex, X_INFO,
|
||
|
"[drm] Sarea %d+%d: %d\n",
|
||
|
(int)sizeof(XF86DRISAREARec), (int)sizeof(MGASAREAPrivRec),
|
||
|
(int)sizeof(XF86DRISAREARec) + (int)sizeof(MGASAREAPrivRec) );
|
||
|
|
||
|
pDRIInfo->SAREASize = SAREA_MAX;
|
||
|
|
||
|
pMGADRI = (MGADRIPtr)calloc( sizeof(MGADRIRec), 1 );
|
||
|
if ( !pMGADRI ) {
|
||
|
DRIDestroyInfoRec( pMga->pDRIInfo );
|
||
|
pMga->pDRIInfo = 0;
|
||
|
xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
|
||
|
"[drm] Failed to allocate memory for private record\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pMGADRIServer = (MGADRIServerPrivatePtr)
|
||
|
calloc( sizeof(MGADRIServerPrivateRec), 1 );
|
||
|
if ( !pMGADRIServer ) {
|
||
|
free( pMGADRI );
|
||
|
DRIDestroyInfoRec( pMga->pDRIInfo );
|
||
|
pMga->pDRIInfo = 0;
|
||
|
xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
|
||
|
"[drm] Failed to allocate memory for private record\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
pMga->DRIServerInfo = pMGADRIServer;
|
||
|
|
||
|
pDRIInfo->devPrivate = pMGADRI;
|
||
|
pDRIInfo->devPrivateSize = sizeof(MGADRIRec);
|
||
|
pDRIInfo->contextSize = sizeof(MGADRIContextRec);
|
||
|
|
||
|
pDRIInfo->CreateContext = MGACreateContext;
|
||
|
pDRIInfo->DestroyContext = MGADestroyContext;
|
||
|
if ( xf86IsEntityShared( pScrn->entityList[0] )
|
||
|
&& pMga->DualHeadEnabled) {
|
||
|
pDRIInfo->SwapContext = MGADRISwapContextShared;
|
||
|
} else {
|
||
|
pDRIInfo->SwapContext = MGADRISwapContext;
|
||
|
}
|
||
|
|
||
|
pDRIInfo->InitBuffers = MGADRIInitBuffersEXA;
|
||
|
pDRIInfo->MoveBuffers = MGADRIMoveBuffersEXA;
|
||
|
#ifdef USE_EXA
|
||
|
if (pMga->Exa) {
|
||
|
pDRIInfo->InitBuffers = MGADRIInitBuffersEXA;
|
||
|
pDRIInfo->MoveBuffers = MGADRIMoveBuffersEXA;
|
||
|
} else {
|
||
|
#endif
|
||
|
#ifdef USE_XAA
|
||
|
pDRIInfo->InitBuffers = MGADRIInitBuffersXAA;
|
||
|
pDRIInfo->MoveBuffers = MGADRIMoveBuffersXAA;
|
||
|
#endif
|
||
|
#ifdef USE_EXA
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
|
||
|
|
||
|
if ( !DRIScreenInit( pScreen, pDRIInfo, &pMga->drmFD ) ) {
|
||
|
free( pMGADRIServer );
|
||
|
pMga->DRIServerInfo = 0;
|
||
|
free( pDRIInfo->devPrivate );
|
||
|
pDRIInfo->devPrivate = 0;
|
||
|
DRIDestroyInfoRec( pMga->pDRIInfo );
|
||
|
pMga->pDRIInfo = 0;
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[drm] DRIScreenInit failed. Disabling DRI.\n" );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/* Check the DRM versioning */
|
||
|
{
|
||
|
drmVersionPtr version;
|
||
|
|
||
|
/* 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(pMga->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(pMga->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] MGADRIScreenInit 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);
|
||
|
MGADRICloseScreen( pScreen ); /* FIXME: ??? */
|
||
|
return FALSE;
|
||
|
}
|
||
|
drmFreeVersion(version);
|
||
|
}
|
||
|
|
||
|
/* Check the MGA DRM version */
|
||
|
version = drmGetVersion(pMga->drmFD);
|
||
|
if ( version ) {
|
||
|
if ( version->version_major != 3 ||
|
||
|
version->version_minor < 0 ) {
|
||
|
/* incompatible drm version */
|
||
|
xf86DrvMsg( pScreen->myNum, X_ERROR,
|
||
|
"[dri] MGADRIScreenInit failed because of a version mismatch.\n"
|
||
|
"[dri] mga.o kernel module version is %d.%d.%d but version 3.0.x is needed.\n"
|
||
|
"[dri] Disabling DRI.\n",
|
||
|
version->version_major,
|
||
|
version->version_minor,
|
||
|
version->version_patchlevel );
|
||
|
drmFreeVersion( version );
|
||
|
MGADRICloseScreen( pScreen ); /* FIXME: ??? */
|
||
|
return FALSE;
|
||
|
}
|
||
|
pMGADRIServer->drm_version_major = version->version_major;
|
||
|
pMGADRIServer->drm_version_minor = version->version_minor;
|
||
|
|
||
|
drmFreeVersion( version );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( (pMga->bios.host_interface == MGA_HOST_PCI) &&
|
||
|
((pMGADRIServer->drm_version_minor < 2) || pMga->useOldDmaInit) ) {
|
||
|
/* PCI cards are supported if the DRM version is at least 3.2 and the
|
||
|
* user has not explicitly disabled the new DMA init path (i.e., to
|
||
|
* support old version of the client-side driver that don't use the
|
||
|
* new features of the 3.2 DRM).
|
||
|
*/
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||
|
"[drm] Direct rendering on PCI cards requires DRM version 3.2 or higher\n");
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||
|
"[drm] and a recent client-side driver. Also make sure that 'OldDmaInit'\n");
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||
|
"[drm] is not selected in xorg.conf.'\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( !MGADRIBootstrapDMA( pScreen ) ) {
|
||
|
DRICloseScreen( pScreen );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
void *scratch_ptr;
|
||
|
int scratch_int;
|
||
|
|
||
|
DRIGetDeviceInfo(pScreen, &pMGADRIServer->fb.handle,
|
||
|
&scratch_int, &scratch_int,
|
||
|
&scratch_int, &scratch_int,
|
||
|
&scratch_ptr);
|
||
|
}
|
||
|
|
||
|
xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n" );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
Bool MGADRIFinishScreenInit( ScreenPtr pScreen )
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
|
||
|
MGADRIPtr pMGADRI;
|
||
|
int i;
|
||
|
|
||
|
if ( !pMga->pDRIInfo )
|
||
|
return FALSE;
|
||
|
|
||
|
pMGADRI = (MGADRIPtr)pMga->pDRIInfo->devPrivate;
|
||
|
|
||
|
pMga->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 ) ) {
|
||
|
MGADRICloseScreen( pScreen );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( !MGADRIKernelInit( pScreen ) ) {
|
||
|
MGADRICloseScreen( pScreen );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( !MGADRIBuffersInit( pScreen ) ) {
|
||
|
MGADRICloseScreen( pScreen );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
MGADRIIrqInit(pMga, pScreen);
|
||
|
|
||
|
pMGADRI->chipset = pMga->chip_attribs->dri_chipset;
|
||
|
pMGADRI->width = pScrn->virtualX;
|
||
|
pMGADRI->height = pScrn->virtualY;
|
||
|
pMGADRI->cpp = pScrn->bitsPerPixel / 8;
|
||
|
|
||
|
pMGADRI->agpMode = pMga->agpMode;
|
||
|
|
||
|
pMGADRI->frontOffset = pMGADRIServer->frontOffset;
|
||
|
pMGADRI->frontPitch = pMGADRIServer->frontPitch;
|
||
|
pMGADRI->backOffset = pMGADRIServer->backOffset;
|
||
|
pMGADRI->backPitch = pMGADRIServer->backPitch;
|
||
|
pMGADRI->depthOffset = pMGADRIServer->depthOffset;
|
||
|
pMGADRI->depthPitch = pMGADRIServer->depthPitch;
|
||
|
pMGADRI->textureOffset = pMGADRIServer->textureOffset;
|
||
|
pMGADRI->textureSize = pMGADRIServer->textureSize;
|
||
|
|
||
|
pMGADRI->agpTextureOffset = (unsigned int)pMGADRIServer->agpTextures.handle;
|
||
|
pMGADRI->agpTextureSize = (unsigned int)pMGADRIServer->agpTextures.size;
|
||
|
|
||
|
pMGADRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
|
||
|
|
||
|
|
||
|
/* Newer versions of the client-side driver do not need these if the
|
||
|
* kernel version is high enough to support interrupt based waiting.
|
||
|
*/
|
||
|
|
||
|
pMGADRI->registers.handle = pMGADRIServer->registers.handle;
|
||
|
pMGADRI->registers.size = pMGADRIServer->registers.size;
|
||
|
pMGADRI->primary.handle = pMGADRIServer->primary.handle;
|
||
|
pMGADRI->primary.size = pMGADRIServer->primary.size;
|
||
|
|
||
|
|
||
|
/* These are no longer used by the client-side DRI driver. They should
|
||
|
* be removed in the next release (i.e., 6.9 / 7.0).
|
||
|
*/
|
||
|
|
||
|
pMGADRI->status.handle = pMGADRIServer->status.handle;
|
||
|
pMGADRI->status.size = pMGADRIServer->status.size;
|
||
|
pMGADRI->buffers.handle = pMGADRIServer->buffers.handle;
|
||
|
pMGADRI->buffers.size = pMGADRIServer->buffers.size;
|
||
|
|
||
|
i = mylog2( pMGADRI->textureSize / MGA_NR_TEX_REGIONS );
|
||
|
if ( i < MGA_LOG_MIN_TEX_REGION_SIZE )
|
||
|
i = MGA_LOG_MIN_TEX_REGION_SIZE;
|
||
|
|
||
|
pMGADRI->logTextureGranularity = i;
|
||
|
pMGADRI->textureSize = (pMGADRI->textureSize >> i) << i; /* truncate */
|
||
|
|
||
|
i = mylog2( pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS );
|
||
|
if ( i < MGA_LOG_MIN_TEX_REGION_SIZE )
|
||
|
i = MGA_LOG_MIN_TEX_REGION_SIZE;
|
||
|
|
||
|
pMGADRI->logAgpTextureGranularity = i;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
void MGADRICloseScreen( ScreenPtr pScreen )
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
||
|
MGAPtr pMga = MGAPTR(pScrn);
|
||
|
MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
|
||
|
drm_mga_init_t init;
|
||
|
|
||
|
if ( pMGADRIServer->drmBuffers ) {
|
||
|
drmUnmapBufs( pMGADRIServer->drmBuffers );
|
||
|
pMGADRIServer->drmBuffers = NULL;
|
||
|
}
|
||
|
|
||
|
if (pMga->irq) {
|
||
|
drmCtlUninstHandler(pMga->drmFD);
|
||
|
pMga->irq = 0;
|
||
|
pMga->reg_ien = 0;
|
||
|
}
|
||
|
|
||
|
/* Cleanup DMA */
|
||
|
memset( &init, 0, sizeof(drm_mga_init_t) );
|
||
|
init.func = MGA_CLEANUP_DMA;
|
||
|
drmCommandWrite( pMga->drmFD, DRM_MGA_INIT, &init, sizeof(drm_mga_init_t) );
|
||
|
|
||
|
if ( pMGADRIServer->agp.handle != DRM_AGP_NO_HANDLE ) {
|
||
|
drmAgpUnbind( pMga->drmFD, pMGADRIServer->agp.handle );
|
||
|
drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle );
|
||
|
pMGADRIServer->agp.handle = DRM_AGP_NO_HANDLE;
|
||
|
drmAgpRelease( pMga->drmFD );
|
||
|
}
|
||
|
|
||
|
DRICloseScreen( pScreen );
|
||
|
|
||
|
if ( pMga->pDRIInfo ) {
|
||
|
free(pMga->pDRIInfo->devPrivate);
|
||
|
pMga->pDRIInfo->devPrivate = 0;
|
||
|
DRIDestroyInfoRec( pMga->pDRIInfo );
|
||
|
pMga->pDRIInfo = 0;
|
||
|
}
|
||
|
free(pMga->DRIServerInfo);
|
||
|
pMga->DRIServerInfo = 0;
|
||
|
}
|