103b705cfSriastradh#ifdef HAVE_CONFIG_H
203b705cfSriastradh#include "config.h"
303b705cfSriastradh#endif
403b705cfSriastradh
503b705cfSriastradh#include <errno.h>
603b705cfSriastradh#include <stdio.h>
703b705cfSriastradh#include <string.h>
803b705cfSriastradh#include <assert.h>
903b705cfSriastradh
109a906b70Schristos#include "xorg-server.h"
1103b705cfSriastradh#include "xf86.h"
1203b705cfSriastradh#include "xf86_OSproc.h"
1303b705cfSriastradh
1403b705cfSriastradh#include "xf86Pci.h"
1503b705cfSriastradh
1603b705cfSriastradh#include "windowstr.h"
1703b705cfSriastradh#include "shadow.h"
1803b705cfSriastradh#include "shadowfb.h"
1903b705cfSriastradh
2003b705cfSriastradh#include "i810.h"
2103b705cfSriastradh#include "i810_dri.h"
2203b705cfSriastradh
2303b705cfSriastradhstatic char I810KernelDriverName[] = "i810";
2403b705cfSriastradhstatic char I810ClientDriverName[] = "i810";
2503b705cfSriastradh
2603b705cfSriastradhstatic Bool I810CreateContext(ScreenPtr pScreen, VisualPtr visual,
2703b705cfSriastradh			      drm_context_t hwContext, void *pVisualConfigPriv,
2803b705cfSriastradh			      DRIContextType contextStore);
2903b705cfSriastradhstatic void I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
3003b705cfSriastradh			       DRIContextType contextStore);
3103b705cfSriastradhstatic void I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
3203b705cfSriastradh			       DRIContextType readContextType,
3303b705cfSriastradh			       void *readContextStore,
3403b705cfSriastradh			       DRIContextType writeContextType,
3503b705cfSriastradh			       void *writeContextStore);
3603b705cfSriastradhstatic void I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
3703b705cfSriastradhstatic void I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
3803b705cfSriastradh			       RegionPtr prgnSrc, CARD32 index);
3903b705cfSriastradh
4003b705cfSriastradh
4103b705cfSriastradhstatic void I810EnablePageFlip(ScreenPtr pScreen);
4203b705cfSriastradhstatic void I810DisablePageFlip(ScreenPtr pScreen);
4303b705cfSriastradhstatic void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen);
4403b705cfSriastradhstatic void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen);
4503b705cfSriastradhstatic void I810DRITransitionTo3d(ScreenPtr pScreen);
4603b705cfSriastradhstatic void I810DRITransitionTo2d(ScreenPtr pScreen);
4703b705cfSriastradh
4803b705cfSriastradhstatic void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
4903b705cfSriastradh
5003b705cfSriastradhstatic int i810_pitches[] = {
5103b705cfSriastradh   512,
5203b705cfSriastradh   1024,
5303b705cfSriastradh   2048,
5403b705cfSriastradh   4096,
5503b705cfSriastradh   0
5603b705cfSriastradh};
5703b705cfSriastradh
5803b705cfSriastradhstatic int i810_pitch_flags[] = {
5903b705cfSriastradh   0x0,
6003b705cfSriastradh   0x1,
6103b705cfSriastradh   0x2,
6203b705cfSriastradh   0x3,
6303b705cfSriastradh   0
6403b705cfSriastradh};
6503b705cfSriastradh
6603b705cfSriastradhstatic unsigned int i810_drm_version = 0;
6703b705cfSriastradh
6803b705cfSriastradhBool
6903b705cfSriastradhI810CleanupDma(ScrnInfoPtr pScrn)
7003b705cfSriastradh{
7103b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
7203b705cfSriastradh   drmI810Init info;
7303b705cfSriastradh
7403b705cfSriastradh   memset(&info, 0, sizeof(drmI810Init));
7503b705cfSriastradh   info.func = I810_CLEANUP_DMA;
7603b705cfSriastradh
7703b705cfSriastradh   if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
7803b705cfSriastradh		       &info, sizeof(drmI810Init))) {
7903b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
8003b705cfSriastradh		 "[dri] I810 Dma Cleanup Failed\n");
8103b705cfSriastradh      return FALSE;
8203b705cfSriastradh   }
8303b705cfSriastradh
8403b705cfSriastradh   return TRUE;
8503b705cfSriastradh}
8603b705cfSriastradh
8703b705cfSriastradhBool
8803b705cfSriastradhI810InitDma(ScrnInfoPtr pScrn)
8903b705cfSriastradh{
9003b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
9103b705cfSriastradh   I810RingBuffer *ring = pI810->LpRing;
9203b705cfSriastradh   I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
9303b705cfSriastradh   drmI810Init info;
9403b705cfSriastradh
9503b705cfSriastradh   memset(&info, 0, sizeof(drmI810Init));
9603b705cfSriastradh
9703b705cfSriastradh   info.ring_start = ring->mem.Start;
9803b705cfSriastradh   info.ring_end = ring->mem.End;
9903b705cfSriastradh   info.ring_size = ring->mem.Size;
10003b705cfSriastradh   info.mmio_offset = (unsigned int)pI810DRI->regs;
10103b705cfSriastradh   info.buffers_offset = (unsigned int)pI810->buffer_map;
10203b705cfSriastradh   info.sarea_priv_offset = sizeof(XF86DRISAREARec);
10303b705cfSriastradh
10403b705cfSriastradh   info.front_offset = 0;
10503b705cfSriastradh   info.back_offset = pI810->BackBuffer.Start;
10603b705cfSriastradh   info.depth_offset = pI810->DepthBuffer.Start;
10703b705cfSriastradh   info.overlay_offset = pI810->OverlayStart;
10803b705cfSriastradh   info.overlay_physical = pI810->OverlayPhysical;
10903b705cfSriastradh   info.w = pScrn->virtualX;
11003b705cfSriastradh   info.h = pScrn->virtualY;
11103b705cfSriastradh   info.pitch = pI810->auxPitch;
11203b705cfSriastradh   info.pitch_bits = pI810->auxPitchBits;
11303b705cfSriastradh
11403b705cfSriastradh   /* We require DRM v1.2 or greater. Since DRM v1.2 broke compatibility
11503b705cfSriastradh    * we created a new v1.4 that supports a new init function. Eventually the
11603b705cfSriastradh    * old init function will go away. If you change the drm interface, make a
11703b705cfSriastradh    * new init type too so that we can detect the new client.
11803b705cfSriastradh    */
11903b705cfSriastradh   switch(i810_drm_version) {
12003b705cfSriastradh   case ((1<<16) | 0):
12103b705cfSriastradh   case ((1<<16) | 1):
12203b705cfSriastradh   case ((1<<16) | 2):
12303b705cfSriastradh   case ((1<<16) | 3):
12403b705cfSriastradh      /* Use OLD drm < 1.4 init */
12503b705cfSriastradh      info.func = I810_INIT_DMA;
12603b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init PRE v1.4 interface.\n");
12703b705cfSriastradh      break;
12803b705cfSriastradh   default:
12903b705cfSriastradh   case ((1<<16) | 4):
13003b705cfSriastradh      /*  DRM version 1.3 or greater init */
13103b705cfSriastradh      info.func = I810_INIT_DMA_1_4;
13203b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init v1.4 interface.\n");
13303b705cfSriastradh      break;
13403b705cfSriastradh   }
13503b705cfSriastradh
13603b705cfSriastradh   if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT,
13703b705cfSriastradh		       &info, sizeof(drmI810Init))) {
13803b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
13903b705cfSriastradh		 "[drm] I810 Dma Initialization failed.\n");
14003b705cfSriastradh      return FALSE;
14103b705cfSriastradh   }
14203b705cfSriastradh
14303b705cfSriastradh   return TRUE;
14403b705cfSriastradh}
14503b705cfSriastradh
14603b705cfSriastradhstatic unsigned int
14703b705cfSriastradhmylog2(unsigned int n)
14803b705cfSriastradh{
14903b705cfSriastradh   unsigned int log2 = 1;
15003b705cfSriastradh
15103b705cfSriastradh   while (n > 1)
15203b705cfSriastradh      n >>= 1, log2++;
15303b705cfSriastradh   return log2;
15403b705cfSriastradh}
15503b705cfSriastradh
15603b705cfSriastradhBool
15703b705cfSriastradhI810DRIScreenInit(ScreenPtr pScreen)
15803b705cfSriastradh{
15903b705cfSriastradh   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
16003b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
16103b705cfSriastradh   DRIInfoPtr pDRIInfo;
16203b705cfSriastradh   I810DRIPtr pI810DRI;
16303b705cfSriastradh   unsigned long tom;
16403b705cfSriastradh   drm_handle_t agpHandle;
16503b705cfSriastradh   drm_handle_t dcacheHandle;
16603b705cfSriastradh   int sysmem_size = 0;
16703b705cfSriastradh   int back_size = 0;
16803b705cfSriastradh   unsigned int pitch_idx = 0;
16903b705cfSriastradh   int bufs;
17003b705cfSriastradh   int width = pScrn->displayWidth * pI810->cpp;
17103b705cfSriastradh   int i;
17203b705cfSriastradh
17303b705cfSriastradh   /* Hardware 3D rendering only implemented for 16bpp */
17403b705cfSriastradh   /* And it only works for 5:6:5 (Mark) */
17503b705cfSriastradh   if (pScrn->depth != 16)
17603b705cfSriastradh      return FALSE;
17703b705cfSriastradh
17803b705cfSriastradh   /* Check that the DRI, and DRM modules have been loaded by testing
17903b705cfSriastradh    * for known symbols in each module. */
18003b705cfSriastradh   if (!xf86LoaderCheckSymbol("drmAvailable"))
18103b705cfSriastradh      return FALSE;
18203b705cfSriastradh   if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
18303b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
18403b705cfSriastradh		 "[dri] I810DRIScreenInit failed (libdri.a too old)\n");
18503b705cfSriastradh      return FALSE;
18603b705cfSriastradh   }
18703b705cfSriastradh
18803b705cfSriastradh   /* adjust width first */
18903b705cfSriastradh#define Elements(x) sizeof(x)/sizeof(*x)
19003b705cfSriastradh   for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++)
19103b705cfSriastradh      if (width <= i810_pitches[pitch_idx])
19203b705cfSriastradh	 break;
19303b705cfSriastradh
19403b705cfSriastradh   if (pitch_idx == Elements(i810_pitches)) {
19503b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
19603b705cfSriastradh		 "[dri] Couldn't find depth/back buffer pitch");
19703b705cfSriastradh      DRICloseScreen(pScreen);
19803b705cfSriastradh      return FALSE;
19903b705cfSriastradh   } else {
20003b705cfSriastradh      /* for tiled memory to work, the buffer needs to have the
20103b705cfSriastradh       * number of lines as a multiple of 16 (the tile size),
20203b705cfSriastradh       *  - airlied */
20303b705cfSriastradh      int lines = (pScrn->virtualY + 15) / 16 * 16;
20403b705cfSriastradh      back_size = i810_pitches[pitch_idx] * lines;
20503b705cfSriastradh      back_size = ((back_size + 4096 - 1) / 4096) * 4096;
20603b705cfSriastradh   }
20703b705cfSriastradh
20803b705cfSriastradh   pScrn->displayWidth = i810_pitches[pitch_idx] / pI810->cpp;
20903b705cfSriastradh
21003b705cfSriastradh   /* Check the DRI version */
21103b705cfSriastradh   {
21203b705cfSriastradh      int major, minor, patch;
21303b705cfSriastradh
21403b705cfSriastradh      DRIQueryVersion(&major, &minor, &patch);
21503b705cfSriastradh      if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
21603b705cfSriastradh	 xf86DrvMsg(pScreen->myNum, X_ERROR,
21703b705cfSriastradh		    "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
21803b705cfSriastradh		    "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n"
21903b705cfSriastradh		    "[dri] Disabling DRI.\n", major, minor, patch,
22003b705cfSriastradh                    DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
22103b705cfSriastradh	 return FALSE;
22203b705cfSriastradh      }
22303b705cfSriastradh   }
22403b705cfSriastradh
22503b705cfSriastradh   pDRIInfo = DRICreateInfoRec();
22603b705cfSriastradh   if (!pDRIInfo) {
22703b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
22803b705cfSriastradh		 "[dri] DRICreateInfoRec failed.  Disabling DRI.\n");
22903b705cfSriastradh      return FALSE;
23003b705cfSriastradh   }
23103b705cfSriastradh
23203b705cfSriastradh/*     pDRIInfo->wrap.ValidateTree = 0;    */
23303b705cfSriastradh/*     pDRIInfo->wrap.PostValidateTree = 0;    */
23403b705cfSriastradh
23503b705cfSriastradh   pI810->pDRIInfo = pDRIInfo;
23603b705cfSriastradh   pI810->LockHeld = 0;
23703b705cfSriastradh
23803b705cfSriastradh   pDRIInfo->drmDriverName = I810KernelDriverName;
23903b705cfSriastradh   pDRIInfo->clientDriverName = I810ClientDriverName;
24003b705cfSriastradh   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
24103b705cfSriastradh      pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo);
24203b705cfSriastradh   } else {
24303b705cfSriastradh      pDRIInfo->busIdString = malloc(64);
24403b705cfSriastradh      if (pDRIInfo->busIdString)
24503b705cfSriastradh	 sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
24603b705cfSriastradh		 ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus),
24703b705cfSriastradh		 pI810->PciInfo->dev, pI810->PciInfo->func
24803b705cfSriastradh		);
24903b705cfSriastradh   }
25003b705cfSriastradh   if (!pDRIInfo->busIdString) {
25103b705cfSriastradh      DRIDestroyInfoRec(pI810->pDRIInfo);
25203b705cfSriastradh      pI810->pDRIInfo = NULL;
25303b705cfSriastradh      return FALSE;
25403b705cfSriastradh   }
25503b705cfSriastradh   pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION;
25603b705cfSriastradh   pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION;
25703b705cfSriastradh   pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL;
25803b705cfSriastradh   pDRIInfo->frameBufferPhysicalAddress = (pointer) pI810->LinearAddr;
25903b705cfSriastradh   pDRIInfo->frameBufferSize = (((pScrn->displayWidth *
26003b705cfSriastradh				  pScrn->virtualY * pI810->cpp) +
26103b705cfSriastradh				 4096 - 1) / 4096) * 4096;
26203b705cfSriastradh
26303b705cfSriastradh   pDRIInfo->frameBufferStride = pScrn->displayWidth * pI810->cpp;
26403b705cfSriastradh   pDRIInfo->ddxDrawableTableEntry = I810_MAX_DRAWABLES;
26503b705cfSriastradh
26603b705cfSriastradh   if (SAREA_MAX_DRAWABLES < I810_MAX_DRAWABLES)
26703b705cfSriastradh      pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
26803b705cfSriastradh   else
26903b705cfSriastradh      pDRIInfo->maxDrawableTableEntry = I810_MAX_DRAWABLES;
27003b705cfSriastradh
27103b705cfSriastradh   /* For now the mapping works by using a fixed size defined
27203b705cfSriastradh    * in the SAREA header
27303b705cfSriastradh    */
27403b705cfSriastradh   if (sizeof(XF86DRISAREARec) + sizeof(I810SAREARec) > SAREA_MAX) {
27503b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
27603b705cfSriastradh		 "[dri] Data does not fit in SAREA\n");
27703b705cfSriastradh      return FALSE;
27803b705cfSriastradh   }
27903b705cfSriastradh   pDRIInfo->SAREASize = SAREA_MAX;
28003b705cfSriastradh
28103b705cfSriastradh   if (!(pI810DRI = (I810DRIPtr) calloc(sizeof(I810DRIRec), 1))) {
28203b705cfSriastradh      DRIDestroyInfoRec(pI810->pDRIInfo);
28303b705cfSriastradh      pI810->pDRIInfo = NULL;
28403b705cfSriastradh      return FALSE;
28503b705cfSriastradh   }
28603b705cfSriastradh   pDRIInfo->devPrivate = pI810DRI;
28703b705cfSriastradh   pDRIInfo->devPrivateSize = sizeof(I810DRIRec);
28803b705cfSriastradh   pDRIInfo->contextSize = sizeof(I810DRIContextRec);
28903b705cfSriastradh
29003b705cfSriastradh   pDRIInfo->CreateContext = I810CreateContext;
29103b705cfSriastradh   pDRIInfo->DestroyContext = I810DestroyContext;
29203b705cfSriastradh   pDRIInfo->SwapContext = I810DRISwapContext;
29303b705cfSriastradh   pDRIInfo->InitBuffers = I810DRIInitBuffers;
29403b705cfSriastradh   pDRIInfo->MoveBuffers = I810DRIMoveBuffers;
29503b705cfSriastradh   pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
29603b705cfSriastradh   pDRIInfo->TransitionTo2d = I810DRITransitionTo2d;
29703b705cfSriastradh   pDRIInfo->TransitionTo3d = I810DRITransitionTo3d;
29803b705cfSriastradh   pDRIInfo->TransitionSingleToMulti3D = I810DRITransitionSingleToMulti3d;
29903b705cfSriastradh   pDRIInfo->TransitionMultiToSingle3D = I810DRITransitionMultiToSingle3d;
30003b705cfSriastradh
30103b705cfSriastradh   pDRIInfo->createDummyCtx = TRUE;
30203b705cfSriastradh   pDRIInfo->createDummyCtxPriv = FALSE;
30303b705cfSriastradh
30403b705cfSriastradh   /* This adds the framebuffer as a drm map *before* we have asked agp
30503b705cfSriastradh    * to allocate it.  Scary stuff, hold on...
30603b705cfSriastradh    */
30703b705cfSriastradh   if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) {
30803b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
30903b705cfSriastradh		 "[dri] DRIScreenInit failed.  Disabling DRI.\n");
31003b705cfSriastradh      free(pDRIInfo->devPrivate);
31103b705cfSriastradh      pDRIInfo->devPrivate = NULL;
31203b705cfSriastradh      DRIDestroyInfoRec(pI810->pDRIInfo);
31303b705cfSriastradh      pI810->pDRIInfo = NULL;
31403b705cfSriastradh      return FALSE;
31503b705cfSriastradh   }
31603b705cfSriastradh
31703b705cfSriastradh   /* Check the i810 DRM versioning */
31803b705cfSriastradh   {
31903b705cfSriastradh      drmVersionPtr version;
32003b705cfSriastradh
32103b705cfSriastradh      /* Check the DRM lib version.
32203b705cfSriastradh       * drmGetLibVersion was not supported in version 1.0, so check for
32303b705cfSriastradh       * symbol first to avoid possible crash or hang.
32403b705cfSriastradh       */
32503b705cfSriastradh      if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
32603b705cfSriastradh	 version = drmGetLibVersion(pI810->drmSubFD);
32703b705cfSriastradh      } else
32803b705cfSriastradh      {
32903b705cfSriastradh	 /* drmlib version 1.0.0 didn't have the drmGetLibVersion
33003b705cfSriastradh	  * entry point.  Fake it by allocating a version record
33103b705cfSriastradh	  * via drmGetVersion and changing it to version 1.0.0
33203b705cfSriastradh	  */
33303b705cfSriastradh	 version = drmGetVersion(pI810->drmSubFD);
33403b705cfSriastradh	 version->version_major = 1;
33503b705cfSriastradh	 version->version_minor = 0;
33603b705cfSriastradh	 version->version_patchlevel = 0;
33703b705cfSriastradh      }
33803b705cfSriastradh
33903b705cfSriastradh#define REQ_MAJ 1
34003b705cfSriastradh#define REQ_MIN 1
34103b705cfSriastradh      if (version) {
34203b705cfSriastradh	 if (version->version_major != REQ_MAJ ||
34303b705cfSriastradh	     version->version_minor < REQ_MIN) {
34403b705cfSriastradh	    /* incompatible drm library version */
34503b705cfSriastradh	    xf86DrvMsg(pScreen->myNum, X_ERROR,
34603b705cfSriastradh		       "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
34703b705cfSriastradh		       "[dri] libdrm.a module version is %d.%d.%d but version %d.%d.x is needed.\n"
34803b705cfSriastradh		       "[dri] Disabling DRI.\n",
34903b705cfSriastradh		       version->version_major,
35003b705cfSriastradh		       version->version_minor, version->version_patchlevel,
35103b705cfSriastradh		       REQ_MAJ, REQ_MIN);
35203b705cfSriastradh	    drmFreeVersion(version);
35303b705cfSriastradh	    I810DRICloseScreen(pScreen);
35403b705cfSriastradh	    return FALSE;
35503b705cfSriastradh	 }
35603b705cfSriastradh	 drmFreeVersion(version);
35703b705cfSriastradh      }
35803b705cfSriastradh
35903b705cfSriastradh      /* Check the i810 DRM version */
36003b705cfSriastradh      version = drmGetVersion(pI810->drmSubFD);
36103b705cfSriastradh      if (version) {
36203b705cfSriastradh	i810_drm_version = (version->version_major<<16) |
36303b705cfSriastradh	                    version->version_minor;
36403b705cfSriastradh	 if (version->version_major != 1 || version->version_minor < 2) {
36503b705cfSriastradh	    /* incompatible drm version */
36603b705cfSriastradh	    xf86DrvMsg(pScreen->myNum, X_ERROR,
36703b705cfSriastradh		       "[dri] I810DRIScreenInit failed because of a version mismatch.\n"
36803b705cfSriastradh		       "[dri] i810.o kernel module version is %d.%d.%d but version 1.2.0 or greater is needed.\n"
36903b705cfSriastradh		       "[dri] Disabling DRI.\n",
37003b705cfSriastradh		       version->version_major,
37103b705cfSriastradh		       version->version_minor, version->version_patchlevel);
37203b705cfSriastradh	    I810DRICloseScreen(pScreen);
37303b705cfSriastradh	    drmFreeVersion(version);
37403b705cfSriastradh	    return FALSE;
37503b705cfSriastradh	 }
37603b705cfSriastradh         pI810->drmMinor = version->version_minor;
37703b705cfSriastradh	 drmFreeVersion(version);
37803b705cfSriastradh      }
37903b705cfSriastradh   }
38003b705cfSriastradh
38103b705cfSriastradh   pI810DRI->regsSize = I810_REG_SIZE;
38203b705cfSriastradh   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->MMIOAddr,
38303b705cfSriastradh		 pI810DRI->regsSize, DRM_REGISTERS, 0,
38403b705cfSriastradh		 (drmAddress) &pI810DRI->regs) < 0) {
38503b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n");
38603b705cfSriastradh      DRICloseScreen(pScreen);
38703b705cfSriastradh      return FALSE;
38803b705cfSriastradh   }
38903b705cfSriastradh   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
39003b705cfSriastradh	      (int)pI810DRI->regs);
39103b705cfSriastradh
39203b705cfSriastradh   pI810->backHandle = DRM_AGP_NO_HANDLE;
39303b705cfSriastradh   pI810->zHandle = DRM_AGP_NO_HANDLE;
39403b705cfSriastradh   pI810->cursorHandle = DRM_AGP_NO_HANDLE;
39503b705cfSriastradh   pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
39603b705cfSriastradh   pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
39703b705cfSriastradh   pI810->agpAcquired = FALSE;
39803b705cfSriastradh   pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
39903b705cfSriastradh
40003b705cfSriastradh   /* Agp Support - Need this just to get the framebuffer.
40103b705cfSriastradh    */
40203b705cfSriastradh   if (drmAgpAcquire(pI810->drmSubFD) < 0) {
40303b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpAquire failed\n");
40403b705cfSriastradh      DRICloseScreen(pScreen);
40503b705cfSriastradh      return FALSE;
40603b705cfSriastradh   }
40703b705cfSriastradh   pI810->agpAcquired = TRUE;
40803b705cfSriastradh
40903b705cfSriastradh   if (drmAgpEnable(pI810->drmSubFD, 0) < 0) {
41003b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpEnable failed\n");
41103b705cfSriastradh      DRICloseScreen(pScreen);
41203b705cfSriastradh      return FALSE;
41303b705cfSriastradh   }
41403b705cfSriastradh
41503b705cfSriastradh   memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
41603b705cfSriastradh   memset(&pI810->BackBuffer, 0, sizeof(I810MemRange));
41703b705cfSriastradh   memset(&pI810->DepthBuffer, 0, sizeof(I810MemRange));
41803b705cfSriastradh   pI810->CursorPhysical = 0;
41903b705cfSriastradh   pI810->CursorARGBPhysical = 0;
42003b705cfSriastradh
42103b705cfSriastradh   /* Dcache - half the speed of normal ram, but has use as a Z buffer
42203b705cfSriastradh    * under the DRI.
42303b705cfSriastradh    */
42403b705cfSriastradh
42503b705cfSriastradh   drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL,
42603b705cfSriastradh	       (drmAddress) &dcacheHandle);
42703b705cfSriastradh   pI810->dcacheHandle = dcacheHandle;
42803b705cfSriastradh
42903b705cfSriastradh   xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : 0x%x\n",
43003b705cfSriastradh	      (int)dcacheHandle);
43103b705cfSriastradh
43203b705cfSriastradh   sysmem_size = pScrn->videoRam * 1024;
43303b705cfSriastradh   if (dcacheHandle != DRM_AGP_NO_HANDLE) {
43403b705cfSriastradh      if (back_size > 4 * 1024 * 1024) {
43503b705cfSriastradh	 xf86DrvMsg(pScreen->myNum, X_INFO,
43603b705cfSriastradh		    "[dri] Backsize is larger then 4 meg\n");
43703b705cfSriastradh	 sysmem_size = sysmem_size - 2 * back_size;
43803b705cfSriastradh	 drmAgpFree(pI810->drmSubFD, dcacheHandle);
43903b705cfSriastradh	 pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
44003b705cfSriastradh      } else {
44103b705cfSriastradh	 sysmem_size = sysmem_size - back_size;
44203b705cfSriastradh      }
44303b705cfSriastradh   } else {
44403b705cfSriastradh      sysmem_size = sysmem_size - 2 * back_size;
44503b705cfSriastradh   }
44603b705cfSriastradh
44703b705cfSriastradh   /* Max size is 48 without XvMC, 41 with 6 surfaces, 40 with 7 surfaces */
44803b705cfSriastradh   if (pI810->numSurfaces && (pI810->numSurfaces == 6)) {
44903b705cfSriastradh      if (sysmem_size > (pI810->FbMapSize - 7 * 1024 * 1024)) {
45003b705cfSriastradh	 sysmem_size = (pI810->FbMapSize - 7 * 1024 * 1024);
45103b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
45203b705cfSriastradh		    "User requested more memory then fits in the agp aperture\n"
45303b705cfSriastradh		    "Truncating to %d bytes of memory\n", sysmem_size);
45403b705cfSriastradh      }
45503b705cfSriastradh   }
45603b705cfSriastradh   if (pI810->numSurfaces && (pI810->numSurfaces == 7)) {
45703b705cfSriastradh      if (sysmem_size > (pI810->FbMapSize - 8 * 1024 * 1024)) {
45803b705cfSriastradh	 sysmem_size = (pI810->FbMapSize - 8 * 1024 * 1024);
45903b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
46003b705cfSriastradh		    "User requested more memory then fits in the agp aperture\n"
46103b705cfSriastradh		    "Truncating to %d bytes of memory\n", sysmem_size);
46203b705cfSriastradh      }
46303b705cfSriastradh   }
46403b705cfSriastradh
46503b705cfSriastradh   if (sysmem_size > pI810->FbMapSize) {
46603b705cfSriastradh      sysmem_size = pI810->FbMapSize;
46703b705cfSriastradh
46803b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
46903b705cfSriastradh		 "[dri] User requested more memory then fits in the agp"
47003b705cfSriastradh		 " aperture\n\tTruncating to %d bytes of memory\n",
47103b705cfSriastradh		 sysmem_size);
47203b705cfSriastradh   }
47303b705cfSriastradh
47403b705cfSriastradh   sysmem_size -= 4096;			/* remove 4k for the hw cursor */
47503b705cfSriastradh   sysmem_size -= 16384;		/* remove 16k for the ARGB hw cursor */
47603b705cfSriastradh
47703b705cfSriastradh   pI810->SysMem.Start = 0;
47803b705cfSriastradh   pI810->SysMem.Size = sysmem_size;
47903b705cfSriastradh   pI810->SysMem.End = sysmem_size;
48003b705cfSriastradh   tom = sysmem_size;
48103b705cfSriastradh
48203b705cfSriastradh   pI810->SavedSysMem = pI810->SysMem;
48303b705cfSriastradh
48403b705cfSriastradh   if (dcacheHandle != DRM_AGP_NO_HANDLE) {
48503b705cfSriastradh      if (drmAgpBind(pI810->drmSubFD, dcacheHandle, pI810->DepthOffset) == 0) {
48603b705cfSriastradh	 memset(&pI810->DcacheMem, 0, sizeof(I810MemRange));
48703b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
48803b705cfSriastradh		    "[agp] GART: Found 4096K Z buffer memory\n");
48903b705cfSriastradh	 pI810->DcacheMem.Start = pI810->DepthOffset;
49003b705cfSriastradh	 pI810->DcacheMem.Size = 1024 * 4096;
49103b705cfSriastradh	 pI810->DcacheMem.End =
49203b705cfSriastradh	       pI810->DcacheMem.Start + pI810->DcacheMem.Size;
49303b705cfSriastradh	 if (!I810AllocLow
49403b705cfSriastradh	     (&(pI810->DepthBuffer), &(pI810->DcacheMem), back_size)) {
49503b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
49603b705cfSriastradh		       "[agp] Depth buffer allocation failed\n");
49703b705cfSriastradh	    DRICloseScreen(pScreen);
49803b705cfSriastradh	    return FALSE;
49903b705cfSriastradh	 }
50003b705cfSriastradh      } else {
50103b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
50203b705cfSriastradh		    "[agp] GART: dcache bind failed\n");
50303b705cfSriastradh	 drmAgpFree(pI810->drmSubFD, dcacheHandle);
50403b705cfSriastradh	 pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE;
50503b705cfSriastradh      }
50603b705cfSriastradh   } else {
50703b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
50803b705cfSriastradh		 "[agp] GART: no dcache memory found\n");
50903b705cfSriastradh   }
51003b705cfSriastradh
51103b705cfSriastradh   drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL,
51203b705cfSriastradh	       (drmAddress) &agpHandle);
51303b705cfSriastradh   pI810->backHandle = agpHandle;
51403b705cfSriastradh
51503b705cfSriastradh   if (agpHandle != DRM_AGP_NO_HANDLE) {
51603b705cfSriastradh      if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->BackOffset) == 0) {
51703b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
51803b705cfSriastradh		    "[agp] Bound backbuffer memory\n");
51903b705cfSriastradh
52003b705cfSriastradh	 pI810->BackBuffer.Start = pI810->BackOffset;
52103b705cfSriastradh	 pI810->BackBuffer.Size = back_size;
52203b705cfSriastradh	 pI810->BackBuffer.End = (pI810->BackBuffer.Start +
52303b705cfSriastradh				  pI810->BackBuffer.Size);
52403b705cfSriastradh      } else {
52503b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
52603b705cfSriastradh		    "[agp] Unable to bind backbuffer.  Disabling DRI.\n");
52703b705cfSriastradh	 DRICloseScreen(pScreen);
52803b705cfSriastradh	 return FALSE;
52903b705cfSriastradh      }
53003b705cfSriastradh   } else {
53103b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
53203b705cfSriastradh		 "[dri] Unable to allocate backbuffer memory.  Disabling DRI.\n");
53303b705cfSriastradh      DRICloseScreen(pScreen);
53403b705cfSriastradh      return FALSE;
53503b705cfSriastradh   }
53603b705cfSriastradh
53703b705cfSriastradh   if (dcacheHandle == DRM_AGP_NO_HANDLE) {
53803b705cfSriastradh     drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL,
53903b705cfSriastradh		 (drmAddress) &agpHandle);
54003b705cfSriastradh
54103b705cfSriastradh      pI810->zHandle = agpHandle;
54203b705cfSriastradh
54303b705cfSriastradh      if (agpHandle != DRM_AGP_NO_HANDLE) {
54403b705cfSriastradh	 if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->DepthOffset) == 0) {
54503b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
54603b705cfSriastradh		       "[agp] Bound depthbuffer memory\n");
54703b705cfSriastradh	    pI810->DepthBuffer.Start = pI810->DepthOffset;
54803b705cfSriastradh	    pI810->DepthBuffer.Size = back_size;
54903b705cfSriastradh	    pI810->DepthBuffer.End = (pI810->DepthBuffer.Start +
55003b705cfSriastradh				      pI810->DepthBuffer.Size);
55103b705cfSriastradh	 } else {
55203b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
55303b705cfSriastradh		       "[agp] Unable to bind depthbuffer.  Disabling DRI.\n");
55403b705cfSriastradh	    DRICloseScreen(pScreen);
55503b705cfSriastradh	    return FALSE;
55603b705cfSriastradh	 }
55703b705cfSriastradh      } else {
55803b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
55903b705cfSriastradh		    "[agp] Unable to allocate depthbuffer memory.  Disabling DRI.\n");
56003b705cfSriastradh	 DRICloseScreen(pScreen);
56103b705cfSriastradh	 return FALSE;
56203b705cfSriastradh      }
56303b705cfSriastradh   }
56403b705cfSriastradh
56503b705cfSriastradh   /* Now allocate and bind the agp space.  This memory will include the
56603b705cfSriastradh    * regular framebuffer as well as texture memory.
56703b705cfSriastradh    */
56803b705cfSriastradh   drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL,
56903b705cfSriastradh	       (drmAddress)&agpHandle);
57003b705cfSriastradh   pI810->sysmemHandle = agpHandle;
57103b705cfSriastradh
57203b705cfSriastradh   if (agpHandle != DRM_AGP_NO_HANDLE) {
57303b705cfSriastradh      if (drmAgpBind(pI810->drmSubFD, agpHandle, 0) == 0) {
57403b705cfSriastradh	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
57503b705cfSriastradh		   "[agp] Bound System Texture Memory\n");
57603b705cfSriastradh      } else {
57703b705cfSriastradh          xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to bind system texture memory. Disabling DRI.\n");
57803b705cfSriastradh	  DRICloseScreen(pScreen);
57903b705cfSriastradh	  return FALSE;
58003b705cfSriastradh      }
58103b705cfSriastradh   } else {
58203b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to allocate system texture memory. Disabling DRI.\n");
58303b705cfSriastradh      DRICloseScreen(pScreen);
58403b705cfSriastradh      return FALSE;
58503b705cfSriastradh   }
58603b705cfSriastradh
58703b705cfSriastradh/* Allocate 7 or 8MB for XvMC this is setup as follows to best use tiled
58803b705cfSriastradh   regions and required surface pitches. (Numbers are adjusted if the
58903b705cfSriastradh   AGP region is only 32MB
59003b705cfSriastradh   For numSurfaces == 6
59103b705cfSriastradh   44 - 48MB = 4MB Fence, 8 Tiles wide
59203b705cfSriastradh   43 - 44MB = 1MB Fence, 8 Tiles wide
59303b705cfSriastradh   42 - 43MB = 1MB Fence, 4 Tiles wide
59403b705cfSriastradh   41 - 42MB = 1MB Fence, 4 Tiles wide
59503b705cfSriastradh   For numSurfaces == 7
59603b705cfSriastradh   44 - 48MB   = 4MB Fence, 8 Tiles wide
59703b705cfSriastradh   43 - 44MB   = 1MB Fence, 8 Tiles wide
59803b705cfSriastradh   42.5 - 43MB = 0.5MB Fence, 8 Tiles wide
59903b705cfSriastradh   42 - 42.5MB = 0.5MB Fence, 4 Tiles wide
60003b705cfSriastradh   40 - 42MB   = 2MB Fence, 4 Tiles wide
60103b705cfSriastradh */
60203b705cfSriastradh   if (pI810->numSurfaces) {
60303b705cfSriastradh      if (pI810->numSurfaces == 6) {
60403b705cfSriastradh	 pI810->MC.Size = 7 * 1024 * 1024;
60503b705cfSriastradh	 pI810->MC.Start = pI810->FbMapSize - 7 * 1024 * 1024;
60603b705cfSriastradh
60703b705cfSriastradh      }
60803b705cfSriastradh      if (pI810->numSurfaces == 7) {
60903b705cfSriastradh	 pI810->MC.Size = 8 * 1024 * 1024;
61003b705cfSriastradh	 pI810->MC.Start = pI810->FbMapSize - 8 * 1024 * 1024;
61103b705cfSriastradh      }
61203b705cfSriastradh      drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL,
61303b705cfSriastradh		  (drmAddress) &agpHandle);
61403b705cfSriastradh
61503b705cfSriastradh      pI810->xvmcHandle = agpHandle;
61603b705cfSriastradh
61703b705cfSriastradh      if (agpHandle != DRM_AGP_NO_HANDLE) {
61803b705cfSriastradh	 if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->MC.Start) == 0) {
61903b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
62003b705cfSriastradh		       "GART: Allocated 7MB for HWMC\n");
62103b705cfSriastradh	    pI810->MC.End = pI810->MC.Start + pI810->MC.Size;
62203b705cfSriastradh	 } else {
62303b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC bind failed\n");
62403b705cfSriastradh	    pI810->MC.Start = 0;
62503b705cfSriastradh	    pI810->MC.Size = 0;
62603b705cfSriastradh	    pI810->MC.End = 0;
62703b705cfSriastradh	 }
62803b705cfSriastradh      } else {
62903b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC alloc failed\n");
63003b705cfSriastradh	 pI810->MC.Start = 0;
63103b705cfSriastradh	 pI810->MC.Size = 0;
63203b705cfSriastradh	 pI810->MC.End = 0;
63303b705cfSriastradh      }
63403b705cfSriastradh      pI810->xvmcContext = 0;
63503b705cfSriastradh   }
63603b705cfSriastradh
63703b705cfSriastradh   drmAgpAlloc(pI810->drmSubFD, 4096, 2,
63803b705cfSriastradh	       (unsigned long *)&pI810->CursorPhysical,
63903b705cfSriastradh	       (drmAddress) &agpHandle);
64003b705cfSriastradh
64103b705cfSriastradh   pI810->cursorHandle = agpHandle;
64203b705cfSriastradh
64303b705cfSriastradh   if (agpHandle != DRM_AGP_NO_HANDLE) {
64403b705cfSriastradh      tom = sysmem_size;
64503b705cfSriastradh
64603b705cfSriastradh      if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) {
64703b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
64803b705cfSriastradh		    "[agp] GART: Allocated 4K for mouse cursor image\n");
64903b705cfSriastradh	 pI810->CursorStart = tom;
65003b705cfSriastradh	 tom += 4096;
65103b705cfSriastradh      } else {
65203b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
65303b705cfSriastradh		    "[agp] GART: cursor bind failed\n");
65403b705cfSriastradh	 pI810->CursorPhysical = 0;
65503b705cfSriastradh      }
65603b705cfSriastradh   } else {
65703b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
65803b705cfSriastradh		 "[agp] GART: cursor alloc failed\n");
65903b705cfSriastradh      pI810->CursorPhysical = 0;
66003b705cfSriastradh   }
66103b705cfSriastradh
66203b705cfSriastradh   drmAgpAlloc(pI810->drmSubFD, 16384, 2,
66303b705cfSriastradh	       (unsigned long *)&pI810->CursorARGBPhysical,
66403b705cfSriastradh	       (drmAddress) &agpHandle);
66503b705cfSriastradh
66603b705cfSriastradh   pI810->cursorARGBHandle = agpHandle;
66703b705cfSriastradh
66803b705cfSriastradh   if (agpHandle != DRM_AGP_NO_HANDLE) {
66903b705cfSriastradh      if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) {
67003b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
67103b705cfSriastradh		    "[agp] GART: Allocated 16K for ARGB mouse cursor image\n");
67203b705cfSriastradh	 pI810->CursorARGBStart = tom;
67303b705cfSriastradh	 tom += 16384;
67403b705cfSriastradh      } else {
67503b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
67603b705cfSriastradh		    "[agp] GART: ARGB cursor bind failed\n");
67703b705cfSriastradh	 pI810->CursorARGBPhysical = 0;
67803b705cfSriastradh      }
67903b705cfSriastradh   } else {
68003b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
68103b705cfSriastradh		 "[agp] GART: ARGB cursor alloc failed\n");
68203b705cfSriastradh      pI810->CursorARGBPhysical = 0;
68303b705cfSriastradh   }
68403b705cfSriastradh
68503b705cfSriastradh   /* Steal some of the excess cursor space for the overlay regs.
68603b705cfSriastradh    */
68703b705cfSriastradh   pI810->OverlayPhysical = pI810->CursorPhysical + 1024;
68803b705cfSriastradh   pI810->OverlayStart = pI810->CursorStart + 1024;
68903b705cfSriastradh
69003b705cfSriastradh   I810SetTiledMemory(pScrn, 1,
69103b705cfSriastradh		      pI810->DepthBuffer.Start,
69203b705cfSriastradh		      i810_pitches[pitch_idx], 8 * 1024 * 1024);
69303b705cfSriastradh
69403b705cfSriastradh   I810SetTiledMemory(pScrn, 2,
69503b705cfSriastradh		      pI810->BackBuffer.Start,
69603b705cfSriastradh		      i810_pitches[pitch_idx], 8 * 1024 * 1024);
69703b705cfSriastradh
69803b705cfSriastradh   /* These are for HWMC surfaces */
69903b705cfSriastradh   if (pI810->numSurfaces == 6) {
70003b705cfSriastradh      I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 1024 * 1024);
70103b705cfSriastradh
70203b705cfSriastradh      I810SetTiledMemory(pScrn, 4,
70303b705cfSriastradh			 pI810->MC.Start + 1024 * 1024, 512, 1024 * 1024);
70403b705cfSriastradh
70503b705cfSriastradh      I810SetTiledMemory(pScrn, 5,
70603b705cfSriastradh			 pI810->MC.Start + 1024 * 1024 * 2,
70703b705cfSriastradh			 1024, 1024 * 1024);
70803b705cfSriastradh
70903b705cfSriastradh      I810SetTiledMemory(pScrn, 6,
71003b705cfSriastradh			 pI810->MC.Start + 1024 * 1024 * 3,
71103b705cfSriastradh			 1024, 4 * 1024 * 1024);
71203b705cfSriastradh   }
71303b705cfSriastradh   if (pI810->numSurfaces == 7) {
71403b705cfSriastradh      I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 2 * 1024 * 1024);
71503b705cfSriastradh
71603b705cfSriastradh      I810SetTiledMemory(pScrn, 4,
71703b705cfSriastradh			 pI810->MC.Start + 2 * 1024 * 1024, 512, 512 * 1024);
71803b705cfSriastradh
71903b705cfSriastradh      I810SetTiledMemory(pScrn, 5,
72003b705cfSriastradh			 pI810->MC.Start + 2 * 1024 * 1024 + 512 * 1024,
72103b705cfSriastradh			 1024, 512 * 1024);
72203b705cfSriastradh
72303b705cfSriastradh      I810SetTiledMemory(pScrn, 6,
72403b705cfSriastradh			 pI810->MC.Start + 3 * 1024 * 1024,
72503b705cfSriastradh			 1024, 1 * 1024 * 1024);
72603b705cfSriastradh
72703b705cfSriastradh      I810SetTiledMemory(pScrn, 7,
72803b705cfSriastradh			 pI810->MC.Start + 4 * 1024 * 1024,
72903b705cfSriastradh			 1024, 4 * 1024 * 1024);
73003b705cfSriastradh
73103b705cfSriastradh   }
73203b705cfSriastradh
73303b705cfSriastradh   pI810->auxPitch = i810_pitches[pitch_idx];
73403b705cfSriastradh   pI810->auxPitchBits = i810_pitch_flags[pitch_idx];
73503b705cfSriastradh   pI810->SavedDcacheMem = pI810->DcacheMem;
73603b705cfSriastradh   pI810DRI->backbufferSize = pI810->BackBuffer.Size;
73703b705cfSriastradh
73803b705cfSriastradh   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BackBuffer.Start,
73903b705cfSriastradh		 pI810->BackBuffer.Size, DRM_AGP, 0,
74003b705cfSriastradh		 (drmAddress) &pI810DRI->backbuffer) < 0) {
74103b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
74203b705cfSriastradh		 "[drm] drmAddMap(backbuffer) failed.  Disabling DRI\n");
74303b705cfSriastradh      DRICloseScreen(pScreen);
74403b705cfSriastradh      return FALSE;
74503b705cfSriastradh   }
74603b705cfSriastradh
74703b705cfSriastradh   pI810DRI->depthbufferSize = pI810->DepthBuffer.Size;
74803b705cfSriastradh   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->DepthBuffer.Start,
74903b705cfSriastradh		 pI810->DepthBuffer.Size, DRM_AGP, 0,
75003b705cfSriastradh		 (drmAddress) &pI810DRI->depthbuffer) < 0) {
75103b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
75203b705cfSriastradh		 "[drm] drmAddMap(depthbuffer) failed.  Disabling DRI.\n");
75303b705cfSriastradh      DRICloseScreen(pScreen);
75403b705cfSriastradh      return FALSE;
75503b705cfSriastradh   }
75603b705cfSriastradh
75703b705cfSriastradh   /* Allocate FrontBuffer etc. */
75803b705cfSriastradh   if (!I810AllocateFront(pScrn)) {
75903b705cfSriastradh      DRICloseScreen(pScreen);
76003b705cfSriastradh      return FALSE;
76103b705cfSriastradh   }
76203b705cfSriastradh
76303b705cfSriastradh   /* Allocate buffer memory */
76403b705cfSriastradh   I810AllocHigh(&(pI810->BufferMem), &(pI810->SysMem),
76503b705cfSriastradh		 I810_DMA_BUF_NR * I810_DMA_BUF_SZ);
76603b705cfSriastradh
76703b705cfSriastradh   xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Buffer map : %lx\n",
76803b705cfSriastradh	      pI810->BufferMem.Start);
76903b705cfSriastradh
77003b705cfSriastradh   if (pI810->BufferMem.Start == 0 ||
77103b705cfSriastradh       pI810->BufferMem.End - pI810->BufferMem.Start >
77203b705cfSriastradh       I810_DMA_BUF_NR * I810_DMA_BUF_SZ) {
77303b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
77403b705cfSriastradh		 "[dri] Not enough memory for dma buffers.  Disabling DRI.\n");
77503b705cfSriastradh      DRICloseScreen(pScreen);
77603b705cfSriastradh      return FALSE;
77703b705cfSriastradh   }
77803b705cfSriastradh   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BufferMem.Start,
77903b705cfSriastradh		 pI810->BufferMem.Size, DRM_AGP, 0,
78003b705cfSriastradh		 (drmAddress) &pI810->buffer_map) < 0) {
78103b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
78203b705cfSriastradh		 "[drm] drmAddMap(buffer_map) failed.  Disabling DRI.\n");
78303b705cfSriastradh      DRICloseScreen(pScreen);
78403b705cfSriastradh      return FALSE;
78503b705cfSriastradh   }
78603b705cfSriastradh
78703b705cfSriastradh   pI810DRI->agp_buffers = pI810->buffer_map;
78803b705cfSriastradh   pI810DRI->agp_buf_size = pI810->BufferMem.Size;
78903b705cfSriastradh
79003b705cfSriastradh   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing->mem.Start,
79103b705cfSriastradh		 pI810->LpRing->mem.Size, DRM_AGP, 0,
79203b705cfSriastradh		 (drmAddress) &pI810->ring_map) < 0) {
79303b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
79403b705cfSriastradh		 "[drm] drmAddMap(ring_map) failed.  Disabling DRI.\n");
79503b705cfSriastradh      DRICloseScreen(pScreen);
79603b705cfSriastradh      return FALSE;
79703b705cfSriastradh   }
79803b705cfSriastradh
79903b705cfSriastradh   /* Use the rest of memory for textures. */
80003b705cfSriastradh   pI810DRI->textureSize = pI810->SysMem.Size;
80103b705cfSriastradh
80203b705cfSriastradh   i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS);
80303b705cfSriastradh
80403b705cfSriastradh   if (i < I810_LOG_MIN_TEX_REGION_SIZE)
80503b705cfSriastradh      i = I810_LOG_MIN_TEX_REGION_SIZE;
80603b705cfSriastradh
80703b705cfSriastradh   pI810DRI->logTextureGranularity = i;
80803b705cfSriastradh   pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i;	/* truncate */
80903b705cfSriastradh
81003b705cfSriastradh   if (pI810DRI->textureSize < 512 * 1024) {
81103b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
81203b705cfSriastradh		 "[drm] Less then 512k memory left for textures.  Disabling DRI.\n");
81303b705cfSriastradh      DRICloseScreen(pScreen);
81403b705cfSriastradh      return FALSE;
81503b705cfSriastradh   }
81603b705cfSriastradh
81703b705cfSriastradh   if (!I810AllocLow(&(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize)) {
81803b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
81903b705cfSriastradh		 "[agp] Texure memory allocation failed\n");
82003b705cfSriastradh      DRICloseScreen(pScreen);
82103b705cfSriastradh      return FALSE;
82203b705cfSriastradh   }
82303b705cfSriastradh
82403b705cfSriastradh   if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->TexMem.Start,
82503b705cfSriastradh		 pI810->TexMem.Size, DRM_AGP, 0,
82603b705cfSriastradh		 (drmAddress) &pI810DRI->textures) < 0) {
82703b705cfSriastradh      xf86DrvMsg(pScreen->myNum, X_ERROR,
82803b705cfSriastradh		 "[drm] drmAddMap(textures) failed.  Disabling DRI.\n");
82903b705cfSriastradh      DRICloseScreen(pScreen);
83003b705cfSriastradh      return FALSE;
83103b705cfSriastradh   }
83203b705cfSriastradh
83303b705cfSriastradh   if ((bufs = drmAddBufs(pI810->drmSubFD,
83403b705cfSriastradh			  I810_DMA_BUF_NR,
83503b705cfSriastradh			  I810_DMA_BUF_SZ,
83603b705cfSriastradh			  DRM_AGP_BUFFER, pI810->BufferMem.Start)) <= 0) {
83703b705cfSriastradh      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
83803b705cfSriastradh		 "[drm] failure adding %d %d byte DMA buffers.  Disabling DRI.\n",
83903b705cfSriastradh		 I810_DMA_BUF_NR, I810_DMA_BUF_SZ);
84003b705cfSriastradh      DRICloseScreen(pScreen);
84103b705cfSriastradh      return FALSE;
84203b705cfSriastradh   }
84303b705cfSriastradh
84403b705cfSriastradh   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
84503b705cfSriastradh	      "[drm] added %d %d byte DMA buffers\n", bufs, I810_DMA_BUF_SZ);
84603b705cfSriastradh
84703b705cfSriastradh   I810InitDma(pScrn);
84803b705cfSriastradh
84903b705cfSriastradh   /* Okay now initialize the dma engine */
85003b705cfSriastradh
85103b705cfSriastradh   if (!pI810DRI->irq) {
85203b705cfSriastradh      pI810DRI->irq = drmGetInterruptFromBusID(pI810->drmSubFD,
85303b705cfSriastradh					       ((pI810->PciInfo->domain << 8) |
85403b705cfSriastradh						pI810->PciInfo->bus),
85503b705cfSriastradh					       pI810->PciInfo->dev,
85603b705cfSriastradh					       pI810->PciInfo->func
85703b705cfSriastradh					       );
85803b705cfSriastradh      if ((drmCtlInstHandler(pI810->drmSubFD, pI810DRI->irq)) != 0) {
85903b705cfSriastradh	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
86003b705cfSriastradh		    "[drm] failure adding irq handler, there is a device "
86103b705cfSriastradh		    "already using that irq\n Consider rearranging your "
86203b705cfSriastradh		    "PCI cards.  Disabling DRI.\n");
86303b705cfSriastradh	 DRICloseScreen(pScreen);
86403b705cfSriastradh	 return FALSE;
86503b705cfSriastradh      }
86603b705cfSriastradh   }
86703b705cfSriastradh
86803b705cfSriastradh   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
86903b705cfSriastradh	      "[drm] dma control initialized, using IRQ %d\n", pI810DRI->irq);
87003b705cfSriastradh
87103b705cfSriastradh   pI810DRI->deviceID = pI810->PciInfo->device_id;
87203b705cfSriastradh   pI810DRI->width = pScrn->virtualX;
87303b705cfSriastradh   pI810DRI->height = pScrn->virtualY;
87403b705cfSriastradh   pI810DRI->mem = pScrn->videoRam * 1024;
87503b705cfSriastradh   pI810DRI->cpp = pI810->cpp;
87603b705cfSriastradh
87703b705cfSriastradh   pI810DRI->fbOffset = pI810->FrontBuffer.Start;
87803b705cfSriastradh   pI810DRI->fbStride = pI810->auxPitch;
87903b705cfSriastradh
88003b705cfSriastradh   pI810DRI->bitsPerPixel = pScrn->bitsPerPixel;
88103b705cfSriastradh
88203b705cfSriastradh   pI810DRI->textureOffset = pI810->TexMem.Start;
88303b705cfSriastradh
88403b705cfSriastradh   pI810DRI->backOffset = pI810->BackBuffer.Start;
88503b705cfSriastradh   pI810DRI->depthOffset = pI810->DepthBuffer.Start;
88603b705cfSriastradh
88703b705cfSriastradh   pI810DRI->ringOffset = pI810->LpRing->mem.Start;
88803b705cfSriastradh   pI810DRI->ringSize = pI810->LpRing->mem.Size;
88903b705cfSriastradh
89003b705cfSriastradh   pI810DRI->auxPitch = pI810->auxPitch;
89103b705cfSriastradh   pI810DRI->auxPitchBits = pI810->auxPitchBits;
89203b705cfSriastradh   pI810DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
89303b705cfSriastradh
89403b705cfSriastradh   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
89503b705cfSriastradh	      "[dri] visual configs initialized.\n");
89603b705cfSriastradh   pI810->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
89703b705cfSriastradh
89803b705cfSriastradh   return TRUE;
89903b705cfSriastradh}
90003b705cfSriastradh
90103b705cfSriastradhvoid
90203b705cfSriastradhI810DRICloseScreen(ScreenPtr pScreen)
90303b705cfSriastradh{
90403b705cfSriastradh   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
90503b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
90603b705cfSriastradh
90703b705cfSriastradh   if (pI810->pDRIInfo) {
90803b705cfSriastradh       I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate;
90903b705cfSriastradh
91003b705cfSriastradh       if (pI810DRI) {
91103b705cfSriastradh	   if (pI810DRI->irq) {
91203b705cfSriastradh	       drmCtlUninstHandler(pI810->drmSubFD);
91303b705cfSriastradh	       pI810DRI->irq = 0;
91403b705cfSriastradh	   }
91503b705cfSriastradh
91603b705cfSriastradh	   free(pI810->pDRIInfo->devPrivate);
91703b705cfSriastradh	   pI810->pDRIInfo->devPrivate = NULL;
91803b705cfSriastradh       }
91903b705cfSriastradh
92003b705cfSriastradh       I810CleanupDma(pScrn);
92103b705cfSriastradh
92203b705cfSriastradh       DRICloseScreen(pScreen);
92303b705cfSriastradh       DRIDestroyInfoRec(pI810->pDRIInfo);
92403b705cfSriastradh       pI810->pDRIInfo = NULL;
92503b705cfSriastradh   }
92603b705cfSriastradh
92703b705cfSriastradh   if (pI810->dcacheHandle!=DRM_AGP_NO_HANDLE)
92803b705cfSriastradh       drmAgpFree(pI810->drmSubFD, pI810->dcacheHandle);
92903b705cfSriastradh   if (pI810->backHandle!=DRM_AGP_NO_HANDLE)
93003b705cfSriastradh       drmAgpFree(pI810->drmSubFD, pI810->backHandle);
93103b705cfSriastradh   if (pI810->zHandle!=DRM_AGP_NO_HANDLE)
93203b705cfSriastradh       drmAgpFree(pI810->drmSubFD, pI810->zHandle);
93303b705cfSriastradh   if (pI810->cursorHandle!=DRM_AGP_NO_HANDLE)
93403b705cfSriastradh       drmAgpFree(pI810->drmSubFD, pI810->cursorHandle);
93503b705cfSriastradh   if (pI810->xvmcHandle!=DRM_AGP_NO_HANDLE)
93603b705cfSriastradh       drmAgpFree(pI810->drmSubFD, pI810->xvmcHandle);
93703b705cfSriastradh   if (pI810->sysmemHandle!=DRM_AGP_NO_HANDLE)
93803b705cfSriastradh       drmAgpFree(pI810->drmSubFD, pI810->sysmemHandle);
93903b705cfSriastradh
94003b705cfSriastradh   if (pI810->agpAcquired == TRUE)
94103b705cfSriastradh       drmAgpRelease(pI810->drmSubFD);
94203b705cfSriastradh
94303b705cfSriastradh   pI810->backHandle = DRM_AGP_NO_HANDLE;
94403b705cfSriastradh   pI810->zHandle = DRM_AGP_NO_HANDLE;
94503b705cfSriastradh   pI810->cursorHandle = DRM_AGP_NO_HANDLE;
94603b705cfSriastradh   pI810->xvmcHandle = DRM_AGP_NO_HANDLE;
94703b705cfSriastradh   pI810->sysmemHandle = DRM_AGP_NO_HANDLE;
94803b705cfSriastradh   pI810->agpAcquired = FALSE;
94903b705cfSriastradh   pI810->dcacheHandle = DRM_AGP_NO_HANDLE;
95003b705cfSriastradh}
95103b705cfSriastradh
95203b705cfSriastradhstatic Bool
95303b705cfSriastradhI810CreateContext(ScreenPtr pScreen, VisualPtr visual,
95403b705cfSriastradh		  drm_context_t hwContext, void *pVisualConfigPriv,
95503b705cfSriastradh		  DRIContextType contextStore)
95603b705cfSriastradh{
95703b705cfSriastradh   return TRUE;
95803b705cfSriastradh}
95903b705cfSriastradh
96003b705cfSriastradhstatic void
96103b705cfSriastradhI810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
96203b705cfSriastradh		   DRIContextType contextStore)
96303b705cfSriastradh{
96403b705cfSriastradh}
96503b705cfSriastradh
96603b705cfSriastradhBool
96703b705cfSriastradhI810DRIFinishScreenInit(ScreenPtr pScreen)
96803b705cfSriastradh{
96903b705cfSriastradh   I810SAREARec *sPriv = (I810SAREARec *) DRIGetSAREAPrivate(pScreen);
97003b705cfSriastradh   ScrnInfoPtr        pScrn = xf86ScreenToScrn(pScreen);
97103b705cfSriastradh   I810Ptr info  = I810PTR(pScrn);
97203b705cfSriastradh
97303b705cfSriastradh   memset(sPriv, 0, sizeof(*sPriv));
97403b705cfSriastradh
97503b705cfSriastradh   /* Have shadow run only while there is 3d active.
97603b705cfSriastradh    */
97703b705cfSriastradh   if (info->allowPageFlip && info->drmMinor >= 3) {
97803b705cfSriastradh     ShadowFBInit( pScreen, I810DRIRefreshArea );
97903b705cfSriastradh   }
98003b705cfSriastradh   else
98103b705cfSriastradh     info->allowPageFlip = 0;
98203b705cfSriastradh   return DRIFinishScreenInit(pScreen);
98303b705cfSriastradh}
98403b705cfSriastradh
98503b705cfSriastradhvoid
98603b705cfSriastradhI810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
98703b705cfSriastradh		   DRIContextType oldContextType, void *oldContext,
98803b705cfSriastradh		   DRIContextType newContextType, void *newContext)
98903b705cfSriastradh{
99003b705cfSriastradh   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
99103b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
99203b705cfSriastradh
99303b705cfSriastradh   if (syncType == DRI_3D_SYNC &&
99403b705cfSriastradh       oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) {
99503b705cfSriastradh      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
99603b705cfSriastradh	 ErrorF("I810DRISwapContext (in)\n");
99703b705cfSriastradh
99803b705cfSriastradh      if (!pScrn->vtSema)
99903b705cfSriastradh	  return;
100003b705cfSriastradh      pI810->LockHeld = 1;
100103b705cfSriastradh      I810RefreshRing(pScrn);
100203b705cfSriastradh   } else if (syncType == DRI_2D_SYNC &&
100303b705cfSriastradh	      oldContextType == DRI_NO_CONTEXT &&
100403b705cfSriastradh	      newContextType == DRI_2D_CONTEXT) {
100503b705cfSriastradh      pI810->LockHeld = 0;
100603b705cfSriastradh      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
100703b705cfSriastradh	 ErrorF("I810DRISwapContext (out)\n");
100803b705cfSriastradh   } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
100903b705cfSriastradh      ErrorF("I810DRISwapContext (other)\n");
101003b705cfSriastradh}
101103b705cfSriastradh
101203b705cfSriastradhstatic void
101303b705cfSriastradhI810DRISetNeedSync(ScrnInfoPtr pScrn)
101403b705cfSriastradh{
101503b705cfSriastradh#ifdef HAVE_XAA_H
101603b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
101703b705cfSriastradh   if (pI810->AccelInfoRec)
101803b705cfSriastradh	pI810->AccelInfoRec->NeedToSync = TRUE;
101903b705cfSriastradh#endif
102003b705cfSriastradh}
102103b705cfSriastradh
102203b705cfSriastradhstatic void
102303b705cfSriastradhI810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
102403b705cfSriastradh{
102503b705cfSriastradh   ScreenPtr pScreen = pWin->drawable.pScreen;
102603b705cfSriastradh   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
102703b705cfSriastradh   BoxPtr pbox = REGION_RECTS(prgn);
102803b705cfSriastradh   int nbox = REGION_NUM_RECTS(prgn);
102903b705cfSriastradh
103003b705cfSriastradh   if (I810_DEBUG & DEBUG_VERBOSE_DRI)
103103b705cfSriastradh      ErrorF("I810DRIInitBuffers\n");
103203b705cfSriastradh
103303b705cfSriastradh   I810SetupForSolidFill(pScrn, 0, GXcopy, -1);
103403b705cfSriastradh   while (nbox--) {
103503b705cfSriastradh      I810SelectBuffer(pScrn, I810_SELECT_BACK);
103603b705cfSriastradh      I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
103703b705cfSriastradh				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
103803b705cfSriastradh      pbox++;
103903b705cfSriastradh   }
104003b705cfSriastradh
104103b705cfSriastradh   /* Clear the depth buffer - uses 0xffff rather than 0.
104203b705cfSriastradh    */
104303b705cfSriastradh   pbox = REGION_RECTS(prgn);
104403b705cfSriastradh   nbox = REGION_NUM_RECTS(prgn);
104503b705cfSriastradh   I810SelectBuffer(pScrn, I810_SELECT_DEPTH);
104603b705cfSriastradh   I810SetupForSolidFill(pScrn, 0xffff, GXcopy, -1);
104703b705cfSriastradh   while (nbox--) {
104803b705cfSriastradh      I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
104903b705cfSriastradh				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
105003b705cfSriastradh      pbox++;
105103b705cfSriastradh   }
105203b705cfSriastradh   I810SelectBuffer(pScrn, I810_SELECT_FRONT);
105303b705cfSriastradh
105403b705cfSriastradh   I810DRISetNeedSync(pScrn);
105503b705cfSriastradh}
105603b705cfSriastradh
105703b705cfSriastradh/* This routine is a modified form of XAADoBitBlt with the calls to
105803b705cfSriastradh * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
105903b705cfSriastradh * instead of destination. My origin is upside down so the ydir cases
106003b705cfSriastradh * are reversed.
106103b705cfSriastradh *
106203b705cfSriastradh * KW: can you believe that this is called even when a 2d window moves?
106303b705cfSriastradh */
106403b705cfSriastradhstatic void
106503b705cfSriastradhI810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
106603b705cfSriastradh		   RegionPtr prgnSrc, CARD32 index)
106703b705cfSriastradh{
106803b705cfSriastradh   ScreenPtr pScreen = pParent->drawable.pScreen;
106903b705cfSriastradh   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
107003b705cfSriastradh   BoxPtr pboxTmp, pboxNext, pboxBase;
107103b705cfSriastradh   DDXPointPtr pptTmp, pptNew2 = NULL;
107203b705cfSriastradh   int xdir, ydir;
107303b705cfSriastradh
107403b705cfSriastradh   int screenwidth = pScrn->virtualX;
107503b705cfSriastradh   int screenheight = pScrn->virtualY;
107603b705cfSriastradh
107703b705cfSriastradh   BoxPtr pbox = REGION_RECTS(prgnSrc);
107803b705cfSriastradh   int nbox = REGION_NUM_RECTS(prgnSrc);
107903b705cfSriastradh
108003b705cfSriastradh   BoxPtr pboxNew1 = NULL;
108103b705cfSriastradh   BoxPtr pboxNew2 = NULL;
108203b705cfSriastradh   DDXPointPtr pptNew1 = NULL;
108303b705cfSriastradh   DDXPointPtr pptSrc = &ptOldOrg;
108403b705cfSriastradh
108503b705cfSriastradh   int dx = pParent->drawable.x - ptOldOrg.x;
108603b705cfSriastradh   int dy = pParent->drawable.y - ptOldOrg.y;
108703b705cfSriastradh
108803b705cfSriastradh   /* If the copy will overlap in Y, reverse the order */
108903b705cfSriastradh   if (dy > 0) {
109003b705cfSriastradh      ydir = -1;
109103b705cfSriastradh
109203b705cfSriastradh      if (nbox > 1) {
109303b705cfSriastradh	 /* Keep ordering in each band, reverse order of bands */
109403b705cfSriastradh	 pboxNew1 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
109503b705cfSriastradh	 if (!pboxNew1)
109603b705cfSriastradh	    return;
109703b705cfSriastradh	 pptNew1 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox);
109803b705cfSriastradh	 if (!pptNew1) {
109903b705cfSriastradh	    free(pboxNew1);
110003b705cfSriastradh	    return;
110103b705cfSriastradh	 }
110203b705cfSriastradh	 pboxBase = pboxNext = pbox + nbox - 1;
110303b705cfSriastradh	 while (pboxBase >= pbox) {
110403b705cfSriastradh	    while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
110503b705cfSriastradh	       pboxNext--;
110603b705cfSriastradh	    pboxTmp = pboxNext + 1;
110764b81f0aSriastradh	    if (pptSrc == &ptOldOrg) {
110864b81f0aSriastradh		if (pboxTmp <= pboxBase) {
110964b81f0aSriastradh	          *pboxNew1++ = *pboxTmp;
111064b81f0aSriastradh	          *pptNew1++ = *pptSrc;
111164b81f0aSriastradh		}
111264b81f0aSriastradh	    } else {
111364b81f0aSriastradh	       pptTmp = pptSrc + (pboxTmp - pbox);
111464b81f0aSriastradh	       while (pboxTmp <= pboxBase) {
111564b81f0aSriastradh	          *pboxNew1++ = *pboxTmp++;
111664b81f0aSriastradh	          *pptNew1++ = *pptTmp++;
111764b81f0aSriastradh	       }
111803b705cfSriastradh	    }
111903b705cfSriastradh	    pboxBase = pboxNext;
112003b705cfSriastradh	 }
112103b705cfSriastradh	 pboxNew1 -= nbox;
112203b705cfSriastradh	 pbox = pboxNew1;
112303b705cfSriastradh	 pptNew1 -= nbox;
112403b705cfSriastradh	 pptSrc = pptNew1;
112503b705cfSriastradh      }
112603b705cfSriastradh   } else {
112703b705cfSriastradh      /* No changes required */
112803b705cfSriastradh      ydir = 1;
112903b705cfSriastradh   }
113003b705cfSriastradh
113103b705cfSriastradh   /* If the regions will overlap in X, reverse the order */
113203b705cfSriastradh   if (dx > 0) {
113303b705cfSriastradh      xdir = -1;
113403b705cfSriastradh
113503b705cfSriastradh      if (nbox > 1) {
113603b705cfSriastradh	 /*reverse orderof rects in each band */
113703b705cfSriastradh	 pboxNew2 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
113803b705cfSriastradh	 pptNew2 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox);
113903b705cfSriastradh	 if (!pboxNew2 || !pptNew2) {
114003b705cfSriastradh	    if (pptNew2)
114103b705cfSriastradh	       free(pptNew2);
114203b705cfSriastradh	    if (pboxNew2)
114303b705cfSriastradh	       free(pboxNew2);
114403b705cfSriastradh	    if (pboxNew1) {
114503b705cfSriastradh	       free(pptNew1);
114603b705cfSriastradh	       free(pboxNew1);
114703b705cfSriastradh	    }
114803b705cfSriastradh	    return;
114903b705cfSriastradh	 }
115003b705cfSriastradh	 pboxBase = pboxNext = pbox;
115103b705cfSriastradh	 while (pboxBase < pbox + nbox) {
115203b705cfSriastradh	    while ((pboxNext < pbox + nbox) && (pboxNext->y1 == pboxBase->y1))
115303b705cfSriastradh	       pboxNext++;
115403b705cfSriastradh	    pboxTmp = pboxNext;
115503b705cfSriastradh	    pptTmp = pptSrc + (pboxTmp - pbox);
115603b705cfSriastradh	    while (pboxTmp != pboxBase) {
115703b705cfSriastradh	       *pboxNew2++ = *--pboxTmp;
115803b705cfSriastradh	       *pptNew2++ = *--pptTmp;
115903b705cfSriastradh	    }
116003b705cfSriastradh	    pboxBase = pboxNext;
116103b705cfSriastradh	 }
116203b705cfSriastradh	 pboxNew2 -= nbox;
116303b705cfSriastradh	 pbox = pboxNew2;
116403b705cfSriastradh	 pptNew2 -= nbox;
116503b705cfSriastradh	 pptSrc = pptNew2;
116603b705cfSriastradh      }
116703b705cfSriastradh   } else {
116803b705cfSriastradh      /* No changes are needed */
116903b705cfSriastradh      xdir = 1;
117003b705cfSriastradh   }
117103b705cfSriastradh
117203b705cfSriastradh   /* SelectBuffer isn't really a good concept for the i810.
117303b705cfSriastradh    */
117403b705cfSriastradh   I810EmitFlush(pScrn);
117503b705cfSriastradh   I810SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);
117603b705cfSriastradh   for (; nbox--; pbox++) {
117703b705cfSriastradh
117803b705cfSriastradh      int x1 = pbox->x1;
117903b705cfSriastradh      int y1 = pbox->y1;
118003b705cfSriastradh      int destx = x1 + dx;
118103b705cfSriastradh      int desty = y1 + dy;
118203b705cfSriastradh      int w = pbox->x2 - x1 + 1;
118303b705cfSriastradh      int h = pbox->y2 - y1 + 1;
118403b705cfSriastradh
118503b705cfSriastradh      if (destx < 0)
118603b705cfSriastradh	 x1 -= destx, w += destx, destx = 0;
118703b705cfSriastradh      if (desty < 0)
118803b705cfSriastradh	 y1 -= desty, h += desty, desty = 0;
118903b705cfSriastradh      if (destx + w > screenwidth)
119003b705cfSriastradh	 w = screenwidth - destx;
119103b705cfSriastradh      if (desty + h > screenheight)
119203b705cfSriastradh	 h = screenheight - desty;
119303b705cfSriastradh      if (w <= 0)
119403b705cfSriastradh	 continue;
119503b705cfSriastradh      if (h <= 0)
119603b705cfSriastradh	 continue;
119703b705cfSriastradh
119803b705cfSriastradh      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
119903b705cfSriastradh	 ErrorF("MoveBuffers %d,%d %dx%d dx: %d dy: %d\n",
120003b705cfSriastradh		x1, y1, w, h, dx, dy);
120103b705cfSriastradh
120203b705cfSriastradh      I810SelectBuffer(pScrn, I810_SELECT_BACK);
120303b705cfSriastradh      I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
120403b705cfSriastradh      I810SelectBuffer(pScrn, I810_SELECT_DEPTH);
120503b705cfSriastradh      I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
120603b705cfSriastradh   }
120703b705cfSriastradh   I810SelectBuffer(pScrn, I810_SELECT_FRONT);
120803b705cfSriastradh   I810EmitFlush(pScrn);
120903b705cfSriastradh
121003b705cfSriastradh   if (pboxNew2) {
121103b705cfSriastradh      free(pptNew2);
121203b705cfSriastradh      free(pboxNew2);
121303b705cfSriastradh   }
121403b705cfSriastradh   if (pboxNew1) {
121503b705cfSriastradh      free(pptNew1);
121603b705cfSriastradh      free(pboxNew1);
121703b705cfSriastradh   }
121803b705cfSriastradh
121903b705cfSriastradh   I810DRISetNeedSync(pScrn);
122003b705cfSriastradh}
122103b705cfSriastradh
122203b705cfSriastradh
122303b705cfSriastradh/* Use the miext/shadow module to maintain a list of dirty rectangles.
122403b705cfSriastradh * These are blitted to the back buffer to keep both buffers clean
122503b705cfSriastradh * during page-flipping when the 3d application isn't fullscreen.
122603b705cfSriastradh *
122703b705cfSriastradh * Unlike most use of the shadow code, both buffers are in video memory.
122803b705cfSriastradh *
122903b705cfSriastradh * An alternative to this would be to organize for all on-screen drawing
123003b705cfSriastradh * operations to be duplicated for the two buffers.  That might be
123103b705cfSriastradh * faster, but seems like a lot more work...
123203b705cfSriastradh */
123303b705cfSriastradh
123403b705cfSriastradh
123503b705cfSriastradh/* This should be done *before* XAA syncs or fires its buffer.
123603b705cfSriastradh * Otherwise will have to fire it again???
123703b705cfSriastradh */
123803b705cfSriastradhstatic void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
123903b705cfSriastradh{
124003b705cfSriastradh    I810Ptr pI810 = I810PTR(pScrn);
124103b705cfSriastradh    int i;
124203b705cfSriastradh    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
124303b705cfSriastradh    unsigned int br13;
124403b705cfSriastradh    int cpp=2;
124503b705cfSriastradh
124603b705cfSriastradh
124703b705cfSriastradh    /* Don't want to do this when no 3d is active and pages are
124803b705cfSriastradh     * right-way-round
124903b705cfSriastradh     */
125003b705cfSriastradh    if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
125103b705cfSriastradh      return;
125203b705cfSriastradh
125303b705cfSriastradh    br13 = (pI810->auxPitch) | (0xcc << 16);
125403b705cfSriastradh
125503b705cfSriastradh    for (i = 0 ; i < num ; i++, pbox++) {
125603b705cfSriastradh      unsigned int w = min(pbox->y2, pScrn->virtualY-1) - max(pbox->y1, 0) + 1;
125703b705cfSriastradh      unsigned int h = min(pbox->x2, pScrn->virtualX-1) - max(pbox->x1, 0) + 1;
125803b705cfSriastradh      unsigned int dst = max(pbox->x1, 0)*cpp + (max(pbox->y1, 0)*pI810->auxPitch);
125903b705cfSriastradh
126003b705cfSriastradh      BEGIN_LP_RING(6);
126103b705cfSriastradh
126203b705cfSriastradh      OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
126303b705cfSriastradh      OUT_RING(br13);
126403b705cfSriastradh      OUT_RING( (h<<16) | (w*cpp) );
126503b705cfSriastradh      OUT_RING(pI810->BackBuffer.Start + dst);
126603b705cfSriastradh      OUT_RING(br13 & 0xffff);
126703b705cfSriastradh      OUT_RING(dst);
126803b705cfSriastradh
126903b705cfSriastradh      ADVANCE_LP_RING();
127003b705cfSriastradh    }
127103b705cfSriastradh
127203b705cfSriastradh}
127303b705cfSriastradh
127403b705cfSriastradhstatic void I810EnablePageFlip(ScreenPtr pScreen)
127503b705cfSriastradh{
127603b705cfSriastradh    ScrnInfoPtr         pScrn      = xf86ScreenToScrn(pScreen);
127703b705cfSriastradh    I810Ptr       pI810       = I810PTR(pScrn);
127803b705cfSriastradh    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
127903b705cfSriastradh    int cpp=2;
128003b705cfSriastradh    pSAREAPriv->pf_enabled = pI810->allowPageFlip;
128103b705cfSriastradh    pSAREAPriv->pf_active = 0;
128203b705cfSriastradh
128303b705cfSriastradh   if (pI810->allowPageFlip) {
128403b705cfSriastradh      unsigned int br13 = pI810->auxPitch | (0xcc << 16);
128503b705cfSriastradh
128603b705cfSriastradh      BEGIN_LP_RING(6);
128703b705cfSriastradh
128803b705cfSriastradh      OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
128903b705cfSriastradh      OUT_RING(br13);
129003b705cfSriastradh      OUT_RING((pScrn->virtualY << 16) | (pScrn->virtualX*cpp));
129103b705cfSriastradh      OUT_RING(pI810->BackBuffer.Start);
129203b705cfSriastradh      OUT_RING(br13 & 0xFFFF);
129303b705cfSriastradh      OUT_RING(0);
129403b705cfSriastradh      ADVANCE_LP_RING();
129503b705cfSriastradh
129603b705cfSriastradh      pSAREAPriv->pf_active = 1;
129703b705cfSriastradh   }
129803b705cfSriastradh
129903b705cfSriastradh}
130003b705cfSriastradh
130103b705cfSriastradhstatic void I810DisablePageFlip(ScreenPtr pScreen)
130203b705cfSriastradh{
130303b705cfSriastradh    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
130403b705cfSriastradh
130503b705cfSriastradh    pSAREAPriv->pf_active=0;
130603b705cfSriastradh}
130703b705cfSriastradh
130803b705cfSriastradhstatic void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen)
130903b705cfSriastradh{
131003b705cfSriastradh    /* Tell the clients not to pageflip.  How?
131103b705cfSriastradh     *   -- Field in sarea, plus bumping the window counters.
131203b705cfSriastradh     *   -- DRM needs to cope with Front-to-Back swapbuffers.
131303b705cfSriastradh     */
131403b705cfSriastradh    I810DisablePageFlip(pScreen);
131503b705cfSriastradh}
131603b705cfSriastradh
131703b705cfSriastradhstatic void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen)
131803b705cfSriastradh{
131903b705cfSriastradh    /* Let the remaining 3d app start page flipping again */
132003b705cfSriastradh    I810EnablePageFlip(pScreen);
132103b705cfSriastradh}
132203b705cfSriastradh
132303b705cfSriastradhstatic void I810DRITransitionTo3d(ScreenPtr pScreen)
132403b705cfSriastradh{
132503b705cfSriastradh    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
132603b705cfSriastradh    I810Ptr  pI810  = I810PTR(pScrn);
132703b705cfSriastradh
132803b705cfSriastradh    I810EnablePageFlip(pScreen);
132903b705cfSriastradh    pI810->have3DWindows = 1;
133003b705cfSriastradh}
133103b705cfSriastradh
133203b705cfSriastradhstatic void I810DRITransitionTo2d(ScreenPtr pScreen)
133303b705cfSriastradh{
133403b705cfSriastradh    ScrnInfoPtr         pScrn      = xf86ScreenToScrn(pScreen);
133503b705cfSriastradh    I810Ptr       pI810       = I810PTR(pScrn);
133603b705cfSriastradh    I810SAREAPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
133703b705cfSriastradh
133803b705cfSriastradh    /* Try flipping back to the front page if necessary */
133903b705cfSriastradh    if (pSAREAPriv->pf_current_page == 1)
134003b705cfSriastradh	drmCommandNone(pI810->drmSubFD, DRM_I810_FLIP);
134103b705cfSriastradh
134203b705cfSriastradh    /* Shut down shadowing if we've made it back to the front page */
134303b705cfSriastradh    if (pSAREAPriv->pf_current_page == 0) {
134403b705cfSriastradh	I810DisablePageFlip(pScreen);
134503b705cfSriastradh    }
134603b705cfSriastradh    pI810->have3DWindows = 0;
134703b705cfSriastradh}
134803b705cfSriastradh
134903b705cfSriastradhBool
135003b705cfSriastradhI810DRILeave(ScrnInfoPtr pScrn)
135103b705cfSriastradh{
135203b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
135303b705cfSriastradh
135403b705cfSriastradh   if (pI810->directRenderingEnabled) {
135503b705cfSriastradh      if (pI810->dcacheHandle != 0)
135603b705cfSriastradh	 if (drmAgpUnbind(pI810->drmSubFD, pI810->dcacheHandle) != 0) {
135703b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
135803b705cfSriastradh	    return FALSE;
135903b705cfSriastradh	 }
136003b705cfSriastradh      if (pI810->backHandle != 0)
136103b705cfSriastradh	 if (drmAgpUnbind(pI810->drmSubFD, pI810->backHandle) != 0) {
136203b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
136303b705cfSriastradh 	    return FALSE;
136403b705cfSriastradh	 }
136503b705cfSriastradh      if (pI810->zHandle != 0)
136603b705cfSriastradh	 if (drmAgpUnbind(pI810->drmSubFD, pI810->zHandle) != 0) {
136703b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
136803b705cfSriastradh  	    return FALSE;
136903b705cfSriastradh	 }
137003b705cfSriastradh      if (pI810->sysmemHandle != 0)
137103b705cfSriastradh	 if (drmAgpUnbind(pI810->drmSubFD, pI810->sysmemHandle) != 0) {
137203b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
137303b705cfSriastradh  	    return FALSE;
137403b705cfSriastradh	 }
137503b705cfSriastradh      if (pI810->xvmcHandle != 0)
137603b705cfSriastradh	 if (drmAgpUnbind(pI810->drmSubFD, pI810->xvmcHandle) != 0) {
137703b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
137803b705cfSriastradh  	    return FALSE;
137903b705cfSriastradh	 }
138003b705cfSriastradh      if (pI810->cursorHandle != 0)
138103b705cfSriastradh	 if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorHandle) != 0) {
138203b705cfSriastradh	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
138303b705cfSriastradh	    return FALSE;
138403b705cfSriastradh	 }
138503b705cfSriastradh      if (pI810->cursorARGBHandle != 0)
138603b705cfSriastradh	  if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorARGBHandle) != 0) {
138703b705cfSriastradh	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno));
138803b705cfSriastradh	      return FALSE;
138903b705cfSriastradh	  }
139003b705cfSriastradh      if (pI810->agpAcquired == TRUE)
139103b705cfSriastradh	 drmAgpRelease(pI810->drmSubFD);
139203b705cfSriastradh      pI810->agpAcquired = FALSE;
139303b705cfSriastradh   }
139403b705cfSriastradh   return TRUE;
139503b705cfSriastradh}
139603b705cfSriastradh
139703b705cfSriastradhBool
139803b705cfSriastradhI810DRIEnter(ScrnInfoPtr pScrn)
139903b705cfSriastradh{
140003b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
140103b705cfSriastradh
140203b705cfSriastradh   if (pI810->directRenderingEnabled) {
140303b705cfSriastradh
140403b705cfSriastradh      if (pI810->agpAcquired == FALSE)
140503b705cfSriastradh	 drmAgpAcquire(pI810->drmSubFD);
140603b705cfSriastradh      pI810->agpAcquired = TRUE;
140703b705cfSriastradh      if (pI810->dcacheHandle != 0)
140803b705cfSriastradh	 if (drmAgpBind(pI810->drmSubFD, pI810->dcacheHandle,
140903b705cfSriastradh			pI810->DepthOffset) != 0)
141003b705cfSriastradh	    return FALSE;
141103b705cfSriastradh      if (pI810->backHandle != 0)
141203b705cfSriastradh	 if (drmAgpBind(pI810->drmSubFD, pI810->backHandle,
141303b705cfSriastradh			pI810->BackOffset) != 0)
141403b705cfSriastradh	    return FALSE;
141503b705cfSriastradh      if (pI810->zHandle != 0)
141603b705cfSriastradh	 if (drmAgpBind(pI810->drmSubFD, pI810->zHandle,
141703b705cfSriastradh			pI810->DepthOffset) != 0)
141803b705cfSriastradh	    return FALSE;
141903b705cfSriastradh      if (pI810->sysmemHandle != 0)
142003b705cfSriastradh	 if (drmAgpBind(pI810->drmSubFD, pI810->sysmemHandle, 0) != 0)
142103b705cfSriastradh	    return FALSE;
142203b705cfSriastradh      if (pI810->xvmcHandle != 0)
142303b705cfSriastradh	 if (drmAgpBind(pI810->drmSubFD, pI810->xvmcHandle,
142403b705cfSriastradh			pI810->MC.Start) != 0)
142503b705cfSriastradh	    return FALSE;
142603b705cfSriastradh      if (pI810->cursorHandle != 0)
142703b705cfSriastradh	 if (drmAgpBind(pI810->drmSubFD, pI810->cursorHandle,
142803b705cfSriastradh			pI810->CursorStart) != 0)
142903b705cfSriastradh	    return FALSE;
143003b705cfSriastradh      if (pI810->cursorARGBHandle != 0)
143103b705cfSriastradh	 if (drmAgpBind(pI810->drmSubFD, pI810->cursorARGBHandle,
143203b705cfSriastradh			pI810->CursorARGBStart) != 0)
143303b705cfSriastradh	    return FALSE;
143403b705cfSriastradh   }
143503b705cfSriastradh
143603b705cfSriastradh   I810SelectBuffer(pScrn, I810_SELECT_FRONT);
143703b705cfSriastradh   return TRUE;
143803b705cfSriastradh}
1439