--- /dev/null
+/**
+ * \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"
+
+
+/* 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
+};