1fe5e51b7Smrg/*
2fe5e51b7Smrg * Copyright 2000 VA Linux Systems Inc., Fremont, California.
3fe5e51b7Smrg * All Rights Reserved.
4fe5e51b7Smrg *
5fe5e51b7Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6fe5e51b7Smrg * copy of this software and associated documentation files (the "Software"),
7fe5e51b7Smrg * to deal in the Software without restriction, including without limitation
8fe5e51b7Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9fe5e51b7Smrg * and/or sell copies of the Software, and to permit persons to whom the
10fe5e51b7Smrg * Software is furnished to do so, subject to the following conditions:
11fe5e51b7Smrg *
12fe5e51b7Smrg * The above copyright notice and this permission notice (including the next
13fe5e51b7Smrg * paragraph) shall be included in all copies or substantial portions of the
14fe5e51b7Smrg * Software.
15fe5e51b7Smrg *
16fe5e51b7Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17fe5e51b7Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18fe5e51b7Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19fe5e51b7Smrg * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES
20fe5e51b7Smrg * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21fe5e51b7Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22fe5e51b7Smrg * OTHER DEALINGS IN THE SOFTWARE.
23fe5e51b7Smrg *
24fe5e51b7Smrg * Authors:
25fe5e51b7Smrg *    Keith Whitwell <keith@tungstengraphics.com>
26fe5e51b7Smrg *    Gareth Hughes <gareth@valinux.com>
27fe5e51b7Smrg */
28fe5e51b7Smrg
29fe5e51b7Smrg#ifdef HAVE_CONFIG_H
30fe5e51b7Smrg#include "config.h"
31fe5e51b7Smrg#endif
32fe5e51b7Smrg
33fe5e51b7Smrg#include "xf86.h"
34fe5e51b7Smrg#include "xf86_OSproc.h"
35fe5e51b7Smrg
36fe5e51b7Smrg#include "xf86Pci.h"
37fe5e51b7Smrg
38fe5e51b7Smrg#include "miline.h"
39fe5e51b7Smrg
40fe5e51b7Smrg#include <errno.h>
41fe5e51b7Smrg
42fe5e51b7Smrg#include <inttypes.h>
43fe5e51b7Smrg#include "mga_reg.h"
44fe5e51b7Smrg#include "mga.h"
45fe5e51b7Smrg#include "mga_macros.h"
46fe5e51b7Smrg#include "mga_dri.h"
47fe5e51b7Smrg#include "mga_sarea.h"
48fe5e51b7Smrg#include "mga_drm.h"
49fe5e51b7Smrg
50fe5e51b7Smrg#define _XF86DRI_SERVER_
51fe5e51b7Smrg#include "sarea.h"
52fe5e51b7Smrg
53fe5e51b7Smrg#include "mga_reg.h"
54fe5e51b7Smrg#include "mga.h"
55fe5e51b7Smrg#include "mga_macros.h"
56fe5e51b7Smrg#include "mga_dri.h"
57fe5e51b7Smrg
58fe5e51b7Smrg#define  DRM_MGA_IDLE_RETRY          2048
59fe5e51b7Smrg
60fe5e51b7Smrgstatic char MGAKernelDriverName[] = "mga";
61fe5e51b7Smrgstatic char MGAClientDriverName[] = "mga";
62fe5e51b7Smrg
63fe5e51b7Smrgstatic Bool MGACreateContext( ScreenPtr pScreen, VisualPtr visual,
64fe5e51b7Smrg			      drm_context_t hwContext, void *pVisualConfigPriv,
65fe5e51b7Smrg			      DRIContextType contextStore )
66fe5e51b7Smrg{
67fe5e51b7Smrg   /* Nothing yet */
68fe5e51b7Smrg   return TRUE;
69fe5e51b7Smrg}
70fe5e51b7Smrg
71fe5e51b7Smrgstatic void MGADestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
72fe5e51b7Smrg			       DRIContextType contextStore )
73fe5e51b7Smrg{
74fe5e51b7Smrg   /* Nothing yet */
75fe5e51b7Smrg}
76fe5e51b7Smrg
77fe5e51b7Smrg
78fe5e51b7Smrg/* Quiescence, locking
79fe5e51b7Smrg */
80fe5e51b7Smrg#define MGA_TIMEOUT		2048
81fe5e51b7Smrg
82fe5e51b7Smrgstatic void MGAWaitForIdleDMA( ScrnInfoPtr pScrn )
83fe5e51b7Smrg{
84fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
85fe5e51b7Smrg   drm_lock_t lock;
86fe5e51b7Smrg   int ret;
87fe5e51b7Smrg   int i = 0;
88fe5e51b7Smrg
89fe5e51b7Smrg   memset( &lock, 0, sizeof(drm_lock_t) );
90fe5e51b7Smrg
91fe5e51b7Smrg   for (;;) {
92fe5e51b7Smrg      do {
93fe5e51b7Smrg         /* first ask for quiescent and flush */
94fe5e51b7Smrg         lock.flags = DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH;
95fe5e51b7Smrg         do {
96fe5e51b7Smrg	    ret = drmCommandWrite( pMga->drmFD, DRM_MGA_FLUSH,
97fe5e51b7Smrg                                   &lock, sizeof( drm_lock_t ) );
98fe5e51b7Smrg         } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
99fe5e51b7Smrg
100fe5e51b7Smrg         /* if it's still busy just try quiescent */
101fe5e51b7Smrg         if ( ret == -EBUSY ) {
102fe5e51b7Smrg            lock.flags = DRM_LOCK_QUIESCENT;
103fe5e51b7Smrg            do {
104fe5e51b7Smrg	       ret = drmCommandWrite( pMga->drmFD, DRM_MGA_FLUSH,
105fe5e51b7Smrg                                      &lock, sizeof( drm_lock_t ) );
106fe5e51b7Smrg            } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
107fe5e51b7Smrg         }
108fe5e51b7Smrg      } while ( ( ret == -EBUSY ) && ( i++ < MGA_TIMEOUT ) );
109fe5e51b7Smrg
110fe5e51b7Smrg      if ( ret == 0 )
111fe5e51b7Smrg	 return;
112fe5e51b7Smrg
113fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
114fe5e51b7Smrg		  "[dri] Idle timed out, resetting engine...\n" );
115fe5e51b7Smrg
116fe5e51b7Smrg      drmCommandNone( pMga->drmFD, DRM_MGA_RESET );
117fe5e51b7Smrg   }
118fe5e51b7Smrg}
119fe5e51b7Smrg
120fe5e51b7Smrg
121fe5e51b7Smrgvoid MGAGetQuiescence( ScrnInfoPtr pScrn )
122fe5e51b7Smrg{
123fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
12481f79626Smrg#ifdef USE_XAA
12581f79626Smrg   MGAFBLayout *pLayout = &pMga->CurrentLayout;
12681f79626Smrg#endif /* USE_XAA */
127fe5e51b7Smrg
128fe5e51b7Smrg   pMga->haveQuiescense = 1;
129fe5e51b7Smrg
130fe5e51b7Smrg   if ( pMga->directRenderingEnabled ) {
131fe5e51b7Smrg      MGAWaitForIdleDMA( pScrn );
132fe5e51b7Smrg
133fe5e51b7Smrg        /* FIXME what about EXA? */
134acd6767fSmrg#ifdef USE_XAA
135fe5e51b7Smrg        if (!pMga->Exa && pMga->AccelInfoRec) {
136fe5e51b7Smrg      WAITFIFO( 11 );
137fe5e51b7Smrg      OUTREG( MGAREG_MACCESS, pMga->MAccess );
138fe5e51b7Smrg      OUTREG( MGAREG_PITCH, pLayout->displayWidth );
139fe5e51b7Smrg
140fe5e51b7Smrg      pMga->PlaneMask = ~0;
141fe5e51b7Smrg      OUTREG( MGAREG_PLNWT, pMga->PlaneMask );
142fe5e51b7Smrg
143fe5e51b7Smrg      pMga->BgColor = 0;
144fe5e51b7Smrg      pMga->FgColor = 0;
145fe5e51b7Smrg      OUTREG( MGAREG_BCOL, pMga->BgColor );
146fe5e51b7Smrg      OUTREG( MGAREG_FCOL, pMga->FgColor );
147fe5e51b7Smrg      OUTREG( MGAREG_SRCORG, pMga->realSrcOrg );
148fe5e51b7Smrg
149fe5e51b7Smrg      pMga->SrcOrg = 0;
150fe5e51b7Smrg      OUTREG( MGAREG_DSTORG, pMga->DstOrg );
151fe5e51b7Smrg      OUTREG( MGAREG_OPMODE, MGAOPM_DMA_BLIT );
152fe5e51b7Smrg      OUTREG( MGAREG_CXBNDRY, 0xFFFF0000 ); /* (maxX << 16) | minX */
153fe5e51b7Smrg      OUTREG( MGAREG_YTOP, 0x00000000 );    /* minPixelPointer */
154fe5e51b7Smrg      OUTREG( MGAREG_YBOT, 0x007FFFFF );    /* maxPixelPointer */
155fe5e51b7Smrg
156fe5e51b7Smrg            pMga->AccelFlags &= ~CLIPPER_ON;
157fe5e51b7Smrg        }
158fe5e51b7Smrg#endif
159fe5e51b7Smrg   }
160fe5e51b7Smrg}
161fe5e51b7Smrg
162fe5e51b7Smrgvoid MGAGetQuiescenceShared( ScrnInfoPtr pScrn )
163fe5e51b7Smrg{
164fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
165fe5e51b7Smrg   MGAEntPtr pMGAEnt = pMga->entityPrivate;
166fe5e51b7Smrg   MGAPtr pMGA2 = MGAPTR(pMGAEnt->pScrn_2);
167fe5e51b7Smrg
168fe5e51b7Smrg   pMga = MGAPTR(pMGAEnt->pScrn_1);
169fe5e51b7Smrg   pMga->haveQuiescense = 1;
170fe5e51b7Smrg   pMGA2->haveQuiescense = 1;
171fe5e51b7Smrg
172fe5e51b7Smrg   if ( pMGAEnt->directRenderingEnabled ) {
173fe5e51b7Smrg      MGAWaitForIdleDMA( pMGAEnt->pScrn_1 );
174fe5e51b7Smrg
175fe5e51b7Smrg        /* FIXME what about EXA? */
176fe5e51b7Smrg#ifdef USE_XAA
177fe5e51b7Smrg        if (!pMga->Exa && pMga->AccelInfoRec)
178fe5e51b7Smrg            pMga->RestoreAccelState( pScrn );
179fe5e51b7Smrg#endif
180fe5e51b7Smrg      xf86SetLastScrnFlag( pScrn->entityList[0], pScrn->scrnIndex );
181fe5e51b7Smrg   }
182fe5e51b7Smrg}
183fe5e51b7Smrg
184fe5e51b7Smrgstatic void MGASwapContext( ScreenPtr pScreen )
185fe5e51b7Smrg{
1860bb88ba4Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
187fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
188fe5e51b7Smrg
189fe5e51b7Smrg   /* Arrange for dma_quiescence and xaa sync to be called as
190fe5e51b7Smrg    * appropriate.
191fe5e51b7Smrg    */
192fe5e51b7Smrg   pMga->haveQuiescense = 0;
193fe5e51b7Smrg
194fe5e51b7Smrg   MGA_MARK_SYNC(pMga, pScrn);
195fe5e51b7Smrg}
196fe5e51b7Smrg
197fe5e51b7Smrgstatic void MGASwapContextShared( ScreenPtr pScreen )
198fe5e51b7Smrg{
1990bb88ba4Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
200fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
201fe5e51b7Smrg   MGAEntPtr pMGAEnt = pMga->entityPrivate;
202fe5e51b7Smrg   MGAPtr pMGA2 = MGAPTR(pMGAEnt->pScrn_2);
203fe5e51b7Smrg
204fe5e51b7Smrg   pMga = MGAPTR(pMGAEnt->pScrn_1);
205fe5e51b7Smrg
206fe5e51b7Smrg   pMga->haveQuiescense = pMGA2->haveQuiescense = 0;
207fe5e51b7Smrg
208fe5e51b7Smrg   MGA_MARK_SYNC(pMga, pScrn);
209fe5e51b7Smrg   MGA_MARK_SYNC(pMGA2, pMGAEnt->pScrn_2);
210fe5e51b7Smrg}
211fe5e51b7Smrg
212fe5e51b7Smrg/* FIXME: This comment is out of date, since we aren't overriding
213fe5e51b7Smrg * Block/Wakeuphandler anymore.
214fe5e51b7Smrg *
215fe5e51b7Smrg *
216fe5e51b7Smrg * This is really only called from validate/postvalidate as we
217fe5e51b7Smrg * override the dri lock/unlock.  Want to remove validate/postvalidate
218fe5e51b7Smrg * processing, but need to remove all client-side use of drawable lock
219d2b10af6Smrg * first (otherwise there is no one recover when a client dies holding
220fe5e51b7Smrg * the drawable lock).
221fe5e51b7Smrg *
222fe5e51b7Smrg * What does this mean?
223fe5e51b7Smrg *
224fe5e51b7Smrg *   - The above code gets executed every time a
225fe5e51b7Smrg *     window changes shape or the focus changes, which isn't really
226fe5e51b7Smrg *     optimal.
227fe5e51b7Smrg *   - The X server therefore believes it needs to do an XAA sync
228fe5e51b7Smrg *     *and* a dma quiescense ioctl each time that happens.
229fe5e51b7Smrg *
230fe5e51b7Smrg * We don't wrap wakeuphandler any longer, so at least we can say that
231fe5e51b7Smrg * this doesn't happen *every time the mouse moves*...
232fe5e51b7Smrg */
233fe5e51b7Smrgstatic void
234fe5e51b7SmrgMGADRISwapContext( ScreenPtr pScreen, DRISyncType syncType,
235fe5e51b7Smrg		   DRIContextType oldContextType, void *oldContext,
236fe5e51b7Smrg		   DRIContextType newContextType, void *newContext )
237fe5e51b7Smrg{
238fe5e51b7Smrg   if ( syncType == DRI_3D_SYNC &&
239fe5e51b7Smrg	oldContextType == DRI_2D_CONTEXT &&
240fe5e51b7Smrg	newContextType == DRI_2D_CONTEXT )
241fe5e51b7Smrg   {
242fe5e51b7Smrg      MGASwapContext( pScreen );
243fe5e51b7Smrg   }
244fe5e51b7Smrg}
245fe5e51b7Smrg
246fe5e51b7Smrgstatic void
247fe5e51b7SmrgMGADRISwapContextShared( ScreenPtr pScreen, DRISyncType syncType,
248fe5e51b7Smrg			  DRIContextType oldContextType, void *oldContext,
249fe5e51b7Smrg			  DRIContextType newContextType, void *newContext )
250fe5e51b7Smrg{
251fe5e51b7Smrg   if ( syncType == DRI_3D_SYNC &&
252fe5e51b7Smrg	oldContextType == DRI_2D_CONTEXT &&
253fe5e51b7Smrg	newContextType == DRI_2D_CONTEXT )
254fe5e51b7Smrg   {
255fe5e51b7Smrg      MGASwapContextShared( pScreen );
256fe5e51b7Smrg   }
257fe5e51b7Smrg}
258fe5e51b7Smrg
259fe5e51b7Smrgvoid MGASelectBuffer( ScrnInfoPtr pScrn, int which )
260fe5e51b7Smrg{
261fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
262fe5e51b7Smrg   MGADRIPtr pMGADRI = (MGADRIPtr)pMga->pDRIInfo->devPrivate;
263fe5e51b7Smrg
264fe5e51b7Smrg   switch ( which ) {
265fe5e51b7Smrg   case MGA_BACK:
266fe5e51b7Smrg      OUTREG( MGAREG_DSTORG, pMGADRI->backOffset );
267fe5e51b7Smrg      OUTREG( MGAREG_SRCORG, pMGADRI->backOffset );
268fe5e51b7Smrg      break;
269fe5e51b7Smrg   case MGA_DEPTH:
270fe5e51b7Smrg      OUTREG( MGAREG_DSTORG, pMGADRI->depthOffset );
271fe5e51b7Smrg      OUTREG( MGAREG_SRCORG, pMGADRI->depthOffset );
272fe5e51b7Smrg      break;
273fe5e51b7Smrg   default:
274fe5e51b7Smrg   case MGA_FRONT:
275fe5e51b7Smrg      OUTREG( MGAREG_DSTORG, pMGADRI->frontOffset );
276fe5e51b7Smrg      OUTREG( MGAREG_SRCORG, pMGADRI->frontOffset );
277fe5e51b7Smrg      break;
278fe5e51b7Smrg   }
279fe5e51b7Smrg}
280fe5e51b7Smrg
281fe5e51b7Smrgstatic unsigned int mylog2( unsigned int n )
282fe5e51b7Smrg{
283fe5e51b7Smrg   unsigned int log2 = 1;
284fe5e51b7Smrg   while ( n > 1 ) n >>= 1, log2++;
285fe5e51b7Smrg   return log2;
286fe5e51b7Smrg}
287fe5e51b7Smrg
288fe5e51b7Smrg/**
289fe5e51b7Smrg * Initialize DMA and secondary texture memory
290fe5e51b7Smrg *
291fe5e51b7Smrg * \todo
292fe5e51b7Smrg * The sizes used for the primary DMA buffer and the bin size and count for
293fe5e51b7Smrg * the secondary DMA buffers should be configurable from the xorg.conf.
294fe5e51b7Smrg *
295fe5e51b7Smrg * \todo
296fe5e51b7Smrg * This routine should use \c mga_bios_values::host_interface to limit the
297fe5e51b7Smrg * AGP mode.  It the card is PCI, \c MGARec::agpSize should be forced to 0.
298fe5e51b7Smrg */
299fe5e51b7Smrgstatic Bool MGADRIBootstrapDMA(ScreenPtr pScreen)
300fe5e51b7Smrg{
3010bb88ba4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
302fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
303fe5e51b7Smrg    MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
304fe5e51b7Smrg    int ret;
305fe5e51b7Smrg    int requested_agp_mode;
306fe5e51b7Smrg    int count;
307fe5e51b7Smrg
308fe5e51b7Smrg
309fe5e51b7Smrg    if(pMga->agpSize < 12)pMga->agpSize = 12;
310fe5e51b7Smrg    if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */
311fe5e51b7Smrg
312fe5e51b7Smrg
313fe5e51b7Smrg    requested_agp_mode = 0;
314fe5e51b7Smrg    switch ( pMga->agpMode ) {
315fe5e51b7Smrg    case 4:
316fe5e51b7Smrg	requested_agp_mode |= MGA_AGP_4X_MODE;
317fe5e51b7Smrg    case 2:
318fe5e51b7Smrg	requested_agp_mode |= MGA_AGP_2X_MODE;
319fe5e51b7Smrg    case 1:
320fe5e51b7Smrg    default:
321fe5e51b7Smrg	requested_agp_mode |= MGA_AGP_1X_MODE;
322fe5e51b7Smrg    }
323fe5e51b7Smrg
324fe5e51b7Smrg
325fe5e51b7Smrg    if ( (pMGADRIServer->drm_version_minor >= 2) && !pMga->useOldDmaInit ) {
326fe5e51b7Smrg	drm_mga_dma_bootstrap_t dma_bs;
327fe5e51b7Smrg
328fe5e51b7Smrg
329fe5e51b7Smrg	(void) memset( & dma_bs, 0, sizeof( dma_bs ) );
330fe5e51b7Smrg	dma_bs.primary_size = 1024 * 1024;
331fe5e51b7Smrg	dma_bs.secondary_bin_count = MGA_NUM_BUFFERS;
332fe5e51b7Smrg	dma_bs.secondary_bin_size = MGA_BUFFER_SIZE;
333fe5e51b7Smrg	dma_bs.agp_size = pMga->agpSize;
334fe5e51b7Smrg	dma_bs.agp_mode = (pMga->forcePciDma) ? 0 : requested_agp_mode;
335fe5e51b7Smrg
336fe5e51b7Smrg	ret = drmCommandWriteRead( pMga->drmFD, DRM_MGA_DMA_BOOTSTRAP,
337fe5e51b7Smrg				   & dma_bs, sizeof( dma_bs ) );
338fe5e51b7Smrg	if ( ret ) {
339fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Could not boot-strap DMA (%d)\n", ret );
340fe5e51b7Smrg	    return FALSE;
341fe5e51b7Smrg	}
342fe5e51b7Smrg
343fe5e51b7Smrg	pMga->agpMode = dma_bs.agp_mode;
344fe5e51b7Smrg	pMGADRIServer->agp.size = dma_bs.agp_size;
345fe5e51b7Smrg
346fe5e51b7Smrg	pMGADRIServer->agpTextures.handle = dma_bs.texture_handle;
347fe5e51b7Smrg	pMGADRIServer->agpTextures.size   = dma_bs.texture_size;
348fe5e51b7Smrg    }
349fe5e51b7Smrg    else {
350fe5e51b7Smrg	unsigned long mode;
351fe5e51b7Smrg	unsigned int vendor, device;
352fe5e51b7Smrg	int i;
353fe5e51b7Smrg
354fe5e51b7Smrg
355fe5e51b7Smrg	if ( pMga->forcePciDma ) {
356fe5e51b7Smrg	    const char * const msg = (pMGADRIServer->drm_version_minor < 2)
357fe5e51b7Smrg	      ? "DRM version is too old (3.2 or later required)"
358fe5e51b7Smrg	      : "old DMA init path was requested";
359fe5e51b7Smrg
360fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_WARNING,
361fe5e51b7Smrg			"[agp] Cannot force PCI DMA because %s\n", msg );
362fe5e51b7Smrg	}
363fe5e51b7Smrg
364fe5e51b7Smrg	if ( drmAgpAcquire( pMga->drmFD ) < 0 ) {
365fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not available\n" );
366fe5e51b7Smrg	    return FALSE;
367fe5e51b7Smrg	}
368fe5e51b7Smrg
369fe5e51b7Smrg	mode   = drmAgpGetMode( pMga->drmFD );        /* Default mode */
370fe5e51b7Smrg	vendor = drmAgpVendorId( pMga->drmFD );
371fe5e51b7Smrg	device = drmAgpDeviceId( pMga->drmFD );
372fe5e51b7Smrg
373fe5e51b7Smrg	mode = (mode & ~MGA_AGP_MODE_MASK) | requested_agp_mode;
374fe5e51b7Smrg
375fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
376fe5e51b7Smrg		    "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
377fe5e51b7Smrg		    mode, vendor, device,
378fe5e51b7Smrg		    VENDOR_ID(pMga->PciInfo),
379fe5e51b7Smrg		    DEVICE_ID(pMga->PciInfo));
380fe5e51b7Smrg
381fe5e51b7Smrg	if ( drmAgpEnable( pMga->drmFD, mode ) < 0 ) {
382fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
383fe5e51b7Smrg	    drmAgpRelease( pMga->drmFD );
384fe5e51b7Smrg	    return FALSE;
385fe5e51b7Smrg	}
386fe5e51b7Smrg
387fe5e51b7Smrg	if ( pMga->Chipset == PCI_CHIP_MGAG200 ) {
388fe5e51b7Smrg	    switch ( pMga->agpMode ) {
389fe5e51b7Smrg	    case 2:
390fe5e51b7Smrg		xf86DrvMsg( pScreen->myNum, X_INFO,
391fe5e51b7Smrg			    "[drm] Enabling AGP 2x PLL encoding\n" );
392fe5e51b7Smrg		OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE );
393fe5e51b7Smrg		break;
394fe5e51b7Smrg
395fe5e51b7Smrg	    case 1:
396fe5e51b7Smrg	    default:
397fe5e51b7Smrg		xf86DrvMsg( pScreen->myNum, X_INFO,
398fe5e51b7Smrg			    "[drm] Disabling AGP 2x PLL encoding\n" );
399fe5e51b7Smrg		OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE );
400fe5e51b7Smrg		pMga->agpMode = 1;
401fe5e51b7Smrg		break;
402fe5e51b7Smrg	    }
403fe5e51b7Smrg	}
404fe5e51b7Smrg
405fe5e51b7Smrg	pMGADRIServer->agp.size = pMga->agpSize * 1024 * 1024;
406fe5e51b7Smrg
407fe5e51b7Smrg	pMGADRIServer->warp.offset = 0;
408fe5e51b7Smrg	pMGADRIServer->warp.size = MGA_WARP_UCODE_SIZE;
409fe5e51b7Smrg
410fe5e51b7Smrg	pMGADRIServer->primary.offset = (pMGADRIServer->warp.offset +
411fe5e51b7Smrg					 pMGADRIServer->warp.size);
412fe5e51b7Smrg	pMGADRIServer->primary.size = 1024 * 1024;
413fe5e51b7Smrg
414fe5e51b7Smrg	pMGADRIServer->buffers.offset = (pMGADRIServer->primary.offset +
415fe5e51b7Smrg					 pMGADRIServer->primary.size);
416fe5e51b7Smrg	pMGADRIServer->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE;
417fe5e51b7Smrg
418fe5e51b7Smrg
419fe5e51b7Smrg	pMGADRIServer->agpTextures.offset = (pMGADRIServer->buffers.offset +
420fe5e51b7Smrg					     pMGADRIServer->buffers.size);
421fe5e51b7Smrg
422fe5e51b7Smrg	pMGADRIServer->agpTextures.size = (pMGADRIServer->agp.size -
423fe5e51b7Smrg					   pMGADRIServer->agpTextures.offset);
424fe5e51b7Smrg
425fe5e51b7Smrg	ret = drmAgpAlloc( pMga->drmFD, pMGADRIServer->agp.size,
426fe5e51b7Smrg			   0, NULL, &pMGADRIServer->agp.handle );
427fe5e51b7Smrg	if ( ret < 0 ) {
428fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
429fe5e51b7Smrg	    drmAgpRelease( pMga->drmFD );
430fe5e51b7Smrg	    return FALSE;
431fe5e51b7Smrg	}
432fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
433fe5e51b7Smrg 		    "[agp] %d kB allocated with handle 0x%08x\n",
434fe5e51b7Smrg		    pMGADRIServer->agp.size/1024,
435fe5e51b7Smrg		    (unsigned int) pMGADRIServer->agp.handle );
436fe5e51b7Smrg
437fe5e51b7Smrg	if ( drmAgpBind( pMga->drmFD, pMGADRIServer->agp.handle, 0 ) < 0 ) {
438fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind memory\n" );
439fe5e51b7Smrg	    drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle );
440fe5e51b7Smrg	    drmAgpRelease( pMga->drmFD );
441fe5e51b7Smrg	    return FALSE;
442fe5e51b7Smrg	}
443fe5e51b7Smrg
444fe5e51b7Smrg	/* WARP microcode space
445fe5e51b7Smrg	 */
446fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
447fe5e51b7Smrg			pMGADRIServer->warp.offset,
448fe5e51b7Smrg			pMGADRIServer->warp.size,
449fe5e51b7Smrg			DRM_AGP, DRM_READ_ONLY,
450fe5e51b7Smrg			&pMGADRIServer->warp.handle ) < 0 ) {
451fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
452fe5e51b7Smrg			"[agp] Could not add WARP microcode mapping\n" );
453fe5e51b7Smrg	    return FALSE;
454fe5e51b7Smrg	}
455fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
456fe5e51b7Smrg 		    "[agp] WARP microcode handle = 0x%08x\n",
457fe5e51b7Smrg		    (unsigned int) pMGADRIServer->warp.handle );
458fe5e51b7Smrg
459fe5e51b7Smrg	/* Primary DMA space
460fe5e51b7Smrg	 */
461fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
462fe5e51b7Smrg			pMGADRIServer->primary.offset,
463fe5e51b7Smrg			pMGADRIServer->primary.size,
464fe5e51b7Smrg			DRM_AGP, DRM_READ_ONLY,
465fe5e51b7Smrg			&pMGADRIServer->primary.handle ) < 0 ) {
466fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
467fe5e51b7Smrg			"[agp] Could not add primary DMA mapping\n" );
468fe5e51b7Smrg	    return FALSE;
469fe5e51b7Smrg	}
470fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
471fe5e51b7Smrg 		    "[agp] Primary DMA handle = 0x%08x\n",
472fe5e51b7Smrg		    (unsigned int) pMGADRIServer->primary.handle );
473fe5e51b7Smrg
474fe5e51b7Smrg	/* DMA buffers
475fe5e51b7Smrg	 */
476fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
477fe5e51b7Smrg			pMGADRIServer->buffers.offset,
478fe5e51b7Smrg			pMGADRIServer->buffers.size,
479fe5e51b7Smrg			DRM_AGP, 0,
480fe5e51b7Smrg			&pMGADRIServer->buffers.handle ) < 0 ) {
481fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
482fe5e51b7Smrg			"[agp] Could not add DMA buffers mapping\n" );
483fe5e51b7Smrg	    return FALSE;
484fe5e51b7Smrg	}
485fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
486fe5e51b7Smrg 		    "[agp] DMA buffers handle = 0x%08x\n",
487fe5e51b7Smrg		    (unsigned int) pMGADRIServer->buffers.handle );
488fe5e51b7Smrg
489fe5e51b7Smrg	count = drmAddBufs( pMga->drmFD,
490fe5e51b7Smrg			    MGA_NUM_BUFFERS, MGA_BUFFER_SIZE,
491fe5e51b7Smrg			    DRM_AGP_BUFFER, pMGADRIServer->buffers.offset );
492fe5e51b7Smrg	if ( count <= 0 ) {
493fe5e51b7Smrg	    xf86DrvMsg( pScrn->scrnIndex, X_INFO,
494fe5e51b7Smrg			"[drm] failure adding %d %d byte DMA buffers\n",
495fe5e51b7Smrg			MGA_NUM_BUFFERS, MGA_BUFFER_SIZE );
496fe5e51b7Smrg	    return FALSE;
497fe5e51b7Smrg	}
498fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
499fe5e51b7Smrg		    "[drm] Added %d %d byte DMA buffers\n",
500fe5e51b7Smrg		    count, MGA_BUFFER_SIZE );
501fe5e51b7Smrg
502fe5e51b7Smrg	i = mylog2(pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS);
503fe5e51b7Smrg	if(i < MGA_LOG_MIN_TEX_REGION_SIZE)
504fe5e51b7Smrg	  i = MGA_LOG_MIN_TEX_REGION_SIZE;
505fe5e51b7Smrg	pMGADRIServer->agpTextures.size = (pMGADRIServer->agpTextures.size >> i) << i;
506fe5e51b7Smrg
507fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
508fe5e51b7Smrg			pMGADRIServer->agpTextures.offset,
509fe5e51b7Smrg			pMGADRIServer->agpTextures.size,
510fe5e51b7Smrg			DRM_AGP, 0,
511fe5e51b7Smrg			&pMGADRIServer->agpTextures.handle ) < 0 ) {
512fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
513fe5e51b7Smrg			"[agp] Could not add agpTexture mapping\n" );
514fe5e51b7Smrg	    return FALSE;
515fe5e51b7Smrg	}
516fe5e51b7Smrg
517fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
518fe5e51b7Smrg 		    "[agp] agpTexture handle = 0x%08x\n",
519fe5e51b7Smrg		    (unsigned int) pMGADRIServer->agpTextures.handle );
520fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
521fe5e51b7Smrg		    "[agp] agpTexture size: %d kb\n", pMGADRIServer->agpTextures.size/1024 );
522fe5e51b7Smrg
523fe5e51b7Smrg	pMGADRIServer->registers.size = MGAIOMAPSIZE;
524fe5e51b7Smrg
525fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD,
526fe5e51b7Smrg			(drm_handle_t) MGA_IO_ADDRESS(pMga),
527fe5e51b7Smrg			pMGADRIServer->registers.size,
528fe5e51b7Smrg			DRM_REGISTERS, DRM_READ_ONLY,
529fe5e51b7Smrg			&pMGADRIServer->registers.handle ) < 0 ) {
530fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
531fe5e51b7Smrg			"[drm] Could not add MMIO registers mapping\n" );
532fe5e51b7Smrg	    return FALSE;
533fe5e51b7Smrg	}
534fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
535fe5e51b7Smrg 		    "[drm] Registers handle = 0x%08x\n",
536fe5e51b7Smrg		    (unsigned int) pMGADRIServer->registers.handle );
537fe5e51b7Smrg
538fe5e51b7Smrg	pMGADRIServer->status.size = SAREA_MAX;
539fe5e51b7Smrg
540fe5e51b7Smrg	if ( drmAddMap( pMga->drmFD, 0, pMGADRIServer->status.size,
541fe5e51b7Smrg			DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL,
542fe5e51b7Smrg			&pMGADRIServer->status.handle ) < 0 ) {
543fe5e51b7Smrg	    xf86DrvMsg( pScreen->myNum, X_ERROR,
544fe5e51b7Smrg			"[drm] Could not add status page mapping\n" );
545fe5e51b7Smrg	    return FALSE;
546fe5e51b7Smrg	}
547fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_INFO,
548fe5e51b7Smrg 		    "[drm] Status handle = 0x%08x\n",
549fe5e51b7Smrg		    (unsigned int) pMGADRIServer->status.handle );
550fe5e51b7Smrg    }
551fe5e51b7Smrg
552fe5e51b7Smrg    return TRUE;
553fe5e51b7Smrg}
554fe5e51b7Smrg
555fe5e51b7Smrgstatic Bool MGADRIKernelInit( ScreenPtr pScreen )
556fe5e51b7Smrg{
5570bb88ba4Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
558fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
559fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
560fe5e51b7Smrg   drm_mga_init_t init;
561fe5e51b7Smrg   int ret;
562fe5e51b7Smrg
563fe5e51b7Smrg
564fe5e51b7Smrg   if (!pMga->chip_attribs->dri_capable) {
565fe5e51b7Smrg       return FALSE;
566fe5e51b7Smrg   }
567fe5e51b7Smrg
568fe5e51b7Smrg   memset( &init, 0, sizeof(drm_mga_init_t) );
569fe5e51b7Smrg
570fe5e51b7Smrg   init.func = MGA_INIT_DMA;
571fe5e51b7Smrg   init.sarea_priv_offset = sizeof(XF86DRISAREARec);
572fe5e51b7Smrg   init.chipset = pMga->chip_attribs->dri_chipset;
573fe5e51b7Smrg   init.sgram = !pMga->HasSDRAM;
574fe5e51b7Smrg
575fe5e51b7Smrg   init.maccess = pMga->MAccess;
576fe5e51b7Smrg
577fe5e51b7Smrg   init.fb_cpp		= pScrn->bitsPerPixel / 8;
578fe5e51b7Smrg   init.front_offset	= pMGADRIServer->frontOffset;
579fe5e51b7Smrg   init.front_pitch	= pMGADRIServer->frontPitch / init.fb_cpp;
580fe5e51b7Smrg   init.back_offset	= pMGADRIServer->backOffset;
581fe5e51b7Smrg   init.back_pitch	= pMGADRIServer->backPitch / init.fb_cpp;
582fe5e51b7Smrg
583fe5e51b7Smrg   init.depth_cpp	= pScrn->bitsPerPixel / 8;
584fe5e51b7Smrg   init.depth_offset	= pMGADRIServer->depthOffset;
585fe5e51b7Smrg   init.depth_pitch	= pMGADRIServer->depthPitch / init.depth_cpp;
586fe5e51b7Smrg
587fe5e51b7Smrg   init.texture_offset[0] = pMGADRIServer->textureOffset;
588fe5e51b7Smrg   init.texture_size[0] = pMGADRIServer->textureSize;
589fe5e51b7Smrg
590fe5e51b7Smrg   init.fb_offset = pMGADRIServer->fb.handle;
591fe5e51b7Smrg   init.mmio_offset = pMGADRIServer->registers.handle;
592fe5e51b7Smrg   init.status_offset = pMGADRIServer->status.handle;
593fe5e51b7Smrg
594fe5e51b7Smrg   init.warp_offset = pMGADRIServer->warp.handle;
595fe5e51b7Smrg   init.primary_offset = pMGADRIServer->primary.handle;
596fe5e51b7Smrg   init.buffers_offset = pMGADRIServer->buffers.handle;
597fe5e51b7Smrg
598fe5e51b7Smrg   init.texture_offset[1] = pMGADRIServer->agpTextures.handle;
599fe5e51b7Smrg   init.texture_size[1] = pMGADRIServer->agpTextures.size;
600fe5e51b7Smrg
601fe5e51b7Smrg   ret = drmCommandWrite( pMga->drmFD, DRM_MGA_INIT, &init, sizeof(drm_mga_init_t));
602fe5e51b7Smrg   if ( ret < 0 ) {
603fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
604fe5e51b7Smrg		  "[drm] Failed to initialize DMA! (%d)\n", ret );
605fe5e51b7Smrg      return FALSE;
606fe5e51b7Smrg   }
607fe5e51b7Smrg
608fe5e51b7Smrg
609fe5e51b7Smrg   return TRUE;
610fe5e51b7Smrg}
611fe5e51b7Smrg
612fe5e51b7Smrg/* FIXME: This function uses the DRM to get the IRQ, but the pci_device
613fe5e51b7Smrg * FIXME: structure (PciInfo) already has that information.
614fe5e51b7Smrg */
615fe5e51b7Smrgstatic void MGADRIIrqInit(MGAPtr pMga, ScreenPtr pScreen)
616fe5e51b7Smrg{
6170bb88ba4Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
618fe5e51b7Smrg
619fe5e51b7Smrg   if (!pMga->irq) {
620fe5e51b7Smrg      pMga->irq = drmGetInterruptFromBusID(pMga->drmFD,
621fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
622fe5e51b7Smrg					   ((pMga->PciInfo->domain << 8) |
623fe5e51b7Smrg					    pMga->PciInfo->bus),
624fe5e51b7Smrg					   pMga->PciInfo->dev,
625fe5e51b7Smrg					   pMga->PciInfo->func
626fe5e51b7Smrg#else
627fe5e51b7Smrg	 ((pciConfigPtr)pMga->PciInfo->thisCard)->busnum,
628fe5e51b7Smrg	 ((pciConfigPtr)pMga->PciInfo->thisCard)->devnum,
629fe5e51b7Smrg	 ((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum
630fe5e51b7Smrg#endif
631fe5e51b7Smrg					   );
632fe5e51b7Smrg
633fe5e51b7Smrg      if((drmCtlInstHandler(pMga->drmFD, pMga->irq)) != 0) {
634fe5e51b7Smrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
635fe5e51b7Smrg		    "[drm] failure adding irq handler, "
636fe5e51b7Smrg		    "there is a device already using that irq\n"
637fe5e51b7Smrg		    "[drm] falling back to irq-free operation\n");
638fe5e51b7Smrg	 pMga->irq = 0;
639fe5e51b7Smrg      } else {
640fe5e51b7Smrg          pMga->reg_ien = INREG( MGAREG_IEN );
641fe5e51b7Smrg      }
642fe5e51b7Smrg   }
643fe5e51b7Smrg
644fe5e51b7Smrg   if (pMga->irq)
645fe5e51b7Smrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
646fe5e51b7Smrg		 "[drm] dma control initialized, using IRQ %d\n",
647fe5e51b7Smrg		 pMga->irq);
648fe5e51b7Smrg}
649fe5e51b7Smrg
650fe5e51b7Smrgstatic Bool MGADRIBuffersInit( ScreenPtr pScreen )
651fe5e51b7Smrg{
6520bb88ba4Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
653fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
654fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
655fe5e51b7Smrg
656fe5e51b7Smrg
657fe5e51b7Smrg   pMGADRIServer->drmBuffers = drmMapBufs( pMga->drmFD );
658fe5e51b7Smrg   if ( !pMGADRIServer->drmBuffers ) {
659fe5e51b7Smrg	xf86DrvMsg( pScreen->myNum, X_ERROR,
660fe5e51b7Smrg		    "[drm] Failed to map DMA buffers list\n" );
661fe5e51b7Smrg	return FALSE;
662fe5e51b7Smrg    }
663fe5e51b7Smrg    xf86DrvMsg( pScreen->myNum, X_INFO,
664fe5e51b7Smrg		"[drm] Mapped %d DMA buffers\n",
665fe5e51b7Smrg		pMGADRIServer->drmBuffers->count );
666fe5e51b7Smrg
667fe5e51b7Smrg    return TRUE;
668fe5e51b7Smrg}
669fe5e51b7Smrg
670fe5e51b7Smrg#ifdef USE_XAA
671fe5e51b7Smrgstatic void MGADRIInitBuffersXAA(WindowPtr pWin, RegionPtr prgn,
672fe5e51b7Smrg                                 CARD32 index)
673fe5e51b7Smrg{
674fe5e51b7Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
6750bb88ba4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
676fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
677fe5e51b7Smrg    BoxPtr pbox = REGION_RECTS(prgn);
678fe5e51b7Smrg    int nbox  = REGION_NUM_RECTS(prgn);
679fe5e51b7Smrg    XAAInfoRecPtr xaa = pMga->AccelInfoRec;
680fe5e51b7Smrg
681fe5e51b7Smrg    CHECK_DMA_QUIESCENT(MGAPTR(pScrn), pScrn);
682fe5e51b7Smrg
683fe5e51b7Smrg    xaa->SetupForSolidFill(pScrn, 0, GXcopy, -1);
684fe5e51b7Smrg
685fe5e51b7Smrg    while (nbox--) {
686fe5e51b7Smrg        MGASelectBuffer(pScrn, MGA_BACK);
687fe5e51b7Smrg        xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
688fe5e51b7Smrg                                     pbox->x2-pbox->x1, pbox->y2-pbox->y1);
689fe5e51b7Smrg        MGASelectBuffer(pScrn, MGA_DEPTH);
690fe5e51b7Smrg        xaa->SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
691fe5e51b7Smrg                                     pbox->x2-pbox->x1, pbox->y2-pbox->y1);
692fe5e51b7Smrg        pbox++;
693fe5e51b7Smrg    }
694fe5e51b7Smrg
695fe5e51b7Smrg    MGASelectBuffer(pScrn, MGA_FRONT);
696fe5e51b7Smrg
697fe5e51b7Smrg    pMga->AccelInfoRec->NeedToSync = TRUE;
698fe5e51b7Smrg}
699fe5e51b7Smrg#endif
700fe5e51b7Smrg
701fe5e51b7Smrgstatic void MGADRIInitBuffersEXA(WindowPtr pWin, RegionPtr prgn,
702fe5e51b7Smrg                                 CARD32 index)
703fe5e51b7Smrg{
704fe5e51b7Smrg    /* FIXME */
705fe5e51b7Smrg}
706fe5e51b7Smrg
707fe5e51b7Smrg#ifdef USE_XAA
708fe5e51b7Smrg/*
709fe5e51b7Smrg  This routine is a modified form of XAADoBitBlt with the calls to
710fe5e51b7Smrg  ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
711fe5e51b7Smrg  instead of destination. My origin is upside down so the ydir cases
712fe5e51b7Smrg  are reversed.
713fe5e51b7Smrg*/
714fe5e51b7Smrgstatic void MGADRIMoveBuffersXAA(WindowPtr pParent, DDXPointRec ptOldOrg,
715fe5e51b7Smrg                                 RegionPtr prgnSrc, CARD32 index)
716fe5e51b7Smrg{
717fe5e51b7Smrg    ScreenPtr pScreen = pParent->drawable.pScreen;
7180bb88ba4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
719fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
720fe5e51b7Smrg    int nbox;
721fe5e51b7Smrg    BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
722fe5e51b7Smrg    DDXPointPtr pptTmp, pptNew1, pptNew2;
723fe5e51b7Smrg    int xdir, ydir;
724fe5e51b7Smrg    int dx, dy;
725fe5e51b7Smrg    DDXPointPtr pptSrc;
726fe5e51b7Smrg    int screenwidth = pScrn->virtualX;
727fe5e51b7Smrg    int screenheight = pScrn->virtualY;
728fe5e51b7Smrg    XAAInfoRecPtr xaa = pMga->AccelInfoRec;
729fe5e51b7Smrg
730fe5e51b7Smrg    CHECK_DMA_QUIESCENT(pMga, pScrn);
731fe5e51b7Smrg
732fe5e51b7Smrg    pbox = REGION_RECTS(prgnSrc);
733fe5e51b7Smrg    nbox = REGION_NUM_RECTS(prgnSrc);
734fe5e51b7Smrg    pboxNew1 = 0;
735fe5e51b7Smrg    pptNew1 = 0;
736fe5e51b7Smrg    pboxNew2 = 0;
73781f79626Smrg    pptNew2 = 0;
738fe5e51b7Smrg    pptSrc = &ptOldOrg;
739fe5e51b7Smrg
740fe5e51b7Smrg    dx = pParent->drawable.x - ptOldOrg.x;
741fe5e51b7Smrg    dy = pParent->drawable.y - ptOldOrg.y;
742fe5e51b7Smrg
743fe5e51b7Smrg    /* If the copy will overlap in Y, reverse the order */
744fe5e51b7Smrg    if (dy>0) {
745fe5e51b7Smrg        ydir = -1;
746fe5e51b7Smrg
747fe5e51b7Smrg        if (nbox>1) {
748fe5e51b7Smrg	    /* Keep ordering in each band, reverse order of bands */
7490bb88ba4Smrg	    pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec)*nbox);
750fe5e51b7Smrg	    if (!pboxNew1) return;
7510bb88ba4Smrg	    pptNew1 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox);
752fe5e51b7Smrg	    if (!pptNew1) {
7530bb88ba4Smrg	        free(pboxNew1);
754fe5e51b7Smrg	        return;
755fe5e51b7Smrg	    }
756fe5e51b7Smrg	    pboxBase = pboxNext = pbox+nbox-1;
757fe5e51b7Smrg	    while (pboxBase >= pbox) {
758fe5e51b7Smrg	        while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
759fe5e51b7Smrg		  pboxNext--;
760fe5e51b7Smrg	        pboxTmp = pboxNext+1;
761fe5e51b7Smrg	        pptTmp = pptSrc + (pboxTmp - pbox);
762fe5e51b7Smrg	        while (pboxTmp <= pboxBase) {
763fe5e51b7Smrg		    *pboxNew1++ = *pboxTmp++;
764fe5e51b7Smrg		    *pptNew1++ = *pptTmp++;
765fe5e51b7Smrg		}
766fe5e51b7Smrg	        pboxBase = pboxNext;
767fe5e51b7Smrg	    }
768fe5e51b7Smrg	    pboxNew1 -= nbox;
769fe5e51b7Smrg	    pbox = pboxNew1;
770fe5e51b7Smrg	    pptNew1 -= nbox;
771fe5e51b7Smrg	    pptSrc = pptNew1;
772fe5e51b7Smrg	}
773fe5e51b7Smrg    } else {
774fe5e51b7Smrg        /* No changes required */
775fe5e51b7Smrg        ydir = 1;
776fe5e51b7Smrg    }
777fe5e51b7Smrg
778fe5e51b7Smrg    /* If the regions will overlap in X, reverse the order */
779fe5e51b7Smrg    if (dx>0) {
780fe5e51b7Smrg        xdir = -1;
781fe5e51b7Smrg
782fe5e51b7Smrg        if (nbox > 1) {
783fe5e51b7Smrg	    /*reverse orderof rects in each band */
7840bb88ba4Smrg	    pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec)*nbox);
7850bb88ba4Smrg	    pptNew2 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox);
786fe5e51b7Smrg	    if (!pboxNew2 || !pptNew2) {
7870bb88ba4Smrg	        free(pptNew2);
7880bb88ba4Smrg	        free(pboxNew2);
789fe5e51b7Smrg	        if (pboxNew1) {
7900bb88ba4Smrg		    free(pptNew1);
7910bb88ba4Smrg		    free(pboxNew1);
792fe5e51b7Smrg		}
793fe5e51b7Smrg	       return;
794fe5e51b7Smrg	    }
795fe5e51b7Smrg	    pboxBase = pboxNext = pbox;
796fe5e51b7Smrg	    while (pboxBase < pbox+nbox) {
797fe5e51b7Smrg	        while ((pboxNext < pbox+nbox) &&
798fe5e51b7Smrg		       (pboxNext->y1 == pboxBase->y1))
799fe5e51b7Smrg		  pboxNext++;
800fe5e51b7Smrg	        pboxTmp = pboxNext;
801fe5e51b7Smrg	        pptTmp = pptSrc + (pboxTmp - pbox);
802fe5e51b7Smrg	        while (pboxTmp != pboxBase) {
803fe5e51b7Smrg		    *pboxNew2++ = *--pboxTmp;
804fe5e51b7Smrg		    *pptNew2++ = *--pptTmp;
805fe5e51b7Smrg		}
806fe5e51b7Smrg	        pboxBase = pboxNext;
807fe5e51b7Smrg	    }
808fe5e51b7Smrg	    pboxNew2 -= nbox;
809fe5e51b7Smrg	    pbox = pboxNew2;
810fe5e51b7Smrg	    pptNew2 -= nbox;
811fe5e51b7Smrg	    pptSrc = pptNew2;
812fe5e51b7Smrg	}
813fe5e51b7Smrg    } else {
814fe5e51b7Smrg        /* No changes are needed */
815fe5e51b7Smrg        xdir = 1;
816fe5e51b7Smrg    }
817fe5e51b7Smrg
818fe5e51b7Smrg    xaa->SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1);
819fe5e51b7Smrg    for ( ; nbox-- ; pbox++) {
820fe5e51b7Smrg	 int x1 = pbox->x1;
821fe5e51b7Smrg	 int y1 = pbox->y1;
822fe5e51b7Smrg	 int destx = x1 + dx;
823fe5e51b7Smrg	 int desty = y1 + dy;
824fe5e51b7Smrg	 int w = pbox->x2 - x1 + 1;
825fe5e51b7Smrg	 int h = pbox->y2 - y1 + 1;
826fe5e51b7Smrg
827fe5e51b7Smrg	 if ( destx < 0 ) x1 -= destx, w += destx, destx = 0;
828fe5e51b7Smrg	 if ( desty < 0 ) y1 -= desty, h += desty, desty = 0;
829fe5e51b7Smrg	 if ( destx + w > screenwidth ) w = screenwidth - destx;
830fe5e51b7Smrg	 if ( desty + h > screenheight ) h = screenheight - desty;
831fe5e51b7Smrg	 if ( w <= 0 ) continue;
832fe5e51b7Smrg	 if ( h <= 0 ) continue;
833fe5e51b7Smrg
834fe5e51b7Smrg	 MGASelectBuffer(pScrn, MGA_BACK);
835fe5e51b7Smrg	 xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
836fe5e51b7Smrg	 MGASelectBuffer(pScrn, MGA_DEPTH);
837fe5e51b7Smrg	 xaa->SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
838fe5e51b7Smrg    }
839fe5e51b7Smrg    MGASelectBuffer(pScrn, MGA_FRONT);
840fe5e51b7Smrg
841fe5e51b7Smrg    if (pboxNew2) {
8420bb88ba4Smrg        free(pptNew2);
8430bb88ba4Smrg        free(pboxNew2);
844fe5e51b7Smrg    }
845fe5e51b7Smrg    if (pboxNew1) {
8460bb88ba4Smrg        free(pptNew1);
8470bb88ba4Smrg        free(pboxNew1);
848fe5e51b7Smrg    }
849fe5e51b7Smrg
850fe5e51b7Smrg    pMga->AccelInfoRec->NeedToSync = TRUE;
851fe5e51b7Smrg
852fe5e51b7Smrg}
853fe5e51b7Smrg#endif
854fe5e51b7Smrg
855fe5e51b7Smrgstatic void MGADRIMoveBuffersEXA(WindowPtr pParent, DDXPointRec ptOldOrg,
856fe5e51b7Smrg                                 RegionPtr prgnSrc, CARD32 index)
857fe5e51b7Smrg{
858fe5e51b7Smrg    /* FIXME */
859fe5e51b7Smrg}
860fe5e51b7Smrg
861fe5e51b7SmrgBool MGADRIScreenInit( ScreenPtr pScreen )
862fe5e51b7Smrg{
8630bb88ba4Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
864fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
865fe5e51b7Smrg   DRIInfoPtr pDRIInfo;
866fe5e51b7Smrg   MGADRIPtr pMGADRI;
867fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer;
868fe5e51b7Smrg
869fe5e51b7Smrg   if (!pMga->chip_attribs->dri_capable) {
870fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] Direct rendering only supported with G200/G400/G450/G550.\n");
871fe5e51b7Smrg       return FALSE;
872fe5e51b7Smrg   }
873fe5e51b7Smrg
87481f79626Smrg   /* Check that the DRI, and DRM modules have been loaded by testing
875fe5e51b7Smrg    * for canonical symbols in each module.
876fe5e51b7Smrg    */
877fe5e51b7Smrg   if ( !xf86LoaderCheckSymbol( "drmAvailable" ) )		return FALSE;
878fe5e51b7Smrg   if ( !xf86LoaderCheckSymbol( "DRIQueryVersion" ) ) {
879fe5e51b7Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
880fe5e51b7Smrg		  "[dri] MGADRIScreenInit failed (libdri.a too old)\n" );
881fe5e51b7Smrg      return FALSE;
882fe5e51b7Smrg   }
883fe5e51b7Smrg
884fe5e51b7Smrg   /* Check the DRI version */
885fe5e51b7Smrg   {
886fe5e51b7Smrg      int major, minor, patch;
887fe5e51b7Smrg      DRIQueryVersion( &major, &minor, &patch );
888fe5e51b7Smrg      if ( major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ) {
889fe5e51b7Smrg         xf86DrvMsg( pScreen->myNum, X_ERROR,
890fe5e51b7Smrg		     "[dri] MGADRIScreenInit failed because of a version mismatch.\n"
891fe5e51b7Smrg		     "[dri] libdri version = %d.%d.%d but version %d.%d.x is needed.\n"
892fe5e51b7Smrg		     "[dri] Disabling the DRI.\n",
893fe5e51b7Smrg		     major, minor, patch,
894fe5e51b7Smrg                     DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION );
895fe5e51b7Smrg         return FALSE;
896fe5e51b7Smrg      }
897fe5e51b7Smrg   }
898fe5e51b7Smrg
899fe5e51b7Smrg   xf86DrvMsg( pScreen->myNum, X_INFO,
900fe5e51b7Smrg	       "[drm] bpp: %d depth: %d\n",
901fe5e51b7Smrg	       pScrn->bitsPerPixel, pScrn->depth );
902fe5e51b7Smrg
903fe5e51b7Smrg   if ( (pScrn->bitsPerPixel / 8) != 2 &&
904fe5e51b7Smrg	(pScrn->bitsPerPixel / 8) != 4 ) {
905fe5e51b7Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
906fe5e51b7Smrg		  "[dri] Direct rendering only supported in 16 and 32 bpp modes\n" );
907fe5e51b7Smrg      return FALSE;
908fe5e51b7Smrg   }
909fe5e51b7Smrg
910fe5e51b7Smrg   pDRIInfo = DRICreateInfoRec();
911fe5e51b7Smrg   if ( !pDRIInfo ) {
912fe5e51b7Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
913fe5e51b7Smrg		  "[dri] DRICreateInfoRec() failed\n" );
914fe5e51b7Smrg      return FALSE;
915fe5e51b7Smrg   }
916fe5e51b7Smrg   pMga->pDRIInfo = pDRIInfo;
917fe5e51b7Smrg
918fe5e51b7Smrg   pDRIInfo->drmDriverName = MGAKernelDriverName;
919fe5e51b7Smrg   pDRIInfo->clientDriverName = MGAClientDriverName;
920fe5e51b7Smrg   if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
921fe5e51b7Smrg      pDRIInfo->busIdString = DRICreatePCIBusID(pMga->PciInfo);
922fe5e51b7Smrg   } else {
9230bb88ba4Smrg      pDRIInfo->busIdString = malloc(64);
924fe5e51b7Smrg      sprintf( pDRIInfo->busIdString, "PCI:%d:%d:%d",
925fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
926fe5e51b7Smrg	       ((pMga->PciInfo->domain << 8) | pMga->PciInfo->bus),
927fe5e51b7Smrg	       pMga->PciInfo->dev, pMga->PciInfo->func
928fe5e51b7Smrg#else
929fe5e51b7Smrg	       ((pciConfigPtr)pMga->PciInfo->thisCard)->busnum,
930fe5e51b7Smrg	       ((pciConfigPtr)pMga->PciInfo->thisCard)->devnum,
931fe5e51b7Smrg	       ((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum
932fe5e51b7Smrg#endif
933fe5e51b7Smrg	       );
934fe5e51b7Smrg   }
935fe5e51b7Smrg   pDRIInfo->ddxDriverMajorVersion = PACKAGE_VERSION_MAJOR;
936fe5e51b7Smrg   pDRIInfo->ddxDriverMinorVersion = PACKAGE_VERSION_MINOR;
937fe5e51b7Smrg   pDRIInfo->ddxDriverPatchVersion = PACKAGE_VERSION_PATCHLEVEL;
938fe5e51b7Smrg   pDRIInfo->frameBufferPhysicalAddress = (void *) pMga->FbAddress;
939fe5e51b7Smrg   pDRIInfo->frameBufferSize = pMga->FbMapSize;
940fe5e51b7Smrg   pDRIInfo->frameBufferStride = pScrn->displayWidth*(pScrn->bitsPerPixel/8);
941fe5e51b7Smrg   pDRIInfo->ddxDrawableTableEntry = MGA_MAX_DRAWABLES;
942fe5e51b7Smrg
943fe5e51b7Smrg   pDRIInfo->createDummyCtx = TRUE;
944fe5e51b7Smrg   pDRIInfo->createDummyCtxPriv = FALSE;
945fe5e51b7Smrg
946fe5e51b7Smrg   if ( SAREA_MAX_DRAWABLES < MGA_MAX_DRAWABLES ) {
947fe5e51b7Smrg      pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
948fe5e51b7Smrg   } else {
949fe5e51b7Smrg      pDRIInfo->maxDrawableTableEntry = MGA_MAX_DRAWABLES;
950fe5e51b7Smrg   }
951fe5e51b7Smrg
952fe5e51b7Smrg   /* For now the mapping works by using a fixed size defined
953fe5e51b7Smrg    * in the SAREA header.
954fe5e51b7Smrg    */
955fe5e51b7Smrg   if ( sizeof(XF86DRISAREARec) + sizeof(MGASAREAPrivRec) > SAREA_MAX ) {
956fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
957fe5e51b7Smrg		  "[drm] Data does not fit in SAREA\n" );
958fe5e51b7Smrg      return FALSE;
959fe5e51b7Smrg   }
960fe5e51b7Smrg
961fe5e51b7Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO,
962fe5e51b7Smrg	       "[drm] Sarea %d+%d: %d\n",
963fe5e51b7Smrg	       (int)sizeof(XF86DRISAREARec), (int)sizeof(MGASAREAPrivRec),
964fe5e51b7Smrg	       (int)sizeof(XF86DRISAREARec) + (int)sizeof(MGASAREAPrivRec) );
965fe5e51b7Smrg
966fe5e51b7Smrg   pDRIInfo->SAREASize = SAREA_MAX;
967fe5e51b7Smrg
9680bb88ba4Smrg   pMGADRI = (MGADRIPtr)calloc( sizeof(MGADRIRec), 1 );
969fe5e51b7Smrg   if ( !pMGADRI ) {
970fe5e51b7Smrg      DRIDestroyInfoRec( pMga->pDRIInfo );
971fe5e51b7Smrg      pMga->pDRIInfo = 0;
972fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
973fe5e51b7Smrg		  "[drm] Failed to allocate memory for private record\n" );
974fe5e51b7Smrg      return FALSE;
975fe5e51b7Smrg   }
976fe5e51b7Smrg
977fe5e51b7Smrg   pMGADRIServer = (MGADRIServerPrivatePtr)
9780bb88ba4Smrg      calloc( sizeof(MGADRIServerPrivateRec), 1 );
979fe5e51b7Smrg   if ( !pMGADRIServer ) {
9800bb88ba4Smrg      free( pMGADRI );
981fe5e51b7Smrg      DRIDestroyInfoRec( pMga->pDRIInfo );
982fe5e51b7Smrg      pMga->pDRIInfo = 0;
983fe5e51b7Smrg      xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
984fe5e51b7Smrg		  "[drm] Failed to allocate memory for private record\n" );
985fe5e51b7Smrg      return FALSE;
986fe5e51b7Smrg   }
987fe5e51b7Smrg   pMga->DRIServerInfo = pMGADRIServer;
988fe5e51b7Smrg
989fe5e51b7Smrg   pDRIInfo->devPrivate = pMGADRI;
990fe5e51b7Smrg   pDRIInfo->devPrivateSize = sizeof(MGADRIRec);
991fe5e51b7Smrg   pDRIInfo->contextSize = sizeof(MGADRIContextRec);
992fe5e51b7Smrg
993fe5e51b7Smrg   pDRIInfo->CreateContext = MGACreateContext;
994fe5e51b7Smrg   pDRIInfo->DestroyContext = MGADestroyContext;
995fe5e51b7Smrg   if ( xf86IsEntityShared( pScrn->entityList[0] )
996fe5e51b7Smrg		&& pMga->DualHeadEnabled) {
997fe5e51b7Smrg      pDRIInfo->SwapContext = MGADRISwapContextShared;
998fe5e51b7Smrg   } else {
999fe5e51b7Smrg      pDRIInfo->SwapContext = MGADRISwapContext;
1000fe5e51b7Smrg   }
1001fe5e51b7Smrg
10020bb88ba4Smrg   pDRIInfo->InitBuffers = MGADRIInitBuffersEXA;
10030bb88ba4Smrg   pDRIInfo->MoveBuffers = MGADRIMoveBuffersEXA;
1004fe5e51b7Smrg#ifdef USE_EXA
1005fe5e51b7Smrg    if (pMga->Exa) {
1006fe5e51b7Smrg        pDRIInfo->InitBuffers = MGADRIInitBuffersEXA;
1007fe5e51b7Smrg        pDRIInfo->MoveBuffers = MGADRIMoveBuffersEXA;
1008fe5e51b7Smrg    } else {
1009fe5e51b7Smrg#endif
1010fe5e51b7Smrg#ifdef USE_XAA
1011fe5e51b7Smrg        pDRIInfo->InitBuffers = MGADRIInitBuffersXAA;
1012fe5e51b7Smrg        pDRIInfo->MoveBuffers = MGADRIMoveBuffersXAA;
1013fe5e51b7Smrg#endif
1014fe5e51b7Smrg#ifdef USE_EXA
1015fe5e51b7Smrg    }
1016fe5e51b7Smrg#endif
1017fe5e51b7Smrg
1018fe5e51b7Smrg   pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
1019fe5e51b7Smrg
1020fe5e51b7Smrg   if ( !DRIScreenInit( pScreen, pDRIInfo, &pMga->drmFD ) ) {
10210bb88ba4Smrg      free( pMGADRIServer );
1022fe5e51b7Smrg      pMga->DRIServerInfo = 0;
10230bb88ba4Smrg      free( pDRIInfo->devPrivate );
1024fe5e51b7Smrg      pDRIInfo->devPrivate = 0;
1025fe5e51b7Smrg      DRIDestroyInfoRec( pMga->pDRIInfo );
1026fe5e51b7Smrg      pMga->pDRIInfo = 0;
1027fe5e51b7Smrg      xf86DrvMsg( pScreen->myNum, X_ERROR,
1028fe5e51b7Smrg		  "[drm] DRIScreenInit failed.  Disabling DRI.\n" );
1029fe5e51b7Smrg      return FALSE;
1030fe5e51b7Smrg   }
1031fe5e51b7Smrg
1032fe5e51b7Smrg   /* Check the DRM versioning */
1033fe5e51b7Smrg   {
1034fe5e51b7Smrg      drmVersionPtr version;
1035fe5e51b7Smrg
1036fe5e51b7Smrg      /* Check the DRM lib version.
1037fe5e51b7Smrg	 drmGetLibVersion was not supported in version 1.0, so check for
1038fe5e51b7Smrg	 symbol first to avoid possible crash or hang.
1039fe5e51b7Smrg       */
1040fe5e51b7Smrg      if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
1041fe5e51b7Smrg         version = drmGetLibVersion(pMga->drmFD);
1042fe5e51b7Smrg      }
1043fe5e51b7Smrg      else {
1044fe5e51b7Smrg	 /* drmlib version 1.0.0 didn't have the drmGetLibVersion
1045fe5e51b7Smrg	    entry point.  Fake it by allocating a version record
1046fe5e51b7Smrg	    via drmGetVersion and changing it to version 1.0.0
1047fe5e51b7Smrg	  */
1048fe5e51b7Smrg	 version = drmGetVersion(pMga->drmFD);
1049fe5e51b7Smrg	 version->version_major      = 1;
1050fe5e51b7Smrg	 version->version_minor      = 0;
1051fe5e51b7Smrg	 version->version_patchlevel = 0;
1052fe5e51b7Smrg      }
1053fe5e51b7Smrg
1054fe5e51b7Smrg      if (version) {
1055fe5e51b7Smrg	 if (version->version_major != 1 ||
1056fe5e51b7Smrg	     version->version_minor < 1) {
1057fe5e51b7Smrg	     /* incompatible drm library version */
1058fe5e51b7Smrg	    xf86DrvMsg(pScreen->myNum, X_ERROR,
1059fe5e51b7Smrg		       "[dri] MGADRIScreenInit failed because of a version mismatch.\n"
1060fe5e51b7Smrg		       "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
1061fe5e51b7Smrg		       "[dri] Disabling DRI.\n",
1062fe5e51b7Smrg		       version->version_major,
1063fe5e51b7Smrg		       version->version_minor,
1064fe5e51b7Smrg		       version->version_patchlevel);
1065fe5e51b7Smrg	    drmFreeVersion(version);
1066fe5e51b7Smrg	    MGADRICloseScreen( pScreen );		/* FIXME: ??? */
1067fe5e51b7Smrg	    return FALSE;
1068fe5e51b7Smrg	 }
1069fe5e51b7Smrg	 drmFreeVersion(version);
1070fe5e51b7Smrg      }
1071fe5e51b7Smrg
1072fe5e51b7Smrg      /* Check the MGA DRM version */
1073fe5e51b7Smrg      version = drmGetVersion(pMga->drmFD);
1074fe5e51b7Smrg      if ( version ) {
1075fe5e51b7Smrg         if ( version->version_major != 3 ||
1076fe5e51b7Smrg	      version->version_minor < 0 ) {
1077fe5e51b7Smrg            /* incompatible drm version */
1078fe5e51b7Smrg            xf86DrvMsg( pScreen->myNum, X_ERROR,
1079fe5e51b7Smrg			"[dri] MGADRIScreenInit failed because of a version mismatch.\n"
1080fe5e51b7Smrg			"[dri] mga.o kernel module version is %d.%d.%d but version 3.0.x is needed.\n"
1081fe5e51b7Smrg			"[dri] Disabling DRI.\n",
1082fe5e51b7Smrg			version->version_major,
1083fe5e51b7Smrg			version->version_minor,
1084fe5e51b7Smrg			version->version_patchlevel );
1085fe5e51b7Smrg            drmFreeVersion( version );
1086fe5e51b7Smrg	    MGADRICloseScreen( pScreen );		/* FIXME: ??? */
1087fe5e51b7Smrg            return FALSE;
1088fe5e51b7Smrg         }
1089fe5e51b7Smrg	 pMGADRIServer->drm_version_major = version->version_major;
1090fe5e51b7Smrg	 pMGADRIServer->drm_version_minor = version->version_minor;
1091fe5e51b7Smrg
1092fe5e51b7Smrg         drmFreeVersion( version );
1093fe5e51b7Smrg      }
1094fe5e51b7Smrg   }
1095fe5e51b7Smrg
1096fe5e51b7Smrg   if ( (pMga->bios.host_interface == MGA_HOST_PCI) &&
1097fe5e51b7Smrg	((pMGADRIServer->drm_version_minor < 2) || pMga->useOldDmaInit) ) {
1098fe5e51b7Smrg       /* PCI cards are supported if the DRM version is at least 3.2 and the
1099fe5e51b7Smrg	* user has not explicitly disabled the new DMA init path (i.e., to
1100fe5e51b7Smrg	* support old version of the client-side driver that don't use the
1101fe5e51b7Smrg	* new features of the 3.2 DRM).
1102fe5e51b7Smrg	*/
1103fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1104fe5e51b7Smrg		  "[drm] Direct rendering on PCI cards requires DRM version 3.2 or higher\n");
1105fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1106fe5e51b7Smrg		  "[drm] and a recent client-side driver.  Also make sure that 'OldDmaInit'\n");
1107fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1108fe5e51b7Smrg		  "[drm] is not selected in xorg.conf.'\n");
1109fe5e51b7Smrg       return FALSE;
1110fe5e51b7Smrg   }
1111fe5e51b7Smrg
1112fe5e51b7Smrg
1113fe5e51b7Smrg   if ( !MGADRIBootstrapDMA( pScreen ) ) {
1114fe5e51b7Smrg      DRICloseScreen( pScreen );
1115fe5e51b7Smrg      return FALSE;
1116fe5e51b7Smrg   }
1117fe5e51b7Smrg
1118fe5e51b7Smrg   {
1119fe5e51b7Smrg       void *scratch_ptr;
1120fe5e51b7Smrg       int scratch_int;
1121fe5e51b7Smrg
1122fe5e51b7Smrg       DRIGetDeviceInfo(pScreen, &pMGADRIServer->fb.handle,
1123fe5e51b7Smrg			&scratch_int, &scratch_int,
1124fe5e51b7Smrg			&scratch_int, &scratch_int,
1125fe5e51b7Smrg			&scratch_ptr);
1126fe5e51b7Smrg   }
1127fe5e51b7Smrg
1128fe5e51b7Smrg   xf86DrvMsg( pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n" );
1129fe5e51b7Smrg
1130fe5e51b7Smrg   return TRUE;
1131fe5e51b7Smrg}
1132fe5e51b7Smrg
1133fe5e51b7Smrg
1134fe5e51b7SmrgBool MGADRIFinishScreenInit( ScreenPtr pScreen )
1135fe5e51b7Smrg{
11360bb88ba4Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1137fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
1138fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
1139fe5e51b7Smrg   MGADRIPtr pMGADRI;
1140fe5e51b7Smrg   int i;
1141fe5e51b7Smrg
1142fe5e51b7Smrg   if ( !pMga->pDRIInfo )
1143fe5e51b7Smrg      return FALSE;
1144fe5e51b7Smrg
1145fe5e51b7Smrg   pMGADRI = (MGADRIPtr)pMga->pDRIInfo->devPrivate;
1146fe5e51b7Smrg
1147fe5e51b7Smrg   pMga->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
1148fe5e51b7Smrg
1149fe5e51b7Smrg   /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
1150fe5e51b7Smrg    * because *DRIKernelInit requires that the hardware lock is held by
1151fe5e51b7Smrg    * the X server, and the first time the hardware lock is grabbed is
1152fe5e51b7Smrg    * in DRIFinishScreenInit.
1153fe5e51b7Smrg    */
1154fe5e51b7Smrg   if ( !DRIFinishScreenInit( pScreen ) ) {
1155fe5e51b7Smrg      MGADRICloseScreen( pScreen );
1156fe5e51b7Smrg      return FALSE;
1157fe5e51b7Smrg   }
1158fe5e51b7Smrg
1159fe5e51b7Smrg   if ( !MGADRIKernelInit( pScreen ) ) {
1160fe5e51b7Smrg      MGADRICloseScreen( pScreen );
1161fe5e51b7Smrg      return FALSE;
1162fe5e51b7Smrg   }
1163fe5e51b7Smrg
1164fe5e51b7Smrg   if ( !MGADRIBuffersInit( pScreen ) ) {
1165fe5e51b7Smrg      MGADRICloseScreen( pScreen );
1166fe5e51b7Smrg      return FALSE;
1167fe5e51b7Smrg   }
1168fe5e51b7Smrg
1169fe5e51b7Smrg   MGADRIIrqInit(pMga, pScreen);
1170fe5e51b7Smrg
1171fe5e51b7Smrg   pMGADRI->chipset		= pMga->chip_attribs->dri_chipset;
1172fe5e51b7Smrg   pMGADRI->width		= pScrn->virtualX;
1173fe5e51b7Smrg   pMGADRI->height		= pScrn->virtualY;
1174fe5e51b7Smrg   pMGADRI->cpp			= pScrn->bitsPerPixel / 8;
1175fe5e51b7Smrg
1176fe5e51b7Smrg   pMGADRI->agpMode		= pMga->agpMode;
1177fe5e51b7Smrg
1178fe5e51b7Smrg   pMGADRI->frontOffset		= pMGADRIServer->frontOffset;
1179fe5e51b7Smrg   pMGADRI->frontPitch		= pMGADRIServer->frontPitch;
1180fe5e51b7Smrg   pMGADRI->backOffset		= pMGADRIServer->backOffset;
1181fe5e51b7Smrg   pMGADRI->backPitch		= pMGADRIServer->backPitch;
1182fe5e51b7Smrg   pMGADRI->depthOffset		= pMGADRIServer->depthOffset;
1183fe5e51b7Smrg   pMGADRI->depthPitch		= pMGADRIServer->depthPitch;
1184fe5e51b7Smrg   pMGADRI->textureOffset	= pMGADRIServer->textureOffset;
1185fe5e51b7Smrg   pMGADRI->textureSize		= pMGADRIServer->textureSize;
1186fe5e51b7Smrg
1187fe5e51b7Smrg   pMGADRI->agpTextureOffset = (unsigned int)pMGADRIServer->agpTextures.handle;
1188fe5e51b7Smrg   pMGADRI->agpTextureSize = (unsigned int)pMGADRIServer->agpTextures.size;
1189fe5e51b7Smrg
1190fe5e51b7Smrg   pMGADRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
1191fe5e51b7Smrg
1192fe5e51b7Smrg
1193fe5e51b7Smrg   /* Newer versions of the client-side driver do not need these if the
1194fe5e51b7Smrg    * kernel version is high enough to support interrupt based waiting.
1195fe5e51b7Smrg    */
1196fe5e51b7Smrg
1197fe5e51b7Smrg   pMGADRI->registers.handle	= pMGADRIServer->registers.handle;
1198fe5e51b7Smrg   pMGADRI->registers.size	= pMGADRIServer->registers.size;
1199fe5e51b7Smrg   pMGADRI->primary.handle	= pMGADRIServer->primary.handle;
1200fe5e51b7Smrg   pMGADRI->primary.size	= pMGADRIServer->primary.size;
1201fe5e51b7Smrg
1202fe5e51b7Smrg
1203fe5e51b7Smrg   /* These are no longer used by the client-side DRI driver.  They should
1204fe5e51b7Smrg    * be removed in the next release (i.e., 6.9 / 7.0).
1205fe5e51b7Smrg    */
1206fe5e51b7Smrg
1207fe5e51b7Smrg   pMGADRI->status.handle	= pMGADRIServer->status.handle;
1208fe5e51b7Smrg   pMGADRI->status.size		= pMGADRIServer->status.size;
1209fe5e51b7Smrg   pMGADRI->buffers.handle	= pMGADRIServer->buffers.handle;
1210fe5e51b7Smrg   pMGADRI->buffers.size	= pMGADRIServer->buffers.size;
1211fe5e51b7Smrg
1212fe5e51b7Smrg   i = mylog2( pMGADRI->textureSize / MGA_NR_TEX_REGIONS );
1213fe5e51b7Smrg   if ( i < MGA_LOG_MIN_TEX_REGION_SIZE )
1214fe5e51b7Smrg      i = MGA_LOG_MIN_TEX_REGION_SIZE;
1215fe5e51b7Smrg
1216fe5e51b7Smrg   pMGADRI->logTextureGranularity = i;
1217fe5e51b7Smrg   pMGADRI->textureSize = (pMGADRI->textureSize >> i) << i; /* truncate */
1218fe5e51b7Smrg
1219fe5e51b7Smrg   i = mylog2( pMGADRIServer->agpTextures.size / MGA_NR_TEX_REGIONS );
1220fe5e51b7Smrg   if ( i < MGA_LOG_MIN_TEX_REGION_SIZE )
1221fe5e51b7Smrg      i = MGA_LOG_MIN_TEX_REGION_SIZE;
1222fe5e51b7Smrg
1223fe5e51b7Smrg   pMGADRI->logAgpTextureGranularity = i;
1224fe5e51b7Smrg
1225fe5e51b7Smrg   return TRUE;
1226fe5e51b7Smrg}
1227fe5e51b7Smrg
1228fe5e51b7Smrg
1229fe5e51b7Smrgvoid MGADRICloseScreen( ScreenPtr pScreen )
1230fe5e51b7Smrg{
12310bb88ba4Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1232fe5e51b7Smrg   MGAPtr pMga = MGAPTR(pScrn);
1233fe5e51b7Smrg   MGADRIServerPrivatePtr pMGADRIServer = pMga->DRIServerInfo;
1234fe5e51b7Smrg   drm_mga_init_t init;
1235fe5e51b7Smrg
1236fe5e51b7Smrg   if ( pMGADRIServer->drmBuffers ) {
1237fe5e51b7Smrg      drmUnmapBufs( pMGADRIServer->drmBuffers );
1238fe5e51b7Smrg      pMGADRIServer->drmBuffers = NULL;
1239fe5e51b7Smrg   }
1240fe5e51b7Smrg
1241fe5e51b7Smrg   if (pMga->irq) {
1242fe5e51b7Smrg      drmCtlUninstHandler(pMga->drmFD);
1243fe5e51b7Smrg      pMga->irq = 0;
1244fe5e51b7Smrg      pMga->reg_ien = 0;
1245fe5e51b7Smrg   }
1246fe5e51b7Smrg
1247fe5e51b7Smrg   /* Cleanup DMA */
1248fe5e51b7Smrg   memset( &init, 0, sizeof(drm_mga_init_t) );
1249fe5e51b7Smrg   init.func = MGA_CLEANUP_DMA;
1250fe5e51b7Smrg   drmCommandWrite( pMga->drmFD, DRM_MGA_INIT, &init, sizeof(drm_mga_init_t) );
1251fe5e51b7Smrg
1252fe5e51b7Smrg   if ( pMGADRIServer->agp.handle != DRM_AGP_NO_HANDLE ) {
1253fe5e51b7Smrg      drmAgpUnbind( pMga->drmFD, pMGADRIServer->agp.handle );
1254fe5e51b7Smrg      drmAgpFree( pMga->drmFD, pMGADRIServer->agp.handle );
1255fe5e51b7Smrg      pMGADRIServer->agp.handle = DRM_AGP_NO_HANDLE;
1256fe5e51b7Smrg      drmAgpRelease( pMga->drmFD );
1257fe5e51b7Smrg   }
1258fe5e51b7Smrg
1259fe5e51b7Smrg   DRICloseScreen( pScreen );
1260fe5e51b7Smrg
1261fe5e51b7Smrg   if ( pMga->pDRIInfo ) {
12620bb88ba4Smrg      free(pMga->pDRIInfo->devPrivate);
12630bb88ba4Smrg      pMga->pDRIInfo->devPrivate = 0;
1264fe5e51b7Smrg      DRIDestroyInfoRec( pMga->pDRIInfo );
1265fe5e51b7Smrg      pMga->pDRIInfo = 0;
1266fe5e51b7Smrg   }
12670bb88ba4Smrg   free(pMga->DRIServerInfo);
12680bb88ba4Smrg   pMga->DRIServerInfo = 0;
1269fe5e51b7Smrg}
1270