Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
      3  *                      Precision Insight, Inc., Cedar Park, Texas, and
      4  *                      VA Linux Systems Inc., Fremont, California.
      5  *
      6  * All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining
      9  * a copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation on the rights to use, copy, modify, merge,
     12  * publish, distribute, sublicense, and/or sell copies of the Software,
     13  * and to permit persons to whom the Software is furnished to do so,
     14  * subject to the following conditions:
     15  *
     16  * The above copyright notice and this permission notice (including the
     17  * next paragraph) shall be included in all copies or substantial
     18  * portions of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     23  * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
     24  * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     25  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     27  * OTHER DEALINGS IN THE SOFTWARE.
     28  */
     29 
     30 #ifdef HAVE_CONFIG_H
     31 #include "config.h"
     32 #endif
     33 
     34 #include <string.h>
     35 #include <stdio.h>
     36 
     37 /*
     38  * Authors:
     39  *   Kevin E. Martin <martin (at) valinux.com>
     40  *   Rickard E. Faith <faith (at) valinux.com>
     41  *   Daryll Strauss <daryll (at) valinux.com>
     42  *   Gareth Hughes <gareth (at) valinux.com>
     43  *
     44  */
     45 
     46 				/* Driver data structures */
     47 #include "r128.h"
     48 #include "r128_dri.h"
     49 #include "r128_common.h"
     50 #include "r128_reg.h"
     51 #include "r128_sarea.h"
     52 #include "r128_version.h"
     53 
     54 				/* X and server generic header files */
     55 #include "xf86.h"
     56 #include "windowstr.h"
     57 
     58 #include "shadowfb.h"
     59 				/* DRI/DRM definitions */
     60 #define _XF86DRI_SERVER_
     61 #include "sarea.h"
     62 
     63 static size_t r128_drm_page_size;
     64 
     65 static void R128DRITransitionTo2d(ScreenPtr pScreen);
     66 static void R128DRITransitionTo3d(ScreenPtr pScreen);
     67 static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen);
     68 static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen);
     69 
     70 static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
     71 
     72 /* Create the Rage 128-specific context information */
     73 static Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual,
     74 			      drm_context_t hwContext, void *pVisualConfigPriv,
     75 			      DRIContextType contextStore)
     76 {
     77     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     78     R128InfoPtr info = R128PTR(pScrn);
     79 
     80     info->drmCtx = hwContext;
     81     return TRUE;
     82 }
     83 
     84 /* Destroy the Rage 128-specific context information */
     85 static void R128DestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
     86 			       DRIContextType contextStore)
     87 {
     88     /* Nothing yet */
     89 }
     90 
     91 /* Called when the X server is woken up to allow the last client's
     92    context to be saved and the X server's context to be loaded.  This is
     93    not necessary for the Rage 128 since the client detects when it's
     94    context is not currently loaded and then load's it itself.  Since the
     95    registers to start and stop the CCE are privileged, only the X server
     96    can start/stop the engine. */
     97 static void R128EnterServer(ScreenPtr pScreen)
     98 {
     99     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    100     R128InfoPtr info = R128PTR(pScrn);
    101 
    102 #ifdef USE_EXA
    103     if (info->ExaDriver) exaMarkSync(pScreen);
    104     /* EXA and DRI are fighting over control of the texture hardware.
    105      * That means we need to setup compositing when the server wakes
    106      * up if a 3D app is running.
    107      */
    108     if (info->have3DWindows) info->state_2d.composite_setup = FALSE;
    109 #endif
    110 }
    111 
    112 /* Called when the X server goes to sleep to allow the X server's
    113    context to be saved and the last client's context to be loaded.  This
    114    is not necessary for the Rage 128 since the client detects when it's
    115    context is not currently loaded and then load's it itself.  Since the
    116    registers to start and stop the CCE are privileged, only the X server
    117    can start/stop the engine. */
    118 static void R128LeaveServer(ScreenPtr pScreen)
    119 {
    120     ScrnInfoPtr   pScrn     = xf86ScreenToScrn(pScreen);
    121     R128InfoPtr   info      = R128PTR(pScrn);
    122     unsigned char *R128MMIO = info->MMIO;
    123 
    124     if (!info->directRenderingEnabled) {
    125 	/* Save all hardware scissors */
    126 	info->sc_left     = INREG(R128_SC_LEFT);
    127 	info->sc_right    = INREG(R128_SC_RIGHT);
    128 	info->sc_top      = INREG(R128_SC_TOP);
    129 	info->sc_bottom   = INREG(R128_SC_BOTTOM);
    130 	info->aux_sc_cntl = INREG(R128_SC_BOTTOM);
    131     } else if (info->CCEInUse) {
    132 	R128CCEReleaseIndirect(pScrn);
    133 
    134 	info->CCEInUse = FALSE;
    135     }
    136 }
    137 
    138 /* Contexts can be swapped by the X server if necessary.  This callback
    139    is currently only used to perform any functions necessary when
    140    entering or leaving the X server, and in the future might not be
    141    necessary. */
    142 static void R128DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
    143 			       DRIContextType oldContextType, void *oldContext,
    144 			       DRIContextType newContextType, void *newContext)
    145 {
    146     if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
    147 	(newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */
    148 	R128EnterServer(pScreen);
    149     }
    150     if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
    151 	(newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */
    152 	R128LeaveServer(pScreen);
    153     }
    154 }
    155 
    156 /* Initialize the state of the back and depth buffers. */
    157 static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx)
    158 {
    159     /* FIXME: This routine needs to have acceleration turned on */
    160     ScreenPtr   pScreen = pWin->drawable.pScreen;
    161     ScrnInfoPtr pScrn   = xf86ScreenToScrn(pScreen);
    162     R128InfoPtr info    = R128PTR(pScrn);
    163 
    164     /* FIXME: Use accel when CCE 2D code is written
    165      * EA: What is this code kept for? Radeon doesn't have it and
    166      * has a comment: "There's no need for the 2d driver to be clearing
    167      * buffers for the 3d client.  It knows how to do that on its own."
    168      */
    169     if (info->directRenderingEnabled)
    170 	return;
    171 }
    172 
    173 /* Copy the back and depth buffers when the X server moves a window. */
    174 static void R128DRIMoveBuffers(WindowPtr pWin, DDXPointRec ptOldOrg,
    175 			       RegionPtr prgnSrc, CARD32 indx)
    176 {
    177     ScreenPtr   pScreen = pWin->drawable.pScreen;
    178     ScrnInfoPtr pScrn   = xf86ScreenToScrn(pScreen);
    179     R128InfoPtr info   = R128PTR(pScrn);
    180 
    181     /* FIXME: This routine needs to have acceleration turned on */
    182     /* FIXME: Copy XAACopyWindow() and use REGION_TRANSLATE() */
    183     /* FIXME: Only initialize the back and depth buffers for contexts
    184        that request them */
    185 
    186     /* FIXME: Use accel when CCE 2D code is written */
    187     if (info->directRenderingEnabled)
    188 	return;
    189 }
    190 
    191 /* Initialize the AGP state.  Request memory for use in AGP space, and
    192    initialize the Rage 128 registers to point to that memory. */
    193 static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen)
    194 {
    195     unsigned char *R128MMIO = info->MMIO;
    196     unsigned long mode;
    197     unsigned int  vendor, device;
    198     int           ret;
    199     unsigned long cntl, chunk;
    200     int           s, l;
    201     int           flags;
    202     unsigned long agpBase;
    203 
    204     if (drmAgpAcquire(info->drmFD) < 0) {
    205 	xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n");
    206 	return FALSE;
    207     }
    208 
    209 				/* Modify the mode if the default mode is
    210 				   not appropriate for this particular
    211 				   combination of graphics card and AGP
    212 				   chipset. */
    213 
    214     mode   = drmAgpGetMode(info->drmFD);        /* Default mode */
    215     vendor = drmAgpVendorId(info->drmFD);
    216     device = drmAgpDeviceId(info->drmFD);
    217 
    218     mode &= ~R128_AGP_MODE_MASK;
    219     switch (info->agpMode) {
    220     case 4:          mode |= R128_AGP_4X_MODE;
    221     case 2:          mode |= R128_AGP_2X_MODE;
    222     case 1: default: mode |= R128_AGP_1X_MODE;
    223     }
    224 
    225     xf86DrvMsg(pScreen->myNum, X_INFO,
    226 	       "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
    227 	       mode, vendor, device,
    228 	       PCI_DEV_VENDOR_ID(info->PciInfo),
    229 	       PCI_DEV_DEVICE_ID(info->PciInfo));
    230 
    231     if (drmAgpEnable(info->drmFD, mode) < 0) {
    232 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n");
    233 	drmAgpRelease(info->drmFD);
    234 	return FALSE;
    235     }
    236 
    237     info->agpOffset = 0;
    238 
    239     if ((ret = drmAgpAlloc(info->drmFD, info->agpSize*1024*1024, 0, NULL,
    240 			   &info->agpMemHandle)) < 0) {
    241 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret);
    242 	drmAgpRelease(info->drmFD);
    243 	return FALSE;
    244     }
    245     xf86DrvMsg(pScreen->myNum, X_INFO,
    246 	       "[agp] %d kB allocated with handle 0x%08x\n",
    247 	       info->agpSize*1024, info->agpMemHandle);
    248 
    249     if (drmAgpBind(info->drmFD, info->agpMemHandle, info->agpOffset) < 0) {
    250 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n");
    251 	drmAgpFree(info->drmFD, info->agpMemHandle);
    252 	drmAgpRelease(info->drmFD);
    253 	return FALSE;
    254     }
    255 
    256 				/* Initialize the CCE ring buffer data */
    257     info->ringStart       = info->agpOffset;
    258     info->ringMapSize     = info->ringSize*1024*1024 + r128_drm_page_size;
    259     info->ringSizeLog2QW  = R128MinBits(info->ringSize*1024*1024/8) - 1;
    260 
    261     info->ringReadOffset  = info->ringStart + info->ringMapSize;
    262     info->ringReadMapSize = r128_drm_page_size;
    263 
    264 				/* Reserve space for vertex/indirect buffers */
    265     info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
    266     info->bufMapSize      = info->bufSize*1024*1024;
    267 
    268 				/* Reserve the rest for AGP textures */
    269     info->agpTexStart     = info->bufStart + info->bufMapSize;
    270     s = (info->agpSize*1024*1024 - info->agpTexStart);
    271     l = R128MinBits((s-1) / R128_NR_TEX_REGIONS);
    272     if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
    273     info->agpTexMapSize   = (s >> l) << l;
    274     info->log2AGPTexGran  = l;
    275 
    276     if (info->CCESecure) flags = DRM_READ_ONLY;
    277     else                  flags = 0;
    278 
    279     if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
    280 		  DRM_AGP, flags, &info->ringHandle) < 0) {
    281 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    282 		   "[agp] Could not add ring mapping\n");
    283 	return FALSE;
    284     }
    285     xf86DrvMsg(pScreen->myNum, X_INFO,
    286 	       "[agp] ring handle = 0x%08x\n", info->ringHandle);
    287 
    288     if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
    289 	       &info->ring) < 0) {
    290 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n");
    291 	return FALSE;
    292     }
    293     xf86DrvMsg(pScreen->myNum, X_INFO,
    294 	       "[agp] Ring mapped at 0x%08lx\n",
    295 	       (unsigned long)info->ring);
    296 
    297     if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
    298 		  DRM_AGP, flags, &info->ringReadPtrHandle) < 0) {
    299 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    300 		   "[agp] Could not add ring read ptr mapping\n");
    301 	return FALSE;
    302     }
    303     xf86DrvMsg(pScreen->myNum, X_INFO,
    304  	       "[agp] ring read ptr handle = 0x%08x\n",
    305 	       info->ringReadPtrHandle);
    306 
    307     if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
    308 	       &info->ringReadPtr) < 0) {
    309 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    310 		   "[agp] Could not map ring read ptr\n");
    311 	return FALSE;
    312     }
    313     xf86DrvMsg(pScreen->myNum, X_INFO,
    314 	       "[agp] Ring read ptr mapped at 0x%08lx\n",
    315 	       (unsigned long)info->ringReadPtr);
    316 
    317     if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
    318 		  DRM_AGP, 0, &info->bufHandle) < 0) {
    319 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    320 		   "[agp] Could not add vertex/indirect buffers mapping\n");
    321 	return FALSE;
    322     }
    323     xf86DrvMsg(pScreen->myNum, X_INFO,
    324 	       "[agp] vertex/indirect buffers handle = 0x%08x\n",
    325 	       info->bufHandle);
    326 
    327     if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
    328 	       &info->buf) < 0) {
    329 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    330 		   "[agp] Could not map vertex/indirect buffers\n");
    331 	return FALSE;
    332     }
    333     xf86DrvMsg(pScreen->myNum, X_INFO,
    334 	       "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
    335 	       (unsigned long)info->buf);
    336 
    337     if (drmAddMap(info->drmFD, info->agpTexStart, info->agpTexMapSize,
    338 		  DRM_AGP, 0, &info->agpTexHandle) < 0) {
    339 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    340 		   "[agp] Could not add AGP texture map mapping\n");
    341 	return FALSE;
    342     }
    343     xf86DrvMsg(pScreen->myNum, X_INFO,
    344 	       "[agp] AGP texture map handle = 0x%08x\n",
    345 	       info->agpTexHandle);
    346 
    347     if (drmMap(info->drmFD, info->agpTexHandle, info->agpTexMapSize,
    348 	       &info->agpTex) < 0) {
    349 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    350 		   "[agp] Could not map AGP texture map\n");
    351 	return FALSE;
    352     }
    353     xf86DrvMsg(pScreen->myNum, X_INFO,
    354 	       "[agp] AGP Texture map mapped at 0x%08lx\n",
    355 	       (unsigned long)info->agpTex);
    356 
    357 				/* Initialize Rage 128's AGP registers */
    358     cntl  = INREG(R128_AGP_CNTL);
    359     cntl &= ~R128_AGP_APER_SIZE_MASK;
    360     switch (info->agpSize) {
    361     case 256: cntl |= R128_AGP_APER_SIZE_256MB; break;
    362     case 128: cntl |= R128_AGP_APER_SIZE_128MB; break;
    363     case  64: cntl |= R128_AGP_APER_SIZE_64MB;  break;
    364     case  32: cntl |= R128_AGP_APER_SIZE_32MB;  break;
    365     case  16: cntl |= R128_AGP_APER_SIZE_16MB;  break;
    366     case   8: cntl |= R128_AGP_APER_SIZE_8MB;   break;
    367     case   4: cntl |= R128_AGP_APER_SIZE_4MB;   break;
    368     default:
    369 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    370 		   "[agp] Illegal aperture size %d kB\n",
    371 		   info->agpSize*1024);
    372 	return FALSE;
    373     }
    374     agpBase = drmAgpBase(info->drmFD);
    375     OUTREG(R128_AGP_BASE, agpBase);
    376     OUTREG(R128_AGP_CNTL, cntl);
    377 
    378 				/* Disable Rage 128's PCIGART registers */
    379     chunk = INREG(R128_BM_CHUNK_0_VAL);
    380     chunk &= ~(R128_BM_PTR_FORCE_TO_PCI |
    381 	       R128_BM_PM4_RD_FORCE_TO_PCI |
    382 	       R128_BM_GLOBAL_FORCE_TO_PCI);
    383     OUTREG(R128_BM_CHUNK_0_VAL, chunk);
    384 
    385     OUTREG(R128_PCI_GART_PAGE, 1); /* Ensure AGP GART is used (for now) */
    386 
    387     return TRUE;
    388 }
    389 
    390 static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen)
    391 {
    392     unsigned char *R128MMIO = info->MMIO;
    393     uint32_t chunk;
    394     int ret;
    395     int flags;
    396 
    397     info->agpOffset = 0;
    398 
    399     ret = drmScatterGatherAlloc(info->drmFD, info->agpSize*1024*1024,
    400 				&info->pciMemHandle);
    401     if (ret < 0) {
    402 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret);
    403 	return FALSE;
    404     }
    405     xf86DrvMsg(pScreen->myNum, X_INFO,
    406 	       "[pci] %d kB allocated with handle 0x%08x\n",
    407 	       info->agpSize*1024, info->pciMemHandle);
    408 
    409 				/* Initialize the CCE ring buffer data */
    410     info->ringStart       = info->agpOffset;
    411     info->ringMapSize     = info->ringSize*1024*1024 + r128_drm_page_size;
    412     info->ringSizeLog2QW  = R128MinBits(info->ringSize*1024*1024/8) - 1;
    413 
    414     info->ringReadOffset  = info->ringStart + info->ringMapSize;
    415     info->ringReadMapSize = r128_drm_page_size;
    416 
    417 				/* Reserve space for vertex/indirect buffers */
    418     info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
    419     info->bufMapSize      = info->bufSize*1024*1024;
    420 
    421     flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
    422 
    423     if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize,
    424 		  DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
    425 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    426 		   "[pci] Could not add ring mapping\n");
    427 	return FALSE;
    428     }
    429     xf86DrvMsg(pScreen->myNum, X_INFO,
    430 	       "[pci] ring handle = 0x%08x\n", info->ringHandle);
    431 
    432     if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize,
    433 	       &info->ring) < 0) {
    434 	xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n");
    435 	return FALSE;
    436     }
    437     xf86DrvMsg(pScreen->myNum, X_INFO,
    438 	       "[pci] Ring mapped at 0x%08lx\n",
    439 	       (unsigned long)info->ring);
    440     xf86DrvMsg(pScreen->myNum, X_INFO,
    441 	       "[pci] Ring contents 0x%08lx\n",
    442 	       *(unsigned long *)(pointer)info->ring);
    443 
    444     if (drmAddMap(info->drmFD, info->ringReadOffset, info->ringReadMapSize,
    445 		  DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
    446 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    447 		   "[pci] Could not add ring read ptr mapping\n");
    448 	return FALSE;
    449     }
    450     xf86DrvMsg(pScreen->myNum, X_INFO,
    451 	       "[pci] ring read ptr handle = 0x%08x\n",
    452 	       info->ringReadPtrHandle);
    453 
    454     if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
    455 	       &info->ringReadPtr) < 0) {
    456 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    457 		   "[pci] Could not map ring read ptr\n");
    458 	return FALSE;
    459     }
    460     xf86DrvMsg(pScreen->myNum, X_INFO,
    461 	       "[pci] Ring read ptr mapped at 0x%08lx\n",
    462 	       (unsigned long)info->ringReadPtr);
    463     xf86DrvMsg(pScreen->myNum, X_INFO,
    464 	       "[pci] Ring read ptr contents 0x%08lx\n",
    465 	       *(unsigned long *)(pointer)info->ringReadPtr);
    466 
    467     if (drmAddMap(info->drmFD, info->bufStart, info->bufMapSize,
    468 		  DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
    469 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    470 		   "[pci] Could not add vertex/indirect buffers mapping\n");
    471 	return FALSE;
    472     }
    473     xf86DrvMsg(pScreen->myNum, X_INFO,
    474 	       "[pci] vertex/indirect buffers handle = 0x%08x\n",
    475 	       info->bufHandle);
    476 
    477     if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize,
    478 	       &info->buf) < 0) {
    479 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    480 		   "[pci] Could not map vertex/indirect buffers\n");
    481 	return FALSE;
    482     }
    483     xf86DrvMsg(pScreen->myNum, X_INFO,
    484 	       "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
    485 	       (unsigned long)info->buf);
    486     xf86DrvMsg(pScreen->myNum, X_INFO,
    487 	       "[pci] Vertex/indirect buffers contents 0x%08lx\n",
    488 	       *(unsigned long *)(pointer)info->buf);
    489 
    490     switch (info->Chipset) {
    491     case PCI_CHIP_RAGE128LE:
    492     case PCI_CHIP_RAGE128RE:
    493     case PCI_CHIP_RAGE128RK:
    494     case PCI_CHIP_RAGE128PD:
    495     case PCI_CHIP_RAGE128PP:
    496     case PCI_CHIP_RAGE128PR:
    497 	/* This is a PCI card, do nothing */
    498 	break;
    499 
    500     case PCI_CHIP_RAGE128LF:
    501     case PCI_CHIP_RAGE128MF:
    502     case PCI_CHIP_RAGE128ML:
    503     case PCI_CHIP_RAGE128RF:
    504     case PCI_CHIP_RAGE128RG:
    505     case PCI_CHIP_RAGE128RL:
    506     case PCI_CHIP_RAGE128SM:
    507     case PCI_CHIP_RAGE128PF:
    508     case PCI_CHIP_RAGE128TF:
    509     case PCI_CHIP_RAGE128TL:
    510     case PCI_CHIP_RAGE128TR:
    511     /* FIXME: ATI documentation does not specify if the following chips are
    512      * AGP or PCI, it just mentions their PCI IDs.  I'm assuming they're AGP
    513      * until I get more correct information. <mharris (at) redhat.com>
    514      */
    515     case PCI_CHIP_RAGE128PA:
    516     case PCI_CHIP_RAGE128PB:
    517     case PCI_CHIP_RAGE128PC:
    518     case PCI_CHIP_RAGE128PE:
    519     case PCI_CHIP_RAGE128PG:
    520     case PCI_CHIP_RAGE128PH:
    521     case PCI_CHIP_RAGE128PI:
    522     case PCI_CHIP_RAGE128PJ:
    523     case PCI_CHIP_RAGE128PK:
    524     case PCI_CHIP_RAGE128PL:
    525     case PCI_CHIP_RAGE128PM:
    526     case PCI_CHIP_RAGE128PN:
    527     case PCI_CHIP_RAGE128PO:
    528     case PCI_CHIP_RAGE128PQ:
    529     case PCI_CHIP_RAGE128PS:
    530     case PCI_CHIP_RAGE128PT:
    531     case PCI_CHIP_RAGE128PU:
    532     case PCI_CHIP_RAGE128PV:
    533     case PCI_CHIP_RAGE128PW:
    534     case PCI_CHIP_RAGE128PX:
    535     case PCI_CHIP_RAGE128SE:
    536     case PCI_CHIP_RAGE128SF:
    537     case PCI_CHIP_RAGE128SG:
    538     case PCI_CHIP_RAGE128SH:
    539     case PCI_CHIP_RAGE128SK:
    540     case PCI_CHIP_RAGE128SL:
    541     case PCI_CHIP_RAGE128SN:
    542     case PCI_CHIP_RAGE128TS:
    543     case PCI_CHIP_RAGE128TT:
    544     case PCI_CHIP_RAGE128TU:
    545     default:
    546 	/* This is really an AGP card, force PCI GART mode */
    547         chunk = INREG(R128_BM_CHUNK_0_VAL);
    548         chunk |= (R128_BM_PTR_FORCE_TO_PCI |
    549 		  R128_BM_PM4_RD_FORCE_TO_PCI |
    550 		  R128_BM_GLOBAL_FORCE_TO_PCI);
    551         OUTREG(R128_BM_CHUNK_0_VAL, chunk);
    552         OUTREG(R128_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */
    553         break;
    554     }
    555 
    556     return TRUE;
    557 }
    558 
    559 /* Add a map for the MMIO registers that will be accessed by any
    560    DRI-based clients. */
    561 static Bool R128DRIMapInit(R128InfoPtr info, ScreenPtr pScreen)
    562 {
    563     int flags;
    564 
    565     if (info->CCESecure) flags = DRM_READ_ONLY;
    566     else                 flags = 0;
    567 
    568 				/* Map registers */
    569     info->registerSize = R128_MMIOSIZE;
    570     if (drmAddMap(info->drmFD, info->MMIOAddr, info->registerSize,
    571 		  DRM_REGISTERS, flags, &info->registerHandle) < 0) {
    572 	return FALSE;
    573     }
    574     xf86DrvMsg(pScreen->myNum, X_INFO,
    575 	       "[drm] register handle = 0x%08x\n", info->registerHandle);
    576 
    577     return TRUE;
    578 }
    579 
    580 /* Initialize the kernel data structures. */
    581 static int R128DRIKernelInit(R128InfoPtr info, ScreenPtr pScreen)
    582 {
    583     drmR128Init drmInfo;
    584 
    585     memset( &drmInfo, 0, sizeof(drmR128Init) );
    586 
    587     drmInfo.func                = DRM_R128_INIT_CCE;
    588     drmInfo.sarea_priv_offset   = sizeof(XF86DRISAREARec);
    589     drmInfo.is_pci              = info->IsPCI;
    590     drmInfo.cce_mode            = info->CCEMode;
    591     drmInfo.cce_secure          = info->CCESecure;
    592     drmInfo.ring_size           = info->ringSize*1024*1024;
    593     drmInfo.usec_timeout        = info->CCEusecTimeout;
    594 
    595     drmInfo.fb_bpp              = info->CurrentLayout.pixel_code;
    596     drmInfo.depth_bpp           = info->CurrentLayout.pixel_code;
    597 
    598     drmInfo.front_offset        = info->frontOffset;
    599     drmInfo.front_pitch         = info->frontPitch;
    600 
    601     drmInfo.back_offset         = info->backOffset;
    602     drmInfo.back_pitch          = info->backPitch;
    603 
    604     drmInfo.depth_offset        = info->depthOffset;
    605     drmInfo.depth_pitch         = info->depthPitch;
    606     drmInfo.span_offset         = info->spanOffset;
    607 
    608     drmInfo.fb_offset           = info->fbHandle;
    609     drmInfo.mmio_offset         = info->registerHandle;
    610     drmInfo.ring_offset         = info->ringHandle;
    611     drmInfo.ring_rptr_offset    = info->ringReadPtrHandle;
    612     drmInfo.buffers_offset      = info->bufHandle;
    613     drmInfo.agp_textures_offset = info->agpTexHandle;
    614 
    615     if (drmCommandWrite(info->drmFD, DRM_R128_INIT,
    616                         &drmInfo, sizeof(drmR128Init)) < 0)
    617         return FALSE;
    618 
    619     return TRUE;
    620 }
    621 
    622 /* Add a map for the vertex buffers that will be accessed by any
    623    DRI-based clients. */
    624 static Bool R128DRIBufInit(R128InfoPtr info, ScreenPtr pScreen)
    625 {
    626 				/* Initialize vertex buffers */
    627     if (info->IsPCI) {
    628 	info->bufNumBufs = drmAddBufs(info->drmFD,
    629 				      info->bufMapSize / R128_BUFFER_SIZE,
    630 				      R128_BUFFER_SIZE,
    631 				      DRM_SG_BUFFER,
    632 				      info->bufStart);
    633     } else {
    634 	info->bufNumBufs = drmAddBufs(info->drmFD,
    635 				      info->bufMapSize / R128_BUFFER_SIZE,
    636 				      R128_BUFFER_SIZE,
    637 				      DRM_AGP_BUFFER,
    638 				      info->bufStart);
    639     }
    640     if (info->bufNumBufs <= 0) {
    641 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    642 		   "[drm] Could not create vertex/indirect buffers list\n");
    643 	return FALSE;
    644     }
    645     xf86DrvMsg(pScreen->myNum, X_INFO,
    646 	       "[drm] Added %d %d byte vertex/indirect buffers\n",
    647 	       info->bufNumBufs, R128_BUFFER_SIZE);
    648 
    649     if (!(info->buffers = drmMapBufs(info->drmFD))) {
    650 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    651 		   "[drm] Failed to map vertex/indirect buffers list\n");
    652 	return FALSE;
    653     }
    654     xf86DrvMsg(pScreen->myNum, X_INFO,
    655 	       "[drm] Mapped %d vertex/indirect buffers\n",
    656 	       info->buffers->count);
    657 
    658     return TRUE;
    659 }
    660 
    661 static void R128DRIIrqInit(R128InfoPtr info, ScreenPtr pScreen)
    662 {
    663    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    664 
    665    if (!info->irq) {
    666       info->irq = drmGetInterruptFromBusID(
    667 	 info->drmFD,
    668 	 PCI_CFG_BUS(info->PciInfo),
    669 	 PCI_CFG_DEV(info->PciInfo),
    670 	 PCI_CFG_FUNC(info->PciInfo));
    671 
    672       if((drmCtlInstHandler(info->drmFD, info->irq)) != 0) {
    673 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    674 		    "[drm] failure adding irq handler, "
    675 		    "there is a device already using that irq\n"
    676 		    "[drm] falling back to irq-free operation\n");
    677 	 info->irq = 0;
    678       } else {
    679           unsigned char *R128MMIO = info->MMIO;
    680           info->gen_int_cntl = INREG( R128_GEN_INT_CNTL );
    681       }
    682    }
    683 
    684    if (info->irq)
    685       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    686 		 "[drm] dma control initialized, using IRQ %d\n",
    687 		 info->irq);
    688 }
    689 
    690 /* Initialize the CCE state, and start the CCE (if used by the X server) */
    691 static void R128DRICCEInit(ScrnInfoPtr pScrn)
    692 {
    693     R128InfoPtr   info      = R128PTR(pScrn);
    694 
    695 				/* Turn on bus mastering */
    696     info->BusCntl &= ~R128_BUS_MASTER_DIS;
    697 
    698 				/* CCEMode is initialized in r128_driver.c */
    699     switch (info->CCEMode) {
    700     case R128_PM4_NONPM4:                 info->CCEFifoSize = 0;   break;
    701     case R128_PM4_192PIO:                 info->CCEFifoSize = 192; break;
    702     case R128_PM4_192BM:                  info->CCEFifoSize = 192; break;
    703     case R128_PM4_128PIO_64INDBM:         info->CCEFifoSize = 128; break;
    704     case R128_PM4_128BM_64INDBM:          info->CCEFifoSize = 128; break;
    705     case R128_PM4_64PIO_128INDBM:         info->CCEFifoSize = 64;  break;
    706     case R128_PM4_64BM_128INDBM:          info->CCEFifoSize = 64;  break;
    707     case R128_PM4_64PIO_64VCBM_64INDBM:   info->CCEFifoSize = 64;  break;
    708     case R128_PM4_64BM_64VCBM_64INDBM:    info->CCEFifoSize = 64;  break;
    709     case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64;  break;
    710     }
    711 
    712     if (info->directRenderingEnabled) {
    713 				/* Make sure the CCE is on for the X server */
    714 	R128CCE_START(pScrn, info);
    715     } else {
    716 				/* Make sure the CCE is off for the X server */
    717 	R128CCE_STOP(pScrn, info);
    718     }
    719 }
    720 
    721 /* Initialize the screen-specific data structures for the DRI and the
    722    Rage 128.  This is the main entry point to the device-specific
    723    initialization code.  It calls device-independent DRI functions to
    724    create the DRI data structures and initialize the DRI state. */
    725 Bool R128DRIScreenInit(ScreenPtr pScreen)
    726 {
    727     ScrnInfoPtr   pScrn = xf86ScreenToScrn(pScreen);
    728     R128InfoPtr   info = R128PTR(pScrn);
    729     DRIInfoPtr    pDRIInfo;
    730     R128DRIPtr    pR128DRI;
    731     int           major, minor, patch;
    732     drmVersionPtr version;
    733 
    734     /* Check that the DRI, and DRM modules have been loaded by testing
    735      * for known symbols in each module. */
    736     if (!xf86LoaderCheckSymbol("drmAvailable"))        return FALSE;
    737     if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
    738       xf86DrvMsg(pScreen->myNum, X_ERROR,
    739 		 "[dri] R128DRIScreenInit failed (libdri.a too old)\n");
    740       return FALSE;
    741     }
    742 
    743     /* Check the DRI version */
    744     DRIQueryVersion(&major, &minor, &patch);
    745     if (major != DRIINFO_MAJOR_VERSION || minor < 0) {
    746 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    747 		"[dri] R128DRIScreenInit failed because of a version mismatch.\n"
    748 		"[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n"
    749 		"[dri] Disabling the DRI.\n",
    750 		major, minor, patch,
    751                 DRIINFO_MAJOR_VERSION, 0);
    752 	return FALSE;
    753     }
    754 
    755     switch (info->CurrentLayout.pixel_code) {
    756     case 8:
    757 	/* These modes are not supported (yet). */
    758     case 15:
    759     case 24:
    760 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    761 		   "[dri] R128DRIScreenInit failed (depth %d not supported).  "
    762 		   "[dri] Disabling DRI.\n", info->CurrentLayout.pixel_code);
    763 	return FALSE;
    764 
    765 	/* Only 16 and 32 color depths are supports currently. */
    766     case 16:
    767     case 32:
    768 	break;
    769     }
    770 
    771     r128_drm_page_size = getpagesize();
    772 
    773     /* Create the DRI data structure, and fill it in before calling the
    774        DRIScreenInit(). */
    775     if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
    776 
    777     info->pDRIInfo                       = pDRIInfo;
    778     pDRIInfo->drmDriverName              = R128_DRIVER_NAME;
    779     pDRIInfo->clientDriverName           = R128_DRIVER_NAME;
    780     if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
    781 	pDRIInfo->busIdString = DRICreatePCIBusID(info->PciInfo);
    782     } else {
    783 	pDRIInfo->busIdString            = malloc(64);
    784 	sprintf(pDRIInfo->busIdString,
    785 		"PCI:%d:%d:%d",
    786 		PCI_DEV_BUS(info->PciInfo),
    787 		PCI_DEV_DEV(info->PciInfo),
    788 		PCI_DEV_FUNC(info->PciInfo));
    789     }
    790     pDRIInfo->ddxDriverMajorVersion      = R128_VERSION_MAJOR;
    791     pDRIInfo->ddxDriverMinorVersion      = R128_VERSION_MINOR;
    792     pDRIInfo->ddxDriverPatchVersion      = R128_VERSION_PATCH;
    793     pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr;
    794     pDRIInfo->frameBufferSize            = info->FbMapSize;
    795     pDRIInfo->frameBufferStride          = (pScrn->displayWidth *
    796 					    info->CurrentLayout.pixel_bytes);
    797     pDRIInfo->ddxDrawableTableEntry      = R128_MAX_DRAWABLES;
    798     pDRIInfo->maxDrawableTableEntry      = (SAREA_MAX_DRAWABLES
    799 					    < R128_MAX_DRAWABLES
    800 					    ? SAREA_MAX_DRAWABLES
    801 					    : R128_MAX_DRAWABLES);
    802 
    803 #ifdef NOT_DONE
    804     /* FIXME: Need to extend DRI protocol to pass this size back to
    805      * client for SAREA mapping that includes a device private record
    806      */
    807     pDRIInfo->SAREASize =
    808 	((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */
    809     /* + shared memory device private rec */
    810 #else
    811     /* For now the mapping works by using a fixed size defined
    812      * in the SAREA header
    813      */
    814     if (sizeof(XF86DRISAREARec)+sizeof(R128SAREAPriv)>SAREA_MAX) {
    815         xf86DrvMsg(pScreen->myNum, X_ERROR,
    816                    "[dri] Data does not fit in SAREA.  Disabling DRI.\n");
    817 	return FALSE;
    818     }
    819     pDRIInfo->SAREASize = SAREA_MAX;
    820 #endif
    821 
    822     if (!(pR128DRI = (R128DRIPtr)calloc(1, sizeof(R128DRIRec)))) {
    823 	DRIDestroyInfoRec(info->pDRIInfo);
    824 	info->pDRIInfo = NULL;
    825 	return FALSE;
    826     }
    827     pDRIInfo->devPrivate     = pR128DRI;
    828     pDRIInfo->devPrivateSize = sizeof(R128DRIRec);
    829     pDRIInfo->contextSize    = sizeof(R128DRIContextRec);
    830 
    831     pDRIInfo->CreateContext  = R128CreateContext;
    832     pDRIInfo->DestroyContext = R128DestroyContext;
    833     pDRIInfo->SwapContext    = R128DRISwapContext;
    834     pDRIInfo->InitBuffers    = R128DRIInitBuffers;
    835     pDRIInfo->MoveBuffers    = R128DRIMoveBuffers;
    836     pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
    837     pDRIInfo->TransitionTo2d = R128DRITransitionTo2d;
    838     pDRIInfo->TransitionTo3d = R128DRITransitionTo3d;
    839     pDRIInfo->TransitionSingleToMulti3D = R128DRITransitionSingleToMulti3d;
    840     pDRIInfo->TransitionMultiToSingle3D = R128DRITransitionMultiToSingle3d;
    841 
    842     pDRIInfo->createDummyCtx     = TRUE;
    843     pDRIInfo->createDummyCtxPriv = FALSE;
    844 
    845     if (!DRIScreenInit(pScreen, pDRIInfo, &info->drmFD)) {
    846 	xf86DrvMsg(pScreen->myNum, X_ERROR,
    847                    "[dri] DRIScreenInit failed.  Disabling DRI.\n");
    848 	free(pDRIInfo->devPrivate);
    849 	pDRIInfo->devPrivate = NULL;
    850 	DRIDestroyInfoRec(pDRIInfo);
    851 	pDRIInfo = NULL;
    852 	return FALSE;
    853     }
    854 
    855     /* Check the DRM lib version.
    856        drmGetLibVersion was not supported in version 1.0, so check for
    857        symbol first to avoid possible crash or hang.
    858      */
    859     if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
    860         version = drmGetLibVersion(info->drmFD);
    861     }
    862     else {
    863         /* drmlib version 1.0.0 didn't have the drmGetLibVersion
    864            entry point.  Fake it by allocating a version record
    865            via drmGetVersion and changing it to version 1.0.0
    866          */
    867         version = drmGetVersion(info->drmFD);
    868         version->version_major      = 1;
    869         version->version_minor      = 0;
    870         version->version_patchlevel = 0;
    871     }
    872 
    873     if (version) {
    874 	if (version->version_major != 1 ||
    875 	    version->version_minor < 1) {
    876             /* incompatible drm library version */
    877             xf86DrvMsg(pScreen->myNum, X_ERROR,
    878 		"[dri] R128DRIScreenInit failed because of a version mismatch.\n"
    879 		"[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
    880 		"[dri] Disabling DRI.\n",
    881                 version->version_major,
    882                 version->version_minor,
    883                 version->version_patchlevel);
    884             drmFreeVersion(version);
    885 	    R128DRICloseScreen(pScreen);
    886             return FALSE;
    887 	}
    888 	drmFreeVersion(version);
    889     }
    890 
    891     /* Check the r128 DRM version */
    892     version = drmGetVersion(info->drmFD);
    893     if (version) {
    894 	if (version->version_major != 2 ||
    895 	    version->version_minor < 2) {
    896 	    /* incompatible drm version */
    897 	    xf86DrvMsg(pScreen->myNum, X_ERROR,
    898 		"[dri] R128DRIScreenInit failed because of a version mismatch.\n"
    899 		"[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
    900 		"[dri] Disabling the DRI.\n",
    901 		version->version_major,
    902 		version->version_minor,
    903 		version->version_patchlevel);
    904 	    drmFreeVersion(version);
    905 	    R128DRICloseScreen(pScreen);
    906 	    return FALSE;
    907 	}
    908 	info->drmMinor = version->version_minor;
    909 	drmFreeVersion(version);
    910     }
    911 
    912 				/* Initialize AGP */
    913     if (!info->IsPCI && !R128DRIAgpInit(info, pScreen)) {
    914 	info->IsPCI = TRUE;
    915 	xf86DrvMsg(pScreen->myNum, X_WARNING,
    916 		   "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
    917 	xf86DrvMsg(pScreen->myNum, X_WARNING,
    918 		   "[agp] Make sure you have the agpgart kernel module loaded.\n");
    919     }
    920 
    921 				/* Initialize PCIGART */
    922     if (info->IsPCI && !R128DRIPciInit(info, pScreen)) {
    923 	R128DRICloseScreen(pScreen);
    924 	return FALSE;
    925     }
    926 
    927 				/* DRIScreenInit doesn't add all the
    928 				   common mappings.  Add additional
    929 				   mappings here. */
    930     if (!R128DRIMapInit(info, pScreen)) {
    931 	R128DRICloseScreen(pScreen);
    932 	return FALSE;
    933     }
    934 
    935 				/* DRIScreenInit adds the frame buffer
    936 				   map, but we need it as well */
    937     {
    938 	void *scratch_ptr;
    939         int scratch_int;
    940 
    941 	DRIGetDeviceInfo(pScreen, &info->fbHandle,
    942                          &scratch_int, &scratch_int,
    943                          &scratch_int, &scratch_int,
    944                          &scratch_ptr);
    945     }
    946 
    947 				/* FIXME: When are these mappings unmapped? */
    948 
    949     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n");
    950 
    951     return TRUE;
    952 }
    953 
    954 /* Finish initializing the device-dependent DRI state, and call
    955    DRIFinishScreenInit() to complete the device-independent DRI
    956    initialization. */
    957 Bool R128DRIFinishScreenInit(ScreenPtr pScreen)
    958 {
    959     ScrnInfoPtr      pScrn = xf86ScreenToScrn(pScreen);
    960     R128InfoPtr      info  = R128PTR(pScrn);
    961     R128SAREAPrivPtr pSAREAPriv;
    962     R128DRIPtr       pR128DRI;
    963 
    964     info->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
    965     /* info->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */
    966 
    967     /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
    968        because *DRIKernelInit requires that the hardware lock is held by
    969        the X server, and the first time the hardware lock is grabbed is
    970        in DRIFinishScreenInit. */
    971     if (!DRIFinishScreenInit(pScreen)) {
    972 	R128DRICloseScreen(pScreen);
    973 	return FALSE;
    974     }
    975 
    976     /* Initialize the kernel data structures */
    977     if (!R128DRIKernelInit(info, pScreen)) {
    978 	R128DRICloseScreen(pScreen);
    979 	return FALSE;
    980     }
    981 
    982     /* Initialize the vertex buffers list */
    983     if (!R128DRIBufInit(info, pScreen)) {
    984 	R128DRICloseScreen(pScreen);
    985 	return FALSE;
    986     }
    987 
    988     /* Initialize IRQ */
    989     R128DRIIrqInit(info, pScreen);
    990 
    991     /* Initialize and start the CCE if required */
    992     R128DRICCEInit(pScrn);
    993 
    994     pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
    995     memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
    996 
    997     pR128DRI                    = (R128DRIPtr)info->pDRIInfo->devPrivate;
    998 
    999     pR128DRI->deviceID          = info->Chipset;
   1000     pR128DRI->width             = pScrn->virtualX;
   1001     pR128DRI->height            = pScrn->virtualY;
   1002     pR128DRI->depth             = pScrn->depth;
   1003     pR128DRI->bpp               = pScrn->bitsPerPixel;
   1004 
   1005     pR128DRI->IsPCI             = info->IsPCI;
   1006     pR128DRI->AGPMode           = info->agpMode;
   1007 
   1008     pR128DRI->frontOffset       = info->frontOffset;
   1009     pR128DRI->frontPitch        = info->frontPitch;
   1010     pR128DRI->backOffset        = info->backOffset;
   1011     pR128DRI->backPitch         = info->backPitch;
   1012     pR128DRI->depthOffset       = info->depthOffset;
   1013     pR128DRI->depthPitch        = info->depthPitch;
   1014     pR128DRI->spanOffset        = info->spanOffset;
   1015     pR128DRI->textureOffset     = info->textureOffset;
   1016     pR128DRI->textureSize       = info->textureSize;
   1017     pR128DRI->log2TexGran       = info->log2TexGran;
   1018 
   1019     pR128DRI->registerHandle    = info->registerHandle;
   1020     pR128DRI->registerSize      = info->registerSize;
   1021 
   1022     pR128DRI->agpTexHandle      = info->agpTexHandle;
   1023     pR128DRI->agpTexMapSize     = info->agpTexMapSize;
   1024     pR128DRI->log2AGPTexGran    = info->log2AGPTexGran;
   1025     pR128DRI->agpTexOffset      = info->agpTexStart;
   1026     pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
   1027 
   1028     /* Have shadowfb run only while there is 3d active. */
   1029     if (info->allowPageFlip && info->drmMinor >= 5 ) {
   1030 	ShadowFBInit( pScreen, R128DRIRefreshArea );
   1031     } else if (info->allowPageFlip) {
   1032 	xf86DrvMsg(pScreen->myNum, X_WARNING,
   1033 		   "[dri] Kernel module version 2.5.0 or newer is required for pageflipping.\n");
   1034        info->allowPageFlip = 0;
   1035     }
   1036 
   1037     return TRUE;
   1038 }
   1039 
   1040 /* The screen is being closed, so clean up any state and free any
   1041    resources used by the DRI. */
   1042 void R128DRICloseScreen(ScreenPtr pScreen)
   1043 {
   1044     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
   1045     R128InfoPtr info = R128PTR(pScrn);
   1046     drmR128Init drmInfo;
   1047 
   1048 				/* Stop the CCE if it is still in use */
   1049     if (info->directRenderingEnabled) {
   1050 	R128CCE_STOP(pScrn, info);
   1051     }
   1052 
   1053     if (info->irq) {
   1054 	drmCtlUninstHandler(info->drmFD);
   1055 	info->irq = 0;
   1056 	info->gen_int_cntl = 0;
   1057     }
   1058 
   1059 				/* De-allocate vertex buffers */
   1060     if (info->buffers) {
   1061 	drmUnmapBufs(info->buffers);
   1062 	info->buffers = NULL;
   1063     }
   1064 
   1065 				/* De-allocate all kernel resources */
   1066     memset(&drmInfo, 0, sizeof(drmR128Init));
   1067     drmInfo.func = DRM_R128_CLEANUP_CCE;
   1068     drmCommandWrite(info->drmFD, DRM_R128_INIT,
   1069                     &drmInfo, sizeof(drmR128Init));
   1070 
   1071 				/* De-allocate all AGP resources */
   1072     if (info->agpTex) {
   1073 	drmUnmap(info->agpTex, info->agpTexMapSize);
   1074 	info->agpTex = NULL;
   1075     }
   1076     if (info->buf) {
   1077 	drmUnmap(info->buf, info->bufMapSize);
   1078 	info->buf = NULL;
   1079     }
   1080     if (info->ringReadPtr) {
   1081 	drmUnmap(info->ringReadPtr, info->ringReadMapSize);
   1082 	info->ringReadPtr = NULL;
   1083     }
   1084     if (info->ring) {
   1085 	drmUnmap(info->ring, info->ringMapSize);
   1086 	info->ring = NULL;
   1087     }
   1088     if (info->agpMemHandle != DRM_AGP_NO_HANDLE) {
   1089 	drmAgpUnbind(info->drmFD, info->agpMemHandle);
   1090 	drmAgpFree(info->drmFD, info->agpMemHandle);
   1091 	info->agpMemHandle = DRM_AGP_NO_HANDLE;
   1092 	drmAgpRelease(info->drmFD);
   1093     }
   1094     if (info->pciMemHandle) {
   1095 	drmScatterGatherFree(info->drmFD, info->pciMemHandle);
   1096 	info->pciMemHandle = 0;
   1097     }
   1098 
   1099 				/* De-allocate all DRI resources */
   1100     DRICloseScreen(pScreen);
   1101 
   1102 				/* De-allocate all DRI data structures */
   1103     if (info->pDRIInfo) {
   1104 	if (info->pDRIInfo->devPrivate) {
   1105 	    free(info->pDRIInfo->devPrivate);
   1106 	    info->pDRIInfo->devPrivate = NULL;
   1107 	}
   1108 	DRIDestroyInfoRec(info->pDRIInfo);
   1109 	info->pDRIInfo = NULL;
   1110     }
   1111 }
   1112 
   1113 /* Use callbacks from dri.c to support pageflipping mode for a single
   1114  * 3d context without need for any specific full-screen extension.
   1115  */
   1116 
   1117 /* Use the shadowfb module to maintain a list of dirty rectangles.
   1118  * These are blitted to the back buffer to keep both buffers clean
   1119  * during page-flipping when the 3d application isn't fullscreen.
   1120  *
   1121  * Unlike most use of the shadowfb code, both buffers are in video memory.
   1122  *
   1123  * An alternative to this would be to organize for all on-screen drawing
   1124  * operations to be duplicated for the two buffers.  That might be
   1125  * faster, but seems like a lot more work...
   1126  */
   1127 
   1128 
   1129 static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
   1130 {
   1131     R128InfoPtr         info       = R128PTR(pScrn);
   1132     int                 i;
   1133     R128SAREAPrivPtr    pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
   1134     PixmapPtr		pPix	   = pScrn->pScreen->GetScreenPixmap(pScrn->pScreen);
   1135 
   1136     /* Don't want to do this when no 3d is active and pages are
   1137      * right-way-round
   1138      */
   1139     if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0)
   1140 	return;
   1141 
   1142 #ifdef USE_EXA
   1143     if (info->useEXA) {
   1144         uint32_t src_pitch_offset, dst_pitch_offset, datatype;
   1145 
   1146 	R128GetPixmapOffsetPitch(pPix, &src_pitch_offset);
   1147 	dst_pitch_offset = src_pitch_offset + (info->backOffset >> 5);
   1148 	R128GetDatatypeBpp(pScrn->bitsPerPixel, &datatype);
   1149 	info->xdir = info->ydir = 1;
   1150 
   1151 	R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, GXcopy, ~0);
   1152     }
   1153 #endif
   1154 
   1155     for (i = 0 ; i < num ; i++, pbox++) {
   1156 	int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1);
   1157 	int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1);
   1158 
   1159 	if (xa <= xb && ya <= yb) {
   1160 #ifdef USE_EXA
   1161 	    if (info->useEXA) {
   1162 		(*info->ExaDriver->Copy)(pPix, xa, ya, xa, ya, xb - xa + 1, yb - ya + 1);
   1163 	    }
   1164 #endif
   1165 	}
   1166     }
   1167 }
   1168 
   1169 static void R128EnablePageFlip(ScreenPtr pScreen)
   1170 {
   1171     ScrnInfoPtr         pScrn      = xf86ScreenToScrn(pScreen);
   1172     R128InfoPtr         info       = R128PTR(pScrn);
   1173     R128SAREAPrivPtr    pSAREAPriv = DRIGetSAREAPrivate(pScreen);
   1174     PixmapPtr		pPix	   = pScreen->GetScreenPixmap(pScreen);
   1175 
   1176     if (info->allowPageFlip) {
   1177 	/* Duplicate the frontbuffer to the backbuffer */
   1178 #ifdef USE_EXA
   1179 	if (info->useEXA) {
   1180 	    uint32_t src_pitch_offset, dst_pitch_offset, datatype;
   1181 
   1182 	    R128GetPixmapOffsetPitch(pPix, &src_pitch_offset);
   1183 	    dst_pitch_offset = src_pitch_offset + (info->backOffset >> 5);
   1184 	    R128GetDatatypeBpp(pScrn->bitsPerPixel, &datatype);
   1185 	    info->xdir = info->ydir = 1;
   1186 
   1187             R128DoPrepareCopy(pScrn, src_pitch_offset, dst_pitch_offset, datatype, GXcopy, ~0);
   1188 
   1189 	    (*info->ExaDriver->Copy)(pPix, 0, 0, 0, 0, pScrn->virtualX, pScrn->virtualY);
   1190 	}
   1191 #endif
   1192 
   1193 	pSAREAPriv->pfAllowPageFlip = 1;
   1194     }
   1195 }
   1196 
   1197 static void R128DisablePageFlip(ScreenPtr pScreen)
   1198 {
   1199     /* Tell the clients not to pageflip.  How?
   1200      *   -- Field in sarea, plus bumping the window counters.
   1201      *   -- DRM needs to cope with Front-to-Back swapbuffers.
   1202      */
   1203     R128SAREAPrivPtr  pSAREAPriv = DRIGetSAREAPrivate(pScreen);
   1204 
   1205     pSAREAPriv->pfAllowPageFlip = 0;
   1206 }
   1207 
   1208 static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen)
   1209 {
   1210     R128DisablePageFlip(pScreen);
   1211 }
   1212 
   1213 static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen)
   1214 {
   1215     /* Let the remaining 3d app start page flipping again */
   1216     R128EnablePageFlip(pScreen);
   1217 }
   1218 
   1219 static void R128DRITransitionTo3d(ScreenPtr pScreen)
   1220 {
   1221     ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
   1222     R128InfoPtr    info  = R128PTR(pScrn);
   1223 
   1224     R128EnablePageFlip(pScreen);
   1225 
   1226     info->have3DWindows = 1;
   1227 }
   1228 
   1229 static void R128DRITransitionTo2d(ScreenPtr pScreen)
   1230 {
   1231     ScrnInfoPtr         pScrn      = xf86ScreenToScrn(pScreen);
   1232     R128InfoPtr         info       = R128PTR(pScrn);
   1233     R128SAREAPrivPtr    pSAREAPriv = DRIGetSAREAPrivate(pScreen);
   1234 
   1235     /* Try flipping back to the front page if necessary */
   1236     if (pSAREAPriv->pfCurrentPage == 1)
   1237 	drmCommandNone(info->drmFD, DRM_R128_FLIP);
   1238 
   1239     /* Shut down shadowing if we've made it back to the front page */
   1240     if (pSAREAPriv->pfCurrentPage == 0) {
   1241 	R128DisablePageFlip(pScreen);
   1242     } else {
   1243 	xf86DrvMsg(pScreen->myNum, X_WARNING,
   1244 		   "[dri] R128DRITransitionTo2d: "
   1245 		   "kernel failed to unflip buffers.\n");
   1246     }
   1247 
   1248     info->have3DWindows = 0;
   1249 }
   1250