via_dri.c revision 485acf3e
17e6fb56fSmrg/* 27e6fb56fSmrg * Copyright 2005-2008 The Openchrome Project [openchrome.org] 37e6fb56fSmrg * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 47e6fb56fSmrg * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 57e6fb56fSmrg * 67e6fb56fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 77e6fb56fSmrg * copy of this software and associated documentation files (the "Software"), 87e6fb56fSmrg * to deal in the Software without restriction, including without limitation 97e6fb56fSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license, 107e6fb56fSmrg * and/or sell copies of the Software, and to permit persons to whom the 117e6fb56fSmrg * Software is furnished to do so, subject to the following conditions: 127e6fb56fSmrg * 137e6fb56fSmrg * The above copyright notice and this permission notice (including the 147e6fb56fSmrg * next paragraph) shall be included in all copies or substantial portions 157e6fb56fSmrg * of the Software. 167e6fb56fSmrg * 177e6fb56fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 187e6fb56fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197e6fb56fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 207e6fb56fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 217e6fb56fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 227e6fb56fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 237e6fb56fSmrg * DEALINGS IN THE SOFTWARE. 247e6fb56fSmrg */ 257e6fb56fSmrg 267e6fb56fSmrg#ifdef HAVE_CONFIG_H 277e6fb56fSmrg#include "config.h" 287e6fb56fSmrg#endif 297e6fb56fSmrg 307e6fb56fSmrg#include "xf86.h" 317e6fb56fSmrg#include "xf86_OSproc.h" 327e6fb56fSmrg#include "xf86Priv.h" 337e6fb56fSmrg 347e6fb56fSmrg#include "xf86PciInfo.h" 357e6fb56fSmrg#include "xf86Pci.h" 367e6fb56fSmrg 377e6fb56fSmrg#define _XF86DRI_SERVER_ 387e6fb56fSmrg#include "GL/glxtokens.h" 397e6fb56fSmrg#include "sarea.h" 407e6fb56fSmrg 417e6fb56fSmrg#include "via.h" 427e6fb56fSmrg#include "via_driver.h" 437e6fb56fSmrg#include "via_drm.h" 447e6fb56fSmrg#include "via_dri.h" 457e6fb56fSmrg#include "via_id.h" 467e6fb56fSmrg#include "xf86drm.h" 477e6fb56fSmrg 487e6fb56fSmrg#ifndef DRIINFO_MAJOR_VERSION 497e6fb56fSmrg#define DRIINFO_MAJOR_VERSION 4 507e6fb56fSmrg#endif 517e6fb56fSmrg#ifndef DRIINFO_MINOR_VERSION 527e6fb56fSmrg#define DRIINFO_MINOR_VERSION 0 537e6fb56fSmrg#endif 547e6fb56fSmrg 557e6fb56fSmrg#define VIDEO 0 567e6fb56fSmrg#define AGP 1 577e6fb56fSmrg#define AGP_CMDBUF_PAGES 512 587e6fb56fSmrg#define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES) 597e6fb56fSmrg#define VIA_AGP_MODE_MASK 0x17 607e6fb56fSmrg#define VIA_AGPv3_MODE 0x08 617e6fb56fSmrg#define VIA_AGPv3_8X_MODE 0x02 627e6fb56fSmrg#define VIA_AGPv3_4X_MODE 0x01 637e6fb56fSmrg#define VIA_AGP_4X_MODE 0x04 647e6fb56fSmrg#define VIA_AGP_2X_MODE 0x02 657e6fb56fSmrg#define VIA_AGP_1X_MODE 0x01 667e6fb56fSmrg#define VIA_AGP_FW_MODE 0x10 677e6fb56fSmrg 687e6fb56fSmrgextern void GlxSetVisualConfigs(int nconfigs, 697e6fb56fSmrg __GLXvisualConfig * configs, 707e6fb56fSmrg void **configprivs); 717e6fb56fSmrg 727e6fb56fSmrgtypedef struct 737e6fb56fSmrg{ 747e6fb56fSmrg int major; 757e6fb56fSmrg int minor; 767e6fb56fSmrg int patchlevel; 777e6fb56fSmrg} ViaDRMVersion; 787e6fb56fSmrg 797e6fb56fSmrgstatic char VIAKernelDriverName[] = "via"; 807e6fb56fSmrgstatic char VIAClientDriverName[] = "unichrome"; 817e6fb56fSmrgstatic const ViaDRMVersion drmExpected = { 1, 3, 0 }; 827e6fb56fSmrgstatic const ViaDRMVersion drmCompat = { 2, 0, 0 }; 837e6fb56fSmrg 847e6fb56fSmrgint test_alloc_FB(ScreenPtr pScreen, VIAPtr pVia, int Size); 857e6fb56fSmrgint test_alloc_AGP(ScreenPtr pScreen, VIAPtr pVia, int Size); 867e6fb56fSmrgstatic Bool VIAInitVisualConfigs(ScreenPtr pScreen); 877e6fb56fSmrgstatic Bool VIADRIAgpInit(ScreenPtr pScreen, VIAPtr pVia); 887e6fb56fSmrgstatic Bool VIADRIPciInit(ScreenPtr pScreen, VIAPtr pVia); 897e6fb56fSmrgstatic Bool VIADRIFBInit(ScreenPtr pScreen, VIAPtr pVia); 907e6fb56fSmrgstatic Bool VIADRIKernelInit(ScreenPtr pScreen, VIAPtr pVia); 917e6fb56fSmrgstatic Bool VIADRIMapInit(ScreenPtr pScreen, VIAPtr pVia); 927e6fb56fSmrg 937e6fb56fSmrgstatic Bool VIACreateContext(ScreenPtr pScreen, VisualPtr visual, 947e6fb56fSmrg drm_context_t hwContext, void *pVisualConfigPriv, 957e6fb56fSmrg DRIContextType contextStore); 967e6fb56fSmrgstatic void VIADestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 977e6fb56fSmrg DRIContextType contextStore); 987e6fb56fSmrgstatic void VIADRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 997e6fb56fSmrg DRIContextType readContextType, 1007e6fb56fSmrg void *readContextStore, 1017e6fb56fSmrg DRIContextType writeContextType, 1027e6fb56fSmrg void *writeContextStore); 1037e6fb56fSmrgstatic void VIADRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); 1047e6fb56fSmrgstatic void VIADRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 1057e6fb56fSmrg RegionPtr prgnSrc, CARD32 index); 1067e6fb56fSmrg 1077e6fb56fSmrg 1087e6fb56fSmrgstatic void 1097e6fb56fSmrgVIADRIIrqInit(ScrnInfoPtr pScrn, VIADRIPtr pVIADRI) 1107e6fb56fSmrg{ 1117e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 1127e6fb56fSmrg 1137e6fb56fSmrg pVIADRI->irqEnabled = drmGetInterruptFromBusID 1147e6fb56fSmrg (pVia->drmFD, 1157e6fb56fSmrg#ifdef XSERVER_LIBPCIACCESS 1167e6fb56fSmrg ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus), 1177e6fb56fSmrg pVia->PciInfo->dev, pVia->PciInfo->func 1187e6fb56fSmrg#else 1197e6fb56fSmrg ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum, 1207e6fb56fSmrg ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum, 1217e6fb56fSmrg ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum 1227e6fb56fSmrg#endif 1237e6fb56fSmrg ); 1247e6fb56fSmrg if ((drmCtlInstHandler(pVia->drmFD, pVIADRI->irqEnabled))) { 1257e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1267e6fb56fSmrg "[drm] Failure adding IRQ handler. " 1277e6fb56fSmrg "Falling back to IRQ-free operation.\n"); 1287e6fb56fSmrg pVIADRI->irqEnabled = 0; 1297e6fb56fSmrg } 1307e6fb56fSmrg 1317e6fb56fSmrg if (pVIADRI->irqEnabled) 1327e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1337e6fb56fSmrg "[drm] IRQ handler installed, using IRQ %d.\n", 1347e6fb56fSmrg pVIADRI->irqEnabled); 1357e6fb56fSmrg} 1367e6fb56fSmrg 1377e6fb56fSmrgstatic void 1387e6fb56fSmrgVIADRIIrqExit(ScrnInfoPtr pScrn, VIADRIPtr pVIADRI) 1397e6fb56fSmrg{ 1407e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 1417e6fb56fSmrg 1427e6fb56fSmrg if (pVIADRI->irqEnabled) { 1437e6fb56fSmrg if (drmCtlUninstHandler(pVia->drmFD)) { 1447e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1457e6fb56fSmrg "[drm] IRQ handler uninstalled.\n"); 1467e6fb56fSmrg } else { 1477e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1487e6fb56fSmrg "[drm] Could not uninstall IRQ handler.\n"); 1497e6fb56fSmrg } 1507e6fb56fSmrg } 1517e6fb56fSmrg} 1527e6fb56fSmrg 1537e6fb56fSmrgvoid 1547e6fb56fSmrgVIADRIRingBufferCleanup(ScrnInfoPtr pScrn) 1557e6fb56fSmrg{ 1567e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 1577e6fb56fSmrg VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 1587e6fb56fSmrg 1597e6fb56fSmrg if (pVIADRI->ringBufActive) { 1607e6fb56fSmrg drm_via_dma_init_t ringBufInit; 1617e6fb56fSmrg 1627e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1637e6fb56fSmrg "[drm] Cleaning up DMA ring-buffer.\n"); 1647e6fb56fSmrg ringBufInit.func = VIA_CLEANUP_DMA; 1657e6fb56fSmrg if (drmCommandWrite(pVia->drmFD, DRM_VIA_DMA_INIT, &ringBufInit, 1667e6fb56fSmrg sizeof(ringBufInit))) { 1677e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1687e6fb56fSmrg "[drm] Failed to clean up DMA ring-buffer: %d\n", errno); 1697e6fb56fSmrg } 1707e6fb56fSmrg pVIADRI->ringBufActive = 0; 1717e6fb56fSmrg } 1727e6fb56fSmrg} 1737e6fb56fSmrg 1747e6fb56fSmrgBool 1757e6fb56fSmrgVIADRIRingBufferInit(ScrnInfoPtr pScrn) 1767e6fb56fSmrg{ 1777e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 1787e6fb56fSmrg VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 1797e6fb56fSmrg 1807e6fb56fSmrg if (pVIADRI->ringBufActive) 1817e6fb56fSmrg return TRUE; 1827e6fb56fSmrg 1837e6fb56fSmrg if (pVia->agpEnable) { 1847e6fb56fSmrg drm_via_dma_init_t ringBufInit; 1857e6fb56fSmrg 1867e6fb56fSmrg if ((pVia->drmVerMajor == 1) && (pVia->drmVerMinor <= 3)) 1877e6fb56fSmrg return FALSE; 1887e6fb56fSmrg 1897e6fb56fSmrg /* 1907e6fb56fSmrg * Info frome code-snippet on DRI-DEVEL list; Erdi Chen. 1917e6fb56fSmrg */ 1927e6fb56fSmrg 1937e6fb56fSmrg switch (pVia->ChipId) { 1947e6fb56fSmrg case PCI_CHIP_VT3314: 1957e6fb56fSmrg case PCI_CHIP_VT3259: 1967e6fb56fSmrg pVIADRI->reg_pause_addr = 0x40c; 1977e6fb56fSmrg break; 1987e6fb56fSmrg default: 1997e6fb56fSmrg pVIADRI->reg_pause_addr = 0x418; 2007e6fb56fSmrg break; 2017e6fb56fSmrg } 2027e6fb56fSmrg 2037e6fb56fSmrg ringBufInit.offset = pVia->agpSize; 2047e6fb56fSmrg ringBufInit.size = AGP_CMDBUF_SIZE; 2057e6fb56fSmrg ringBufInit.reg_pause_addr = pVIADRI->reg_pause_addr; 2067e6fb56fSmrg ringBufInit.func = VIA_INIT_DMA; 2077e6fb56fSmrg 2087e6fb56fSmrg if (drmCommandWrite(pVia->drmFD, DRM_VIA_DMA_INIT, &ringBufInit, 2097e6fb56fSmrg sizeof(ringBufInit))) { 2107e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2117e6fb56fSmrg "[drm] Failed to initialize DMA ring-buffer: %d\n", 2127e6fb56fSmrg errno); 2137e6fb56fSmrg return FALSE; 2147e6fb56fSmrg } 2157e6fb56fSmrg 2167e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2177e6fb56fSmrg "[drm] Initialized AGP ring-buffer, size 0x%lx at AGP " 2187e6fb56fSmrg "offset 0x%lx.\n", ringBufInit.size, ringBufInit.offset); 2197e6fb56fSmrg pVIADRI->ringBufActive = 1; 2207e6fb56fSmrg } 2217e6fb56fSmrg return TRUE; 2227e6fb56fSmrg} 2237e6fb56fSmrg 2247e6fb56fSmrgstatic Bool 2257e6fb56fSmrgVIASetAgpMode(ScrnInfoPtr pScrn) 2267e6fb56fSmrg{ 2277e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 2287e6fb56fSmrg CARD32 mode = drmAgpGetMode(pVia->drmFD); 2297e6fb56fSmrg unsigned int vendor = drmAgpVendorId(pVia->drmFD); 2307e6fb56fSmrg unsigned int device = drmAgpDeviceId(pVia->drmFD); 2317e6fb56fSmrg 2327e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Detected AGP " 2337e6fb56fSmrg "vendor 0x%04x, device 0x%04x\n", vendor, device); 2347e6fb56fSmrg 2357e6fb56fSmrg mode &= ~VIA_AGP_MODE_MASK; 2367e6fb56fSmrg if (mode & VIA_AGPv3_MODE) { 2377e6fb56fSmrg mode |= VIA_AGPv3_8X_MODE; 2387e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Found AGP v3 " 2397e6fb56fSmrg "compatible device. Trying AGP 8X mode.\n"); 2407e6fb56fSmrg } else { 2417e6fb56fSmrg mode |= VIA_AGP_4X_MODE; 2427e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Didn't find any AGP v3 " 2437e6fb56fSmrg "compatible device. Trying AGP 4X mode.\n"); 2447e6fb56fSmrg } 2457e6fb56fSmrg 2467e6fb56fSmrg mode |= VIA_AGP_FW_MODE; 2477e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2487e6fb56fSmrg "[drm] Trying to enable AGP fast writes.\n"); 2497e6fb56fSmrg 2507e6fb56fSmrg if (drmAgpEnable(pVia->drmFD, mode) < 0) 2517e6fb56fSmrg return FALSE; 2527e6fb56fSmrg 2537e6fb56fSmrg return TRUE; 2547e6fb56fSmrg} 2557e6fb56fSmrg 2567e6fb56fSmrgstatic Bool 2577e6fb56fSmrgVIADRIAgpInit(ScreenPtr pScreen, VIAPtr pVia) 2587e6fb56fSmrg{ 2597e6fb56fSmrg int agpPages; 2607e6fb56fSmrg unsigned long agpCmdSize; 2617e6fb56fSmrg unsigned long agp_phys; 2627e6fb56fSmrg drmAddress agpaddr; 2637e6fb56fSmrg VIADRIPtr pVIADRI; 2647e6fb56fSmrg DRIInfoPtr pDRIInfo; 2657e6fb56fSmrg 2667e6fb56fSmrg pDRIInfo = pVia->pDRIInfo; 2677e6fb56fSmrg pVIADRI = pDRIInfo->devPrivate; 2687e6fb56fSmrg pVia->agpSize = 0; 2697e6fb56fSmrg 2707e6fb56fSmrg if (drmAgpAcquire(pVia->drmFD) < 0) { 2717e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAcquire failed %d\n", 2727e6fb56fSmrg errno); 2737e6fb56fSmrg return FALSE; 2747e6fb56fSmrg } 2757e6fb56fSmrg 2767e6fb56fSmrg if (!VIASetAgpMode(xf86Screens[pScreen->myNum])) { 2777e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] VIASetAgpMode failed\n"); 2787e6fb56fSmrg drmAgpRelease(pVia->drmFD); 2797e6fb56fSmrg return FALSE; 2807e6fb56fSmrg } 2817e6fb56fSmrg 2827e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] drmAgpEnabled succeeded\n"); 2837e6fb56fSmrg 2847e6fb56fSmrg agpCmdSize = (pVia->agpEnable) ? AGP_CMDBUF_SIZE : 0; 2857e6fb56fSmrg 2867e6fb56fSmrg if (pVia->agpMem * 1024 < agpCmdSize + AGP_PAGE_SIZE) { 2877e6fb56fSmrg pVia->agpMem = (agpCmdSize + AGP_PAGE_SIZE) / 1024; 2887e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, 2897e6fb56fSmrg "[drm] Forcing AGP size to %d kB\n", pVia->agpMem); 2907e6fb56fSmrg } 2917e6fb56fSmrg 2927e6fb56fSmrg agpPages = (pVia->agpMem * 1024 + AGP_PAGE_SIZE - 1) / AGP_PAGE_SIZE; 2937e6fb56fSmrg 2947e6fb56fSmrg if (drmAgpAlloc(pVia->drmFD, agpPages * AGP_PAGE_SIZE, 2957e6fb56fSmrg 0, &agp_phys, &pVia->agpHandle) < 0) { 2967e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAlloc failed\n"); 2977e6fb56fSmrg drmAgpRelease(pVia->drmFD); 2987e6fb56fSmrg return FALSE; 2997e6fb56fSmrg } 3007e6fb56fSmrg 3017e6fb56fSmrg if (drmAgpBind(pVia->drmFD, pVia->agpHandle, 0) < 0) { 3027e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpBind failed\n"); 3037e6fb56fSmrg drmAgpFree(pVia->drmFD, pVia->agpHandle); 3047e6fb56fSmrg drmAgpRelease(pVia->drmFD); 3057e6fb56fSmrg return FALSE; 3067e6fb56fSmrg } 3077e6fb56fSmrg 3087e6fb56fSmrg /* 3097e6fb56fSmrg * Place the ring-buffer last in the AGP region, and restrict the 3107e6fb56fSmrg * public map not to include the buffer for security reasons. 3117e6fb56fSmrg */ 3127e6fb56fSmrg 3137e6fb56fSmrg pVia->agpSize = agpPages * AGP_PAGE_SIZE - agpCmdSize; 3147e6fb56fSmrg pVia->agpAddr = drmAgpBase(pVia->drmFD); 3157e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, 3167e6fb56fSmrg "[drm] agpAddr = 0x%08lx\n", pVia->agpAddr); 3177e6fb56fSmrg 3187e6fb56fSmrg pVIADRI->agp.size = pVia->agpSize; 3197e6fb56fSmrg if (drmAddMap(pVia->drmFD, (drm_handle_t) 0, pVIADRI->agp.size, 3207e6fb56fSmrg DRM_AGP, 0, &pVIADRI->agp.handle) < 0) { 3217e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, 3227e6fb56fSmrg "[drm] Failed to map public agp area.\n"); 3237e6fb56fSmrg pVIADRI->agp.size = 0; 3247e6fb56fSmrg drmAgpUnbind(pVia->drmFD, pVia->agpHandle); 3257e6fb56fSmrg drmAgpFree(pVia->drmFD, pVia->agpHandle); 3267e6fb56fSmrg drmAgpRelease(pVia->drmFD); 3277e6fb56fSmrg return FALSE; 3287e6fb56fSmrg } 3297e6fb56fSmrg 3307e6fb56fSmrg drmMap(pVia->drmFD, pVIADRI->agp.handle, pVIADRI->agp.size, &agpaddr); 3317e6fb56fSmrg pVia->agpMappedAddr = agpaddr; 3327e6fb56fSmrg 3337e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, 3347e6fb56fSmrg "[drm] agpBase = %p\n", pVia->agpBase); 3357e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, 3367e6fb56fSmrg "[drm] agpAddr = 0x%08lx\n", pVia->agpAddr); 3377e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, 3387e6fb56fSmrg "[drm] agpSize = 0x%08x\n", pVia->agpSize); 3397e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, 3407e6fb56fSmrg "[drm] agp physical addr = 0x%08lx\n", agp_phys); 3417e6fb56fSmrg 3427e6fb56fSmrg { 3437e6fb56fSmrg drm_via_agp_t agp; 3447e6fb56fSmrg 3457e6fb56fSmrg agp.offset = 0; 3467e6fb56fSmrg agp.size = pVia->agpSize; 3477e6fb56fSmrg if (drmCommandWrite(pVia->drmFD, DRM_VIA_AGP_INIT, &agp, 3487e6fb56fSmrg sizeof(drm_via_agp_t)) < 0) { 3497e6fb56fSmrg drmUnmap(agpaddr, pVia->agpSize); 3507e6fb56fSmrg drmRmMap(pVia->drmFD, pVIADRI->agp.handle); 3517e6fb56fSmrg drmAgpUnbind(pVia->drmFD, pVia->agpHandle); 3527e6fb56fSmrg drmAgpFree(pVia->drmFD, pVia->agpHandle); 3537e6fb56fSmrg drmAgpRelease(pVia->drmFD); 3547e6fb56fSmrg return FALSE; 3557e6fb56fSmrg } 3567e6fb56fSmrg } 3577e6fb56fSmrg 3587e6fb56fSmrg return TRUE; 3597e6fb56fSmrg} 3607e6fb56fSmrg 3617e6fb56fSmrgstatic Bool 3627e6fb56fSmrgVIADRIFBInit(ScreenPtr pScreen, VIAPtr pVia) 3637e6fb56fSmrg{ 3647e6fb56fSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 3657e6fb56fSmrg int FBSize = pVia->driSize; 3667e6fb56fSmrg int FBOffset; 3677e6fb56fSmrg VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 3687e6fb56fSmrg 3697e6fb56fSmrg if (FBSize < pVia->Bpl) { 3707e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, 3717e6fb56fSmrg "[drm] No DRM framebuffer heap available.\n" 3727e6fb56fSmrg "[drm] Please increase the frame buffer\n" 3737e6fb56fSmrg "[drm] memory area in the BIOS. Disabling DRI.\n"); 3747e6fb56fSmrg return FALSE; 3757e6fb56fSmrg } 3767e6fb56fSmrg if (FBSize < 3 * (pScrn->virtualY * pVia->Bpl)) { 3777e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_WARNING, 3787e6fb56fSmrg "[drm] The DRM heap and pixmap cache memory may be too\n" 3797e6fb56fSmrg "[drm] small for optimal performance. Please increase\n" 3807e6fb56fSmrg "[drm] the frame buffer memory area in the BIOS.\n"); 3817e6fb56fSmrg } 3827e6fb56fSmrg 3837e6fb56fSmrg pVia->driOffScreenMem.pool = 0; 3847e6fb56fSmrg if (Success != viaOffScreenLinear(&pVia->driOffScreenMem, pScrn, FBSize)) { 3857e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, 3867e6fb56fSmrg "[drm] Failed to allocate offscreen frame buffer area.\n"); 3877e6fb56fSmrg return FALSE; 3887e6fb56fSmrg } 3897e6fb56fSmrg 3907e6fb56fSmrg FBOffset = pVia->driOffScreenMem.base; 3917e6fb56fSmrg 3927e6fb56fSmrg pVIADRI->fbOffset = FBOffset; 3937e6fb56fSmrg pVIADRI->fbSize = FBSize; 3947e6fb56fSmrg 3957e6fb56fSmrg { 3967e6fb56fSmrg drm_via_fb_t fb; 3977e6fb56fSmrg 3987e6fb56fSmrg fb.offset = FBOffset; 3997e6fb56fSmrg fb.size = FBSize; 4007e6fb56fSmrg 4017e6fb56fSmrg if (drmCommandWrite(pVia->drmFD, DRM_VIA_FB_INIT, &fb, 4027e6fb56fSmrg sizeof(drm_via_fb_t)) < 0) { 4037e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, 4047e6fb56fSmrg "[drm] Failed to initialize frame buffer area.\n"); 4057e6fb56fSmrg return FALSE; 4067e6fb56fSmrg } else { 4077e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, 4087e6fb56fSmrg "[drm] Using %d bytes for DRM memory heap.\n", FBSize); 4097e6fb56fSmrg return TRUE; 4107e6fb56fSmrg } 4117e6fb56fSmrg } 4127e6fb56fSmrg} 4137e6fb56fSmrg 4147e6fb56fSmrgstatic Bool 4157e6fb56fSmrgVIADRIPciInit(ScreenPtr pScreen, VIAPtr pVia) 4167e6fb56fSmrg{ 4177e6fb56fSmrg return TRUE; 4187e6fb56fSmrg} 4197e6fb56fSmrg 4207e6fb56fSmrgstatic Bool 4217e6fb56fSmrgVIAInitVisualConfigs(ScreenPtr pScreen) 4227e6fb56fSmrg{ 4237e6fb56fSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 4247e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 4257e6fb56fSmrg int numConfigs = 0; 4267e6fb56fSmrg __GLXvisualConfig *pConfigs = 0; 4277e6fb56fSmrg VIAConfigPrivPtr pVIAConfigs = 0; 4287e6fb56fSmrg VIAConfigPrivPtr *pVIAConfigPtrs = 0; 4297e6fb56fSmrg int i, db, stencil, accum; 4307e6fb56fSmrg 4317e6fb56fSmrg if (pScrn->bitsPerPixel == 16 || pScrn->bitsPerPixel == 32) { 4327e6fb56fSmrg numConfigs = 12; 4337e6fb56fSmrg if (!(pConfigs = (__GLXvisualConfig *) 4347e6fb56fSmrg xcalloc(sizeof(__GLXvisualConfig), numConfigs))) 4357e6fb56fSmrg return FALSE; 4367e6fb56fSmrg if (!(pVIAConfigs = (VIAConfigPrivPtr) 4377e6fb56fSmrg xcalloc(sizeof(VIAConfigPrivRec), numConfigs))) { 4387e6fb56fSmrg xfree(pConfigs); 4397e6fb56fSmrg return FALSE; 4407e6fb56fSmrg } 4417e6fb56fSmrg if (!(pVIAConfigPtrs = (VIAConfigPrivPtr *) 4427e6fb56fSmrg xcalloc(sizeof(VIAConfigPrivPtr), numConfigs))) { 4437e6fb56fSmrg xfree(pConfigs); 4447e6fb56fSmrg xfree(pVIAConfigs); 4457e6fb56fSmrg return FALSE; 4467e6fb56fSmrg } 4477e6fb56fSmrg for (i = 0; i < numConfigs; i++) 4487e6fb56fSmrg pVIAConfigPtrs[i] = &pVIAConfigs[i]; 4497e6fb56fSmrg 4507e6fb56fSmrg i = 0; 4517e6fb56fSmrg for (accum = 0; accum <= 1; accum++) { 4527e6fb56fSmrg /* 32bpp depth buffer disabled, as Mesa has limitations */ 4537e6fb56fSmrg for (stencil = 0; stencil <= 2; stencil++) { 4547e6fb56fSmrg for (db = 0; db <= 1; db++) { 4557e6fb56fSmrg pConfigs[i].vid = -1; 4567e6fb56fSmrg pConfigs[i].class = -1; 4577e6fb56fSmrg pConfigs[i].rgba = TRUE; 4587e6fb56fSmrg pConfigs[i].redSize = -1; 4597e6fb56fSmrg pConfigs[i].greenSize = -1; 4607e6fb56fSmrg pConfigs[i].blueSize = -1; 4617e6fb56fSmrg pConfigs[i].redMask = -1; 4627e6fb56fSmrg pConfigs[i].greenMask = -1; 4637e6fb56fSmrg pConfigs[i].blueMask = -1; 4647e6fb56fSmrg if (pScrn->bitsPerPixel == 32) { 4657e6fb56fSmrg pConfigs[i].alphaSize = 8; 4667e6fb56fSmrg pConfigs[i].alphaMask = 0xFF000000; 4677e6fb56fSmrg } else { 4687e6fb56fSmrg pConfigs[i].alphaSize = 0; 4697e6fb56fSmrg pConfigs[i].alphaMask = 0; 4707e6fb56fSmrg } 4717e6fb56fSmrg 4727e6fb56fSmrg if (accum) { 4737e6fb56fSmrg pConfigs[i].accumRedSize = 16; 4747e6fb56fSmrg pConfigs[i].accumGreenSize = 16; 4757e6fb56fSmrg pConfigs[i].accumBlueSize = 16; 4767e6fb56fSmrg if (pScrn->bitsPerPixel == 32) 4777e6fb56fSmrg pConfigs[i].accumAlphaSize = 16; 4787e6fb56fSmrg else 4797e6fb56fSmrg pConfigs[i].accumAlphaSize = 0; 4807e6fb56fSmrg } else { 4817e6fb56fSmrg pConfigs[i].accumRedSize = 0; 4827e6fb56fSmrg pConfigs[i].accumGreenSize = 0; 4837e6fb56fSmrg pConfigs[i].accumBlueSize = 0; 4847e6fb56fSmrg pConfigs[i].accumAlphaSize = 0; 4857e6fb56fSmrg } 4867e6fb56fSmrg if (!db) 4877e6fb56fSmrg pConfigs[i].doubleBuffer = TRUE; 4887e6fb56fSmrg else 4897e6fb56fSmrg pConfigs[i].doubleBuffer = FALSE; 4907e6fb56fSmrg 4917e6fb56fSmrg pConfigs[i].stereo = FALSE; 4927e6fb56fSmrg pConfigs[i].bufferSize = -1; 4937e6fb56fSmrg 4947e6fb56fSmrg switch (stencil) { 4957e6fb56fSmrg case 0: 4967e6fb56fSmrg pConfigs[i].depthSize = 24; 4977e6fb56fSmrg pConfigs[i].stencilSize = 8; 4987e6fb56fSmrg break; 4997e6fb56fSmrg case 1: 5007e6fb56fSmrg pConfigs[i].depthSize = 16; 5017e6fb56fSmrg pConfigs[i].stencilSize = 0; 5027e6fb56fSmrg break; 5037e6fb56fSmrg case 2: 5047e6fb56fSmrg pConfigs[i].depthSize = 0; 5057e6fb56fSmrg pConfigs[i].stencilSize = 0; 5067e6fb56fSmrg break; 5077e6fb56fSmrg case 3: 5087e6fb56fSmrg pConfigs[i].depthSize = 32; 5097e6fb56fSmrg pConfigs[i].stencilSize = 0; 5107e6fb56fSmrg break; 5117e6fb56fSmrg } 5127e6fb56fSmrg 5137e6fb56fSmrg pConfigs[i].auxBuffers = 0; 5147e6fb56fSmrg pConfigs[i].level = 0; 5157e6fb56fSmrg if (accum) 5167e6fb56fSmrg pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; 5177e6fb56fSmrg else 5187e6fb56fSmrg pConfigs[i].visualRating = GLX_NONE_EXT; 5197e6fb56fSmrg pConfigs[i].transparentPixel = GLX_NONE_EXT; 5207e6fb56fSmrg pConfigs[i].transparentRed = 0; 5217e6fb56fSmrg pConfigs[i].transparentGreen = 0; 5227e6fb56fSmrg pConfigs[i].transparentBlue = 0; 5237e6fb56fSmrg pConfigs[i].transparentAlpha = 0; 5247e6fb56fSmrg pConfigs[i].transparentIndex = 0; 5257e6fb56fSmrg i++; 5267e6fb56fSmrg } 5277e6fb56fSmrg } 5287e6fb56fSmrg } 5297e6fb56fSmrg 5307e6fb56fSmrg if (i != numConfigs) { 5317e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] Incorrect " 5327e6fb56fSmrg "initialization of visuals. Disabling DRI.\n"); 5337e6fb56fSmrg return FALSE; 5347e6fb56fSmrg } 5357e6fb56fSmrg } 5367e6fb56fSmrg 5377e6fb56fSmrg pVia->numVisualConfigs = numConfigs; 5387e6fb56fSmrg pVia->pVisualConfigs = pConfigs; 5397e6fb56fSmrg pVia->pVisualConfigsPriv = pVIAConfigs; 5407e6fb56fSmrg GlxSetVisualConfigs(numConfigs, pConfigs, (void **)pVIAConfigPtrs); 5417e6fb56fSmrg 5427e6fb56fSmrg return TRUE; 5437e6fb56fSmrg} 5447e6fb56fSmrg 5457e6fb56fSmrgBool 5467e6fb56fSmrgVIADRIScreenInit(ScreenPtr pScreen) 5477e6fb56fSmrg{ 5487e6fb56fSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 5497e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 5507e6fb56fSmrg DRIInfoPtr pDRIInfo; 5517e6fb56fSmrg VIADRIPtr pVIADRI; 5527e6fb56fSmrg drmVersionPtr drmVer; 5537e6fb56fSmrg 5547e6fb56fSmrg /* If symbols or version check fails, we still want this to be NULL. */ 5557e6fb56fSmrg pVia->pDRIInfo = NULL; 5567e6fb56fSmrg 5577e6fb56fSmrg /* Check that the GLX, DRI, and DRM modules have been loaded by testing 5587e6fb56fSmrg * for canonical symbols in each module. */ 5597e6fb56fSmrg if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) 5607e6fb56fSmrg return FALSE; 5617e6fb56fSmrg if (!xf86LoaderCheckSymbol("drmAvailable")) 5627e6fb56fSmrg return FALSE; 5637e6fb56fSmrg if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { 5647e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, 5657e6fb56fSmrg "[dri] VIADRIScreenInit failed (libdri.a is too old).\n"); 5667e6fb56fSmrg return FALSE; 5677e6fb56fSmrg } 5687e6fb56fSmrg 5697e6fb56fSmrg /* Check the DRI version. */ 5707e6fb56fSmrg { 5717e6fb56fSmrg int major, minor, patch; 5727e6fb56fSmrg 5737e6fb56fSmrg DRIQueryVersion(&major, &minor, &patch); 5747e6fb56fSmrg if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { 5757e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, 5767e6fb56fSmrg "[dri] VIADRIScreenInit failed -- version mismatch.\n" 5777e6fb56fSmrg "[dri] libdri is %d.%d.%d, but %d.%d.x is needed.\n" 5787e6fb56fSmrg "[dri] Disabling DRI.\n", 5797e6fb56fSmrg major, minor, patch, 5807e6fb56fSmrg DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); 5817e6fb56fSmrg return FALSE; 5827e6fb56fSmrg } 5837e6fb56fSmrg } 5847e6fb56fSmrg 5857e6fb56fSmrg pVia->pDRIInfo = DRICreateInfoRec(); 5867e6fb56fSmrg if (!pVia->pDRIInfo) 5877e6fb56fSmrg return FALSE; 5887e6fb56fSmrg 5897e6fb56fSmrg pDRIInfo = pVia->pDRIInfo; 5907e6fb56fSmrg pDRIInfo->drmDriverName = VIAKernelDriverName; 5917e6fb56fSmrg switch (pVia->Chipset) { 5927e6fb56fSmrg case VIA_K8M890: 5937e6fb56fSmrg case VIA_P4M900: 5947e6fb56fSmrg case VIA_VX800: 5957e6fb56fSmrg case VIA_VX855: 5967e6fb56fSmrg pDRIInfo->clientDriverName = "swrast"; 5977e6fb56fSmrg break; 5987e6fb56fSmrg default: 5997e6fb56fSmrg pDRIInfo->clientDriverName = VIAClientDriverName; 6007e6fb56fSmrg break; 6017e6fb56fSmrg } 602485acf3eSjmcneill if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 603485acf3eSjmcneill pDRIInfo->busIdString = DRICreatePCIBusID(pVia->PciInfo); 604485acf3eSjmcneill } else { 605485acf3eSjmcneill pDRIInfo->busIdString = xalloc(64); 606485acf3eSjmcneill sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", 6077e6fb56fSmrg#ifdef XSERVER_LIBPCIACCESS 608485acf3eSjmcneill ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus), 609485acf3eSjmcneill pVia->PciInfo->dev, pVia->PciInfo->func 6107e6fb56fSmrg#else 611485acf3eSjmcneill ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum, 612485acf3eSjmcneill ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum, 613485acf3eSjmcneill ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum 6147e6fb56fSmrg#endif 615485acf3eSjmcneill ); 616485acf3eSjmcneill } 6177e6fb56fSmrg pDRIInfo->ddxDriverMajorVersion = VIA_DRIDDX_VERSION_MAJOR; 6187e6fb56fSmrg pDRIInfo->ddxDriverMinorVersion = VIA_DRIDDX_VERSION_MINOR; 6197e6fb56fSmrg pDRIInfo->ddxDriverPatchVersion = VIA_DRIDDX_VERSION_PATCH; 6207e6fb56fSmrg#if (DRIINFO_MAJOR_VERSION == 5) 6217e6fb56fSmrg pDRIInfo->frameBufferPhysicalAddress = (pointer) pVia->FrameBufferBase; 6227e6fb56fSmrg#else 6237e6fb56fSmrg pDRIInfo->frameBufferPhysicalAddress = pVia->FrameBufferBase; 6247e6fb56fSmrg#endif 6257e6fb56fSmrg pDRIInfo->frameBufferSize = pVia->videoRambytes; 6267e6fb56fSmrg 6277e6fb56fSmrg pDRIInfo->frameBufferStride = (pScrn->displayWidth * 6287e6fb56fSmrg pScrn->bitsPerPixel / 8); 6297e6fb56fSmrg pDRIInfo->ddxDrawableTableEntry = VIA_MAX_DRAWABLES; 6307e6fb56fSmrg 6317e6fb56fSmrg if (SAREA_MAX_DRAWABLES < VIA_MAX_DRAWABLES) 6327e6fb56fSmrg pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; 6337e6fb56fSmrg else 6347e6fb56fSmrg pDRIInfo->maxDrawableTableEntry = VIA_MAX_DRAWABLES; 6357e6fb56fSmrg 6367e6fb56fSmrg#ifdef NOT_DONE 6377e6fb56fSmrg /* FIXME: need to extend DRI protocol to pass this size back to client 6387e6fb56fSmrg * for SAREA mapping that includes a device private record. */ 6397e6fb56fSmrg pDRIInfo->SAREASize = ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */ 6407e6fb56fSmrg /* + shared memory device private rec */ 6417e6fb56fSmrg#else 6427e6fb56fSmrg /* For now the mapping works by using a fixed size defined 6437e6fb56fSmrg * in the SAREA header. */ 6447e6fb56fSmrg if (sizeof(XF86DRISAREARec) + sizeof(drm_via_sarea_t) > SAREA_MAX) { 6457e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Data does not fit in SAREA\n"); 6467e6fb56fSmrg DRIDestroyInfoRec(pVia->pDRIInfo); 6477e6fb56fSmrg pVia->pDRIInfo = NULL; 6487e6fb56fSmrg return FALSE; 6497e6fb56fSmrg } 6507e6fb56fSmrg pDRIInfo->SAREASize = SAREA_MAX; 6517e6fb56fSmrg#endif 6527e6fb56fSmrg 6537e6fb56fSmrg if (!(pVIADRI = (VIADRIPtr) xcalloc(sizeof(VIADRIRec), 1))) { 6547e6fb56fSmrg DRIDestroyInfoRec(pVia->pDRIInfo); 6557e6fb56fSmrg pVia->pDRIInfo = NULL; 6567e6fb56fSmrg return FALSE; 6577e6fb56fSmrg } 6587e6fb56fSmrg pDRIInfo->devPrivate = pVIADRI; 6597e6fb56fSmrg pDRIInfo->devPrivateSize = sizeof(VIADRIRec); 6607e6fb56fSmrg pDRIInfo->contextSize = sizeof(VIADRIContextRec); 6617e6fb56fSmrg 6627e6fb56fSmrg pDRIInfo->CreateContext = VIACreateContext; 6637e6fb56fSmrg pDRIInfo->DestroyContext = VIADestroyContext; 6647e6fb56fSmrg pDRIInfo->SwapContext = VIADRISwapContext; 6657e6fb56fSmrg pDRIInfo->InitBuffers = VIADRIInitBuffers; 6667e6fb56fSmrg pDRIInfo->MoveBuffers = VIADRIMoveBuffers; 6677e6fb56fSmrg pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; 6687e6fb56fSmrg 6697e6fb56fSmrg if (!DRIScreenInit(pScreen, pDRIInfo, &pVia->drmFD)) { 6707e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_ERROR, 6717e6fb56fSmrg "[dri] DRIScreenInit failed. Disabling DRI.\n"); 6727e6fb56fSmrg xfree(pDRIInfo->devPrivate); 6737e6fb56fSmrg pDRIInfo->devPrivate = NULL; 6747e6fb56fSmrg DRIDestroyInfoRec(pVia->pDRIInfo); 6757e6fb56fSmrg pVia->pDRIInfo = NULL; 6767e6fb56fSmrg pVia->drmFD = -1; 6777e6fb56fSmrg return FALSE; 6787e6fb56fSmrg } 6797e6fb56fSmrg 6807e6fb56fSmrg if (NULL == (drmVer = drmGetVersion(pVia->drmFD))) { 6817e6fb56fSmrg VIADRICloseScreen(pScreen); 6827e6fb56fSmrg return FALSE; 6837e6fb56fSmrg } 6847e6fb56fSmrg pVia->drmVerMajor = drmVer->version_major; 6857e6fb56fSmrg pVia->drmVerMinor = drmVer->version_minor; 6867e6fb56fSmrg pVia->drmVerPL = drmVer->version_patchlevel; 6877e6fb56fSmrg 6887e6fb56fSmrg if ((drmVer->version_major < drmExpected.major) || 6897e6fb56fSmrg (drmVer->version_major > drmCompat.major) || 6907e6fb56fSmrg ((drmVer->version_major == drmExpected.major) && 6917e6fb56fSmrg (drmVer->version_minor < drmExpected.minor))) { 6927e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6937e6fb56fSmrg "[dri] Kernel drm is not compatible with this driver.\n" 6947e6fb56fSmrg "[dri] Kernel drm version is %d.%d.%d, " 6957e6fb56fSmrg "and I can work with versions %d.%d.x - %d.x.x.\n" 6967e6fb56fSmrg "[dri] Update either this 2D driver or your kernel DRM. " 6977e6fb56fSmrg "Disabling DRI.\n", 6987e6fb56fSmrg drmVer->version_major, drmVer->version_minor, 6997e6fb56fSmrg drmVer->version_patchlevel, 7007e6fb56fSmrg drmExpected.major, drmExpected.minor, drmCompat.major); 7017e6fb56fSmrg drmFreeVersion(drmVer); 7027e6fb56fSmrg VIADRICloseScreen(pScreen); 7037e6fb56fSmrg return FALSE; 7047e6fb56fSmrg } 7057e6fb56fSmrg drmFreeVersion(drmVer); 7067e6fb56fSmrg 7077e6fb56fSmrg if (!(VIAInitVisualConfigs(pScreen))) { 7087e6fb56fSmrg VIADRICloseScreen(pScreen); 7097e6fb56fSmrg return FALSE; 7107e6fb56fSmrg } 7117e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized.\n"); 7127e6fb56fSmrg 7137e6fb56fSmrg /* DRIScreenInit doesn't add all the common mappings. 7147e6fb56fSmrg * Add additional mappings here. */ 7157e6fb56fSmrg if (!VIADRIMapInit(pScreen, pVia)) { 7167e6fb56fSmrg VIADRICloseScreen(pScreen); 7177e6fb56fSmrg return FALSE; 7187e6fb56fSmrg } 7197e6fb56fSmrg pVIADRI->regs.size = VIA_MMIO_REGSIZE; 7207e6fb56fSmrg pVIADRI->regs.handle = pVia->registerHandle; 7217e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] mmio Registers = 0x%08lx\n", 7227e6fb56fSmrg (unsigned long)pVIADRI->regs.handle); 7237e6fb56fSmrg 7247e6fb56fSmrg pVIADRI->drixinerama = FALSE; 7257e6fb56fSmrg 7267e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] mmio mapped.\n"); 7277e6fb56fSmrg 7287e6fb56fSmrg return TRUE; 7297e6fb56fSmrg} 7307e6fb56fSmrg 7317e6fb56fSmrgvoid 7327e6fb56fSmrgVIADRICloseScreen(ScreenPtr pScreen) 7337e6fb56fSmrg{ 7347e6fb56fSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 7357e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 7367e6fb56fSmrg VIADRIPtr pVIADRI; 7377e6fb56fSmrg 7387e6fb56fSmrg VIADRIRingBufferCleanup(pScrn); 7397e6fb56fSmrg if (pVia->agpSize) { 7407e6fb56fSmrg drmUnmap(pVia->agpMappedAddr, pVia->agpSize); 7417e6fb56fSmrg drmRmMap(pVia->drmFD, pVia->agpHandle); 7427e6fb56fSmrg drmAgpUnbind(pVia->drmFD, pVia->agpHandle); 7437e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Freeing agp memory\n"); 7447e6fb56fSmrg drmAgpFree(pVia->drmFD, pVia->agpHandle); 7457e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Releasing agp module\n"); 7467e6fb56fSmrg drmAgpRelease(pVia->drmFD); 7477e6fb56fSmrg } 7487e6fb56fSmrg 7497e6fb56fSmrg DRICloseScreen(pScreen); 7507e6fb56fSmrg VIAFreeLinear(&pVia->driOffScreenMem); 7517e6fb56fSmrg 7527e6fb56fSmrg if (pVia->pDRIInfo) { 7537e6fb56fSmrg if ((pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate)) { 7547e6fb56fSmrg VIADRIIrqExit(pScrn, pVIADRI); 7557e6fb56fSmrg xfree(pVIADRI); 7567e6fb56fSmrg pVia->pDRIInfo->devPrivate = NULL; 7577e6fb56fSmrg } 7587e6fb56fSmrg DRIDestroyInfoRec(pVia->pDRIInfo); 7597e6fb56fSmrg pVia->pDRIInfo = NULL; 7607e6fb56fSmrg } 7617e6fb56fSmrg 7627e6fb56fSmrg if (pVia->pVisualConfigs) { 7637e6fb56fSmrg xfree(pVia->pVisualConfigs); 7647e6fb56fSmrg pVia->pVisualConfigs = NULL; 7657e6fb56fSmrg } 7667e6fb56fSmrg if (pVia->pVisualConfigsPriv) { 7677e6fb56fSmrg xfree(pVia->pVisualConfigsPriv); 7687e6fb56fSmrg pVia->pVisualConfigsPriv = NULL; 7697e6fb56fSmrg } 7707e6fb56fSmrg} 7717e6fb56fSmrg 7727e6fb56fSmrg/* TODO: xserver receives driver's swapping event and does something 7737e6fb56fSmrg * according the data initialized in this function. 7747e6fb56fSmrg */ 7757e6fb56fSmrgstatic Bool 7767e6fb56fSmrgVIACreateContext(ScreenPtr pScreen, VisualPtr visual, 7777e6fb56fSmrg drm_context_t hwContext, void *pVisualConfigPriv, 7787e6fb56fSmrg DRIContextType contextStore) 7797e6fb56fSmrg{ 7807e6fb56fSmrg return TRUE; 7817e6fb56fSmrg} 7827e6fb56fSmrg 7837e6fb56fSmrgstatic void 7847e6fb56fSmrgVIADestroyContext(ScreenPtr pScreen, drm_context_t hwContext, 7857e6fb56fSmrg DRIContextType contextStore) 7867e6fb56fSmrg{ 7877e6fb56fSmrg} 7887e6fb56fSmrg 7897e6fb56fSmrgBool 7907e6fb56fSmrgVIADRIFinishScreenInit(ScreenPtr pScreen) 7917e6fb56fSmrg{ 7927e6fb56fSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 7937e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 7947e6fb56fSmrg VIADRIPtr pVIADRI; 7957e6fb56fSmrg 7967e6fb56fSmrg pVia->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; 7977e6fb56fSmrg 7987e6fb56fSmrg pVia->IsPCI = !VIADRIAgpInit(pScreen, pVia); 7997e6fb56fSmrg 8007e6fb56fSmrg if (pVia->IsPCI) { 8017e6fb56fSmrg VIADRIPciInit(pScreen, pVia); 8027e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Using PCI.\n"); 8037e6fb56fSmrg } else 8047e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Using AGP.\n"); 8057e6fb56fSmrg 8067e6fb56fSmrg if (!(VIADRIFBInit(pScreen, pVia))) { 8077e6fb56fSmrg VIADRICloseScreen(pScreen); 8087e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 8097e6fb56fSmrg "[dri] Frame buffer initialization failed.\n"); 8107e6fb56fSmrg return FALSE; 8117e6fb56fSmrg } 8127e6fb56fSmrg 8137e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Frame buffer initialized.\n"); 8147e6fb56fSmrg 8157e6fb56fSmrg DRIFinishScreenInit(pScreen); 8167e6fb56fSmrg 8177e6fb56fSmrg if (!VIADRIKernelInit(pScreen, pVia)) { 8187e6fb56fSmrg VIADRICloseScreen(pScreen); 8197e6fb56fSmrg return FALSE; 8207e6fb56fSmrg } 8217e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Kernel data initialized.\n"); 8227e6fb56fSmrg 8237e6fb56fSmrg /* Set SAREA value. */ 8247e6fb56fSmrg { 8257e6fb56fSmrg drm_via_sarea_t *saPriv; 8267e6fb56fSmrg 8277e6fb56fSmrg saPriv = (drm_via_sarea_t *) DRIGetSAREAPrivate(pScreen); 8287e6fb56fSmrg assert(saPriv); 8297e6fb56fSmrg memset(saPriv, 0, sizeof(*saPriv)); 8307e6fb56fSmrg saPriv->ctxOwner = -1; 8317e6fb56fSmrg } 8327e6fb56fSmrg pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate; 8337e6fb56fSmrg pVIADRI->deviceID = pVia->Chipset; 8347e6fb56fSmrg pVIADRI->width = pScrn->virtualX; 8357e6fb56fSmrg pVIADRI->height = pScrn->virtualY; 8367e6fb56fSmrg pVIADRI->mem = pScrn->videoRam * 1024; 8377e6fb56fSmrg pVIADRI->bytesPerPixel = (pScrn->bitsPerPixel + 7) / 8; 8387e6fb56fSmrg pVIADRI->sarea_priv_offset = sizeof(XF86DRISAREARec); 8397e6fb56fSmrg /* TODO */ 8407e6fb56fSmrg pVIADRI->scrnX = pVIADRI->width; 8417e6fb56fSmrg pVIADRI->scrnY = pVIADRI->height; 8427e6fb56fSmrg 8437e6fb56fSmrg /* Initialize IRQ. */ 8447e6fb56fSmrg if (pVia->DRIIrqEnable) 8457e6fb56fSmrg VIADRIIrqInit(pScrn, pVIADRI); 8467e6fb56fSmrg 8477e6fb56fSmrg pVIADRI->ringBufActive = 0; 8487e6fb56fSmrg VIADRIRingBufferInit(pScrn); 8497e6fb56fSmrg return TRUE; 8507e6fb56fSmrg} 8517e6fb56fSmrg 8527e6fb56fSmrgstatic void 8537e6fb56fSmrgVIADRISwapContext(ScreenPtr pScreen, DRISyncType syncType, 8547e6fb56fSmrg DRIContextType oldContextType, void *oldContext, 8557e6fb56fSmrg DRIContextType newContextType, void *newContext) 8567e6fb56fSmrg{ 8577e6fb56fSmrg#if 0 8587e6fb56fSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8597e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 8607e6fb56fSmrg#endif 8617e6fb56fSmrg return; 8627e6fb56fSmrg} 8637e6fb56fSmrg 8647e6fb56fSmrgstatic void 8657e6fb56fSmrgVIADRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) 8667e6fb56fSmrg{ 8677e6fb56fSmrg#if 0 8687e6fb56fSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 8697e6fb56fSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8707e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 8717e6fb56fSmrg#endif 8727e6fb56fSmrg return; 8737e6fb56fSmrg} 8747e6fb56fSmrg 8757e6fb56fSmrgstatic void 8767e6fb56fSmrgVIADRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, 8777e6fb56fSmrg RegionPtr prgnSrc, CARD32 index) 8787e6fb56fSmrg{ 8797e6fb56fSmrg#if 0 8807e6fb56fSmrg ScreenPtr pScreen = pParent->drawable.pScreen; 8817e6fb56fSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 8827e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 8837e6fb56fSmrg#endif 8847e6fb56fSmrg return; 8857e6fb56fSmrg} 8867e6fb56fSmrg 8877e6fb56fSmrg/* Initialize the kernel data structures. */ 8887e6fb56fSmrgstatic Bool 8897e6fb56fSmrgVIADRIKernelInit(ScreenPtr pScreen, VIAPtr pVia) 8907e6fb56fSmrg{ 8917e6fb56fSmrg drm_via_init_t drmInfo; 8927e6fb56fSmrg 8937e6fb56fSmrg memset(&drmInfo, 0, sizeof(drm_via_init_t)); 8947e6fb56fSmrg drmInfo.func = VIA_INIT_MAP; 8957e6fb56fSmrg drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); 8967e6fb56fSmrg drmInfo.fb_offset = pVia->frameBufferHandle; 8977e6fb56fSmrg drmInfo.mmio_offset = pVia->registerHandle; 8987e6fb56fSmrg 8997e6fb56fSmrg if (pVia->IsPCI) { 9007e6fb56fSmrg drmInfo.agpAddr = (CARD32) NULL; 9017e6fb56fSmrg } else { 9027e6fb56fSmrg /*For AMD64*/ 9037e6fb56fSmrg#ifndef __x86_64__ 9047e6fb56fSmrg drmInfo.agpAddr = (CARD32)pVia->agpAddr; 9057e6fb56fSmrg#else 9067e6fb56fSmrg drmInfo.agpAddr = (CARD64)pVia->agpAddr; 9077e6fb56fSmrg#endif 9087e6fb56fSmrg } 9097e6fb56fSmrg 9107e6fb56fSmrg if ((drmCommandWrite(pVia->drmFD, DRM_VIA_MAP_INIT, &drmInfo, 9117e6fb56fSmrg sizeof(drm_via_init_t))) < 0) 9127e6fb56fSmrg return FALSE; 9137e6fb56fSmrg 9147e6fb56fSmrg return TRUE; 9157e6fb56fSmrg} 9167e6fb56fSmrg 9177e6fb56fSmrg/* Add a map for the MMIO registers. */ 9187e6fb56fSmrgstatic Bool 9197e6fb56fSmrgVIADRIMapInit(ScreenPtr pScreen, VIAPtr pVia) 9207e6fb56fSmrg{ 9217e6fb56fSmrg int flags = DRM_READ_ONLY; 9227e6fb56fSmrg 9237e6fb56fSmrg if (drmAddMap(pVia->drmFD, pVia->MmioBase, VIA_MMIO_REGSIZE, 9247e6fb56fSmrg DRM_REGISTERS, flags, &pVia->registerHandle) < 0) { 9257e6fb56fSmrg return FALSE; 9267e6fb56fSmrg } 9277e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] register handle = 0x%08lx\n", 9287e6fb56fSmrg (unsigned long)pVia->registerHandle); 9297e6fb56fSmrg if (drmAddMap(pVia->drmFD, pVia->FrameBufferBase, pVia->videoRambytes, 9307e6fb56fSmrg DRM_FRAME_BUFFER, 0, &pVia->frameBufferHandle) < 0) { 9317e6fb56fSmrg return FALSE; 9327e6fb56fSmrg } 9337e6fb56fSmrg xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = 0x%08lx\n", 9347e6fb56fSmrg (unsigned long)pVia->frameBufferHandle); 9357e6fb56fSmrg 9367e6fb56fSmrg return TRUE; 9377e6fb56fSmrg} 9387e6fb56fSmrg 9397e6fb56fSmrg#define DRM_VIA_BLIT_MAX_SIZE (2048*2048*4) 9407e6fb56fSmrg 9417e6fb56fSmrgstatic int 9427e6fb56fSmrgviaDRIFBMemcpy(int fd, unsigned long fbOffset, unsigned char *addr, 9437e6fb56fSmrg unsigned long size, Bool toFB) 9447e6fb56fSmrg{ 9457e6fb56fSmrg int err; 9467e6fb56fSmrg drm_via_dmablit_t blit; 9477e6fb56fSmrg unsigned long curSize; 9487e6fb56fSmrg 9497e6fb56fSmrg do { 9507e6fb56fSmrg curSize = (size > DRM_VIA_BLIT_MAX_SIZE) ? DRM_VIA_BLIT_MAX_SIZE : size; 9517e6fb56fSmrg 9527e6fb56fSmrg blit.num_lines = 1; 9537e6fb56fSmrg blit.line_length = curSize; 9547e6fb56fSmrg blit.fb_addr = fbOffset; 9557e6fb56fSmrg blit.fb_stride = ALIGN_TO(curSize, 16); 9567e6fb56fSmrg blit.mem_addr = addr; 9577e6fb56fSmrg blit.mem_stride = blit.fb_stride; 9587e6fb56fSmrg blit.to_fb = (toFB) ? 1 : 0; 9597e6fb56fSmrg 9607e6fb56fSmrg do { 9617e6fb56fSmrg err = drmCommandWriteRead(fd, DRM_VIA_DMA_BLIT, 9627e6fb56fSmrg &blit, sizeof(blit)); 9637e6fb56fSmrg } while (-EAGAIN == err); 9647e6fb56fSmrg if (err) 9657e6fb56fSmrg return err; 9667e6fb56fSmrg 9677e6fb56fSmrg do { 9687e6fb56fSmrg err = drmCommandWriteRead(fd, DRM_VIA_BLIT_SYNC, 9697e6fb56fSmrg &blit.sync, sizeof(blit.sync)); 9707e6fb56fSmrg } while (-EAGAIN == err); 9717e6fb56fSmrg if (err) 9727e6fb56fSmrg return err; 9737e6fb56fSmrg 9747e6fb56fSmrg fbOffset += curSize; 9757e6fb56fSmrg addr += curSize; 9767e6fb56fSmrg size -= curSize; 9777e6fb56fSmrg 9787e6fb56fSmrg } while (size > 0); 9797e6fb56fSmrg return 0; 9807e6fb56fSmrg} 9817e6fb56fSmrg 9827e6fb56fSmrg 9837e6fb56fSmrgvoid 9847e6fb56fSmrgviaDRIOffscreenSave(ScrnInfoPtr pScrn) 9857e6fb56fSmrg{ 9867e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 9877e6fb56fSmrg VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 9887e6fb56fSmrg unsigned char *saveAddr = pVia->FBBase + pVIADRI->fbOffset; 9897e6fb56fSmrg unsigned long saveSize = pVIADRI->fbSize; 9907e6fb56fSmrg unsigned long curSize; 9917e6fb56fSmrg int err; 9927e6fb56fSmrg 9937e6fb56fSmrg if (pVia->driOffScreenSave) 9947e6fb56fSmrg free(pVia->driOffScreenSave); 9957e6fb56fSmrg 9967e6fb56fSmrg pVia->driOffScreenSave = malloc(saveSize + 16); 9977e6fb56fSmrg if (pVia->driOffScreenSave) { 9987e6fb56fSmrg if ((pVia->drmVerMajor == 2) && (pVia->drmVerMinor >= 8)) { 9997e6fb56fSmrg err = viaDRIFBMemcpy(pVia->drmFD, pVIADRI->fbOffset, 10007e6fb56fSmrg (unsigned char *) 10017e6fb56fSmrg ALIGN_TO((unsigned long) 10027e6fb56fSmrg pVia->driOffScreenSave, 16), 10037e6fb56fSmrg saveSize, FALSE); 10047e6fb56fSmrg if (!err) 10057e6fb56fSmrg return; 10067e6fb56fSmrg 10077e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 10087e6fb56fSmrg "Hardware backup of DRI offscreen memory failed: %s.\n" 10097e6fb56fSmrg "\tUsing slow software backup instead.\n", 10107e6fb56fSmrg strerror(-err)); 10117e6fb56fSmrg } 10127e6fb56fSmrg memcpy((void *)ALIGN_TO((unsigned long)pVia->driOffScreenSave, 16), 10137e6fb56fSmrg saveAddr, saveSize); 10147e6fb56fSmrg 10157e6fb56fSmrg } else { 10167e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 10177e6fb56fSmrg "Out of memory trying to backup DRI offscreen memory.\n"); 10187e6fb56fSmrg } 10197e6fb56fSmrg return; 10207e6fb56fSmrg} 10217e6fb56fSmrg 10227e6fb56fSmrgvoid 10237e6fb56fSmrgviaDRIOffscreenRestore(ScrnInfoPtr pScrn) 10247e6fb56fSmrg{ 10257e6fb56fSmrg VIAPtr pVia = VIAPTR(pScrn); 10267e6fb56fSmrg VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate; 10277e6fb56fSmrg 10287e6fb56fSmrg unsigned char *saveAddr = pVia->FBBase + pVIADRI->fbOffset; 10297e6fb56fSmrg unsigned long saveSize = pVIADRI->fbSize; 10307e6fb56fSmrg 10317e6fb56fSmrg if (pVia->driOffScreenSave) { 10327e6fb56fSmrg memcpy(saveAddr, 10337e6fb56fSmrg (void *)ALIGN_TO((unsigned long)pVia->driOffScreenSave, 16), 10347e6fb56fSmrg saveSize); 10357e6fb56fSmrg free(pVia->driOffScreenSave); 10367e6fb56fSmrg pVia->driOffScreenSave = NULL; 10377e6fb56fSmrg } 10387e6fb56fSmrg} 1039