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