📄 via_dri.c
字号:
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/via/via_dri.c,v 1.4 2003/09/24 02:43:30 dawes Exp $ *//* * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h> #include "driver.h"#include "drm.h"#include "imports.h"#include "dri_util.h"#include "via_context.h"#include "via_dri.h"#include "via_driver.h"#include "xf86drm.h"static void VIAEnableMMIO(DRIDriverContext * ctx);static void VIADisableMMIO(DRIDriverContext * ctx);static void VIADisableExtendedFIFO(DRIDriverContext *ctx);static void VIAEnableExtendedFIFO(DRIDriverContext *ctx);static void VIAInitialize2DEngine(DRIDriverContext *ctx);static void VIAInitialize3DEngine(DRIDriverContext *ctx);static int VIADRIScreenInit(DRIDriverContext * ctx);static void VIADRICloseScreen(DRIDriverContext * ctx);static int VIADRIFinishScreenInit(DRIDriverContext * ctx);/* _SOLO : missing macros normally defined by X code */#define xf86DrvMsg(a, b, ...) fprintf(stderr, __VA_ARGS__)#define MMIO_IN8(base, addr) ((*(((volatile u_int8_t*)base)+(addr)))+0)#define MMIO_OUT8(base, addr, val) ((*(((volatile u_int8_t*)base)+(addr)))=((u_int8_t)val))#define MMIO_OUT16(base, addr, val) ((*(volatile u_int16_t*)(((u_int8_t*)base)+(addr)))=((u_int16_t)val))#define VIDEO 0 #define AGP 1#define AGP_PAGE_SIZE 4096#define AGP_PAGES 8192#define AGP_SIZE (AGP_PAGE_SIZE * AGP_PAGES)#define AGP_CMDBUF_PAGES 512#define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES)static char VIAKernelDriverName[] = "via";static char VIAClientDriverName[] = "unichrome";static int VIADRIAgpInit(const DRIDriverContext *ctx, VIAPtr pVia);static int VIADRIPciInit(DRIDriverContext * ctx, VIAPtr pVia);static int VIADRIFBInit(DRIDriverContext * ctx, VIAPtr pVia);static int VIADRIKernelInit(DRIDriverContext * ctx, VIAPtr pVia);static int VIADRIMapInit(DRIDriverContext * ctx, VIAPtr pVia);static void VIADRIIrqInit( DRIDriverContext *ctx ){ VIAPtr pVia = VIAPTR(ctx); VIADRIPtr pVIADRI = pVia->devPrivate; pVIADRI->irqEnabled = drmGetInterruptFromBusID(pVia->drmFD, ctx->pciBus, ctx->pciDevice, ctx->pciFunc); if ((drmCtlInstHandler(pVia->drmFD, pVIADRI->irqEnabled))) { xf86DrvMsg(pScreen->myNum, X_WARNING, "[drm] Failure adding irq handler. " "Falling back to irq-free operation.\n"); pVIADRI->irqEnabled = 0; } if (pVIADRI->irqEnabled) xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Irq handler installed, using IRQ %d.\n", pVIADRI->irqEnabled);}static void VIADRIIrqExit( DRIDriverContext *ctx ) { VIAPtr pVia = VIAPTR(ctx); VIADRIPtr pVIADRI = pVia->devPrivate; if (pVIADRI->irqEnabled) { if (drmCtlUninstHandler(pVia->drmFD)) { xf86DrvMsg(pScreen-myNum, X_INFO,"[drm] Irq handler uninstalled.\n"); } else { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Could not uninstall irq handler.\n"); } }} static void VIADRIRingBufferCleanup(DRIDriverContext *ctx){ VIAPtr pVia = VIAPTR(ctx); VIADRIPtr pVIADRI = pVia->devPrivate; drm_via_dma_init_t ringBufInit; if (pVIADRI->ringBufActive) { xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Cleaning up DMA ring-buffer.\n"); ringBufInit.func = VIA_CLEANUP_DMA; if (drmCommandWrite(pVia->drmFD, DRM_VIA_DMA_INIT, &ringBufInit, sizeof(ringBufInit))) { xf86DrvMsg(pScreen->myNum, X_WARNING, "[drm] Failed to clean up DMA ring-buffer: %d\n", errno); } pVIADRI->ringBufActive = 0; }}static int VIADRIRingBufferInit(DRIDriverContext *ctx){ VIAPtr pVia = VIAPTR(ctx); VIADRIPtr pVIADRI = pVia->devPrivate; drm_via_dma_init_t ringBufInit; drmVersionPtr drmVer; pVIADRI->ringBufActive = 0; if (NULL == (drmVer = drmGetVersion(pVia->drmFD))) { return GL_FALSE; } if (((drmVer->version_major <= 1) && (drmVer->version_minor <= 3))) { return GL_FALSE; } /* * Info frome code-snippet on DRI-DEVEL list; Erdi Chen. */ switch (pVia->ChipId) { case PCI_CHIP_VT3259: ringBufInit.reg_pause_addr = 0x40c; break; default: ringBufInit.reg_pause_addr = 0x418; break; } ringBufInit.offset = pVia->agpSize; ringBufInit.size = AGP_CMDBUF_SIZE; ringBufInit.func = VIA_INIT_DMA; if (drmCommandWrite(pVia->drmFD, DRM_VIA_DMA_INIT, &ringBufInit, sizeof(ringBufInit))) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to initialize DMA ring-buffer: %d\n", errno); return GL_FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Initialized AGP ring-buffer, size 0x%lx at AGP offset 0x%lx.\n", ringBufInit.size, ringBufInit.offset); pVIADRI->ringBufActive = 1; return GL_TRUE;} static int VIADRIAgpInit(const DRIDriverContext *ctx, VIAPtr pVia){ unsigned long agp_phys; drmAddress agpaddr; VIADRIPtr pVIADRI; pVIADRI = pVia->devPrivate; pVia->agpSize = 0; if (drmAgpAcquire(pVia->drmFD) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAcquire failed %d\n", errno); return GL_FALSE; } if (drmAgpEnable(pVia->drmFD, drmAgpGetMode(pVia->drmFD)&~0x0) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpEnable failed\n"); return GL_FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] drmAgpEnabled succeeded\n"); if (drmAgpAlloc(pVia->drmFD, AGP_SIZE, 0, &agp_phys, &pVia->agpHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAlloc failed\n"); drmAgpRelease(pVia->drmFD); return GL_FALSE; } if (drmAgpBind(pVia->drmFD, pVia->agpHandle, 0) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpBind failed\n"); drmAgpFree(pVia->drmFD, pVia->agpHandle); drmAgpRelease(pVia->drmFD); return GL_FALSE; } /* * Place the ring-buffer last in the AGP region, and restrict the * public map not to include the buffer for security reasons. */ pVia->agpSize = AGP_SIZE - AGP_CMDBUF_SIZE; pVia->agpAddr = drmAgpBase(pVia->drmFD); xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] agpAddr = 0x%08lx\n",pVia->agpAddr); pVIADRI->agp.size = pVia->agpSize; if (drmAddMap(pVia->drmFD, (drm_handle_t)0, pVIADRI->agp.size, DRM_AGP, 0, &pVIADRI->agp.handle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to map public agp area\n"); pVIADRI->agp.size = 0; return GL_FALSE; } /* Map AGP from kernel to Xserver - Not really needed */ drmMap(pVia->drmFD, pVIADRI->agp.handle,pVIADRI->agp.size, &agpaddr); xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] agpAddr = 0x%08lx\n", pVia->agpAddr); xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] agpSize = 0x%08lx\n", pVia->agpSize); xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] agp physical addr = 0x%08lx\n", agp_phys); { drm_via_agp_t agp; agp.offset = 0; agp.size = AGP_SIZE-AGP_CMDBUF_SIZE; if (drmCommandWrite(pVia->drmFD, DRM_VIA_AGP_INIT, &agp, sizeof(drm_via_agp_t)) < 0) { drmUnmap(&agpaddr,pVia->agpSize); drmRmMap(pVia->drmFD,pVIADRI->agp.handle); drmAgpUnbind(pVia->drmFD, pVia->agpHandle); drmAgpFree(pVia->drmFD, pVia->agpHandle); drmAgpRelease(pVia->drmFD); return GL_FALSE; } } return GL_TRUE;}static int VIADRIFBInit(DRIDriverContext * ctx, VIAPtr pVia){ int FBSize = pVia->FBFreeEnd-pVia->FBFreeStart; int FBOffset = pVia->FBFreeStart; VIADRIPtr pVIADRI = pVia->devPrivate; pVIADRI->fbOffset = FBOffset; pVIADRI->fbSize = pVia->videoRambytes; { drm_via_fb_t fb; fb.offset = FBOffset; fb.size = FBSize; if (drmCommandWrite(pVia->drmFD, DRM_VIA_FB_INIT, &fb, sizeof(drm_via_fb_t)) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] failed to init frame buffer area\n"); return GL_FALSE; } else { xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] FBFreeStart= 0x%08x FBFreeEnd= 0x%08x " "FBSize= 0x%08x\n", pVia->FBFreeStart, pVia->FBFreeEnd, FBSize); return GL_TRUE; } }}static int VIADRIPciInit(DRIDriverContext * ctx, VIAPtr pVia){ return GL_TRUE; }static int VIADRIScreenInit(DRIDriverContext * ctx){ VIAPtr pVia = VIAPTR(ctx); VIADRIPtr pVIADRI; int err;#if 0 ctx->shared.SAREASize = ((sizeof(drm_sarea_t) + 0xfff) & 0x1000);#else if (sizeof(drm_sarea_t)+sizeof(drm_via_sarea_t) > SAREA_MAX) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Data does not fit in SAREA\n"); return GL_FALSE; } ctx->shared.SAREASize = SAREA_MAX;#endif ctx->drmFD = drmOpen(VIAKernelDriverName, NULL); if (ctx->drmFD < 0) { fprintf(stderr, "[drm] drmOpen failed\n"); return 0; } pVia->drmFD = ctx->drmFD; err = drmSetBusid(ctx->drmFD, ctx->pciBusID); if (err < 0) { fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", ctx->drmFD, ctx->pciBusID, strerror(-err)); return 0; } err = drmAddMap(ctx->drmFD, 0, ctx->shared.SAREASize, DRM_SHM, DRM_CONTAINS_LOCK, &ctx->shared.hSAREA); if (err < 0) { fprintf(stderr, "[drm] drmAddMap failed\n"); return 0; } fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", ctx->shared.SAREASize, ctx->shared.hSAREA); if (drmMap(ctx->drmFD, ctx->shared.hSAREA, ctx->shared.SAREASize, (drmAddressPtr)(&ctx->pSAREA)) < 0) { fprintf(stderr, "[drm] drmMap failed\n"); return 0; } memset(ctx->pSAREA, 0, ctx->shared.SAREASize); fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); /* Need to AddMap the framebuffer and mmio regions here: */ if (drmAddMap(ctx->drmFD, (drm_handle_t)ctx->FBStart, ctx->FBSize, DRM_FRAME_BUFFER,#ifndef _EMBEDDED 0,#else DRM_READ_ONLY,#endif &ctx->shared.hFrameBuffer) < 0) { fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); return 0; } fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", ctx->shared.hFrameBuffer); pVIADRI = (VIADRIPtr) CALLOC(sizeof(VIADRIRec)); if (!pVIADRI) { drmClose(ctx->drmFD); return GL_FALSE; } pVia->devPrivate = pVIADRI; ctx->driverClientMsg = pVIADRI; ctx->driverClientMsgSize = sizeof(*pVIADRI); /* DRIScreenInit doesn't add all the common mappings. Add additional mappings here. */ if (!VIADRIMapInit(ctx, pVia)) { VIADRICloseScreen(ctx); return GL_FALSE; } pVIADRI->regs.size = VIA_MMIO_REGSIZE; pVIADRI->regs.handle = pVia->registerHandle; xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] mmio Registers = 0x%08lx\n", pVIADRI->regs.handle); if (drmMap(pVia->drmFD, pVIADRI->regs.handle, pVIADRI->regs.size, (drmAddress *)&pVia->MapBase) != 0) { VIADRICloseScreen(ctx); return GL_FALSE; } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] mmio mapped.\n" ); VIAEnableMMIO(ctx); /* Get video memory clock. */ VGAOUT8(0x3D4, 0x3D); pVia->MemClk = (VGAIN8(0x3D5) & 0xF0) >> 4; xf86DrvMsg(0, X_INFO, "[dri] MemClk (0x%x)\n", pVia->MemClk); /* 3D rendering has noise if not enabled. */ VIAEnableExtendedFIFO(ctx); VIAInitialize2DEngine(ctx); /* Must disable MMIO or 3D won't work. */ VIADisableMMIO(ctx); VIAInitialize3DEngine(ctx); pVia->IsPCI = !VIADRIAgpInit(ctx, pVia); if (pVia->IsPCI) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -