📄 i810_dri.c
字号:
/** * \file server/i810_dri.c * \brief File to perform the device-specific initialization tasks typically * done in the X server. * * Here they are converted to run in the client (or perhaps a standalone * process), and to work with the frame buffer device rather than the X * server infrastructure. * * Copyright (C) 2004 Dave Airlie (airlied@linux.ie) */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include "driver.h"#include "drm.h"#include "i810.h"#include "i810_dri.h"#include "i810_reg.h"static int i810_pitches[] = { 512, 1024, 2048, 4096, 0};static int i810_pitch_flags[] = { 0x0, 0x1, 0x2, 0x3, 0};static unsigned int i810_drm_version = 0;static intI810AllocLow(I810MemRange * result, I810MemRange * pool, int size){ if (size > pool->Size) return 0; pool->Size -= size; result->Size = size; result->Start = pool->Start; result->End = pool->Start += size; return 1;}static intI810AllocHigh(I810MemRange * result, I810MemRange * pool, int size){ if (size > pool->Size) return 0; pool->Size -= size; result->Size = size; result->End = pool->End; result->Start = pool->End -= size; return 1;}/** * \brief Wait for free FIFO entries. * * \param ctx display handle. * \param entries number of free entries to wait. * * It polls the free entries from the chip until it reaches the requested value * or a timeout (3000 tries) occurs. Aborts the program if the FIFO times out. */static void I810WaitForFifo( const DRIDriverContext *ctx, int entries ){}/** * \brief Reset graphics card to known state. * * \param ctx display handle. * * Resets the values of several I810 registers. */static void I810EngineReset( const DRIDriverContext *ctx ){ unsigned char *I810MMIO = ctx->MMIOAddress;}/** * \brief Restore the drawing engine. * * \param ctx display handle * * Resets the graphics card and sets initial values for several registers of * the card's drawing engine. * * Turns on the i810 command processor engine (i.e., the ringbuffer). */static int I810EngineRestore( const DRIDriverContext *ctx ){ I810Ptr info = ctx->driverPrivate; unsigned char *I810MMIO = ctx->MMIOAddress; fprintf(stderr, "%s\n", __FUNCTION__); return 1;}/** * \brief Shutdown the drawing engine. * * \param ctx display handle * * Turns off the command processor engine & restores the graphics card * to a state that fbdev understands. */static int I810EngineShutdown( const DRIDriverContext *ctx ){ drmI810Init info; int ret; memset(&info, 0, sizeof(drmI810Init)); info.func = I810_CLEANUP_DMA; ret = drmCommandWrite(ctx->drmFD, DRM_I810_INIT, &info, sizeof(drmI810Init)); if (ret>0) { fprintf(stderr,"[dri] I810 DMA Cleanup failed\n"); return -errno; } return 0;}/** * \brief Compute base 2 logarithm. * * \param val value. * * \return base 2 logarithm of \p val. */static int I810MinBits(int val){ int bits; if (!val) return 1; for (bits = 0; val; val >>= 1, ++bits); return bits;}static int I810DRIAgpPreInit( const DRIDriverContext *ctx, I810Ptr info){ if (drmAgpAcquire(ctx->drmFD) < 0) { fprintf(stderr, "[gart] AGP not available\n"); return 0; } if (drmAgpEnable(ctx->drmFD, 0) < 0) { fprintf(stderr, "[gart] AGP not enabled\n"); drmAgpRelease(ctx->drmFD); return 0; }}/** * \brief Initialize the AGP state * * \param ctx display handle. * \param info driver private data. * * \return one on success, or zero on failure. * * Acquires and enables the AGP device. Reserves memory in the AGP space for * the ring buffer, vertex buffers and textures. Initialize the I810 * registers to point to that memory and add client mappings. */static int I810DRIAgpInit( const DRIDriverContext *ctx, I810Ptr info){ unsigned char *I810MMIO = ctx->MMIOAddress; int ret; int s, l; unsigned long dcacheHandle; unsigned long agpHandle; int pitch_idx = 0; int back_size = 0; int sysmem_size = 0; int width = ctx->shared.virtualWidth * ctx->cpp; info->backHandle = DRM_AGP_NO_HANDLE; info->zHandle = DRM_AGP_NO_HANDLE; info->sysmemHandle = DRM_AGP_NO_HANDLE; info->dcacheHandle = DRM_AGP_NO_HANDLE; memset(&info->DcacheMem, 0, sizeof(I810MemRange)); memset(&info->BackBuffer, 0, sizeof(I810MemRange)); memset(&info->DepthBuffer, 0, sizeof(I810MemRange)); drmAgpAlloc(ctx->drmFD, 4096 * 1024, 1, NULL, &dcacheHandle); info->dcacheHandle = dcacheHandle; fprintf(stderr, "[agp] dcacheHandle : 0x%x\n", dcacheHandle);#define Elements(x) sizeof(x)/sizeof(*x) for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++) if (width <= i810_pitches[pitch_idx]) break; if (pitch_idx == Elements(i810_pitches)) { fprintf(stderr,"[dri] Couldn't find depth/back buffer pitch\n"); exit(-1); } else { int lines = (ctx->shared.virtualWidth + 15) / 16 * 16; back_size = i810_pitches[pitch_idx] * lines; back_size = ((back_size + 4096 - 1) / 4096) * 4096; } sysmem_size = ctx->shared.fbSize; fprintf(stderr,"sysmem_size is %lu back_size is %lu\n", sysmem_size, back_size); if (dcacheHandle != DRM_AGP_NO_HANDLE) { if (back_size > 4 * 1024 * 1024) { fprintf(stderr,"[dri] Backsize is larger then 4 meg\n"); sysmem_size = sysmem_size - 2 * back_size; drmAgpFree(ctx->drmFD, dcacheHandle); info->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; } else { sysmem_size = sysmem_size - back_size; } } else { sysmem_size = sysmem_size - 2 * back_size; } info->SysMem.Start=0; info->SysMem.Size = sysmem_size; info->SysMem.End = sysmem_size; if (dcacheHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(ctx->drmFD, dcacheHandle, info->DepthOffset) == 0) { memset(&info->DcacheMem, 0, sizeof(I810MemRange)); fprintf(stderr,"[agp] GART: Found 4096K Z buffer memory\n"); info->DcacheMem.Start = info->DepthOffset; info->DcacheMem.Size = 1024 * 4096; info->DcacheMem.End = info->DcacheMem.Start + info->DcacheMem.Size; } else { fprintf(stderr, "[agp] GART: dcache bind failed\n"); drmAgpFree(ctx->drmFD, dcacheHandle); info->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; } } else { fprintf(stderr, "[agp] GART: no dcache memory found\n"); } drmAgpAlloc(ctx->drmFD, back_size, 0, NULL, &agpHandle); info->backHandle = agpHandle; if (agpHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(ctx->drmFD, agpHandle, info->BackOffset) == 0) { fprintf(stderr, "[agp] Bound backbuffer memory\n"); info->BackBuffer.Start = info->BackOffset; info->BackBuffer.Size = back_size; info->BackBuffer.End = (info->BackBuffer.Start + info->BackBuffer.Size); } else { fprintf(stderr,"[agp] Unable to bind backbuffer. Disabling DRI.\n"); return 0; } } else { fprintf(stderr, "[dri] Unable to allocate backbuffer memory. Disabling DRI.\n"); return 0; } if (dcacheHandle == DRM_AGP_NO_HANDLE) { drmAgpAlloc(ctx->drmFD, back_size, 0, NULL, &agpHandle); info->zHandle = agpHandle; if (agpHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(ctx->drmFD, agpHandle, info->DepthOffset) == 0) { fprintf(stderr,"[agp] Bound depthbuffer memory\n"); info->DepthBuffer.Start = info->DepthOffset; info->DepthBuffer.Size = back_size; info->DepthBuffer.End = (info->DepthBuffer.Start + info->DepthBuffer.Size); } else { fprintf(stderr,"[agp] Unable to bind depthbuffer. Disabling DRI.\n"); return 0; } } else { fprintf(stderr,"[agp] Unable to allocate depthbuffer memory. Disabling DRI.\n"); return 0; } } /* Now allocate and bind the agp space. This memory will include the * regular framebuffer as well as texture memory. */ drmAgpAlloc(ctx->drmFD, sysmem_size, 0, NULL, &agpHandle); info->sysmemHandle = agpHandle; if (agpHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(ctx->drmFD, agpHandle, 0) == 0) { fprintf(stderr, "[agp] Bound System Texture Memory\n"); } else { fprintf(stderr, "[agp] Unable to bind system texture memory. Disabling DRI.\n"); return 0; } } else { fprintf(stderr, "[agp] Unable to allocate system texture memory. Disabling DRI.\n"); return 0; } info->auxPitch = i810_pitches[pitch_idx]; info->auxPitchBits = i810_pitch_flags[pitch_idx]; return 1;}/** * \brief Initialize the kernel data structures and enable the CP engine. * * \param ctx display handle. * \param info driver private data. * * \return non-zero on success, or zero on failure. * * This function is a wrapper around the DRM_I810_CP_INIT command, passing * all the parameters in a drmI810Init structure. */static int I810DRIKernelInit( const DRIDriverContext *ctx, I810Ptr info){ int cpp = ctx->bpp / 8; drmI810Init drmInfo; int ret; I810RingBuffer *ring = &(info->LpRing); /* This is the struct passed to the kernel module for its initialization */ memset(&drmInfo, 0, sizeof(drmI810Init)); /* make sure we have at least 1.4 */ drmInfo.func = I810_INIT_DMA_1_4; drmInfo.ring_start = ring->mem.Start; drmInfo.ring_end = ring->mem.End; drmInfo.ring_size = ring->mem.Size; drmInfo.mmio_offset = (unsigned int)info->regs; drmInfo.buffers_offset = (unsigned int)info->buffer_map; drmInfo.sarea_priv_offset = sizeof(drm_sarea_t); drmInfo.front_offset = 0; drmInfo.back_offset = info->BackBuffer.Start; drmInfo.depth_offset = info->DepthBuffer.Start; drmInfo.w = ctx->shared.virtualWidth; drmInfo.h = ctx->shared.virtualHeight; drmInfo.pitch = info->auxPitch; drmInfo.pitch_bits = info->auxPitchBits; ret = drmCommandWrite(ctx->drmFD, DRM_I810_INIT, &drmInfo, sizeof(drmI810Init)); return ret >= 0;}/** * \brief Add a map for the vertex buffers that will be accessed by any * DRI-based clients. * * \param ctx display handle. * \param info driver private data. * * \return one on success, or zero on failure. * * Calls drmAddBufs() with the previously allocated vertex buffers. */static int I810DRIBufInit( const DRIDriverContext *ctx, I810Ptr info ){ /* Initialize vertex buffers */ info->bufNumBufs = drmAddBufs(ctx->drmFD, I810_DMA_BUF_NR, I810_DMA_BUF_SZ, DRM_AGP_BUFFER, info->BufferMem.Start); if (info->bufNumBufs <= 0) { fprintf(stderr, "[drm] Could not create vertex/indirect buffers list\n"); return 0; } fprintf(stderr, "[drm] Added %d %d byte vertex/indirect buffers\n", info->bufNumBufs, I810_DMA_BUF_SZ); return 1;}/** * \brief Install an IRQ handler. * * \param ctx display handle. * \param info driver private data. * * Attempts to install an IRQ handler via drmCtlInstHandler(), falling back to * IRQ-free operation on failure. */static void I810DRIIrqInit(const DRIDriverContext *ctx, I810Ptr info){ if (!info->irq) { info->irq = drmGetInterruptFromBusID(ctx->drmFD, ctx->pciBus, ctx->pciDevice, ctx->pciFunc); if ((drmCtlInstHandler(ctx->drmFD, info->irq)) != 0) { fprintf(stderr, "[drm] failure adding irq handler, " "there is a device already using that irq\n" "[drm] falling back to irq-free operation\n"); info->irq = 0; } } if (info->irq) fprintf(stderr, "[drm] dma control initialized, using IRQ %d\n", info->irq);}static int I810CheckDRMVersion( const DRIDriverContext *ctx, I810Ptr info ){ drmVersionPtr version; version = drmGetVersion(ctx->drmFD); if (version) { int req_minor, req_patch; req_minor = 4; req_patch = 0; i810_drm_version = (version->version_major<<16) | version->version_minor; if (version->version_major != 1 || version->version_minor < req_minor || (version->version_minor == req_minor && version->version_patchlevel < req_patch)) { /* Incompatible drm version */ fprintf(stderr, "[dri] I810DRIScreenInit failed because of a version " "mismatch.\n" "[dri] i810.o kernel module version is %d.%d.%d " "but version 1.%d.%d or newer is needed.\n" "[dri] Disabling DRI.\n", version->version_major, version->version_minor, version->version_patchlevel, req_minor, req_patch); drmFreeVersion(version); return 0; } info->drmMinor = version->version_minor; drmFreeVersion(version); } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -