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