via_dri.c revision 7e6fb56f
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 pDRIInfo->busIdString = xalloc(64); 603 sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", 604#ifdef XSERVER_LIBPCIACCESS 605 ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus), 606 pVia->PciInfo->dev, pVia->PciInfo->func 607#else 608 ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum, 609 ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum, 610 ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum 611#endif 612 ); 613 pDRIInfo->ddxDriverMajorVersion = VIA_DRIDDX_VERSION_MAJOR; 614 pDRIInfo->ddxDriverMinorVersion = VIA_DRIDDX_VERSION_MINOR; 615 pDRIInfo->ddxDriverPatchVersion = VIA_DRIDDX_VERSION_PATCH; 616#if (DRIINFO_MAJOR_VERSION == 5) 617 pDRIInfo->frameBufferPhysicalAddress = (pointer) pVia->FrameBufferBase; 618#else 619 pDRIInfo->frameBufferPhysicalAddress = pVia->FrameBufferBase; 620#endif 621 pDRIInfo->frameBufferSize = pVia->videoRambytes; 622 623 pDRIInfo->frameBufferStride = (pScrn->displayWidth * 624 pScrn->bitsPerPixel / 8); 625 pDRIInfo->ddxDrawableTableEntry = VIA_MAX_DRAWABLES; 626 627 if (SAREA_MAX_DRAWABLES < VIA_MAX_DRAWABLES) 628 pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; 629 else 630 pDRIInfo->maxDrawableTableEntry = VIA_MAX_DRAWABLES; 631 632#ifdef NOT_DONE 633 /* FIXME: need to extend DRI protocol to pass this size back to client 634 * for SAREA mapping that includes a device private record. */ 635 pDRIInfo->SAREASize = ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */ 636 /* + shared memory device private rec */ 637#else 638 /* For now the mapping works by using a fixed size defined 639 * in the SAREA header. */ 640 if (sizeof(XF86DRISAREARec) + sizeof(drm_via_sarea_t) > SAREA_MAX) { 641 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Data does not fit in SAREA\n"); 642 DRIDestroyInfoRec(pVia->pDRIInfo); 643 pVia->pDRIInfo = NULL; 644 return FALSE; 645 } 646 pDRIInfo->SAREASize = SAREA_MAX; 647#endif 648 649 if (!(pVIADRI = (VIADRIPtr) xcalloc(sizeof(VIADRIRec), 1))) { 650 DRIDestroyInfoRec(pVia->pDRIInfo); 651 pVia->pDRIInfo = NULL; 652 return FALSE; 653 } 654 pDRIInfo->devPrivate = pVIADRI; 655 pDRIInfo->devPrivateSize = sizeof(VIADRIRec); 656 pDRIInfo->contextSize = sizeof(VIADRIContextRec); 657 658 pDRIInfo->CreateContext = VIACreateContext; 659 pDRIInfo->DestroyContext = VIADestroyContext; 660 pDRIInfo->SwapContext = VIADRISwapContext; 661 pDRIInfo->InitBuffers = VIADRIInitBuffers; 662 pDRIInfo->MoveBuffers = VIADRIMoveBuffers; 663 pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 664 665 if (!DRIScreenInit(pScreen, pDRIInfo, &pVia->drmFD)) { 666 xf86DrvMsg(pScreen->myNum, X_ERROR, 667 "[dri] DRIScreenInit failed. Disabling DRI.\n"); 668 xfree(pDRIInfo->devPrivate); 669 pDRIInfo->devPrivate = NULL; 670 DRIDestroyInfoRec(pVia->pDRIInfo); 671 pVia->pDRIInfo = NULL; 672 pVia->drmFD = -1; 673 return FALSE; 674 } 675 676 if (NULL == (drmVer = drmGetVersion(pVia->drmFD))) { 677 VIADRICloseScreen(pScreen); 678 return FALSE; 679 } 680 pVia->drmVerMajor = drmVer->version_major; 681 pVia->drmVerMinor = drmVer->version_minor; 682 pVia->drmVerPL = drmVer->version_patchlevel; 683 684 if ((drmVer->version_major < drmExpected.major) || 685 (drmVer->version_major > drmCompat.major) || 686 ((drmVer->version_major == drmExpected.major) && 687 (drmVer->version_minor < drmExpected.minor))) { 688 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 689 "[dri] Kernel drm is not compatible with this driver.\n" 690 "[dri] Kernel drm version is %d.%d.%d, " 691 "and I can work with versions %d.%d.x - %d.x.x.\n" 692 "[dri] Update either this 2D driver or your kernel DRM. " 693 "Disabling DRI.\n", 694 drmVer->version_major, drmVer->version_minor, 695 drmVer->version_patchlevel, 696 drmExpected.major, drmExpected.minor, drmCompat.major); 697 drmFreeVersion(drmVer); 698 VIADRICloseScreen(pScreen); 699 return FALSE; 700 } 701 drmFreeVersion(drmVer); 702 703 if (!(VIAInitVisualConfigs(pScreen))) { 704 VIADRICloseScreen(pScreen); 705 return FALSE; 706 } 707 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized.\n"); 708 709 /* DRIScreenInit doesn't add all the common mappings. 710 * Add additional mappings here. */ 711 if (!VIADRIMapInit(pScreen, pVia)) { 712 VIADRICloseScreen(pScreen); 713 return FALSE; 714 } 715 pVIADRI->regs.size = VIA_MMIO_REGSIZE; 716 pVIADRI->regs.handle = pVia->registerHandle; 717 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] mmio Registers = 0x%08lx\n", 718 (unsigned long)pVIADRI->regs.handle); 719 720 pVIADRI->drixinerama = FALSE; 721 722 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] mmio mapped.\n"); 723 724 return TRUE; 725} 726 727void 728VIADRICloseScreen(ScreenPtr pScreen) 729{ 730 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 731 VIAPtr pVia = VIAPTR(pScrn); 732 VIADRIPtr pVIADRI; 733 734 VIADRIRingBufferCleanup(pScrn); 735 if (pVia->agpSize) { 736 drmUnmap(pVia->agpMappedAddr, pVia->agpSize); 737 drmRmMap(pVia->drmFD, pVia->agpHandle); 738 drmAgpUnbind(pVia->drmFD, pVia->agpHandle); 739 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Freeing agp memory\n"); 740 drmAgpFree(pVia->drmFD, pVia->agpHandle); 741 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Releasing agp module\n"); 742 drmAgpRelease(pVia->drmFD); 743 } 744 745 DRICloseScreen(pScreen); 746 VIAFreeLinear(&pVia->driOffScreenMem); 747 748 if (pVia->pDRIInfo) { 749 if ((pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate)) { 750 VIADRIIrqExit(pScrn, pVIADRI); 751 xfree(pVIADRI); 752 pVia->pDRIInfo->devPrivate = NULL; 753 } 754 DRIDestroyInfoRec(pVia->pDRIInfo); 755 pVia->pDRIInfo = NULL; 756 } 757 758 if (pVia->pVisualConfigs) { 759 xfree(pVia->pVisualConfigs); 760 pVia->pVisualConfigs = NULL; 761 } 762 if (pVia->pVisualConfigsPriv) { 763 xfree(pVia->pVisualConfigsPriv); 764 pVia->pVisualConfigsPriv = NULL; 765 } 766} 767 768/* TODO: xserver receives driver's swapping event and does something 769 * according the data initialized in this function. 770 */ 771static Bool 772VIACreateContext(ScreenPtr pScreen, VisualPtr visual, 773 drm_context_t hwContext, void *pVisualConfigPriv, 774 DRIContextType contextStore) 775{ 776 return TRUE; 777} 778 779static void 780VIADestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 781 DRIContextType contextStore) 782{ 783} 784 785Bool 786VIADRIFinishScreenInit(ScreenPtr pScreen) 787{ 788 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 789 VIAPtr pVia = VIAPTR(pScrn); 790 VIADRIPtr pVIADRI; 791 792 pVia->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 793 794 pVia->IsPCI = !VIADRIAgpInit(pScreen, pVia); 795 796 if (pVia->IsPCI) { 797 VIADRIPciInit(pScreen, pVia); 798 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Using PCI.\n"); 799 } else 800 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Using AGP.\n"); 801 802 if (!(VIADRIFBInit(pScreen, pVia))) { 803 VIADRICloseScreen(pScreen); 804 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 805 "[dri] Frame buffer initialization failed.\n"); 806 return FALSE; 807 } 808 809 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Frame buffer initialized.\n"); 810 811 DRIFinishScreenInit(pScreen); 812 813 if (!VIADRIKernelInit(pScreen, pVia)) { 814 VIADRICloseScreen(pScreen); 815 return FALSE; 816 } 817 xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Kernel data initialized.\n"); 818 819 /* Set SAREA value. */ 820 { 821 drm_via_sarea_t *saPriv; 822 823 saPriv = (drm_via_sarea_t *) DRIGetSAREAPrivate(pScreen); 824 assert(saPriv); 825 memset(saPriv, 0, sizeof(*saPriv)); 826 saPriv->ctxOwner = -1; 827 } 828 pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate; 829 pVIADRI->deviceID = pVia->Chipset; 830 pVIADRI->width = pScrn->virtualX; 831 pVIADRI->height = pScrn->virtualY; 832 pVIADRI->mem = pScrn->videoRam * 1024; 833 pVIADRI->bytesPerPixel = (pScrn->bitsPerPixel + 7) / 8; 834 pVIADRI->sarea_priv_offset = sizeof(XF86DRISAREARec); 835 /* TODO */ 836 pVIADRI->scrnX = pVIADRI->width; 837 pVIADRI->scrnY = pVIADRI->height; 838 839 /* Initialize IRQ. */ 840 if (pVia->DRIIrqEnable) 841 VIADRIIrqInit(pScrn, pVIADRI); 842 843 pVIADRI->ringBufActive = 0; 844 VIADRIRingBufferInit(pScrn); 845 return TRUE; 846} 847 848static void 849VIADRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 850 DRIContextType oldContextType, void *oldContext, 851 DRIContextType newContextType, void *newContext) 852{ 853#if 0 854 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 855 VIAPtr pVia = VIAPTR(pScrn); 856#endif 857 return; 858} 859 860static void 861VIADRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) 862{ 863#if 0 864 ScreenPtr pScreen = pWin->drawable.pScreen; 865 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 866 VIAPtr pVia = VIAPTR(pScrn); 867#endif 868 return; 869} 870 871static void 872VIADRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 873 RegionPtr prgnSrc, CARD32 index) 874{ 875#if 0 876 ScreenPtr pScreen = pParent->drawable.pScreen; 877 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 878 VIAPtr pVia = VIAPTR(pScrn); 879#endif 880 return; 881} 882 883/* Initialize the kernel data structures. */ 884static Bool 885VIADRIKernelInit(ScreenPtr pScreen, VIAPtr pVia) 886{ 887 drm_via_init_t drmInfo; 888 889 memset(&drmInfo, 0, sizeof(drm_via_init_t)); 890 drmInfo.func = VIA_INIT_MAP; 891 drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); 892 drmInfo.fb_offset = pVia->frameBufferHandle; 893 drmInfo.mmio_offset = pVia->registerHandle; 894 895 if (pVia->IsPCI) { 896 drmInfo.agpAddr = (CARD32) NULL; 897 } else { 898 /*For AMD64*/ 899#ifndef __x86_64__ 900 drmInfo.agpAddr = (CARD32)pVia->agpAddr; 901#else 902 drmInfo.agpAddr = (CARD64)pVia->agpAddr; 903#endif 904 } 905 906 if ((drmCommandWrite(pVia->drmFD, DRM_VIA_MAP_INIT, &drmInfo, 907 sizeof(drm_via_init_t))) < 0) 908 return FALSE; 909 910 return TRUE; 911} 912 913/* Add a map for the MMIO registers. */ 914static Bool 915VIADRIMapInit(ScreenPtr pScreen, VIAPtr pVia) 916{ 917 int flags = DRM_READ_ONLY; 918 919 if (drmAddMap(pVia->drmFD, pVia->MmioBase, VIA_MMIO_REGSIZE, 920 DRM_REGISTERS, flags, &pVia->registerHandle) < 0) { 921 return FALSE; 922 } 923 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] register handle = 0x%08lx\n", 924 (unsigned long)pVia->registerHandle); 925 if (drmAddMap(pVia->drmFD, pVia->FrameBufferBase, pVia->videoRambytes, 926 DRM_FRAME_BUFFER, 0, &pVia->frameBufferHandle) < 0) { 927 return FALSE; 928 } 929 xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = 0x%08lx\n", 930 (unsigned long)pVia->frameBufferHandle); 931 932 return TRUE; 933} 934 935#define DRM_VIA_BLIT_MAX_SIZE (2048*2048*4) 936 937static int 938viaDRIFBMemcpy(int fd, unsigned long fbOffset, unsigned char *addr, 939 unsigned long size, Bool toFB) 940{ 941 int err; 942 drm_via_dmablit_t blit; 943 unsigned long curSize; 944 945 do { 946 curSize = (size > DRM_VIA_BLIT_MAX_SIZE) ? DRM_VIA_BLIT_MAX_SIZE : size; 947 948 blit.num_lines = 1; 949 blit.line_length = curSize; 950 blit.fb_addr = fbOffset; 951 blit.fb_stride = ALIGN_TO(curSize, 16); 952 blit.mem_addr = addr; 953 blit.mem_stride = blit.fb_stride; 954 blit.to_fb = (toFB) ? 1 : 0; 955 956 do { 957 err = drmCommandWriteRead(fd, DRM_VIA_DMA_BLIT, 958 &blit, sizeof(blit)); 959 } while (-EAGAIN == err); 960 if (err) 961 return err; 962 963 do { 964 err = drmCommandWriteRead(fd, DRM_VIA_BLIT_SYNC, 965 &blit.sync, sizeof(blit.sync)); 966 } while (-EAGAIN == err); 967 if (err) 968 return err; 969 970 fbOffset += curSize; 971 addr += curSize; 972 size -= curSize; 973 974 } while (size > 0); 975 return 0; 976} 977 978 979void 980viaDRIOffscreenSave(ScrnInfoPtr pScrn) 981{ 982 VIAPtr pVia = VIAPTR(pScrn); 983 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 984 unsigned char *saveAddr = pVia->FBBase + pVIADRI->fbOffset; 985 unsigned long saveSize = pVIADRI->fbSize; 986 unsigned long curSize; 987 int err; 988 989 if (pVia->driOffScreenSave) 990 free(pVia->driOffScreenSave); 991 992 pVia->driOffScreenSave = malloc(saveSize + 16); 993 if (pVia->driOffScreenSave) { 994 if ((pVia->drmVerMajor == 2) && (pVia->drmVerMinor >= 8)) { 995 err = viaDRIFBMemcpy(pVia->drmFD, pVIADRI->fbOffset, 996 (unsigned char *) 997 ALIGN_TO((unsigned long) 998 pVia->driOffScreenSave, 16), 999 saveSize, FALSE); 1000 if (!err) 1001 return; 1002 1003 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1004 "Hardware backup of DRI offscreen memory failed: %s.\n" 1005 "\tUsing slow software backup instead.\n", 1006 strerror(-err)); 1007 } 1008 memcpy((void *)ALIGN_TO((unsigned long)pVia->driOffScreenSave, 16), 1009 saveAddr, saveSize); 1010 1011 } else { 1012 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1013 "Out of memory trying to backup DRI offscreen memory.\n"); 1014 } 1015 return; 1016} 1017 1018void 1019viaDRIOffscreenRestore(ScrnInfoPtr pScrn) 1020{ 1021 VIAPtr pVia = VIAPTR(pScrn); 1022 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 1023 1024 unsigned char *saveAddr = pVia->FBBase + pVIADRI->fbOffset; 1025 unsigned long saveSize = pVIADRI->fbSize; 1026 1027 if (pVia->driOffScreenSave) { 1028 memcpy(saveAddr, 1029 (void *)ALIGN_TO((unsigned long)pVia->driOffScreenSave, 16), 1030 saveSize); 1031 free(pVia->driOffScreenSave); 1032 pVia->driOffScreenSave = NULL; 1033 } 1034} 1035