1
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_dri.c,v 1.25 2003/01/29 15:42:17 eich Exp $ */
4
* DRI wrapper for 300, 540, 630, 730
5
* (310/325 series experimental and incomplete)
7
* taken and modified from tdfx_dri.c, mga_dri.c
11
#include "xf86_OSproc.h"
12
#include "xf86_ansic.h"
15
#include "xf86PciInfo.h"
19
#include "GL/glxtokens.h"
23
#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0)
24
#include "xf86drmCompat.h"
27
/* TW: Idle function for 300 series */
28
#define BR(x) (0x8200 | (x) << 2)
30
while((MMIO_IN16(pSiS->IOBase, BR(16)+2) & 0xE000) != 0xE000){}; \
31
while((MMIO_IN16(pSiS->IOBase, BR(16)+2) & 0xE000) != 0xE000){}; \
32
MMIO_IN16(pSiS->IOBase, 0x8240);
34
/* TW: Idle function for 310/325 series */
35
#define Q_STATUS 0x85CC
38
while( (MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
39
while( (MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
40
while( (MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
41
MMIO_IN16(pSiS->IOBase, Q_STATUS); \
45
extern void GlxSetVisualConfigs(
47
__GLXvisualConfig *configs,
51
#define AGP_PAGE_SIZE 4096
52
#define AGP_PAGES 2048
53
#define AGP_SIZE (AGP_PAGE_SIZE * AGP_PAGES)
54
#define AGP_CMDBUF_PAGES 256
55
#define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES)
57
static char SISKernelDriverName[] = "sis";
58
static char SISClientDriverName[] = "sis";
60
static Bool SISInitVisualConfigs(ScreenPtr pScreen);
61
static Bool SISCreateContext(ScreenPtr pScreen, VisualPtr visual,
62
drmContext hwContext, void *pVisualConfigPriv,
63
DRIContextType contextStore);
64
static void SISDestroyContext(ScreenPtr pScreen, drmContext hwContext,
65
DRIContextType contextStore);
66
static void SISDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
67
DRIContextType readContextType,
68
void *readContextStore,
69
DRIContextType writeContextType,
70
void *writeContextStore);
71
static void SISDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
72
static void SISDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
73
RegionPtr prgnSrc, CARD32 index);
75
#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
76
extern Bool drmSiSAgpInit(int driSubFD, int offset, int size);
80
SISInitVisualConfigs(ScreenPtr pScreen)
82
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
83
SISPtr pSIS = SISPTR(pScrn);
85
__GLXvisualConfig *pConfigs = 0;
86
SISConfigPrivPtr pSISConfigs = 0;
87
SISConfigPrivPtr *pSISConfigPtrs = 0;
88
int i, db, z_stencil, accum;
91
if(getenv("SIS_FORCE_Z16")){
95
switch (pScrn->bitsPerPixel) {
101
numConfigs = (useZ16)?8:16;
103
if (!(pConfigs = (__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),
107
if (!(pSISConfigs = (SISConfigPrivPtr)xcalloc(sizeof(SISConfigPrivRec),
112
if (!(pSISConfigPtrs = (SISConfigPrivPtr*)xcalloc(sizeof(SISConfigPrivPtr),
118
for (i=0; i<numConfigs; i++)
119
pSISConfigPtrs[i] = &pSISConfigs[i];
122
for (accum = 0; accum <= 1; accum++) {
123
for (z_stencil=0; z_stencil<(useZ16?2:4); z_stencil++) {
124
for (db = 0; db <= 1; db++) {
125
pConfigs[i].vid = -1;
126
pConfigs[i].class = -1;
127
pConfigs[i].rgba = TRUE;
128
pConfigs[i].redSize = -1;
129
pConfigs[i].greenSize = -1;
130
pConfigs[i].blueSize = -1;
131
pConfigs[i].redMask = -1;
132
pConfigs[i].greenMask = -1;
133
pConfigs[i].blueMask = -1;
134
pConfigs[i].alphaMask = 0;
136
pConfigs[i].accumRedSize = 16;
137
pConfigs[i].accumGreenSize = 16;
138
pConfigs[i].accumBlueSize = 16;
139
pConfigs[i].accumAlphaSize = 16;
141
pConfigs[i].accumRedSize = 0;
142
pConfigs[i].accumGreenSize = 0;
143
pConfigs[i].accumBlueSize = 0;
144
pConfigs[i].accumAlphaSize = 0;
147
pConfigs[i].doubleBuffer = TRUE;
149
pConfigs[i].doubleBuffer = FALSE;
150
pConfigs[i].stereo = FALSE;
151
pConfigs[i].bufferSize = -1;
154
pConfigs[i].depthSize = 0;
155
pConfigs[i].stencilSize = 0;
158
pConfigs[i].depthSize = 16;
159
pConfigs[i].stencilSize = 0;
162
pConfigs[i].depthSize = 32;
163
pConfigs[i].stencilSize = 0;
166
pConfigs[i].depthSize = 24;
167
pConfigs[i].stencilSize = 8;
170
pConfigs[i].auxBuffers = 0;
171
pConfigs[i].level = 0;
172
pConfigs[i].visualRating = GLX_NONE_EXT;
173
pConfigs[i].transparentPixel = 0;
174
pConfigs[i].transparentRed = 0;
175
pConfigs[i].transparentGreen = 0;
176
pConfigs[i].transparentBlue = 0;
177
pConfigs[i].transparentAlpha = 0;
178
pConfigs[i].transparentIndex = 0;
183
if (i != numConfigs) {
184
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
185
"[dri] Incorrect initialization of visuals. Disabling DRI.\n");
191
pSIS->numVisualConfigs = numConfigs;
192
pSIS->pVisualConfigs = pConfigs;
193
pSIS->pVisualConfigsPriv = pSISConfigs;
194
GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pSISConfigPtrs);
199
Bool SISDRIScreenInit(ScreenPtr pScreen)
201
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
202
SISPtr pSIS = SISPTR(pScrn);
206
drmVersionPtr version;
209
/* Check that the GLX, DRI, and DRM modules have been loaded by testing
210
* for canonical symbols in each module. */
211
if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE;
212
if (!xf86LoaderCheckSymbol("DRIScreenInit")) return FALSE;
213
if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE;
214
if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
215
xf86DrvMsg(pScreen->myNum, X_ERROR,
216
"[dri] SISDRIScreenInit failed (libdri.a too old)\n");
220
/* Check the DRI version */
222
int major, minor, patch;
223
DRIQueryVersion(&major, &minor, &patch);
224
if (major != 4 || minor < 0) {
225
xf86DrvMsg(pScreen->myNum, X_ERROR,
226
"[dri] SISDRIScreenInit failed because of a version mismatch.\n"
227
"[dri] libDRI version is %d.%d.%d but version 4.0.x is needed.\n"
228
"[dri] Disabling DRI.\n",
229
major, minor, patch);
234
pDRIInfo = DRICreateInfoRec();
235
if (!pDRIInfo) return FALSE;
236
pSIS->pDRIInfo = pDRIInfo;
238
pDRIInfo->drmDriverName = SISKernelDriverName;
239
pDRIInfo->clientDriverName = SISClientDriverName;
240
pDRIInfo->busIdString = xalloc(64);
241
sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
242
((pciConfigPtr)pSIS->PciInfo->thisCard)->busnum,
243
((pciConfigPtr)pSIS->PciInfo->thisCard)->devnum,
244
((pciConfigPtr)pSIS->PciInfo->thisCard)->funcnum);
245
pDRIInfo->ddxDriverMajorVersion = 0;
246
pDRIInfo->ddxDriverMinorVersion = 1;
247
pDRIInfo->ddxDriverPatchVersion = 0;
249
pDRIInfo->frameBufferPhysicalAddress = pSIS->FbAddress;
251
/* TW: This was FbMapSize which is wrong as we must not
252
* ever overwrite HWCursor and TQ area. On the other
253
* hand, using availMem here causes MTRR allocation
254
* to fail ("base is not aligned to size"). Since
255
* DRI memory management is done via framebuffer
256
* device, I assume that the size given here
257
* is NOT used for eventual memory management.
259
pDRIInfo->frameBufferSize = pSIS->FbMapSize; /* availMem; */
261
/* TW: scrnOffset is being calulated in sis_vga.c */
262
pDRIInfo->frameBufferStride = pSIS->scrnOffset;
264
pDRIInfo->ddxDrawableTableEntry = SIS_MAX_DRAWABLES;
266
if (SAREA_MAX_DRAWABLES < SIS_MAX_DRAWABLES)
267
pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
269
pDRIInfo->maxDrawableTableEntry = SIS_MAX_DRAWABLES;
272
/* FIXME need to extend DRI protocol to pass this size back to client
273
* for SAREA mapping that includes a device private record
275
pDRIInfo->SAREASize =
276
((sizeof(XF86DRISAREARec) + getpagesize() - 1) & getpagesize()); /* round to page */
277
/* ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); */ /* round to page */
278
/* + shared memory device private rec */
280
/* For now the mapping works by using a fixed size defined
281
* in the SAREA header
283
if (sizeof(XF86DRISAREARec)+sizeof(SISSAREAPriv) > SAREA_MAX) {
284
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
285
"Data does not fit in SAREA\n");
288
pDRIInfo->SAREASize = SAREA_MAX;
291
if (!(pSISDRI = (SISDRIPtr)xcalloc(sizeof(SISDRIRec),1))) {
292
DRIDestroyInfoRec(pSIS->pDRIInfo);
296
pDRIInfo->devPrivate = pSISDRI;
297
pDRIInfo->devPrivateSize = sizeof(SISDRIRec);
298
pDRIInfo->contextSize = sizeof(SISDRIContextRec);
300
pDRIInfo->CreateContext = SISCreateContext;
301
pDRIInfo->DestroyContext = SISDestroyContext;
302
pDRIInfo->SwapContext = SISDRISwapContext;
303
pDRIInfo->InitBuffers = SISDRIInitBuffers;
304
pDRIInfo->MoveBuffers = SISDRIMoveBuffers;
305
pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
307
if (!DRIScreenInit(pScreen, pDRIInfo, &pSIS->drmSubFD)) {
308
xf86DrvMsg(pScreen->myNum, X_ERROR,
309
"[dri] DRIScreenInit failed. Disabling DRI.\n");
310
xfree(pDRIInfo->devPrivate);
311
pDRIInfo->devPrivate=0;
312
DRIDestroyInfoRec(pSIS->pDRIInfo);
319
/* XXX Check DRM kernel version here */
320
version = drmGetVersion(info->drmFD);
322
if (version->version_major != 1 ||
323
version->version_minor < 0) {
324
/* incompatible drm version */
325
xf86DrvMsg(pScreen->myNum, X_ERROR,
326
"[dri] SISDRIScreenInit failed because of a version mismatch.\n"
327
"[dri] sis.o kernel module version is %d.%d.%d but version 1.0.x is needed.\n"
328
"[dri] Disabling the DRI.\n",
329
version->version_major,
330
version->version_minor,
331
version->version_patchlevel);
332
drmFreeVersion(version);
333
R128DRICloseScreen(pScreen);
336
drmFreeVersion(version);
340
pSISDRI->regs.size = SISIOMAPSIZE;
341
pSISDRI->regs.map = 0;
342
if (drmAddMap(pSIS->drmSubFD, (drmHandle)pSIS->IOAddress,
343
pSISDRI->regs.size, DRM_REGISTERS, 0,
344
&pSISDRI->regs.handle)<0)
346
SISDRICloseScreen(pScreen);
350
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08lx\n",
351
pSISDRI->regs.handle);
356
pSIS->agpCmdBufSize = 0;
357
pSISDRI->AGPCmdBufSize = 0;
359
if (drmAgpAcquire(pSIS->drmSubFD) < 0) {
360
xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAcquire failed\n");
364
/* TODO: default value is 2x? */
365
if (drmAgpEnable(pSIS->drmSubFD, drmAgpGetMode(pSIS->drmSubFD)&~0x0) < 0) {
366
xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpEnable failed\n");
369
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] drmAgpEnabled succeeded\n");
371
if (drmAgpAlloc(pSIS->drmSubFD, AGP_SIZE, 0, NULL, &pSIS->agpHandle) < 0) {
372
xf86DrvMsg(pScreen->myNum, X_ERROR,
373
"[drm] drmAgpAlloc failed\n");
374
drmAgpRelease(pSIS->drmSubFD);
378
if (drmAgpBind(pSIS->drmSubFD, pSIS->agpHandle, 0) < 0) {
379
xf86DrvMsg(pScreen->myNum, X_ERROR,
380
"[drm] drmAgpBind failed\n");
381
drmAgpFree(pSIS->drmSubFD, pSIS->agpHandle);
382
drmAgpRelease(pSIS->drmSubFD);
387
pSIS->agpSize = AGP_SIZE;
388
pSIS->agpAddr = drmAgpBase(pSIS->drmSubFD);
389
/* pSIS->agpBase = */
391
pSISDRI->agp.size = pSIS->agpSize;
392
if (drmAddMap(pSIS->drmSubFD, (drmHandle)0,
393
pSISDRI->agp.size, DRM_AGP, 0,
394
&pSISDRI->agp.handle) < 0) {
395
xf86DrvMsg(pScreen->myNum, X_ERROR,
396
"[drm] Failed to map public agp area\n");
397
pSISDRI->agp.size = 0;
401
pSIS->agpCmdBufSize = AGP_CMDBUF_SIZE;
402
pSIS->agpCmdBufAddr = pSIS->agpAddr;
403
pSIS->agpCmdBufBase = pSIS->agpCmdBufAddr - pSIS->agpAddr +
405
pSIS->agpCmdBufFree = 0;
407
pSISDRI->AGPCmdBufOffset = pSIS->agpCmdBufAddr - pSIS->agpAddr;
408
pSISDRI->AGPCmdBufSize = pSIS->agpCmdBufSize;
410
drmSiSAgpInit(pSIS->drmSubFD, AGP_CMDBUF_SIZE,(AGP_SIZE - AGP_CMDBUF_SIZE));
415
pSIS->irq = drmGetInterruptFromBusID(pSIS->drmSubFD,
416
((pciConfigPtr)pSIS->PciInfo->thisCard)->busnum,
417
((pciConfigPtr)pSIS->PciInfo->thisCard)->devnum,
418
((pciConfigPtr)pSIS->PciInfo->thisCard)->funcnum);
420
if((drmCtlInstHandler(pSIS->drmSubFD, pSIS->irq)) != 0)
422
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
423
"[drm] failure adding irq %d handler, stereo disabled\n",
425
pSIS->irqEnabled = FALSE;
429
pSIS->irqEnabled = TRUE;
432
pSISDRI->irqEnabled = pSIS->irqEnabled;
434
if (!(SISInitVisualConfigs(pScreen))) {
435
SISDRICloseScreen(pScreen);
438
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized.\n" );
444
SISDRICloseScreen(ScreenPtr pScreen)
446
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
447
SISPtr pSIS = SISPTR(pScrn);
449
DRICloseScreen(pScreen);
451
if (pSIS->pDRIInfo) {
452
if (pSIS->pDRIInfo->devPrivate) {
453
xfree(pSIS->pDRIInfo->devPrivate);
454
pSIS->pDRIInfo->devPrivate=0;
456
DRIDestroyInfoRec(pSIS->pDRIInfo);
459
if (pSIS->pVisualConfigs) xfree(pSIS->pVisualConfigs);
460
if (pSIS->pVisualConfigsPriv) xfree(pSIS->pVisualConfigsPriv);
463
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Freeing agp memory\n");
464
drmAgpFree(pSIS->drmSubFD, pSIS->agpHandle);
465
xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Releasing agp module\n");
466
drmAgpRelease(pSIS->drmSubFD);
470
/* TODO: xserver receives driver's swapping event and do something
471
* according the data initialized in this function
474
SISCreateContext(ScreenPtr pScreen, VisualPtr visual,
475
drmContext hwContext, void *pVisualConfigPriv,
476
DRIContextType contextStore)
482
SISDestroyContext(ScreenPtr pScreen, drmContext hwContext,
483
DRIContextType contextStore)
488
SISDRIFinishScreenInit(ScreenPtr pScreen)
490
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
491
SISPtr pSiS = SISPTR(pScrn);
494
pSiS->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
495
/* pSiS->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */
497
pSISDRI=(SISDRIPtr)pSiS->pDRIInfo->devPrivate;
498
pSISDRI->deviceID=pSiS->Chipset;
499
pSISDRI->width=pScrn->virtualX;
500
pSISDRI->height=pScrn->virtualY;
501
pSISDRI->mem=pScrn->videoRam*1024;
502
pSISDRI->bytesPerPixel= (pScrn->bitsPerPixel+7) / 8;
504
pSISDRI->scrnX=pSISDRI->width;
505
pSISDRI->scrnY=pSISDRI->height;
508
pSISDRI->textureOffset=pSiS->texOffset;
509
pSISDRI->textureSize=pSiS->texSize;
510
pSISDRI->fbOffset=pSiS->fbOffset;
511
pSISDRI->backOffset=pSiS->backOffset;
512
pSISDRI->depthOffset=pSiS->depthOffset;
515
/* set SAREA value */
517
SISSAREAPriv *saPriv;
519
saPriv=(SISSAREAPriv*)DRIGetSAREAPrivate(pScreen);
523
saPriv->CtxOwner = -1;
524
saPriv->QueueLength = 0;
525
pSiS->cmdQueueLenPtr = &(saPriv->QueueLength);
526
saPriv->AGPCmdBufNext = 0;
529
saPriv->FrameCount = 0;
530
if (pSiS->VGAEngine == SIS_315_VGA) { /* 310/325 series */
532
*(unsigned long *)(pSiS->IOBase+0x8a2c) = 0; /* FIXME: Where is this on the 310 series ? */
535
} else { /* 300 series (and below) */
536
*(unsigned long *)(pSiS->IOBase+0x8a2c) = 0;
541
return DRIFinishScreenInit(pScreen);
545
SISDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
546
DRIContextType oldContextType, void *oldContext,
547
DRIContextType newContextType, void *newContext)
549
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
550
SISPtr pSiS = SISPTR(pScrn);
553
if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
554
(newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */
555
SISSwapContextPrivate(pScreen);
557
if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
558
(newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */
559
SISLostContext(pScreen);
565
* TODO: do this only if X-Server get lock. If kernel supports delayed
566
* signal, needless to do this
568
if (pSiS->VGAEngine == SIS_315_VGA) {
570
*(pSiS->IOBase + 0x8B50) = 0xff; /* FIXME: Where is this on 310 series */
571
*(unsigned int *)(pSiS->IOBase + 0x8B60) = -1; /* FIXME: Where is this on 310 series */
574
*(pSiS->IOBase + 0x8B50) = 0xff;
575
*(unsigned int *)(pSiS->IOBase + 0x8B60) = -1;
580
SISDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
582
ScreenPtr pScreen = pWin->drawable.pScreen;
583
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
584
SISPtr pSiS = SISPTR(pScrn);
586
if (pSiS->VGAEngine == SIS_315_VGA) {
587
SiS310Idle /* 310/325 series */
589
SiSIdle /* 300 series */
594
SISDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
595
RegionPtr prgnSrc, CARD32 index)
597
ScreenPtr pScreen = pParent->drawable.pScreen;
598
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
599
SISPtr pSiS = SISPTR(pScrn);
601
if (pSiS->VGAEngine == SIS_315_VGA) {
602
SiS310Idle /* 310/325 series */
604
SiSIdle /* 300 series and below */
609
void SISLostContext(ScreenPtr pScreen)
613
void SISSwapContextPrivate(ScreenPtr pScreen)