1fe5e51b7Smrg/* 2fe5e51b7Smrg * Copyright 2000 VA Linux Systems Inc., Fremont, California. 3fe5e51b7Smrg * All Rights Reserved. 4fe5e51b7Smrg * 5fe5e51b7Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6fe5e51b7Smrg * copy of this software and associated documentation files (the "Software"), 7fe5e51b7Smrg * to deal in the Software without restriction, including without limitation 8fe5e51b7Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9fe5e51b7Smrg * and/or sell copies of the Software, and to permit persons to whom the 10fe5e51b7Smrg * Software is furnished to do so, subject to the following conditions: 11fe5e51b7Smrg * 12fe5e51b7Smrg * The above copyright notice and this permission notice (including the next 13fe5e51b7Smrg * paragraph) shall be included in all copies or substantial portions of the 14fe5e51b7Smrg * Software. 15fe5e51b7Smrg * 16fe5e51b7Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17fe5e51b7Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18fe5e51b7Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19fe5e51b7Smrg * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES 20fe5e51b7Smrg * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21fe5e51b7Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22fe5e51b7Smrg * OTHER DEALINGS IN THE SOFTWARE. 23fe5e51b7Smrg * 24fe5e51b7Smrg * Authors: 25fe5e51b7Smrg * Keith Whitwell <keith@tungstengraphics.com> 26fe5e51b7Smrg * Gareth Hughes <gareth@valinux.com> 27fe5e51b7Smrg */ 28fe5e51b7Smrg 29fe5e51b7Smrg#ifdef HAVE_CONFIG_H 30fe5e51b7Smrg#include "config.h" 31fe5e51b7Smrg#endif 32fe5e51b7Smrg 33fe5e51b7Smrg#include "xf86.h" 34fe5e51b7Smrg#include "xf86_OSproc.h" 35fe5e51b7Smrg 36fe5e51b7Smrg#include "xf86Pci.h" 37fe5e51b7Smrg 38fe5e51b7Smrg#include "miline.h" 39fe5e51b7Smrg 40fe5e51b7Smrg#include <errno.h> 41fe5e51b7Smrg 42fe5e51b7Smrg#include <inttypes.h> 43fe5e51b7Smrg#include "mga_reg.h" 44fe5e51b7Smrg#include "mga.h" 45fe5e51b7Smrg#include "mga_macros.h" 46fe5e51b7Smrg#include "mga_dri.h" 47fe5e51b7Smrg#include "mga_sarea.h" 48fe5e51b7Smrg#include "mga_drm.h" 49fe5e51b7Smrg 50fe5e51b7Smrg#define _XF86DRI_SERVER_ 51fe5e51b7Smrg#include "sarea.h" 52fe5e51b7Smrg 53fe5e51b7Smrg#include "mga_reg.h" 54fe5e51b7Smrg#include "mga.h" 55fe5e51b7Smrg#include "mga_macros.h" 56fe5e51b7Smrg#include "mga_dri.h" 57fe5e51b7Smrg 58fe5e51b7Smrg#define DRM_MGA_IDLE_RETRY 2048 59fe5e51b7Smrg 60fe5e51b7Smrgstatic char MGAKernelDriverName[] = "mga"; 61fe5e51b7Smrgstatic char MGAClientDriverName[] = "mga"; 62fe5e51b7Smrg 63fe5e51b7Smrgstatic Bool MGACreateContext( ScreenPtr pScreen, VisualPtr visual, 64fe5e51b7Smrg drm_context_t hwContext, void *pVisualConfigPriv, 65fe5e51b7Smrg DRIContextType contextStore ) 66fe5e51b7Smrg{ 67fe5e51b7Smrg /* Nothing yet */ 68fe5e51b7Smrg return TRUE; 69fe5e51b7Smrg} 70fe5e51b7Smrg 71fe5e51b7Smrgstatic void MGADestroyContext( ScreenPtr pScreen, drm_context_t hwContext, 72fe5e51b7Smrg DRIContextType contextStore ) 73fe5e51b7Smrg{ 74fe5e51b7Smrg /* Nothing yet */ 75fe5e51b7Smrg} 76fe5e51b7Smrg 77fe5e51b7Smrg 78fe5e51b7Smrg/* Quiescence, locking 79fe5e51b7Smrg */ 80fe5e51b7Smrg#define MGA_TIMEOUT 2048 81fe5e51b7Smrg 82fe5e51b7Smrgstatic void MGAWaitForIdleDMA( ScrnInfoPtr pScrn ) 83fe5e51b7Smrg{ 84fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 85fe5e51b7Smrg drm_lock_t lock; 86fe5e51b7Smrg int ret; 87fe5e51b7Smrg int i = 0; 88fe5e51b7Smrg 89fe5e51b7Smrg memset( &lock, 0, sizeof(drm_lock_t) ); 90fe5e51b7Smrg 91fe5e51b7Smrg for (;;) { 92fe5e51b7Smrg do { 93fe5e51b7Smrg /* first ask for quiescent and flush */ 94fe5e51b7Smrg lock.flags = DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH; 95fe5e51b7Smrg do { 96fe5e51b7Smrg ret = drmCommandWrite( pMga->drmFD, DRM_MGA_FLUSH, 97fe5e51b7Smrg &lock, sizeof( drm_lock_t ) ); 98fe5e51b7Smrg } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY ); 99fe5e51b7Smrg 100fe5e51b7Smrg /* if it's still busy just try quiescent */ 101fe5e51b7Smrg if ( ret == -EBUSY ) { 102fe5e51b7Smrg lock.flags = DRM_LOCK_QUIESCENT; 103fe5e51b7Smrg do { 104fe5e51b7Smrg ret = drmCommandWrite( pMga->drmFD, DRM_MGA_FLUSH, 105fe5e51b7Smrg &lock, sizeof( drm_lock_t ) ); 106fe5e51b7Smrg } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY ); 107fe5e51b7Smrg } 108fe5e51b7Smrg } while ( ( ret == -EBUSY ) && ( i++ < MGA_TIMEOUT ) ); 109fe5e51b7Smrg 110fe5e51b7Smrg if ( ret == 0 ) 111fe5e51b7Smrg return; 112fe5e51b7Smrg 113fe5e51b7Smrg xf86DrvMsg( pScrn->scrnIndex, X_ERROR, 114fe5e51b7Smrg "[dri] Idle timed out, resetting engine...\n" ); 115fe5e51b7Smrg 116fe5e51b7Smrg drmCommandNone( pMga->drmFD, DRM_MGA_RESET ); 117fe5e51b7Smrg } 118fe5e51b7Smrg} 119fe5e51b7Smrg 120fe5e51b7Smrg 121fe5e51b7Smrgvoid MGAGetQuiescence( ScrnInfoPtr pScrn ) 122fe5e51b7Smrg{ 123fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 12481f79626Smrg#ifdef USE_XAA 12581f79626Smrg MGAFBLayout *pLayout = &pMga->CurrentLayout; 12681f79626Smrg#endif /* USE_XAA */ 127fe5e51b7Smrg 128fe5e51b7Smrg pMga->haveQuiescense = 1; 129fe5e51b7Smrg 130fe5e51b7Smrg if ( pMga->directRenderingEnabled ) { 131fe5e51b7Smrg MGAWaitForIdleDMA( pScrn ); 132fe5e51b7Smrg 133fe5e51b7Smrg /* FIXME what about EXA? */ 134acd6767fSmrg#ifdef USE_XAA 135fe5e51b7Smrg if (!pMga->Exa && pMga->AccelInfoRec) { 136fe5e51b7Smrg WAITFIFO( 11 ); 137fe5e51b7Smrg OUTREG( MGAREG_MACCESS, pMga->MAccess ); 138fe5e51b7Smrg OUTREG( MGAREG_PITCH, pLayout->displayWidth ); 139fe5e51b7Smrg 140fe5e51b7Smrg pMga->PlaneMask = ~0; 141fe5e51b7Smrg OUTREG( MGAREG_PLNWT, pMga->PlaneMask ); 142fe5e51b7Smrg 143fe5e51b7Smrg pMga->BgColor = 0; 144fe5e51b7Smrg pMga->FgColor = 0; 145fe5e51b7Smrg OUTREG( MGAREG_BCOL, pMga->BgColor ); 146fe5e51b7Smrg OUTREG( MGAREG_FCOL, pMga->FgColor ); 147fe5e51b7Smrg OUTREG( MGAREG_SRCORG, pMga->realSrcOrg ); 148fe5e51b7Smrg 149fe5e51b7Smrg pMga->SrcOrg = 0; 150fe5e51b7Smrg OUTREG( MGAREG_DSTORG, pMga->DstOrg ); 151fe5e51b7Smrg OUTREG( MGAREG_OPMODE, MGAOPM_DMA_BLIT ); 152fe5e51b7Smrg OUTREG( MGAREG_CXBNDRY, 0xFFFF0000 ); /* (maxX << 16) | minX */ 153fe5e51b7Smrg OUTREG( MGAREG_YTOP, 0x00000000 ); /* minPixelPointer */ 154fe5e51b7Smrg OUTREG( MGAREG_YBOT, 0x007FFFFF ); /* maxPixelPointer */ 155fe5e51b7Smrg 156fe5e51b7Smrg pMga->AccelFlags &= ~CLIPPER_ON; 157fe5e51b7Smrg } 158fe5e51b7Smrg#endif 159fe5e51b7Smrg } 160fe5e51b7Smrg} 161fe5e51b7Smrg 162fe5e51b7Smrgvoid MGAGetQuiescenceShared( ScrnInfoPtr pScrn ) 163fe5e51b7Smrg{ 164fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 165fe5e51b7Smrg MGAEntPtr pMGAEnt = pMga->entityPrivate; 166fe5e51b7Smrg MGAPtr pMGA2 = MGAPTR(pMGAEnt->pScrn_2); 167fe5e51b7Smrg 168fe5e51b7Smrg pMga = MGAPTR(pMGAEnt->pScrn_1); 169fe5e51b7Smrg pMga->haveQuiescense = 1; 170fe5e51b7Smrg pMGA2->haveQuiescense = 1; 171fe5e51b7Smrg 172fe5e51b7Smrg if ( pMGAEnt->directRenderingEnabled ) { 173fe5e51b7Smrg MGAWaitForIdleDMA( pMGAEnt->pScrn_1 ); 174fe5e51b7Smrg 175fe5e51b7Smrg /* FIXME what about EXA? */ 176fe5e51b7Smrg#ifdef USE_XAA 177fe5e51b7Smrg if (!pMga->Exa && pMga->AccelInfoRec) 178fe5e51b7Smrg pMga->RestoreAccelState( pScrn ); 179fe5e51b7Smrg#endif 180fe5e51b7Smrg xf86SetLastScrnFlag( pScrn->entityList[0], pScrn->scrnIndex ); 181fe5e51b7Smrg } 182fe5e51b7Smrg} 183fe5e51b7Smrg 184fe5e51b7Smrgstatic void MGASwapContext( ScreenPtr pScreen ) 185fe5e51b7Smrg{ 1860bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 187fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 188fe5e51b7Smrg 189fe5e51b7Smrg /* Arrange for dma_quiescence and xaa sync to be called as 190fe5e51b7Smrg * appropriate. 191fe5e51b7Smrg */ 192fe5e51b7Smrg pMga->haveQuiescense = 0; 193fe5e51b7Smrg 194fe5e51b7Smrg MGA_MARK_SYNC(pMga, pScrn); 195fe5e51b7Smrg} 196fe5e51b7Smrg 197fe5e51b7Smrgstatic void MGASwapContextShared( ScreenPtr pScreen ) 198fe5e51b7Smrg{ 1990bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 200fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 201fe5e51b7Smrg MGAEntPtr pMGAEnt = pMga->entityPrivate; 202fe5e51b7Smrg MGAPtr pMGA2 = MGAPTR(pMGAEnt->pScrn_2); 203fe5e51b7Smrg 204fe5e51b7Smrg pMga = MGAPTR(pMGAEnt->pScrn_1); 205fe5e51b7Smrg 206fe5e51b7Smrg pMga->haveQuiescense = pMGA2->haveQuiescense = 0; 207fe5e51b7Smrg 208fe5e51b7Smrg MGA_MARK_SYNC(pMga, pScrn); 209fe5e51b7Smrg MGA_MARK_SYNC(pMGA2, pMGAEnt->pScrn_2); 210fe5e51b7Smrg} 211fe5e51b7Smrg 212fe5e51b7Smrg/* FIXME: This comment is out of date, since we aren't overriding 213fe5e51b7Smrg * Block/Wakeuphandler anymore. 214fe5e51b7Smrg * 215fe5e51b7Smrg * 216fe5e51b7Smrg * This is really only called from validate/postvalidate as we 217fe5e51b7Smrg * override the dri lock/unlock. Want to remove validate/postvalidate 218fe5e51b7Smrg * processing, but need to remove all client-side use of drawable lock 219d2b10af6Smrg * first (otherwise there is no one recover when a client dies holding 220fe5e51b7Smrg * the drawable lock). 221fe5e51b7Smrg * 222fe5e51b7Smrg * What does this mean? 223fe5e51b7Smrg * 224fe5e51b7Smrg * - The above code gets executed every time a 225fe5e51b7Smrg * window changes shape or the focus changes, which isn't really 226fe5e51b7Smrg * optimal. 227fe5e51b7Smrg * - The X server therefore believes it needs to do an XAA sync 228fe5e51b7Smrg * *and* a dma quiescense ioctl each time that happens. 229fe5e51b7Smrg * 230fe5e51b7Smrg * We don't wrap wakeuphandler any longer, so at least we can say that 231fe5e51b7Smrg * this doesn't happen *every time the mouse moves*... 232fe5e51b7Smrg */ 233fe5e51b7Smrgstatic void 234fe5e51b7SmrgMGADRISwapContext( ScreenPtr pScreen, DRISyncType syncType, 235fe5e51b7Smrg DRIContextType oldContextType, void *oldContext, 236fe5e51b7Smrg DRIContextType newContextType, void *newContext ) 237fe5e51b7Smrg{ 238fe5e51b7Smrg if ( syncType == DRI_3D_SYNC && 239fe5e51b7Smrg oldContextType == DRI_2D_CONTEXT && 240fe5e51b7Smrg newContextType == DRI_2D_CONTEXT ) 241fe5e51b7Smrg { 242fe5e51b7Smrg MGASwapContext( pScreen ); 243fe5e51b7Smrg } 244fe5e51b7Smrg} 245fe5e51b7Smrg 246fe5e51b7Smrgstatic void 247fe5e51b7SmrgMGADRISwapContextShared( ScreenPtr pScreen, DRISyncType syncType, 248fe5e51b7Smrg DRIContextType oldContextType, void *oldContext, 249fe5e51b7Smrg DRIContextType newContextType, void *newContext ) 250fe5e51b7Smrg{ 251fe5e51b7Smrg if ( syncType == DRI_3D_SYNC && 252fe5e51b7Smrg oldContextType == DRI_2D_CONTEXT && 253fe5e51b7Smrg newContextType == DRI_2D_CONTEXT ) 254fe5e51b7Smrg { 255fe5e51b7Smrg MGASwapContextShared( pScreen ); 256fe5e51b7Smrg } 257fe5e51b7Smrg} 258fe5e51b7Smrg 259fe5e51b7Smrgvoid MGASelectBuffer( ScrnInfoPtr pScrn, int which ) 260fe5e51b7Smrg{ 261fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 262fe5e51b7Smrg MGADRIPtr pMGADRI = (MGADRIPtr)pMga->pDRIInfo->devPrivate; 263fe5e51b7Smrg 264fe5e51b7Smrg switch ( which ) { 265fe5e51b7Smrg case MGA_BACK: 266fe5e51b7Smrg OUTREG( MGAREG_DSTORG, pMGADRI->backOffset ); 267fe5e51b7Smrg OUTREG( MGAREG_SRCORG, pMGADRI->backOffset ); 268fe5e51b7Smrg break; 269fe5e51b7Smrg case MGA_DEPTH: 270fe5e51b7Smrg OUTREG( MGAREG_DSTORG, pMGADRI->depthOffset ); 271fe5e51b7Smrg OUTREG( MGAREG_SRCORG, pMGADRI->depthOffset ); 272fe5e51b7Smrg break; 273fe5e51b7Smrg default: 274fe5e51b7Smrg case MGA_FRONT: 275fe5e51b7Smrg OUTREG( MGAREG_DSTORG, pMGADRI->frontOffset ); 276fe5e51b7Smrg OUTREG( MGAREG_SRCORG, pMGADRI->frontOffset ); 277fe5e51b7Smrg break; 278fe5e51b7Smrg } 279fe5e51b7Smrg} 280fe5e51b7Smrg 281fe5e51b7Smrgstatic unsigned int mylog2( unsigned int n ) 282fe5e51b7Smrg{ 283fe5e51b7Smrg unsigned int log2 = 1; 284fe5e51b7Smrg while ( n > 1 ) n >>= 1, log2++; 285fe5e51b7Smrg return log2; 286fe5e51b7Smrg} 287fe5e51b7Smrg 288fe5e51b7Smrg/** 289fe5e51b7Smrg * Initialize DMA and secondary texture memory 290fe5e51b7Smrg * 291fe5e51b7Smrg * \todo 292fe5e51b7Smrg * The sizes used for the primary DMA buffer and the bin size and count for 293fe5e51b7Smrg * the secondary DMA buffers should be configurable from the xorg.conf. 294fe5e51b7Smrg * 295fe5e51b7Smrg * \todo 296fe5e51b7Smrg * This routine should use \c mga_bios_values::host_interface to limit the 297fe5e51b7Smrg * AGP mode. It the card is PCI, \c MGARec::agpSize should be forced to 0. 298fe5e51b7Smrg */ 299fe5e51b7Smrgstatic Bool MGADRIBootstrapDMA(ScreenPtr pScreen) 300fe5e51b7Smrg{ 3010bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 302fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 303fe5e51b7Smrg MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo; 304fe5e51b7Smrg int ret; 305fe5e51b7Smrg int requested_agp_mode; 306fe5e51b7Smrg int count; 307fe5e51b7Smrg 308fe5e51b7Smrg 309fe5e51b7Smrg if(pMga->agpSize < 12)pMga->agpSize = 12; 310fe5e51b7Smrg if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */ 311fe5e51b7Smrg 312fe5e51b7Smrg 313fe5e51b7Smrg requested_agp_mode = 0; 314fe5e51b7Smrg switch ( pMga->agpMode ) { 315fe5e51b7Smrg case 4: 316fe5e51b7Smrg requested_agp_mode |= MGA_AGP_4X_MODE; 317fe5e51b7Smrg case 2: 318fe5e51b7Smrg requested_agp_mode |= MGA_AGP_2X_MODE; 319fe5e51b7Smrg case 1: 320fe5e51b7Smrg default: 321fe5e51b7Smrg requested_agp_mode |= MGA_AGP_1X_MODE; 322fe5e51b7Smrg } 323fe5e51b7Smrg 324fe5e51b7Smrg 325fe5e51b7Smrg if ( (pMGADRIServer->drm_version_minor >= 2) && !pMga->useOldDmaInit ) { 326fe5e51b7Smrg drm_mga_dma_bootstrap_t dma_bs; 327fe5e51b7Smrg 328fe5e51b7Smrg 329fe5e51b7Smrg (void) memset( & dma_bs, 0, sizeof( dma_bs ) ); 330fe5e51b7Smrg dma_bs.primary_size = 1024 * 1024; 331fe5e51b7Smrg dma_bs.secondary_bin_count = MGA_NUM_BUFFERS; 332fe5e51b7Smrg dma_bs.secondary_bin_size = MGA_BUFFER_SIZE; 333fe5e51b7Smrg dma_bs.agp_size = pMga->agpSize; 334fe5e51b7Smrg dma_bs.agp_mode = (pMga->forcePciDma) ? 0 : requested_agp_mode; 335fe5e51b7Smrg 336fe5e51b7Smrg ret = drmCommandWriteRead( pMga->drmFD, DRM_MGA_DMA_BOOTSTRAP, 337fe5e51b7Smrg & dma_bs, sizeof( dma_bs ) ); 338fe5e51b7Smrg if ( ret ) { 339fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Could not boot-strap DMA (%d)\n", ret ); 340fe5e51b7Smrg return FALSE; 341fe5e51b7Smrg } 342fe5e51b7Smrg 343fe5e51b7Smrg pMga->agpMode = dma_bs.agp_mode; 344fe5e51b7Smrg pMGADRIServer->agp.size = dma_bs.agp_size; 345fe5e51b7Smrg 346fe5e51b7Smrg pMGADRIServer->agpTextures.handle = dma_bs.texture_handle; 347fe5e51b7Smrg pMGADRIServer->agpTextures.size = dma_bs.texture_size; 348fe5e51b7Smrg } 349fe5e51b7Smrg else { 350fe5e51b7Smrg unsigned long mode; 351fe5e51b7Smrg unsigned int vendor, device; 352fe5e51b7Smrg int i; 353fe5e51b7Smrg 354fe5e51b7Smrg 355fe5e51b7Smrg if ( pMga->forcePciDma ) { 356fe5e51b7Smrg const char * const msg = (pMGADRIServer->drm_version_minor < 2) 357fe5e51b7Smrg ? "DRM version is too old (3.2 or later required)" 358fe5e51b7Smrg : "old DMA init path was requested"; 359fe5e51b7Smrg 360fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_WARNING, 361fe5e51b7Smrg "[agp] Cannot force PCI DMA because %s\n", msg ); 362fe5e51b7Smrg } 363fe5e51b7Smrg 364fe5e51b7Smrg if ( drmAgpAcquire( pMga->drmFD ) < 0 ) { 365fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not available\n" ); 366fe5e51b7Smrg return FALSE; 367fe5e51b7Smrg } 368fe5e51b7Smrg 369fe5e51b7Smrg mode = drmAgpGetMode( pMga->drmFD ); /* Default mode */ 370fe5e51b7Smrg vendor = drmAgpVendorId( pMga->drmFD ); 371fe5e51b7Smrg device = drmAgpDeviceId( pMga->drmFD ); 372fe5e51b7Smrg 373fe5e51b7Smrg mode = (mode & ~MGA_AGP_MODE_MASK) | requested_agp_mode; 374fe5e51b7Smrg 375fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 376fe5e51b7Smrg "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", 377fe5e51b7Smrg mode, vendor, device, 378fe5e51b7Smrg VENDOR_ID(pMga->PciInfo), 379fe5e51b7Smrg DEVICE_ID(pMga->PciInfo)); 380fe5e51b7Smrg 381fe5e51b7Smrg if ( drmAgpEnable( pMga->drmFD, mode ) < 0 ) { 382fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" ); 383fe5e51b7Smrg drmAgpRelease( pMga->drmFD ); 384fe5e51b7Smrg return FALSE; 385fe5e51b7Smrg } 386fe5e51b7Smrg 387fe5e51b7Smrg if ( pMga->Chipset == PCI_CHIP_MGAG200 ) { 388fe5e51b7Smrg switch ( pMga->agpMode ) { 389fe5e51b7Smrg case 2: 390fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 391fe5e51b7Smrg "[drm] Enabling AGP 2x PLL encoding\n" ); 392fe5e51b7Smrg OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE ); 393fe5e51b7Smrg break; 394fe5e51b7Smrg 395fe5e51b7Smrg case 1: 396fe5e51b7Smrg default: 397fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 398fe5e51b7Smrg "[drm] Disabling AGP 2x PLL encoding\n" ); 399fe5e51b7Smrg OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE ); 400fe5e51b7Smrg pMga->agpMode = 1; 401fe5e51b7Smrg break; 402fe5e51b7Smrg } 403fe5e51b7Smrg } 404fe5e51b7Smrg 405fe5e51b7Smrg pMGADRIServer->agp.size = pMga->agpSize * 1024 * 1024; 406fe5e51b7Smrg 407fe5e51b7Smrg pMGADRIServer->warp.offset = 0; 408fe5e51b7Smrg pMGADRIServer->warp.size = MGA_WARP_UCODE_SIZE; 409fe5e51b7Smrg 410fe5e51b7Smrg pMGADRIServer->primary.offset = (pMGADRIServer->warp.offset + 411fe5e51b7Smrg pMGADRIServer->warp.size); 412fe5e51b7Smrg pMGADRIServer->primary.size = 1024 * 1024; 413fe5e51b7Smrg 414fe5e51b7Smrg pMGADRIServer->buffers.offset = (pMGADRIServer->primary.offset + 415fe5e51b7Smrg pMGADRIServer->primary.size); 416fe5e51b7Smrg pMGADRIServer->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE; 417fe5e51b7Smrg 418fe5e51b7Smrg 419fe5e51b7Smrg pMGADRIServer->agpTextures.offset = (pMGADRIServer->buffers.offset + 420fe5e51b7Smrg pMGADRIServer->buffers.size); 421fe5e51b7Smrg 422fe5e51b7Smrg pMGADRIServer->agpTextures.size = (pMGADRIServer->agp.size - 423fe5e51b7Smrg pMGADRIServer->agpTextures.offset); 424fe5e51b7Smrg 425fe5e51b7Smrg ret = drmAgpAlloc( pMga->drmFD, pMGADRIServer->agp.size, 426fe5e51b7Smrg 0, NULL, &pMGADRIServer->agp.handle ); 427fe5e51b7Smrg if ( ret < 0 ) { 428fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret ); 429fe5e51b7Smrg drmAgpRelease( pMga->drmFD ); 430fe5e51b7Smrg return FALSE; 431fe5e51b7Smrg } 432fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 433fe5e51b7Smrg "[agp] %d kB allocated with handle 0x%08x\n", 434fe5e51b7Smrg pMGADRIServer->agp.size/1024, 435fe5e51b7Smrg (unsigned int) pMGADRIServer->agp.handle ); 436fe5e51b7Smrg 437fe5e51b7Smrg if ( drmAgpBind( pMga->drmFD, pMGADRIServer->agp.handle, 0 ) < 0 ) { 438fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind memory\n" ); 439fe5e51b7Smrg drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle ); 440fe5e51b7Smrg drmAgpRelease( pMga->drmFD ); 441fe5e51b7Smrg return FALSE; 442fe5e51b7Smrg } 443fe5e51b7Smrg 444fe5e51b7Smrg /* WARP microcode space 445fe5e51b7Smrg */ 446fe5e51b7Smrg if ( drmAddMap( pMga->drmFD, 447fe5e51b7Smrg pMGADRIServer->warp.offset, 448fe5e51b7Smrg pMGADRIServer->warp.size, 449fe5e51b7Smrg DRM_AGP, DRM_READ_ONLY, 450fe5e51b7Smrg &pMGADRIServer->warp.handle ) < 0 ) { 451fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 452fe5e51b7Smrg "[agp] Could not add WARP microcode mapping\n" ); 453fe5e51b7Smrg return FALSE; 454fe5e51b7Smrg } 455fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 456fe5e51b7Smrg "[agp] WARP microcode handle = 0x%08x\n", 457fe5e51b7Smrg (unsigned int) pMGADRIServer->warp.handle ); 458fe5e51b7Smrg 459fe5e51b7Smrg /* Primary DMA space 460fe5e51b7Smrg */ 461fe5e51b7Smrg if ( drmAddMap( pMga->drmFD, 462fe5e51b7Smrg pMGADRIServer->primary.offset, 463fe5e51b7Smrg pMGADRIServer->primary.size, 464fe5e51b7Smrg DRM_AGP, DRM_READ_ONLY, 465fe5e51b7Smrg &pMGADRIServer->primary.handle ) < 0 ) { 466fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 467fe5e51b7Smrg "[agp] Could not add primary DMA mapping\n" ); 468fe5e51b7Smrg return FALSE; 469fe5e51b7Smrg } 470fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 471fe5e51b7Smrg "[agp] Primary DMA handle = 0x%08x\n", 472fe5e51b7Smrg (unsigned int) pMGADRIServer->primary.handle ); 473fe5e51b7Smrg 474fe5e51b7Smrg /* DMA buffers 475fe5e51b7Smrg */ 476fe5e51b7Smrg if ( drmAddMap( pMga->drmFD, 477fe5e51b7Smrg pMGADRIServer->buffers.offset, 478fe5e51b7Smrg pMGADRIServer->buffers.size, 479fe5e51b7Smrg DRM_AGP, 0, 480fe5e51b7Smrg &pMGADRIServer->buffers.handle ) < 0 ) { 481fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 482fe5e51b7Smrg "[agp] Could not add DMA buffers mapping\n" ); 483fe5e51b7Smrg return FALSE; 484fe5e51b7Smrg } 485fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 486fe5e51b7Smrg "[agp] DMA buffers handle = 0x%08x\n", 487fe5e51b7Smrg (unsigned int) pMGADRIServer->buffers.handle ); 488fe5e51b7Smrg 489fe5e51b7Smrg count = drmAddBufs( pMga->drmFD, 490fe5e51b7Smrg MGA_NUM_BUFFERS, MGA_BUFFER_SIZE, 491fe5e51b7Smrg DRM_AGP_BUFFER, pMGADRIServer->buffers.offset ); 492fe5e51b7Smrg if ( count <= 0 ) { 493fe5e51b7Smrg xf86DrvMsg( pScrn->scrnIndex, X_INFO, 494fe5e51b7Smrg "[drm] failure adding %d %d byte DMA buffers\n", 495fe5e51b7Smrg MGA_NUM_BUFFERS, MGA_BUFFER_SIZE ); 496fe5e51b7Smrg return FALSE; 497fe5e51b7Smrg } 498fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 499fe5e51b7Smrg "[drm] Added %d %d byte DMA buffers\n", 500fe5e51b7Smrg count, MGA_BUFFER_SIZE ); 501fe5e51b7Smrg 502fe5e51b7Smrg i = mylog2(pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS); 503fe5e51b7Smrg if(i < MGA_LOG_MIN_TEX_REGION_SIZE) 504fe5e51b7Smrg i = MGA_LOG_MIN_TEX_REGION_SIZE; 505fe5e51b7Smrg pMGADRIServer->agpTextures.size = (pMGADRIServer->agpTextures.size >> i) << i; 506fe5e51b7Smrg 507fe5e51b7Smrg if ( drmAddMap( pMga->drmFD, 508fe5e51b7Smrg pMGADRIServer->agpTextures.offset, 509fe5e51b7Smrg pMGADRIServer->agpTextures.size, 510fe5e51b7Smrg DRM_AGP, 0, 511fe5e51b7Smrg &pMGADRIServer->agpTextures.handle ) < 0 ) { 512fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 513fe5e51b7Smrg "[agp] Could not add agpTexture mapping\n" ); 514fe5e51b7Smrg return FALSE; 515fe5e51b7Smrg } 516fe5e51b7Smrg 517fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 518fe5e51b7Smrg "[agp] agpTexture handle = 0x%08x\n", 519fe5e51b7Smrg (unsigned int) pMGADRIServer->agpTextures.handle ); 520fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 521fe5e51b7Smrg "[agp] agpTexture size: %d kb\n", pMGADRIServer->agpTextures.size/1024 ); 522fe5e51b7Smrg 523fe5e51b7Smrg pMGADRIServer->registers.size = MGAIOMAPSIZE; 524fe5e51b7Smrg 525fe5e51b7Smrg if ( drmAddMap( pMga->drmFD, 526fe5e51b7Smrg (drm_handle_t) MGA_IO_ADDRESS(pMga), 527fe5e51b7Smrg pMGADRIServer->registers.size, 528fe5e51b7Smrg DRM_REGISTERS, DRM_READ_ONLY, 529fe5e51b7Smrg &pMGADRIServer->registers.handle ) < 0 ) { 530fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 531fe5e51b7Smrg "[drm] Could not add MMIO registers mapping\n" ); 532fe5e51b7Smrg return FALSE; 533fe5e51b7Smrg } 534fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 535fe5e51b7Smrg "[drm] Registers handle = 0x%08x\n", 536fe5e51b7Smrg (unsigned int) pMGADRIServer->registers.handle ); 537fe5e51b7Smrg 538fe5e51b7Smrg pMGADRIServer->status.size = SAREA_MAX; 539fe5e51b7Smrg 540fe5e51b7Smrg if ( drmAddMap( pMga->drmFD, 0, pMGADRIServer->status.size, 541fe5e51b7Smrg DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL, 542fe5e51b7Smrg &pMGADRIServer->status.handle ) < 0 ) { 543fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 544fe5e51b7Smrg "[drm] Could not add status page mapping\n" ); 545fe5e51b7Smrg return FALSE; 546fe5e51b7Smrg } 547fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 548fe5e51b7Smrg "[drm] Status handle = 0x%08x\n", 549fe5e51b7Smrg (unsigned int) pMGADRIServer->status.handle ); 550fe5e51b7Smrg } 551fe5e51b7Smrg 552fe5e51b7Smrg return TRUE; 553fe5e51b7Smrg} 554fe5e51b7Smrg 555fe5e51b7Smrgstatic Bool MGADRIKernelInit( ScreenPtr pScreen ) 556fe5e51b7Smrg{ 5570bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 558fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 559fe5e51b7Smrg MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo; 560fe5e51b7Smrg drm_mga_init_t init; 561fe5e51b7Smrg int ret; 562fe5e51b7Smrg 563fe5e51b7Smrg 564fe5e51b7Smrg if (!pMga->chip_attribs->dri_capable) { 565fe5e51b7Smrg return FALSE; 566fe5e51b7Smrg } 567fe5e51b7Smrg 568fe5e51b7Smrg memset( &init, 0, sizeof(drm_mga_init_t) ); 569fe5e51b7Smrg 570fe5e51b7Smrg init.func = MGA_INIT_DMA; 571fe5e51b7Smrg init.sarea_priv_offset = sizeof(XF86DRISAREARec); 572fe5e51b7Smrg init.chipset = pMga->chip_attribs->dri_chipset; 573fe5e51b7Smrg init.sgram = !pMga->HasSDRAM; 574fe5e51b7Smrg 575fe5e51b7Smrg init.maccess = pMga->MAccess; 576fe5e51b7Smrg 577fe5e51b7Smrg init.fb_cpp = pScrn->bitsPerPixel / 8; 578fe5e51b7Smrg init.front_offset = pMGADRIServer->frontOffset; 579fe5e51b7Smrg init.front_pitch = pMGADRIServer->frontPitch / init.fb_cpp; 580fe5e51b7Smrg init.back_offset = pMGADRIServer->backOffset; 581fe5e51b7Smrg init.back_pitch = pMGADRIServer->backPitch / init.fb_cpp; 582fe5e51b7Smrg 583fe5e51b7Smrg init.depth_cpp = pScrn->bitsPerPixel / 8; 584fe5e51b7Smrg init.depth_offset = pMGADRIServer->depthOffset; 585fe5e51b7Smrg init.depth_pitch = pMGADRIServer->depthPitch / init.depth_cpp; 586fe5e51b7Smrg 587fe5e51b7Smrg init.texture_offset[0] = pMGADRIServer->textureOffset; 588fe5e51b7Smrg init.texture_size[0] = pMGADRIServer->textureSize; 589fe5e51b7Smrg 590fe5e51b7Smrg init.fb_offset = pMGADRIServer->fb.handle; 591fe5e51b7Smrg init.mmio_offset = pMGADRIServer->registers.handle; 592fe5e51b7Smrg init.status_offset = pMGADRIServer->status.handle; 593fe5e51b7Smrg 594fe5e51b7Smrg init.warp_offset = pMGADRIServer->warp.handle; 595fe5e51b7Smrg init.primary_offset = pMGADRIServer->primary.handle; 596fe5e51b7Smrg init.buffers_offset = pMGADRIServer->buffers.handle; 597fe5e51b7Smrg 598fe5e51b7Smrg init.texture_offset[1] = pMGADRIServer->agpTextures.handle; 599fe5e51b7Smrg init.texture_size[1] = pMGADRIServer->agpTextures.size; 600fe5e51b7Smrg 601fe5e51b7Smrg ret = drmCommandWrite( pMga->drmFD, DRM_MGA_INIT, &init, sizeof(drm_mga_init_t)); 602fe5e51b7Smrg if ( ret < 0 ) { 603fe5e51b7Smrg xf86DrvMsg( pScrn->scrnIndex, X_ERROR, 604fe5e51b7Smrg "[drm] Failed to initialize DMA! (%d)\n", ret ); 605fe5e51b7Smrg return FALSE; 606fe5e51b7Smrg } 607fe5e51b7Smrg 608fe5e51b7Smrg 609fe5e51b7Smrg return TRUE; 610fe5e51b7Smrg} 611fe5e51b7Smrg 612fe5e51b7Smrg/* FIXME: This function uses the DRM to get the IRQ, but the pci_device 613fe5e51b7Smrg * FIXME: structure (PciInfo) already has that information. 614fe5e51b7Smrg */ 615fe5e51b7Smrgstatic void MGADRIIrqInit(MGAPtr pMga, ScreenPtr pScreen) 616fe5e51b7Smrg{ 6170bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 618fe5e51b7Smrg 619fe5e51b7Smrg if (!pMga->irq) { 620fe5e51b7Smrg pMga->irq = drmGetInterruptFromBusID(pMga->drmFD, 621fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 622fe5e51b7Smrg ((pMga->PciInfo->domain << 8) | 623fe5e51b7Smrg pMga->PciInfo->bus), 624fe5e51b7Smrg pMga->PciInfo->dev, 625fe5e51b7Smrg pMga->PciInfo->func 626fe5e51b7Smrg#else 627fe5e51b7Smrg ((pciConfigPtr)pMga->PciInfo->thisCard)->busnum, 628fe5e51b7Smrg ((pciConfigPtr)pMga->PciInfo->thisCard)->devnum, 629fe5e51b7Smrg ((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum 630fe5e51b7Smrg#endif 631fe5e51b7Smrg ); 632fe5e51b7Smrg 633fe5e51b7Smrg if((drmCtlInstHandler(pMga->drmFD, pMga->irq)) != 0) { 634fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 635fe5e51b7Smrg "[drm] failure adding irq handler, " 636fe5e51b7Smrg "there is a device already using that irq\n" 637fe5e51b7Smrg "[drm] falling back to irq-free operation\n"); 638fe5e51b7Smrg pMga->irq = 0; 639fe5e51b7Smrg } else { 640fe5e51b7Smrg pMga->reg_ien = INREG( MGAREG_IEN ); 641fe5e51b7Smrg } 642fe5e51b7Smrg } 643fe5e51b7Smrg 644fe5e51b7Smrg if (pMga->irq) 645fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 646fe5e51b7Smrg "[drm] dma control initialized, using IRQ %d\n", 647fe5e51b7Smrg pMga->irq); 648fe5e51b7Smrg} 649fe5e51b7Smrg 650fe5e51b7Smrgstatic Bool MGADRIBuffersInit( ScreenPtr pScreen ) 651fe5e51b7Smrg{ 6520bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 653fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 654fe5e51b7Smrg MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo; 655fe5e51b7Smrg 656fe5e51b7Smrg 657fe5e51b7Smrg pMGADRIServer->drmBuffers = drmMapBufs( pMga->drmFD ); 658fe5e51b7Smrg if ( !pMGADRIServer->drmBuffers ) { 659fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 660fe5e51b7Smrg "[drm] Failed to map DMA buffers list\n" ); 661fe5e51b7Smrg return FALSE; 662fe5e51b7Smrg } 663fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 664fe5e51b7Smrg "[drm] Mapped %d DMA buffers\n", 665fe5e51b7Smrg pMGADRIServer->drmBuffers->count ); 666fe5e51b7Smrg 667fe5e51b7Smrg return TRUE; 668fe5e51b7Smrg} 669fe5e51b7Smrg 670fe5e51b7Smrg#ifdef USE_XAA 671fe5e51b7Smrgstatic void MGADRIInitBuffersXAA(WindowPtr pWin, RegionPtr prgn, 672fe5e51b7Smrg CARD32 index) 673fe5e51b7Smrg{ 674fe5e51b7Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 6750bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 676fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 677fe5e51b7Smrg BoxPtr pbox = REGION_RECTS(prgn); 678fe5e51b7Smrg int nbox = REGION_NUM_RECTS(prgn); 679fe5e51b7Smrg XAAInfoRecPtr xaa = pMga->AccelInfoRec; 680fe5e51b7Smrg 681fe5e51b7Smrg CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn); 682fe5e51b7Smrg 683fe5e51b7Smrg xaa->SetupForSolidFill(pScrn, 0, GXcopy, -1); 684fe5e51b7Smrg 685fe5e51b7Smrg while (nbox--) { 686fe5e51b7Smrg MGASelectBuffer(pScrn, MGA_BACK); 687fe5e51b7Smrg xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, 688fe5e51b7Smrg pbox->x2-pbox->x1, pbox->y2-pbox->y1); 689fe5e51b7Smrg MGASelectBuffer(pScrn, MGA_DEPTH); 690fe5e51b7Smrg xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, 691fe5e51b7Smrg pbox->x2-pbox->x1, pbox->y2-pbox->y1); 692fe5e51b7Smrg pbox++; 693fe5e51b7Smrg } 694fe5e51b7Smrg 695fe5e51b7Smrg MGASelectBuffer(pScrn, MGA_FRONT); 696fe5e51b7Smrg 697fe5e51b7Smrg pMga->AccelInfoRec->NeedToSync = TRUE; 698fe5e51b7Smrg} 699fe5e51b7Smrg#endif 700fe5e51b7Smrg 701fe5e51b7Smrgstatic void MGADRIInitBuffersEXA(WindowPtr pWin, RegionPtr prgn, 702fe5e51b7Smrg CARD32 index) 703fe5e51b7Smrg{ 704fe5e51b7Smrg /* FIXME */ 705fe5e51b7Smrg} 706fe5e51b7Smrg 707fe5e51b7Smrg#ifdef USE_XAA 708fe5e51b7Smrg/* 709fe5e51b7Smrg This routine is a modified form of XAADoBitBlt with the calls to 710fe5e51b7Smrg ScreenToScreenBitBlt built in. My routine has the prgnSrc as source 711fe5e51b7Smrg instead of destination. My origin is upside down so the ydir cases 712fe5e51b7Smrg are reversed. 713fe5e51b7Smrg*/ 714fe5e51b7Smrgstatic void MGADRIMoveBuffersXAA(WindowPtr pParent, DDXPointRec ptOldOrg, 715fe5e51b7Smrg RegionPtr prgnSrc, CARD32 index) 716fe5e51b7Smrg{ 717fe5e51b7Smrg ScreenPtr pScreen = pParent->drawable.pScreen; 7180bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 719fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 720fe5e51b7Smrg int nbox; 721fe5e51b7Smrg BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; 722fe5e51b7Smrg DDXPointPtr pptTmp, pptNew1, pptNew2; 723fe5e51b7Smrg int xdir, ydir; 724fe5e51b7Smrg int dx, dy; 725fe5e51b7Smrg DDXPointPtr pptSrc; 726fe5e51b7Smrg int screenwidth = pScrn->virtualX; 727fe5e51b7Smrg int screenheight = pScrn->virtualY; 728fe5e51b7Smrg XAAInfoRecPtr xaa = pMga->AccelInfoRec; 729fe5e51b7Smrg 730fe5e51b7Smrg CHECK_DMA_QUIESCENT(pMga, pScrn); 731fe5e51b7Smrg 732fe5e51b7Smrg pbox = REGION_RECTS(prgnSrc); 733fe5e51b7Smrg nbox = REGION_NUM_RECTS(prgnSrc); 734fe5e51b7Smrg pboxNew1 = 0; 735fe5e51b7Smrg pptNew1 = 0; 736fe5e51b7Smrg pboxNew2 = 0; 73781f79626Smrg pptNew2 = 0; 738fe5e51b7Smrg pptSrc = &ptOldOrg; 739fe5e51b7Smrg 740fe5e51b7Smrg dx = pParent->drawable.x - ptOldOrg.x; 741fe5e51b7Smrg dy = pParent->drawable.y - ptOldOrg.y; 742fe5e51b7Smrg 743fe5e51b7Smrg /* If the copy will overlap in Y, reverse the order */ 744fe5e51b7Smrg if (dy>0) { 745fe5e51b7Smrg ydir = -1; 746fe5e51b7Smrg 747fe5e51b7Smrg if (nbox>1) { 748fe5e51b7Smrg /* Keep ordering in each band, reverse order of bands */ 7490bb88ba4Smrg pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec)*nbox); 750fe5e51b7Smrg if (!pboxNew1) return; 7510bb88ba4Smrg pptNew1 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox); 752fe5e51b7Smrg if (!pptNew1) { 7530bb88ba4Smrg free(pboxNew1); 754fe5e51b7Smrg return; 755fe5e51b7Smrg } 756fe5e51b7Smrg pboxBase = pboxNext = pbox+nbox-1; 757fe5e51b7Smrg while (pboxBase >= pbox) { 758fe5e51b7Smrg while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) 759fe5e51b7Smrg pboxNext--; 760fe5e51b7Smrg pboxTmp = pboxNext+1; 761fe5e51b7Smrg pptTmp = pptSrc + (pboxTmp - pbox); 762fe5e51b7Smrg while (pboxTmp <= pboxBase) { 763fe5e51b7Smrg *pboxNew1++ = *pboxTmp++; 764fe5e51b7Smrg *pptNew1++ = *pptTmp++; 765fe5e51b7Smrg } 766fe5e51b7Smrg pboxBase = pboxNext; 767fe5e51b7Smrg } 768fe5e51b7Smrg pboxNew1 -= nbox; 769fe5e51b7Smrg pbox = pboxNew1; 770fe5e51b7Smrg pptNew1 -= nbox; 771fe5e51b7Smrg pptSrc = pptNew1; 772fe5e51b7Smrg } 773fe5e51b7Smrg } else { 774fe5e51b7Smrg /* No changes required */ 775fe5e51b7Smrg ydir = 1; 776fe5e51b7Smrg } 777fe5e51b7Smrg 778fe5e51b7Smrg /* If the regions will overlap in X, reverse the order */ 779fe5e51b7Smrg if (dx>0) { 780fe5e51b7Smrg xdir = -1; 781fe5e51b7Smrg 782fe5e51b7Smrg if (nbox > 1) { 783fe5e51b7Smrg /*reverse orderof rects in each band */ 7840bb88ba4Smrg pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec)*nbox); 7850bb88ba4Smrg pptNew2 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox); 786fe5e51b7Smrg if (!pboxNew2 || !pptNew2) { 7870bb88ba4Smrg free(pptNew2); 7880bb88ba4Smrg free(pboxNew2); 789fe5e51b7Smrg if (pboxNew1) { 7900bb88ba4Smrg free(pptNew1); 7910bb88ba4Smrg free(pboxNew1); 792fe5e51b7Smrg } 793fe5e51b7Smrg return; 794fe5e51b7Smrg } 795fe5e51b7Smrg pboxBase = pboxNext = pbox; 796fe5e51b7Smrg while (pboxBase < pbox+nbox) { 797fe5e51b7Smrg while ((pboxNext < pbox+nbox) && 798fe5e51b7Smrg (pboxNext->y1 == pboxBase->y1)) 799fe5e51b7Smrg pboxNext++; 800fe5e51b7Smrg pboxTmp = pboxNext; 801fe5e51b7Smrg pptTmp = pptSrc + (pboxTmp - pbox); 802fe5e51b7Smrg while (pboxTmp != pboxBase) { 803fe5e51b7Smrg *pboxNew2++ = *--pboxTmp; 804fe5e51b7Smrg *pptNew2++ = *--pptTmp; 805fe5e51b7Smrg } 806fe5e51b7Smrg pboxBase = pboxNext; 807fe5e51b7Smrg } 808fe5e51b7Smrg pboxNew2 -= nbox; 809fe5e51b7Smrg pbox = pboxNew2; 810fe5e51b7Smrg pptNew2 -= nbox; 811fe5e51b7Smrg pptSrc = pptNew2; 812fe5e51b7Smrg } 813fe5e51b7Smrg } else { 814fe5e51b7Smrg /* No changes are needed */ 815fe5e51b7Smrg xdir = 1; 816fe5e51b7Smrg } 817fe5e51b7Smrg 818fe5e51b7Smrg xaa->SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1); 819fe5e51b7Smrg for ( ; nbox-- ; pbox++) { 820fe5e51b7Smrg int x1 = pbox->x1; 821fe5e51b7Smrg int y1 = pbox->y1; 822fe5e51b7Smrg int destx = x1 + dx; 823fe5e51b7Smrg int desty = y1 + dy; 824fe5e51b7Smrg int w = pbox->x2 - x1 + 1; 825fe5e51b7Smrg int h = pbox->y2 - y1 + 1; 826fe5e51b7Smrg 827fe5e51b7Smrg if ( destx < 0 ) x1 -= destx, w += destx, destx = 0; 828fe5e51b7Smrg if ( desty < 0 ) y1 -= desty, h += desty, desty = 0; 829fe5e51b7Smrg if ( destx + w > screenwidth ) w = screenwidth - destx; 830fe5e51b7Smrg if ( desty + h > screenheight ) h = screenheight - desty; 831fe5e51b7Smrg if ( w <= 0 ) continue; 832fe5e51b7Smrg if ( h <= 0 ) continue; 833fe5e51b7Smrg 834fe5e51b7Smrg MGASelectBuffer(pScrn, MGA_BACK); 835fe5e51b7Smrg xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); 836fe5e51b7Smrg MGASelectBuffer(pScrn, MGA_DEPTH); 837fe5e51b7Smrg xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); 838fe5e51b7Smrg } 839fe5e51b7Smrg MGASelectBuffer(pScrn, MGA_FRONT); 840fe5e51b7Smrg 841fe5e51b7Smrg if (pboxNew2) { 8420bb88ba4Smrg free(pptNew2); 8430bb88ba4Smrg free(pboxNew2); 844fe5e51b7Smrg } 845fe5e51b7Smrg if (pboxNew1) { 8460bb88ba4Smrg free(pptNew1); 8470bb88ba4Smrg free(pboxNew1); 848fe5e51b7Smrg } 849fe5e51b7Smrg 850fe5e51b7Smrg pMga->AccelInfoRec->NeedToSync = TRUE; 851fe5e51b7Smrg 852fe5e51b7Smrg} 853fe5e51b7Smrg#endif 854fe5e51b7Smrg 855fe5e51b7Smrgstatic void MGADRIMoveBuffersEXA(WindowPtr pParent, DDXPointRec ptOldOrg, 856fe5e51b7Smrg RegionPtr prgnSrc, CARD32 index) 857fe5e51b7Smrg{ 858fe5e51b7Smrg /* FIXME */ 859fe5e51b7Smrg} 860fe5e51b7Smrg 861fe5e51b7SmrgBool MGADRIScreenInit( ScreenPtr pScreen ) 862fe5e51b7Smrg{ 8630bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 864fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 865fe5e51b7Smrg DRIInfoPtr pDRIInfo; 866fe5e51b7Smrg MGADRIPtr pMGADRI; 867fe5e51b7Smrg MGADRIServerPrivatePtr pMGADRIServer; 868fe5e51b7Smrg 869fe5e51b7Smrg if (!pMga->chip_attribs->dri_capable) { 870fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] Direct rendering only supported with G200/G400/G450/G550.\n"); 871fe5e51b7Smrg return FALSE; 872fe5e51b7Smrg } 873fe5e51b7Smrg 87481f79626Smrg /* Check that the DRI, and DRM modules have been loaded by testing 875fe5e51b7Smrg * for canonical symbols in each module. 876fe5e51b7Smrg */ 877fe5e51b7Smrg if ( !xf86LoaderCheckSymbol( "drmAvailable" ) ) return FALSE; 878fe5e51b7Smrg if ( !xf86LoaderCheckSymbol( "DRIQueryVersion" ) ) { 879fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 880fe5e51b7Smrg "[dri] MGADRIScreenInit failed (libdri.a too old)\n" ); 881fe5e51b7Smrg return FALSE; 882fe5e51b7Smrg } 883fe5e51b7Smrg 884fe5e51b7Smrg /* Check the DRI version */ 885fe5e51b7Smrg { 886fe5e51b7Smrg int major, minor, patch; 887fe5e51b7Smrg DRIQueryVersion( &major, &minor, &patch ); 888fe5e51b7Smrg if ( major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ) { 889fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 890fe5e51b7Smrg "[dri] MGADRIScreenInit failed because of a version mismatch.\n" 891fe5e51b7Smrg "[dri] libdri version = %d.%d.%d but version %d.%d.x is needed.\n" 892fe5e51b7Smrg "[dri] Disabling the DRI.\n", 893fe5e51b7Smrg major, minor, patch, 894fe5e51b7Smrg DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION ); 895fe5e51b7Smrg return FALSE; 896fe5e51b7Smrg } 897fe5e51b7Smrg } 898fe5e51b7Smrg 899fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_INFO, 900fe5e51b7Smrg "[drm] bpp: %d depth: %d\n", 901fe5e51b7Smrg pScrn->bitsPerPixel, pScrn->depth ); 902fe5e51b7Smrg 903fe5e51b7Smrg if ( (pScrn->bitsPerPixel / 8) != 2 && 904fe5e51b7Smrg (pScrn->bitsPerPixel / 8) != 4 ) { 905fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 906fe5e51b7Smrg "[dri] Direct rendering only supported in 16 and 32 bpp modes\n" ); 907fe5e51b7Smrg return FALSE; 908fe5e51b7Smrg } 909fe5e51b7Smrg 910fe5e51b7Smrg pDRIInfo = DRICreateInfoRec(); 911fe5e51b7Smrg if ( !pDRIInfo ) { 912fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 913fe5e51b7Smrg "[dri] DRICreateInfoRec() failed\n" ); 914fe5e51b7Smrg return FALSE; 915fe5e51b7Smrg } 916fe5e51b7Smrg pMga->pDRIInfo = pDRIInfo; 917fe5e51b7Smrg 918fe5e51b7Smrg pDRIInfo->drmDriverName = MGAKernelDriverName; 919fe5e51b7Smrg pDRIInfo->clientDriverName = MGAClientDriverName; 920fe5e51b7Smrg if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 921fe5e51b7Smrg pDRIInfo->busIdString = DRICreatePCIBusID(pMga->PciInfo); 922fe5e51b7Smrg } else { 9230bb88ba4Smrg pDRIInfo->busIdString = malloc(64); 924fe5e51b7Smrg sprintf( pDRIInfo->busIdString, "PCI:%d:%d:%d", 925fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS 926fe5e51b7Smrg ((pMga->PciInfo->domain << 8) | pMga->PciInfo->bus), 927fe5e51b7Smrg pMga->PciInfo->dev, pMga->PciInfo->func 928fe5e51b7Smrg#else 929fe5e51b7Smrg ((pciConfigPtr)pMga->PciInfo->thisCard)->busnum, 930fe5e51b7Smrg ((pciConfigPtr)pMga->PciInfo->thisCard)->devnum, 931fe5e51b7Smrg ((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum 932fe5e51b7Smrg#endif 933fe5e51b7Smrg ); 934fe5e51b7Smrg } 935fe5e51b7Smrg pDRIInfo->ddxDriverMajorVersion = PACKAGE_VERSION_MAJOR; 936fe5e51b7Smrg pDRIInfo->ddxDriverMinorVersion = PACKAGE_VERSION_MINOR; 937fe5e51b7Smrg pDRIInfo->ddxDriverPatchVersion = PACKAGE_VERSION_PATCHLEVEL; 938fe5e51b7Smrg pDRIInfo->frameBufferPhysicalAddress = (void *) pMga->FbAddress; 939fe5e51b7Smrg pDRIInfo->frameBufferSize = pMga->FbMapSize; 940fe5e51b7Smrg pDRIInfo->frameBufferStride = pScrn->displayWidth*(pScrn->bitsPerPixel/8); 941fe5e51b7Smrg pDRIInfo->ddxDrawableTableEntry = MGA_MAX_DRAWABLES; 942fe5e51b7Smrg 943fe5e51b7Smrg pDRIInfo->createDummyCtx = TRUE; 944fe5e51b7Smrg pDRIInfo->createDummyCtxPriv = FALSE; 945fe5e51b7Smrg 946fe5e51b7Smrg if ( SAREA_MAX_DRAWABLES < MGA_MAX_DRAWABLES ) { 947fe5e51b7Smrg pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; 948fe5e51b7Smrg } else { 949fe5e51b7Smrg pDRIInfo->maxDrawableTableEntry = MGA_MAX_DRAWABLES; 950fe5e51b7Smrg } 951fe5e51b7Smrg 952fe5e51b7Smrg /* For now the mapping works by using a fixed size defined 953fe5e51b7Smrg * in the SAREA header. 954fe5e51b7Smrg */ 955fe5e51b7Smrg if ( sizeof(XF86DRISAREARec) + sizeof(MGASAREAPrivRec) > SAREA_MAX ) { 956fe5e51b7Smrg xf86DrvMsg( pScrn->scrnIndex, X_ERROR, 957fe5e51b7Smrg "[drm] Data does not fit in SAREA\n" ); 958fe5e51b7Smrg return FALSE; 959fe5e51b7Smrg } 960fe5e51b7Smrg 961fe5e51b7Smrg xf86DrvMsg( pScrn->scrnIndex, X_INFO, 962fe5e51b7Smrg "[drm] Sarea %d+%d: %d\n", 963fe5e51b7Smrg (int)sizeof(XF86DRISAREARec), (int)sizeof(MGASAREAPrivRec), 964fe5e51b7Smrg (int)sizeof(XF86DRISAREARec) + (int)sizeof(MGASAREAPrivRec) ); 965fe5e51b7Smrg 966fe5e51b7Smrg pDRIInfo->SAREASize = SAREA_MAX; 967fe5e51b7Smrg 9680bb88ba4Smrg pMGADRI = (MGADRIPtr)calloc( sizeof(MGADRIRec), 1 ); 969fe5e51b7Smrg if ( !pMGADRI ) { 970fe5e51b7Smrg DRIDestroyInfoRec( pMga->pDRIInfo ); 971fe5e51b7Smrg pMga->pDRIInfo = 0; 972fe5e51b7Smrg xf86DrvMsg( pScrn->scrnIndex, X_ERROR, 973fe5e51b7Smrg "[drm] Failed to allocate memory for private record\n" ); 974fe5e51b7Smrg return FALSE; 975fe5e51b7Smrg } 976fe5e51b7Smrg 977fe5e51b7Smrg pMGADRIServer = (MGADRIServerPrivatePtr) 9780bb88ba4Smrg calloc( sizeof(MGADRIServerPrivateRec), 1 ); 979fe5e51b7Smrg if ( !pMGADRIServer ) { 9800bb88ba4Smrg free( pMGADRI ); 981fe5e51b7Smrg DRIDestroyInfoRec( pMga->pDRIInfo ); 982fe5e51b7Smrg pMga->pDRIInfo = 0; 983fe5e51b7Smrg xf86DrvMsg( pScrn->scrnIndex, X_ERROR, 984fe5e51b7Smrg "[drm] Failed to allocate memory for private record\n" ); 985fe5e51b7Smrg return FALSE; 986fe5e51b7Smrg } 987fe5e51b7Smrg pMga->DRIServerInfo = pMGADRIServer; 988fe5e51b7Smrg 989fe5e51b7Smrg pDRIInfo->devPrivate = pMGADRI; 990fe5e51b7Smrg pDRIInfo->devPrivateSize = sizeof(MGADRIRec); 991fe5e51b7Smrg pDRIInfo->contextSize = sizeof(MGADRIContextRec); 992fe5e51b7Smrg 993fe5e51b7Smrg pDRIInfo->CreateContext = MGACreateContext; 994fe5e51b7Smrg pDRIInfo->DestroyContext = MGADestroyContext; 995fe5e51b7Smrg if ( xf86IsEntityShared( pScrn->entityList[0] ) 996fe5e51b7Smrg && pMga->DualHeadEnabled) { 997fe5e51b7Smrg pDRIInfo->SwapContext = MGADRISwapContextShared; 998fe5e51b7Smrg } else { 999fe5e51b7Smrg pDRIInfo->SwapContext = MGADRISwapContext; 1000fe5e51b7Smrg } 1001fe5e51b7Smrg 10020bb88ba4Smrg pDRIInfo->InitBuffers = MGADRIInitBuffersEXA; 10030bb88ba4Smrg pDRIInfo->MoveBuffers = MGADRIMoveBuffersEXA; 1004fe5e51b7Smrg#ifdef USE_EXA 1005fe5e51b7Smrg if (pMga->Exa) { 1006fe5e51b7Smrg pDRIInfo->InitBuffers = MGADRIInitBuffersEXA; 1007fe5e51b7Smrg pDRIInfo->MoveBuffers = MGADRIMoveBuffersEXA; 1008fe5e51b7Smrg } else { 1009fe5e51b7Smrg#endif 1010fe5e51b7Smrg#ifdef USE_XAA 1011fe5e51b7Smrg pDRIInfo->InitBuffers = MGADRIInitBuffersXAA; 1012fe5e51b7Smrg pDRIInfo->MoveBuffers = MGADRIMoveBuffersXAA; 1013fe5e51b7Smrg#endif 1014fe5e51b7Smrg#ifdef USE_EXA 1015fe5e51b7Smrg } 1016fe5e51b7Smrg#endif 1017fe5e51b7Smrg 1018fe5e51b7Smrg pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 1019fe5e51b7Smrg 1020fe5e51b7Smrg if ( !DRIScreenInit( pScreen, pDRIInfo, &pMga->drmFD ) ) { 10210bb88ba4Smrg free( pMGADRIServer ); 1022fe5e51b7Smrg pMga->DRIServerInfo = 0; 10230bb88ba4Smrg free( pDRIInfo->devPrivate ); 1024fe5e51b7Smrg pDRIInfo->devPrivate = 0; 1025fe5e51b7Smrg DRIDestroyInfoRec( pMga->pDRIInfo ); 1026fe5e51b7Smrg pMga->pDRIInfo = 0; 1027fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 1028fe5e51b7Smrg "[drm] DRIScreenInit failed. Disabling DRI.\n" ); 1029fe5e51b7Smrg return FALSE; 1030fe5e51b7Smrg } 1031fe5e51b7Smrg 1032fe5e51b7Smrg /* Check the DRM versioning */ 1033fe5e51b7Smrg { 1034fe5e51b7Smrg drmVersionPtr version; 1035fe5e51b7Smrg 1036fe5e51b7Smrg /* Check the DRM lib version. 1037fe5e51b7Smrg drmGetLibVersion was not supported in version 1.0, so check for 1038fe5e51b7Smrg symbol first to avoid possible crash or hang. 1039fe5e51b7Smrg */ 1040fe5e51b7Smrg if (xf86LoaderCheckSymbol("drmGetLibVersion")) { 1041fe5e51b7Smrg version = drmGetLibVersion(pMga->drmFD); 1042fe5e51b7Smrg } 1043fe5e51b7Smrg else { 1044fe5e51b7Smrg /* drmlib version 1.0.0 didn't have the drmGetLibVersion 1045fe5e51b7Smrg entry point. Fake it by allocating a version record 1046fe5e51b7Smrg via drmGetVersion and changing it to version 1.0.0 1047fe5e51b7Smrg */ 1048fe5e51b7Smrg version = drmGetVersion(pMga->drmFD); 1049fe5e51b7Smrg version->version_major = 1; 1050fe5e51b7Smrg version->version_minor = 0; 1051fe5e51b7Smrg version->version_patchlevel = 0; 1052fe5e51b7Smrg } 1053fe5e51b7Smrg 1054fe5e51b7Smrg if (version) { 1055fe5e51b7Smrg if (version->version_major != 1 || 1056fe5e51b7Smrg version->version_minor < 1) { 1057fe5e51b7Smrg /* incompatible drm library version */ 1058fe5e51b7Smrg xf86DrvMsg(pScreen->myNum, X_ERROR, 1059fe5e51b7Smrg "[dri] MGADRIScreenInit failed because of a version mismatch.\n" 1060fe5e51b7Smrg "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n" 1061fe5e51b7Smrg "[dri] Disabling DRI.\n", 1062fe5e51b7Smrg version->version_major, 1063fe5e51b7Smrg version->version_minor, 1064fe5e51b7Smrg version->version_patchlevel); 1065fe5e51b7Smrg drmFreeVersion(version); 1066fe5e51b7Smrg MGADRICloseScreen( pScreen ); /* FIXME: ??? */ 1067fe5e51b7Smrg return FALSE; 1068fe5e51b7Smrg } 1069fe5e51b7Smrg drmFreeVersion(version); 1070fe5e51b7Smrg } 1071fe5e51b7Smrg 1072fe5e51b7Smrg /* Check the MGA DRM version */ 1073fe5e51b7Smrg version = drmGetVersion(pMga->drmFD); 1074fe5e51b7Smrg if ( version ) { 1075fe5e51b7Smrg if ( version->version_major != 3 || 1076fe5e51b7Smrg version->version_minor < 0 ) { 1077fe5e51b7Smrg /* incompatible drm version */ 1078fe5e51b7Smrg xf86DrvMsg( pScreen->myNum, X_ERROR, 1079fe5e51b7Smrg "[dri] MGADRIScreenInit failed because of a version mismatch.\n" 1080fe5e51b7Smrg "[dri] mga.o kernel module version is %d.%d.%d but version 3.0.x is needed.\n" 1081fe5e51b7Smrg "[dri] Disabling DRI.\n", 1082fe5e51b7Smrg version->version_major, 1083fe5e51b7Smrg version->version_minor, 1084fe5e51b7Smrg version->version_patchlevel ); 1085fe5e51b7Smrg drmFreeVersion( version ); 1086fe5e51b7Smrg MGADRICloseScreen( pScreen ); /* FIXME: ??? */ 1087fe5e51b7Smrg return FALSE; 1088fe5e51b7Smrg } 1089fe5e51b7Smrg pMGADRIServer->drm_version_major = version->version_major; 1090fe5e51b7Smrg pMGADRIServer->drm_version_minor = version->version_minor; 1091fe5e51b7Smrg 1092fe5e51b7Smrg drmFreeVersion( version ); 1093fe5e51b7Smrg } 1094fe5e51b7Smrg } 1095fe5e51b7Smrg 1096fe5e51b7Smrg if ( (pMga->bios.host_interface == MGA_HOST_PCI) && 1097fe5e51b7Smrg ((pMGADRIServer->drm_version_minor < 2) || pMga->useOldDmaInit) ) { 1098fe5e51b7Smrg /* PCI cards are supported if the DRM version is at least 3.2 and the 1099fe5e51b7Smrg * user has not explicitly disabled the new DMA init path (i.e., to 1100fe5e51b7Smrg * support old version of the client-side driver that don't use the 1101fe5e51b7Smrg * new features of the 3.2 DRM). 1102fe5e51b7Smrg */ 1103fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1104fe5e51b7Smrg "[drm] Direct rendering on PCI cards requires DRM version 3.2 or higher\n"); 1105fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1106fe5e51b7Smrg "[drm] and a recent client-side driver. Also make sure that 'OldDmaInit'\n"); 1107fe5e51b7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1108fe5e51b7Smrg "[drm] is not selected in xorg.conf.'\n"); 1109fe5e51b7Smrg return FALSE; 1110fe5e51b7Smrg } 1111fe5e51b7Smrg 1112fe5e51b7Smrg 1113fe5e51b7Smrg if ( !MGADRIBootstrapDMA( pScreen ) ) { 1114fe5e51b7Smrg DRICloseScreen( pScreen ); 1115fe5e51b7Smrg return FALSE; 1116fe5e51b7Smrg } 1117fe5e51b7Smrg 1118fe5e51b7Smrg { 1119fe5e51b7Smrg void *scratch_ptr; 1120fe5e51b7Smrg int scratch_int; 1121fe5e51b7Smrg 1122fe5e51b7Smrg DRIGetDeviceInfo(pScreen, &pMGADRIServer->fb.handle, 1123fe5e51b7Smrg &scratch_int, &scratch_int, 1124fe5e51b7Smrg &scratch_int, &scratch_int, 1125fe5e51b7Smrg &scratch_ptr); 1126fe5e51b7Smrg } 1127fe5e51b7Smrg 1128fe5e51b7Smrg xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n" ); 1129fe5e51b7Smrg 1130fe5e51b7Smrg return TRUE; 1131fe5e51b7Smrg} 1132fe5e51b7Smrg 1133fe5e51b7Smrg 1134fe5e51b7SmrgBool MGADRIFinishScreenInit( ScreenPtr pScreen ) 1135fe5e51b7Smrg{ 11360bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1137fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1138fe5e51b7Smrg MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo; 1139fe5e51b7Smrg MGADRIPtr pMGADRI; 1140fe5e51b7Smrg int i; 1141fe5e51b7Smrg 1142fe5e51b7Smrg if ( !pMga->pDRIInfo ) 1143fe5e51b7Smrg return FALSE; 1144fe5e51b7Smrg 1145fe5e51b7Smrg pMGADRI = (MGADRIPtr)pMga->pDRIInfo->devPrivate; 1146fe5e51b7Smrg 1147fe5e51b7Smrg pMga->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 1148fe5e51b7Smrg 1149fe5e51b7Smrg /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit 1150fe5e51b7Smrg * because *DRIKernelInit requires that the hardware lock is held by 1151fe5e51b7Smrg * the X server, and the first time the hardware lock is grabbed is 1152fe5e51b7Smrg * in DRIFinishScreenInit. 1153fe5e51b7Smrg */ 1154fe5e51b7Smrg if ( !DRIFinishScreenInit( pScreen ) ) { 1155fe5e51b7Smrg MGADRICloseScreen( pScreen ); 1156fe5e51b7Smrg return FALSE; 1157fe5e51b7Smrg } 1158fe5e51b7Smrg 1159fe5e51b7Smrg if ( !MGADRIKernelInit( pScreen ) ) { 1160fe5e51b7Smrg MGADRICloseScreen( pScreen ); 1161fe5e51b7Smrg return FALSE; 1162fe5e51b7Smrg } 1163fe5e51b7Smrg 1164fe5e51b7Smrg if ( !MGADRIBuffersInit( pScreen ) ) { 1165fe5e51b7Smrg MGADRICloseScreen( pScreen ); 1166fe5e51b7Smrg return FALSE; 1167fe5e51b7Smrg } 1168fe5e51b7Smrg 1169fe5e51b7Smrg MGADRIIrqInit(pMga, pScreen); 1170fe5e51b7Smrg 1171fe5e51b7Smrg pMGADRI->chipset = pMga->chip_attribs->dri_chipset; 1172fe5e51b7Smrg pMGADRI->width = pScrn->virtualX; 1173fe5e51b7Smrg pMGADRI->height = pScrn->virtualY; 1174fe5e51b7Smrg pMGADRI->cpp = pScrn->bitsPerPixel / 8; 1175fe5e51b7Smrg 1176fe5e51b7Smrg pMGADRI->agpMode = pMga->agpMode; 1177fe5e51b7Smrg 1178fe5e51b7Smrg pMGADRI->frontOffset = pMGADRIServer->frontOffset; 1179fe5e51b7Smrg pMGADRI->frontPitch = pMGADRIServer->frontPitch; 1180fe5e51b7Smrg pMGADRI->backOffset = pMGADRIServer->backOffset; 1181fe5e51b7Smrg pMGADRI->backPitch = pMGADRIServer->backPitch; 1182fe5e51b7Smrg pMGADRI->depthOffset = pMGADRIServer->depthOffset; 1183fe5e51b7Smrg pMGADRI->depthPitch = pMGADRIServer->depthPitch; 1184fe5e51b7Smrg pMGADRI->textureOffset = pMGADRIServer->textureOffset; 1185fe5e51b7Smrg pMGADRI->textureSize = pMGADRIServer->textureSize; 1186fe5e51b7Smrg 1187fe5e51b7Smrg pMGADRI->agpTextureOffset = (unsigned int)pMGADRIServer->agpTextures.handle; 1188fe5e51b7Smrg pMGADRI->agpTextureSize = (unsigned int)pMGADRIServer->agpTextures.size; 1189fe5e51b7Smrg 1190fe5e51b7Smrg pMGADRI->sarea_priv_offset = sizeof(XF86DRISAREARec); 1191fe5e51b7Smrg 1192fe5e51b7Smrg 1193fe5e51b7Smrg /* Newer versions of the client-side driver do not need these if the 1194fe5e51b7Smrg * kernel version is high enough to support interrupt based waiting. 1195fe5e51b7Smrg */ 1196fe5e51b7Smrg 1197fe5e51b7Smrg pMGADRI->registers.handle = pMGADRIServer->registers.handle; 1198fe5e51b7Smrg pMGADRI->registers.size = pMGADRIServer->registers.size; 1199fe5e51b7Smrg pMGADRI->primary.handle = pMGADRIServer->primary.handle; 1200fe5e51b7Smrg pMGADRI->primary.size = pMGADRIServer->primary.size; 1201fe5e51b7Smrg 1202fe5e51b7Smrg 1203fe5e51b7Smrg /* These are no longer used by the client-side DRI driver. They should 1204fe5e51b7Smrg * be removed in the next release (i.e., 6.9 / 7.0). 1205fe5e51b7Smrg */ 1206fe5e51b7Smrg 1207fe5e51b7Smrg pMGADRI->status.handle = pMGADRIServer->status.handle; 1208fe5e51b7Smrg pMGADRI->status.size = pMGADRIServer->status.size; 1209fe5e51b7Smrg pMGADRI->buffers.handle = pMGADRIServer->buffers.handle; 1210fe5e51b7Smrg pMGADRI->buffers.size = pMGADRIServer->buffers.size; 1211fe5e51b7Smrg 1212fe5e51b7Smrg i = mylog2( pMGADRI->textureSize / MGA_NR_TEX_REGIONS ); 1213fe5e51b7Smrg if ( i < MGA_LOG_MIN_TEX_REGION_SIZE ) 1214fe5e51b7Smrg i = MGA_LOG_MIN_TEX_REGION_SIZE; 1215fe5e51b7Smrg 1216fe5e51b7Smrg pMGADRI->logTextureGranularity = i; 1217fe5e51b7Smrg pMGADRI->textureSize = (pMGADRI->textureSize >> i) << i; /* truncate */ 1218fe5e51b7Smrg 1219fe5e51b7Smrg i = mylog2( pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS ); 1220fe5e51b7Smrg if ( i < MGA_LOG_MIN_TEX_REGION_SIZE ) 1221fe5e51b7Smrg i = MGA_LOG_MIN_TEX_REGION_SIZE; 1222fe5e51b7Smrg 1223fe5e51b7Smrg pMGADRI->logAgpTextureGranularity = i; 1224fe5e51b7Smrg 1225fe5e51b7Smrg return TRUE; 1226fe5e51b7Smrg} 1227fe5e51b7Smrg 1228fe5e51b7Smrg 1229fe5e51b7Smrgvoid MGADRICloseScreen( ScreenPtr pScreen ) 1230fe5e51b7Smrg{ 12310bb88ba4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1232fe5e51b7Smrg MGAPtr pMga = MGAPTR(pScrn); 1233fe5e51b7Smrg MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo; 1234fe5e51b7Smrg drm_mga_init_t init; 1235fe5e51b7Smrg 1236fe5e51b7Smrg if ( pMGADRIServer->drmBuffers ) { 1237fe5e51b7Smrg drmUnmapBufs( pMGADRIServer->drmBuffers ); 1238fe5e51b7Smrg pMGADRIServer->drmBuffers = NULL; 1239fe5e51b7Smrg } 1240fe5e51b7Smrg 1241fe5e51b7Smrg if (pMga->irq) { 1242fe5e51b7Smrg drmCtlUninstHandler(pMga->drmFD); 1243fe5e51b7Smrg pMga->irq = 0; 1244fe5e51b7Smrg pMga->reg_ien = 0; 1245fe5e51b7Smrg } 1246fe5e51b7Smrg 1247fe5e51b7Smrg /* Cleanup DMA */ 1248fe5e51b7Smrg memset( &init, 0, sizeof(drm_mga_init_t) ); 1249fe5e51b7Smrg init.func = MGA_CLEANUP_DMA; 1250fe5e51b7Smrg drmCommandWrite( pMga->drmFD, DRM_MGA_INIT, &init, sizeof(drm_mga_init_t) ); 1251fe5e51b7Smrg 1252fe5e51b7Smrg if ( pMGADRIServer->agp.handle != DRM_AGP_NO_HANDLE ) { 1253fe5e51b7Smrg drmAgpUnbind( pMga->drmFD, pMGADRIServer->agp.handle ); 1254fe5e51b7Smrg drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle ); 1255fe5e51b7Smrg pMGADRIServer->agp.handle = DRM_AGP_NO_HANDLE; 1256fe5e51b7Smrg drmAgpRelease( pMga->drmFD ); 1257fe5e51b7Smrg } 1258fe5e51b7Smrg 1259fe5e51b7Smrg DRICloseScreen( pScreen ); 1260fe5e51b7Smrg 1261fe5e51b7Smrg if ( pMga->pDRIInfo ) { 12620bb88ba4Smrg free(pMga->pDRIInfo->devPrivate); 12630bb88ba4Smrg pMga->pDRIInfo->devPrivate = 0; 1264fe5e51b7Smrg DRIDestroyInfoRec( pMga->pDRIInfo ); 1265fe5e51b7Smrg pMga->pDRIInfo = 0; 1266fe5e51b7Smrg } 12670bb88ba4Smrg free(pMga->DRIServerInfo); 12680bb88ba4Smrg pMga->DRIServerInfo = 0; 1269fe5e51b7Smrg} 1270