1
/* -*- mode: c; c-basic-offset: 3 -*- */
3
* Copyright 2000 Gareth Hughes
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the "Software"),
8
* to deal in the Software without restriction, including without limitation
9
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
* and/or sell copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following conditions:
13
* The above copyright notice and this permission notice (including the next
14
* paragraph) shall be included in all copies or substantial portions of the
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
* GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
* Gareth Hughes <gareth@valinux.com>
31
* Leif Delgass <ldelgass@retinalburn.net>
38
/* Driver data structures */
43
#include "atistruct.h"
45
#include "atimach64io.h"
46
#include "atimach64version.h"
47
#include "mach64_dri.h"
48
#include "mach64_common.h"
49
#include "mach64_sarea.h"
51
/* X and server generic header files */
53
#include "windowstr.h"
55
/* GLX/DRI/DRM definitions */
56
#define _XF86DRI_SERVER_
57
#include "GL/glxtokens.h"
60
static char ATIKernelDriverName[] = "mach64";
61
static char ATIClientDriverName[] = "mach64";
63
/* Initialize the visual configs that are supported by the hardware.
64
* These are combined with the visual configs that the indirect
65
* rendering core supports, and the intersection is exported to the
68
static Bool ATIInitVisualConfigs( ScreenPtr pScreen )
70
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
71
ATIPtr pATI = ATIPTR(pScreenInfo);
73
__GLXvisualConfig *pConfigs = NULL;
74
ATIConfigPrivPtr pATIConfigs = NULL;
75
ATIConfigPrivPtr *pATIConfigPtrs = NULL;
76
int i, accum, stencil, db;
78
switch ( pATI->bitsPerPixel ) {
79
case 8: /* 8bpp mode is not support */
82
xf86DrvMsg(pScreen->myNum, X_ERROR,
83
"[dri] ATIInitVisualConfigs failed (%d bpp not supported). "
84
"Disabling DRI.\n", pATI->bitsPerPixel);
87
#define ATI_USE_ACCUM 1
88
#define ATI_USE_STENCIL 1
92
if ( pATI->depth != 16) {
93
xf86DrvMsg(pScreen->myNum, X_ERROR,
94
"[dri] ATIInitVisualConfigs failed (depth %d at 16 bpp not supported). "
95
"Disabling DRI.\n", pATI->depth);
100
if ( ATI_USE_ACCUM ) numConfigs *= 2;
101
if ( ATI_USE_STENCIL ) numConfigs *= 2;
102
numConfigs *= 2; /* single- and double-buffered */
104
pConfigs = (__GLXvisualConfig*)
105
xnfcalloc( sizeof(__GLXvisualConfig), numConfigs );
109
pATIConfigs = (ATIConfigPrivPtr)
110
xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs );
111
if ( !pATIConfigs ) {
115
pATIConfigPtrs = (ATIConfigPrivPtr*)
116
xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs );
117
if ( !pATIConfigPtrs ) {
124
for (db = 1; db >= 0; db--) {
125
for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) {
126
for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) {
127
pATIConfigPtrs[i] = &pATIConfigs[i];
129
pConfigs[i].vid = -1;
130
pConfigs[i].class = -1;
131
pConfigs[i].rgba = TRUE;
132
pConfigs[i].redSize = 5;
133
pConfigs[i].greenSize = 6;
134
pConfigs[i].blueSize = 5;
135
pConfigs[i].alphaSize = 0;
136
pConfigs[i].redMask = 0x0000F800;
137
pConfigs[i].greenMask = 0x000007E0;
138
pConfigs[i].blueMask = 0x0000001F;
139
pConfigs[i].alphaMask = 0x00000000;
140
if ( accum ) { /* Simulated in software */
141
pConfigs[i].accumRedSize = 16;
142
pConfigs[i].accumGreenSize = 16;
143
pConfigs[i].accumBlueSize = 16;
144
pConfigs[i].accumAlphaSize = 0;
146
pConfigs[i].accumRedSize = 0;
147
pConfigs[i].accumGreenSize = 0;
148
pConfigs[i].accumBlueSize = 0;
149
pConfigs[i].accumAlphaSize = 0;
151
pConfigs[i].doubleBuffer = db ? TRUE : FALSE;
152
pConfigs[i].stereo = FALSE;
153
pConfigs[i].bufferSize = 16;
154
pConfigs[i].depthSize = 16;
155
if ( stencil ) { /* Simulated in software */
156
pConfigs[i].stencilSize = 8;
158
pConfigs[i].stencilSize = 0;
160
pConfigs[i].auxBuffers = 0;
161
pConfigs[i].level = 0;
162
if ( accum || stencil ) {
163
pConfigs[i].visualRating = GLX_SLOW_CONFIG;
165
pConfigs[i].visualRating = GLX_NONE;
167
pConfigs[i].transparentPixel = GLX_NONE;
168
pConfigs[i].transparentRed = 0;
169
pConfigs[i].transparentGreen = 0;
170
pConfigs[i].transparentBlue = 0;
171
pConfigs[i].transparentAlpha = 0;
172
pConfigs[i].transparentIndex = 0;
181
if ( ATI_USE_ACCUM ) numConfigs *= 2;
182
if ( ATI_USE_STENCIL ) numConfigs *= 2;
183
numConfigs *= 2; /* single- and double-buffered */
185
pConfigs = (__GLXvisualConfig*)
186
xnfcalloc( sizeof(__GLXvisualConfig), numConfigs );
190
pATIConfigs = (ATIConfigPrivPtr)
191
xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs );
192
if ( !pATIConfigs ) {
196
pATIConfigPtrs = (ATIConfigPrivPtr*)
197
xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs );
198
if ( !pATIConfigPtrs ) {
205
for (db = 1; db >= 0; db--) {
206
for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) {
207
for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) {
208
pATIConfigPtrs[i] = &pATIConfigs[i];
210
pConfigs[i].vid = -1;
211
pConfigs[i].class = -1;
212
pConfigs[i].rgba = TRUE;
213
pConfigs[i].redSize = 8;
214
pConfigs[i].greenSize = 8;
215
pConfigs[i].blueSize = 8;
216
pConfigs[i].alphaSize = 0;
217
pConfigs[i].redMask = 0x00FF0000;
218
pConfigs[i].greenMask = 0x0000FF00;
219
pConfigs[i].blueMask = 0x000000FF;
220
pConfigs[i].alphaMask = 0x00000000;
221
if ( accum ) { /* Simulated in software */
222
pConfigs[i].accumRedSize = 16;
223
pConfigs[i].accumGreenSize = 16;
224
pConfigs[i].accumBlueSize = 16;
225
pConfigs[i].accumAlphaSize = 0;
227
pConfigs[i].accumRedSize = 0;
228
pConfigs[i].accumGreenSize = 0;
229
pConfigs[i].accumBlueSize = 0;
230
pConfigs[i].accumAlphaSize = 0;
232
pConfigs[i].doubleBuffer = db ? TRUE : FALSE;
233
pConfigs[i].stereo = FALSE;
234
pConfigs[i].bufferSize = 24;
235
if ( stencil ) { /* Simulated in software */
236
pConfigs[i].depthSize = 16;
237
pConfigs[i].stencilSize = 8;
239
pConfigs[i].depthSize = 16;
240
pConfigs[i].stencilSize = 0;
242
pConfigs[i].auxBuffers = 0;
243
pConfigs[i].level = 0;
244
if ( accum || stencil ) {
245
pConfigs[i].visualRating = GLX_SLOW_CONFIG;
247
pConfigs[i].visualRating = GLX_NONE;
249
pConfigs[i].transparentPixel = GLX_NONE;
250
pConfigs[i].transparentRed = 0;
251
pConfigs[i].transparentGreen = 0;
252
pConfigs[i].transparentBlue = 0;
253
pConfigs[i].transparentAlpha = 0;
254
pConfigs[i].transparentIndex = 0;
262
pATI->numVisualConfigs = numConfigs;
263
pATI->pVisualConfigs = pConfigs;
264
pATI->pVisualConfigsPriv = pATIConfigs;
265
GlxSetVisualConfigs( numConfigs, pConfigs, (void**)pATIConfigPtrs );
269
/* Create the ATI-specific context information */
270
static Bool ATICreateContext( ScreenPtr pScreen, VisualPtr visual,
271
drm_context_t hwContext, void *pVisualConfigPriv,
272
DRIContextType contextStore )
278
/* Destroy the ATI-specific context information */
279
static void ATIDestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
280
DRIContextType contextStore )
285
/* Called when the X server is woken up to allow the last client's
286
* context to be saved and the X server's context to be loaded.
287
* The client detects when it's context is not currently loaded and
288
* then loads it itself. The X server's context is loaded in the
289
* XAA Sync callback if NeedDRISync is set.
291
static void ATIEnterServer( ScreenPtr pScreen )
293
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
294
ATIPtr pATI = ATIPTR(pScreenInfo);
296
if ( pATI->directRenderingEnabled ) {
297
ATIDRIMarkSyncInt(pScreenInfo);
298
ATIDRIMarkSyncExt(pScreenInfo);
302
/* Called when the X server goes to sleep to allow the X server's
303
* context to be saved and the last client's context to be loaded.
304
* The client detects when it's context is not currently loaded and
305
* then loads it itself. The X server keeps track of it's own state.
307
static void ATILeaveServer( ScreenPtr pScreen )
312
/* Contexts can be swapped by the X server if necessary. This callback
313
* is currently only used to perform any functions necessary when
314
* entering or leaving the X server, and in the future might not be
317
static void ATIDRISwapContext( ScreenPtr pScreen,
318
DRISyncType syncType,
319
DRIContextType oldContextType,
321
DRIContextType newContextType,
324
if ( ( syncType == DRI_3D_SYNC ) && ( oldContextType == DRI_2D_CONTEXT ) &&
325
( newContextType == DRI_2D_CONTEXT ) ) {
326
/* Entering from Wakeup */
327
ATIEnterServer( pScreen );
329
if ( ( syncType == DRI_2D_SYNC ) && ( oldContextType == DRI_NO_CONTEXT ) &&
330
( newContextType == DRI_2D_CONTEXT ) ) {
331
/* Exiting from Block Handler */
332
ATILeaveServer( pScreen );
337
static void ATIDRITransitionTo2d(ScreenPtr pScreen)
339
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
340
ATIPtr pATI = ATIPTR(pScreenInfo);
342
if (pATI->backArea) {
343
xf86FreeOffscreenArea(pATI->backArea);
344
pATI->backArea = NULL;
346
if (pATI->depthTexArea) {
347
xf86FreeOffscreenArea(pATI->depthTexArea);
348
pATI->depthTexArea = NULL;
350
pATI->have3DWindows = FALSE;
353
static void ATIDRITransitionTo3d(ScreenPtr pScreen)
355
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
356
ATIPtr pATI = ATIPTR(pScreenInfo);
360
xf86PurgeUnlockedOffscreenAreas(pScreen);
362
xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0);
364
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
365
"Largest offscreen area available: %d x %d\n",
368
fbArea = xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
369
height - pATI->depthTexLines -
371
pScreenInfo->displayWidth, NULL, NULL, NULL);
374
xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve placeholder "
375
"offscreen area, you might experience screen corruption\n");
377
if (!pATI->backArea) {
379
xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
381
pScreenInfo->displayWidth,
385
xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area "
386
"for back buffer, you might experience screen corruption\n");
388
if (!pATI->depthTexArea) {
390
xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
392
pScreenInfo->displayWidth,
395
if (!pATI->depthTexArea)
396
xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area "
397
"for depth buffer and textures, you might experience screen corruption\n");
400
xf86FreeOffscreenArea(fbArea);
402
pATI->have3DWindows = TRUE;
407
static void ATIDRITransitionTo2d_EXA(ScreenPtr pScreen)
409
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
410
ATIPtr pATI = ATIPTR(pScreenInfo);
411
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
413
exaEnableDisableFBAccess(SCREEN_ARG(pScreen), FALSE);
415
pATI->pExa->offScreenBase = pATIDRIServer->backOffset;
417
exaEnableDisableFBAccess(SCREEN_ARG(pScreen), TRUE);
419
pATI->have3DWindows = FALSE;
422
static void ATIDRITransitionTo3d_EXA(ScreenPtr pScreen)
424
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
425
ATIPtr pATI = ATIPTR(pScreenInfo);
426
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
428
exaEnableDisableFBAccess(SCREEN_ARG(pScreen), FALSE);
430
pATI->pExa->offScreenBase = pATIDRIServer->textureOffset +
431
pATIDRIServer->textureSize;
433
exaEnableDisableFBAccess(SCREEN_ARG(pScreen), TRUE);
435
pATI->have3DWindows = TRUE;
439
/* Initialize the state of the back and depth buffers. */
440
static void ATIDRIInitBuffers( WindowPtr pWin, RegionPtr prgn, CARD32 indx )
443
ScreenPtr pScreen = pWin->drawable.pScreen;
444
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
445
ATIPtr pATI = ATIPTR(pScreenInfo);
446
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
447
XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
448
BoxPtr pbox, pboxSave;
457
if (!pXAAInfo->SetupForSolidFill)
460
/* FIXME: Only initialize the back and depth buffers for contexts
463
/* FIXME: Use drm clear? (see Radeon driver) */
465
pboxSave = pbox = REGION_RECTS(prgn);
466
nboxSave = nbox = REGION_NUM_RECTS(prgn);
468
(*pXAAInfo->SetupForSolidFill)(pScreenInfo, 0, GXcopy, (CARD32)(-1));
469
for (; nbox; nbox--, pbox++) {
470
(*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
471
pbox->x1 + pATIDRIServer->fbX,
472
pbox->y1 + pATIDRIServer->fbY,
474
pbox->y2 - pbox->y1);
475
(*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
476
pbox->x1 + pATIDRIServer->backX,
477
pbox->y1 + pATIDRIServer->backY,
479
pbox->y2 - pbox->y1);
485
(*pXAAInfo->SetupForSolidFill)(pScreenInfo, depth, GXcopy, (CARD32)(-1));
486
for (; nbox; nbox--, pbox++)
487
(*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
488
pbox->x1 + pATIDRIServer->depthX,
489
pbox->y1 + pATIDRIServer->depthY,
491
pbox->y2 - pbox->y1);
493
ATIDRIMarkSyncInt(pScreenInfo);
497
/* Copy the back and depth buffers when the X server moves a window.
499
* Note: this function was copied from the Radeon driver...
501
* This routine is a modified form of XAADoBitBlt with the calls to
502
* ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
503
* instead of destination. My origin is upside down so the ydir cases
506
static void ATIDRIMoveBuffers( WindowPtr pWin, DDXPointRec ptOldOrg,
507
RegionPtr prgnSrc, CARD32 indx )
510
ScreenPtr pScreen = pWin->drawable.pScreen;
511
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
512
ATIPtr pATI = ATIPTR(pScreenInfo);
513
XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
515
int backOffsetPitch = (((pATI->pDRIServerInfo->backPitch/8) << 22) |
516
(pATI->pDRIServerInfo->backOffset >> 3));
518
int depthOffsetPitch = (((pATI->pDRIServerInfo->depthPitch/8) << 22) |
519
(pATI->pDRIServerInfo->depthOffset >> 3));
521
BoxPtr pboxTmp, pboxNext, pboxBase;
525
int screenwidth = pScreenInfo->virtualX;
526
int screenheight = pScreenInfo->virtualY;
528
BoxPtr pbox = REGION_RECTS(prgnSrc);
529
int nbox = REGION_NUM_RECTS(prgnSrc);
531
BoxPtr pboxNew1 = NULL;
532
BoxPtr pboxNew2 = NULL;
533
DDXPointPtr pptNew1 = NULL;
534
DDXPointPtr pptNew2 = NULL;
535
DDXPointPtr pptSrc = &ptOldOrg;
537
int dx = pWin->drawable.x - ptOldOrg.x;
538
int dy = pWin->drawable.y - ptOldOrg.y;
543
if (!pXAAInfo->SetupForScreenToScreenCopy)
546
/* FIXME: Only move the back and depth buffers for contexts
550
/* If the copy will overlap in Y, reverse the order */
555
/* Keep ordering in each band, reverse order of bands */
556
pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec)*nbox);
557
if (!pboxNew1) return;
558
pptNew1 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox);
563
pboxBase = pboxNext = pbox+nbox-1;
564
while (pboxBase >= pbox) {
565
while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
567
pboxTmp = pboxNext+1;
568
pptTmp = pptSrc + (pboxTmp - pbox);
569
while (pboxTmp <= pboxBase) {
570
*pboxNew1++ = *pboxTmp++;
571
*pptNew1++ = *pptTmp++;
581
/* No changes required */
585
/* If the regions will overlap in X, reverse the order */
590
/* reverse order of rects in each band */
591
pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec)*nbox);
592
pptNew2 = (DDXPointPtr)malloc(sizeof(DDXPointRec)*nbox);
593
if (!pboxNew2 || !pptNew2) {
600
pboxBase = pboxNext = pbox;
601
while (pboxBase < pbox+nbox) {
602
while ((pboxNext < pbox+nbox)
603
&& (pboxNext->y1 == pboxBase->y1))
606
pptTmp = pptSrc + (pboxTmp - pbox);
607
while (pboxTmp != pboxBase) {
608
*pboxNew2++ = *--pboxTmp;
609
*pptNew2++ = *--pptTmp;
619
/* No changes are needed */
623
(*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, xdir, ydir, GXcopy,
626
for (; nbox-- ; pbox++) {
631
int w = pbox->x2 - xa + 1;
632
int h = pbox->y2 - ya + 1;
634
if (destx < 0) xa -= destx, w += destx, destx = 0;
635
if (desty < 0) ya -= desty, h += desty, desty = 0;
636
if (destx + w > screenwidth) w = screenwidth - destx;
637
if (desty + h > screenheight) h = screenheight - desty;
639
if (w <= 0) continue;
640
if (h <= 0) continue;
642
ATIMach64WaitForFIFO(pATI, 2);
643
outf(SRC_OFF_PITCH, backOffsetPitch);
644
outf(DST_OFF_PITCH, backOffsetPitch);
646
(*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo,
651
/* FIXME: Move depth buffers? */
652
ATIMach64WaitForFIFO(pATI, 2);
653
outf(SRC_OFF_PITCH, depthOffsetPitch);
654
outf(DST_OFF_PITCH, depthOffsetPitch);
656
if (pATI->depthMoves)
657
ATIScreenToScreenCopyDepth(pScreenInfo,
664
ATIMach64WaitForFIFO(pATI, 2);
665
outf(SRC_OFF_PITCH, pATI->NewHW.dst_off_pitch);
666
outf(DST_OFF_PITCH, pATI->NewHW.src_off_pitch);
673
ATIDRIMarkSyncInt(pScreenInfo);
677
/* Compute log base 2 of val. */
678
static int Mach64MinBits(int val)
683
for (bits = 0; val; val >>= 1, ++bits);
687
static Bool ATIDRISetBufSize( ScreenPtr pScreen, unsigned int maxSize )
689
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
690
ATIPtr pATI = ATIPTR(pScreenInfo);
691
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
693
if (pATI->OptionBufferSize) {
694
if (pATI->OptionBufferSize < 1 || pATI->OptionBufferSize > maxSize ) {
695
xf86DrvMsg( pScreen->myNum, X_ERROR, "[drm] Illegal DMA buffers size: %d MB\n",
696
pATI->OptionBufferSize );
699
if (pATI->OptionBufferSize > 2) {
700
xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Illegal DMA buffers size: %d MB\n",
701
pATI->OptionBufferSize );
702
xf86DrvMsg( pScreen->myNum, X_WARNING, "[drm] Clamping DMA buffers size to 2 MB\n");
703
pATIDRIServer->bufferSize = 2;
705
pATIDRIServer->bufferSize = pATI->OptionBufferSize;
706
xf86DrvMsg( pScreen->myNum, X_CONFIG, "[drm] Using %d MB for DMA buffers\n",
707
pATIDRIServer->bufferSize );
710
xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[drm] Using %d MB for DMA buffers\n",
711
pATIDRIServer->bufferSize );
717
static Bool ATIDRISetAgpMode( ScreenPtr pScreen )
719
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
720
ATIPtr pATI = ATIPTR(pScreenInfo);
721
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
723
unsigned long mode = drmAgpGetMode( pATI->drmFD ); /* Default mode */
724
unsigned int vendor = drmAgpVendorId( pATI->drmFD );
725
unsigned int device = drmAgpDeviceId( pATI->drmFD );
727
if (pATI->OptionAGPMode > 0 && pATI->OptionAGPMode <= ATI_AGP_MAX_MODE) {
728
pATIDRIServer->agpMode = pATI->OptionAGPMode;
729
xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using AGP %dx Mode\n",
730
pATIDRIServer->agpMode );
731
} else if (pATI->OptionAGPMode > 0) {
732
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Illegal AGP Mode: %d\n",
733
pATI->OptionAGPMode );
736
/* If no mode configured, use the default mode obtained from agpgart */
737
if ( mode & AGP_MODE_2X ) {
738
pATIDRIServer->agpMode = 2;
739
} else if ( mode & AGP_MODE_1X ) {
740
pATIDRIServer->agpMode = 1;
742
xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using AGP %dx Mode\n",
743
pATIDRIServer->agpMode );
746
mode &= ~AGP_MODE_MASK;
747
switch ( pATIDRIServer->agpMode ) {
748
case 2: mode |= AGP_MODE_2X;
749
case 1: default: mode |= AGP_MODE_1X;
752
if (pATI->OptionAGPSize) {
753
switch (pATI->OptionAGPSize) {
760
pATIDRIServer->agpSize = pATI->OptionAGPSize;
761
xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using %d MB AGP aperture\n",
762
pATIDRIServer->agpSize );
765
xf86DrvMsg( pScreen->myNum, X_ERROR,
766
"[agp] Illegal aperture size %d MB\n", pATI->OptionAGPSize );
770
xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using %d MB AGP aperture\n",
771
pATIDRIServer->agpSize );
774
xf86DrvMsg( pScreen->myNum, X_INFO,
775
"[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
776
mode, vendor, device,
777
PCI_DEV_VENDOR_ID(pATI->PCIInfo),
778
PCI_DEV_DEVICE_ID(pATI->PCIInfo) );
780
if ( drmAgpEnable( pATI->drmFD, mode ) < 0 ) {
781
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
782
drmAgpRelease( pATI->drmFD );
789
/* Initialize the AGP state. Request memory for use in AGP space, and
790
* initialize the Rage Pro registers to point to that memory.
792
static Bool ATIDRIAgpInit( ScreenPtr pScreen )
794
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
795
ATIPtr pATI = ATIPTR(pScreenInfo);
796
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
802
pATIDRIServer->agpSize = ATI_DEFAULT_AGP_SIZE;
803
pATIDRIServer->agpMode = ATI_DEFAULT_AGP_MODE;
804
pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
805
pATIDRIServer->ringSize = 16; /* 16 kB ring */
807
if ( drmAgpAcquire( pATI->drmFD ) < 0 ) {
808
xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP not available\n" );
812
if (!ATIDRISetAgpMode( pScreen ))
815
pATIDRIServer->agpOffset = 0;
817
ret = drmAgpAlloc( pATI->drmFD, pATIDRIServer->agpSize*1024*1024,
818
0, NULL, &pATIDRIServer->agpHandle );
820
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
821
drmAgpRelease( pATI->drmFD );
824
xf86DrvMsg( pScreen->myNum, X_INFO,
825
"[agp] %d kB allocated with handle 0x%08x\n",
826
pATIDRIServer->agpSize*1024, pATIDRIServer->agpHandle );
828
if ( drmAgpBind( pATI->drmFD, pATIDRIServer->agpHandle, pATIDRIServer->agpOffset) < 0 ) {
829
xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind\n" );
830
drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
831
drmAgpRelease( pATI->drmFD );
835
xf86DrvMsg(pScreen->myNum, X_INFO,
836
"[agp] Using %d kB for DMA descriptor ring\n", pATIDRIServer->ringSize);
838
if ( !ATIDRISetBufSize( pScreen, pATIDRIServer->agpSize ) )
841
pATIDRIServer->agpTexSize = pATIDRIServer->agpSize - pATIDRIServer->bufferSize;
843
/* Reserve space for the DMA descriptor ring */
844
pATIDRIServer->ringStart = pATIDRIServer->agpOffset;
845
pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */
847
/* Reserve space for the vertex buffer */
848
pATIDRIServer->bufferStart = pATIDRIServer->ringStart + pATIDRIServer->ringMapSize;
849
pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024;
851
/* Reserve the rest for AGP textures */
852
pATIDRIServer->agpTexStart = pATIDRIServer->bufferStart + pATIDRIServer->bufferMapSize;
853
s = (pATIDRIServer->agpSize*1024*1024 - pATIDRIServer->agpTexStart);
854
l = Mach64MinBits((s-1) / MACH64_NR_TEX_REGIONS);
855
if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY;
856
pATIDRIServer->agpTexMapSize = (s >> l) << l;
857
pATIDRIServer->log2AGPTexGran = l;
859
xf86DrvMsg(pScreen->myNum, X_INFO,
860
"[agp] Using %d kB for AGP textures\n", pATIDRIServer->agpTexMapSize/1024);
862
/* Map DMA descriptor ring */
863
if ( drmAddMap( pATI->drmFD, pATIDRIServer->ringStart, pATIDRIServer->ringMapSize,
864
DRM_AGP, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) {
865
xf86DrvMsg( pScreen->myNum, X_ERROR,
866
"[agp] Could not add ring mapping\n" );
869
xf86DrvMsg( pScreen->myNum, X_INFO,
870
"[agp] ring handle = 0x%08x\n",
871
pATIDRIServer->ringHandle );
873
if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle,
874
pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) {
875
xf86DrvMsg( pScreen->myNum, X_ERROR,
876
"[agp] Could not map ring\n" );
879
xf86DrvMsg( pScreen->myNum, X_INFO,
880
"[agp] Ring mapped at 0x%08lx\n",
881
(unsigned long)pATIDRIServer->ringMap );
883
/* Map vertex buffers */
884
if ( drmAddMap( pATI->drmFD, pATIDRIServer->bufferStart, pATIDRIServer->bufferMapSize,
885
DRM_AGP, DRM_READ_ONLY, &pATIDRIServer->bufferHandle ) < 0 ) {
886
xf86DrvMsg( pScreen->myNum, X_ERROR,
887
"[agp] Could not add vertex buffers mapping\n" );
890
xf86DrvMsg( pScreen->myNum, X_INFO,
891
"[agp] vertex buffers handle = 0x%08x\n",
892
pATIDRIServer->bufferHandle );
894
if ( drmMap( pATI->drmFD, pATIDRIServer->bufferHandle,
895
pATIDRIServer->bufferMapSize, &pATIDRIServer->bufferMap ) < 0 ) {
896
xf86DrvMsg( pScreen->myNum, X_ERROR,
897
"[agp] Could not map vertex buffers\n" );
900
xf86DrvMsg( pScreen->myNum, X_INFO,
901
"[agp] Vertex buffers mapped at 0x%08lx\n",
902
(unsigned long)pATIDRIServer->bufferMap );
904
/* Map AGP Textures */
905
if (drmAddMap(pATI->drmFD, pATIDRIServer->agpTexStart, pATIDRIServer->agpTexMapSize,
906
DRM_AGP, 0, &pATIDRIServer->agpTexHandle) < 0) {
907
xf86DrvMsg(pScreen->myNum, X_ERROR,
908
"[agp] Could not add AGP texture region mapping\n");
911
xf86DrvMsg(pScreen->myNum, X_INFO,
912
"[agp] AGP texture region handle = 0x%08x\n",
913
pATIDRIServer->agpTexHandle);
915
if (drmMap(pATI->drmFD, pATIDRIServer->agpTexHandle, pATIDRIServer->agpTexMapSize,
916
&pATIDRIServer->agpTexMap) < 0) {
917
xf86DrvMsg(pScreen->myNum, X_ERROR,
918
"[agp] Could not map AGP texture region\n");
921
xf86DrvMsg(pScreen->myNum, X_INFO,
922
"[agp] AGP Texture region mapped at 0x%08lx\n",
923
(unsigned long)pATIDRIServer->agpTexMap);
925
/* Initialize Mach64's AGP registers */
926
cntl = inm( AGP_CNTL );
927
cntl &= ~AGP_APER_SIZE_MASK;
928
switch ( pATIDRIServer->agpSize ) {
929
case 256: cntl |= AGP_APER_SIZE_256MB; break;
930
case 128: cntl |= AGP_APER_SIZE_128MB; break;
931
case 64: cntl |= AGP_APER_SIZE_64MB; break;
932
case 32: cntl |= AGP_APER_SIZE_32MB; break;
933
case 16: cntl |= AGP_APER_SIZE_16MB; break;
934
case 8: cntl |= AGP_APER_SIZE_8MB; break;
935
case 4: cntl |= AGP_APER_SIZE_4MB; break;
937
xf86DrvMsg( pScreen->myNum, X_ERROR,
938
"[agp] Illegal aperture size %d kB\n",
939
pATIDRIServer->agpSize*1024 );
943
/* 1 = DATA comes in clock in which TRDY sampled (default) */
944
/* 0 = DATA comes in clock after TRDY sampled */
945
cntl |= AGP_TRDY_MODE;
947
/* 1 = generate all reads as high priority */
948
/* 0 = generate all reads as their default priority (default) */
949
/* Setting this only works for me at AGP 1x mode (LLD) */
950
if (pATIDRIServer->agpMode == 1) {
951
cntl |= HIGH_PRIORITY_READ_EN;
953
cntl &= ~HIGH_PRIORITY_READ_EN;
956
outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
957
outm( AGP_CNTL, cntl );
962
static Bool ATIDRIPciInit( ScreenPtr pScreen )
964
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
965
ATIPtr pATI = ATIPTR(pScreenInfo);
966
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
968
pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
969
pATIDRIServer->ringSize = 16; /* 16 kB ring */
971
if ( !ATIDRISetBufSize( pScreen, (unsigned)(-1) ) )
974
/* Set size of the DMA descriptor ring */
975
pATIDRIServer->ringStart = 0;
976
pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */
978
/* Set size of the vertex buffer */
979
pATIDRIServer->bufferStart = 0;
980
pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024;
982
/* Map DMA descriptor ring */
983
if ( drmAddMap( pATI->drmFD, 0, pATIDRIServer->ringMapSize,
984
DRM_CONSISTENT, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) {
985
xf86DrvMsg( pScreen->myNum, X_ERROR,
986
"[pci] Could not add ring mapping\n" );
989
xf86DrvMsg( pScreen->myNum, X_INFO, "[pci] ring handle = 0x%08x\n",
990
pATIDRIServer->ringHandle );
992
if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle,
993
pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) {
994
xf86DrvMsg( pScreen->myNum, X_ERROR,
995
"[pci] Could not map ring\n" );
998
xf86DrvMsg( pScreen->myNum, X_INFO,
999
"[pci] Ring mapped at 0x%08lx\n",
1000
(unsigned long)pATIDRIServer->ringMap );
1002
/* Disable AGP for ForcePCIMode */
1003
if ( pATI->BusType != ATI_BUS_PCI ) {
1004
outm( AGP_BASE, 0 );
1005
outm( AGP_CNTL, 0 );
1011
/* Add a map for the MMIO registers that will be accessed by any
1012
* DRI-based clients.
1014
static Bool ATIDRIMapInit( ScreenPtr pScreen )
1016
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
1017
ATIPtr pATI = ATIPTR(pScreenInfo);
1018
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1020
pATIDRIServer->regsSize = getpagesize();
1021
if ( drmAddMap( pATI->drmFD, pATI->Block1Base,
1022
pATIDRIServer->regsSize,
1023
DRM_REGISTERS, DRM_READ_ONLY,
1024
&pATIDRIServer->regsHandle ) < 0 ) {
1025
xf86DrvMsg( pScreen->myNum, X_ERROR,
1026
"[drm] failed to map registers\n" );
1029
xf86DrvMsg( pScreen->myNum, X_INFO,
1030
"[drm] register handle = 0x%08x\n",
1031
pATIDRIServer->regsHandle );
1036
/* Initialize the kernel data structures. */
1037
static Bool ATIDRIKernelInit( ScreenPtr pScreen )
1039
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
1040
ATIPtr pATI = ATIPTR(pScreenInfo);
1041
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1044
memset( &info, 0, sizeof(drmMach64Init) );
1046
info.func = DRM_MACH64_INIT_DMA;
1047
info.sarea_priv_offset = sizeof(XF86DRISAREARec);
1048
info.is_pci = pATIDRIServer->IsPCI;
1049
info.dma_mode = pATI->OptionDMAMode;
1051
info.fb_bpp = pATI->bitsPerPixel;
1052
info.front_offset = pATIDRIServer->frontOffset;
1053
info.front_pitch = pATIDRIServer->frontPitch;
1054
info.back_offset = pATIDRIServer->backOffset;
1055
info.back_pitch = pATIDRIServer->backPitch;
1057
info.depth_bpp = 16;
1058
info.depth_offset = pATIDRIServer->depthOffset;
1059
info.depth_pitch = pATIDRIServer->depthPitch;
1061
info.fb_offset = pATI->LinearBase;
1062
info.mmio_offset = pATIDRIServer->regsHandle;
1063
info.ring_offset = pATIDRIServer->ringHandle;
1064
info.buffers_offset = pATIDRIServer->bufferHandle;
1065
info.agp_textures_offset = pATIDRIServer->agpTexHandle;
1067
if ( drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
1068
&info, sizeof(drmMach64Init) ) < 0 ) {
1075
/* Add a map for the DMA buffers that will be accessed by any
1076
* DRI-based clients.
1078
static Bool ATIDRIAddBuffers( ScreenPtr pScreen )
1080
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
1081
ATIPtr pATI = ATIPTR(pScreenInfo);
1082
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1084
/* Initialize vertex buffers */
1085
if ( pATIDRIServer->IsPCI ) {
1086
pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
1087
pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE,
1092
pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
1093
pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE,
1096
pATIDRIServer->bufferStart );
1098
if ( pATIDRIServer->numBuffers <= 0 ) {
1099
xf86DrvMsg( pScreen->myNum, X_ERROR,
1100
"[drm] Could not create DMA buffers list\n" );
1103
xf86DrvMsg( pScreen->myNum, X_INFO,
1104
"[drm] Added %d %d byte DMA buffers\n",
1105
pATIDRIServer->numBuffers, MACH64_BUFFER_SIZE );
1110
static Bool ATIDRIMapBuffers( ScreenPtr pScreen )
1112
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
1113
ATIPtr pATI = ATIPTR(pScreenInfo);
1114
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1116
pATIDRIServer->drmBuffers = drmMapBufs( pATI->drmFD );
1117
if ( !pATIDRIServer->drmBuffers ) {
1118
xf86DrvMsg( pScreen->myNum, X_ERROR,
1119
"[drm] Failed to map DMA buffers list\n" );
1122
xf86DrvMsg( pScreen->myNum, X_INFO,
1123
"[drm] Mapped %d DMA buffers at 0x%08lx\n",
1124
pATIDRIServer->drmBuffers->count,
1125
(unsigned long)pATIDRIServer->drmBuffers->list->address );
1130
static Bool ATIDRIIrqInit( ScreenPtr pScreen )
1132
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
1133
ATIPtr pATI = ATIPTR(pScreenInfo);
1135
if ( pATI->irq <= 0 ) {
1136
pATI->irq = drmGetInterruptFromBusID(pATI->drmFD,
1137
PCI_CFG_BUS(pATI->PCIInfo),
1138
PCI_CFG_DEV(pATI->PCIInfo),
1139
PCI_CFG_FUNC(pATI->PCIInfo));
1140
if ( pATI->irq <= 0 ) {
1141
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1142
"[drm] Couldn't find IRQ for bus id %d:%d:%d\n",
1143
PCI_CFG_BUS(pATI->PCIInfo),
1144
PCI_CFG_DEV(pATI->PCIInfo),
1145
PCI_CFG_FUNC(pATI->PCIInfo));
1147
} else if ((drmCtlInstHandler(pATI->drmFD, pATI->irq)) != 0) {
1148
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1149
"[drm] Failed to initialize interrupt handler with IRQ %d\n",
1155
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1156
"[drm] Installed interrupt handler, using IRQ %d\n",
1159
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1160
"[drm] Falling back to irq-free operation\n");
1169
/* Initialize the screen-specific data structures for the DRI and the
1170
* Rage Pro. This is the main entry point to the device-specific
1171
* initialization code. It calls device-independent DRI functions to
1172
* create the DRI data structures and initialize the DRI state.
1174
Bool ATIDRIScreenInit( ScreenPtr pScreen )
1176
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
1177
ATIPtr pATI = ATIPTR(pScreenInfo);
1178
DRIInfoPtr pDRIInfo;
1180
ATIDRIServerInfoPtr pATIDRIServer;
1181
drmVersionPtr version;
1182
int major, minor, patch;
1184
/* Check that the GLX, DRI, and DRM modules have been loaded by testing
1185
* for known symbols in each module.
1187
if ( !xf86LoaderCheckSymbol("GlxSetVisualConfigs") ) return FALSE;
1188
if ( !xf86LoaderCheckSymbol("drmAvailable") ) return FALSE;
1189
if ( !xf86LoaderCheckSymbol("DRIQueryVersion") ) {
1190
xf86DrvMsg( pScreen->myNum, X_ERROR,
1191
"[dri] ATIDRIScreenInit failed (libdri.a too old)\n" );
1195
/* Check the DRI version */
1196
DRIQueryVersion( &major, &minor, &patch );
1197
if ( major != DRIINFO_MAJOR_VERSION || minor < 0 ) {
1198
xf86DrvMsg( pScreen->myNum, X_ERROR,
1199
"[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
1200
"[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n"
1201
"[dri] Disabling the DRI.\n",
1202
major, minor, patch,
1203
DRIINFO_MAJOR_VERSION, 0 );
1207
switch ( pATI->bitsPerPixel ) {
1209
/* These modes are not supported (yet). */
1212
xf86DrvMsg( pScreen->myNum, X_ERROR,
1213
"[dri] Direct rendering only supported in 16 and 32 bpp modes\n");
1216
/* Only 16 and 32 color depths are supported currently. */
1218
if ( pATI->depth != 16) {
1219
xf86DrvMsg( pScreen->myNum, X_ERROR,
1220
"[dri] Direct rendering not supported for depth %d at fbbpp 16.\n", pATI->depth );
1228
/* Create the DRI data structure, and fill it in before calling the
1231
pDRIInfo = DRICreateInfoRec();
1232
if ( !pDRIInfo ) return FALSE;
1234
pATI->pDRIInfo = pDRIInfo;
1235
pDRIInfo->drmDriverName = ATIKernelDriverName;
1236
pDRIInfo->clientDriverName = ATIClientDriverName;
1237
if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
1238
pDRIInfo->busIdString = DRICreatePCIBusID(pATI->PCIInfo);
1240
pDRIInfo->busIdString = malloc( 64 );
1241
sprintf( pDRIInfo->busIdString,
1243
PCI_DEV_BUS(pATI->PCIInfo),
1244
PCI_DEV_DEV(pATI->PCIInfo),
1245
PCI_DEV_FUNC(pATI->PCIInfo) );
1247
pDRIInfo->ddxDriverMajorVersion = MACH64_VERSION_MAJOR;
1248
pDRIInfo->ddxDriverMinorVersion = MACH64_VERSION_MINOR;
1249
pDRIInfo->ddxDriverPatchVersion = MACH64_VERSION_PATCH;
1250
pDRIInfo->frameBufferPhysicalAddress = (void *)pATI->LinearBase;
1251
pDRIInfo->frameBufferSize = pATI->LinearSize;
1252
pDRIInfo->frameBufferStride = (pScreenInfo->displayWidth *
1253
pATI->FBBytesPerPixel);
1254
pDRIInfo->ddxDrawableTableEntry = ATI_MAX_DRAWABLES;
1256
if ( SAREA_MAX_DRAWABLES < ATI_MAX_DRAWABLES ) {
1257
pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
1259
pDRIInfo->maxDrawableTableEntry = ATI_MAX_DRAWABLES;
1262
/* For now the mapping works by using a fixed size defined
1263
* in the SAREA header
1265
if ( sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec) > SAREA_MAX ) {
1266
ErrorF( "[dri] Data does not fit in SAREA\n" );
1269
xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %u+%u: %u\n",
1270
(unsigned)sizeof(XF86DRISAREARec),
1271
(unsigned)sizeof(ATISAREAPrivRec),
1272
(unsigned)(sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec)) );
1273
pDRIInfo->SAREASize = SAREA_MAX;
1275
pATIDRI = (ATIDRIPtr) xnfcalloc( sizeof(ATIDRIRec), 1 );
1277
DRIDestroyInfoRec( pATI->pDRIInfo );
1278
pATI->pDRIInfo = NULL;
1279
xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
1280
"[dri] Failed to allocate memory for private record\n" );
1283
pATIDRIServer = (ATIDRIServerInfoPtr)
1284
xnfcalloc( sizeof(ATIDRIServerInfoRec), 1 );
1285
if ( !pATIDRIServer ) {
1287
DRIDestroyInfoRec( pATI->pDRIInfo );
1288
pATI->pDRIInfo = NULL;
1289
xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
1290
"[dri] Failed to allocate memory for private record\n" );
1294
pATI->pDRIServerInfo = pATIDRIServer;
1296
pDRIInfo->devPrivate = pATIDRI;
1297
pDRIInfo->devPrivateSize = sizeof(ATIDRIRec);
1298
pDRIInfo->contextSize = sizeof(ATIDRIContextRec);
1300
pDRIInfo->CreateContext = ATICreateContext;
1301
pDRIInfo->DestroyContext = ATIDestroyContext;
1302
pDRIInfo->SwapContext = ATIDRISwapContext;
1303
pDRIInfo->InitBuffers = ATIDRIInitBuffers;
1304
pDRIInfo->MoveBuffers = ATIDRIMoveBuffers;
1306
if (!pATI->useEXA) {
1307
pDRIInfo->TransitionTo2d = ATIDRITransitionTo2d;
1308
pDRIInfo->TransitionTo3d = ATIDRITransitionTo3d;
1310
#endif /* USE_XAA */
1313
pDRIInfo->TransitionTo2d = ATIDRITransitionTo2d_EXA;
1314
pDRIInfo->TransitionTo3d = ATIDRITransitionTo3d_EXA;
1316
#endif /* USE_EXA */
1317
pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
1319
pDRIInfo->createDummyCtx = TRUE;
1320
pDRIInfo->createDummyCtxPriv = FALSE;
1322
pATI->have3DWindows = FALSE;
1324
if ( !DRIScreenInit( pScreen, pDRIInfo, &pATI->drmFD ) ) {
1325
free( pATIDRIServer );
1326
pATI->pDRIServerInfo = NULL;
1327
free( pDRIInfo->devPrivate );
1328
pDRIInfo->devPrivate = NULL;
1329
DRIDestroyInfoRec( pDRIInfo );
1331
xf86DrvMsg( pScreen->myNum, X_ERROR,
1332
"[dri] DRIScreenInit Failed\n" );
1336
/* Check the DRM lib version.
1337
drmGetLibVersion was not supported in version 1.0, so check for
1338
symbol first to avoid possible crash or hang.
1340
if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
1341
version = drmGetLibVersion(pATI->drmFD);
1343
/* drmlib version 1.0.0 didn't have the drmGetLibVersion
1344
entry point. Fake it by allocating a version record
1345
via drmGetVersion and changing it to version 1.0.0
1347
version = drmGetVersion(pATI->drmFD);
1348
version->version_major = 1;
1349
version->version_minor = 0;
1350
version->version_patchlevel = 0;
1354
if (version->version_major != 1 ||
1355
version->version_minor < 1) {
1356
/* incompatible drm library version */
1357
xf86DrvMsg(pScreen->myNum, X_ERROR,
1358
"[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
1359
"[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
1360
"[dri] Disabling DRI.\n",
1361
version->version_major,
1362
version->version_minor,
1363
version->version_patchlevel);
1364
drmFreeVersion(version);
1365
ATIDRICloseScreen(pScreen);
1368
drmFreeVersion(version);
1371
/* Check the mach64 DRM version */
1372
version = drmGetVersion( pATI->drmFD );
1374
if ( version->version_major != 2 ||
1375
version->version_minor < 0 ) {
1376
/* Incompatible DRM version */
1377
xf86DrvMsg( pScreen->myNum, X_ERROR,
1378
"[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
1379
"[dri] mach64.o kernel module version is %d.%d.%d, but version 2.x is needed (with 2.x >= 2.0).\n"
1380
"[dri] Disabling DRI.\n",
1381
version->version_major,
1382
version->version_minor,
1383
version->version_patchlevel );
1384
drmFreeVersion( version );
1385
ATIDRICloseScreen( pScreen );
1388
drmFreeVersion( version );
1391
switch ( pATI->OptionDMAMode ) {
1392
case MACH64_MODE_DMA_ASYNC:
1393
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request asynchronous DMA mode\n");
1395
case MACH64_MODE_DMA_SYNC:
1396
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request synchronous DMA mode\n");
1398
case MACH64_MODE_MMIO:
1399
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request pseudo-DMA (MMIO) mode\n");
1402
xf86DrvMsg(pScreen->myNum, X_WARNING, "[drm] Unknown DMA mode\n");
1405
pATIDRIServer->IsPCI = (pATI->BusType == ATI_BUS_PCI || pATI->OptionIsPCI) ? TRUE : FALSE;
1407
if ( pATI->BusType != ATI_BUS_PCI && pATI->OptionIsPCI ) {
1408
xf86DrvMsg(pScreen->myNum, X_CONFIG, "[dri] Forcing PCI mode\n");
1411
/* Initialize AGP */
1412
if ( !pATIDRIServer->IsPCI && !ATIDRIAgpInit( pScreen ) ) {
1413
pATIDRIServer->IsPCI = TRUE;
1414
xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP failed to initialize -- falling back to PCI mode.\n" );
1415
xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] Make sure you have the agpgart kernel module loaded.\n" );
1418
/* Initialize PCI */
1419
if ( pATIDRIServer->IsPCI && !ATIDRIPciInit( pScreen ) ) {
1420
ATIDRICloseScreen( pScreen );
1424
if ( !ATIDRIMapInit( pScreen ) ) {
1425
ATIDRICloseScreen( pScreen );
1429
if ( !ATIInitVisualConfigs( pScreen ) ) {
1430
ATIDRICloseScreen( pScreen );
1433
xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
1434
"[dri] Visual configs initialized\n" );
1436
xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
1437
"[dri] Block 0 base at 0x%08lx\n", pATI->Block0Base );
1442
/* Finish initializing the device-dependent DRI state, and call
1443
* DRIFinishScreenInit() to complete the device-independent DRI
1446
Bool ATIDRIFinishScreenInit( ScreenPtr pScreen )
1448
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
1449
ATIPtr pATI = ATIPTR(pScreenInfo);
1450
ATISAREAPrivPtr pSAREAPriv;
1452
ATIDRIServerInfoPtr pATIDRIServer;
1454
pATI->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
1456
/* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
1457
* because *DRIKernelInit requires that the hardware lock is held by
1458
* the X server, and the first time the hardware lock is grabbed is
1459
* in DRIFinishScreenInit.
1461
if ( !DRIFinishScreenInit( pScreen ) ) {
1462
ATIDRICloseScreen( pScreen );
1466
/* Initialize the DMA buffer list */
1467
/* Need to do this before ATIDRIKernelInit so we can init the freelist */
1468
if ( !ATIDRIAddBuffers( pScreen ) ) {
1469
ATIDRICloseScreen( pScreen );
1473
/* Initialize the kernel data structures */
1474
if ( !ATIDRIKernelInit( pScreen ) ) {
1475
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1476
"[drm] Failed to initialize the mach64.o kernel module\n");
1477
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1478
"[drm] Check the system log for more information.\n");
1479
ATIDRICloseScreen( pScreen );
1483
if ( !ATIDRIMapBuffers( pScreen ) ) {
1484
ATIDRICloseScreen( pScreen );
1488
/* Initialize IRQ */
1489
ATIDRIIrqInit( pScreen );
1491
pSAREAPriv = (ATISAREAPrivPtr) DRIGetSAREAPrivate( pScreen );
1492
memset( pSAREAPriv, 0, sizeof(*pSAREAPriv) );
1494
pATIDRI = (ATIDRIPtr)pATI->pDRIInfo->devPrivate;
1495
pATIDRIServer = pATI->pDRIServerInfo;
1497
pATIDRI->width = pScreenInfo->virtualX;
1498
pATIDRI->height = pScreenInfo->virtualY;
1499
pATIDRI->mem = pScreenInfo->videoRam * 1024;
1500
pATIDRI->cpp = pScreenInfo->bitsPerPixel / 8;
1502
pATIDRI->IsPCI = pATIDRIServer->IsPCI;
1503
pATIDRI->AGPMode = pATIDRIServer->agpMode;
1505
pATIDRI->frontOffset = pATIDRIServer->frontOffset;
1506
pATIDRI->frontPitch = pATIDRIServer->frontPitch;
1508
pATIDRI->backOffset = pATIDRIServer->backOffset;
1509
pATIDRI->backPitch = pATIDRIServer->backPitch;
1511
pATIDRI->depthOffset = pATIDRIServer->depthOffset;
1512
pATIDRI->depthPitch = pATIDRIServer->depthPitch;
1514
pATIDRI->textureOffset = pATIDRIServer->textureOffset;
1515
pATIDRI->textureSize = pATIDRIServer->textureSize;
1516
pATIDRI->logTextureGranularity = pATIDRIServer->logTextureGranularity;
1518
pATIDRI->regs = pATIDRIServer->regsHandle;
1519
pATIDRI->regsSize = pATIDRIServer->regsSize;
1521
pATIDRI->agp = pATIDRIServer->agpTexHandle;
1522
pATIDRI->agpSize = pATIDRIServer->agpTexMapSize;
1523
pATIDRI->logAgpTextureGranularity = pATIDRIServer->log2AGPTexGran;
1524
pATIDRI->agpTextureOffset = pATIDRIServer->agpTexStart;
1530
* This function will attempt to get the Mach64 hardware back into shape
1531
* after a resume from disc. Its an extract from ATIDRIAgpInit and ATIDRIFinishScreenInit
1532
* This also calls a new ioctl in the mach64 DRM that in its turn is
1533
* an extraction of the hardware-affecting bits from mach64_do_init_drm()
1535
* I am assuming here that pATI->pDRIServerInfo doesn't change
1536
* elsewhere in incomaptible ways.
1537
* How will this code react to resuming after a failed resumeor pci based dri ?
1539
void ATIDRIResume( ScreenPtr pScreen )
1541
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
1542
ATIPtr pATI = ATIPTR(pScreenInfo);
1543
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1545
xf86DrvMsg( pScreen->myNum, X_INFO,
1546
"[RESUME] Attempting to re-init Mach64 hardware.\n");
1548
if (!pATIDRIServer->IsPCI) {
1549
if (!ATIDRISetAgpMode(pScreen))
1552
outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
1556
/* The screen is being closed, so clean up any state and free any
1557
* resources used by the DRI.
1559
void ATIDRICloseScreen( ScreenPtr pScreen )
1561
ScrnInfoPtr pScreenInfo = xf86ScreenToScrn(pScreen);
1562
ATIPtr pATI = ATIPTR(pScreenInfo);
1563
ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
1566
/* Stop interrupt generation and handling if used */
1567
if ( pATI->irq > 0 ) {
1568
if ( drmCtlUninstHandler(pATI->drmFD) != 0 ) {
1569
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
1570
"[drm] Error uninstalling interrupt handler for IRQ %d\n", pATI->irq);
1572
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
1573
"[drm] Uninstalled interrupt handler for IRQ %d\n", pATI->irq);
1578
/* De-allocate DMA buffers */
1579
if ( pATIDRIServer->drmBuffers ) {
1580
drmUnmapBufs( pATIDRIServer->drmBuffers );
1581
pATIDRIServer->drmBuffers = NULL;
1584
/* De-allocate all kernel resources */
1585
memset(&info, 0, sizeof(drmMach64Init));
1586
info.func = DRM_MACH64_CLEANUP_DMA;
1587
drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
1588
&info, sizeof(drmMach64Init) );
1590
/* De-allocate all AGP resources */
1591
if ( pATIDRIServer->agpTexMap ) {
1592
drmUnmap( pATIDRIServer->agpTexMap, pATIDRIServer->agpTexMapSize );
1593
pATIDRIServer->agpTexMap = NULL;
1595
if ( pATIDRIServer->bufferMap ) {
1596
drmUnmap( pATIDRIServer->bufferMap, pATIDRIServer->bufferMapSize );
1597
pATIDRIServer->bufferMap = NULL;
1599
if ( pATIDRIServer->ringMap ) {
1600
drmUnmap( pATIDRIServer->ringMap, pATIDRIServer->ringMapSize );
1601
pATIDRIServer->ringMap = NULL;
1603
if ( pATIDRIServer->agpHandle ) {
1604
drmAgpUnbind( pATI->drmFD, pATIDRIServer->agpHandle );
1605
drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
1606
pATIDRIServer->agpHandle = 0;
1607
drmAgpRelease( pATI->drmFD );
1610
/* De-allocate all PCI resources */
1611
if ( pATIDRIServer->IsPCI && pATIDRIServer->ringHandle ) {
1612
drmRmMap( pATI->drmFD, pATIDRIServer->ringHandle );
1613
pATIDRIServer->ringHandle = 0;
1616
/* De-allocate all DRI resources */
1617
DRICloseScreen( pScreen );
1619
/* De-allocate all DRI data structures */
1620
if ( pATI->pDRIInfo ) {
1621
if ( pATI->pDRIInfo->devPrivate ) {
1622
free( pATI->pDRIInfo->devPrivate );
1623
pATI->pDRIInfo->devPrivate = NULL;
1625
DRIDestroyInfoRec( pATI->pDRIInfo );
1626
pATI->pDRIInfo = NULL;
1628
if ( pATI->pDRIServerInfo ) {
1629
free( pATI->pDRIServerInfo );
1630
pATI->pDRIServerInfo = NULL;
1632
if ( pATI->pVisualConfigs ) {
1633
free( pATI->pVisualConfigs );
1634
pATI->pVisualConfigs = NULL;
1636
if ( pATI->pVisualConfigsPriv ) {
1637
free( pATI->pVisualConfigsPriv );
1638
pATI->pVisualConfigsPriv = NULL;