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