📄 intel_dri.c
字号:
/** * \file server/intel_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) 2006 Dave Airlie (airlied@linux.ie) 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 THE COPYRIGHT HOLDERS AND/OR THEIR 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 "intel.h"#include "i830_dri.h"#include "memops.h"#include "pciaccess.h"static size_t drm_page_size;static int nextTile = 0;#define xf86DrvMsg(...) do {} while(0)static const int pitches[] = { 128 * 8, 128 * 16, 128 * 32, 128 * 64, 0};static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea);static unsigned longGetBestTileAlignment(unsigned long size){ unsigned long i; for (i = KB(512); i < size; i <<= 1) ; if (i > MB(64)) i = MB(64); return i;}static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830){ int i; unsigned char *MMIO = ctx->MMIOAddress; for (i = 0; i < 8; i++) { OUTREG(FENCE + i * 4, pI830->Fence[i]); // if (I810_DEBUG & DEBUG_VERBOSE_VGA) fprintf(stderr,"Fence Register : %x\n", pI830->Fence[i]); }}/* Tiled memory is good... really, really good... * * Need to make it less likely that we miss out on this - probably * need to move the frontbuffer away from the 'guarenteed' alignment * of the first memory segment, or perhaps allocate a discontigous * framebuffer to get more alignment 'sweet spots'. */static voidSetFence(const DRIDriverContext *ctx, I830Rec *pI830, int nr, unsigned int start, unsigned int pitch, unsigned int size){ unsigned int val; unsigned int fence_mask = 0; unsigned int fence_pitch; if (nr < 0 || nr > 7) { fprintf(stderr, "SetFence: fence %d out of range\n",nr); return; } pI830->Fence[nr] = 0; if (IS_I9XX(pI830)) fence_mask = ~I915G_FENCE_START_MASK; else fence_mask = ~I830_FENCE_START_MASK; if (start & fence_mask) { fprintf(stderr, "SetFence: %d: start (0x%08x) is not %s aligned\n", nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k"); return; } if (start % size) { fprintf(stderr, "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n", nr, start, size / 1024); return; } if (pitch & 127) { fprintf(stderr, "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n", nr, pitch); return; } val = (start | FENCE_X_MAJOR | FENCE_VALID); if (IS_I9XX(pI830)) { switch (size) { case MB(1): val |= I915G_FENCE_SIZE_1M; break; case MB(2): val |= I915G_FENCE_SIZE_2M; break; case MB(4): val |= I915G_FENCE_SIZE_4M; break; case MB(8): val |= I915G_FENCE_SIZE_8M; break; case MB(16): val |= I915G_FENCE_SIZE_16M; break; case MB(32): val |= I915G_FENCE_SIZE_32M; break; case MB(64): val |= I915G_FENCE_SIZE_64M; break; default: fprintf(stderr, "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); return; } } else { switch (size) { case KB(512): val |= FENCE_SIZE_512K; break; case MB(1): val |= FENCE_SIZE_1M; break; case MB(2): val |= FENCE_SIZE_2M; break; case MB(4): val |= FENCE_SIZE_4M; break; case MB(8): val |= FENCE_SIZE_8M; break; case MB(16): val |= FENCE_SIZE_16M; break; case MB(32): val |= FENCE_SIZE_32M; break; case MB(64): val |= FENCE_SIZE_64M; break; default: fprintf(stderr, "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); return; } } if (IS_I9XX(pI830)) fence_pitch = pitch / 512; else fence_pitch = pitch / 128; switch (fence_pitch) { case 1: val |= FENCE_PITCH_1; break; case 2: val |= FENCE_PITCH_2; break; case 4: val |= FENCE_PITCH_4; break; case 8: val |= FENCE_PITCH_8; break; case 16: val |= FENCE_PITCH_16; break; case 32: val |= FENCE_PITCH_32; break; case 64: val |= FENCE_PITCH_64; break; default: fprintf(stderr, "SetFence: %d: illegal pitch (%d)\n", nr, pitch); return; } pI830->Fence[nr] = val;}static BoolMakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem){ int pitch, ntiles, i; pitch = pMem->Pitch * ctx->cpp; /* * Simply try to break the region up into at most four pieces of size * equal to the alignment. */ ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment; if (ntiles >= 4) { return FALSE; } for (i = 0; i < ntiles; i++, nextTile++) { SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment, pitch, pMem->Alignment); } return TRUE;}static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830){ int i; /* Clear out */ for (i = 0; i < 8; i++) pI830->Fence[i] = 0; nextTile = 0; if (pI830->BackBuffer.Alignment >= KB(512)) { if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) { fprintf(stderr, "Activating tiled memory for the back buffer.\n"); } else { fprintf(stderr, "MakeTiles failed for the back buffer.\n"); pI830->allowPageFlip = FALSE; } } if (pI830->DepthBuffer.Alignment >= KB(512)) { if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) { fprintf(stderr, "Activating tiled memory for the depth buffer.\n"); } else { fprintf(stderr, "MakeTiles failed for the depth buffer.\n"); } } return;}static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830){ struct pci_device host_bridge, ig_dev; uint32_t gmch_ctrl; int memsize = 0; int range; uint32_t aper_size; uint32_t membase2 = 0; memset(&host_bridge, 0, sizeof(host_bridge)); memset(&ig_dev, 0, sizeof(ig_dev)); ig_dev.dev = 2; pci_device_cfg_read_u32(&host_bridge, &gmch_ctrl, I830_GMCH_CTRL); if (IS_I830(pI830) || IS_845G(pI830)) { if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { aper_size = 0x80000000; } else { aper_size = 0x40000000; } } else { if (IS_I9XX(pI830)) { int ret; ret = pci_device_cfg_read_u32(&ig_dev, &membase2, 0x18); if (membase2 & 0x08000000) aper_size = 0x8000000; else aper_size = 0x10000000; fprintf(stderr,"aper size is %08X %08x %d\n", aper_size, membase2, ret); } else aper_size = 0x8000000; } pI830->aper_size = aper_size; /* We need to reduce the stolen size, by the GTT and the popup. * The GTT varying according the the FbMapSize and the popup is 4KB */ range = (ctx->shared.fbSize / (1024*1024)) + 4; if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: memsize = MB(1) - KB(range); break; case I855_GMCH_GMS_STOLEN_4M: memsize = MB(4) - KB(range); break; case I855_GMCH_GMS_STOLEN_8M: memsize = MB(8) - KB(range); break; case I855_GMCH_GMS_STOLEN_16M: memsize = MB(16) - KB(range); break; case I855_GMCH_GMS_STOLEN_32M: memsize = MB(32) - KB(range); break; case I915G_GMCH_GMS_STOLEN_48M: if (IS_I9XX(pI830)) memsize = MB(48) - KB(range); break; case I915G_GMCH_GMS_STOLEN_64M: if (IS_I9XX(pI830)) memsize = MB(64) - KB(range); break; } } else { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { case I830_GMCH_GMS_STOLEN_512: memsize = KB(512) - KB(range); break; case I830_GMCH_GMS_STOLEN_1024: memsize = MB(1) - KB(range); break; case I830_GMCH_GMS_STOLEN_8192: memsize = MB(8) - KB(range); break; case I830_GMCH_GMS_LOCAL: memsize = 0; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Local memory found, but won't be used.\n"); break; } } if (memsize > 0) { fprintf(stderr, "detected %d kB stolen memory.\n", memsize / 1024); } else { fprintf(stderr, "no video memory detected.\n"); } return memsize;}static int AgpInit(const DRIDriverContext *ctx, I830Rec *info){ unsigned long mode = 0x4; if (drmAgpAcquire(ctx->drmFD) < 0) { fprintf(stderr, "[gart] AGP not available\n"); return 0; } if (drmAgpEnable(ctx->drmFD, mode) < 0) { fprintf(stderr, "[gart] AGP not enabled\n"); drmAgpRelease(ctx->drmFD); return 0; } else fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode); return 1;}/* * Allocate memory from the given pool. Grow the pool if needed and if * possible. */static unsigned longAllocFromPool(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *result, I830MemPool *pool, long size, unsigned long alignment, int flags){ long needed, start, end; if (!result || !pool || !size) return 0; /* Calculate how much space is needed. */ if (alignment <= GTT_PAGE_SIZE) needed = size; else { start = ROUND_TO(pool->Free.Start, alignment); end = ROUND_TO(start + size, alignment); needed = end - pool->Free.Start; } if (needed > pool->Free.Size) { return 0; } result->Start = ROUND_TO(pool->Free.Start, alignment);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -