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