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