atidri.c revision 32b578d3
1/* -*- mode: c; c-basic-offset: 3 -*- */ 2/* 3 * Copyright 2000 Gareth Hughes 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28/* 29 * Authors: 30 * Gareth Hughes <gareth@valinux.com> 31 * Leif Delgass <ldelgass@retinalburn.net> 32 */ 33 34#include <string.h> 35#include <stdio.h> 36#include <unistd.h> 37 38/* Driver data structures */ 39#include "ati.h" 40#include "atibus.h" 41#include "atidri.h" 42#include "atiregs.h" 43#include "atistruct.h" 44 45#include "atimach64io.h" 46#include "atimach64version.h" 47#include "mach64_dri.h" 48#include "mach64_common.h" 49#include "mach64_sarea.h" 50 51/* X and server generic header files */ 52#include "xf86.h" 53#include "windowstr.h" 54 55/* GLX/DRI/DRM definitions */ 56#define _XF86DRI_SERVER_ 57#include "GL/glxtokens.h" 58#include "sarea.h" 59 60static char ATIKernelDriverName[] = "mach64"; 61static char ATIClientDriverName[] = "mach64"; 62 63/* Initialize the visual configs that are supported by the hardware. 64 * These are combined with the visual configs that the indirect 65 * rendering core supports, and the intersection is exported to the 66 * client. 67 */ 68static Bool ATIInitVisualConfigs( ScreenPtr pScreen ) 69{ 70 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 71 ATIPtr pATI = ATIPTR(pScreenInfo); 72 int numConfigs = 0; 73 __GLXvisualConfig *pConfigs = NULL; 74 ATIConfigPrivPtr pATIConfigs = NULL; 75 ATIConfigPrivPtr *pATIConfigPtrs = NULL; 76 int i, accum, stencil, db; 77 78 switch ( pATI->bitsPerPixel ) { 79 case 8: /* 8bpp mode is not support */ 80 case 15: /* FIXME */ 81 case 24: /* FIXME */ 82 xf86DrvMsg(pScreen->myNum, X_ERROR, 83 "[dri] ATIInitVisualConfigs failed (%d bpp not supported). " 84 "Disabling DRI.\n", pATI->bitsPerPixel); 85 return FALSE; 86 87#define ATI_USE_ACCUM 1 88#define ATI_USE_STENCIL 1 89 90 case 16: 91 92 if ( pATI->depth != 16) { 93 xf86DrvMsg(pScreen->myNum, X_ERROR, 94 "[dri] ATIInitVisualConfigs failed (depth %d at 16 bpp not supported). " 95 "Disabling DRI.\n", pATI->depth); 96 return FALSE; 97 } 98 99 numConfigs = 1; 100 if ( ATI_USE_ACCUM ) numConfigs *= 2; 101 if ( ATI_USE_STENCIL ) numConfigs *= 2; 102 numConfigs *= 2; /* single- and double-buffered */ 103 104 pConfigs = (__GLXvisualConfig*) 105 xnfcalloc( sizeof(__GLXvisualConfig), numConfigs ); 106 if ( !pConfigs ) { 107 return FALSE; 108 } 109 pATIConfigs = (ATIConfigPrivPtr) 110 xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs ); 111 if ( !pATIConfigs ) { 112 xfree( pConfigs ); 113 return FALSE; 114 } 115 pATIConfigPtrs = (ATIConfigPrivPtr*) 116 xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs ); 117 if ( !pATIConfigPtrs ) { 118 xfree( pConfigs ); 119 xfree( pATIConfigs ); 120 return FALSE; 121 } 122 123 i = 0; 124 for (db = 1; db >= 0; db--) { 125 for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) { 126 for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) { 127 pATIConfigPtrs[i] = &pATIConfigs[i]; 128 129 pConfigs[i].vid = -1; 130 pConfigs[i].class = -1; 131 pConfigs[i].rgba = TRUE; 132 pConfigs[i].redSize = 5; 133 pConfigs[i].greenSize = 6; 134 pConfigs[i].blueSize = 5; 135 pConfigs[i].alphaSize = 0; 136 pConfigs[i].redMask = 0x0000F800; 137 pConfigs[i].greenMask = 0x000007E0; 138 pConfigs[i].blueMask = 0x0000001F; 139 pConfigs[i].alphaMask = 0x00000000; 140 if ( accum ) { /* Simulated in software */ 141 pConfigs[i].accumRedSize = 16; 142 pConfigs[i].accumGreenSize = 16; 143 pConfigs[i].accumBlueSize = 16; 144 pConfigs[i].accumAlphaSize = 0; 145 } else { 146 pConfigs[i].accumRedSize = 0; 147 pConfigs[i].accumGreenSize = 0; 148 pConfigs[i].accumBlueSize = 0; 149 pConfigs[i].accumAlphaSize = 0; 150 } 151 pConfigs[i].doubleBuffer = db ? TRUE : FALSE; 152 pConfigs[i].stereo = FALSE; 153 pConfigs[i].bufferSize = 16; 154 pConfigs[i].depthSize = 16; 155 if ( stencil ) { /* Simulated in software */ 156 pConfigs[i].stencilSize = 8; 157 } else { 158 pConfigs[i].stencilSize = 0; 159 } 160 pConfigs[i].auxBuffers = 0; 161 pConfigs[i].level = 0; 162 if ( accum || stencil ) { 163 pConfigs[i].visualRating = GLX_SLOW_CONFIG; 164 } else { 165 pConfigs[i].visualRating = GLX_NONE; 166 } 167 pConfigs[i].transparentPixel = GLX_NONE; 168 pConfigs[i].transparentRed = 0; 169 pConfigs[i].transparentGreen = 0; 170 pConfigs[i].transparentBlue = 0; 171 pConfigs[i].transparentAlpha = 0; 172 pConfigs[i].transparentIndex = 0; 173 i++; 174 } 175 } 176 } 177 break; 178 179 case 32: 180 numConfigs = 1; 181 if ( ATI_USE_ACCUM ) numConfigs *= 2; 182 if ( ATI_USE_STENCIL ) numConfigs *= 2; 183 numConfigs *= 2; /* single- and double-buffered */ 184 185 pConfigs = (__GLXvisualConfig*) 186 xnfcalloc( sizeof(__GLXvisualConfig), numConfigs ); 187 if ( !pConfigs ) { 188 return FALSE; 189 } 190 pATIConfigs = (ATIConfigPrivPtr) 191 xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs ); 192 if ( !pATIConfigs ) { 193 xfree( pConfigs ); 194 return FALSE; 195 } 196 pATIConfigPtrs = (ATIConfigPrivPtr*) 197 xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs ); 198 if ( !pATIConfigPtrs ) { 199 xfree( pConfigs ); 200 xfree( pATIConfigs ); 201 return FALSE; 202 } 203 204 i = 0; 205 for (db = 1; db >= 0; db--) { 206 for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) { 207 for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) { 208 pATIConfigPtrs[i] = &pATIConfigs[i]; 209 210 pConfigs[i].vid = -1; 211 pConfigs[i].class = -1; 212 pConfigs[i].rgba = TRUE; 213 pConfigs[i].redSize = 8; 214 pConfigs[i].greenSize = 8; 215 pConfigs[i].blueSize = 8; 216 pConfigs[i].alphaSize = 0; 217 pConfigs[i].redMask = 0x00FF0000; 218 pConfigs[i].greenMask = 0x0000FF00; 219 pConfigs[i].blueMask = 0x000000FF; 220 pConfigs[i].alphaMask = 0x00000000; 221 if ( accum ) { /* Simulated in software */ 222 pConfigs[i].accumRedSize = 16; 223 pConfigs[i].accumGreenSize = 16; 224 pConfigs[i].accumBlueSize = 16; 225 pConfigs[i].accumAlphaSize = 0; 226 } else { 227 pConfigs[i].accumRedSize = 0; 228 pConfigs[i].accumGreenSize = 0; 229 pConfigs[i].accumBlueSize = 0; 230 pConfigs[i].accumAlphaSize = 0; 231 } 232 pConfigs[i].doubleBuffer = db ? TRUE : FALSE; 233 pConfigs[i].stereo = FALSE; 234 pConfigs[i].bufferSize = 24; 235 if ( stencil ) { /* Simulated in software */ 236 pConfigs[i].depthSize = 16; 237 pConfigs[i].stencilSize = 8; 238 } else { 239 pConfigs[i].depthSize = 16; 240 pConfigs[i].stencilSize = 0; 241 } 242 pConfigs[i].auxBuffers = 0; 243 pConfigs[i].level = 0; 244 if ( accum || stencil ) { 245 pConfigs[i].visualRating = GLX_SLOW_CONFIG; 246 } else { 247 pConfigs[i].visualRating = GLX_NONE; 248 } 249 pConfigs[i].transparentPixel = GLX_NONE; 250 pConfigs[i].transparentRed = 0; 251 pConfigs[i].transparentGreen = 0; 252 pConfigs[i].transparentBlue = 0; 253 pConfigs[i].transparentAlpha = 0; 254 pConfigs[i].transparentIndex = 0; 255 i++; 256 } 257 } 258 } 259 break; 260 } 261 262 pATI->numVisualConfigs = numConfigs; 263 pATI->pVisualConfigs = pConfigs; 264 pATI->pVisualConfigsPriv = pATIConfigs; 265 GlxSetVisualConfigs( numConfigs, pConfigs, (void**)pATIConfigPtrs ); 266 return TRUE; 267} 268 269/* Create the ATI-specific context information */ 270static Bool ATICreateContext( ScreenPtr pScreen, VisualPtr visual, 271 drm_context_t hwContext, void *pVisualConfigPriv, 272 DRIContextType contextStore ) 273{ 274 /* Nothing yet */ 275 return TRUE; 276} 277 278/* Destroy the ATI-specific context information */ 279static void ATIDestroyContext( ScreenPtr pScreen, drm_context_t hwContext, 280 DRIContextType contextStore ) 281{ 282 /* Nothing yet */ 283} 284 285/* Called when the X server is woken up to allow the last client's 286 * context to be saved and the X server's context to be loaded. 287 * The client detects when it's context is not currently loaded and 288 * then loads it itself. The X server's context is loaded in the 289 * XAA Sync callback if NeedDRISync is set. 290 */ 291static void ATIEnterServer( ScreenPtr pScreen ) 292{ 293 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 294 ATIPtr pATI = ATIPTR(pScreenInfo); 295 296 if ( pATI->directRenderingEnabled ) { 297 ATIDRIMarkSyncInt(pScreenInfo); 298 ATIDRIMarkSyncExt(pScreenInfo); 299 } 300} 301 302/* Called when the X server goes to sleep to allow the X server's 303 * context to be saved and the last client's context to be loaded. 304 * The client detects when it's context is not currently loaded and 305 * then loads it itself. The X server keeps track of it's own state. 306 */ 307static void ATILeaveServer( ScreenPtr pScreen ) 308{ 309 /* Nothing yet */ 310} 311 312/* Contexts can be swapped by the X server if necessary. This callback 313 * is currently only used to perform any functions necessary when 314 * entering or leaving the X server, and in the future might not be 315 * necessary. 316 */ 317static void ATIDRISwapContext( ScreenPtr pScreen, 318 DRISyncType syncType, 319 DRIContextType oldContextType, 320 void *oldContext, 321 DRIContextType newContextType, 322 void *newContext ) 323{ 324 if ( ( syncType == DRI_3D_SYNC ) && ( oldContextType == DRI_2D_CONTEXT ) && 325 ( newContextType == DRI_2D_CONTEXT ) ) { 326 /* Entering from Wakeup */ 327 ATIEnterServer( pScreen ); 328 } 329 if ( ( syncType == DRI_2D_SYNC ) && ( oldContextType == DRI_NO_CONTEXT ) && 330 ( newContextType == DRI_2D_CONTEXT ) ) { 331 /* Exiting from Block Handler */ 332 ATILeaveServer( pScreen ); 333 } 334} 335 336#ifdef USE_XAA 337static void ATIDRITransitionTo2d(ScreenPtr pScreen) 338{ 339 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 340 ATIPtr pATI = ATIPTR(pScreenInfo); 341 342 if (pATI->backArea) { 343 xf86FreeOffscreenArea(pATI->backArea); 344 pATI->backArea = NULL; 345 } 346 if (pATI->depthTexArea) { 347 xf86FreeOffscreenArea(pATI->depthTexArea); 348 pATI->depthTexArea = NULL; 349 } 350 pATI->have3DWindows = FALSE; 351} 352 353static void ATIDRITransitionTo3d(ScreenPtr pScreen) 354{ 355 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 356 ATIPtr pATI = ATIPTR(pScreenInfo); 357 FBAreaPtr fbArea; 358 int width, height; 359 360 xf86PurgeUnlockedOffscreenAreas(pScreen); 361 362 xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0); 363 364 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 365 "Largest offscreen area available: %d x %d\n", 366 width, height); 367 368 fbArea = xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth, 369 height - pATI->depthTexLines - 370 pATI->backLines, 371 pScreenInfo->displayWidth, NULL, NULL, NULL); 372 373 if (!fbArea) 374 xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve placeholder " 375 "offscreen area, you might experience screen corruption\n"); 376 377 if (!pATI->backArea) { 378 pATI->backArea = 379 xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth, 380 pATI->backLines, 381 pScreenInfo->displayWidth, 382 NULL, NULL, NULL); 383 } 384 if (!pATI->backArea) 385 xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area " 386 "for back buffer, you might experience screen corruption\n"); 387 388 if (!pATI->depthTexArea) { 389 pATI->depthTexArea = 390 xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth, 391 pATI->depthTexLines, 392 pScreenInfo->displayWidth, 393 NULL, NULL, NULL); 394 } 395 if (!pATI->depthTexArea) 396 xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area " 397 "for depth buffer and textures, you might experience screen corruption\n"); 398 399 if (fbArea) 400 xf86FreeOffscreenArea(fbArea); 401 402 pATI->have3DWindows = TRUE; 403} 404#endif /* USE_XAA */ 405 406#ifdef USE_EXA 407static void ATIDRITransitionTo2d_EXA(ScreenPtr pScreen) 408{ 409 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 410 ATIPtr pATI = ATIPTR(pScreenInfo); 411 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 412 413 exaEnableDisableFBAccess(pScreen->myNum, FALSE); 414 415 pATI->pExa->offScreenBase = pATIDRIServer->backOffset; 416 417 exaEnableDisableFBAccess(pScreen->myNum, TRUE); 418 419 pATI->have3DWindows = FALSE; 420} 421 422static void ATIDRITransitionTo3d_EXA(ScreenPtr pScreen) 423{ 424 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 425 ATIPtr pATI = ATIPTR(pScreenInfo); 426 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 427 428 exaEnableDisableFBAccess(pScreen->myNum, FALSE); 429 430 pATI->pExa->offScreenBase = pATIDRIServer->textureOffset + 431 pATIDRIServer->textureSize; 432 433 exaEnableDisableFBAccess(pScreen->myNum, TRUE); 434 435 pATI->have3DWindows = TRUE; 436} 437#endif /* USE_EXA */ 438 439/* Initialize the state of the back and depth buffers. */ 440static void ATIDRIInitBuffers( WindowPtr pWin, RegionPtr prgn, CARD32 indx ) 441{ 442#ifdef USE_XAA 443 ScreenPtr pScreen = pWin->drawable.pScreen; 444 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 445 ATIPtr pATI = ATIPTR(pScreenInfo); 446 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 447 XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; 448 BoxPtr pbox, pboxSave; 449 int nbox, nboxSave; 450 int depth; 451 452 depth = 0x0000ffff; 453 454 if (!pXAAInfo) 455 return; 456 457 if (!pXAAInfo->SetupForSolidFill) 458 return; 459 460 /* FIXME: Only initialize the back and depth buffers for contexts 461 that request them */ 462 463 /* FIXME: Use drm clear? (see Radeon driver) */ 464 465 pboxSave = pbox = REGION_RECTS(prgn); 466 nboxSave = nbox = REGION_NUM_RECTS(prgn); 467 468 (*pXAAInfo->SetupForSolidFill)(pScreenInfo, 0, GXcopy, (CARD32)(-1)); 469 for (; nbox; nbox--, pbox++) { 470 (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, 471 pbox->x1 + pATIDRIServer->fbX, 472 pbox->y1 + pATIDRIServer->fbY, 473 pbox->x2 - pbox->x1, 474 pbox->y2 - pbox->y1); 475 (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, 476 pbox->x1 + pATIDRIServer->backX, 477 pbox->y1 + pATIDRIServer->backY, 478 pbox->x2 - pbox->x1, 479 pbox->y2 - pbox->y1); 480 } 481 482 pbox = pboxSave; 483 nbox = nboxSave; 484 485 (*pXAAInfo->SetupForSolidFill)(pScreenInfo, depth, GXcopy, (CARD32)(-1)); 486 for (; nbox; nbox--, pbox++) 487 (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, 488 pbox->x1 + pATIDRIServer->depthX, 489 pbox->y1 + pATIDRIServer->depthY, 490 pbox->x2 - pbox->x1, 491 pbox->y2 - pbox->y1); 492 493 ATIDRIMarkSyncInt(pScreenInfo); 494#endif 495} 496 497/* Copy the back and depth buffers when the X server moves a window. 498 * 499 * Note: this function was copied from the Radeon driver... 500 * 501 * This routine is a modified form of XAADoBitBlt with the calls to 502 * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source 503 * instead of destination. My origin is upside down so the ydir cases 504 * are reversed. 505 */ 506static void ATIDRIMoveBuffers( WindowPtr pWin, DDXPointRec ptOldOrg, 507 RegionPtr prgnSrc, CARD32 indx ) 508{ 509#ifdef USE_XAA 510 ScreenPtr pScreen = pWin->drawable.pScreen; 511 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 512 ATIPtr pATI = ATIPTR(pScreenInfo); 513 XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; 514 515 int backOffsetPitch = (((pATI->pDRIServerInfo->backPitch/8) << 22) | 516 (pATI->pDRIServerInfo->backOffset >> 3)); 517#if 0 518 int depthOffsetPitch = (((pATI->pDRIServerInfo->depthPitch/8) << 22) | 519 (pATI->pDRIServerInfo->depthOffset >> 3)); 520#endif 521 BoxPtr pboxTmp, pboxNext, pboxBase; 522 DDXPointPtr pptTmp; 523 int xdir, ydir; 524 525 int screenwidth = pScreenInfo->virtualX; 526 int screenheight = pScreenInfo->virtualY; 527 528 BoxPtr pbox = REGION_RECTS(prgnSrc); 529 int nbox = REGION_NUM_RECTS(prgnSrc); 530 531 BoxPtr pboxNew1 = NULL; 532 BoxPtr pboxNew2 = NULL; 533 DDXPointPtr pptNew1 = NULL; 534 DDXPointPtr pptNew2 = NULL; 535 DDXPointPtr pptSrc = &ptOldOrg; 536 537 int dx = pWin->drawable.x - ptOldOrg.x; 538 int dy = pWin->drawable.y - ptOldOrg.y; 539 540 if (!pXAAInfo) 541 return; 542 543 if (!pXAAInfo->SetupForScreenToScreenCopy) 544 return; 545 546 /* FIXME: Only move the back and depth buffers for contexts 547 * that request them. 548 */ 549 550 /* If the copy will overlap in Y, reverse the order */ 551 if (dy > 0) { 552 ydir = -1; 553 554 if (nbox > 1) { 555 /* Keep ordering in each band, reverse order of bands */ 556 pboxNew1 = (BoxPtr)xalloc(sizeof(BoxRec)*nbox); 557 if (!pboxNew1) return; 558 pptNew1 = (DDXPointPtr)xalloc(sizeof(DDXPointRec)*nbox); 559 if (!pptNew1) { 560 xfree(pboxNew1); 561 return; 562 } 563 pboxBase = pboxNext = pbox+nbox-1; 564 while (pboxBase >= pbox) { 565 while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) 566 pboxNext--; 567 pboxTmp = pboxNext+1; 568 pptTmp = pptSrc + (pboxTmp - pbox); 569 while (pboxTmp <= pboxBase) { 570 *pboxNew1++ = *pboxTmp++; 571 *pptNew1++ = *pptTmp++; 572 } 573 pboxBase = pboxNext; 574 } 575 pboxNew1 -= nbox; 576 pbox = pboxNew1; 577 pptNew1 -= nbox; 578 pptSrc = pptNew1; 579 } 580 } else { 581 /* No changes required */ 582 ydir = 1; 583 } 584 585 /* If the regions will overlap in X, reverse the order */ 586 if (dx > 0) { 587 xdir = -1; 588 589 if (nbox > 1) { 590 /* reverse order of rects in each band */ 591 pboxNew2 = (BoxPtr)xalloc(sizeof(BoxRec)*nbox); 592 pptNew2 = (DDXPointPtr)xalloc(sizeof(DDXPointRec)*nbox); 593 if (!pboxNew2 || !pptNew2) { 594 xfree(pptNew2); 595 xfree(pboxNew2); 596 xfree(pptNew1); 597 xfree(pboxNew1); 598 return; 599 } 600 pboxBase = pboxNext = pbox; 601 while (pboxBase < pbox+nbox) { 602 while ((pboxNext < pbox+nbox) 603 && (pboxNext->y1 == pboxBase->y1)) 604 pboxNext++; 605 pboxTmp = pboxNext; 606 pptTmp = pptSrc + (pboxTmp - pbox); 607 while (pboxTmp != pboxBase) { 608 *pboxNew2++ = *--pboxTmp; 609 *pptNew2++ = *--pptTmp; 610 } 611 pboxBase = pboxNext; 612 } 613 pboxNew2 -= nbox; 614 pbox = pboxNew2; 615 pptNew2 -= nbox; 616 pptSrc = pptNew2; 617 } 618 } else { 619 /* No changes are needed */ 620 xdir = 1; 621 } 622 623 (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, xdir, ydir, GXcopy, 624 (CARD32)(-1), -1); 625 626 for (; nbox-- ; pbox++) { 627 int xa = pbox->x1; 628 int ya = pbox->y1; 629 int destx = xa + dx; 630 int desty = ya + dy; 631 int w = pbox->x2 - xa + 1; 632 int h = pbox->y2 - ya + 1; 633 634 if (destx < 0) xa -= destx, w += destx, destx = 0; 635 if (desty < 0) ya -= desty, h += desty, desty = 0; 636 if (destx + w > screenwidth) w = screenwidth - destx; 637 if (desty + h > screenheight) h = screenheight - desty; 638 639 if (w <= 0) continue; 640 if (h <= 0) continue; 641 642 ATIMach64WaitForFIFO(pATI, 2); 643 outf(SRC_OFF_PITCH, backOffsetPitch); 644 outf(DST_OFF_PITCH, backOffsetPitch); 645 646 (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo, 647 xa, ya, 648 destx, desty, 649 w, h); 650#if 0 651 /* FIXME: Move depth buffers? */ 652 ATIMach64WaitForFIFO(pATI, 2); 653 outf(SRC_OFF_PITCH, depthOffsetPitch); 654 outf(DST_OFF_PITCH, depthOffsetPitch); 655 656 if (pATI->depthMoves) 657 ATIScreenToScreenCopyDepth(pScreenInfo, 658 xa, ya, 659 destx, desty, 660 w, h); 661#endif 662 } 663 664 ATIMach64WaitForFIFO(pATI, 2); 665 outf(SRC_OFF_PITCH, pATI->NewHW.dst_off_pitch); 666 outf(DST_OFF_PITCH, pATI->NewHW.src_off_pitch); 667 668 xfree(pptNew2); 669 xfree(pboxNew2); 670 xfree(pptNew1); 671 xfree(pboxNew1); 672 673 ATIDRIMarkSyncInt(pScreenInfo); 674#endif 675} 676 677/* Compute log base 2 of val. */ 678static int Mach64MinBits(int val) 679{ 680 int bits; 681 682 if (!val) return 1; 683 for (bits = 0; val; val >>= 1, ++bits); 684 return bits; 685} 686 687static Bool ATIDRISetBufSize( ScreenPtr pScreen, unsigned int maxSize ) 688{ 689 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 690 ATIPtr pATI = ATIPTR(pScreenInfo); 691 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 692 693 if (pATI->OptionBufferSize) { 694 if (pATI->OptionBufferSize < 1 || pATI->OptionBufferSize > maxSize ) { 695 xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Illegal DMA buffers size: %d MB\n", 696 pATI->OptionBufferSize ); 697 return FALSE; 698 } 699 if (pATI->OptionBufferSize > 2) { 700 xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Illegal DMA buffers size: %d MB\n", 701 pATI->OptionBufferSize ); 702 xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Clamping DMA buffers size to 2 MB\n"); 703 pATIDRIServer->bufferSize = 2; 704 } else { 705 pATIDRIServer->bufferSize = pATI->OptionBufferSize; 706 xf86DrvMsg( pScreen->myNum, X_CONFIG, "[drm] Using %d MB for DMA buffers\n", 707 pATIDRIServer->bufferSize ); 708 } 709 } else { 710 xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[drm] Using %d MB for DMA buffers\n", 711 pATIDRIServer->bufferSize ); 712 } 713 714 return TRUE; 715} 716 717static Bool ATIDRISetAgpMode( ScreenPtr pScreen ) 718{ 719 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 720 ATIPtr pATI = ATIPTR(pScreenInfo); 721 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 722 723 unsigned long mode = drmAgpGetMode( pATI->drmFD ); /* Default mode */ 724 unsigned int vendor = drmAgpVendorId( pATI->drmFD ); 725 unsigned int device = drmAgpDeviceId( pATI->drmFD ); 726 727 if (pATI->OptionAGPMode > 0 && pATI->OptionAGPMode <= ATI_AGP_MAX_MODE) { 728 pATIDRIServer->agpMode = pATI->OptionAGPMode; 729 xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using AGP %dx Mode\n", 730 pATIDRIServer->agpMode ); 731 } else if (pATI->OptionAGPMode > 0) { 732 xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Illegal AGP Mode: %d\n", 733 pATI->OptionAGPMode ); 734 return FALSE; 735 } else { 736 /* If no mode configured, use the default mode obtained from agpgart */ 737 if ( mode & AGP_MODE_2X ) { 738 pATIDRIServer->agpMode = 2; 739 } else if ( mode & AGP_MODE_1X ) { 740 pATIDRIServer->agpMode = 1; 741 } 742 xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using AGP %dx Mode\n", 743 pATIDRIServer->agpMode ); 744 } 745 746 mode &= ~AGP_MODE_MASK; 747 switch ( pATIDRIServer->agpMode ) { 748 case 2: mode |= AGP_MODE_2X; 749 case 1: default: mode |= AGP_MODE_1X; 750 } 751 752 if (pATI->OptionAGPSize) { 753 switch (pATI->OptionAGPSize) { 754 case 128: 755 case 64: 756 case 32: 757 case 16: 758 case 8: 759 case 4: 760 pATIDRIServer->agpSize = pATI->OptionAGPSize; 761 xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using %d MB AGP aperture\n", 762 pATIDRIServer->agpSize ); 763 break; 764 default: 765 xf86DrvMsg( pScreen->myNum, X_ERROR, 766 "[agp] Illegal aperture size %d MB\n", pATI->OptionAGPSize ); 767 return FALSE; 768 } 769 } else { 770 xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using %d MB AGP aperture\n", 771 pATIDRIServer->agpSize ); 772 } 773 774 xf86DrvMsg( pScreen->myNum, X_INFO, 775 "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", 776 mode, vendor, device, 777 PCI_DEV_VENDOR_ID(pATI->PCIInfo), 778 PCI_DEV_DEVICE_ID(pATI->PCIInfo) ); 779 780 if ( drmAgpEnable( pATI->drmFD, mode ) < 0 ) { 781 xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" ); 782 drmAgpRelease( pATI->drmFD ); 783 return FALSE; 784 } 785 786 return TRUE; 787} 788 789/* Initialize the AGP state. Request memory for use in AGP space, and 790 * initialize the Rage Pro registers to point to that memory. 791 */ 792static Bool ATIDRIAgpInit( ScreenPtr pScreen ) 793{ 794 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 795 ATIPtr pATI = ATIPTR(pScreenInfo); 796 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 797 798 int ret; 799 unsigned long cntl; 800 int s, l; 801 802 pATIDRIServer->agpSize = ATI_DEFAULT_AGP_SIZE; 803 pATIDRIServer->agpMode = ATI_DEFAULT_AGP_MODE; 804 pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE; 805 pATIDRIServer->ringSize = 16; /* 16 kB ring */ 806 807 if ( drmAgpAcquire( pATI->drmFD ) < 0 ) { 808 xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP not available\n" ); 809 return FALSE; 810 } 811 812 if (!ATIDRISetAgpMode( pScreen )) 813 return FALSE; 814 815 pATIDRIServer->agpOffset = 0; 816 817 ret = drmAgpAlloc( pATI->drmFD, pATIDRIServer->agpSize*1024*1024, 818 0, NULL, &pATIDRIServer->agpHandle ); 819 if ( ret < 0 ) { 820 xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret ); 821 drmAgpRelease( pATI->drmFD ); 822 return FALSE; 823 } 824 xf86DrvMsg( pScreen->myNum, X_INFO, 825 "[agp] %d kB allocated with handle 0x%08x\n", 826 pATIDRIServer->agpSize*1024, pATIDRIServer->agpHandle ); 827 828 if ( drmAgpBind( pATI->drmFD, pATIDRIServer->agpHandle, pATIDRIServer->agpOffset) < 0 ) { 829 xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind\n" ); 830 drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle ); 831 drmAgpRelease( pATI->drmFD ); 832 return FALSE; 833 } 834 835 xf86DrvMsg(pScreen->myNum, X_INFO, 836 "[agp] Using %d kB for DMA descriptor ring\n", pATIDRIServer->ringSize); 837 838 if ( !ATIDRISetBufSize( pScreen, pATIDRIServer->agpSize ) ) 839 return FALSE; 840 841 pATIDRIServer->agpTexSize = pATIDRIServer->agpSize - pATIDRIServer->bufferSize; 842 843 /* Reserve space for the DMA descriptor ring */ 844 pATIDRIServer->ringStart = pATIDRIServer->agpOffset; 845 pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */ 846 847 /* Reserve space for the vertex buffer */ 848 pATIDRIServer->bufferStart = pATIDRIServer->ringStart + pATIDRIServer->ringMapSize; 849 pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024; 850 851 /* Reserve the rest for AGP textures */ 852 pATIDRIServer->agpTexStart = pATIDRIServer->bufferStart + pATIDRIServer->bufferMapSize; 853 s = (pATIDRIServer->agpSize*1024*1024 - pATIDRIServer->agpTexStart); 854 l = Mach64MinBits((s-1) / MACH64_NR_TEX_REGIONS); 855 if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY; 856 pATIDRIServer->agpTexMapSize = (s >> l) << l; 857 pATIDRIServer->log2AGPTexGran = l; 858 859 xf86DrvMsg(pScreen->myNum, X_INFO, 860 "[agp] Using %d kB for AGP textures\n", pATIDRIServer->agpTexMapSize/1024); 861 862 /* Map DMA descriptor ring */ 863 if ( drmAddMap( pATI->drmFD, pATIDRIServer->ringStart, pATIDRIServer->ringMapSize, 864 DRM_AGP, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) { 865 xf86DrvMsg( pScreen->myNum, X_ERROR, 866 "[agp] Could not add ring mapping\n" ); 867 return FALSE; 868 } 869 xf86DrvMsg( pScreen->myNum, X_INFO, 870 "[agp] ring handle = 0x%08x\n", 871 pATIDRIServer->ringHandle ); 872 873 if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle, 874 pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) { 875 xf86DrvMsg( pScreen->myNum, X_ERROR, 876 "[agp] Could not map ring\n" ); 877 return FALSE; 878 } 879 xf86DrvMsg( pScreen->myNum, X_INFO, 880 "[agp] Ring mapped at 0x%08lx\n", 881 (unsigned long)pATIDRIServer->ringMap ); 882 883 /* Map vertex buffers */ 884 if ( drmAddMap( pATI->drmFD, pATIDRIServer->bufferStart, pATIDRIServer->bufferMapSize, 885 DRM_AGP, DRM_READ_ONLY, &pATIDRIServer->bufferHandle ) < 0 ) { 886 xf86DrvMsg( pScreen->myNum, X_ERROR, 887 "[agp] Could not add vertex buffers mapping\n" ); 888 return FALSE; 889 } 890 xf86DrvMsg( pScreen->myNum, X_INFO, 891 "[agp] vertex buffers handle = 0x%08x\n", 892 pATIDRIServer->bufferHandle ); 893 894 if ( drmMap( pATI->drmFD, pATIDRIServer->bufferHandle, 895 pATIDRIServer->bufferMapSize, &pATIDRIServer->bufferMap ) < 0 ) { 896 xf86DrvMsg( pScreen->myNum, X_ERROR, 897 "[agp] Could not map vertex buffers\n" ); 898 return FALSE; 899 } 900 xf86DrvMsg( pScreen->myNum, X_INFO, 901 "[agp] Vertex buffers mapped at 0x%08lx\n", 902 (unsigned long)pATIDRIServer->bufferMap ); 903 904 /* Map AGP Textures */ 905 if (drmAddMap(pATI->drmFD, pATIDRIServer->agpTexStart, pATIDRIServer->agpTexMapSize, 906 DRM_AGP, 0, &pATIDRIServer->agpTexHandle) < 0) { 907 xf86DrvMsg(pScreen->myNum, X_ERROR, 908 "[agp] Could not add AGP texture region mapping\n"); 909 return FALSE; 910 } 911 xf86DrvMsg(pScreen->myNum, X_INFO, 912 "[agp] AGP texture region handle = 0x%08x\n", 913 pATIDRIServer->agpTexHandle); 914 915 if (drmMap(pATI->drmFD, pATIDRIServer->agpTexHandle, pATIDRIServer->agpTexMapSize, 916 &pATIDRIServer->agpTexMap) < 0) { 917 xf86DrvMsg(pScreen->myNum, X_ERROR, 918 "[agp] Could not map AGP texture region\n"); 919 return FALSE; 920 } 921 xf86DrvMsg(pScreen->myNum, X_INFO, 922 "[agp] AGP Texture region mapped at 0x%08lx\n", 923 (unsigned long)pATIDRIServer->agpTexMap); 924 925 /* Initialize Mach64's AGP registers */ 926 cntl = inm( AGP_CNTL ); 927 cntl &= ~AGP_APER_SIZE_MASK; 928 switch ( pATIDRIServer->agpSize ) { 929 case 256: cntl |= AGP_APER_SIZE_256MB; break; 930 case 128: cntl |= AGP_APER_SIZE_128MB; break; 931 case 64: cntl |= AGP_APER_SIZE_64MB; break; 932 case 32: cntl |= AGP_APER_SIZE_32MB; break; 933 case 16: cntl |= AGP_APER_SIZE_16MB; break; 934 case 8: cntl |= AGP_APER_SIZE_8MB; break; 935 case 4: cntl |= AGP_APER_SIZE_4MB; break; 936 default: 937 xf86DrvMsg( pScreen->myNum, X_ERROR, 938 "[agp] Illegal aperture size %d kB\n", 939 pATIDRIServer->agpSize*1024 ); 940 return FALSE; 941 } 942 943 /* 1 = DATA comes in clock in which TRDY sampled (default) */ 944 /* 0 = DATA comes in clock after TRDY sampled */ 945 cntl |= AGP_TRDY_MODE; 946 947 /* 1 = generate all reads as high priority */ 948 /* 0 = generate all reads as their default priority (default) */ 949 /* Setting this only works for me at AGP 1x mode (LLD) */ 950 if (pATIDRIServer->agpMode == 1) { 951 cntl |= HIGH_PRIORITY_READ_EN; 952 } else { 953 cntl &= ~HIGH_PRIORITY_READ_EN; 954 } 955 956 outm( AGP_BASE, drmAgpBase(pATI->drmFD) ); 957 outm( AGP_CNTL, cntl ); 958 959 return TRUE; 960} 961 962static Bool ATIDRIPciInit( ScreenPtr pScreen ) 963{ 964 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 965 ATIPtr pATI = ATIPTR(pScreenInfo); 966 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 967 968 pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE; 969 pATIDRIServer->ringSize = 16; /* 16 kB ring */ 970 971 if ( !ATIDRISetBufSize( pScreen, (unsigned)(-1) ) ) 972 return FALSE; 973 974 /* Set size of the DMA descriptor ring */ 975 pATIDRIServer->ringStart = 0; 976 pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */ 977 978 /* Set size of the vertex buffer */ 979 pATIDRIServer->bufferStart = 0; 980 pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024; 981 982 /* Map DMA descriptor ring */ 983 if ( drmAddMap( pATI->drmFD, 0, pATIDRIServer->ringMapSize, 984 DRM_CONSISTENT, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) { 985 xf86DrvMsg( pScreen->myNum, X_ERROR, 986 "[pci] Could not add ring mapping\n" ); 987 return FALSE; 988 } 989 xf86DrvMsg( pScreen->myNum, X_INFO, "[pci] ring handle = 0x%08x\n", 990 pATIDRIServer->ringHandle ); 991 992 if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle, 993 pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) { 994 xf86DrvMsg( pScreen->myNum, X_ERROR, 995 "[pci] Could not map ring\n" ); 996 return FALSE; 997 } 998 xf86DrvMsg( pScreen->myNum, X_INFO, 999 "[pci] Ring mapped at 0x%08lx\n", 1000 (unsigned long)pATIDRIServer->ringMap ); 1001 1002 /* Disable AGP for ForcePCIMode */ 1003 if ( pATI->BusType != ATI_BUS_PCI ) { 1004 outm( AGP_BASE, 0 ); 1005 outm( AGP_CNTL, 0 ); 1006 } 1007 1008 return TRUE; 1009} 1010 1011/* Add a map for the MMIO registers that will be accessed by any 1012 * DRI-based clients. 1013 */ 1014static Bool ATIDRIMapInit( ScreenPtr pScreen ) 1015{ 1016 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 1017 ATIPtr pATI = ATIPTR(pScreenInfo); 1018 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 1019 1020 pATIDRIServer->regsSize = getpagesize(); 1021 if ( drmAddMap( pATI->drmFD, pATI->Block1Base, 1022 pATIDRIServer->regsSize, 1023 DRM_REGISTERS, DRM_READ_ONLY, 1024 &pATIDRIServer->regsHandle ) < 0 ) { 1025 xf86DrvMsg( pScreen->myNum, X_ERROR, 1026 "[drm] failed to map registers\n" ); 1027 return FALSE; 1028 } 1029 xf86DrvMsg( pScreen->myNum, X_INFO, 1030 "[drm] register handle = 0x%08x\n", 1031 pATIDRIServer->regsHandle ); 1032 1033 return TRUE; 1034} 1035 1036/* Initialize the kernel data structures. */ 1037static Bool ATIDRIKernelInit( ScreenPtr pScreen ) 1038{ 1039 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 1040 ATIPtr pATI = ATIPTR(pScreenInfo); 1041 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 1042 drmMach64Init info; 1043 1044 memset( &info, 0, sizeof(drmMach64Init) ); 1045 1046 info.func = DRM_MACH64_INIT_DMA; 1047 info.sarea_priv_offset = sizeof(XF86DRISAREARec); 1048 info.is_pci = pATIDRIServer->IsPCI; 1049 info.dma_mode = pATI->OptionDMAMode; 1050 1051 info.fb_bpp = pATI->bitsPerPixel; 1052 info.front_offset = pATIDRIServer->frontOffset; 1053 info.front_pitch = pATIDRIServer->frontPitch; 1054 info.back_offset = pATIDRIServer->backOffset; 1055 info.back_pitch = pATIDRIServer->backPitch; 1056 1057 info.depth_bpp = 16; 1058 info.depth_offset = pATIDRIServer->depthOffset; 1059 info.depth_pitch = pATIDRIServer->depthPitch; 1060 1061 info.fb_offset = pATI->LinearBase; 1062 info.mmio_offset = pATIDRIServer->regsHandle; 1063 info.ring_offset = pATIDRIServer->ringHandle; 1064 info.buffers_offset = pATIDRIServer->bufferHandle; 1065 info.agp_textures_offset = pATIDRIServer->agpTexHandle; 1066 1067 if ( drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT, 1068 &info, sizeof(drmMach64Init) ) < 0 ) { 1069 return FALSE; 1070 } else { 1071 return TRUE; 1072 } 1073} 1074 1075/* Add a map for the DMA buffers that will be accessed by any 1076 * DRI-based clients. 1077 */ 1078static Bool ATIDRIAddBuffers( ScreenPtr pScreen ) 1079{ 1080 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 1081 ATIPtr pATI = ATIPTR(pScreenInfo); 1082 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 1083 1084 /* Initialize vertex buffers */ 1085 if ( pATIDRIServer->IsPCI ) { 1086 pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD, 1087 pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE, 1088 MACH64_BUFFER_SIZE, 1089 DRM_PCI_BUFFER_RO, 1090 0 ); 1091 } else { 1092 pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD, 1093 pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE, 1094 MACH64_BUFFER_SIZE, 1095 DRM_AGP_BUFFER, 1096 pATIDRIServer->bufferStart ); 1097 } 1098 if ( pATIDRIServer->numBuffers <= 0 ) { 1099 xf86DrvMsg( pScreen->myNum, X_ERROR, 1100 "[drm] Could not create DMA buffers list\n" ); 1101 return FALSE; 1102 } 1103 xf86DrvMsg( pScreen->myNum, X_INFO, 1104 "[drm] Added %d %d byte DMA buffers\n", 1105 pATIDRIServer->numBuffers, MACH64_BUFFER_SIZE ); 1106 1107 return TRUE; 1108} 1109 1110static Bool ATIDRIMapBuffers( ScreenPtr pScreen ) 1111{ 1112 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 1113 ATIPtr pATI = ATIPTR(pScreenInfo); 1114 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 1115 1116 pATIDRIServer->drmBuffers = drmMapBufs( pATI->drmFD ); 1117 if ( !pATIDRIServer->drmBuffers ) { 1118 xf86DrvMsg( pScreen->myNum, X_ERROR, 1119 "[drm] Failed to map DMA buffers list\n" ); 1120 return FALSE; 1121 } 1122 xf86DrvMsg( pScreen->myNum, X_INFO, 1123 "[drm] Mapped %d DMA buffers at 0x%08lx\n", 1124 pATIDRIServer->drmBuffers->count, 1125 (unsigned long)pATIDRIServer->drmBuffers->list->address ); 1126 1127 return TRUE; 1128} 1129 1130static Bool ATIDRIIrqInit( ScreenPtr pScreen ) 1131{ 1132 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 1133 ATIPtr pATI = ATIPTR(pScreenInfo); 1134 1135 if ( pATI->irq <= 0 ) { 1136 pATI->irq = drmGetInterruptFromBusID(pATI->drmFD, 1137 PCI_CFG_BUS(pATI->PCIInfo), 1138 PCI_CFG_DEV(pATI->PCIInfo), 1139 PCI_CFG_FUNC(pATI->PCIInfo)); 1140 if ( pATI->irq <= 0 ) { 1141 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 1142 "[drm] Couldn't find IRQ for bus id %d:%d:%d\n", 1143 PCI_CFG_BUS(pATI->PCIInfo), 1144 PCI_CFG_DEV(pATI->PCIInfo), 1145 PCI_CFG_FUNC(pATI->PCIInfo)); 1146 pATI->irq = 0; 1147 } else if ((drmCtlInstHandler(pATI->drmFD, pATI->irq)) != 0) { 1148 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 1149 "[drm] Failed to initialize interrupt handler with IRQ %d\n", 1150 pATI->irq); 1151 pATI->irq = 0; 1152 } 1153 1154 if (pATI->irq) 1155 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 1156 "[drm] Installed interrupt handler, using IRQ %d\n", 1157 pATI->irq); 1158 else { 1159 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 1160 "[drm] Falling back to irq-free operation\n"); 1161 return FALSE; 1162 } 1163 } 1164 1165 return TRUE; 1166 1167} 1168 1169/* Initialize the screen-specific data structures for the DRI and the 1170 * Rage Pro. This is the main entry point to the device-specific 1171 * initialization code. It calls device-independent DRI functions to 1172 * create the DRI data structures and initialize the DRI state. 1173 */ 1174Bool ATIDRIScreenInit( ScreenPtr pScreen ) 1175{ 1176 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 1177 ATIPtr pATI = ATIPTR(pScreenInfo); 1178 DRIInfoPtr pDRIInfo; 1179 ATIDRIPtr pATIDRI; 1180 ATIDRIServerInfoPtr pATIDRIServer; 1181 drmVersionPtr version; 1182 int major, minor, patch; 1183 1184 /* Check that the GLX, DRI, and DRM modules have been loaded by testing 1185 * for known symbols in each module. 1186 */ 1187 if ( !xf86LoaderCheckSymbol("GlxSetVisualConfigs") ) return FALSE; 1188 if ( !xf86LoaderCheckSymbol("drmAvailable") ) return FALSE; 1189 if ( !xf86LoaderCheckSymbol("DRIQueryVersion") ) { 1190 xf86DrvMsg( pScreen->myNum, X_ERROR, 1191 "[dri] ATIDRIScreenInit failed (libdri.a too old)\n" ); 1192 return FALSE; 1193 } 1194 1195 /* Check the DRI version */ 1196 DRIQueryVersion( &major, &minor, &patch ); 1197 if ( major != DRIINFO_MAJOR_VERSION || minor < 0 ) { 1198 xf86DrvMsg( pScreen->myNum, X_ERROR, 1199 "[dri] ATIDRIScreenInit failed because of a version mismatch.\n" 1200 "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n" 1201 "[dri] Disabling the DRI.\n", 1202 major, minor, patch, 1203 DRIINFO_MAJOR_VERSION, 0 ); 1204 return FALSE; 1205 } 1206 1207 switch ( pATI->bitsPerPixel ) { 1208 case 8: 1209 /* These modes are not supported (yet). */ 1210 case 15: 1211 case 24: 1212 xf86DrvMsg( pScreen->myNum, X_ERROR, 1213 "[dri] Direct rendering only supported in 16 and 32 bpp modes\n"); 1214 return FALSE; 1215 1216 /* Only 16 and 32 color depths are supported currently. */ 1217 case 16: 1218 if ( pATI->depth != 16) { 1219 xf86DrvMsg( pScreen->myNum, X_ERROR, 1220 "[dri] Direct rendering not supported for depth %d at fbbpp 16.\n", pATI->depth ); 1221 return FALSE; 1222 } 1223 break; 1224 case 32: 1225 break; 1226 } 1227 1228 /* Create the DRI data structure, and fill it in before calling the 1229 * DRIScreenInit(). 1230 */ 1231 pDRIInfo = DRICreateInfoRec(); 1232 if ( !pDRIInfo ) return FALSE; 1233 1234 pATI->pDRIInfo = pDRIInfo; 1235 pDRIInfo->drmDriverName = ATIKernelDriverName; 1236 pDRIInfo->clientDriverName = ATIClientDriverName; 1237 if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 1238 pDRIInfo->busIdString = DRICreatePCIBusID(pATI->PCIInfo); 1239 } else { 1240 pDRIInfo->busIdString = xalloc( 64 ); 1241 sprintf( pDRIInfo->busIdString, 1242 "PCI:%d:%d:%d", 1243 PCI_DEV_BUS(pATI->PCIInfo), 1244 PCI_DEV_DEV(pATI->PCIInfo), 1245 PCI_DEV_FUNC(pATI->PCIInfo) ); 1246 } 1247 pDRIInfo->ddxDriverMajorVersion = MACH64_VERSION_MAJOR; 1248 pDRIInfo->ddxDriverMinorVersion = MACH64_VERSION_MINOR; 1249 pDRIInfo->ddxDriverPatchVersion = MACH64_VERSION_PATCH; 1250 pDRIInfo->frameBufferPhysicalAddress = (void *)pATI->LinearBase; 1251 pDRIInfo->frameBufferSize = pATI->LinearSize; 1252 pDRIInfo->frameBufferStride = (pScreenInfo->displayWidth * 1253 pATI->FBBytesPerPixel); 1254 pDRIInfo->ddxDrawableTableEntry = ATI_MAX_DRAWABLES; 1255 1256 if ( SAREA_MAX_DRAWABLES < ATI_MAX_DRAWABLES ) { 1257 pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; 1258 } else { 1259 pDRIInfo->maxDrawableTableEntry = ATI_MAX_DRAWABLES; 1260 } 1261 1262 /* For now the mapping works by using a fixed size defined 1263 * in the SAREA header 1264 */ 1265 if ( sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec) > SAREA_MAX ) { 1266 ErrorF( "[dri] Data does not fit in SAREA\n" ); 1267 return FALSE; 1268 } 1269 xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %u+%u: %u\n", 1270 (unsigned)sizeof(XF86DRISAREARec), 1271 (unsigned)sizeof(ATISAREAPrivRec), 1272 (unsigned)(sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec)) ); 1273 pDRIInfo->SAREASize = SAREA_MAX; 1274 1275 pATIDRI = (ATIDRIPtr) xnfcalloc( sizeof(ATIDRIRec), 1 ); 1276 if ( !pATIDRI ) { 1277 DRIDestroyInfoRec( pATI->pDRIInfo ); 1278 pATI->pDRIInfo = NULL; 1279 xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR, 1280 "[dri] Failed to allocate memory for private record\n" ); 1281 return FALSE; 1282 } 1283 pATIDRIServer = (ATIDRIServerInfoPtr) 1284 xnfcalloc( sizeof(ATIDRIServerInfoRec), 1 ); 1285 if ( !pATIDRIServer ) { 1286 xfree( pATIDRI ); 1287 DRIDestroyInfoRec( pATI->pDRIInfo ); 1288 pATI->pDRIInfo = NULL; 1289 xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR, 1290 "[dri] Failed to allocate memory for private record\n" ); 1291 return FALSE; 1292 } 1293 1294 pATI->pDRIServerInfo = pATIDRIServer; 1295 1296 pDRIInfo->devPrivate = pATIDRI; 1297 pDRIInfo->devPrivateSize = sizeof(ATIDRIRec); 1298 pDRIInfo->contextSize = sizeof(ATIDRIContextRec); 1299 1300 pDRIInfo->CreateContext = ATICreateContext; 1301 pDRIInfo->DestroyContext = ATIDestroyContext; 1302 pDRIInfo->SwapContext = ATIDRISwapContext; 1303 pDRIInfo->InitBuffers = ATIDRIInitBuffers; 1304 pDRIInfo->MoveBuffers = ATIDRIMoveBuffers; 1305#ifdef USE_XAA 1306 if (!pATI->useEXA) { 1307 pDRIInfo->TransitionTo2d = ATIDRITransitionTo2d; 1308 pDRIInfo->TransitionTo3d = ATIDRITransitionTo3d; 1309 } 1310#endif /* USE_XAA */ 1311#ifdef USE_EXA 1312 if (pATI->useEXA) { 1313 pDRIInfo->TransitionTo2d = ATIDRITransitionTo2d_EXA; 1314 pDRIInfo->TransitionTo3d = ATIDRITransitionTo3d_EXA; 1315 } 1316#endif /* USE_EXA */ 1317 pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 1318 1319 pDRIInfo->createDummyCtx = TRUE; 1320 pDRIInfo->createDummyCtxPriv = FALSE; 1321 1322 pATI->have3DWindows = FALSE; 1323 1324 if ( !DRIScreenInit( pScreen, pDRIInfo, &pATI->drmFD ) ) { 1325 xfree( pATIDRIServer ); 1326 pATI->pDRIServerInfo = NULL; 1327 xfree( pDRIInfo->devPrivate ); 1328 pDRIInfo->devPrivate = NULL; 1329 DRIDestroyInfoRec( pDRIInfo ); 1330 pDRIInfo = NULL; 1331 xf86DrvMsg( pScreen->myNum, X_ERROR, 1332 "[dri] DRIScreenInit Failed\n" ); 1333 return FALSE; 1334 } 1335 1336 /* Check the DRM lib version. 1337 drmGetLibVersion was not supported in version 1.0, so check for 1338 symbol first to avoid possible crash or hang. 1339 */ 1340 if (xf86LoaderCheckSymbol("drmGetLibVersion")) { 1341 version = drmGetLibVersion(pATI->drmFD); 1342 } else { 1343 /* drmlib version 1.0.0 didn't have the drmGetLibVersion 1344 entry point. Fake it by allocating a version record 1345 via drmGetVersion and changing it to version 1.0.0 1346 */ 1347 version = drmGetVersion(pATI->drmFD); 1348 version->version_major = 1; 1349 version->version_minor = 0; 1350 version->version_patchlevel = 0; 1351 } 1352 1353 if (version) { 1354 if (version->version_major != 1 || 1355 version->version_minor < 1) { 1356 /* incompatible drm library version */ 1357 xf86DrvMsg(pScreen->myNum, X_ERROR, 1358 "[dri] ATIDRIScreenInit failed because of a version mismatch.\n" 1359 "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n" 1360 "[dri] Disabling DRI.\n", 1361 version->version_major, 1362 version->version_minor, 1363 version->version_patchlevel); 1364 drmFreeVersion(version); 1365 ATIDRICloseScreen(pScreen); 1366 return FALSE; 1367 } 1368 drmFreeVersion(version); 1369 } 1370 1371 /* Check the mach64 DRM version */ 1372 version = drmGetVersion( pATI->drmFD ); 1373 if ( version ) { 1374 if ( version->version_major != 2 || 1375 version->version_minor < 0 ) { 1376 /* Incompatible DRM version */ 1377 xf86DrvMsg( pScreen->myNum, X_ERROR, 1378 "[dri] ATIDRIScreenInit failed because of a version mismatch.\n" 1379 "[dri] mach64.o kernel module version is %d.%d.%d, but version 2.x is needed (with 2.x >= 2.0).\n" 1380 "[dri] Disabling DRI.\n", 1381 version->version_major, 1382 version->version_minor, 1383 version->version_patchlevel ); 1384 drmFreeVersion( version ); 1385 ATIDRICloseScreen( pScreen ); 1386 return FALSE; 1387 } 1388 drmFreeVersion( version ); 1389 } 1390 1391 switch ( pATI->OptionDMAMode ) { 1392 case MACH64_MODE_DMA_ASYNC: 1393 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request asynchronous DMA mode\n"); 1394 break; 1395 case MACH64_MODE_DMA_SYNC: 1396 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request synchronous DMA mode\n"); 1397 break; 1398 case MACH64_MODE_MMIO: 1399 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request pseudo-DMA (MMIO) mode\n"); 1400 break; 1401 default: 1402 xf86DrvMsg(pScreen->myNum, X_WARNING, "[drm] Unknown DMA mode\n"); 1403 } 1404 1405 pATIDRIServer->IsPCI = (pATI->BusType == ATI_BUS_PCI || pATI->OptionIsPCI) ? TRUE : FALSE; 1406 1407 if ( pATI->BusType != ATI_BUS_PCI && pATI->OptionIsPCI ) { 1408 xf86DrvMsg(pScreen->myNum, X_CONFIG, "[dri] Forcing PCI mode\n"); 1409 } 1410 1411 /* Initialize AGP */ 1412 if ( !pATIDRIServer->IsPCI && !ATIDRIAgpInit( pScreen ) ) { 1413 pATIDRIServer->IsPCI = TRUE; 1414 xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP failed to initialize -- falling back to PCI mode.\n" ); 1415 xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] Make sure you have the agpgart kernel module loaded.\n" ); 1416 } 1417 1418 /* Initialize PCI */ 1419 if ( pATIDRIServer->IsPCI && !ATIDRIPciInit( pScreen ) ) { 1420 ATIDRICloseScreen( pScreen ); 1421 return FALSE; 1422 } 1423 1424 if ( !ATIDRIMapInit( pScreen ) ) { 1425 ATIDRICloseScreen( pScreen ); 1426 return FALSE; 1427 } 1428 1429 if ( !ATIInitVisualConfigs( pScreen ) ) { 1430 ATIDRICloseScreen( pScreen ); 1431 return FALSE; 1432 } 1433 xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, 1434 "[dri] Visual configs initialized\n" ); 1435 1436 xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, 1437 "[dri] Block 0 base at 0x%08lx\n", pATI->Block0Base ); 1438 1439 return TRUE; 1440} 1441 1442/* Finish initializing the device-dependent DRI state, and call 1443 * DRIFinishScreenInit() to complete the device-independent DRI 1444 * initialization. 1445 */ 1446Bool ATIDRIFinishScreenInit( ScreenPtr pScreen ) 1447{ 1448 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 1449 ATIPtr pATI = ATIPTR(pScreenInfo); 1450 ATISAREAPrivPtr pSAREAPriv; 1451 ATIDRIPtr pATIDRI; 1452 ATIDRIServerInfoPtr pATIDRIServer; 1453 1454 pATI->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 1455 1456 /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit 1457 * because *DRIKernelInit requires that the hardware lock is held by 1458 * the X server, and the first time the hardware lock is grabbed is 1459 * in DRIFinishScreenInit. 1460 */ 1461 if ( !DRIFinishScreenInit( pScreen ) ) { 1462 ATIDRICloseScreen( pScreen ); 1463 return FALSE; 1464 } 1465 1466 /* Initialize the DMA buffer list */ 1467 /* Need to do this before ATIDRIKernelInit so we can init the freelist */ 1468 if ( !ATIDRIAddBuffers( pScreen ) ) { 1469 ATIDRICloseScreen( pScreen ); 1470 return FALSE; 1471 } 1472 1473 /* Initialize the kernel data structures */ 1474 if ( !ATIDRIKernelInit( pScreen ) ) { 1475 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 1476 "[drm] Failed to initialize the mach64.o kernel module\n"); 1477 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 1478 "[drm] Check the system log for more information.\n"); 1479 ATIDRICloseScreen( pScreen ); 1480 return FALSE; 1481 } 1482 1483 if ( !ATIDRIMapBuffers( pScreen ) ) { 1484 ATIDRICloseScreen( pScreen ); 1485 return FALSE; 1486 } 1487 1488 /* Initialize IRQ */ 1489 ATIDRIIrqInit( pScreen ); 1490 1491 pSAREAPriv = (ATISAREAPrivPtr) DRIGetSAREAPrivate( pScreen ); 1492 memset( pSAREAPriv, 0, sizeof(*pSAREAPriv) ); 1493 1494 pATIDRI = (ATIDRIPtr)pATI->pDRIInfo->devPrivate; 1495 pATIDRIServer = pATI->pDRIServerInfo; 1496 1497 pATIDRI->width = pScreenInfo->virtualX; 1498 pATIDRI->height = pScreenInfo->virtualY; 1499 pATIDRI->mem = pScreenInfo->videoRam * 1024; 1500 pATIDRI->cpp = pScreenInfo->bitsPerPixel / 8; 1501 1502 pATIDRI->IsPCI = pATIDRIServer->IsPCI; 1503 pATIDRI->AGPMode = pATIDRIServer->agpMode; 1504 1505 pATIDRI->frontOffset = pATIDRIServer->frontOffset; 1506 pATIDRI->frontPitch = pATIDRIServer->frontPitch; 1507 1508 pATIDRI->backOffset = pATIDRIServer->backOffset; 1509 pATIDRI->backPitch = pATIDRIServer->backPitch; 1510 1511 pATIDRI->depthOffset = pATIDRIServer->depthOffset; 1512 pATIDRI->depthPitch = pATIDRIServer->depthPitch; 1513 1514 pATIDRI->textureOffset = pATIDRIServer->textureOffset; 1515 pATIDRI->textureSize = pATIDRIServer->textureSize; 1516 pATIDRI->logTextureGranularity = pATIDRIServer->logTextureGranularity; 1517 1518 pATIDRI->regs = pATIDRIServer->regsHandle; 1519 pATIDRI->regsSize = pATIDRIServer->regsSize; 1520 1521 pATIDRI->agp = pATIDRIServer->agpTexHandle; 1522 pATIDRI->agpSize = pATIDRIServer->agpTexMapSize; 1523 pATIDRI->logAgpTextureGranularity = pATIDRIServer->log2AGPTexGran; 1524 pATIDRI->agpTextureOffset = pATIDRIServer->agpTexStart; 1525 1526 return TRUE; 1527} 1528 1529/* 1530 * This function will attempt to get the Mach64 hardware back into shape 1531 * after a resume from disc. Its an extract from ATIDRIAgpInit and ATIDRIFinishScreenInit 1532 * This also calls a new ioctl in the mach64 DRM that in its turn is 1533 * an extraction of the hardware-affecting bits from mach64_do_init_drm() 1534 * (see atidrm.c) 1535 * I am assuming here that pATI->pDRIServerInfo doesn't change 1536 * elsewhere in incomaptible ways. 1537 * How will this code react to resuming after a failed resumeor pci based dri ? 1538 */ 1539void ATIDRIResume( ScreenPtr pScreen ) 1540{ 1541 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 1542 ATIPtr pATI = ATIPTR(pScreenInfo); 1543 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 1544 1545 xf86DrvMsg( pScreen->myNum, X_INFO, 1546 "[RESUME] Attempting to re-init Mach64 hardware.\n"); 1547 1548 if (!pATIDRIServer->IsPCI) { 1549 if (!ATIDRISetAgpMode(pScreen)) 1550 return; 1551 1552 outm( AGP_BASE, drmAgpBase(pATI->drmFD) ); 1553 } 1554} 1555 1556/* The screen is being closed, so clean up any state and free any 1557 * resources used by the DRI. 1558 */ 1559void ATIDRICloseScreen( ScreenPtr pScreen ) 1560{ 1561 ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; 1562 ATIPtr pATI = ATIPTR(pScreenInfo); 1563 ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; 1564 drmMach64Init info; 1565 1566 /* Stop interrupt generation and handling if used */ 1567 if ( pATI->irq > 0 ) { 1568 if ( drmCtlUninstHandler(pATI->drmFD) != 0 ) { 1569 xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, 1570 "[drm] Error uninstalling interrupt handler for IRQ %d\n", pATI->irq); 1571 } else { 1572 xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, 1573 "[drm] Uninstalled interrupt handler for IRQ %d\n", pATI->irq); 1574 } 1575 pATI->irq = 0; 1576 } 1577 1578 /* De-allocate DMA buffers */ 1579 if ( pATIDRIServer->drmBuffers ) { 1580 drmUnmapBufs( pATIDRIServer->drmBuffers ); 1581 pATIDRIServer->drmBuffers = NULL; 1582 } 1583 1584 /* De-allocate all kernel resources */ 1585 memset(&info, 0, sizeof(drmMach64Init)); 1586 info.func = DRM_MACH64_CLEANUP_DMA; 1587 drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT, 1588 &info, sizeof(drmMach64Init) ); 1589 1590 /* De-allocate all AGP resources */ 1591 if ( pATIDRIServer->agpTexMap ) { 1592 drmUnmap( pATIDRIServer->agpTexMap, pATIDRIServer->agpTexMapSize ); 1593 pATIDRIServer->agpTexMap = NULL; 1594 } 1595 if ( pATIDRIServer->bufferMap ) { 1596 drmUnmap( pATIDRIServer->bufferMap, pATIDRIServer->bufferMapSize ); 1597 pATIDRIServer->bufferMap = NULL; 1598 } 1599 if ( pATIDRIServer->ringMap ) { 1600 drmUnmap( pATIDRIServer->ringMap, pATIDRIServer->ringMapSize ); 1601 pATIDRIServer->ringMap = NULL; 1602 } 1603 if ( pATIDRIServer->agpHandle ) { 1604 drmAgpUnbind( pATI->drmFD, pATIDRIServer->agpHandle ); 1605 drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle ); 1606 pATIDRIServer->agpHandle = 0; 1607 drmAgpRelease( pATI->drmFD ); 1608 } 1609 1610 /* De-allocate all PCI resources */ 1611 if ( pATIDRIServer->IsPCI && pATIDRIServer->ringHandle ) { 1612 drmRmMap( pATI->drmFD, pATIDRIServer->ringHandle ); 1613 pATIDRIServer->ringHandle = 0; 1614 } 1615 1616 /* De-allocate all DRI resources */ 1617 DRICloseScreen( pScreen ); 1618 1619 /* De-allocate all DRI data structures */ 1620 if ( pATI->pDRIInfo ) { 1621 if ( pATI->pDRIInfo->devPrivate ) { 1622 xfree( pATI->pDRIInfo->devPrivate ); 1623 pATI->pDRIInfo->devPrivate = NULL; 1624 } 1625 DRIDestroyInfoRec( pATI->pDRIInfo ); 1626 pATI->pDRIInfo = NULL; 1627 } 1628 if ( pATI->pDRIServerInfo ) { 1629 xfree( pATI->pDRIServerInfo ); 1630 pATI->pDRIServerInfo = NULL; 1631 } 1632 if ( pATI->pVisualConfigs ) { 1633 xfree( pATI->pVisualConfigs ); 1634 pATI->pVisualConfigs = NULL; 1635 } 1636 if ( pATI->pVisualConfigsPriv ) { 1637 xfree( pATI->pVisualConfigsPriv ); 1638 pATI->pVisualConfigsPriv = NULL; 1639 } 1640} 1641