via_dri.c revision 485acf3e
1/* 2 * Copyright 2005-2008 The Openchrome Project [openchrome.org] 3 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 4 * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, 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 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the 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 NON-INFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26#ifdef HAVE_CONFIG_H 27#include "config.h" 28#endif 29 30#include "xf86.h" 31#include "xf86_OSproc.h" 32#include "xf86Priv.h" 33 34#include "xf86PciInfo.h" 35#include "xf86Pci.h" 36 37#define _XF86DRI_SERVER_ 38#include "GL/glxtokens.h" 39#include "sarea.h" 40 41#include "via.h" 42#include "via_driver.h" 43#include "via_drm.h" 44#include "via_dri.h" 45#include "via_id.h" 46#include "xf86drm.h" 47 48#ifndef DRIINFO_MAJOR_VERSION 49#define DRIINFO_MAJOR_VERSION 4 50#endif 51#ifndef DRIINFO_MINOR_VERSION 52#define DRIINFO_MINOR_VERSION 0 53#endif 54 55#define VIDEO 0 56#define AGP 1 57#define AGP_CMDBUF_PAGES 512 58#define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES) 59#define VIA_AGP_MODE_MASK 0x17 60#define VIA_AGPv3_MODE 0x08 61#define VIA_AGPv3_8X_MODE 0x02 62#define VIA_AGPv3_4X_MODE 0x01 63#define VIA_AGP_4X_MODE 0x04 64#define VIA_AGP_2X_MODE 0x02 65#define VIA_AGP_1X_MODE 0x01 66#define VIA_AGP_FW_MODE 0x10 67 68extern void GlxSetVisualConfigs(int nconfigs, 69 __GLXvisualConfig * configs, 70 void **configprivs); 71 72typedef struct 73{ 74 int major; 75 int minor; 76 int patchlevel; 77} ViaDRMVersion; 78 79static char VIAKernelDriverName[] = "via"; 80static char VIAClientDriverName[] = "unichrome"; 81static const ViaDRMVersion drmExpected = { 1, 3, 0 }; 82static const ViaDRMVersion drmCompat = { 2, 0, 0 }; 83 84int test_alloc_FB(ScreenPtr pScreen, VIAPtr pVia, int Size); 85int test_alloc_AGP(ScreenPtr pScreen, VIAPtr pVia, int Size); 86static Bool VIAInitVisualConfigs(ScreenPtr pScreen); 87static Bool VIADRIAgpInit(ScreenPtr pScreen, VIAPtr pVia); 88static Bool VIADRIPciInit(ScreenPtr pScreen, VIAPtr pVia); 89static Bool VIADRIFBInit(ScreenPtr pScreen, VIAPtr pVia); 90static Bool VIADRIKernelInit(ScreenPtr pScreen, VIAPtr pVia); 91static Bool VIADRIMapInit(ScreenPtr pScreen, VIAPtr pVia); 92 93static Bool VIACreateContext(ScreenPtr pScreen, VisualPtr visual, 94 drm_context_t hwContext, void *pVisualConfigPriv, 95 DRIContextType contextStore); 96static void VIADestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 97 DRIContextType contextStore); 98static void VIADRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 99 DRIContextType readContextType, 100 void *readContextStore, 101 DRIContextType writeContextType, 102 void *writeContextStore); 103static void VIADRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); 104static void VIADRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 105 RegionPtr prgnSrc, CARD32 index); 106 107 108static void 109VIADRIIrqInit(ScrnInfoPtr pScrn, VIADRIPtr pVIADRI) 110{ 111 VIAPtr pVia = VIAPTR(pScrn); 112 113 pVIADRI->irqEnabled = drmGetInterruptFromBusID 114 (pVia->drmFD, 115#ifdef XSERVER_LIBPCIACCESS 116 ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus), 117 pVia->PciInfo->dev, pVia->PciInfo->func 118#else 119 ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum, 120 ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum, 121 ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum 122#endif 123 ); 124 if ((drmCtlInstHandler(pVia->drmFD, pVIADRI->irqEnabled))) { 125 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 126 "[drm] Failure adding IRQ handler. " 127 "Falling back to IRQ-free operation.\n"); 128 pVIADRI->irqEnabled = 0; 129 } 130 131 if (pVIADRI->irqEnabled) 132 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 133 "[drm] IRQ handler installed, using IRQ %d.\n", 134 pVIADRI->irqEnabled); 135} 136 137static void 138VIADRIIrqExit(ScrnInfoPtr pScrn, VIADRIPtr pVIADRI) 139{ 140 VIAPtr pVia = VIAPTR(pScrn); 141 142 if (pVIADRI->irqEnabled) { 143 if (drmCtlUninstHandler(pVia->drmFD)) { 144 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 145 "[drm] IRQ handler uninstalled.\n"); 146 } else { 147 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 148 "[drm] Could not uninstall IRQ handler.\n"); 149 } 150 } 151} 152 153void 154VIADRIRingBufferCleanup(ScrnInfoPtr pScrn) 155{ 156 VIAPtr pVia = VIAPTR(pScrn); 157 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 158 159 if (pVIADRI->ringBufActive) { 160 drm_via_dma_init_t ringBufInit; 161 162 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 163 "[drm] Cleaning up DMA ring-buffer.\n"); 164 ringBufInit.func = VIA_CLEANUP_DMA; 165 if (drmCommandWrite(pVia->drmFD, DRM_VIA_DMA_INIT, &ringBufInit, 166 sizeof(ringBufInit))) { 167 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 168 "[drm] Failed to clean up DMA ring-buffer: %d\n", errno); 169 } 170 pVIADRI->ringBufActive = 0; 171 } 172} 173 174Bool 175VIADRIRingBufferInit(ScrnInfoPtr pScrn) 176{ 177 VIAPtr pVia = VIAPTR(pScrn); 178 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 179 180 if (pVIADRI->ringBufActive) 181 return TRUE; 182 183 if (pVia->agpEnable) { 184 drm_via_dma_init_t ringBufInit; 185 186 if ((pVia->drmVerMajor == 1) && (pVia->drmVerMinor <= 3)) 187 return FALSE; 188 189 /* 190 * Info frome code-snippet on DRI-DEVEL list; Erdi Chen. 191 */ 192 193 switch (pVia->ChipId) { 194 case PCI_CHIP_VT3314: 195 case PCI_CHIP_VT3259: 196 pVIADRI->reg_pause_addr = 0x40c; 197 break; 198 default: 199 pVIADRI->reg_pause_addr = 0x418; 200 break; 201 } 202 203 ringBufInit.offset = pVia->agpSize; 204 ringBufInit.size = AGP_CMDBUF_SIZE; 205 ringBufInit.reg_pause_addr = pVIADRI->reg_pause_addr; 206 ringBufInit.func = VIA_INIT_DMA; 207 208 if (drmCommandWrite(pVia->drmFD, DRM_VIA_DMA_INIT, &ringBufInit, 209 sizeof(ringBufInit))) { 210 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 211 "[drm] Failed to initialize DMA ring-buffer: %d\n", 212 errno); 213 return FALSE; 214 } 215 216 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 217 "[drm] Initialized AGP ring-buffer, size 0x%lx at AGP " 218 "offset 0x%lx.\n", ringBufInit.size, ringBufInit.offset); 219 pVIADRI->ringBufActive = 1; 220 } 221 return TRUE; 222} 223 224static Bool 225VIASetAgpMode(ScrnInfoPtr pScrn) 226{ 227 VIAPtr pVia = VIAPTR(pScrn); 228 CARD32 mode = drmAgpGetMode(pVia->drmFD); 229 unsigned int vendor = drmAgpVendorId(pVia->drmFD); 230 unsigned int device = drmAgpDeviceId(pVia->drmFD); 231 232 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Detected AGP " 233 "vendor 0x%04x, device 0x%04x\n", vendor, device); 234 235 mode &= ~VIA_AGP_MODE_MASK; 236 if (mode & VIA_AGPv3_MODE) { 237 mode |= VIA_AGPv3_8X_MODE; 238 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Found AGP v3 " 239 "compatible device. Trying AGP 8X mode.\n"); 240 } else { 241 mode |= VIA_AGP_4X_MODE; 242 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Didn't find any AGP v3 " 243 "compatible device. Trying AGP 4X mode.\n"); 244 } 245 246 mode |= VIA_AGP_FW_MODE; 247 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 248 "[drm] Trying to enable AGP fast writes.\n"); 249 250 if (drmAgpEnable(pVia->drmFD, mode) < 0) 251 return FALSE; 252 253 return TRUE; 254} 255 256static Bool 257VIADRIAgpInit(ScreenPtr pScreen, VIAPtr pVia) 258{ 259 int agpPages; 260 unsigned long agpCmdSize; 261 unsigned long agp_phys; 262 drmAddress agpaddr; 263 VIADRIPtr pVIADRI; 264 DRIInfoPtr pDRIInfo; 265 266 pDRIInfo = pVia->pDRIInfo; 267 pVIADRI = pDRIInfo->devPrivate; 268 pVia->agpSize = 0; 269 270 if (drmAgpAcquire(pVia->drmFD) < 0) { 271 xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAcquire failed %d\n", 272 errno); 273 return FALSE; 274 } 275 276 if (!VIASetAgpMode(xf86Screens[pScreen->myNum])) { 277 xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] VIASetAgpMode failed\n"); 278 drmAgpRelease(pVia->drmFD); 279 return FALSE; 280 } 281 282 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] drmAgpEnabled succeeded\n"); 283 284 agpCmdSize = (pVia->agpEnable) ? AGP_CMDBUF_SIZE : 0; 285 286 if (pVia->agpMem * 1024 < agpCmdSize + AGP_PAGE_SIZE) { 287 pVia->agpMem = (agpCmdSize + AGP_PAGE_SIZE) / 1024; 288 xf86DrvMsg(pScreen->myNum, X_INFO, 289 "[drm] Forcing AGP size to %d kB\n", pVia->agpMem); 290 } 291 292 agpPages = (pVia->agpMem * 1024 + AGP_PAGE_SIZE - 1) / AGP_PAGE_SIZE; 293 294 if (drmAgpAlloc(pVia->drmFD, agpPages * AGP_PAGE_SIZE, 295 0, &agp_phys, &pVia->agpHandle) < 0) { 296 xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAlloc failed\n"); 297 drmAgpRelease(pVia->drmFD); 298 return FALSE; 299 } 300 301 if (drmAgpBind(pVia->drmFD, pVia->agpHandle, 0) < 0) { 302 xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpBind failed\n"); 303 drmAgpFree(pVia->drmFD, pVia->agpHandle); 304 drmAgpRelease(pVia->drmFD); 305 return FALSE; 306 } 307 308 /* 309 * Place the ring-buffer last in the AGP region, and restrict the 310 * public map not to include the buffer for security reasons. 311 */ 312 313 pVia->agpSize = agpPages * AGP_PAGE_SIZE - agpCmdSize; 314 pVia->agpAddr = drmAgpBase(pVia->drmFD); 315 xf86DrvMsg(pScreen->myNum, X_INFO, 316 "[drm] agpAddr = 0x%08lx\n", pVia->agpAddr); 317 318 pVIADRI->agp.size = pVia->agpSize; 319 if (drmAddMap(pVia->drmFD, (drm_handle_t) 0, pVIADRI->agp.size, 320 DRM_AGP, 0, &pVIADRI->agp.handle) < 0) { 321 xf86DrvMsg(pScreen->myNum, X_ERROR, 322 "[drm] Failed to map public agp area.\n"); 323 pVIADRI->agp.size = 0; 324 drmAgpUnbind(pVia->drmFD, pVia->agpHandle); 325 drmAgpFree(pVia->drmFD, pVia->agpHandle); 326 drmAgpRelease(pVia->drmFD); 327 return FALSE; 328 } 329 330 drmMap(pVia->drmFD, pVIADRI->agp.handle, pVIADRI->agp.size, &agpaddr); 331 pVia->agpMappedAddr = agpaddr; 332 333 xf86DrvMsg(pScreen->myNum, X_INFO, 334 "[drm] agpBase = %p\n", pVia->agpBase); 335 xf86DrvMsg(pScreen->myNum, X_INFO, 336 "[drm] agpAddr = 0x%08lx\n", pVia->agpAddr); 337 xf86DrvMsg(pScreen->myNum, X_INFO, 338 "[drm] agpSize = 0x%08x\n", pVia->agpSize); 339 xf86DrvMsg(pScreen->myNum, X_INFO, 340 "[drm] agp physical addr = 0x%08lx\n", agp_phys); 341 342 { 343 drm_via_agp_t agp; 344 345 agp.offset = 0; 346 agp.size = pVia->agpSize; 347 if (drmCommandWrite(pVia->drmFD, DRM_VIA_AGP_INIT, &agp, 348 sizeof(drm_via_agp_t)) < 0) { 349 drmUnmap(agpaddr, pVia->agpSize); 350 drmRmMap(pVia->drmFD, pVIADRI->agp.handle); 351 drmAgpUnbind(pVia->drmFD, pVia->agpHandle); 352 drmAgpFree(pVia->drmFD, pVia->agpHandle); 353 drmAgpRelease(pVia->drmFD); 354 return FALSE; 355 } 356 } 357 358 return TRUE; 359} 360 361static Bool 362VIADRIFBInit(ScreenPtr pScreen, VIAPtr pVia) 363{ 364 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 365 int FBSize = pVia->driSize; 366 int FBOffset; 367 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 368 369 if (FBSize < pVia->Bpl) { 370 xf86DrvMsg(pScreen->myNum, X_ERROR, 371 "[drm] No DRM framebuffer heap available.\n" 372 "[drm] Please increase the frame buffer\n" 373 "[drm] memory area in the BIOS. Disabling DRI.\n"); 374 return FALSE; 375 } 376 if (FBSize < 3 * (pScrn->virtualY * pVia->Bpl)) { 377 xf86DrvMsg(pScreen->myNum, X_WARNING, 378 "[drm] The DRM heap and pixmap cache memory may be too\n" 379 "[drm] small for optimal performance. Please increase\n" 380 "[drm] the frame buffer memory area in the BIOS.\n"); 381 } 382 383 pVia->driOffScreenMem.pool = 0; 384 if (Success != viaOffScreenLinear(&pVia->driOffScreenMem, pScrn, FBSize)) { 385 xf86DrvMsg(pScreen->myNum, X_ERROR, 386 "[drm] Failed to allocate offscreen frame buffer area.\n"); 387 return FALSE; 388 } 389 390 FBOffset = pVia->driOffScreenMem.base; 391 392 pVIADRI->fbOffset = FBOffset; 393 pVIADRI->fbSize = FBSize; 394 395 { 396 drm_via_fb_t fb; 397 398 fb.offset = FBOffset; 399 fb.size = FBSize; 400 401 if (drmCommandWrite(pVia->drmFD, DRM_VIA_FB_INIT, &fb, 402 sizeof(drm_via_fb_t)) < 0) { 403 xf86DrvMsg(pScreen->myNum, X_ERROR, 404 "[drm] Failed to initialize frame buffer area.\n"); 405 return FALSE; 406 } else { 407 xf86DrvMsg(pScreen->myNum, X_INFO, 408 "[drm] Using %d bytes for DRM memory heap.\n", FBSize); 409 return TRUE; 410 } 411 } 412} 413 414static Bool 415VIADRIPciInit(ScreenPtr pScreen, VIAPtr pVia) 416{ 417 return TRUE; 418} 419 420static Bool 421VIAInitVisualConfigs(ScreenPtr pScreen) 422{ 423 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 424 VIAPtr pVia = VIAPTR(pScrn); 425 int numConfigs = 0; 426 __GLXvisualConfig *pConfigs = 0; 427 VIAConfigPrivPtr pVIAConfigs = 0; 428 VIAConfigPrivPtr *pVIAConfigPtrs = 0; 429 int i, db, stencil, accum; 430 431 if (pScrn->bitsPerPixel == 16 || pScrn->bitsPerPixel == 32) { 432 numConfigs = 12; 433 if (!(pConfigs = (__GLXvisualConfig *) 434 xcalloc(sizeof(__GLXvisualConfig), numConfigs))) 435 return FALSE; 436 if (!(pVIAConfigs = (VIAConfigPrivPtr) 437 xcalloc(sizeof(VIAConfigPrivRec), numConfigs))) { 438 xfree(pConfigs); 439 return FALSE; 440 } 441 if (!(pVIAConfigPtrs = (VIAConfigPrivPtr *) 442 xcalloc(sizeof(VIAConfigPrivPtr), numConfigs))) { 443 xfree(pConfigs); 444 xfree(pVIAConfigs); 445 return FALSE; 446 } 447 for (i = 0; i < numConfigs; i++) 448 pVIAConfigPtrs[i] = &pVIAConfigs[i]; 449 450 i = 0; 451 for (accum = 0; accum <= 1; accum++) { 452 /* 32bpp depth buffer disabled, as Mesa has limitations */ 453 for (stencil = 0; stencil <= 2; stencil++) { 454 for (db = 0; db <= 1; db++) { 455 pConfigs[i].vid = -1; 456 pConfigs[i].class = -1; 457 pConfigs[i].rgba = TRUE; 458 pConfigs[i].redSize = -1; 459 pConfigs[i].greenSize = -1; 460 pConfigs[i].blueSize = -1; 461 pConfigs[i].redMask = -1; 462 pConfigs[i].greenMask = -1; 463 pConfigs[i].blueMask = -1; 464 if (pScrn->bitsPerPixel == 32) { 465 pConfigs[i].alphaSize = 8; 466 pConfigs[i].alphaMask = 0xFF000000; 467 } else { 468 pConfigs[i].alphaSize = 0; 469 pConfigs[i].alphaMask = 0; 470 } 471 472 if (accum) { 473 pConfigs[i].accumRedSize = 16; 474 pConfigs[i].accumGreenSize = 16; 475 pConfigs[i].accumBlueSize = 16; 476 if (pScrn->bitsPerPixel == 32) 477 pConfigs[i].accumAlphaSize = 16; 478 else 479 pConfigs[i].accumAlphaSize = 0; 480 } else { 481 pConfigs[i].accumRedSize = 0; 482 pConfigs[i].accumGreenSize = 0; 483 pConfigs[i].accumBlueSize = 0; 484 pConfigs[i].accumAlphaSize = 0; 485 } 486 if (!db) 487 pConfigs[i].doubleBuffer = TRUE; 488 else 489 pConfigs[i].doubleBuffer = FALSE; 490 491 pConfigs[i].stereo = FALSE; 492 pConfigs[i].bufferSize = -1; 493 494 switch (stencil) { 495 case 0: 496 pConfigs[i].depthSize = 24; 497 pConfigs[i].stencilSize = 8; 498 break; 499 case 1: 500 pConfigs[i].depthSize = 16; 501 pConfigs[i].stencilSize = 0; 502 break; 503 case 2: 504 pConfigs[i].depthSize = 0; 505 pConfigs[i].stencilSize = 0; 506 break; 507 case 3: 508 pConfigs[i].depthSize = 32; 509 pConfigs[i].stencilSize = 0; 510 break; 511 } 512 513 pConfigs[i].auxBuffers = 0; 514 pConfigs[i].level = 0; 515 if (accum) 516 pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; 517 else 518 pConfigs[i].visualRating = GLX_NONE_EXT; 519 pConfigs[i].transparentPixel = GLX_NONE_EXT; 520 pConfigs[i].transparentRed = 0; 521 pConfigs[i].transparentGreen = 0; 522 pConfigs[i].transparentBlue = 0; 523 pConfigs[i].transparentAlpha = 0; 524 pConfigs[i].transparentIndex = 0; 525 i++; 526 } 527 } 528 } 529 530 if (i != numConfigs) { 531 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] Incorrect " 532 "initialization of visuals. Disabling DRI.\n"); 533 return FALSE; 534 } 535 } 536 537 pVia->numVisualConfigs = numConfigs; 538 pVia->pVisualConfigs = pConfigs; 539 pVia->pVisualConfigsPriv = pVIAConfigs; 540 GlxSetVisualConfigs(numConfigs, pConfigs, (void **)pVIAConfigPtrs); 541 542 return TRUE; 543} 544 545Bool 546VIADRIScreenInit(ScreenPtr pScreen) 547{ 548 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 549 VIAPtr pVia = VIAPTR(pScrn); 550 DRIInfoPtr pDRIInfo; 551 VIADRIPtr pVIADRI; 552 drmVersionPtr drmVer; 553 554 /* If symbols or version check fails, we still want this to be NULL. */ 555 pVia->pDRIInfo = NULL; 556 557 /* Check that the GLX, DRI, and DRM modules have been loaded by testing 558 * for canonical symbols in each module. */ 559 if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) 560 return FALSE; 561 if (!xf86LoaderCheckSymbol("drmAvailable")) 562 return FALSE; 563 if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { 564 xf86DrvMsg(pScreen->myNum, X_ERROR, 565 "[dri] VIADRIScreenInit failed (libdri.a is too old).\n"); 566 return FALSE; 567 } 568 569 /* Check the DRI version. */ 570 { 571 int major, minor, patch; 572 573 DRIQueryVersion(&major, &minor, &patch); 574 if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { 575 xf86DrvMsg(pScreen->myNum, X_ERROR, 576 "[dri] VIADRIScreenInit failed -- version mismatch.\n" 577 "[dri] libdri is %d.%d.%d, but %d.%d.x is needed.\n" 578 "[dri] Disabling DRI.\n", 579 major, minor, patch, 580 DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); 581 return FALSE; 582 } 583 } 584 585 pVia->pDRIInfo = DRICreateInfoRec(); 586 if (!pVia->pDRIInfo) 587 return FALSE; 588 589 pDRIInfo = pVia->pDRIInfo; 590 pDRIInfo->drmDriverName = VIAKernelDriverName; 591 switch (pVia->Chipset) { 592 case VIA_K8M890: 593 case VIA_P4M900: 594 case VIA_VX800: 595 case VIA_VX855: 596 pDRIInfo->clientDriverName = "swrast"; 597 break; 598 default: 599 pDRIInfo->clientDriverName = VIAClientDriverName; 600 break; 601 } 602 if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 603 pDRIInfo->busIdString = DRICreatePCIBusID(pVia->PciInfo); 604 } else { 605 pDRIInfo->busIdString = xalloc(64); 606 sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", 607#ifdef XSERVER_LIBPCIACCESS 608 ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus), 609 pVia->PciInfo->dev, pVia->PciInfo->func 610#else 611 ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum, 612 ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum, 613 ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum 614#endif 615 ); 616 } 617 pDRIInfo->ddxDriverMajorVersion = VIA_DRIDDX_VERSION_MAJOR; 618 pDRIInfo->ddxDriverMinorVersion = VIA_DRIDDX_VERSION_MINOR; 619 pDRIInfo->ddxDriverPatchVersion = VIA_DRIDDX_VERSION_PATCH; 620#if (DRIINFO_MAJOR_VERSION == 5) 621 pDRIInfo->frameBufferPhysicalAddress = (pointer) pVia->FrameBufferBase; 622#else 623 pDRIInfo->frameBufferPhysicalAddress = pVia->FrameBufferBase; 624#endif 625 pDRIInfo->frameBufferSize = pVia->videoRambytes; 626 627 pDRIInfo->frameBufferStride = (pScrn->displayWidth * 628 pScrn->bitsPerPixel / 8); 629 pDRIInfo->ddxDrawableTableEntry = VIA_MAX_DRAWABLES; 630 631 if (SAREA_MAX_DRAWABLES < VIA_MAX_DRAWABLES) 632 pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; 633 else 634 pDRIInfo->maxDrawableTableEntry = VIA_MAX_DRAWABLES; 635 636#ifdef NOT_DONE 637 /* FIXME: need to extend DRI protocol to pass this size back to client 638 * for SAREA mapping that includes a device private record. */ 639 pDRIInfo->SAREASize = ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */ 640 /* + shared memory device private rec */ 641#else 642 /* For now the mapping works by using a fixed size defined 643 * in the SAREA header. */ 644 if (sizeof(XF86DRISAREARec) + sizeof(drm_via_sarea_t) > SAREA_MAX) { 645 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Data does not fit in SAREA\n"); 646 DRIDestroyInfoRec(pVia->pDRIInfo); 647 pVia->pDRIInfo = NULL; 648 return FALSE; 649 } 650 pDRIInfo->SAREASize = SAREA_MAX; 651#endif 652 653 if (!(pVIADRI = (VIADRIPtr) xcalloc(sizeof(VIADRIRec), 1))) { 654 DRIDestroyInfoRec(pVia->pDRIInfo); 655 pVia->pDRIInfo = NULL; 656 return FALSE; 657 } 658 pDRIInfo->devPrivate = pVIADRI; 659 pDRIInfo->devPrivateSize = sizeof(VIADRIRec); 660 pDRIInfo->contextSize = sizeof(VIADRIContextRec); 661 662 pDRIInfo->CreateContext = VIACreateContext; 663 pDRIInfo->DestroyContext = VIADestroyContext; 664 pDRIInfo->SwapContext = VIADRISwapContext; 665 pDRIInfo->InitBuffers = VIADRIInitBuffers; 666 pDRIInfo->MoveBuffers = VIADRIMoveBuffers; 667 pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 668 669 if (!DRIScreenInit(pScreen, pDRIInfo, &pVia->drmFD)) { 670 xf86DrvMsg(pScreen->myNum, X_ERROR, 671 "[dri] DRIScreenInit failed. Disabling DRI.\n"); 672 xfree(pDRIInfo->devPrivate); 673 pDRIInfo->devPrivate = NULL; 674 DRIDestroyInfoRec(pVia->pDRIInfo); 675 pVia->pDRIInfo = NULL; 676 pVia->drmFD = -1; 677 return FALSE; 678 } 679 680 if (NULL == (drmVer = drmGetVersion(pVia->drmFD))) { 681 VIADRICloseScreen(pScreen); 682 return FALSE; 683 } 684 pVia->drmVerMajor = drmVer->version_major; 685 pVia->drmVerMinor = drmVer->version_minor; 686 pVia->drmVerPL = drmVer->version_patchlevel; 687 688 if ((drmVer->version_major < drmExpected.major) || 689 (drmVer->version_major > drmCompat.major) || 690 ((drmVer->version_major == drmExpected.major) && 691 (drmVer->version_minor < drmExpected.minor))) { 692 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 693 "[dri] Kernel drm is not compatible with this driver.\n" 694 "[dri] Kernel drm version is %d.%d.%d, " 695 "and I can work with versions %d.%d.x - %d.x.x.\n" 696 "[dri] Update either this 2D driver or your kernel DRM. " 697 "Disabling DRI.\n", 698 drmVer->version_major, drmVer->version_minor, 699 drmVer->version_patchlevel, 700 drmExpected.major, drmExpected.minor, drmCompat.major); 701 drmFreeVersion(drmVer); 702 VIADRICloseScreen(pScreen); 703 return FALSE; 704 } 705 drmFreeVersion(drmVer); 706 707 if (!(VIAInitVisualConfigs(pScreen))) { 708 VIADRICloseScreen(pScreen); 709 return FALSE; 710 } 711 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized.\n"); 712 713 /* DRIScreenInit doesn't add all the common mappings. 714 * Add additional mappings here. */ 715 if (!VIADRIMapInit(pScreen, pVia)) { 716 VIADRICloseScreen(pScreen); 717 return FALSE; 718 } 719 pVIADRI->regs.size = VIA_MMIO_REGSIZE; 720 pVIADRI->regs.handle = pVia->registerHandle; 721 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] mmio Registers = 0x%08lx\n", 722 (unsigned long)pVIADRI->regs.handle); 723 724 pVIADRI->drixinerama = FALSE; 725 726 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] mmio mapped.\n"); 727 728 return TRUE; 729} 730 731void 732VIADRICloseScreen(ScreenPtr pScreen) 733{ 734 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 735 VIAPtr pVia = VIAPTR(pScrn); 736 VIADRIPtr pVIADRI; 737 738 VIADRIRingBufferCleanup(pScrn); 739 if (pVia->agpSize) { 740 drmUnmap(pVia->agpMappedAddr, pVia->agpSize); 741 drmRmMap(pVia->drmFD, pVia->agpHandle); 742 drmAgpUnbind(pVia->drmFD, pVia->agpHandle); 743 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Freeing agp memory\n"); 744 drmAgpFree(pVia->drmFD, pVia->agpHandle); 745 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Releasing agp module\n"); 746 drmAgpRelease(pVia->drmFD); 747 } 748 749 DRICloseScreen(pScreen); 750 VIAFreeLinear(&pVia->driOffScreenMem); 751 752 if (pVia->pDRIInfo) { 753 if ((pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate)) { 754 VIADRIIrqExit(pScrn, pVIADRI); 755 xfree(pVIADRI); 756 pVia->pDRIInfo->devPrivate = NULL; 757 } 758 DRIDestroyInfoRec(pVia->pDRIInfo); 759 pVia->pDRIInfo = NULL; 760 } 761 762 if (pVia->pVisualConfigs) { 763 xfree(pVia->pVisualConfigs); 764 pVia->pVisualConfigs = NULL; 765 } 766 if (pVia->pVisualConfigsPriv) { 767 xfree(pVia->pVisualConfigsPriv); 768 pVia->pVisualConfigsPriv = NULL; 769 } 770} 771 772/* TODO: xserver receives driver's swapping event and does something 773 * according the data initialized in this function. 774 */ 775static Bool 776VIACreateContext(ScreenPtr pScreen, VisualPtr visual, 777 drm_context_t hwContext, void *pVisualConfigPriv, 778 DRIContextType contextStore) 779{ 780 return TRUE; 781} 782 783static void 784VIADestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 785 DRIContextType contextStore) 786{ 787} 788 789Bool 790VIADRIFinishScreenInit(ScreenPtr pScreen) 791{ 792 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 793 VIAPtr pVia = VIAPTR(pScrn); 794 VIADRIPtr pVIADRI; 795 796 pVia->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 797 798 pVia->IsPCI = !VIADRIAgpInit(pScreen, pVia); 799 800 if (pVia->IsPCI) { 801 VIADRIPciInit(pScreen, pVia); 802 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Using PCI.\n"); 803 } else 804 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Using AGP.\n"); 805 806 if (!(VIADRIFBInit(pScreen, pVia))) { 807 VIADRICloseScreen(pScreen); 808 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 809 "[dri] Frame buffer initialization failed.\n"); 810 return FALSE; 811 } 812 813 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Frame buffer initialized.\n"); 814 815 DRIFinishScreenInit(pScreen); 816 817 if (!VIADRIKernelInit(pScreen, pVia)) { 818 VIADRICloseScreen(pScreen); 819 return FALSE; 820 } 821 xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Kernel data initialized.\n"); 822 823 /* Set SAREA value. */ 824 { 825 drm_via_sarea_t *saPriv; 826 827 saPriv = (drm_via_sarea_t *) DRIGetSAREAPrivate(pScreen); 828 assert(saPriv); 829 memset(saPriv, 0, sizeof(*saPriv)); 830 saPriv->ctxOwner = -1; 831 } 832 pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate; 833 pVIADRI->deviceID = pVia->Chipset; 834 pVIADRI->width = pScrn->virtualX; 835 pVIADRI->height = pScrn->virtualY; 836 pVIADRI->mem = pScrn->videoRam * 1024; 837 pVIADRI->bytesPerPixel = (pScrn->bitsPerPixel + 7) / 8; 838 pVIADRI->sarea_priv_offset = sizeof(XF86DRISAREARec); 839 /* TODO */ 840 pVIADRI->scrnX = pVIADRI->width; 841 pVIADRI->scrnY = pVIADRI->height; 842 843 /* Initialize IRQ. */ 844 if (pVia->DRIIrqEnable) 845 VIADRIIrqInit(pScrn, pVIADRI); 846 847 pVIADRI->ringBufActive = 0; 848 VIADRIRingBufferInit(pScrn); 849 return TRUE; 850} 851 852static void 853VIADRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 854 DRIContextType oldContextType, void *oldContext, 855 DRIContextType newContextType, void *newContext) 856{ 857#if 0 858 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 859 VIAPtr pVia = VIAPTR(pScrn); 860#endif 861 return; 862} 863 864static void 865VIADRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) 866{ 867#if 0 868 ScreenPtr pScreen = pWin->drawable.pScreen; 869 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 870 VIAPtr pVia = VIAPTR(pScrn); 871#endif 872 return; 873} 874 875static void 876VIADRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 877 RegionPtr prgnSrc, CARD32 index) 878{ 879#if 0 880 ScreenPtr pScreen = pParent->drawable.pScreen; 881 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 882 VIAPtr pVia = VIAPTR(pScrn); 883#endif 884 return; 885} 886 887/* Initialize the kernel data structures. */ 888static Bool 889VIADRIKernelInit(ScreenPtr pScreen, VIAPtr pVia) 890{ 891 drm_via_init_t drmInfo; 892 893 memset(&drmInfo, 0, sizeof(drm_via_init_t)); 894 drmInfo.func = VIA_INIT_MAP; 895 drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); 896 drmInfo.fb_offset = pVia->frameBufferHandle; 897 drmInfo.mmio_offset = pVia->registerHandle; 898 899 if (pVia->IsPCI) { 900 drmInfo.agpAddr = (CARD32) NULL; 901 } else { 902 /*For AMD64*/ 903#ifndef __x86_64__ 904 drmInfo.agpAddr = (CARD32)pVia->agpAddr; 905#else 906 drmInfo.agpAddr = (CARD64)pVia->agpAddr; 907#endif 908 } 909 910 if ((drmCommandWrite(pVia->drmFD, DRM_VIA_MAP_INIT, &drmInfo, 911 sizeof(drm_via_init_t))) < 0) 912 return FALSE; 913 914 return TRUE; 915} 916 917/* Add a map for the MMIO registers. */ 918static Bool 919VIADRIMapInit(ScreenPtr pScreen, VIAPtr pVia) 920{ 921 int flags = DRM_READ_ONLY; 922 923 if (drmAddMap(pVia->drmFD, pVia->MmioBase, VIA_MMIO_REGSIZE, 924 DRM_REGISTERS, flags, &pVia->registerHandle) < 0) { 925 return FALSE; 926 } 927 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] register handle = 0x%08lx\n", 928 (unsigned long)pVia->registerHandle); 929 if (drmAddMap(pVia->drmFD, pVia->FrameBufferBase, pVia->videoRambytes, 930 DRM_FRAME_BUFFER, 0, &pVia->frameBufferHandle) < 0) { 931 return FALSE; 932 } 933 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = 0x%08lx\n", 934 (unsigned long)pVia->frameBufferHandle); 935 936 return TRUE; 937} 938 939#define DRM_VIA_BLIT_MAX_SIZE (2048*2048*4) 940 941static int 942viaDRIFBMemcpy(int fd, unsigned long fbOffset, unsigned char *addr, 943 unsigned long size, Bool toFB) 944{ 945 int err; 946 drm_via_dmablit_t blit; 947 unsigned long curSize; 948 949 do { 950 curSize = (size > DRM_VIA_BLIT_MAX_SIZE) ? DRM_VIA_BLIT_MAX_SIZE : size; 951 952 blit.num_lines = 1; 953 blit.line_length = curSize; 954 blit.fb_addr = fbOffset; 955 blit.fb_stride = ALIGN_TO(curSize, 16); 956 blit.mem_addr = addr; 957 blit.mem_stride = blit.fb_stride; 958 blit.to_fb = (toFB) ? 1 : 0; 959 960 do { 961 err = drmCommandWriteRead(fd, DRM_VIA_DMA_BLIT, 962 &blit, sizeof(blit)); 963 } while (-EAGAIN == err); 964 if (err) 965 return err; 966 967 do { 968 err = drmCommandWriteRead(fd, DRM_VIA_BLIT_SYNC, 969 &blit.sync, sizeof(blit.sync)); 970 } while (-EAGAIN == err); 971 if (err) 972 return err; 973 974 fbOffset += curSize; 975 addr += curSize; 976 size -= curSize; 977 978 } while (size > 0); 979 return 0; 980} 981 982 983void 984viaDRIOffscreenSave(ScrnInfoPtr pScrn) 985{ 986 VIAPtr pVia = VIAPTR(pScrn); 987 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 988 unsigned char *saveAddr = pVia->FBBase + pVIADRI->fbOffset; 989 unsigned long saveSize = pVIADRI->fbSize; 990 unsigned long curSize; 991 int err; 992 993 if (pVia->driOffScreenSave) 994 free(pVia->driOffScreenSave); 995 996 pVia->driOffScreenSave = malloc(saveSize + 16); 997 if (pVia->driOffScreenSave) { 998 if ((pVia->drmVerMajor == 2) && (pVia->drmVerMinor >= 8)) { 999 err = viaDRIFBMemcpy(pVia->drmFD, pVIADRI->fbOffset, 1000 (unsigned char *) 1001 ALIGN_TO((unsigned long) 1002 pVia->driOffScreenSave, 16), 1003 saveSize, FALSE); 1004 if (!err) 1005 return; 1006 1007 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1008 "Hardware backup of DRI offscreen memory failed: %s.\n" 1009 "\tUsing slow software backup instead.\n", 1010 strerror(-err)); 1011 } 1012 memcpy((void *)ALIGN_TO((unsigned long)pVia->driOffScreenSave, 16), 1013 saveAddr, saveSize); 1014 1015 } else { 1016 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1017 "Out of memory trying to backup DRI offscreen memory.\n"); 1018 } 1019 return; 1020} 1021 1022void 1023viaDRIOffscreenRestore(ScrnInfoPtr pScrn) 1024{ 1025 VIAPtr pVia = VIAPTR(pScrn); 1026 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 1027 1028 unsigned char *saveAddr = pVia->FBBase + pVIADRI->fbOffset; 1029 unsigned long saveSize = pVIADRI->fbSize; 1030 1031 if (pVia->driOffScreenSave) { 1032 memcpy(saveAddr, 1033 (void *)ALIGN_TO((unsigned long)pVia->driOffScreenSave, 16), 1034 saveSize); 1035 free(pVia->driOffScreenSave); 1036 pVia->driOffScreenSave = NULL; 1037 } 1038} 1039