OSDN Git Service

add initial miniglx files for i915, not integrated yet
authorDave Airlie <airliedfreedesktop.org>
Thu, 30 Mar 2006 04:33:58 +0000 (04:33 +0000)
committerDave Airlie <airliedfreedesktop.org>
Thu, 30 Mar 2006 04:33:58 +0000 (04:33 +0000)
src/mesa/drivers/dri/i915/server/intel.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/server/intel_dri.c [new file with mode: 0644]

diff --git a/src/mesa/drivers/dri/i915/server/intel.h b/src/mesa/drivers/dri/i915/server/intel.h
new file mode 100644 (file)
index 0000000..606db97
--- /dev/null
@@ -0,0 +1,294 @@
+#ifndef _INTEL_H_
+#define _INTEL_H_
+
+#include "xf86drm.h"           /* drm_handle_t, etc */
+
+/* Intel */
+#ifndef PCI_CHIP_I810
+#define PCI_CHIP_I810              0x7121
+#define PCI_CHIP_I810_DC100        0x7123
+#define PCI_CHIP_I810_E            0x7125
+#define PCI_CHIP_I815              0x1132
+#define PCI_CHIP_I810_BRIDGE       0x7120
+#define PCI_CHIP_I810_DC100_BRIDGE 0x7122
+#define PCI_CHIP_I810_E_BRIDGE     0x7124
+#define PCI_CHIP_I815_BRIDGE       0x1130
+#endif
+
+#define PCI_CHIP_845_G                 0x2562
+#define PCI_CHIP_I830_M                        0x3577
+
+#ifndef PCI_CHIP_I855_GM
+#define PCI_CHIP_I855_GM          0x3582
+#define PCI_CHIP_I855_GM_BRIDGE           0x3580
+#endif
+
+#ifndef PCI_CHIP_I865_G
+#define PCI_CHIP_I865_G                   0x2572
+#define PCI_CHIP_I865_G_BRIDGE    0x2570
+#endif
+
+#ifndef PCI_CHIP_I915_G
+#define PCI_CHIP_I915_G                   0x2582
+#define PCI_CHIP_I915_G_BRIDGE    0x2580
+#endif
+
+#ifndef PCI_CHIP_I915_GM
+#define PCI_CHIP_I915_GM          0x2592
+#define PCI_CHIP_I915_GM_BRIDGE           0x2590
+#endif
+
+#ifndef PCI_CHIP_E7221_G
+#define PCI_CHIP_E7221_G          0x258A
+/* Same as I915_G_BRIDGE */
+#define PCI_CHIP_E7221_G_BRIDGE           0x2580
+#endif
+
+#ifndef PCI_CHIP_I945_G
+#define PCI_CHIP_I945_G        0x2772
+#define PCI_CHIP_I945_G_BRIDGE 0x2770
+#endif
+
+#ifndef PCI_CHIP_I945_GM
+#define PCI_CHIP_I945_GM        0x27A2
+#define PCI_CHIP_I945_GM_BRIDGE 0x27A0
+#endif
+
+#define IS_I810(pI810) (pI810->Chipset == PCI_CHIP_I810 ||     \
+                       pI810->Chipset == PCI_CHIP_I810_DC100 || \
+                       pI810->Chipset == PCI_CHIP_I810_E)
+#define IS_I815(pI810) (pI810->Chipset == PCI_CHIP_I815)
+#define IS_I830(pI810) (pI810->Chipset == PCI_CHIP_I830_M)
+#define IS_845G(pI810) (pI810->Chipset == PCI_CHIP_845_G)
+#define IS_I85X(pI810)  (pI810->Chipset == PCI_CHIP_I855_GM)
+#define IS_I852(pI810)  (pI810->Chipset == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME))
+#define IS_I855(pI810)  (pI810->Chipset == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME))
+#define IS_I865G(pI810) (pI810->Chipset == PCI_CHIP_I865_G)
+
+#define IS_I915G(pI810) (pI810->Chipset == PCI_CHIP_I915_G || pI810->Chipset == PCI_CHIP_E7221_G)
+#define IS_I915GM(pI810) (pI810->Chipset == PCI_CHIP_I915_GM)
+#define IS_I945G(pI810) (pI810->Chipset == PCI_CHIP_I945_G)
+#define IS_I945GM(pI810) (pI810->Chipset == PCI_CHIP_I945_GM)
+#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810))
+
+#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810))
+
+#define I830_GMCH_CTRL         0x52
+
+
+#define I830_GMCH_GMS_MASK                     0x70
+#define I830_GMCH_GMS_DISABLED         0x00
+#define I830_GMCH_GMS_LOCAL                    0x10
+#define I830_GMCH_GMS_STOLEN_512       0x20
+#define I830_GMCH_GMS_STOLEN_1024      0x30
+#define I830_GMCH_GMS_STOLEN_8192      0x40
+
+#define I855_GMCH_GMS_MASK                     (0x7 << 4)
+#define I855_GMCH_GMS_DISABLED                 0x00
+#define I855_GMCH_GMS_STOLEN_1M                        (0x1 << 4)
+#define I855_GMCH_GMS_STOLEN_4M                        (0x2 << 4)
+#define I855_GMCH_GMS_STOLEN_8M                        (0x3 << 4)
+#define I855_GMCH_GMS_STOLEN_16M               (0x4 << 4)
+#define I855_GMCH_GMS_STOLEN_32M               (0x5 << 4)
+#define I915G_GMCH_GMS_STOLEN_48M              (0x6 << 4)
+#define I915G_GMCH_GMS_STOLEN_64M              (0x7 << 4)
+
+typedef unsigned char Bool;
+#define TRUE 1
+#define FALSE 0
+
+#define PIPE_NONE      0<<0
+#define PIPE_CRT       1<<0
+#define PIPE_TV                1<<1
+#define PIPE_DFP       1<<2
+#define PIPE_LFP       1<<3
+#define PIPE_CRT2      1<<4
+#define PIPE_TV2       1<<5
+#define PIPE_DFP2      1<<6
+#define PIPE_LFP2      1<<7
+
+typedef struct _I830MemPool *I830MemPoolPtr;
+typedef struct _I830MemRange *I830MemRangePtr;
+typedef struct _I830MemRange {
+   long Start;
+   long End;
+   long Size;
+   unsigned long Physical;
+   unsigned long Offset;               /* Offset of AGP-allocated portion */
+   unsigned long Alignment;
+   drm_handle_t Key;
+   unsigned long Pitch; // add pitch
+   I830MemPoolPtr Pool;
+} I830MemRange;
+
+typedef struct _I830MemPool {
+   I830MemRange Total;
+   I830MemRange Free;
+   I830MemRange Fixed;
+   I830MemRange Allocated;
+} I830MemPool;
+
+typedef struct {
+   int tail_mask;
+   I830MemRange mem;
+   unsigned char *virtual_start;
+   int head;
+   int tail;
+   int space;
+} I830RingBuffer;
+
+typedef struct {
+   unsigned int Fence[8];
+} I830RegRec, *I830RegPtr;
+
+
+typedef struct _I830Rec {
+   unsigned char *MMIOBase;
+   unsigned char *FbBase;
+   int cpp;
+
+   unsigned int bios_version;
+
+   /* These are set in PreInit and never changed. */
+   long FbMapSize;
+   long TotalVideoRam;
+   I830MemRange StolenMemory;          /* pre-allocated memory */
+   long BIOSMemorySize;                        /* min stolen pool size */
+   int BIOSMemSizeLoc;
+
+   /* These change according to what has been allocated. */
+   long FreeMemory;
+   I830MemRange MemoryAperture;
+   I830MemPool StolenPool;
+   long allocatedMemory;
+
+   /* Regions allocated either from the above pools, or from agpgart. */
+   /* for single and dual head configurations */
+   I830MemRange FrontBuffer;
+   I830MemRange FrontBuffer2;
+   I830MemRange Scratch;
+   I830MemRange Scratch2;
+
+   I830RingBuffer *LpRing;
+
+   I830MemRange BackBuffer;
+   I830MemRange DepthBuffer;
+   I830MemRange TexMem;
+   int TexGranularity;
+   I830MemRange ContextMem;
+   int drmMinor;
+   Bool have3DWindows;
+
+   Bool NeedRingBufferLow;
+   Bool allowPageFlip;
+   Bool disableTiling;
+
+   int Chipset;
+   unsigned long LinearAddr;
+   unsigned long MMIOAddr;
+
+   drmSize           registerSize;     /**< \brief MMIO register map size */
+   drm_handle_t         registerHandle;   /**< \brief MMIO register map handle */
+  //   IOADDRESS ioBase;
+   int               irq;              /**< \brief IRQ number */
+   int GttBound;
+
+   drm_handle_t ring_map;
+
+} I830Rec;
+
+/*
+ * 12288 is set as the maximum, chosen because it is enough for
+ * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare.
+ */
+#define I830_MAXIMUM_VBIOS_MEM         12288
+#define I830_DEFAULT_VIDEOMEM_2D       (MB(32) / 1024)
+#define I830_DEFAULT_VIDEOMEM_3D       (MB(64) / 1024)
+
+/* Flags for memory allocation function */
+#define FROM_ANYWHERE                  0x00000000
+#define FROM_POOL_ONLY                 0x00000001
+#define FROM_NEW_ONLY                  0x00000002
+#define FROM_MASK                      0x0000000f
+
+#define ALLOCATE_AT_TOP                        0x00000010
+#define ALLOCATE_AT_BOTTOM             0x00000020
+#define FORCE_GAPS                     0x00000040
+
+#define NEED_PHYSICAL_ADDR             0x00000100
+#define ALIGN_BOTH_ENDS                        0x00000200
+#define FORCE_LOW                      0x00000400
+
+#define ALLOC_NO_TILING                        0x00001000
+#define ALLOC_INITIAL                  0x00002000
+
+#define ALLOCATE_DRY_RUN               0x80000000
+
+/* Chipset registers for VIDEO BIOS memory RW access */
+#define _855_DRAM_RW_CONTROL 0x58
+#define _845_DRAM_RW_CONTROL 0x90
+#define DRAM_WRITE    0x33330000
+
+#define KB(x) ((x) * 1024)
+#define MB(x) ((x) * KB(1024))
+
+#define GTT_PAGE_SIZE                  KB(4)
+#define ROUND_TO(x, y)                 (((x) + (y) - 1) / (y) * (y))
+#define ROUND_DOWN_TO(x, y)            ((x) / (y) * (y))
+#define ROUND_TO_PAGE(x)               ROUND_TO((x), GTT_PAGE_SIZE)
+#define ROUND_TO_MB(x)                 ROUND_TO((x), MB(1))
+#define PRIMARY_RINGBUFFER_SIZE                KB(128)
+
+
+/* Ring buffer registers, p277, overview p19
+ */
+#define LP_RING     0x2030
+#define HP_RING     0x2040
+
+#define RING_TAIL      0x00
+#define TAIL_ADDR           0x000FFFF8
+#define I830_TAIL_MASK     0x001FFFF8
+
+#define RING_HEAD      0x04
+#define HEAD_WRAP_COUNT     0xFFE00000
+#define HEAD_WRAP_ONE       0x00200000
+#define HEAD_ADDR           0x001FFFFC
+#define I830_HEAD_MASK      0x001FFFFC
+
+#define RING_START     0x08
+#define START_ADDR          0x03FFFFF8
+#define I830_RING_START_MASK   0xFFFFF000
+
+#define RING_LEN       0x0C
+#define RING_NR_PAGES       0x001FF000 
+#define I830_RING_NR_PAGES     0x001FF000
+#define RING_REPORT_MASK    0x00000006
+#define RING_REPORT_64K     0x00000002
+#define RING_REPORT_128K    0x00000004
+#define RING_NO_REPORT      0x00000000
+#define RING_VALID_MASK     0x00000001
+#define RING_VALID          0x00000001
+#define RING_INVALID        0x00000000
+
+
+#include <mmio.h>
+
+#  define MMIO_IN8(base, offset) \
+       *(volatile unsigned char *)(((unsigned char*)(base)) + (offset))
+#  define MMIO_IN32(base, offset) \
+       read_MMIO_LE32(base, offset)
+#  define MMIO_OUT8(base, offset, val) \
+       *(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) = (val)
+#  define MMIO_OUT32(base, offset, val) \
+       *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) = CPU_TO_LE32(val)
+
+
+                               /* Memory mapped register access macros */
+#define INREG8(addr)        MMIO_IN8(MMIO, addr)
+#define INREG(addr)         MMIO_IN32(MMIO, addr)
+#define OUTREG8(addr, val)  MMIO_OUT8(MMIO, addr, val)
+#define OUTREG(addr, val)   MMIO_OUT32(MMIO, addr, val)
+
+#define DSPABASE               0x70184
+
+#endif
diff --git a/src/mesa/drivers/dri/i915/server/intel_dri.c b/src/mesa/drivers/dri/i915/server/intel_dri.c
new file mode 100644 (file)
index 0000000..6e32cb4
--- /dev/null
@@ -0,0 +1,957 @@
+/**
+ * \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;
+#define xf86DrvMsg(...) do {} while(0)
+
+static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea);
+
+static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  struct pci_device host_bridge;
+  uint32_t gmch_ctrl;
+  int memsize = 0;
+  int range;
+
+  memset(&host_bridge, 0, sizeof(host_bridge));
+
+  pci_device_cfg_read_u32(&host_bridge, &gmch_ctrl, I830_GMCH_CTRL);
+  
+  /* 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;
+}
+
+static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, long size, unsigned long alignment, I830MemRange  *result)
+{
+   unsigned long start, end;
+   unsigned long newApStart, newApEnd;
+   int ret;
+   if (!result || !size)
+      return 0;
+   
+   if (!alignment)
+     alignment = 4;
+
+   start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
+   end = ROUND_TO(start + size, alignment);
+   newApStart = end;
+   newApEnd = pI830->MemoryAperture.End;
+
+   ret=drmAgpAlloc(ctx->drmFD, size, 0, &(result->Physical), (drm_handle_t *)&(result->Key));
+   
+   if (ret)
+   {
+     fprintf(stderr,"drmAgpAlloc failed %d\n", ret);
+     return 0;
+   }
+   pI830->allocatedMemory += size;
+   pI830->MemoryAperture.Start = newApStart;
+   pI830->MemoryAperture.End = newApEnd;
+   pI830->MemoryAperture.Size = newApEnd - newApStart;
+   pI830->FreeMemory -= size;
+   result->Start = start;
+   result->End = start + size;
+   result->Size = size;
+   result->Offset = start;
+   result->Alignment = alignment;
+   result->Pool = NULL;
+  
+   return size;
+}
+
+static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem)
+{
+  if (!mem)
+    return FALSE;
+  
+  if (mem->Key == -1)
+    return TRUE;
+
+  return drmAgpBind(ctx->drmFD, mem->Key, mem->Offset);
+}
+
+/* simple memory allocation routines needed */
+/* put ring buffer in low memory */
+/* need to allocate front, back, depth buffers aligned correctly,
+   allocate ring buffer, 
+*/
+
+/* */
+static Bool
+I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  unsigned long size, ret;
+  unsigned long lines, lineSize, align;
+
+  /* allocate ring buffer */
+  memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
+  pI830->LpRing->mem.Key = -1;
+
+  size = PRIMARY_RINGBUFFER_SIZE;
+  
+  ret = AllocFromAGP(ctx, pI830, size, 0x1000, &pI830->LpRing->mem);
+  
+  if (ret != size)
+  {
+    fprintf(stderr,"unable to allocate ring buffer %ld\n", ret);
+    return FALSE;
+  }
+
+  pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
+
+  
+  /* allocate front buffer */
+  memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
+  pI830->FrontBuffer.Key = -1;
+  pI830->FrontBuffer.Pitch = ctx->shared.virtualWidth;
+
+  align = KB(512);  
+
+  lineSize = ctx->shared.virtualWidth * ctx->cpp;
+  lines = (ctx->shared.virtualHeight + 15) / 16 * 16;
+  size = lineSize * lines;
+  size = ROUND_TO_PAGE(size);
+
+  ret = AllocFromAGP(ctx, pI830, size, align, &pI830->FrontBuffer);
+  if (ret != size)
+  {
+    fprintf(stderr,"unable to allocate front buffer %ld\n", ret);
+    return FALSE;
+  }
+
+  memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
+  pI830->BackBuffer.Key = -1;
+  pI830->BackBuffer.Pitch = ctx->shared.virtualWidth;
+
+  ret = AllocFromAGP(ctx, pI830, size, align, &pI830->BackBuffer);
+  if (ret != size)
+  {
+    fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
+    return FALSE;
+  }
+  
+  memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
+  pI830->DepthBuffer.Key = -1;
+  pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth;
+
+  ret = AllocFromAGP(ctx, pI830, size, align, &pI830->DepthBuffer);
+  if (ret != size)
+  {
+    fprintf(stderr,"unable to allocate depth buffer %ld\n", ret);
+    return FALSE;
+  }
+
+  memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
+  pI830->ContextMem.Key = -1;
+  size = KB(32);
+
+  ret = AllocFromAGP(ctx, pI830, size, align, &pI830->ContextMem);
+  if (ret != size)
+  {
+    fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
+    return FALSE;
+  }
+  
+  memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
+  pI830->TexMem.Key = -1;
+
+  size = 32768 * 1024;
+  ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem);
+  if (ret != size)
+  {
+    fprintf(stderr,"unable to allocate texture memory %ld\n", ret);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static Bool
+I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  if (BindAgpRange(ctx, &pI830->LpRing->mem))
+    return FALSE;
+  if (BindAgpRange(ctx, &pI830->FrontBuffer))
+    return FALSE;
+  if (BindAgpRange(ctx, &pI830->BackBuffer))
+    return FALSE;
+  if (BindAgpRange(ctx, &pI830->DepthBuffer))
+    return FALSE;
+  if (BindAgpRange(ctx, &pI830->ContextMem))
+    return FALSE;
+  if (BindAgpRange(ctx, &pI830->TexMem))
+    return FALSE;
+
+  return TRUE;
+}
+
+static Bool
+I830CleanupDma(const DRIDriverContext *ctx)
+{
+   drmI830Init info;
+
+   memset(&info, 0, sizeof(drmI830Init));
+   info.func = I830_CLEANUP_DMA;
+
+   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
+                      &info, sizeof(drmI830Init))) {
+     xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Dma Cleanup Failed\n");
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+static Bool
+I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+   I830RingBuffer *ring = pI830->LpRing;
+   drmI830Init info;
+
+   memset(&info, 0, sizeof(drmI830Init));
+   info.func = I830_INIT_DMA;
+
+   info.ring_start = ring->mem.Start + pI830->LinearAddr;
+   info.ring_end = ring->mem.End + pI830->LinearAddr;
+   info.ring_size = ring->mem.Size;
+
+   info.mmio_offset = (unsigned int)ctx->MMIOStart;
+
+   info.sarea_priv_offset = sizeof(drm_sarea_t);
+
+   info.front_offset = pI830->FrontBuffer.Start;
+   info.back_offset = pI830->BackBuffer.Start;
+   info.depth_offset = pI830->DepthBuffer.Start;
+   info.w = ctx->shared.virtualWidth;
+   info.h = ctx->shared.virtualHeight;
+   info.pitch = ctx->shared.virtualWidth;
+   info.back_pitch = pI830->BackBuffer.Pitch;
+   info.depth_pitch = pI830->DepthBuffer.Pitch;
+   info.cpp = pI830->cpp;
+
+   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
+                      &info, sizeof(drmI830Init))) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                "I830 Dma Initialization Failed\n");
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+static int I830CheckDRMVersion( const DRIDriverContext *ctx,
+                                 I830Rec *pI830 )
+{
+   drmVersionPtr  version;
+
+   version = drmGetVersion(ctx->drmFD);
+
+   if (version) {
+     int req_minor, req_patch;
+
+     req_minor = 4;
+     req_patch = 0;    
+
+     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] I830DRIScreenInit failed because of a version "
+              "mismatch.\n"
+              "[dri] i915.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;
+     }
+     
+     pI830->drmMinor = version->version_minor;
+     drmFreeVersion(version);
+   }
+   return 1;
+}
+
+static void
+I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  unsigned int itemp;
+  unsigned char *MMIO = ctx->MMIOAddress;
+
+   OUTREG(LP_RING + RING_LEN, 0);
+   OUTREG(LP_RING + RING_TAIL, 0);
+   OUTREG(LP_RING + RING_HEAD, 0);
+
+   if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
+       pI830->LpRing->mem.Start) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                "I830SetRingRegs: Ring buffer start (%lx) violates its "
+                "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
+   }
+   /* Don't care about the old value.  Reserved bits must be zero anyway. */
+   itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
+   OUTREG(LP_RING + RING_START, itemp);
+
+   if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
+       pI830->LpRing->mem.Size - 4096) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
+                "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
+                I830_RING_NR_PAGES);
+   }
+   /* Don't care about the old value.  Reserved bits must be zero anyway. */
+   itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
+   itemp |= (RING_NO_REPORT | RING_VALID);
+   OUTREG(LP_RING + RING_LEN, itemp);
+
+   pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
+   pI830->LpRing->tail = INREG(LP_RING + RING_TAIL);
+   pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
+   if (pI830->LpRing->space < 0)
+      pI830->LpRing->space += pI830->LpRing->mem.Size;
+   
+   /* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky
+      hacky hacky */
+   OUTREG(DSPABASE, pI830->FrontBuffer.Start + pI830->LinearAddr);
+
+}
+
+static Bool
+I830SetParam(const DRIDriverContext *ctx, int param, int value)
+{
+   drmI830SetParam sp;
+
+   memset(&sp, 0, sizeof(sp));
+   sp.param = param;
+   sp.value = value;
+
+   if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 SetParam Failed\n");
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+static Bool
+I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+   fprintf(stderr,
+              "[drm] Mapping front buffer\n");
+
+   if (drmAddMap(ctx->drmFD,
+                 (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
+                 sarea->front_size,
+                 DRM_FRAME_BUFFER,  /*DRM_AGP,*/
+                 0,
+                 &sarea->front_handle) < 0) {
+     fprintf(stderr,
+            "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
+      return FALSE;
+   }
+   ctx->shared.hFrameBuffer = sarea->front_handle;
+   ctx->shared.fbSize = sarea->front_size;
+   fprintf(stderr, "[drm] Front Buffer = 0x%08x\n",
+          sarea->front_handle);
+
+   if (drmAddMap(ctx->drmFD,
+                 (drm_handle_t)(sarea->back_offset),
+                 sarea->back_size, DRM_AGP, 0,
+                 &sarea->back_handle) < 0) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                 "[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
+      return FALSE;
+   }
+   fprintf(stderr, "[drm] Back Buffer = 0x%08x\n",
+              sarea->back_handle);
+
+   if (drmAddMap(ctx->drmFD,
+                 (drm_handle_t)sarea->depth_offset,
+                 sarea->depth_size, DRM_AGP, 0,
+                 &sarea->depth_handle) < 0) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                 "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
+      return FALSE;
+   }
+   fprintf(stderr, "[drm] Depth Buffer = 0x%08x\n",
+              sarea->depth_handle);
+
+   if (drmAddMap(ctx->drmFD,
+                (drm_handle_t)sarea->tex_offset,
+                sarea->tex_size, DRM_AGP, 0,
+                &sarea->tex_handle) < 0) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
+      return FALSE;
+   }
+   fprintf(stderr, "[drm] textures = 0x%08x\n",
+             sarea->tex_handle);
+
+   return TRUE;
+}
+
+
+static void
+I830DRIUnmapScreenRegions(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+#if 1
+   if (sarea->front_handle) {
+      drmRmMap(ctx->drmFD, sarea->front_handle);
+      sarea->front_handle = 0;
+   }
+#endif
+   if (sarea->back_handle) {
+      drmRmMap(ctx->drmFD, sarea->back_handle);
+      sarea->back_handle = 0;
+   }
+   if (sarea->depth_handle) {
+      drmRmMap(ctx->drmFD, sarea->depth_handle);
+      sarea->depth_handle = 0;
+   }
+   if (sarea->tex_handle) {
+      drmRmMap(ctx->drmFD, sarea->tex_handle);
+      sarea->tex_handle = 0;
+   }
+}
+
+static void
+I830InitTextureHeap(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+   /* Start up the simple memory manager for agp space */
+   drmI830MemInitHeap drmHeap;
+   drmHeap.region = I830_MEM_REGION_AGP;
+   drmHeap.start  = 0;
+   drmHeap.size   = sarea->tex_size;
+      
+   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT_HEAP,
+                         &drmHeap, sizeof(drmHeap))) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                   "[drm] Failed to initialized agp heap manager\n");
+   } else {
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+                   "[drm] Initialized kernel agp heap manager, %d\n",
+                   sarea->tex_size);
+
+      I830SetParam(ctx, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, 
+                     sarea->log_tex_granularity);
+   }
+}
+
+static Bool
+I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+  if (drmAddMap(ctx->drmFD,
+               (drm_handle_t)pI830->LpRing->mem.Start,
+               pI830->LpRing->mem.Size, DRM_AGP, 0,
+               &pI830->ring_map) < 0) {
+    fprintf(stderr,
+           "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
+    return FALSE;
+  }
+  fprintf(stderr, "[drm] ring buffer = 0x%08x\n",
+         pI830->ring_map);
+
+  if (I830InitDma(ctx, pI830) == FALSE) {
+    return FALSE;
+  }
+  
+   /* init to zero to be safe */
+
+  I830DRIMapScreenRegions(ctx, pI830, sarea);
+  I830InitTextureHeap(ctx, pI830, sarea);
+
+   if (ctx->pciDevice != PCI_CHIP_845_G &&
+       ctx->pciDevice != PCI_CHIP_I830_M) {
+      I830SetParam(ctx, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 );
+   }
+
+   /* Okay now initialize the dma engine */
+   {
+      pI830->irq = drmGetInterruptFromBusID(ctx->drmFD,
+                                           ctx->pciBus,
+                                           ctx->pciDevice,
+                                           ctx->pciFunc);
+
+      if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                   "[drm] failure adding irq handler\n");
+        pI830->irq = 0;
+        return FALSE;
+      }
+      else
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+                   "[drm] dma control initialized, using IRQ %d\n",
+                   pI830DRI->irq);
+   }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n");
+
+   return TRUE;
+}
+
+static Bool
+I830ClearScreen(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+  /* need to drmMap front and back buffers and zero them */
+  drmAddressPtr map_addr;
+  int ret;
+
+  ret = drmMap(ctx->drmFD,
+              sarea->front_handle,
+              sarea->front_size,
+              map_addr);
+
+  if (ret)
+  {
+    fprintf(stderr, "Unable to map front buffer\n");
+    return FALSE;
+  }
+
+  drimemsetio((char *)map_addr,
+             0,
+             sarea->front_size);
+  drmUnmap(map_addr, sarea->front_size);
+
+
+  ret = drmMap(ctx->drmFD,
+              sarea->back_handle,
+              sarea->back_size,
+              map_addr);
+
+  if (ret)
+  {
+    fprintf(stderr, "Unable to map back buffer\n");
+    return FALSE;
+  }
+
+  drimemsetio((char *)map_addr,
+             0,
+             sarea->back_size);
+  drmUnmap(map_addr, sarea->back_size);
+
+  return TRUE;
+}
+
+static Bool
+I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
+                 
+{
+   I830DRIPtr pI830DRI;
+   drmI830Sarea *pSAREAPriv;
+   int err;
+
+      
+   drm_page_size = getpagesize();   
+
+   pI830->registerSize = ctx->MMIOSize;
+   /* This is a hack for now.  We have to have more than a 4k page here
+    * because of the size of the state.  However, the state should be
+    * in a per-context mapping.  This will be added in the Mesa 3.5 port
+    * of the I830 driver.
+    */
+   ctx->shared.SAREASize = SAREA_MAX;
+
+  /* Note that drmOpen will try to load the kernel module, if needed. */
+   ctx->drmFD = drmOpen("i915", 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%08x\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%08x 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, 
+                &pI830->registerHandle) < 0) {
+      fprintf(stderr, "[drm] drmAddMap mmio failed\n");        
+      return 0;
+   }
+   fprintf(stderr,
+          "[drm] register handle = 0x%08x\n", pI830->registerHandle);
+
+
+   if (!I830CheckDRMVersion(ctx, pI830)) {
+     return FALSE;
+   }
+
+   /* 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 SAREA private data structure */
+   pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + 
+                                sizeof(drm_sarea_t));
+   memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
+
+   pI830->StolenMemory.Size = I830DetectMemory(ctx, pI830);
+   pI830->StolenMemory.Start = 0;
+   pI830->StolenMemory.End = pI830->StolenMemory.Size;
+
+   pI830->MemoryAperture.Start = pI830->StolenMemory.End;
+   pI830->MemoryAperture.End = KB(40000);
+   pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
+
+   if (!AgpInit(ctx, pI830))
+     return FALSE;
+
+   if (I830AllocateMemory(ctx, pI830) == FALSE)
+   {
+     return FALSE;
+   }
+
+   if (I830BindMemory(ctx, pI830) == FALSE)
+   {
+     return FALSE;
+   }
+
+   pSAREAPriv->front_offset = pI830->FrontBuffer.Start;
+   pSAREAPriv->front_size = pI830->FrontBuffer.Size;
+   pSAREAPriv->width = ctx->shared.virtualWidth;
+   pSAREAPriv->height = ctx->shared.virtualHeight;
+   pSAREAPriv->pitch = ctx->shared.virtualWidth;
+   pSAREAPriv->virtualX = ctx->shared.virtualWidth;
+   pSAREAPriv->virtualY = ctx->shared.virtualHeight;
+   pSAREAPriv->back_offset = pI830->BackBuffer.Start;
+   pSAREAPriv->back_size = pI830->BackBuffer.Size;
+   pSAREAPriv->depth_offset = pI830->DepthBuffer.Start;
+   pSAREAPriv->depth_size = pI830->DepthBuffer.Size;
+   pSAREAPriv->tex_offset = pI830->TexMem.Start;
+   pSAREAPriv->tex_size = pI830->TexMem.Size;
+   pSAREAPriv->log_tex_granularity = pI830->TexGranularity;
+
+   ctx->driverClientMsg = malloc(sizeof(I830DRIRec));
+   ctx->driverClientMsgSize = sizeof(I830DRIRec);
+   pI830DRI = (I830DRIPtr)ctx->driverClientMsg;
+   pI830DRI->deviceID = pI830->Chipset;
+   pI830DRI->regsSize = I830_REG_SIZE;
+   pI830DRI->width = ctx->shared.virtualWidth;
+   pI830DRI->height = ctx->shared.virtualHeight;
+   pI830DRI->mem = ctx->shared.fbSize;
+   pI830DRI->cpp = ctx->cpp;
+   pI830DRI->backOffset = pI830->BackBuffer.Start;
+   pI830DRI->backPitch = pI830->BackBuffer.Pitch; 
+
+   pI830DRI->depthOffset = pI830->DepthBuffer.Start;
+   pI830DRI->depthPitch = pI830->DepthBuffer.Pitch; 
+
+   pI830DRI->fbOffset = pI830->FrontBuffer.Start;
+   pI830DRI->fbStride = pI830->FrontBuffer.Pitch;
+
+   pI830DRI->bitsPerPixel = ctx->bpp;
+   pI830DRI->sarea_priv_offset = sizeof(drm_sarea_t);
+   
+   err = I830DRIDoMappings(ctx, pI830, pSAREAPriv);
+   if (err == FALSE)
+       return FALSE;
+
+   I830SetRingRegs(ctx, pI830);
+
+   /* 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.
+    */
+   I830ClearScreen(ctx, pI830, pSAREAPriv);
+
+   return TRUE;
+}
+
+
+/**
+ * \brief Validate the fbdev mode.
+ * 
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Saves some registers and returns 1.
+ *
+ * \sa radeonValidateMode().
+ */
+static int i830ValidateMode( const DRIDriverContext *ctx )
+{
+  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 i830PostValidateMode( const DRIDriverContext *ctx )
+{
+  I830Rec *pI830 = ctx->driverPrivate;
+
+  I830SetRingRegs(ctx, pI830);
+  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 i830InitFBDev( DRIDriverContext *ctx )
+{
+  I830Rec *pI830 = calloc(1, sizeof(I830Rec));
+
+   {
+      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 *)pI830;
+   
+   pI830->LpRing = calloc(1, sizeof(I830RingBuffer));
+   pI830->Chipset = ctx->chipset;
+   pI830->LinearAddr = ctx->FBStart;
+
+   if (!I830ScreenInit( ctx, pI830 ))
+      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 i830HaltFBDev( DRIDriverContext *ctx )
+{
+  drmI830Sarea *pSAREAPriv;
+  I830Rec *pI830 = ctx->driverPrivate;
+
+   if (pI830->irq) {
+       drmCtlUninstHandler(ctx->drmFD);
+       pI830->irq = 0;   }
+
+   I830CleanupDma(ctx);
+
+  pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + 
+                               sizeof(drm_sarea_t));
+
+  I830DRIUnmapScreenRegions(ctx, pI830, pSAREAPriv);
+  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 = {
+   i830ValidateMode,
+   i830PostValidateMode,
+   i830InitFBDev,
+   i830HaltFBDev,
+   NULL,//I830EngineShutdown,
+   NULL, //I830EngineRestore,  
+#ifndef _EMBEDDED
+   0,
+#else
+   i810NotifyFocus, 
+#endif
+};