1ab47cfaaSmrg/*
2ab47cfaaSmrg * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3ab47cfaaSmrg * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4ab47cfaaSmrg *
5ab47cfaaSmrg * Permission is hereby granted, free of charge, to any person obtaining a
6ab47cfaaSmrg * copy of this software and associated documentation files (the "Software"),
7ab47cfaaSmrg * to deal in the Software without restriction, including without limitation
8ab47cfaaSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
9ab47cfaaSmrg * and/or sell copies of the Software, and to permit persons to whom the
10ab47cfaaSmrg * Software is furnished to do so, subject to the following conditions:
11ab47cfaaSmrg *
12ab47cfaaSmrg * The above copyright notice and this permission notice (including the
13ab47cfaaSmrg * next paragraph) shall be included in all copies or substantial portions
14ab47cfaaSmrg * of the Software.
15ab47cfaaSmrg *
16ab47cfaaSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17ab47cfaaSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18ab47cfaaSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19ab47cfaaSmrg * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20ab47cfaaSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21ab47cfaaSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22ab47cfaaSmrg * DEALINGS IN THE SOFTWARE.
23ab47cfaaSmrg */
24ab47cfaaSmrg
25ab47cfaaSmrg#ifdef HAVE_CONFIG_H
26ab47cfaaSmrg#include "config.h"
27ab47cfaaSmrg#endif
28ab47cfaaSmrg
295788ca14Smrg#ifdef SAVAGEDRI
30ab47cfaaSmrg
31ab47cfaaSmrg#include "xf86.h"
32ab47cfaaSmrg#include "xf86_OSproc.h"
33ab47cfaaSmrg
345788ca14Smrg#ifdef HAVE_XAA_H
35ab47cfaaSmrg#include "xaalocal.h"
36ab47cfaaSmrg#include "xaarop.h"
375788ca14Smrg#endif
38ab47cfaaSmrg
39ab47cfaaSmrg#include "xf86Pci.h"
40ab47cfaaSmrg#include "xf86fbman.h"
41ab47cfaaSmrg
42ab47cfaaSmrg#include "miline.h"
43ab47cfaaSmrg
44ab47cfaaSmrg
45ab47cfaaSmrg/*#include "savage_vbe.h"*/
46ab47cfaaSmrg#include "savage_regs.h"
47ab47cfaaSmrg#include "savage_driver.h"
48ab47cfaaSmrg#include "savage_bci.h"
49ab47cfaaSmrg#include "savage_streams.h"
50ab47cfaaSmrg#include "savage_common.h"
51ab47cfaaSmrg
52ab47cfaaSmrg#define _XF86DRI_SERVER_
53ab47cfaaSmrg#include "sarea.h"
54ab47cfaaSmrg#include "savage_dri.h"
55ab47cfaaSmrg#include "savage_sarea.h"
56ab47cfaaSmrg
57ab47cfaaSmrgstatic char SAVAGEKernelDriverName[] = "savage";
58ab47cfaaSmrgstatic char SAVAGEClientDriverName[] = "savage";
59ab47cfaaSmrg
60ab47cfaaSmrgstatic Bool SAVAGEDRIOpenFullScreen(ScreenPtr pScreen);
61ab47cfaaSmrgstatic Bool SAVAGEDRICloseFullScreen(ScreenPtr pScreen);
62ab47cfaaSmrg/* DRI buffer management
63ab47cfaaSmrg */
64ab47cfaaSmrgvoid SAVAGEDRIInitBuffers( WindowPtr pWin, RegionPtr prgn,
65ab47cfaaSmrg				CARD32 index );
66ab47cfaaSmrgvoid SAVAGEDRIMoveBuffers( WindowPtr pParent, DDXPointRec ptOldOrg,
67ab47cfaaSmrg				RegionPtr prgnSrc, CARD32 index );
68ab47cfaaSmrg
69ab47cfaaSmrg/*        almost the same besides set src/desc to */
70ab47cfaaSmrg/*        Primary Bitmap Description              */
71ab47cfaaSmrg
72ab47cfaaSmrgstatic void
73ab47cfaaSmrgSAVAGEDRISetupForScreenToScreenCopy(
74ab47cfaaSmrg    ScrnInfoPtr pScrn, int xdir, int ydir,
75ab47cfaaSmrg    int rop, unsigned planemask, int transparency_color);
76ab47cfaaSmrg
77ab47cfaaSmrg
78ab47cfaaSmrgstatic void
79ab47cfaaSmrgSAVAGEDRISubsequentScreenToScreenCopy(
80ab47cfaaSmrg    ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
81ab47cfaaSmrg    int w, int h);
82ab47cfaaSmrg
83ab47cfaaSmrgstatic Bool SAVAGECreateContext( ScreenPtr pScreen, VisualPtr visual,
84ab47cfaaSmrg			      drm_context_t hwContext, void *pVisualConfigPriv,
85ab47cfaaSmrg			      DRIContextType contextStore )
86ab47cfaaSmrg{
875788ca14Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
88ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
89ab47cfaaSmrg
90ab47cfaaSmrg    if(psav->xvmcContext)
91ab47cfaaSmrg        return FALSE;
92ab47cfaaSmrg    else
93ab47cfaaSmrg    {
94ab47cfaaSmrg        psav->DRIrunning++;
95ab47cfaaSmrg    }
96ab47cfaaSmrg
97ab47cfaaSmrg    return TRUE;
98ab47cfaaSmrg}
99ab47cfaaSmrg
100ab47cfaaSmrgstatic void SAVAGEDestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
101ab47cfaaSmrg			       DRIContextType contextStore )
102ab47cfaaSmrg{
1035788ca14Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
104ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
105ab47cfaaSmrg
106ab47cfaaSmrg    psav->DRIrunning--;
107ab47cfaaSmrg}
108ab47cfaaSmrg
1095788ca14Smrgstatic void SAVAGEWakeupHandler(WAKEUPHANDLER_ARGS_DECL)
110ab47cfaaSmrg{
1115788ca14Smrg   SCREEN_PTR(arg);
1125788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
113ab47cfaaSmrg   SavagePtr psav = SAVPTR(pScrn);
114ab47cfaaSmrg
115ab47cfaaSmrg   psav->pDRIInfo->wrap.WakeupHandler = psav->coreWakeupHandler;
1165788ca14Smrg   (*psav->pDRIInfo->wrap.WakeupHandler) (WAKEUPHANDLER_ARGS);
117ab47cfaaSmrg   psav->pDRIInfo->wrap.WakeupHandler = SAVAGEWakeupHandler;
118ab47cfaaSmrg   psav->LockHeld = 1;
119ab47cfaaSmrg   if (psav->ShadowStatus) {
120ab47cfaaSmrg      /* fetch the global shadow counter */
121ab47cfaaSmrg#if 0
122ab47cfaaSmrg      if (psav->ShadowCounter != (psav->ShadowVirtual[1023] & 0xffff))
123ab47cfaaSmrg	 xf86DrvMsg( pScrn->scrnIndex, X_INFO,
124ab47cfaaSmrg		     "[dri] WakeupHandler: shadowCounter adjusted from %04x to %04lx\n",
125ab47cfaaSmrg		     psav->ShadowCounter, psav->ShadowVirtual[1023] & 0xffff);
126ab47cfaaSmrg#endif
127ab47cfaaSmrg      psav->ShadowCounter = psav->ShadowVirtual[1023] & 0xffff;
128ab47cfaaSmrg   }
129ab47cfaaSmrg   if (psav->useEXA)
130ab47cfaaSmrg	exaMarkSync(pScreen);
1315788ca14Smrg#ifdef HAVE_XAA_H
132ab47cfaaSmrg   else
133ab47cfaaSmrg	psav->AccelInfoRec->NeedToSync = TRUE;
1345788ca14Smrg#endif
135ab47cfaaSmrg   /* FK: this flag doesn't seem to be used. */
136ab47cfaaSmrg}
137ab47cfaaSmrg
1385788ca14Smrgstatic void SAVAGEBlockHandler(BLOCKHANDLER_ARGS_DECL)
139ab47cfaaSmrg{
1405788ca14Smrg   SCREEN_PTR(arg);
1415788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
142ab47cfaaSmrg   SavagePtr psav = SAVPTR(pScrn);
143ab47cfaaSmrg
144ab47cfaaSmrg   if (psav->ShadowStatus) {
145ab47cfaaSmrg      /* update the global shadow counter */
146ab47cfaaSmrg      CARD32 globalShadowCounter = psav->ShadowVirtual[1023];
147ab47cfaaSmrg      globalShadowCounter = (globalShadowCounter & 0xffff0000) |
148ab47cfaaSmrg	  ((CARD32)psav->ShadowCounter & 0x0000ffff);
149ab47cfaaSmrg
150ab47cfaaSmrg#if 0
151ab47cfaaSmrg      if (globalShadowCounter != psav->ShadowVirtual[1023])
152ab47cfaaSmrg	 xf86DrvMsg( pScrn->scrnIndex, X_INFO,
153ab47cfaaSmrg		     "[dri] BlockHandler: shadowCounter adjusted from %08lx to %08x\n",
154ab47cfaaSmrg		     psav->ShadowVirtual[1023], globalShadowCounter);
155ab47cfaaSmrg#endif
156ab47cfaaSmrg      psav->ShadowVirtual[1023] = globalShadowCounter;
157ab47cfaaSmrg   }
158ab47cfaaSmrg   psav->LockHeld = 0;
159ab47cfaaSmrg   psav->pDRIInfo->wrap.BlockHandler = psav->coreBlockHandler;
1605788ca14Smrg   (*psav->pDRIInfo->wrap.BlockHandler) (BLOCKHANDLER_ARGS);
161ab47cfaaSmrg   psav->pDRIInfo->wrap.BlockHandler = SAVAGEBlockHandler;
162ab47cfaaSmrg}
163ab47cfaaSmrg
1645788ca14Smrgstatic void SAVAGESelectBuffer( ScrnInfoPtr pScrn, int which )
165ab47cfaaSmrg{
166ab47cfaaSmrg   SavagePtr psav = SAVPTR(pScrn);
167ab47cfaaSmrg   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
168ab47cfaaSmrg
169ab47cfaaSmrg   psav->WaitIdleEmpty(psav);
170ab47cfaaSmrg
171ab47cfaaSmrg   OUTREG(0x48C18,INREG(0x48C18)&(~0x00000008));
172ab47cfaaSmrg
173ab47cfaaSmrg   switch ( which ) {
174ab47cfaaSmrg   case SAVAGE_BACK:
175ab47cfaaSmrg      OUTREG( 0x8170, pSAVAGEDRIServer->backOffset );
176ab47cfaaSmrg      OUTREG( 0x8174, pSAVAGEDRIServer->backBitmapDesc );
177ab47cfaaSmrg      break;
178ab47cfaaSmrg   case SAVAGE_DEPTH:
179ab47cfaaSmrg      OUTREG( 0x8170, pSAVAGEDRIServer->depthOffset );
180ab47cfaaSmrg      OUTREG( 0x8174, pSAVAGEDRIServer->depthBitmapDesc );
181ab47cfaaSmrg      break;
182ab47cfaaSmrg   default:
183ab47cfaaSmrg   case SAVAGE_FRONT:
184ab47cfaaSmrg      OUTREG( 0x8170, pSAVAGEDRIServer->frontOffset );
185ab47cfaaSmrg      OUTREG( 0x8174, pSAVAGEDRIServer->frontBitmapDesc );
186ab47cfaaSmrg      break;
187ab47cfaaSmrg   }
188ab47cfaaSmrg   OUTREG(0x48C18,INREG(0x48C18)|(0x00000008));
189ab47cfaaSmrg   psav->WaitIdleEmpty(psav);
190ab47cfaaSmrg
191ab47cfaaSmrg}
192ab47cfaaSmrg
193ab47cfaaSmrg
194ab47cfaaSmrgstatic unsigned int mylog2( unsigned int n )
195ab47cfaaSmrg{
196ab47cfaaSmrg   unsigned int log2 = 1;
197ab47cfaaSmrg
198ab47cfaaSmrg   n--;
199ab47cfaaSmrg   while ( n > 1 ) n >>= 1, log2++;
200ab47cfaaSmrg
201ab47cfaaSmrg   return log2;
202ab47cfaaSmrg}
203ab47cfaaSmrg
2045788ca14Smrgstatic Bool SAVAGESetAgpMode(SavagePtr psav, ScreenPtr pScreen)
205ab47cfaaSmrg{
2065788ca14Smrg   unsigned long mode = drmAgpGetMode( psav->drmFD );    /* Default mode */
2075788ca14Smrg   unsigned int vendor = drmAgpVendorId( psav->drmFD );
2085788ca14Smrg   unsigned int device = drmAgpDeviceId( psav->drmFD );
209ab47cfaaSmrg
210ab47cfaaSmrg   mode &= ~SAVAGE_AGP_MODE_MASK;
211ab47cfaaSmrg
212ab47cfaaSmrg   switch ( psav->agpMode ) {
213ab47cfaaSmrg   case 4:
214ab47cfaaSmrg      mode |= SAVAGE_AGP_4X_MODE;
215ab47cfaaSmrg   case 2:
216ab47cfaaSmrg      mode |= SAVAGE_AGP_2X_MODE;
217ab47cfaaSmrg   case 1:
218ab47cfaaSmrg   default:
219ab47cfaaSmrg      mode |= SAVAGE_AGP_1X_MODE;
220ab47cfaaSmrg   }
221ab47cfaaSmrg
222ab47cfaaSmrg   xf86DrvMsg( pScreen->myNum, X_INFO,
223ab47cfaaSmrg	       "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
224ab47cfaaSmrg	       mode, vendor, device,
2258697ee19Smrg	       VENDOR_ID(psav->PciInfo),
2268697ee19Smrg	       DEVICE_ID(psav->PciInfo));
227ab47cfaaSmrg
228ab47cfaaSmrg   if ( drmAgpEnable( psav->drmFD, mode ) < 0 ) {
229ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
230ab47cfaaSmrg      drmAgpRelease( psav->drmFD );
2315788ca14Smrg      return FALSE;
2325788ca14Smrg   }
2335788ca14Smrg
2345788ca14Smrg   return TRUE;
2355788ca14Smrg}
2365788ca14Smrg
2375788ca14Smrgstatic Bool SAVAGEDRIAgpInit(ScreenPtr pScreen)
2385788ca14Smrg{
2395788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2405788ca14Smrg   SavagePtr psav = SAVPTR(pScrn);
2415788ca14Smrg   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
2425788ca14Smrg   unsigned int offset;
2435788ca14Smrg   int ret;
2445788ca14Smrg
2455788ca14Smrg   if (psav->agpSize < 2)
2465788ca14Smrg      psav->agpSize = 2; /* at least 2MB for DMA buffers */
2475788ca14Smrg
2485788ca14Smrg   pSAVAGEDRIServer->agp.size = psav->agpSize * 1024 * 1024;
2495788ca14Smrg   pSAVAGEDRIServer->agp.offset = pSAVAGEDRIServer->agp.size; /* ? */
2505788ca14Smrg
2515788ca14Smrg   if ( drmAgpAcquire( psav->drmFD ) < 0 ) {
2525788ca14Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not available\n" );
2535788ca14Smrg      return FALSE;
2545788ca14Smrg   }
2555788ca14Smrg
2565788ca14Smrg   if (!SAVAGESetAgpMode(psav, pScreen)) {
257ab47cfaaSmrg      pSAVAGEDRIServer->agp.handle = 0; /* indicate that AGP init failed */
258ab47cfaaSmrg      return FALSE;
259ab47cfaaSmrg   }
260ab47cfaaSmrg
261ab47cfaaSmrg   ret = drmAgpAlloc( psav->drmFD, pSAVAGEDRIServer->agp.size,
262ab47cfaaSmrg		      0, NULL, &pSAVAGEDRIServer->agp.handle );
263ab47cfaaSmrg   if ( ret < 0 ) {
264ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
265ab47cfaaSmrg      drmAgpRelease( psav->drmFD );
266ab47cfaaSmrg      pSAVAGEDRIServer->agp.handle = 0; /* indicate that AGP init failed */
267ab47cfaaSmrg      return FALSE;
268ab47cfaaSmrg   }
269ab47cfaaSmrg   xf86DrvMsg( pScreen->myNum, X_INFO,
270ab47cfaaSmrg	       "[agp] %d kB allocated with handle 0x%08lx\n",
2715788ca14Smrg	       pSAVAGEDRIServer->agp.size/1024,
2725788ca14Smrg	       (unsigned long)pSAVAGEDRIServer->agp.handle );
273ab47cfaaSmrg
274ab47cfaaSmrg   if ( drmAgpBind( psav->drmFD, pSAVAGEDRIServer->agp.handle, 0 ) < 0 ) {
275ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind memory\n" );
276ab47cfaaSmrg      drmAgpFree( psav->drmFD, pSAVAGEDRIServer->agp.handle );
277ab47cfaaSmrg      drmAgpRelease( psav->drmFD );
278ab47cfaaSmrg      pSAVAGEDRIServer->agp.handle = 0; /* indicate that AGP init failed */
279ab47cfaaSmrg      return FALSE;
280ab47cfaaSmrg   }
281ab47cfaaSmrg
282ab47cfaaSmrg   /* AGP initialization failures above are not fatal, we can fall
283ab47cfaaSmrg    * back to PCI mode. Failures while adding AGP mappings below are
284ab47cfaaSmrg    * fatal though. DRI must be disabled in that case.
285ab47cfaaSmrg    * pSAVAGEDRIServer->agp.handle can be used to distinguish these
286ab47cfaaSmrg    * two cases.
287ab47cfaaSmrg    */
288ab47cfaaSmrg
289ab47cfaaSmrg   /* AGP memory layout
290ab47cfaaSmrg    */
291ab47cfaaSmrg   offset = 0;
292ab47cfaaSmrg
293ab47cfaaSmrg   if ( psav->AgpDMA ) {
294ab47cfaaSmrg       if ( psav->CommandDMA ) {
295ab47cfaaSmrg	   pSAVAGEDRIServer->cmdDma.offset = offset;
296ab47cfaaSmrg	   pSAVAGEDRIServer->cmdDma.size = SAVAGE_CMDDMA_SIZE;
297ab47cfaaSmrg	   offset += pSAVAGEDRIServer->cmdDma.size;
298ab47cfaaSmrg       } else if ( psav->VertexDMA ) {
299ab47cfaaSmrg	   pSAVAGEDRIServer->buffers.offset = 0;
300ab47cfaaSmrg	   pSAVAGEDRIServer->buffers.size = SAVAGE_NUM_BUFFERS * SAVAGE_BUFFER_SIZE;
301ab47cfaaSmrg	   offset += pSAVAGEDRIServer->buffers.size;
302ab47cfaaSmrg       }
303ab47cfaaSmrg   }
304ab47cfaaSmrg
3051c79cd07Smrg   if (psav->AGPforXv) {
3061c79cd07Smrg       pSAVAGEDRIServer->agpXVideo.offset = offset;
3071c79cd07Smrg       pSAVAGEDRIServer->agpXVideo.size = 2 * 1024 * 1024; /* Max XV image is 1024x1024x16bpp */
3081c79cd07Smrg       offset += pSAVAGEDRIServer->agpXVideo.size;
3091c79cd07Smrg   } else {
3101c79cd07Smrg       pSAVAGEDRIServer->agpXVideo.offset = 0;
3111c79cd07Smrg       pSAVAGEDRIServer->agpXVideo.size = 0;
3121c79cd07Smrg   }
3131c79cd07Smrg
314ab47cfaaSmrg   pSAVAGEDRIServer->agpTextures.offset = offset;
315ab47cfaaSmrg   pSAVAGEDRIServer->agpTextures.size = (pSAVAGEDRIServer->agp.size - offset);
316ab47cfaaSmrg
317ab47cfaaSmrg   /* DMA buffers
318ab47cfaaSmrg    */
319ab47cfaaSmrg   if ( psav->AgpDMA ) {
320ab47cfaaSmrg       if ( psav->CommandDMA ) {
321ab47cfaaSmrg	   if ( drmAddMap( psav->drmFD,
322ab47cfaaSmrg			   pSAVAGEDRIServer->cmdDma.offset,
323ab47cfaaSmrg			   pSAVAGEDRIServer->cmdDma.size,
324ab47cfaaSmrg			   DRM_AGP, DRM_RESTRICTED | DRM_KERNEL,
325ab47cfaaSmrg			   &pSAVAGEDRIServer->cmdDma.handle ) < 0 ) {
326ab47cfaaSmrg	       xf86DrvMsg( pScreen->myNum, X_ERROR,
327ab47cfaaSmrg			   "[agp] Could not add command DMA mapping\n" );
328ab47cfaaSmrg	       return FALSE;
329ab47cfaaSmrg	   }
330ab47cfaaSmrg	   xf86DrvMsg( pScreen->myNum, X_INFO,
331ab47cfaaSmrg		       "[agp] command DMA handle = 0x%08lx\n",
3325788ca14Smrg		       (unsigned long)pSAVAGEDRIServer->cmdDma.handle );
333ab47cfaaSmrg	   /* not needed in the server
334ab47cfaaSmrg	   if ( drmMap( psav->drmFD,
335ab47cfaaSmrg			pSAVAGEDRIServer->cmdDma.handle,
336ab47cfaaSmrg			pSAVAGEDRIServer->cmdDma.size,
337ab47cfaaSmrg			&pSAVAGEDRIServer->cmdDma.map ) < 0 ) {
338ab47cfaaSmrg	       xf86DrvMsg( pScreen->myNum, X_ERROR,
339ab47cfaaSmrg			   "[agp] Could not map command DMA\n" );
340ab47cfaaSmrg	       return FALSE;
341ab47cfaaSmrg	   }
342ab47cfaaSmrg	   xf86DrvMsg( pScreen->myNum, X_INFO,
343ab47cfaaSmrg		       "[agp] command DMA mapped at 0x%08lx\n",
344ab47cfaaSmrg		       (unsigned long)pSAVAGEDRIServer->cmdDma.map );
345ab47cfaaSmrg	   */
346ab47cfaaSmrg       } else if ( psav->VertexDMA ) {
347ab47cfaaSmrg	   if ( drmAddMap( psav->drmFD,
348ab47cfaaSmrg			   pSAVAGEDRIServer->buffers.offset,
349ab47cfaaSmrg			   pSAVAGEDRIServer->buffers.size,
350ab47cfaaSmrg			   DRM_AGP, 0,
351ab47cfaaSmrg			   &pSAVAGEDRIServer->buffers.handle ) < 0 ) {
352ab47cfaaSmrg	       xf86DrvMsg( pScreen->myNum, X_ERROR,
353ab47cfaaSmrg			   "[agp] Could not add DMA buffers mapping\n" );
354ab47cfaaSmrg	       return FALSE;
355ab47cfaaSmrg	   }
356ab47cfaaSmrg	   xf86DrvMsg( pScreen->myNum, X_INFO,
357ab47cfaaSmrg		       "[agp] DMA buffers handle = 0x%08lx\n",
3585788ca14Smrg		       (unsigned long)pSAVAGEDRIServer->buffers.handle );
359ab47cfaaSmrg	   /* not needed in the server
360ab47cfaaSmrg	   if ( drmMap( psav->drmFD,
361ab47cfaaSmrg			pSAVAGEDRIServer->buffers.handle,
362ab47cfaaSmrg			pSAVAGEDRIServer->buffers.size,
363ab47cfaaSmrg			&pSAVAGEDRIServer->buffers.map ) < 0 ) {
364ab47cfaaSmrg	       xf86DrvMsg( pScreen->myNum, X_ERROR,
365ab47cfaaSmrg			   "[agp] Could not map DMA buffers\n" );
366ab47cfaaSmrg	       return FALSE;
367ab47cfaaSmrg	   }
368ab47cfaaSmrg	   xf86DrvMsg( pScreen->myNum, X_INFO,
369ab47cfaaSmrg		       "[agp] DMA buffers mapped at 0x%08lx\n",
370ab47cfaaSmrg		       (unsigned long)pSAVAGEDRIServer->buffers.map );
371ab47cfaaSmrg	   */
372ab47cfaaSmrg       }
373ab47cfaaSmrg   }
374ab47cfaaSmrg
3751c79cd07Smrg   /* XVideo buffer
3761c79cd07Smrg    */
3771c79cd07Smrg   if (pSAVAGEDRIServer->agpXVideo.size != 0) {
3781c79cd07Smrg       if ( drmAddMap( psav->drmFD,
3791c79cd07Smrg		   pSAVAGEDRIServer->agpXVideo.offset,
3801c79cd07Smrg		   pSAVAGEDRIServer->agpXVideo.size,
3811c79cd07Smrg		   DRM_AGP, 0,
3821c79cd07Smrg		   &pSAVAGEDRIServer->agpXVideo.handle ) < 0 ) {
3831c79cd07Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
3841c79cd07Smrg		  "[agp] Could not add agpXVideo, will use framebuffer upload (slower) \n" );
3851c79cd07Smrg	    pSAVAGEDRIServer->agpXVideo.size = 0;
3861c79cd07Smrg	    pSAVAGEDRIServer->agpXVideo.handle = 0;
3871c79cd07Smrg       } else {
3881c79cd07Smrg	    xf86DrvMsg( pScreen->myNum, X_INFO,
3891c79cd07Smrg	       "[agp] agpXVideo handle = 0x%08lx\n",
3905788ca14Smrg	       (unsigned long)pSAVAGEDRIServer->agpXVideo.handle );
3911c79cd07Smrg       }
3921c79cd07Smrg   }
3931c79cd07Smrg
394ab47cfaaSmrg   /* AGP textures
395ab47cfaaSmrg    */
396ab47cfaaSmrg   if ( drmAddMap( psav->drmFD,
397ab47cfaaSmrg		   pSAVAGEDRIServer->agpTextures.offset,
398ab47cfaaSmrg		   pSAVAGEDRIServer->agpTextures.size,
399ab47cfaaSmrg		   DRM_AGP, 0,
400ab47cfaaSmrg		   &pSAVAGEDRIServer->agpTextures.handle ) < 0 ) {
401ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
402ab47cfaaSmrg		  "[agp] Could not add agpTextures \n" );
403ab47cfaaSmrg      return FALSE;
404ab47cfaaSmrg   }
405ab47cfaaSmrg   /*   pSAVAGEDRIServer->agp_offset=pSAVAGEDRIServer->agpTexture.size;*/
406ab47cfaaSmrg   xf86DrvMsg( pScreen->myNum, X_INFO,
407ab47cfaaSmrg	       "[agp] agpTextures handle = 0x%08lx\n",
4085788ca14Smrg	       (unsigned long)pSAVAGEDRIServer->agpTextures.handle );
409ab47cfaaSmrg
410ab47cfaaSmrg   /* not needed in the server
411ab47cfaaSmrg   if ( drmMap( psav->drmFD,
412ab47cfaaSmrg		pSAVAGEDRIServer->agpTextures.handle,
413ab47cfaaSmrg		pSAVAGEDRIServer->agpTextures.size,
414ab47cfaaSmrg		&pSAVAGEDRIServer->agpTextures.map ) < 0 ) {
415ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
416ab47cfaaSmrg		  "[agp] Could not map agpTextures \n" );
417ab47cfaaSmrg      return FALSE;
418ab47cfaaSmrg   }
419ab47cfaaSmrg
420ab47cfaaSmrg   xf86DrvMsg( pScreen->myNum, X_INFO,
421ab47cfaaSmrg	       "[agp] agpTextures mapped at 0x%08lx\n",
422ab47cfaaSmrg	       (unsigned long)pSAVAGEDRIServer->agpTextures.map );
423ab47cfaaSmrg   */
424ab47cfaaSmrg
425ab47cfaaSmrg   return TRUE;
426ab47cfaaSmrg}
427ab47cfaaSmrg
428ab47cfaaSmrgstatic Bool SAVAGEDRIMapInit( ScreenPtr pScreen )
429ab47cfaaSmrg{
4305788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
431ab47cfaaSmrg   SavagePtr psav = SAVPTR(pScrn);
432ab47cfaaSmrg   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
433ab47cfaaSmrg
434ab47cfaaSmrg   pSAVAGEDRIServer->registers.size = SAVAGEIOMAPSIZE;
435ab47cfaaSmrg
436ab47cfaaSmrg   if ( drmAddMap( psav->drmFD,
4378697ee19Smrg		   (drm_handle_t)psav->MmioRegion.base,
438ab47cfaaSmrg		   pSAVAGEDRIServer->registers.size,
439ab47cfaaSmrg		   DRM_REGISTERS,0,
440ab47cfaaSmrg		   &pSAVAGEDRIServer->registers.handle ) < 0 ) {
441ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
442ab47cfaaSmrg		  "[drm] Could not add MMIO registers mapping\n" );
443ab47cfaaSmrg      return FALSE;
444ab47cfaaSmrg   }
445ab47cfaaSmrg
446ab47cfaaSmrg   pSAVAGEDRIServer->aperture.size = 5 * 0x01000000;
447ab47cfaaSmrg
448ab47cfaaSmrg   if ( drmAddMap( psav->drmFD,
4498697ee19Smrg		   (drm_handle_t)(psav->ApertureRegion.base),
450ab47cfaaSmrg		   pSAVAGEDRIServer->aperture.size,
451ab47cfaaSmrg		   DRM_FRAME_BUFFER,0,
452ab47cfaaSmrg		   &pSAVAGEDRIServer->aperture.handle ) < 0 ) {
453ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
454ab47cfaaSmrg		  "[drm] Could not add aperture mapping\n" );
455ab47cfaaSmrg      return FALSE;
456ab47cfaaSmrg   }
457ab47cfaaSmrg
458ab47cfaaSmrg   xf86DrvMsg( pScreen->myNum, X_INFO,
459ab47cfaaSmrg	       "[drm] aperture handle = 0x%08lx\n",
4605788ca14Smrg	       (unsigned long)pSAVAGEDRIServer->aperture.handle );
461ab47cfaaSmrg
462ab47cfaaSmrg   /*if(drmMap(psav->drmFD,
463ab47cfaaSmrg          pSAVAGEDRIServer->registers.handle,
464ab47cfaaSmrg          pSAVAGEDRIServer->registers.size,
465ab47cfaaSmrg          &pSAVAGEDRIServer->registers.map)<0)
466ab47cfaaSmrg   {
467ab47cfaaSmrg         xf86DrvMsg( pScreen->myNum, X_ERROR,
468ab47cfaaSmrg		  "[drm] Could not map MMIO registers region to virtual\n" );
469ab47cfaaSmrg      return FALSE;
470ab47cfaaSmrg
471ab47cfaaSmrg   }*/
472ab47cfaaSmrg
473ab47cfaaSmrg   if ( !psav->AgpDMA && psav->CommandDMA ) {
474ab47cfaaSmrg       pSAVAGEDRIServer->cmdDma.size = SAVAGE_CMDDMA_SIZE;
475ab47cfaaSmrg       if ( drmAddMap( psav->drmFD, 0, pSAVAGEDRIServer->cmdDma.size,
476ab47cfaaSmrg		       DRM_CONSISTENT, DRM_RESTRICTED | DRM_LOCKED |
477ab47cfaaSmrg		       DRM_KERNEL | DRM_WRITE_COMBINING,
478ab47cfaaSmrg		       &pSAVAGEDRIServer->cmdDma.handle ) < 0 ) {
479ab47cfaaSmrg	   psav->CommandDMA = FALSE;
480ab47cfaaSmrg	   xf86DrvMsg( pScreen->myNum, X_WARNING,
481ab47cfaaSmrg		       "[drm] Could not add PCI command DMA mapping\n" );
482ab47cfaaSmrg       } else
483ab47cfaaSmrg	   xf86DrvMsg( pScreen->myNum, X_INFO,
484ab47cfaaSmrg		       "[drm] PCI command DMA handle = 0x%08lx\n",
4855788ca14Smrg		       (unsigned long)pSAVAGEDRIServer->cmdDma.handle );
486ab47cfaaSmrg   }
487ab47cfaaSmrg
488ab47cfaaSmrg   /* Enable ShadowStatus by default for direct rendering. */
489ab47cfaaSmrg   if ( !psav->ShadowStatus && !psav->ForceShadowStatus ) {
490ab47cfaaSmrg       psav->ShadowStatus = TRUE;
491ab47cfaaSmrg       xf86DrvMsg( pScreen->myNum, X_INFO,
492ab47cfaaSmrg		   "[drm] Enabling ShadowStatus for DRI.\n" );
493ab47cfaaSmrg   }
494ab47cfaaSmrg
495ab47cfaaSmrg   /* If shadow status is manually or automatically enabled, use a
496ab47cfaaSmrg    * page in system memory. */
497ab47cfaaSmrg   if ( psav->ShadowStatus ) {
498ab47cfaaSmrg       pSAVAGEDRIServer->status.size = 4096; /* 1 page */
499ab47cfaaSmrg
500ab47cfaaSmrg       if ( drmAddMap( psav->drmFD, 0, pSAVAGEDRIServer->status.size,
501ab47cfaaSmrg		       DRM_CONSISTENT, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL,
502ab47cfaaSmrg		       &pSAVAGEDRIServer->status.handle ) < 0 ) {
503ab47cfaaSmrg	   xf86DrvMsg( pScreen->myNum, X_ERROR,
504ab47cfaaSmrg		       "[drm] Could not add status page mapping\n" );
505ab47cfaaSmrg	   return FALSE;
506ab47cfaaSmrg       }
507ab47cfaaSmrg       xf86DrvMsg( pScreen->myNum, X_INFO,
508ab47cfaaSmrg		   "[drm] Status handle = 0x%08lx\n",
5095788ca14Smrg		   (unsigned long)pSAVAGEDRIServer->status.handle );
510ab47cfaaSmrg
511ab47cfaaSmrg       if ( drmMap( psav->drmFD,
512ab47cfaaSmrg		    pSAVAGEDRIServer->status.handle,
513ab47cfaaSmrg		    pSAVAGEDRIServer->status.size,
514ab47cfaaSmrg		    &pSAVAGEDRIServer->status.map ) < 0 ) {
515ab47cfaaSmrg	   xf86DrvMsg( pScreen->myNum, X_ERROR,
516ab47cfaaSmrg		       "[drm] Could not map status page\n" );
517ab47cfaaSmrg	   return FALSE;
518ab47cfaaSmrg       }
519ab47cfaaSmrg       xf86DrvMsg( pScreen->myNum, X_INFO,
520ab47cfaaSmrg		   "[drm] Status page mapped at 0x%08lx\n",
521ab47cfaaSmrg		   (unsigned long)pSAVAGEDRIServer->status.map );
522ab47cfaaSmrg
523ab47cfaaSmrg       psav->ShadowPhysical = pSAVAGEDRIServer->status.handle;
524ab47cfaaSmrg       psav->ShadowVirtual = pSAVAGEDRIServer->status.map;
525ab47cfaaSmrg   }
526ab47cfaaSmrg
527ab47cfaaSmrg   return TRUE;
528ab47cfaaSmrg}
529ab47cfaaSmrg
530ab47cfaaSmrgstatic Bool SAVAGEDRIBuffersInit( ScreenPtr pScreen )
531ab47cfaaSmrg{
5325788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
533ab47cfaaSmrg   SavagePtr psav = SAVPTR(pScrn);
534ab47cfaaSmrg   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
535ab47cfaaSmrg   int count;
536ab47cfaaSmrg
537ab47cfaaSmrg   if ( !psav->VertexDMA || psav->CommandDMA ) {
538ab47cfaaSmrg       /* At this point psav->CommandDMA == TRUE means that CommandDMA
539ab47cfaaSmrg	* allocation was actually successful. */
540ab47cfaaSmrg       psav->VertexDMA = FALSE;
541ab47cfaaSmrg       return TRUE;
542ab47cfaaSmrg   }
543ab47cfaaSmrg
544ab47cfaaSmrg   if ( psav->AgpDMA ) {
545ab47cfaaSmrg       count = drmAddBufs( psav->drmFD,
546ab47cfaaSmrg			   SAVAGE_NUM_BUFFERS, SAVAGE_BUFFER_SIZE,
547ab47cfaaSmrg			   DRM_AGP_BUFFER, pSAVAGEDRIServer->buffers.offset );
548ab47cfaaSmrg   } else {
549ab47cfaaSmrg       count = drmAddBufs( psav->drmFD,
550ab47cfaaSmrg			   SAVAGE_NUM_BUFFERS, SAVAGE_BUFFER_SIZE,
551ab47cfaaSmrg			   0, 0 );
552ab47cfaaSmrg   }
553ab47cfaaSmrg   if ( count <= 0 ) {
554ab47cfaaSmrg       xf86DrvMsg( pScrn->scrnIndex, X_INFO,
555ab47cfaaSmrg		   "[drm] failure adding %d %d byte DMA buffers (%d)\n",
556ab47cfaaSmrg		   SAVAGE_NUM_BUFFERS, SAVAGE_BUFFER_SIZE, count );
557ab47cfaaSmrg       return FALSE;
558ab47cfaaSmrg   }
559ab47cfaaSmrg   xf86DrvMsg( pScreen->myNum, X_INFO,
560ab47cfaaSmrg	       "[drm] Added %d %d byte DMA buffers\n",
561ab47cfaaSmrg	       count, SAVAGE_BUFFER_SIZE );
562ab47cfaaSmrg
563ab47cfaaSmrg   /* not needed in the server
564ab47cfaaSmrg   pSAVAGEDRIServer->drmBuffers = drmMapBufs( psav->drmFD );
565ab47cfaaSmrg   if ( !pSAVAGEDRIServer->drmBuffers ) {
566ab47cfaaSmrg	xf86DrvMsg( pScreen->myNum, X_ERROR,
567ab47cfaaSmrg		    "[drm] Failed to map DMA buffers list\n" );
568ab47cfaaSmrg	return FALSE;
569ab47cfaaSmrg    }
570ab47cfaaSmrg    xf86DrvMsg( pScreen->myNum, X_INFO,
571ab47cfaaSmrg		"[drm] Mapped %d DMA buffers\n",
572ab47cfaaSmrg		pSAVAGEDRIServer->drmBuffers->count );
573ab47cfaaSmrg   */
574ab47cfaaSmrg
575ab47cfaaSmrg    return TRUE;
576ab47cfaaSmrg}
577ab47cfaaSmrg
578ab47cfaaSmrgstatic Bool SAVAGEDRIKernelInit( ScreenPtr pScreen )
579ab47cfaaSmrg{
5805788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
581ab47cfaaSmrg   SavagePtr psav = SAVPTR(pScrn);
582ab47cfaaSmrg   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
583ab47cfaaSmrg   drmSAVAGEInit init;
584ab47cfaaSmrg   int ret;
585ab47cfaaSmrg
586ab47cfaaSmrg   memset( &init, 0, sizeof(drmSAVAGEInit) );
587ab47cfaaSmrg
588ab47cfaaSmrg   init.func = SAVAGE_INIT_BCI;
589ab47cfaaSmrg   init.sarea_priv_offset = sizeof(XF86DRISAREARec);
590ab47cfaaSmrg
591ab47cfaaSmrg   init.cob_size = psav->cobSize/4; /* size in 32-bit entries */
592ab47cfaaSmrg   init.bci_threshold_lo = psav->bciThresholdLo;
593ab47cfaaSmrg   init.bci_threshold_hi = psav->bciThresholdHi;
594ab47cfaaSmrg   init.dma_type = psav->AgpDMA ? SAVAGE_DMA_AGP : SAVAGE_DMA_PCI;
595ab47cfaaSmrg
596ab47cfaaSmrg   init.fb_bpp		= pScrn->bitsPerPixel;
597ab47cfaaSmrg   init.front_offset	= pSAVAGEDRIServer->frontOffset;
598ab47cfaaSmrg   init.front_pitch	= pSAVAGEDRIServer->frontPitch;
599ab47cfaaSmrg   init.back_offset	= pSAVAGEDRIServer->backOffset;
600ab47cfaaSmrg   init.back_pitch	= pSAVAGEDRIServer->backPitch;
601ab47cfaaSmrg
602ab47cfaaSmrg   init.depth_bpp	= pScrn->bitsPerPixel;
603ab47cfaaSmrg   init.depth_offset	= pSAVAGEDRIServer->depthOffset;
604ab47cfaaSmrg   init.depth_pitch	= pSAVAGEDRIServer->depthPitch;
605ab47cfaaSmrg
606ab47cfaaSmrg   init.texture_offset  = pSAVAGEDRIServer->textureOffset;
607ab47cfaaSmrg   init.texture_size    = pSAVAGEDRIServer->textureSize;
608ab47cfaaSmrg
609ab47cfaaSmrg   init.status_offset   = pSAVAGEDRIServer->status.handle;
610ab47cfaaSmrg   init.agp_textures_offset = pSAVAGEDRIServer->agpTextures.handle;
611ab47cfaaSmrg
612ab47cfaaSmrg   /* Savage4-based chips with DRM version >= 2.4 support command DMA,
613ab47cfaaSmrg    * which is preferred because it works with all vertex
614ab47cfaaSmrg    * formats. Command DMA and vertex DMA don't work at the same
615ab47cfaaSmrg    * time. */
616ab47cfaaSmrg   init.buffers_offset = 0;
617ab47cfaaSmrg   init.cmd_dma_offset = 0;
618ab47cfaaSmrg   if ( psav->CommandDMA )
619ab47cfaaSmrg       init.cmd_dma_offset = pSAVAGEDRIServer->cmdDma.handle;
620ab47cfaaSmrg   else if ( psav->VertexDMA )
621ab47cfaaSmrg       init.buffers_offset = pSAVAGEDRIServer->buffers.handle;
622ab47cfaaSmrg
623ab47cfaaSmrg   ret = drmCommandWrite( psav->drmFD, DRM_SAVAGE_BCI_INIT, &init, sizeof(init) );
624ab47cfaaSmrg   if ( ret < 0 ) {
625ab47cfaaSmrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
626ab47cfaaSmrg		  "[drm] Failed to initialize BCI! (%d)\n", ret );
627ab47cfaaSmrg      return FALSE;
628ab47cfaaSmrg   }
629ab47cfaaSmrg
630ab47cfaaSmrg   return TRUE;
631ab47cfaaSmrg}
632ab47cfaaSmrg
633ab47cfaaSmrgBool SAVAGEDRIScreenInit( ScreenPtr pScreen )
634ab47cfaaSmrg{
6355788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
636ab47cfaaSmrg   SavagePtr psav = SAVPTR(pScrn);
637ab47cfaaSmrg   DRIInfoPtr pDRIInfo;
638ab47cfaaSmrg   SAVAGEDRIPtr pSAVAGEDRI;
639ab47cfaaSmrg   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer;
640ab47cfaaSmrg
641c744f008Smrg   /* Check that the DRI, and DRM modules have been loaded by testing
642ab47cfaaSmrg    * for canonical symbols in each module.
643ab47cfaaSmrg    */
644ab47cfaaSmrg   if ( !xf86LoaderCheckSymbol( "drmAvailable" ) )		return FALSE;
645ab47cfaaSmrg   if ( !xf86LoaderCheckSymbol( "DRIQueryVersion" ) ) {
646ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
647ab47cfaaSmrg		  "[dri] SAVAGEDRIScreenInit failed (libdri.a too old)\n" );
648ab47cfaaSmrg      return FALSE;
649ab47cfaaSmrg   }
650ab47cfaaSmrg
651ab47cfaaSmrg   /* Check the DRI version */
652ab47cfaaSmrg   {
653ab47cfaaSmrg      int major, minor, patch;
654ab47cfaaSmrg      DRIQueryVersion( &major, &minor, &patch );
655ab47cfaaSmrg      if ( major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ) {
656ab47cfaaSmrg         xf86DrvMsg( pScreen->myNum, X_ERROR,
657ab47cfaaSmrg		     "[dri] SAVAGEDRIScreenInit failed because of a version mismatch.\n"
658ab47cfaaSmrg		     "[dri] libdri version = %d.%d.%d but version %d.%d.x is needed.\n"
659ab47cfaaSmrg		     "[dri] Disabling the DRI.\n",
660ab47cfaaSmrg		     major, minor, patch,
661ab47cfaaSmrg                     DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION );
662ab47cfaaSmrg         return FALSE;
663ab47cfaaSmrg      }
664ab47cfaaSmrg   }
665ab47cfaaSmrg
666ab47cfaaSmrg   xf86DrvMsg( pScreen->myNum, X_INFO,
667ab47cfaaSmrg	       "[drm] bpp: %d depth: %d\n",
668ab47cfaaSmrg	       pScrn->bitsPerPixel, pScrn->depth );
669ab47cfaaSmrg
670ab47cfaaSmrg   if ( (pScrn->bitsPerPixel / 8) != 2 &&
671ab47cfaaSmrg	(pScrn->bitsPerPixel / 8) != 4 ) {
672ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
673ab47cfaaSmrg		  "[dri] Direct rendering only supported in 16 and 32 bpp modes\n" );
674ab47cfaaSmrg      return FALSE;
675ab47cfaaSmrg   }
676ab47cfaaSmrg
677ab47cfaaSmrg   pDRIInfo = DRICreateInfoRec();
678ab47cfaaSmrg   if ( !pDRIInfo ) {
679ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
680ab47cfaaSmrg		  "[dri] DRICreateInfoRec() failed\n" );
681ab47cfaaSmrg      return FALSE;
682ab47cfaaSmrg   }
683ab47cfaaSmrg   psav->pDRIInfo = pDRIInfo;
684ab47cfaaSmrg
685ab47cfaaSmrg   pDRIInfo->drmDriverName = SAVAGEKernelDriverName;
686ab47cfaaSmrg   pDRIInfo->clientDriverName = SAVAGEClientDriverName;
687ab47cfaaSmrg   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
688ab47cfaaSmrg      pDRIInfo->busIdString = DRICreatePCIBusID(psav->PciInfo);
689ab47cfaaSmrg   } else {
6905788ca14Smrg      pDRIInfo->busIdString            = malloc(64);
691ab47cfaaSmrg      sprintf(pDRIInfo->busIdString,
692ab47cfaaSmrg              "PCI:%d:%d:%d",
693ab47cfaaSmrg              psav->PciInfo->bus,
6948697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
6958697ee19Smrg              psav->PciInfo->dev,
6968697ee19Smrg#else
697ab47cfaaSmrg              psav->PciInfo->device,
6988697ee19Smrg#endif
699ab47cfaaSmrg              psav->PciInfo->func);
700ab47cfaaSmrg   }
701ab47cfaaSmrg   pDRIInfo->ddxDriverMajorVersion = SAVAGE_VERSION_MAJOR;
702ab47cfaaSmrg   pDRIInfo->ddxDriverMinorVersion = SAVAGE_VERSION_MINOR;
703ab47cfaaSmrg   pDRIInfo->ddxDriverPatchVersion = SAVAGE_PATCHLEVEL;
704ab47cfaaSmrg
7052c9fd100Smrg   pDRIInfo->frameBufferPhysicalAddress = (pointer)(uintptr_t) psav->FbRegion.base;
706ab47cfaaSmrg   pDRIInfo->frameBufferSize = psav->videoRambytes;
707ab47cfaaSmrg   pDRIInfo->frameBufferStride = pScrn->displayWidth*(pScrn->bitsPerPixel/8);
708ab47cfaaSmrg   pDRIInfo->ddxDrawableTableEntry = SAVAGE_MAX_DRAWABLES;
709ab47cfaaSmrg
710ab47cfaaSmrg   /* override default DRI block and wakeup handler */
711ab47cfaaSmrg   psav->coreBlockHandler = pDRIInfo->wrap.BlockHandler;
712ab47cfaaSmrg   pDRIInfo->wrap.BlockHandler = SAVAGEBlockHandler;
713ab47cfaaSmrg   psav->coreWakeupHandler = pDRIInfo->wrap.WakeupHandler;
714ab47cfaaSmrg   pDRIInfo->wrap.WakeupHandler = SAVAGEWakeupHandler;
715ab47cfaaSmrg
716ab47cfaaSmrg   pDRIInfo->createDummyCtx = TRUE;
717ab47cfaaSmrg   pDRIInfo->createDummyCtxPriv = FALSE;
718ab47cfaaSmrg
719ab47cfaaSmrg   if ( SAREA_MAX_DRAWABLES < SAVAGE_MAX_DRAWABLES ) {
720ab47cfaaSmrg      pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
721ab47cfaaSmrg   } else {
722ab47cfaaSmrg      pDRIInfo->maxDrawableTableEntry = SAVAGE_MAX_DRAWABLES;
723ab47cfaaSmrg   }
724ab47cfaaSmrg
725ab47cfaaSmrg   /* For now the mapping works by using a fixed size defined
726ab47cfaaSmrg    * in the SAREA header.
727ab47cfaaSmrg    */
728ab47cfaaSmrg   if ( sizeof(XF86DRISAREARec) + sizeof(SAVAGESAREAPrivRec) > SAREA_MAX ) {
729ab47cfaaSmrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
730ab47cfaaSmrg		  "[drm] Data does not fit in SAREA\n" );
731ab47cfaaSmrg      return FALSE;
732ab47cfaaSmrg   }
733ab47cfaaSmrg
734ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO,
735ab47cfaaSmrg	       "[drm] Sarea %d+%d: %d\n",
736c744f008Smrg	       (int) sizeof(XF86DRISAREARec), (int) sizeof(SAVAGESAREAPrivRec),
737c744f008Smrg	       (int) (sizeof(XF86DRISAREARec) + sizeof(SAVAGESAREAPrivRec)) );
738ab47cfaaSmrg
739ab47cfaaSmrg   pDRIInfo->SAREASize = SAREA_MAX;
740ab47cfaaSmrg
7415788ca14Smrg   pSAVAGEDRI = (SAVAGEDRIPtr)calloc( sizeof(SAVAGEDRIRec), 1 );
742ab47cfaaSmrg   if ( !pSAVAGEDRI ) {
743ab47cfaaSmrg      DRIDestroyInfoRec( psav->pDRIInfo );
744ab47cfaaSmrg      psav->pDRIInfo = 0;
745ab47cfaaSmrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
746ab47cfaaSmrg		  "[drm] Failed to allocate memory for private record\n" );
747ab47cfaaSmrg      return FALSE;
748ab47cfaaSmrg   }
749ab47cfaaSmrg
750ab47cfaaSmrg   pSAVAGEDRIServer = (SAVAGEDRIServerPrivatePtr)
7515788ca14Smrg      calloc( sizeof(SAVAGEDRIServerPrivateRec), 1 );
752ab47cfaaSmrg   if ( !pSAVAGEDRIServer ) {
7535788ca14Smrg      free( pSAVAGEDRI );
754ab47cfaaSmrg      DRIDestroyInfoRec( psav->pDRIInfo );
755ab47cfaaSmrg      psav->pDRIInfo = 0;
756ab47cfaaSmrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
757ab47cfaaSmrg		  "[drm] Failed to allocate memory for private record\n" );
758ab47cfaaSmrg      return FALSE;
759ab47cfaaSmrg   }
760ab47cfaaSmrg   psav->DRIServerInfo = pSAVAGEDRIServer;
761ab47cfaaSmrg
762ab47cfaaSmrg   pDRIInfo->devPrivate = pSAVAGEDRI;
763ab47cfaaSmrg   pDRIInfo->devPrivateSize = sizeof(SAVAGEDRIRec);
764ab47cfaaSmrg   pDRIInfo->contextSize = sizeof(SAVAGEDRIContextRec);
765ab47cfaaSmrg
766ab47cfaaSmrg   pDRIInfo->CreateContext = SAVAGECreateContext;
767ab47cfaaSmrg   pDRIInfo->DestroyContext = SAVAGEDestroyContext;
768ab47cfaaSmrg
769ab47cfaaSmrg   /* FK: SwapContext is not used with KERNEL_SWAP. */
770ab47cfaaSmrg   pDRIInfo->SwapContext = NULL;
771ab47cfaaSmrg
772ab47cfaaSmrg   pDRIInfo->InitBuffers = SAVAGEDRIInitBuffers;
773ab47cfaaSmrg   pDRIInfo->MoveBuffers = SAVAGEDRIMoveBuffers;
774ab47cfaaSmrg   pDRIInfo->OpenFullScreen = SAVAGEDRIOpenFullScreen;
775ab47cfaaSmrg   pDRIInfo->CloseFullScreen = SAVAGEDRICloseFullScreen;
776ab47cfaaSmrg   pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
777ab47cfaaSmrg
778ab47cfaaSmrg   if ( !DRIScreenInit( pScreen, pDRIInfo, &psav->drmFD ) ) {
7795788ca14Smrg      free( pSAVAGEDRIServer );
780ab47cfaaSmrg      psav->DRIServerInfo = 0;
7815788ca14Smrg      free( pDRIInfo->devPrivate );
782ab47cfaaSmrg      pDRIInfo->devPrivate = 0;
783ab47cfaaSmrg      DRIDestroyInfoRec( psav->pDRIInfo );
784ab47cfaaSmrg      psav->pDRIInfo = 0;
785ab47cfaaSmrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
786ab47cfaaSmrg		  "[drm] DRIScreenInit failed.  Disabling DRI.\n" );
787ab47cfaaSmrg      return FALSE;
788ab47cfaaSmrg   }
789ab47cfaaSmrg
790ab47cfaaSmrg   /* Check the SAVAGE DRM version */
791ab47cfaaSmrg   {
792ab47cfaaSmrg      drmVersionPtr version = drmGetVersion(psav->drmFD);
793ab47cfaaSmrg      if ( version ) {
794ab47cfaaSmrg         if ( version->version_major != 2 ||
795ab47cfaaSmrg	      version->version_minor < 0 ) {
796ab47cfaaSmrg            /* incompatible drm version */
797ab47cfaaSmrg            xf86DrvMsg( pScreen->myNum, X_ERROR,
798ab47cfaaSmrg			"[dri] SAVAGEDRIScreenInit failed because of a version mismatch.\n"
799ab47cfaaSmrg			"[dri] savage.ko kernel module version is %d.%d.%d but version 2.0.x is needed.\n"
800ab47cfaaSmrg			"[dri] Disabling DRI.\n",
801ab47cfaaSmrg			version->version_major,
802ab47cfaaSmrg			version->version_minor,
803ab47cfaaSmrg			version->version_patchlevel );
804ab47cfaaSmrg            drmFreeVersion( version );
805ab47cfaaSmrg	    SAVAGEDRICloseScreen( pScreen );		/* FIXME: ??? */
806ab47cfaaSmrg            return FALSE;
807ab47cfaaSmrg         }
808ab47cfaaSmrg	 if ( psav->CommandDMA && version->version_minor < 4 ) {
809ab47cfaaSmrg	    xf86DrvMsg( pScreen->myNum, X_WARNING,
810ab47cfaaSmrg			"[drm] DRM version < 2.4.0 does not support command DMA.\n");
811ab47cfaaSmrg	    psav->CommandDMA = FALSE;
812ab47cfaaSmrg	 }
813ab47cfaaSmrg	 if ( !psav->VertexDMA && version->version_minor < 4 ) {
814ab47cfaaSmrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
815ab47cfaaSmrg			"[drm] DRM version < 2.4.0 requires vertex DMA.\n");
816ab47cfaaSmrg	    drmFreeVersion( version );
817ab47cfaaSmrg	    SAVAGEDRICloseScreen( pScreen );
818ab47cfaaSmrg	    return FALSE;
819ab47cfaaSmrg	 }
820ab47cfaaSmrg         drmFreeVersion( version );
821ab47cfaaSmrg      }
822ab47cfaaSmrg   }
823ab47cfaaSmrg
824ab47cfaaSmrg   if ( !psav->IsPCI && !SAVAGEDRIAgpInit( pScreen ) ) {
825ab47cfaaSmrg       if (pSAVAGEDRIServer->agp.handle != 0) {
826ab47cfaaSmrg	   /* AGP initialization succeeded, but adding AGP mappings failed. */
827ab47cfaaSmrg	   SAVAGEDRICloseScreen( pScreen );
828ab47cfaaSmrg	   return FALSE;
829ab47cfaaSmrg       }
830ab47cfaaSmrg       /* AGP initialization failed, fall back to PCI mode. */
831ab47cfaaSmrg       psav->IsPCI = TRUE;
832ab47cfaaSmrg       psav->AgpDMA = FALSE;
833ab47cfaaSmrg       xf86DrvMsg( pScrn->scrnIndex, X_WARNING,
834ab47cfaaSmrg		   "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
835ab47cfaaSmrg       xf86DrvMsg( pScrn->scrnIndex, X_WARNING,
836ab47cfaaSmrg		   "[agp] Make sure you have the agpgart kernel module loaded.\n");
837ab47cfaaSmrg   }
838ab47cfaaSmrg
839ab47cfaaSmrg   if ( !SAVAGEDRIMapInit( pScreen ) ) {
840ab47cfaaSmrg      SAVAGEDRICloseScreen( pScreen );
841ab47cfaaSmrg      return FALSE;
842ab47cfaaSmrg   }
843ab47cfaaSmrg
8445788ca14Smrg   /* Linux kernel DRM broken in 2.6.30 through 2.6.39 */
8455788ca14Smrg   if (pDRIInfo->hFrameBuffer == pSAVAGEDRIServer->aperture.handle)
8465788ca14Smrg       xf86DrvMsg( pScrn->scrnIndex, X_WARNING,
8475788ca14Smrg		   "[drm] Detected broken drm maps. Please upgrade to linux kernel 3.x\n");
8485788ca14Smrg
849ab47cfaaSmrg   if ( !SAVAGEDRIBuffersInit( pScreen ) ) {
850ab47cfaaSmrg      SAVAGEDRICloseScreen( pScreen );
851ab47cfaaSmrg      return FALSE;
852ab47cfaaSmrg   }
853ab47cfaaSmrg
854ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n" );
855ab47cfaaSmrg
856ab47cfaaSmrg   return TRUE;
857ab47cfaaSmrg}
858ab47cfaaSmrg
8595788ca14Smrgstatic void SAVAGEDRISetupTiledSurfaceRegs( SavagePtr psav )
8605788ca14Smrg{
8615788ca14Smrg      SAVAGEDRIPtr pSAVAGEDRI = (SAVAGEDRIPtr)psav->pDRIInfo->devPrivate;
8625788ca14Smrg      unsigned int value = 0;
8635788ca14Smrg
8645788ca14Smrg      OUTREG(0x850C,(INREG(0x850C) | 0x00008000)); /* AGD: I don't think this does anything on 3D/MX/IX */
8655788ca14Smrg						   /* maybe savage4 too... */
8665788ca14Smrg      /* we don't use Y range flag,so comment it */
8675788ca14Smrg      /*
8685788ca14Smrg        if(pSAVAGEDRI->width <= 1024)
8695788ca14Smrg            value |= (1<<29);
8705788ca14Smrg      */
8715788ca14Smrg      if ((psav->Chipset == S3_SAVAGE_MX) /* 3D/MX/IX seem to set up the tile stride differently */
8725788ca14Smrg	|| (psav->Chipset == S3_SAVAGE3D)) {
8735788ca14Smrg      	    if(pSAVAGEDRI->cpp == 2)
8745788ca14Smrg      	    {
8755788ca14Smrg         	value |=  ((psav->lDelta / 4) >> 5) << 24;
8765788ca14Smrg         	value |= 2<<30;
8775788ca14Smrg      	    } else {
8785788ca14Smrg         	value |=  ((psav->lDelta / 4) >> 5) << 24;
8795788ca14Smrg         	value |= 3<<30;
8805788ca14Smrg      	    }
8815788ca14Smrg
8825788ca14Smrg	    OUTREG(TILED_SURFACE_REGISTER_0, value|(pSAVAGEDRI->frontOffset) ); /* front */
8835788ca14Smrg	    OUTREG(TILED_SURFACE_REGISTER_1, value|(pSAVAGEDRI->backOffset) ); /* back  */
8845788ca14Smrg	    OUTREG(TILED_SURFACE_REGISTER_2, value|(pSAVAGEDRI->depthOffset) ); /* depth */
8855788ca14Smrg      } else {
8865788ca14Smrg	    int offset_shift = 5;
8875788ca14Smrg      	    if(pSAVAGEDRI->cpp == 2)
8885788ca14Smrg      	    {
8895788ca14Smrg         	value |=  (((pSAVAGEDRI->width + 0x3F) & 0xFFC0) >> 6) << 20;
8905788ca14Smrg         	value |= 2<<30;
8915788ca14Smrg      	    } else {
8925788ca14Smrg         	value |=  (((pSAVAGEDRI->width + 0x1F) & 0xFFE0) >> 5) << 20;
8935788ca14Smrg         	value |= 3<<30;
8945788ca14Smrg      	    }
8955788ca14Smrg	    if (psav->Chipset == S3_SUPERSAVAGE) /* supersavages have a different shift */
8965788ca14Smrg		offset_shift = 6;
8975788ca14Smrg	    OUTREG(TILED_SURFACE_REGISTER_0, value|(pSAVAGEDRI->frontOffset >> offset_shift) ); /* front */
8985788ca14Smrg	    OUTREG(TILED_SURFACE_REGISTER_1, value|(pSAVAGEDRI->backOffset >> offset_shift) ); /* back  */
8995788ca14Smrg	    OUTREG(TILED_SURFACE_REGISTER_2, value|(pSAVAGEDRI->depthOffset >> offset_shift) ); /* depth */
9005788ca14Smrg      }
9015788ca14Smrg}
902ab47cfaaSmrg
903ab47cfaaSmrgBool SAVAGEDRIFinishScreenInit( ScreenPtr pScreen )
904ab47cfaaSmrg{
9055788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
906ab47cfaaSmrg   SavagePtr psav = SAVPTR(pScrn);
907ab47cfaaSmrg   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
908ab47cfaaSmrg   SAVAGEDRIPtr pSAVAGEDRI = (SAVAGEDRIPtr)psav->pDRIInfo->devPrivate;
909ab47cfaaSmrg   int i;
910ab47cfaaSmrg
911ab47cfaaSmrg   if ( !psav->pDRIInfo )
912ab47cfaaSmrg      return FALSE;
913ab47cfaaSmrg
914ab47cfaaSmrg   psav->pDRIInfo->driverSwapMethod = DRI_KERNEL_SWAP;
915ab47cfaaSmrg
916ab47cfaaSmrg   /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
917ab47cfaaSmrg    * because *DRIKernelInit requires that the hardware lock is held by
918ab47cfaaSmrg    * the X server, and the first time the hardware lock is grabbed is
919ab47cfaaSmrg    * in DRIFinishScreenInit.
920ab47cfaaSmrg    */
921ab47cfaaSmrg   if ( !DRIFinishScreenInit( pScreen ) ) {
922ab47cfaaSmrg      SAVAGEDRICloseScreen( pScreen );
923ab47cfaaSmrg      return FALSE;
924ab47cfaaSmrg   }
925ab47cfaaSmrg   psav->LockHeld = 1;
926ab47cfaaSmrg
927ab47cfaaSmrg   if ( !SAVAGEDRIKernelInit( pScreen ) ) {
928ab47cfaaSmrg      SAVAGEDRICloseScreen( pScreen );
929ab47cfaaSmrg      return FALSE;
930ab47cfaaSmrg   }
931ab47cfaaSmrg
932ab47cfaaSmrg   pSAVAGEDRI->chipset          = psav->Chipset;
933ab47cfaaSmrg   pSAVAGEDRI->width		= pScrn->virtualX;
934ab47cfaaSmrg   pSAVAGEDRI->height		= pScrn->virtualY;
935ab47cfaaSmrg   pSAVAGEDRI->mem		= pScrn->videoRam * 1024;
936ab47cfaaSmrg   pSAVAGEDRI->cpp		= pScrn->bitsPerPixel / 8;
937ab47cfaaSmrg   pSAVAGEDRI->zpp		= pSAVAGEDRI->cpp;
938ab47cfaaSmrg
939ab47cfaaSmrg   pSAVAGEDRI->agpMode		= psav->IsPCI ? 0 : psav->agpMode;
940ab47cfaaSmrg
941ab47cfaaSmrg   pSAVAGEDRI->bufferSize       = SAVAGE_BUFFER_SIZE;
942ab47cfaaSmrg
943ab47cfaaSmrg   pSAVAGEDRI->frontOffset		= pSAVAGEDRIServer->frontOffset;
944ab47cfaaSmrg   pSAVAGEDRI->frontbufferSize		= pSAVAGEDRIServer->frontbufferSize;
945ab47cfaaSmrg
946ab47cfaaSmrg   pSAVAGEDRI->backOffset		= pSAVAGEDRIServer->backOffset;
947ab47cfaaSmrg   pSAVAGEDRI->backbufferSize		= pSAVAGEDRIServer->backbufferSize;
948ab47cfaaSmrg
949ab47cfaaSmrg   pSAVAGEDRI->depthOffset		= pSAVAGEDRIServer->depthOffset;
950ab47cfaaSmrg   pSAVAGEDRI->depthbufferSize		= pSAVAGEDRIServer->depthbufferSize;
951ab47cfaaSmrg
952ab47cfaaSmrg   pSAVAGEDRI->textureOffset	= pSAVAGEDRIServer->textureOffset;
953ab47cfaaSmrg
954ab47cfaaSmrg   i = mylog2( pSAVAGEDRIServer->textureSize / SAVAGE_NR_TEX_REGIONS );
955ab47cfaaSmrg   if ( i < SAVAGE_LOG_MIN_TEX_REGION_SIZE )
956ab47cfaaSmrg      i = SAVAGE_LOG_MIN_TEX_REGION_SIZE;
957ab47cfaaSmrg
958ab47cfaaSmrg   pSAVAGEDRI->logTextureGranularity = i;
959ab47cfaaSmrg   pSAVAGEDRI->textureSize = (pSAVAGEDRIServer->textureSize >> i) << i; /* truncate */
960ab47cfaaSmrg
961ab47cfaaSmrg   pSAVAGEDRI->agpTextureHandle = pSAVAGEDRIServer->agpTextures.handle;
962ab47cfaaSmrg
963ab47cfaaSmrg   i = mylog2( pSAVAGEDRIServer->agpTextures.size / SAVAGE_NR_TEX_REGIONS );
964ab47cfaaSmrg   if ( i < SAVAGE_LOG_MIN_TEX_REGION_SIZE )
965ab47cfaaSmrg      i = SAVAGE_LOG_MIN_TEX_REGION_SIZE;
966ab47cfaaSmrg
967ab47cfaaSmrg   pSAVAGEDRI->logAgpTextureGranularity = i;
968ab47cfaaSmrg   pSAVAGEDRI->agpTextureSize = (pSAVAGEDRIServer->agpTextures.size >> i) << i; /* truncate */
969ab47cfaaSmrg
970ab47cfaaSmrg   pSAVAGEDRI->apertureHandle	= pSAVAGEDRIServer->aperture.handle;
971ab47cfaaSmrg   pSAVAGEDRI->apertureSize	= pSAVAGEDRIServer->aperture.size;
9728697ee19Smrg   pSAVAGEDRI->aperturePitch    = psav->ulAperturePitch;
973ab47cfaaSmrg
974ab47cfaaSmrg   pSAVAGEDRI->statusHandle	= pSAVAGEDRIServer->status.handle;
975ab47cfaaSmrg   pSAVAGEDRI->statusSize	= pSAVAGEDRIServer->status.size;
976ab47cfaaSmrg
977ab47cfaaSmrg   pSAVAGEDRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
978ab47cfaaSmrg
979ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]pSAVAGEDRIServer:\n" );
980ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	reserved_map_agpstart:0x%08x\n",pSAVAGEDRIServer->reserved_map_agpstart);
981ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	reserved_map_idx:0x%08x\n",pSAVAGEDRIServer->reserved_map_idx);
982ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	sarea_priv_offset:0x%08x\n",pSAVAGEDRIServer->sarea_priv_offset);
983ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	chipset:0x%08x\n",pSAVAGEDRIServer->chipset);
984ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	sgram:0x%08x\n",pSAVAGEDRIServer->sgram);
985ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontbufferSize:0x%08x\n",pSAVAGEDRIServer->frontbufferSize);
986ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontOffset:0x%08x\n",pSAVAGEDRIServer->frontOffset);
987ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontPitch:0x%08x\n",pSAVAGEDRIServer->frontPitch);
988ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backbufferSize:0x%08x\n",pSAVAGEDRIServer->backbufferSize);
989ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backOffset:0x%08x\n",pSAVAGEDRIServer->backOffset);
990ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backPitch:0x%08x\n",pSAVAGEDRIServer->backPitch);
991ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthbufferSize:0x%08x\n",pSAVAGEDRIServer->depthbufferSize);
992ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthOffset:0x%08x\n",pSAVAGEDRIServer->depthOffset);
993ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthPitch:0x%08x\n",pSAVAGEDRIServer->depthPitch);
994ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureOffset:0x%08x\n",pSAVAGEDRIServer->textureOffset);
995ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureSize:0x%08x\n",pSAVAGEDRIServer->textureSize);
996ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureSize:0x%08x\n",pSAVAGEDRIServer->textureSize);
997ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	logTextureGranularity:0x%08x\n",pSAVAGEDRIServer->logTextureGranularity);
998ab47cfaaSmrg
9995788ca14Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agp:handle:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->agp.handle);
1000ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agp:offset:0x%08x\n",pSAVAGEDRIServer->agp.offset);
1001ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agp:size:0x%08x\n",pSAVAGEDRIServer->agp.size);
1002ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agp:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->agp.map);
1003ab47cfaaSmrg
10045788ca14Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	registers:handle:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->registers.handle);
1005ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	registers:offset:0x%08x\n",pSAVAGEDRIServer->registers.offset);
1006ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	registers:size:0x%08x\n",pSAVAGEDRIServer->registers.size);
1007ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	registers:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->registers.map);
1008ab47cfaaSmrg
10095788ca14Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	status:handle:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->status.handle);
1010ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	status:offset:0x%08x\n",pSAVAGEDRIServer->status.offset);
1011ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	status:size:0x%08x\n",pSAVAGEDRIServer->status.size);
1012ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	status:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->status.map);
1013ab47cfaaSmrg
10145788ca14Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextures:handle:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->agpTextures.handle);
1015ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextures:offset:0x%08x\n",pSAVAGEDRIServer->agpTextures.offset);
1016ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextures:size:0x%08x\n",pSAVAGEDRIServer->agpTextures.size);
1017ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	apgTextures:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->agpTextures.map);
1018ab47cfaaSmrg
1019ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	logAgpTextureGranularity:0x%08x\n",pSAVAGEDRIServer->logAgpTextureGranularity);
1020ab47cfaaSmrg
10215788ca14Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cmdDma:handle:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->cmdDma.handle);
1022ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cmdDma:offset:0x%08x\n",pSAVAGEDRIServer->cmdDma.offset);
1023ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cmdDma:size:0x%08x\n",pSAVAGEDRIServer->cmdDma.size);
1024ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cmdDma:map:0x%08lx\n",(unsigned long)pSAVAGEDRIServer->cmdDma.map);
1025ab47cfaaSmrg
1026ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]pSAVAGEDRI:\n" );
1027ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	chipset:0x%08x\n",pSAVAGEDRI->chipset );
1028ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	width:0x%08x\n",pSAVAGEDRI->width );
1029ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	height:0x%08x\n",pSAVAGEDRI->height );
1030ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	mem:0x%08x\n",pSAVAGEDRI->mem );
1031ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	cpp:%d\n",pSAVAGEDRI->cpp );
1032ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	zpp:%d\n",pSAVAGEDRI->zpp );
1033ab47cfaaSmrg
1034ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpMode:%d\n",pSAVAGEDRI->agpMode );
1035ab47cfaaSmrg
1036ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	bufferSize:%u\n",pSAVAGEDRI->bufferSize );
1037ab47cfaaSmrg
1038ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontbufferSize:0x%08x\n",pSAVAGEDRI->frontbufferSize);
1039ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	frontOffset:0x%08x\n",pSAVAGEDRI->frontOffset );
1040ab47cfaaSmrg
1041ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backbufferSize:0x%08x\n",pSAVAGEDRI->backbufferSize);
1042ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	backOffset:0x%08x\n",pSAVAGEDRI->backOffset );
1043ab47cfaaSmrg
1044ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthbufferSize:0x%08x\n",pSAVAGEDRI->depthbufferSize);
1045ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	depthOffset:0x%08x\n",pSAVAGEDRI->depthOffset );
1046ab47cfaaSmrg
1047ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureOffset:0x%08x\n",pSAVAGEDRI->textureOffset );
1048ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	textureSize:0x%08x\n",pSAVAGEDRI->textureSize );
1049ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	logTextureGranularity:0x%08x\n",pSAVAGEDRI->logTextureGranularity );
1050ab47cfaaSmrg
10515788ca14Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextureHandle:0x%08lx\n",(unsigned long)pSAVAGEDRI->agpTextureHandle );
1052ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	agpTextureSize:0x%08x\n",pSAVAGEDRI->agpTextureSize );
1053ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	logAgpTextureGranularity:0x%08x\n",pSAVAGEDRI->logAgpTextureGranularity );
1054ab47cfaaSmrg
10555788ca14Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	apertureHandle:0x%08lx\n",(unsigned long)pSAVAGEDRI->apertureHandle);
1056ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	apertureSize:0x%08x\n",pSAVAGEDRI->apertureSize);
1057ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	aperturePitch:0x%08x\n",pSAVAGEDRI->aperturePitch);
1058ab47cfaaSmrg
10595788ca14Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	statusHandle:0x%08lx\n",(unsigned long)pSAVAGEDRI->statusHandle);
1060ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	statusSize:0x%08x\n",pSAVAGEDRI->statusSize);
1061ab47cfaaSmrg
1062ab47cfaaSmrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[junkers]	sarea_priv_offset:0x%08x\n",pSAVAGEDRI->sarea_priv_offset);
1063ab47cfaaSmrg
10645788ca14Smrg   SAVAGEDRISetupTiledSurfaceRegs( psav );
1065ab47cfaaSmrg   return TRUE;
1066ab47cfaaSmrg}
1067ab47cfaaSmrg
10685788ca14Smrgvoid SAVAGEDRIResume(ScreenPtr pScreen)
10695788ca14Smrg{
10705788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
10715788ca14Smrg   SavagePtr psav = SAVPTR(pScrn);
10725788ca14Smrg   SAVAGESAREAPrivPtr pSAREAPriv =
10735788ca14Smrg			(SAVAGESAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
10745788ca14Smrg
10755788ca14Smrg   if (!psav->IsPCI) {
10765788ca14Smrg	SAVAGESetAgpMode(psav, pScreen);
10775788ca14Smrg   }
10785788ca14Smrg   SAVAGEDRISetupTiledSurfaceRegs(psav);
10795788ca14Smrg   /* Assume that 3D state was clobbered, invalidate it by
10805788ca14Smrg    * changing ctxOwner in the sarea. */
10815788ca14Smrg   pSAREAPriv->ctxOwner = DRIGetContext(pScreen);
10825788ca14Smrg}
1083ab47cfaaSmrg
1084ab47cfaaSmrgvoid SAVAGEDRICloseScreen( ScreenPtr pScreen )
1085ab47cfaaSmrg{
10865788ca14Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1087ab47cfaaSmrg   SavagePtr psav = SAVPTR(pScrn);
1088ab47cfaaSmrg   SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
1089ab47cfaaSmrg
1090ab47cfaaSmrg   if ( pSAVAGEDRIServer->status.map ) {
1091ab47cfaaSmrg      drmUnmap( pSAVAGEDRIServer->status.map, pSAVAGEDRIServer->status.size );
1092ab47cfaaSmrg      pSAVAGEDRIServer->status.map = NULL;
1093ab47cfaaSmrg   }
1094ab47cfaaSmrg
1095ab47cfaaSmrg   if ( pSAVAGEDRIServer->registers.map ) {
1096ab47cfaaSmrg      drmUnmap( pSAVAGEDRIServer->registers.map, pSAVAGEDRIServer->registers.size );
1097ab47cfaaSmrg      pSAVAGEDRIServer->registers.map = NULL;
1098ab47cfaaSmrg   }
1099ab47cfaaSmrg
1100ab47cfaaSmrg   if ( pSAVAGEDRIServer->aperture.map ) {
1101ab47cfaaSmrg      drmUnmap( pSAVAGEDRIServer->aperture.map, pSAVAGEDRIServer->aperture.size );
1102ab47cfaaSmrg      pSAVAGEDRIServer->aperture.map = NULL;
1103ab47cfaaSmrg   }
1104ab47cfaaSmrg
11051c79cd07Smrg   if ( pSAVAGEDRIServer->agpXVideo.map ) {
11061c79cd07Smrg      drmUnmap( pSAVAGEDRIServer->agpXVideo.map,
11071c79cd07Smrg                pSAVAGEDRIServer->agpXVideo.size );
11081c79cd07Smrg      pSAVAGEDRIServer->agpXVideo.map = NULL;
11091c79cd07Smrg   }
11101c79cd07Smrg
1111ab47cfaaSmrg   if ( pSAVAGEDRIServer->agpTextures.map ) {
1112ab47cfaaSmrg      drmUnmap( pSAVAGEDRIServer->agpTextures.map,
1113ab47cfaaSmrg                pSAVAGEDRIServer->agpTextures.size );
1114ab47cfaaSmrg      pSAVAGEDRIServer->agpTextures.map = NULL;
1115ab47cfaaSmrg   }
1116ab47cfaaSmrg
1117ab47cfaaSmrg   if (pSAVAGEDRIServer->status.handle)
1118ab47cfaaSmrg       drmRmMap(psav->drmFD,pSAVAGEDRIServer->status.handle);
1119ab47cfaaSmrg
1120ab47cfaaSmrg   if (pSAVAGEDRIServer->registers.handle)
1121ab47cfaaSmrg       drmRmMap(psav->drmFD,pSAVAGEDRIServer->registers.handle);
1122ab47cfaaSmrg
1123ab47cfaaSmrg   if (pSAVAGEDRIServer->aperture.handle)
1124ab47cfaaSmrg       drmRmMap(psav->drmFD,pSAVAGEDRIServer->registers.handle);
1125ab47cfaaSmrg
11261c79cd07Smrg   if (pSAVAGEDRIServer->agpXVideo.handle)
11271c79cd07Smrg       drmRmMap(psav->drmFD,pSAVAGEDRIServer->agpXVideo.handle);
11281c79cd07Smrg
1129ab47cfaaSmrg   if (pSAVAGEDRIServer->agpTextures.handle)
1130ab47cfaaSmrg       drmRmMap(psav->drmFD,pSAVAGEDRIServer->agpTextures.handle);
1131ab47cfaaSmrg
1132ab47cfaaSmrg   if (pSAVAGEDRIServer->cmdDma.handle)
1133ab47cfaaSmrg       drmRmMap(psav->drmFD,pSAVAGEDRIServer->cmdDma.handle);
1134ab47cfaaSmrg
1135ab47cfaaSmrg   if ( pSAVAGEDRIServer->buffers.map ) {
1136ab47cfaaSmrg      drmUnmap( pSAVAGEDRIServer->buffers.map, pSAVAGEDRIServer->buffers.size );
1137ab47cfaaSmrg      pSAVAGEDRIServer->buffers.map = NULL;
1138ab47cfaaSmrg   }
1139ab47cfaaSmrg
1140ab47cfaaSmrg   if ( pSAVAGEDRIServer->agp.handle ) {
1141ab47cfaaSmrg      drmAgpUnbind( psav->drmFD, pSAVAGEDRIServer->agp.handle );
1142ab47cfaaSmrg      drmAgpFree( psav->drmFD, pSAVAGEDRIServer->agp.handle );
1143ab47cfaaSmrg      pSAVAGEDRIServer->agp.handle = 0;
1144ab47cfaaSmrg      drmAgpRelease( psav->drmFD );
1145ab47cfaaSmrg   }
1146ab47cfaaSmrg
1147ab47cfaaSmrg   DRICloseScreen( pScreen );
1148ab47cfaaSmrg
1149ab47cfaaSmrg   /* Don't use shadow status any more. If this happens due to failed
1150ab47cfaaSmrg    * DRI initialization then SavageScreenInit will do the real
1151ab47cfaaSmrg    * cleanup and restore ShadowStatus to sane settings. */
1152ab47cfaaSmrg   psav->ShadowVirtual = NULL;
1153ab47cfaaSmrg   psav->ShadowPhysical = 0;
1154ab47cfaaSmrg
1155ab47cfaaSmrg   if(psav->reserved)
1156ab47cfaaSmrg      xf86FreeOffscreenLinear(psav->reserved);
1157ab47cfaaSmrg
1158ab47cfaaSmrg   if ( psav->pDRIInfo ) {
1159ab47cfaaSmrg      if ( psav->pDRIInfo->devPrivate ) {
11605788ca14Smrg	 free( psav->pDRIInfo->devPrivate );
1161ab47cfaaSmrg	 psav->pDRIInfo->devPrivate = 0;
1162ab47cfaaSmrg      }
1163ab47cfaaSmrg      DRIDestroyInfoRec( psav->pDRIInfo );
1164ab47cfaaSmrg      psav->pDRIInfo = 0;
1165ab47cfaaSmrg   }
1166ab47cfaaSmrg   if ( psav->DRIServerInfo ) {
11675788ca14Smrg      free( psav->DRIServerInfo );
1168ab47cfaaSmrg      psav->DRIServerInfo = 0;
1169ab47cfaaSmrg   }
1170ab47cfaaSmrg}
1171ab47cfaaSmrg
1172ab47cfaaSmrgvoid
1173ab47cfaaSmrgSAVAGEDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
1174ab47cfaaSmrg{
1175ab47cfaaSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
11765788ca14Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1177ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1178ab47cfaaSmrg    BoxPtr pbox = REGION_RECTS(prgn);
1179ab47cfaaSmrg    int nbox  = REGION_NUM_RECTS(prgn);
1180ab47cfaaSmrg    drmSAVAGECmdHeader cmd[2];
1181ab47cfaaSmrg    drmSAVAGECmdbuf cmdBuf;
1182ab47cfaaSmrg    int ret;
1183ab47cfaaSmrg
1184ab47cfaaSmrg    if (!psav->LockHeld) {
1185ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_WARNING,
1186ab47cfaaSmrg		    "Not holding the lock in InitBuffers.\n");
1187ab47cfaaSmrg	return;
1188ab47cfaaSmrg    }
1189ab47cfaaSmrg
1190ab47cfaaSmrg    cmd[0].clear0.cmd = SAVAGE_CMD_CLEAR;
1191ab47cfaaSmrg    cmd[0].clear0.flags = SAVAGE_BACK|SAVAGE_DEPTH;
1192ab47cfaaSmrg    cmd[1].clear1.mask = 0xffffffff;
1193ab47cfaaSmrg    cmd[1].clear1.value = 0;
1194ab47cfaaSmrg
1195ab47cfaaSmrg    cmdBuf.cmd_addr = cmd;
1196ab47cfaaSmrg    cmdBuf.size = 2;
1197ab47cfaaSmrg    cmdBuf.dma_idx = 0;
1198ab47cfaaSmrg    cmdBuf.discard = 0;
1199ab47cfaaSmrg    cmdBuf.vb_addr = NULL;
1200ab47cfaaSmrg    cmdBuf.vb_size = 0;
1201ab47cfaaSmrg    cmdBuf.vb_stride = 0;
1202ab47cfaaSmrg    cmdBuf.box_addr = (drm_clip_rect_t*)pbox;
1203ab47cfaaSmrg    cmdBuf.nbox = nbox;
1204ab47cfaaSmrg
1205ab47cfaaSmrg    ret = drmCommandWrite(psav->drmFD, DRM_SAVAGE_BCI_CMDBUF,
1206ab47cfaaSmrg			  &cmdBuf, sizeof(cmdBuf));
1207ab47cfaaSmrg    if (ret < 0) {
1208ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
1209ab47cfaaSmrg		    "SAVAGEDRIInitBuffers: drmCommandWrite returned %d.\n",
1210ab47cfaaSmrg		    ret);
1211ab47cfaaSmrg    }
1212ab47cfaaSmrg}
1213ab47cfaaSmrg
1214ab47cfaaSmrg/*
1215ab47cfaaSmrg  This routine is a modified form of XAADoBitBlt with the calls to
1216ab47cfaaSmrg  ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
1217ab47cfaaSmrg  instead of destination. My origin is upside down so the ydir cases
1218ab47cfaaSmrg  are reversed.
1219ab47cfaaSmrg*/
1220ab47cfaaSmrg
1221ab47cfaaSmrgvoid
1222ab47cfaaSmrgSAVAGEDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
1223ab47cfaaSmrg		   RegionPtr prgnSrc, CARD32 index)
1224ab47cfaaSmrg{
1225ab47cfaaSmrg    ScreenPtr pScreen = pParent->drawable.pScreen;
12265788ca14Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1227ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1228ab47cfaaSmrg    int nbox;
1229ab47cfaaSmrg    BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
1230ab47cfaaSmrg    DDXPointPtr pptTmp, pptNew1, pptNew2;
1231ab47cfaaSmrg    int xdir, ydir;
1232ab47cfaaSmrg    int dx, dy;
1233ab47cfaaSmrg    DDXPointPtr pptSrc;
1234ab47cfaaSmrg    int screenwidth = pScrn->virtualX;
1235ab47cfaaSmrg    int screenheight = pScrn->virtualY;
1236ab47cfaaSmrg    BCI_GET_PTR;
1237ab47cfaaSmrg
1238ab47cfaaSmrg    if (!psav->LockHeld) {
1239ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_INFO, "Not holding lock in MoveBuffers\n");
1240ab47cfaaSmrg    }
1241ab47cfaaSmrg
1242ab47cfaaSmrg    pbox = REGION_RECTS(prgnSrc);
1243ab47cfaaSmrg    nbox = REGION_NUM_RECTS(prgnSrc);
1244ab47cfaaSmrg    pboxNew1 = 0;
1245ab47cfaaSmrg    pptNew1 = 0;
1246ab47cfaaSmrg    pboxNew2 = 0;
12475788ca14Smrg    pptNew2 = 0;
1248ab47cfaaSmrg    pptSrc = &ptOldOrg;
1249ab47cfaaSmrg
1250ab47cfaaSmrg    dx = pParent->drawable.x - ptOldOrg.x;
1251ab47cfaaSmrg    dy = pParent->drawable.y - ptOldOrg.y;
1252ab47cfaaSmrg
1253ab47cfaaSmrg    /* If the copy will overlap in Y, reverse the order */
1254ab47cfaaSmrg    if (dy>0) {
1255ab47cfaaSmrg        ydir = -1;
1256ab47cfaaSmrg
1257ab47cfaaSmrg        if (nbox>1) {
1258ab47cfaaSmrg	    /* Keep ordering in each band, reverse order of bands */
12595788ca14Smrg	    pboxNew1 = malloc(sizeof(BoxRec)*nbox);
1260ab47cfaaSmrg	    if (!pboxNew1) return;
12615788ca14Smrg	    pptNew1 = malloc(sizeof(DDXPointRec)*nbox);
1262ab47cfaaSmrg	    if (!pptNew1) {
12635788ca14Smrg	        free(pboxNew1);
1264ab47cfaaSmrg	        return;
1265ab47cfaaSmrg	    }
1266ab47cfaaSmrg	    pboxBase = pboxNext = pbox+nbox-1;
1267ab47cfaaSmrg	    while (pboxBase >= pbox) {
1268ab47cfaaSmrg	        while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
1269ab47cfaaSmrg		  pboxNext--;
1270ab47cfaaSmrg	        pboxTmp = pboxNext+1;
1271ab47cfaaSmrg	        pptTmp = pptSrc + (pboxTmp - pbox);
1272ab47cfaaSmrg	        while (pboxTmp <= pboxBase) {
1273ab47cfaaSmrg		    *pboxNew1++ = *pboxTmp++;
1274ab47cfaaSmrg		    *pptNew1++ = *pptTmp++;
1275ab47cfaaSmrg		}
1276ab47cfaaSmrg	        pboxBase = pboxNext;
1277ab47cfaaSmrg	    }
1278ab47cfaaSmrg	    pboxNew1 -= nbox;
1279ab47cfaaSmrg	    pbox = pboxNew1;
1280ab47cfaaSmrg	    pptNew1 -= nbox;
1281ab47cfaaSmrg	    pptSrc = pptNew1;
1282ab47cfaaSmrg	}
1283ab47cfaaSmrg    } else {
1284ab47cfaaSmrg        /* No changes required */
1285ab47cfaaSmrg        ydir = 1;
1286ab47cfaaSmrg    }
1287ab47cfaaSmrg
1288ab47cfaaSmrg    /* If the regions will overlap in X, reverse the order */
1289ab47cfaaSmrg    if (dx>0) {
1290ab47cfaaSmrg        xdir = -1;
1291ab47cfaaSmrg
1292ab47cfaaSmrg        if (nbox > 1) {
1293ab47cfaaSmrg	    /*reverse orderof rects in each band */
12945788ca14Smrg	    pboxNew2 = malloc(sizeof(BoxRec)*nbox);
12955788ca14Smrg	    pptNew2 = malloc(sizeof(DDXPointRec)*nbox);
1296ab47cfaaSmrg	    if (!pboxNew2 || !pptNew2) {
12975788ca14Smrg	        if (pptNew2) free(pptNew2);
12985788ca14Smrg	        if (pboxNew2) free(pboxNew2);
1299ab47cfaaSmrg	        if (pboxNew1) {
13005788ca14Smrg		    free(pptNew1);
13015788ca14Smrg		    free(pboxNew1);
1302ab47cfaaSmrg		}
1303ab47cfaaSmrg	       return;
1304ab47cfaaSmrg	    }
1305ab47cfaaSmrg	    pboxBase = pboxNext = pbox;
1306ab47cfaaSmrg	    while (pboxBase < pbox+nbox) {
1307ab47cfaaSmrg	        while ((pboxNext < pbox+nbox) &&
1308ab47cfaaSmrg		       (pboxNext->y1 == pboxBase->y1))
1309ab47cfaaSmrg		  pboxNext++;
1310ab47cfaaSmrg	        pboxTmp = pboxNext;
1311ab47cfaaSmrg	        pptTmp = pptSrc + (pboxTmp - pbox);
1312ab47cfaaSmrg	        while (pboxTmp != pboxBase) {
1313ab47cfaaSmrg		    *pboxNew2++ = *--pboxTmp;
1314ab47cfaaSmrg		    *pptNew2++ = *--pptTmp;
1315ab47cfaaSmrg		}
1316ab47cfaaSmrg	        pboxBase = pboxNext;
1317ab47cfaaSmrg	    }
1318ab47cfaaSmrg	    pboxNew2 -= nbox;
1319ab47cfaaSmrg	    pbox = pboxNew2;
1320ab47cfaaSmrg	    pptNew2 -= nbox;
1321ab47cfaaSmrg	    pptSrc = pptNew2;
1322ab47cfaaSmrg	}
1323ab47cfaaSmrg    } else {
1324ab47cfaaSmrg        /* No changes are needed */
1325ab47cfaaSmrg        xdir = 1;
1326ab47cfaaSmrg    }
1327ab47cfaaSmrg
1328ab47cfaaSmrg    BCI_SEND(0xc0030000); /* wait for 2D+3D idle */
1329ab47cfaaSmrg    SAVAGEDRISetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);
1330ab47cfaaSmrg    for ( ; nbox-- ; pbox++)
1331ab47cfaaSmrg     {
1332ab47cfaaSmrg	 int x1 = pbox->x1;
1333ab47cfaaSmrg	 int y1 = pbox->y1;
1334ab47cfaaSmrg	 int destx = x1 + dx;
1335ab47cfaaSmrg	 int desty = y1 + dy;
1336ab47cfaaSmrg	 int w = pbox->x2 - x1 + 1;
1337ab47cfaaSmrg	 int h = pbox->y2 - y1 + 1;
1338ab47cfaaSmrg
1339ab47cfaaSmrg	 if ( destx < 0 ) x1 -= destx, w += destx, destx = 0;
1340ab47cfaaSmrg	 if ( desty < 0 ) y1 -= desty, h += desty, desty = 0;
1341ab47cfaaSmrg	 if ( destx + w > screenwidth ) w = screenwidth - destx;
1342ab47cfaaSmrg	 if ( desty + h > screenheight ) h = screenheight - desty;
1343ab47cfaaSmrg	 if ( w <= 0 ) continue;
1344ab47cfaaSmrg	 if ( h <= 0 ) continue;
1345ab47cfaaSmrg
1346ab47cfaaSmrg	 SAVAGESelectBuffer(pScrn, SAVAGE_BACK);
1347ab47cfaaSmrg	 SAVAGEDRISubsequentScreenToScreenCopy(pScrn, x1, y1,
1348ab47cfaaSmrg					       destx,desty, w, h);
1349ab47cfaaSmrg	 SAVAGESelectBuffer(pScrn, SAVAGE_DEPTH);
1350ab47cfaaSmrg	 SAVAGEDRISubsequentScreenToScreenCopy(pScrn, x1,y1,
1351ab47cfaaSmrg					       destx,desty, w, h);
1352ab47cfaaSmrg     }
1353ab47cfaaSmrg    SAVAGESelectBuffer(pScrn, SAVAGE_FRONT);
1354ab47cfaaSmrg
1355ab47cfaaSmrg    if (pboxNew2) {
13565788ca14Smrg        free(pptNew2);
13575788ca14Smrg        free(pboxNew2);
1358ab47cfaaSmrg    }
1359ab47cfaaSmrg    if (pboxNew1) {
13605788ca14Smrg        free(pptNew1);
13615788ca14Smrg        free(pboxNew1);
1362ab47cfaaSmrg    }
1363ab47cfaaSmrg
1364ab47cfaaSmrg    BCI_SEND(0xc0020000); /* wait for 2D idle */
1365ab47cfaaSmrg    if (psav->useEXA)
1366ab47cfaaSmrg	exaMarkSync(pScreen);
13675788ca14Smrg#ifdef HAVE_XAA_H
1368ab47cfaaSmrg    else
1369ab47cfaaSmrg	psav->AccelInfoRec->NeedToSync = TRUE;
13705788ca14Smrg#endif
1371ab47cfaaSmrg}
1372ab47cfaaSmrg
1373ab47cfaaSmrgstatic void
1374ab47cfaaSmrgSAVAGEDRISetupForScreenToScreenCopy(
1375ab47cfaaSmrg    ScrnInfoPtr pScrn,
1376ab47cfaaSmrg    int xdir,
1377ab47cfaaSmrg    int ydir,
1378ab47cfaaSmrg    int rop,
1379ab47cfaaSmrg    unsigned planemask,
1380ab47cfaaSmrg    int transparency_color)
1381ab47cfaaSmrg{
1382ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1383ab47cfaaSmrg    int cmd =0;
1384ab47cfaaSmrg
1385ab47cfaaSmrg    cmd = BCI_CMD_RECT | BCI_CMD_DEST_PBD | BCI_CMD_SRC_PBD_COLOR;
13861c79cd07Smrg    BCI_CMD_SET_ROP( cmd, SavageGetCopyROP(rop) );
1387ab47cfaaSmrg    if (transparency_color != -1)
1388ab47cfaaSmrg        cmd |= BCI_CMD_SEND_COLOR | BCI_CMD_SRC_TRANSPARENT;
1389ab47cfaaSmrg
1390ab47cfaaSmrg    if (xdir == 1 ) cmd |= BCI_CMD_RECT_XP;
1391ab47cfaaSmrg    if (ydir == 1 ) cmd |= BCI_CMD_RECT_YP;
1392ab47cfaaSmrg
1393ab47cfaaSmrg    psav->SavedBciCmd = cmd;
1394ab47cfaaSmrg    psav->SavedBgColor = transparency_color;
1395ab47cfaaSmrg
1396ab47cfaaSmrg}
1397ab47cfaaSmrg
1398ab47cfaaSmrgstatic void
1399ab47cfaaSmrgSAVAGEDRISubsequentScreenToScreenCopy(
1400ab47cfaaSmrg    ScrnInfoPtr pScrn,
1401ab47cfaaSmrg    int x1,
1402ab47cfaaSmrg    int y1,
1403ab47cfaaSmrg    int x2,
1404ab47cfaaSmrg    int y2,
1405ab47cfaaSmrg    int w,
1406ab47cfaaSmrg    int h)
1407ab47cfaaSmrg{
1408ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
1409ab47cfaaSmrg    BCI_GET_PTR;
1410ab47cfaaSmrg
1411ab47cfaaSmrg    if (!w || !h) return;
1412ab47cfaaSmrg    if (!(psav->SavedBciCmd & BCI_CMD_RECT_XP)) {
1413ab47cfaaSmrg        w --;
1414ab47cfaaSmrg        x1 += w;
1415ab47cfaaSmrg        x2 += w;
1416ab47cfaaSmrg        w ++;
1417ab47cfaaSmrg    }
1418ab47cfaaSmrg    if (!(psav->SavedBciCmd & BCI_CMD_RECT_YP)) {
1419ab47cfaaSmrg        h --;
1420ab47cfaaSmrg        y1 += h;
1421ab47cfaaSmrg        y2 += h;
1422ab47cfaaSmrg        h ++;
1423ab47cfaaSmrg    }
1424ab47cfaaSmrg
1425ab47cfaaSmrg    psav->WaitQueue(psav,6);
1426ab47cfaaSmrg    BCI_SEND(psav->SavedBciCmd);
1427ab47cfaaSmrg    if (psav->SavedBgColor != -1)
1428ab47cfaaSmrg	BCI_SEND(psav->SavedBgColor);
1429ab47cfaaSmrg    BCI_SEND(BCI_X_Y(x1, y1));
1430ab47cfaaSmrg    BCI_SEND(BCI_X_Y(x2, y2));
1431ab47cfaaSmrg    BCI_SEND(BCI_W_H(w, h));
1432ab47cfaaSmrg
1433ab47cfaaSmrg}
1434ab47cfaaSmrg
1435ab47cfaaSmrg/*
1436ab47cfaaSmrg * the FullScreen DRI code is dead, this is just left in place to show how
1437ab47cfaaSmrg * to set up pageflipping.
1438ab47cfaaSmrg */
1439ab47cfaaSmrgstatic Bool
1440ab47cfaaSmrgSAVAGEDRIOpenFullScreen(ScreenPtr pScreen)
1441ab47cfaaSmrg{
14425788ca14Smrg  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1443ab47cfaaSmrg  vgaHWPtr hwp = VGAHWPTR(pScrn);
1444ab47cfaaSmrg  SavagePtr psav = SAVPTR(pScrn);
1445ab47cfaaSmrg  unsigned int vgaCRIndex = hwp->IOBase + 4;
1446ab47cfaaSmrg  unsigned int vgaCRReg = hwp->IOBase + 5;
1447ab47cfaaSmrg  SAVAGEDRIPtr pSAVAGEDRI = (SAVAGEDRIPtr)psav->pDRIInfo->devPrivate;
1448ab47cfaaSmrg  unsigned int TileStride;
1449ab47cfaaSmrg  unsigned int WidthinTiles;
1450ab47cfaaSmrg  unsigned int depth;
1451ab47cfaaSmrg
1452ab47cfaaSmrg  OUTREG(0x48C18, INREG(0x48C18) & 0xFFFFFFF7);
1453ab47cfaaSmrg  /*VGAOUT8(vgaCRIndex,0x66);
1454ab47cfaaSmrg  VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg)|0x10);*/
1455ab47cfaaSmrg  VGAOUT8(vgaCRIndex,0x69);
1456ab47cfaaSmrg  VGAOUT8(vgaCRReg, 0x80);
1457ab47cfaaSmrg
1458ab47cfaaSmrg  depth = pScrn->bitsPerPixel;
1459ab47cfaaSmrg
1460ab47cfaaSmrg  if(depth == 16)
1461ab47cfaaSmrg  {
1462ab47cfaaSmrg      WidthinTiles = (pSAVAGEDRI->width+63)>>6;
1463ab47cfaaSmrg      TileStride = (pSAVAGEDRI->width+63)&(~63);
1464ab47cfaaSmrg
1465ab47cfaaSmrg  }
1466ab47cfaaSmrg  else
1467ab47cfaaSmrg  {
1468ab47cfaaSmrg      WidthinTiles = (pSAVAGEDRI->width+31)>>5;
1469ab47cfaaSmrg      TileStride = (pSAVAGEDRI->width+31)&(~31);
1470ab47cfaaSmrg
1471ab47cfaaSmrg  }
1472ab47cfaaSmrg
1473ab47cfaaSmrg
1474ab47cfaaSmrg  /* set primary stream stride */
1475ab47cfaaSmrg  {
1476ab47cfaaSmrg      unsigned int value;
1477ab47cfaaSmrg
1478ab47cfaaSmrg      /*value = 0x80000000|(WidthinTiles<<24)|(TileStride*depth/8);*/
1479ab47cfaaSmrg      value = 0x80000000|(WidthinTiles<<24);
1480ab47cfaaSmrg      if(depth == 32)
1481ab47cfaaSmrg          value |= 0x40000000;
1482ab47cfaaSmrg
1483ab47cfaaSmrg      OUTREG(PRI_STREAM_STRIDE, value);
1484ab47cfaaSmrg
1485ab47cfaaSmrg  }
1486ab47cfaaSmrg
1487ab47cfaaSmrg  /* set global bitmap descriptor */
1488ab47cfaaSmrg  {
1489ab47cfaaSmrg      unsigned int value;
1490ab47cfaaSmrg      value = 0x10000000|
1491ab47cfaaSmrg              0x00000009|
1492ab47cfaaSmrg              0x01000000|
1493ab47cfaaSmrg              (depth<<16)  | TileStride;
1494ab47cfaaSmrg
1495ab47cfaaSmrg      OUTREG(0x816C,value);
1496ab47cfaaSmrg
1497ab47cfaaSmrg  }
1498ab47cfaaSmrg
1499ab47cfaaSmrg   OUTREG(0x48C18, INREG(0x48C18) | 0x8);
1500ab47cfaaSmrg
1501ab47cfaaSmrg  return TRUE;
1502ab47cfaaSmrg}
1503ab47cfaaSmrg
1504ab47cfaaSmrgstatic Bool
1505ab47cfaaSmrgSAVAGEDRICloseFullScreen(ScreenPtr pScreen)
1506ab47cfaaSmrg{
15075788ca14Smrg  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1508ab47cfaaSmrg  SavagePtr psav = SAVPTR(pScrn);
1509ab47cfaaSmrg  BCI_GET_PTR;
1510ab47cfaaSmrg
1511ab47cfaaSmrg  BCI_SEND(0xC0FF0000);
1512ab47cfaaSmrg  psav->WaitIdleEmpty(psav);
1513ab47cfaaSmrg  OUTREG(0x48C18, INREG(0x48C18) & 0xFFFFFFF7);
1514ab47cfaaSmrg  /* set primary stream stride */
1515ab47cfaaSmrg  {
1516ab47cfaaSmrg      /* MM81C0 and 81C4 are used to control primary stream. */
1517ab47cfaaSmrg      OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000);
1518ab47cfaaSmrg      OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000);
1519ab47cfaaSmrg
1520ab47cfaaSmrg      /* FIFO control */
1521ab47cfaaSmrg      OUTREG32(0X81EC,0Xffffffff);
1522ab47cfaaSmrg
1523ab47cfaaSmrg      if (!psav->bTiled) {
1524ab47cfaaSmrg          OUTREG32(PRI_STREAM_STRIDE,
1525ab47cfaaSmrg                   (((psav->lDelta * 2) << 16) & 0x3FFFE000) |
1526ab47cfaaSmrg                   (psav->lDelta & 0x00001fff));
1527ab47cfaaSmrg      }
1528ab47cfaaSmrg      else if (pScrn->bitsPerPixel == 16) {
1529ab47cfaaSmrg          /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
1530ab47cfaaSmrg          OUTREG32(PRI_STREAM_STRIDE,
1531ab47cfaaSmrg                   (((psav->lDelta * 2) << 16) & 0x3FFFE000)
1532ab47cfaaSmrg                   | 0x80000000 | (psav->lDelta & 0x00001fff));
1533ab47cfaaSmrg      }
1534ab47cfaaSmrg      else if (pScrn->bitsPerPixel == 32) {
1535ab47cfaaSmrg          OUTREG32(PRI_STREAM_STRIDE,
1536ab47cfaaSmrg                   (((psav->lDelta * 2) << 16) & 0x3FFFE000)
1537ab47cfaaSmrg                   | 0xC0000000 | (psav->lDelta & 0x00001fff));
1538ab47cfaaSmrg      }
1539ab47cfaaSmrg
1540ab47cfaaSmrg
1541ab47cfaaSmrg  }
1542ab47cfaaSmrg
1543ab47cfaaSmrg  /* set global bitmap descriptor */
1544ab47cfaaSmrg      {
1545ab47cfaaSmrg          OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart );
1546ab47cfaaSmrg          OUTREG32(S3_GLB_BD_HIGH,psav->GlobalBD.bd2.HiPart | BCI_ENABLE | S3_LITTLE_ENDIAN | S3_BD64);
1547ab47cfaaSmrg
1548ab47cfaaSmrg      }
1549ab47cfaaSmrg
1550ab47cfaaSmrg  OUTREG(0x48C18, INREG(0x48C18) | 0x8);
1551ab47cfaaSmrg  return TRUE;
1552ab47cfaaSmrg}
1553ab47cfaaSmrg
1554ab47cfaaSmrg#endif
1555