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