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