1/*
2 * DRI wrapper for 300 and 315 series
3 *
4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
5 *
6 * Preliminary 315/330 support by Thomas Winischhofer
7 * Portions of Mesa 4/5/6 changes by Eric Anholt
8 *
9 * Licensed under the following terms:
10 *
11 * Permission to use, copy, modify, distribute, and sell this software and its
12 * documentation for any purpose is hereby granted without fee, provided that
13 * the above copyright notice appears in all copies and that both that copyright
14 * notice and this permission notice appear in supporting documentation, and
15 * and that the name of the copyright holder not be used in advertising
16 * or publicity pertaining to distribution of the software without specific,
17 * written prior permission. The copyright holder makes no representations
18 * about the suitability of this software for any purpose.  It is provided
19 * "as is" without expressed or implied warranty.
20 *
21 * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
23 * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
25 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
26 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 * PERFORMANCE OF THIS SOFTWARE.
28 *
29 * Previously taken and modified from tdfx_dri.c, mga_dri.c
30 *
31 * Authors:	Can-Ru Yeou, SiS Inc.
32 *		Alan Hourihane, Wigan, England,
33 *		Thomas Winischhofer <thomas@winischhofer.net>
34 *		others.
35 */
36
37#ifdef HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41#include <assert.h>
42
43#include "sis.h"
44#include "sis_regs.h"
45
46#include "fb.h"
47
48#ifndef SISHAVEDRMWRITE
49# if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
50extern Bool drmSiSAgpInit(int driSubFD, int offset, int size);
51# else
52#  include "xf86drmCompat.h"
53# endif
54#endif
55
56#ifdef XORG_VERSION_CURRENT
57#define SISHAVECREATEBUSID
58#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(6,7,99,1,0)
59#ifndef XSERVER_LIBPCIACCESS
60extern char *DRICreatePCIBusID(pciVideoPtr PciInfo);
61#endif
62#endif
63#else
64# if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,4,99,9,0)
65# undef SISHAVECREATEBUSID
66# endif
67#endif
68
69#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0)
70#include "sis_common.h"
71#endif
72
73#ifndef DRIINFO_MAJOR_VERSION
74#define DRIINFO_MAJOR_VERSION 4
75#endif
76
77#ifndef DRIINFO_MINOR_VERSION
78#define DRIINFO_MINOR_VERSION 0
79#endif
80
81/* Idle function for 300 series */
82#define BR(x)   (0x8200 | (x) << 2)
83#define SiSIdle \
84  while((SIS_MMIO_IN16(pSiS->IOBase, BR(16)+2) & 0xE000) != 0xE000){}; \
85  while((SIS_MMIO_IN16(pSiS->IOBase, BR(16)+2) & 0xE000) != 0xE000){}; \
86  SIS_MMIO_IN16(pSiS->IOBase, 0x8240);
87
88/* Idle function for 315/330/340 series and XGI */
89#define Q_STATUS 0x85CC
90#define SiS315Idle \
91  { \
92  while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
93  while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
94  while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
95  while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
96  }
97
98/* The kernel's "sis" DRM module handles all chipsets */
99static char SISKernelDriverName[] = "sis";
100
101/* The client side DRI drivers are different: */
102static char SISClientDriverNameSiS300[] = "sis";	/* 300, 540, 630, 730 */
103static char SISClientDriverNameSiS315[] = "sis315";	/* All of 315/330 series */
104static char SISClientDriverNameXGI[]    = "xgi";	/* XGI V3, V5, V8 */
105
106static Bool SISCreateContext(ScreenPtr pScreen, VisualPtr visual,
107                   drm_context_t hwContext, void *pVisualConfigPriv,
108                   DRIContextType contextStore);
109static void SISDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
110                   DRIContextType contextStore);
111static void SISDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
112                   DRIContextType readContextType,
113                   void *readContextStore,
114                   DRIContextType writeContextType,
115                   void *writeContextStore);
116static void SISDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
117static void SISDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
118                   RegionPtr prgnSrc, CARD32 index);
119
120Bool
121SISDRIScreenInit(ScreenPtr pScreen)
122{
123  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
124  SISPtr pSIS = SISPTR(pScrn);
125  DRIInfoPtr pDRIInfo;
126  SISDRIPtr pSISDRI;
127#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0)
128  drmVersionPtr version;
129#endif
130
131   pSIS->cmdQueueLenPtrBackup = NULL;
132#ifdef SIS315DRI
133   pSIS->cmdQ_SharedWritePortBackup = NULL;
134#endif
135
136  /* Check that the DRI, and DRM modules have been loaded by testing
137   * for canonical symbols in each module.
138   */
139  if(!xf86LoaderCheckSymbol("drmAvailable"))        return FALSE;
140  if(!xf86LoaderCheckSymbol("DRIQueryVersion")) {
141     xf86DrvMsg(pScreen->myNum, X_ERROR,
142		"[dri] SISDRIScreenInit failed (libdri.a too old). Disabling the DRI.\n");
143     return FALSE;
144  }
145
146  /* Check the DRI version */
147  {
148     int major, minor, patch;
149     DRIQueryVersion(&major, &minor, &patch);
150     if(major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
151        xf86DrvMsg(pScreen->myNum, X_ERROR,
152		"[dri] SISDRIScreenInit failed because of a version mismatch.\n"
153		"\t[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n"
154		"\t[dri] Disabling the DRI.\n",
155		major, minor, patch, DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
156        return FALSE;
157     }
158  }
159
160  pDRIInfo = DRICreateInfoRec();
161  if(!pDRIInfo) return FALSE;
162  pSIS->pDRIInfo = pDRIInfo;
163
164  pDRIInfo->drmDriverName = SISKernelDriverName;
165  if(pSIS->VGAEngine == SIS_300_VGA) {
166     pDRIInfo->clientDriverName = SISClientDriverNameSiS300;
167  } else if(pSIS->ChipFlags & SiSCF_IsXGI) {
168     pDRIInfo->clientDriverName = SISClientDriverNameXGI;
169  } else {
170     pDRIInfo->clientDriverName = SISClientDriverNameSiS315;
171  }
172
173#ifdef SISHAVECREATEBUSID
174  if(xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
175     pDRIInfo->busIdString = DRICreatePCIBusID(pSIS->PciInfo);
176  } else {
177#endif
178     pDRIInfo->busIdString = malloc(64);
179     sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
180	     pSIS->PciBus, pSIS->PciDevice, pSIS->PciFunc);
181#ifdef SISHAVECREATEBUSID
182  }
183#endif
184
185  /* Hack to keep old DRI working -- checked for major==1 and
186   * minor==1.
187   */
188#ifdef SISNEWDRI
189  pDRIInfo->ddxDriverMajorVersion = SIS_MAJOR_VERSION;
190  pDRIInfo->ddxDriverMinorVersion = SIS_MINOR_VERSION;
191  pDRIInfo->ddxDriverPatchVersion = SIS_PATCHLEVEL;
192#else
193  pDRIInfo->ddxDriverMajorVersion = 0;
194  pDRIInfo->ddxDriverMinorVersion = 1;
195  pDRIInfo->ddxDriverPatchVersion = 0;
196#endif
197
198  /* Strictly for mapping the framebuffer,
199   * NOT for memory management!
200   * Note: For 315/330/340 series, the
201   * framebuffer area also contains
202   * the (non-AGP) command queue, located
203   * at the offset sarea->cmdQueueOffset
204   */
205#if DRIINFO_MAJOR_VERSION <= 4
206  pDRIInfo->frameBufferPhysicalAddress = pSIS->realFbAddress;
207#else
208  pDRIInfo->frameBufferPhysicalAddress = (pointer)pSIS->realFbAddress;
209#endif
210  pDRIInfo->frameBufferSize = pSIS->FbMapSize;
211
212  /* scrnOffset is being calulated in sis_vga.c */
213  pDRIInfo->frameBufferStride = pSIS->scrnOffset;
214
215  pDRIInfo->ddxDrawableTableEntry = SIS_MAX_DRAWABLES;
216
217  if(SAREA_MAX_DRAWABLES < SIS_MAX_DRAWABLES)
218     pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
219  else
220     pDRIInfo->maxDrawableTableEntry = SIS_MAX_DRAWABLES;
221
222#ifdef NOT_DONE
223  /* FIXME need to extend DRI protocol to pass this size back to client
224   * for SAREA mapping that includes a device private record
225   */
226  pDRIInfo->SAREASize =
227    ((sizeof(XF86DRISAREARec) + getpagesize() - 1) & getpagesize()); /* round to page */
228    /* ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); */ /* round to page */
229  /* + shared memory device private rec */
230#else
231  /* For now the mapping works by using a fixed size defined
232   * in the SAREA header
233   */
234  if(sizeof(XF86DRISAREARec) + sizeof(SISSAREAPriv) > SAREA_MAX) {
235     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
236		"[dri] Data does not fit in SAREA. Disabling the DRI.\n");
237     return FALSE;
238  }
239  pDRIInfo->SAREASize = SAREA_MAX;
240#endif
241
242  if(!(pSISDRI = (SISDRIPtr)calloc(sizeof(SISDRIRec), 1))) {
243     DRIDestroyInfoRec(pSIS->pDRIInfo);
244     pSIS->pDRIInfo = 0;
245     return FALSE;
246  }
247  pDRIInfo->devPrivate = pSISDRI;
248  pDRIInfo->devPrivateSize = sizeof(SISDRIRec);
249  pDRIInfo->contextSize = sizeof(SISDRIContextRec);
250
251  pDRIInfo->CreateContext = SISCreateContext;
252  pDRIInfo->DestroyContext = SISDestroyContext;
253  pDRIInfo->SwapContext = SISDRISwapContext;
254  pDRIInfo->InitBuffers = SISDRIInitBuffers;
255  pDRIInfo->MoveBuffers = SISDRIMoveBuffers;
256  pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
257
258  if(!DRIScreenInit(pScreen, pDRIInfo, &pSIS->drmSubFD)) {
259     xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed. Disabling the DRI.\n");
260     free(pDRIInfo->devPrivate);
261     pDRIInfo->devPrivate = 0;
262     DRIDestroyInfoRec(pSIS->pDRIInfo);
263     pSIS->pDRIInfo = 0;
264     pSIS->drmSubFD = -1;
265     return FALSE;
266  }
267
268#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0)
269  /* Check DRM kernel version */
270  version = drmGetVersion(pSIS->drmSubFD);
271  if(version) {
272     if((version->version_major != 1) ||
273        (version->version_minor < 0)) {
274        /* incompatible drm version */
275        xf86DrvMsg(pScreen->myNum, X_ERROR,
276		"[dri] SISDRIScreenInit failed because of a version mismatch.\n"
277		"\t[dri] sis DRM kernel module version is %d.%d.%d but version >=1.0.x\n"
278		"\t[dri] is needed. Disabling the DRI.\n",
279		version->version_major,
280		version->version_minor,
281		version->version_patchlevel);
282        drmFreeVersion(version);
283        SISDRICloseScreen(pScreen);
284        return FALSE;
285     }
286     if(version->version_minor >= 1) {
287        /* Includes support for framebuffer memory allocation without sisfb */
288        drm_sis_fb_t fb;
289        fb.offset = pSIS->DRIheapstart;
290        fb.size = pSIS->DRIheapend - pSIS->DRIheapstart;
291        drmCommandWrite(pSIS->drmSubFD, DRM_SIS_FB_INIT, &fb, sizeof(fb));
292        xf86DrvMsg(pScreen->myNum, X_INFO,
293		"[dri] Video RAM memory heap: 0x%0x to 0x%0x (%dKB)\n",
294		pSIS->DRIheapstart, pSIS->DRIheapend,
295		(int)((pSIS->DRIheapend - pSIS->DRIheapstart) >> 10));
296     }
297     drmFreeVersion(version);
298  }
299#endif
300
301  /* MMIO */
302  pSISDRI->regs.size = SISIOMAPSIZE;
303#ifndef SISISXORG6899900
304  pSISDRI->regs.map = 0;
305#endif
306  if(drmAddMap(pSIS->drmSubFD, (drm_handle_t)pSIS->IOAddress,
307		pSISDRI->regs.size, DRM_REGISTERS, 0,
308		&pSISDRI->regs.handle) < 0) {
309     SISDRICloseScreen(pScreen);
310     return FALSE;
311  }
312
313  xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] MMIO registers mapped to 0x%0x\n",
314		pSISDRI->regs.handle);
315
316  /* AGP */
317  do {
318
319    unsigned long agpmodemask = 0;
320
321    pSIS->agpWantedSize = pSIS->agpWantedPages * AGP_PAGE_SIZE;
322    pSIS->agpSize = 0;
323    pSIS->agpCmdBufSize = 0;
324    pSISDRI->AGPCmdBufSize = 0;
325
326    if(!pSIS->IsAGPCard)
327       break;
328
329    if(drmAgpAcquire(pSIS->drmSubFD) < 0) {
330       xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to acquire AGP, AGP disabled\n");
331       break;
332    }
333
334    switch(pSIS->VGAEngine) {
335#ifdef SIS315DRI
336    case SIS_315_VGA:
337       /* Default to 1X agp mode in SIS315 */
338       agpmodemask = ~0x00000002;
339       break;
340#endif
341    case SIS_300_VGA:
342       /* TODO: default value is 2x? */
343       agpmodemask = ~0x0;
344       break;
345    }
346
347    if(drmAgpEnable(pSIS->drmSubFD, drmAgpGetMode(pSIS->drmSubFD) & agpmodemask) < 0) {
348       xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to enable AGP, AGP disabled\n");
349       break;
350    }
351
352    xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] AGP enabled\n");
353
354#define AGP_DEFAULT_SIZE_MB 8
355#define AGP_DEFAULT_SIZE    (AGP_DEFAULT_SIZE_MB * 1024 * 1024)
356
357    if(drmAgpAlloc(pSIS->drmSubFD, pSIS->agpWantedSize, 0, NULL, &pSIS->agpHandle) < 0) {
358
359       xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to allocate %dMB AGP memory\n",
360		(int)(pSIS->agpWantedSize / (1024 * 1024)));
361
362       if(pSIS->agpWantedSize > AGP_DEFAULT_SIZE) {
363
364	  xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Retrying with %dMB\n", AGP_DEFAULT_SIZE_MB);
365
366	  pSIS->agpWantedSize = AGP_DEFAULT_SIZE;
367
368	  if(drmAgpAlloc(pSIS->drmSubFD, pSIS->agpWantedSize, 0, NULL, &pSIS->agpHandle) < 0) {
369	     xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to allocate %dMB AGP memory, AGP disabled\n",
370			AGP_DEFAULT_SIZE_MB);
371	     drmAgpRelease(pSIS->drmSubFD);
372	     break;
373	  }
374
375       } else {
376
377	  drmAgpRelease(pSIS->drmSubFD);
378	  break;
379
380       }
381
382    }
383
384    xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Allocated %dMB AGP memory\n",
385		(int)(pSIS->agpWantedSize / (1024 * 1024)));
386
387    if(drmAgpBind(pSIS->drmSubFD, pSIS->agpHandle, 0) < 0) {
388
389       xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to bind AGP memory\n");
390       drmAgpFree(pSIS->drmSubFD, pSIS->agpHandle);
391
392       if(pSIS->agpWantedSize > AGP_DEFAULT_SIZE) {
393
394	  xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Retrying with %dMB\n", AGP_DEFAULT_SIZE_MB);
395	  pSIS->agpWantedSize = AGP_DEFAULT_SIZE;
396
397	  if(drmAgpAlloc(pSIS->drmSubFD, pSIS->agpWantedSize, 0, NULL, &pSIS->agpHandle) < 0) {
398
399	     xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to re-allocate AGP memory, AGP disabled\n");
400	     drmAgpRelease(pSIS->drmSubFD);
401	     break;
402
403	  } else if(drmAgpBind(pSIS->drmSubFD, pSIS->agpHandle, 0) < 0) {
404
405	     xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to bind AGP memory again, AGP disabled\n");
406	     drmAgpFree(pSIS->drmSubFD, pSIS->agpHandle);
407	     drmAgpRelease(pSIS->drmSubFD);
408	     break;
409
410	  }
411
412       } else {
413
414	  drmAgpRelease(pSIS->drmSubFD);
415	  break;
416
417       }
418
419    }
420
421    xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Bound %dMB AGP memory\n",
422	       (int)(pSIS->agpWantedSize / (1024 * 1024)));
423
424    pSIS->agpSize = pSIS->agpWantedSize;
425    pSIS->agpAddr = drmAgpBase(pSIS->drmSubFD);
426    /* pSIS->agpBase = */
427
428    pSISDRI->agp.size = pSIS->agpSize;
429    if(drmAddMap(pSIS->drmSubFD, (drm_handle_t)0, pSISDRI->agp.size, DRM_AGP, 0, &pSISDRI->agp.handle) < 0) {
430       xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Failed to map public AGP area, AGP disabled\n");
431       drmAgpUnbind(pSIS->drmSubFD, pSIS->agpHandle);
432       drmAgpFree(pSIS->drmSubFD, pSIS->agpHandle);
433       drmAgpRelease(pSIS->drmSubFD);
434       pSIS->agpSize = pSISDRI->agp.size = 0;
435       break;
436    }
437
438    switch(pSIS->VGAEngine) {
439#ifdef SIS315DRI
440    case SIS_315_VGA:
441       pSIS->agpVtxBufSize = AGP_VTXBUF_SIZE; /* = 2MB */
442       pSIS->agpVtxBufAddr = pSIS->agpAddr;
443       pSIS->agpVtxBufBase = pSIS->agpVtxBufAddr - pSIS->agpAddr + pSIS->agpBase;
444       pSIS->agpVtxBufFree = 0;
445
446       pSISDRI->AGPVtxBufOffset = pSIS->agpVtxBufAddr - pSIS->agpAddr;
447       pSISDRI->AGPVtxBufSize = pSIS->agpVtxBufSize;
448
449#ifndef SISHAVEDRMWRITE
450       drmSiSAgpInit(pSIS->drmSubFD, AGP_VTXBUF_SIZE, (pSIS->agpSize - AGP_VTXBUF_SIZE));
451#else
452       {
453	   drm_sis_agp_t agp;
454
455	   agp.offset = AGP_VTXBUF_SIZE;
456	   agp.size = pSIS->agpSize - AGP_VTXBUF_SIZE;
457	   drmCommandWrite(pSIS->drmSubFD, DRM_SIS_AGP_INIT, &agp, sizeof(agp));
458       }
459
460#endif
461       break;
462#endif
463    case SIS_300_VGA:
464       pSIS->agpCmdBufSize = AGP_CMDBUF_SIZE;
465       pSIS->agpCmdBufAddr = pSIS->agpAddr;
466       pSIS->agpCmdBufBase = pSIS->agpCmdBufAddr - pSIS->agpAddr + pSIS->agpBase;
467       pSIS->agpCmdBufFree = 0;
468
469       pSISDRI->AGPCmdBufOffset = pSIS->agpCmdBufAddr - pSIS->agpAddr;
470       pSISDRI->AGPCmdBufSize = pSIS->agpCmdBufSize;
471
472#ifndef SISHAVEDRMWRITE
473       drmSiSAgpInit(pSIS->drmSubFD, AGP_CMDBUF_SIZE, (pSIS->agpSize - AGP_CMDBUF_SIZE));
474#else
475       {
476	   drm_sis_agp_t agp;
477
478	   agp.offset = AGP_CMDBUF_SIZE;
479	   agp.size = pSIS->agpSize - AGP_CMDBUF_SIZE;
480	   drmCommandWrite(pSIS->drmSubFD, DRM_SIS_AGP_INIT, &agp, sizeof(agp));
481       }
482#endif
483       break;
484    }
485  } while(0);
486
487  /* Eventually grab and enable IRQ */
488  pSIS->irqEnabled = FALSE;
489  pSIS->irq = drmGetInterruptFromBusID(pSIS->drmSubFD,
490	   pSIS->PciBus, pSIS->PciDevice, pSIS->PciFunc);
491
492  if(pSIS->irq < 0) {
493     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
494	  "[drm] No valid IRQ number for device %d:%d:%d (code %d)\n",
495	   pSIS->PciBus, pSIS->PciDevice, pSIS->PciFunc,
496	   pSIS->irq);
497  } else if((drmCtlInstHandler(pSIS->drmSubFD, pSIS->irq)) != 0) {
498     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
499	  "[drm] Failed to add IRQ %d handler\n",
500	   pSIS->irq);
501  } else {
502     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
503	  "[drm] Successfully installed handler for IRQ %d\n",
504	   pSIS->irq);
505     pSIS->irqEnabled = TRUE;
506  }
507
508  pSISDRI->irqEnabled = pSIS->irqEnabled;
509
510  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n" );
511
512  return TRUE;
513}
514
515Bool
516SISDRIFinishScreenInit(ScreenPtr pScreen)
517{
518  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
519  SISPtr pSiS = SISPTR(pScrn);
520  SISDRIPtr pSISDRI;
521
522  pSiS->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
523  /* pSiS->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */
524
525  pSISDRI = (SISDRIPtr)pSiS->pDRIInfo->devPrivate;
526  pSISDRI->deviceID = pSiS->Chipset;
527#ifdef SIS315DRI
528  pSISDRI->deviceRev= pSiS->ChipRev;
529#endif
530  pSISDRI->width    = pScrn->virtualX;
531  pSISDRI->height   = pScrn->virtualY;
532  pSISDRI->mem      = pScrn->videoRam * 1024;
533  pSISDRI->bytesPerPixel = (pScrn->bitsPerPixel+7) / 8;
534
535  /* TODO */
536  pSISDRI->scrnX    = pSISDRI->width;
537  pSISDRI->scrnY    = pSISDRI->height;
538
539  /* Offset of the front buffer (relative from beginning
540   * of video RAM). This is usually 0, but eventually not
541   * if running on a SiS76x with LFB and UMA memory.
542   * THE DRI DRIVER DOES NOT USE THIS YET (MESA 6.2.1)
543   */
544  pSISDRI->fbOffset      = pSiS->FbBaseOffset;
545
546  /* These are unused. Offsets are set up by the DRI */
547  pSISDRI->textureOffset = 0;
548  pSISDRI->textureSize   = 0;
549  pSISDRI->backOffset    = 0;
550  pSISDRI->depthOffset   = 0;
551
552  /* set SAREA value */
553  {
554    SISSAREAPriv *saPriv;
555
556    saPriv = (SISSAREAPriv *)DRIGetSAREAPrivate(pScreen);
557
558    assert(saPriv);
559
560    saPriv->CtxOwner = -1;
561
562    switch(pSiS->VGAEngine) {
563
564#ifdef SIS315DRI
565    case SIS_315_VGA:
566       saPriv->AGPVtxBufNext = 0;
567
568       saPriv->QueueLength = pSiS->cmdQueueSize;  /* Total (not: current) size, in bytes! */
569
570       /* Copy current queue position to sarea */
571       saPriv->sharedWPoffset = *(pSiS->cmdQ_SharedWritePort);
572       /* Delegate our shared offset to current queue position */
573       pSiS->cmdQ_SharedWritePortBackup = pSiS->cmdQ_SharedWritePort;
574       pSiS->cmdQ_SharedWritePort = &(saPriv->sharedWPoffset);
575
576       saPriv->cmdQueueOffset = pSiS->cmdQueueOffset;
577
578       /* TODO: Reset frame control */
579
580       break;
581#endif
582
583    case SIS_300_VGA:
584       saPriv->AGPCmdBufNext = 0;
585
586       /* Delegate our shared pointer to current queue length */
587       saPriv->QueueLength = *(pSiS->cmdQueueLenPtr);
588       pSiS->cmdQueueLenPtrBackup = pSiS->cmdQueueLenPtr;
589       pSiS->cmdQueueLenPtr = &(saPriv->QueueLength);
590
591       /* frame control */
592       saPriv->FrameCount = 0;
593       *(CARD32 *)(pSiS->IOBase+0x8a2c) = 0;
594       SiSIdle
595       break;
596    }
597  }
598
599  return DRIFinishScreenInit(pScreen);
600}
601
602void
603SISDRICloseScreen(ScreenPtr pScreen)
604{
605  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
606  SISPtr pSIS = SISPTR(pScrn);
607
608  switch(pSIS->VGAEngine) {
609#ifdef SIS315DRI
610  case SIS_315_VGA:
611     if(pSIS->cmdQ_SharedWritePortBackup) {
612	/* Re-instate our shared offset to current queue position */
613	pSIS->cmdQ_SharedWritePort_2D = *(pSIS->cmdQ_SharedWritePort);
614	pSIS->cmdQ_SharedWritePort = pSIS->cmdQ_SharedWritePortBackup;
615	pSIS->cmdQ_SharedWritePortBackup = 0;
616     }
617     break;
618#endif
619  case SIS_300_VGA:
620     if(pSIS->cmdQueueLenPtrBackup) {
621	/* Re-instate our shared pointer to current queue length */
622	pSIS->cmdQueueLenPtr = pSIS->cmdQueueLenPtrBackup;
623	*(pSIS->cmdQueueLenPtr) = 0;
624     }
625     break;
626  }
627
628  if(pSIS->irqEnabled) {
629     xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Removing IRQ handler\n");
630     drmCtlUninstHandler(pSIS->drmSubFD);
631     pSIS->irqEnabled = FALSE;
632     pSIS->irq = 0;
633  }
634
635  if(pSIS->agpSize){
636     xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Freeing AGP memory\n");
637     drmAgpUnbind(pSIS->drmSubFD, pSIS->agpHandle);
638     drmAgpFree(pSIS->drmSubFD, pSIS->agpHandle);
639     xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Releasing AGP module\n");
640     drmAgpRelease(pSIS->drmSubFD);
641     pSIS->agpSize = 0;
642  }
643
644  DRICloseScreen(pScreen);
645
646  if(pSIS->pDRIInfo) {
647     if(pSIS->pDRIInfo->devPrivate) {
648	free(pSIS->pDRIInfo->devPrivate);
649	pSIS->pDRIInfo->devPrivate = NULL;
650     }
651     DRIDestroyInfoRec(pSIS->pDRIInfo);
652     pSIS->pDRIInfo = NULL;
653  }
654
655}
656
657/* TODO: xserver receives driver's swapping event and do something
658 *       according the data initialized in this function
659 */
660static Bool
661SISCreateContext(ScreenPtr pScreen, VisualPtr visual,
662          drm_context_t hwContext, void *pVisualConfigPriv,
663          DRIContextType contextStore)
664{
665  return TRUE;
666}
667
668static void
669SISDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
670           DRIContextType contextStore)
671{
672}
673
674static void
675SISDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
676           DRIContextType oldContextType, void *oldContext,
677           DRIContextType newContextType, void *newContext)
678{
679  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
680  SISPtr pSiS = SISPTR(pScrn);
681
682#if 0
683  if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) &&
684      (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */
685    SISSwapContextPrivate(pScreen);
686  }
687  if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) &&
688      (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */
689    SISLostContext(pScreen);
690  }
691#endif
692
693  /* mEndPrimitive */
694  /*
695   * TODO: do this only if X-Server get lock. If kernel supports delayed
696   * signal, needless to do this
697   */
698  switch(pSiS->VGAEngine) {
699#ifdef SIS315DRI
700  case SIS_315_VGA:
701     /* ? */
702     break;
703#endif
704  case SIS_300_VGA:
705     *((unsigned char *)pSiS->IOBase + 0x8B50) = 0xff;
706     *(CARD32 *)(pSiS->IOBase + 0x8B60) = 0xffffffff;
707     break;
708  }
709}
710
711static void
712SISDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
713{
714  ScreenPtr pScreen = pWin->drawable.pScreen;
715  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
716  SISPtr pSiS = SISPTR(pScrn);
717
718  switch(pSiS->VGAEngine) {
719#ifdef SIS315DRI
720  case SIS_315_VGA:
721     SiS315Idle
722     break;
723#endif
724  case SIS_300_VGA:
725     SiSIdle
726     break;
727  }
728}
729
730static void
731SISDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
732           RegionPtr prgnSrc, CARD32 index)
733{
734  ScreenPtr pScreen = pParent->drawable.pScreen;
735  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
736  SISPtr pSiS = SISPTR(pScrn);
737
738  switch(pSiS->VGAEngine) {
739#ifdef SIS315DRI
740  case SIS_315_VGA:
741     SiS315Idle
742     break;
743#endif
744  case SIS_300_VGA:
745     SiSIdle
746     break;
747  }
748}
749
750#if 0
751void SISLostContext(ScreenPtr pScreen)
752{
753}
754
755void SISSwapContextPrivate(ScreenPtr pScreen)
756{
757}
758#endif
759
760
761
762