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