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