From: Dave Airlie Date: Mon, 15 Mar 2004 05:20:08 +0000 (+0000) Subject: Initial i810_dri.c for miniglx isn't fully functional yet... X-Git-Tag: mesa-7.8~11351 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6ff468d19e369f61834b7576b1d3244fdb447839;p=platform%2Fupstream%2Fmesa.git Initial i810_dri.c for miniglx isn't fully functional yet... --- diff --git a/src/mesa/drivers/dri/i810/server/i810_dri.c b/src/mesa/drivers/dri/i810/server/i810_dri.c new file mode 100644 index 0000000..82c04bf --- /dev/null +++ b/src/mesa/drivers/dri/i810/server/i810_dri.c @@ -0,0 +1,1024 @@ +/** + * \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 +#include +#include +#include +#include + +#include "driver.h" +#include "drm.h" + +#include "i810.h" +#include "i810_dri.h" +#include "i810_reg.h" + + +/* HACK - for now, put this here... */ +/* Alpha - this may need to be a variable to handle UP1x00 vs TITAN */ +#if defined(__alpha__) +# define DRM_PAGE_SIZE 8192 +#elif defined(__ia64__) +# define DRM_PAGE_SIZE getpagesize() +#else +# define DRM_PAGE_SIZE 4096 +#endif + +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 int +I810AllocLow(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 int +I810AllocHigh(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; + + + 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 : %p\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; +} + +static int I810MemoryInit( const DRIDriverContext *ctx, I810Ptr info ) +{ + int width_bytes = ctx->shared.virtualWidth * ctx->cpp; + int cpp = ctx->cpp; + int bufferSize = (ctx->shared.virtualHeight * width_bytes); + int depthSize = (((ctx->shared.virtualHeight+15) & ~15) * width_bytes); + int l; + + if (drmAddMap(ctx->drmFD, (drmHandle) info->BackBuffer.Start, + info->BackBuffer.Size, DRM_AGP, 0, + &info->backbuffer) < 0) { + fprintf(stderr, "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n"); + return 0; + } + + if (drmAddMap(ctx->drmFD, (drmHandle) info->DepthBuffer.Start, + info->DepthBuffer.Size, DRM_AGP, 0, + &info->depthbuffer) < 0) { + fprintf(stderr, "[drm] drmAddMap(depthbuffer) failed. Disabling DRI.\n"); + return 0; + } + + if (!I810AllocLow(&(info->FrontBuffer), &(info->SysMem), (((ctx->shared.virtualHeight * width_bytes) + 4095) & ~4095))) + { + fprintf(stderr,"Framebuffer allocation failed\n"); + return 0; + } + else + fprintf(stderr,"Frame buffer at 0x%.8x (%luk, %lu bytes)\n", + info->FrontBuffer.Start, + info->FrontBuffer.Size / 1024, info->FrontBuffer.Size); + + memset(&(info->LpRing), 0, sizeof(I810RingBuffer)); + if (I810AllocLow(&(info->LpRing.mem), &(info->SysMem), 16 * 4096)) { + fprintf(stderr, + "Ring buffer at 0x%.8x (%luk, %lu bytes)\n", + info->LpRing.mem.Start, + info->LpRing.mem.Size / 1024, info->LpRing.mem.Size); + + info->LpRing.tail_mask = info->LpRing.mem.Size - 1; + info->LpRing.virtual_start = info->FbBase + info->LpRing.mem.Start; + info->LpRing.head = 0; + info->LpRing.tail = 0; + info->LpRing.space = 0; + } else { + fprintf(stderr, "Ring buffer allocation failed\n"); + return (0); + } + + /* Allocate buffer memory */ + I810AllocHigh(&(info->BufferMem), &(info->SysMem), + I810_DMA_BUF_NR * I810_DMA_BUF_SZ); + + + fprintf(stderr, "[dri] Buffer map : %lx\n", + info->BufferMem.Start); + + if (info->BufferMem.Start == 0 || + info->BufferMem.End - info->BufferMem.Start > + I810_DMA_BUF_NR * I810_DMA_BUF_SZ) { + fprintf(stderr,"[dri] Not enough memory for dma buffers. Disabling DRI.\n"); + return 0; + } + + if (drmAddMap(ctx->drmFD, (drmHandle) info->BufferMem.Start, + info->BufferMem.Size, DRM_AGP, 0, &info->buffer_map) < 0) { + fprintf(stderr, "[drm] drmAddMap(buffer_map) failed. Disabling DRI.\n"); + return 0; + } + + if (drmAddMap(ctx->drmFD, (drmHandle) info->LpRing.mem.Start, + info->LpRing.mem.Size, DRM_AGP, 0, &info->ring_map) < 0) { + fprintf(stderr, "[drm] drmAddMap(ring_map) failed. Disabling DRI. \n"); + return 0; + } + + /* Front, back and depth buffers - everything else texture?? + */ + info->textureSize = info->SysMem.Size; + + if (info->textureSize < 0) + return 0; + + + l = I810MinBits((info->textureSize-1) / I810_NR_TEX_REGIONS); + if (l < I810_LOG_MIN_TEX_REGION_SIZE) l = I810_LOG_MIN_TEX_REGION_SIZE; + + /* Round the texture size up to the nearest whole number of + * texture regions. Again, be greedy about this, don't + * round down. + */ + info->logTextureGranularity = l; + info->textureSize = (info->textureSize >> l) << l; + + /* Set a minimum usable local texture heap size. This will fit + * two 256x256x32bpp textures. + */ + if (info->textureSize < 512 * 1024) { + info->textureOffset = 0; + info->textureSize = 0; + } + + I810AllocLow(&(info->TexMem), &(info->SysMem), info->textureSize); + + if (drmAddMap(ctx->drmFD, (drmHandle) info->TexMem.Start, + info->TexMem.Size, DRM_AGP, 0, &info->textures) < 0) { + fprintf(stderr, + "[drm] drmAddMap(textures) failed. Disabling DRI.\n"); + return 0; + } + + /* Reserve space for textures */ + fprintf(stderr, + "Will use back buffer at offset 0x%x\n", + info->BackOffset); + fprintf(stderr, + "Will use depth buffer at offset 0x%x\n", + info->DepthOffset); + fprintf(stderr, + "Will use %d kb for textures at offset 0x%x\n", + info->TexMem.Size/1024, info->TexMem.Start); + + return 1; +} + + + +/** + * Called at the start of each server generation. + * + * \param ctx display handle. + * \param info driver private data. + * + * \return non-zero on success, or zero on failure. + * + * Performs static frame buffer allocation. Opens the DRM device and add maps + * to the SAREA, framebuffer and MMIO regions. Fills in \p info with more + * information. Creates a \e server context to grab the lock for the + * initialization ioctls and calls the other initilization functions in this + * file. Starts the CP engine via the DRM_I810_CP_START command. + * + * Setups a I810DRIRec structure to be passed to i810_dri.so for its + * initialization. + */ +static int I810ScreenInit( DRIDriverContext *ctx, I810Ptr info ) +{ + I810DRIPtr pI810DRI; + int err; + + usleep(100); + /*assert(!ctx->IsClient);*/ + + /* from XFree86 driver */ + info->DepthOffset = 0x3000000; + info->BackOffset = 0x3800000; + { + int width_bytes = (ctx->shared.virtualWidth * ctx->cpp); + int maxy = ctx->shared.fbSize / width_bytes; + + + if (maxy <= ctx->shared.virtualHeight * 3) { + fprintf(stderr, + "Static buffer allocation failed -- " + "need at least %d kB video memory (have %d kB)\n", + (ctx->shared.virtualWidth * ctx->shared.virtualHeight * + ctx->cpp * 3 + 1023) / 1024, + ctx->shared.fbSize / 1024); + return 0; + } + } + + + info->regsSize = ctx->MMIOSize; + ctx->shared.SAREASize = 0x2000; + + /* Note that drmOpen will try to load the kernel module, if needed. */ + ctx->drmFD = drmOpen("i810", NULL ); + if (ctx->drmFD < 0) { + fprintf(stderr, "[drm] drmOpen failed\n"); + return 0; + } + + if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { + fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", + ctx->drmFD, ctx->pciBusID, strerror(-err)); + return 0; + } + + if (drmAddMap( ctx->drmFD, + 0, + ctx->shared.SAREASize, + DRM_SHM, + DRM_CONTAINS_LOCK, + &ctx->shared.hSAREA) < 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); + + if (drmAddMap(ctx->drmFD, + ctx->MMIOStart, + ctx->MMIOSize, + DRM_REGISTERS, + DRM_READ_ONLY, + &info->regs) < 0) { + fprintf(stderr, "[drm] drmAddMap mmio failed\n"); + return 0; + } + fprintf(stderr, + "[drm] register handle = 0x%08lx\n", info->regs); + + I810DRIAgpPreInit(ctx, info); + /* Need to AddMap the framebuffer and mmio regions here: + */ + if (drmAddMap( ctx->drmFD, + (drmHandle)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); + + + + + + /* Check the i810 DRM version */ + if (!I810CheckDRMVersion(ctx, info)) { + return 0; + } + + /* Initialize AGP */ + if (!I810DRIAgpInit(ctx, info)) { + return 0; + } + + + /* Memory manager setup */ + if (!I810MemoryInit(ctx, info)) { + return 0; + } + + /* Create a 'server' context so we can grab the lock for + * initialization ioctls. + */ + if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { + fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); + return 0; + } + + DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); + + /* Initialize the kernel data structures */ + if (!I810DRIKernelInit(ctx, info)) { + fprintf(stderr, "I810DRIKernelInit failed\n"); + DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); + return 0; + } + + /* Initialize the vertex buffers list */ + if (!I810DRIBufInit(ctx, info)) { + fprintf(stderr, "I810DRIBufInit failed\n"); + DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext); + return 0; + } + + /* Initialize IRQ */ + I810DRIIrqInit(ctx, info); + + /* Initialize the SAREA private data structure */ + { + I810SAREAPtr pSAREAPriv; + pSAREAPriv = (I810SAREAPtr)(((char*)ctx->pSAREA) + + sizeof(drm_sarea_t)); + memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); + // pSAREAPriv->pf_enabled=1; + } + + + /* Quick hack to clear the front & back buffers. Could also use + * the clear ioctl to do this, but would need to setup hw state + * first. + */ +#if 0 + memset((char *)ctx->FBAddress, + 0, + info->auxPitch * ctx->cpp * ctx->shared.virtualHeight ); + + memset((char *)info->backbuffer, + 0, + info->auxPitch * ctx->cpp * ctx->shared.virtualHeight ); +#endif + + /* This is the struct passed to i810_dri.so for its initialization */ + ctx->driverClientMsg = malloc(sizeof(I810DRIRec)); + ctx->driverClientMsgSize = sizeof(I810DRIRec); + pI810DRI = (I810DRIPtr)ctx->driverClientMsg; + + pI810DRI->regs = info->regs; + pI810DRI->regsSize = info->regsSize; + // regsMap is unused + + pI810DRI->backbufferSize = info->BackBuffer.Size; + pI810DRI->backbuffer = info->backbuffer; + + pI810DRI->depthbufferSize = info->DepthBuffer.Size; + pI810DRI->depthbuffer = info->depthbuffer; + + pI810DRI->textures = info->textures; + pI810DRI->textureSize = info->textureSize; + + pI810DRI->agp_buffers = info->buffer_map; + pI810DRI->agp_buf_size = info->BufferMem.Size; + + pI810DRI->deviceID = info->Chipset; + pI810DRI->width = ctx->shared.virtualWidth; + pI810DRI->height = ctx->shared.virtualHeight; + pI810DRI->mem = ctx->shared.fbSize; + pI810DRI->cpp = ctx->bpp / 8; + pI810DRI->bitsPerPixel = ctx->bpp; + pI810DRI->fbOffset = info->FrontBuffer.Start; + pI810DRI->fbStride = info->auxPitch; + + pI810DRI->backOffset = info->BackBuffer.Start; + pI810DRI->depthOffset = info->DepthBuffer.Start; + + pI810DRI->auxPitch = info->auxPitch; + pI810DRI->auxPitchBits = info->auxPitchBits; + + pI810DRI->logTextureGranularity = info->logTextureGranularity; + pI810DRI->textureOffset = info->TexMem.Start; + + pI810DRI->ringOffset = info->LpRing.mem.Start; + pI810DRI->ringSize = info->LpRing.mem.Size; + + // drmBufs looks unused + pI810DRI->irq = info->irq; + pI810DRI->sarea_priv_offset = sizeof(drm_sarea_t); + + /* Don't release the lock now - let the VT switch handler do it. */ + return 1; +} + + +/** + * \brief Establish the set of modes available for the display. + * + * \param ctx display handle. + * \param numModes will receive the number of supported modes. + * \param modes will point to the list of supported modes. + * + * \return one on success, or zero on failure. + * + * Allocates a single visual and fills it with information according to the + * display bit depth. Supports only 16 and 32 bpp bit depths, aborting + * otherwise. + */ +const __GLcontextModes __glModes[] = { + + /* 16 bit, RGB Depth=16 */ + {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE, + .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_FALSE, + .redBits = 5, .greenBits = 6, .blueBits = 5, .alphaBits = 0, + .redMask = 0xf800, .greenMask = 0x07e0, .blueMask = 0x001f, .alphaMask = 0x0, + .rgbBits = 16, .indexBits = 0, + .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0, + .depthBits = 16, .stencilBits = 0, + .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, }, +}; +static int i810InitContextModes( const DRIDriverContext *ctx, + int *numModes, const __GLcontextModes **modes) +{ + *numModes = sizeof(__glModes)/sizeof(__GLcontextModes *); + *modes = &__glModes[0]; + return 1; +} + + +/** + * \brief Validate the fbdev mode. + * + * \param ctx display handle. + * + * \return one on success, or zero on failure. + * + * Saves some registers and returns 1. + * + * \sa i810ValidateMode(). + */ +static int i810ValidateMode( const DRIDriverContext *ctx ) +{ + unsigned char *I810MMIO = ctx->MMIOAddress; + I810Ptr info = ctx->driverPrivate; + + return 1; +} + + +/** + * \brief Examine mode returned by fbdev. + * + * \param ctx display handle. + * + * \return one on success, or zero on failure. + * + * Restores registers that fbdev has clobbered and returns 1. + * + * \sa i810ValidateMode(). + */ +static int i810PostValidateMode( const DRIDriverContext *ctx ) +{ + unsigned char *I810MMIO = ctx->MMIOAddress; + I810Ptr info = ctx->driverPrivate; + + return 1; +} + + +/** + * \brief Initialize the framebuffer device mode + * + * \param ctx display handle. + * + * \return one on success, or zero on failure. + * + * Fills in \p info with some default values and some information from \p ctx + * and then calls I810ScreenInit() for the screen initialization. + * + * Before exiting clears the framebuffer memory accessing it directly. + */ +static int i810InitFBDev( DRIDriverContext *ctx ) +{ + I810Ptr info = calloc(1, sizeof(*info)); + + { + int dummy = ctx->shared.virtualWidth; + + switch (ctx->bpp / 8) { + case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break; + case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break; + case 3: + case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break; + } + + ctx->shared.virtualWidth = dummy; + } + + ctx->driverPrivate = (void *)info; + + info->Chipset = ctx->chipset; + + if (!I810ScreenInit( ctx, info )) + return 0; + + + return 1; +} + + +/** + * \brief The screen is being closed, so clean up any state and free any + * resources used by the DRI. + * + * \param ctx display handle. + * + * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver + * private data. + */ +static void i810HaltFBDev( DRIDriverContext *ctx ) +{ + drmUnmap( ctx->pSAREA, ctx->shared.SAREASize ); + drmClose(ctx->drmFD); + + if (ctx->driverPrivate) { + free(ctx->driverPrivate); + ctx->driverPrivate = 0; + } +} + + +extern void i810NotifyFocus( int ); + +/** + * \brief Exported driver interface for Mini GLX. + * + * \sa DRIDriverRec. + */ +const struct DRIDriverRec __driDriver = { + i810InitContextModes, + i810ValidateMode, + i810PostValidateMode, + i810InitFBDev, + i810HaltFBDev, + I810EngineShutdown, + I810EngineRestore, +#ifndef _EMBEDDED + 0, +#else + i810NotifyFocus, +#endif +};