1/* modified from tdfx_dri.c, mga_dri.c */
2
3/*
4 * DRI wrapper for 300 and 315 series
5 *
6 * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
7 *
8 * Preliminary 315/330 support by Thomas Winischhofer
9 * Portions of Mesa 4/5 changes by Eric Anholt
10 *
11 * Licensed under the following terms:
12 *
13 * Permission to use, copy, modify, distribute, and sell this software and its
14 * documentation for any purpose is hereby granted without fee, provided that
15 * the above copyright notice appears in all copies and that both that copyright
16 * notice and this permission notice appear in supporting documentation, and
17 * and that the name of the copyright holder not be used in advertising
18 * or publicity pertaining to distribution of the software without specific,
19 * written prior permission. The copyright holder makes no representations
20 * about the suitability of this software for any purpose.  It is provided
21 * "as is" without expressed or implied warranty.
22 *
23 * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
25 * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
27 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
28 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29 * PERFORMANCE OF THIS SOFTWARE.
30 *
31 * Previously taken and modified from tdfx_dri.c, mga_dri.c
32 *
33 * Authors:	Can-Ru Yeou, SiS Inc.
34 *		Alan Hourihane, Wigan, England,
35 *		Thomas Winischhofer <thomas@winischhofer.net>
36 *		others.
37 */
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42/* Jong 09/27/2007; added for PACKAGE_VERSION_MAJOR,... */
43#define  PACKAGE_VERSION_MAJOR   1
44#define  PACKAGE_VERSION_MINOR   1
45#define  PACKAGE_VERSION_PATCHLEVEL   0
46
47#include "xf86.h"
48#include "xf86_OSproc.h"
49#include "xf86Priv.h"
50
51#include "xf86PciInfo.h"
52#include "xf86Pci.h"
53#include "fb.h"
54#define PSZ 8
55/* #include "cfb.h" */
56#undef PSZ
57/* #include "cfb16.h" */
58/* #include "cfb32.h" */
59
60#include "miline.h"
61
62#include "GL/glxtokens.h"
63
64#include "xgi.h"
65#include "xgi_dri.h"
66
67#include "xgi_accel.h"
68#include "xgi_common.h"
69#include "drm.h"
70
71extern void GlxSetVisualConfigs(
72    int nconfigs,
73    __GLXvisualConfig *configs,
74    void **configprivs
75);
76
77#define PCIE_BUS_TYPE	2
78#define AGP_BUS_TYPE	1
79#define PCI_BUS_TYPE	0
80
81#define AGP_PAGE_SIZE 4096     /* Texture memory 8M  */
82/*#define AGP_PAGE_SIZE 5120*/ /* Texture memory 10M */
83#define AGP_PAGES 2048
84#define AGP_SIZE (AGP_PAGE_SIZE * AGP_PAGES)
85#define AGP_VTXBUF_PAGES 512
86#define AGP_VTXBUF_SIZE (AGP_PAGE_SIZE * AGP_VTXBUF_PAGES)
87
88/**
89 * Base name of kernel DRM driver.
90 *
91 * Support for XG40 chips is included in the SiS DRM because the DMA and
92 * interrupt handling for the chips is identical.
93 */
94static const char XGIKernelDriverName[] = "sis";
95
96static const char XGIClientDriverName[] = "xgi";
97
98static Bool XGIInitVisualConfigs(ScreenPtr pScreen);
99static Bool XGICreateContext(ScreenPtr pScreen, VisualPtr visual,
100			      drm_context_t hwContext, void *pVisualConfigPriv,
101			      DRIContextType contextStore);
102static void XGIDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
103			       DRIContextType contextStore);
104static void XGIDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
105			       DRIContextType readContextType,
106			       void *readContextStore,
107			       DRIContextType writeContextType,
108			       void *writeContextStore);
109static void XGIDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
110static void XGIDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
111			       RegionPtr prgnSrc, CARD32 index);
112
113void xgiLostContext(ScreenPtr pScreen);
114
115ULONG IsXGIAGPCard(ScreenPtr pScreen);
116ULONG CheckAGPSlot(ScreenPtr pScreen, ULONG uNextLink);
117
118static Bool
119XGIInitVisualConfigs(ScreenPtr pScreen)
120{
121  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
122  XGIPtr pXGI = XGIPTR(pScrn);
123  int numConfigs = 0;
124  __GLXvisualConfig *pConfigs = 0;
125  XGIConfigPrivPtr pXGIConfigs = 0;
126  XGIConfigPrivPtr *pXGIConfigPtrs = 0;
127  int i, db, z_stencil, accum;
128  Bool useZ16 = FALSE;
129
130  if(getenv("XGI_FORCE_Z16")){
131    useZ16 = TRUE;
132  }
133
134  switch (pScrn->bitsPerPixel) {
135  case 8:
136  case 24:
137    break;
138  case 16:
139  case 32:
140    numConfigs = (useZ16)?8:16;
141
142    if (!(pConfigs = (__GLXvisualConfig*)xnfcalloc(sizeof(__GLXvisualConfig),
143						   numConfigs))) {
144      return FALSE;
145    }
146    if (!(pXGIConfigs = (XGIConfigPrivPtr)xnfcalloc(sizeof(XGIConfigPrivRec),
147						    numConfigs))) {
148      xfree(pConfigs);
149      return FALSE;
150    }
151    if (!(pXGIConfigPtrs = (XGIConfigPrivPtr*)xnfcalloc(sizeof(XGIConfigPrivPtr),
152							  numConfigs))) {
153      xfree(pConfigs);
154      xfree(pXGIConfigs);
155      return FALSE;
156    }
157    for (i=0; i<numConfigs; i++)
158      pXGIConfigPtrs[i] = &pXGIConfigs[i];
159
160    i = 0;
161    for (accum = 0; accum <= 1; accum++) {
162      for (z_stencil=0; z_stencil<(useZ16?2:4); z_stencil++) {
163        for (db = 0; db <= 1; db++) {
164          pConfigs[i].vid = -1;
165          pConfigs[i].class = -1;
166          pConfigs[i].rgba = TRUE;
167          pConfigs[i].redSize = -1;
168          pConfigs[i].greenSize = -1;
169          pConfigs[i].blueSize = -1;
170          pConfigs[i].redMask = -1;
171          pConfigs[i].greenMask = -1;
172          pConfigs[i].blueMask = -1;
173          pConfigs[i].alphaMask = 0;
174          if (accum) {
175            pConfigs[i].accumRedSize = 16;
176            pConfigs[i].accumGreenSize = 16;
177            pConfigs[i].accumBlueSize = 16;
178            pConfigs[i].accumAlphaSize = 16;
179          } else {
180            pConfigs[i].accumRedSize = 0;
181            pConfigs[i].accumGreenSize = 0;
182            pConfigs[i].accumBlueSize = 0;
183            pConfigs[i].accumAlphaSize = 0;
184          }
185          if (db)
186            pConfigs[i].doubleBuffer = TRUE;
187          else
188            pConfigs[i].doubleBuffer = FALSE;
189          pConfigs[i].stereo = FALSE;
190          pConfigs[i].bufferSize = -1;
191          switch (z_stencil){
192            case 0:
193              pConfigs[i].depthSize = 0;
194              pConfigs[i].stencilSize = 0;
195              break;
196            case 1:
197              pConfigs[i].depthSize = 16;
198              pConfigs[i].stencilSize = 0;
199              break;
200            case 2:
201              pConfigs[i].depthSize = 32;
202              pConfigs[i].stencilSize = 0;
203              break;
204            case 3:
205              pConfigs[i].depthSize = 24;
206              pConfigs[i].stencilSize = 8;
207              break;
208          }
209          pConfigs[i].auxBuffers = 0;
210          pConfigs[i].level = 0;
211          pConfigs[i].visualRating = GLX_NONE_EXT;
212          pConfigs[i].transparentPixel = 0;
213          pConfigs[i].transparentRed = 0;
214          pConfigs[i].transparentGreen = 0;
215          pConfigs[i].transparentBlue = 0;
216          pConfigs[i].transparentAlpha = 0;
217          pConfigs[i].transparentIndex = 0;
218          i++;
219        }
220      }
221    }
222    if (i != numConfigs) {
223      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
224                 "[drm] Incorrect initialization of visuals\n");
225      return FALSE;
226    }
227    break;
228  }
229
230  pXGI->numVisualConfigs = numConfigs;
231  pXGI->pVisualConfigs = pConfigs;
232  pXGI->pVisualConfigsPriv = pXGIConfigs;
233  GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pXGIConfigPtrs);
234
235  return TRUE;
236}
237
238Bool XGIDRIScreenInit(ScreenPtr pScreen)
239{
240#ifndef linux
241  return FALSE;
242#else /* linux */
243
244  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
245  XGIPtr pXGI = XGIPTR(pScrn);
246  DRIInfoPtr pDRIInfo;
247  XGIDRIPtr pXGIDRI;
248    drm_xgi_fb_t  fb;
249    int major, minor, patch;
250    drmVersionPtr drm_ver;
251
252
253   /* Check that the GLX, DRI, and DRM modules have been loaded by testing
254    * for canonical symbols in each module. */
255   if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE;
256   if (!xf86LoaderCheckSymbol("DRIScreenInit"))       return FALSE;
257   if (!xf86LoaderCheckSymbol("drmAvailable"))        return FALSE;
258   if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
259      xf86DrvMsg(pScreen->myNum, X_ERROR,
260                 "XGIDRIScreenInit failed (libdri.a too old)\n");
261      return FALSE;
262   }
263
264    /* Make sure the server's DRI extension version matches the version the
265     * driver was built against.
266     */
267    DRIQueryVersion(&major, &minor, &patch);
268    if ((major != DRIINFO_MAJOR_VERSION) || (minor < DRIINFO_MINOR_VERSION)) {
269        xf86DrvMsg(pScreen->myNum, X_ERROR,
270                   "[drm] XGIDRIScreenInit failed (DRI version = %d.%d.%d, "
271                   "expected %d.%d.x). Disabling DRI.\n",
272                   major, minor, patch,
273                   DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
274        return FALSE;
275    }
276
277    pDRIInfo = DRICreateInfoRec();
278    if (!pDRIInfo) {
279        return FALSE;
280    }
281
282    pXGI->pDRIInfo = pDRIInfo;
283    pDRIInfo->drmDriverName = XGIKernelDriverName;
284    pDRIInfo->clientDriverName = XGIClientDriverName;
285    pDRIInfo->busIdString = DRICreatePCIBusID(pXGI->PciInfo);
286    pDRIInfo->ddxDriverMajorVersion = PACKAGE_VERSION_MAJOR;
287    pDRIInfo->ddxDriverMinorVersion = PACKAGE_VERSION_MINOR;
288    pDRIInfo->ddxDriverPatchVersion = PACKAGE_VERSION_PATCHLEVEL;
289    pDRIInfo->frameBufferPhysicalAddress = pXGI->FbAddress;
290    pDRIInfo->frameBufferSize = pXGI->FbMapSize;
291
292  /* ?? */
293  pDRIInfo->frameBufferStride = pXGI->scrnOffset;
294  pDRIInfo->ddxDrawableTableEntry = XGI_MAX_DRAWABLES;
295
296  if (SAREA_MAX_DRAWABLES < XGI_MAX_DRAWABLES)
297    pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
298  else
299    pDRIInfo->maxDrawableTableEntry = XGI_MAX_DRAWABLES;
300
301#ifdef NOT_DONE
302  /* FIXME need to extend DRI protocol to pass this size back to client
303   * for SAREA mapping that includes a device private record
304   */
305  pDRIInfo->SAREASize =
306    ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */
307  /* + shared memory device private rec */
308#else
309  /* For now the mapping works by using a fixed size defined
310   * in the SAREA header
311   */
312  if (sizeof(XF86DRISAREARec)+sizeof(XGISAREAPriv)>SAREA_MAX) {
313/* ErrorF("Data does not fit in SAREA\n"); */
314    return FALSE;
315  }
316  pDRIInfo->SAREASize = SAREA_MAX;
317#endif
318
319  if (!(pXGIDRI = (XGIDRIPtr)xnfcalloc(sizeof(XGIDRIRec),1))) {
320    DRIDestroyInfoRec(pXGI->pDRIInfo);
321    pXGI->pDRIInfo=0;
322    return FALSE;
323  }
324  pDRIInfo->devPrivate = pXGIDRI;
325  pDRIInfo->devPrivateSize = sizeof(XGIDRIRec);
326  pDRIInfo->contextSize = sizeof(XGIDRIContextRec);
327
328  pDRIInfo->CreateContext = XGICreateContext;
329  pDRIInfo->DestroyContext = XGIDestroyContext;
330  pDRIInfo->SwapContext = XGIDRISwapContext;
331  pDRIInfo->InitBuffers = XGIDRIInitBuffers;
332  pDRIInfo->MoveBuffers = XGIDRIMoveBuffers;
333  pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
334
335  if (!DRIScreenInit(pScreen, pDRIInfo, &pXGI->drmSubFD)) {
336    xfree(pDRIInfo->devPrivate);
337    pDRIInfo->devPrivate=0;
338    DRIDestroyInfoRec(pXGI->pDRIInfo);
339    pXGI->pDRIInfo=0;
340    pXGI->drmSubFD = -1;
341    return FALSE;
342  }
343
344    drm_ver = drmGetVersion(pXGI->drmSubFD);
345    if (drm_ver != NULL) {
346        major = drm_ver->version_major;
347        minor = drm_ver->version_minor;
348        patch = drm_ver->version_patchlevel;
349
350        drmFreeVersion(drm_ver);
351        drm_ver = NULL;
352    }
353    else {
354        major = 0;
355        minor = 0;
356        patch = 0;
357    }
358
359    if ((major != 1) || (minor < 3)) {
360        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
361                   "[drm] Incorrect kernel module version.  Expected 1.3.x, got %d.%d.%d\n",
362                   major, minor, patch);
363
364        XGIDRICloseScreen(pScreen);
365        return FALSE;
366    }
367    else {
368        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
369                   "[drm] Kernel module version is %d.%d.%d\n",
370                   major, minor, patch);
371    }
372
373  pXGIDRI->regs.size = XGIIOMAPSIZE;
374  pXGIDRI->regs.map = 0;
375  if (drmAddMap(pXGI->drmSubFD, (drm_handle_t)pXGI->IOAddress,
376		pXGIDRI->regs.size, DRM_REGISTERS, 0,
377		&pXGIDRI->regs.handle)<0)
378  {
379    XGIDRICloseScreen(pScreen);
380    return FALSE;
381  }
382
383  xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08lx\n",
384	     (unsigned long) pXGIDRI->regs.handle);
385
386    /* Initialize the framebuffer memory manager.
387     */
388    fb.offset = pXGI->DRIheapstart;
389    fb.size = pXGI->DRIheapend - pXGI->DRIheapstart;
390    drmCommandWrite(pXGI->drmSubFD, DRM_XGI_FB_INIT, &fb, sizeof(fb));
391    xf86DrvMsg(pScreen->myNum, X_INFO,
392               "[dri] Video RAM memory heap: 0x%0x to 0x%0x (%dKB)\n",
393               pXGI->DRIheapstart, pXGI->DRIheapend,
394               (int)((pXGI->DRIheapend - pXGI->DRIheapstart) >> 10));
395
396
397  /* AGP */
398  do{
399    pXGI->agpSize = 0;
400    pXGI->agpVtxBufSize = 0;
401    pXGIDRI->AGPVtxBufSize = 0;
402
403    /* jill note: IF not AGP, diable AGP memory allocate */
404    if (AGP_BUS_TYPE != IsXGIAGPCard(pScreen))
405	    break;
406
407    if (drmAgpAcquire(pXGI->drmSubFD) < 0) {
408      xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAcquire failed\n");
409      break;
410    }
411
412    pXGI->agpSize = drmAgpSize(pXGI->drmSubFD);
413    if(pXGI->agpSize==0)
414    {
415      xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpSize =0\n");
416      break;
417    }
418
419    /* TODO: default value is 2x? */
420/* if (drmAgpEnable(pXGI->drmSubFD, drmAgpGetMode(pXGI->drmSubFD)&~0x0) < 0) {
421*/
422    /* Default to 1X agp mode */
423    if (drmAgpEnable(pXGI->drmSubFD, drmAgpGetMode(pXGI->drmSubFD)&~0x00000002) < 0) {
424      xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpEnable failed\n");
425      break;
426    }
427/* ErrorF("[drm] drmAgpEnabled succeeded\n"); */
428
429    if (drmAgpAlloc(pXGI->drmSubFD, pXGI->agpSize, 0, NULL, &pXGI->agpHandle) < 0) {
430      xf86DrvMsg(pScreen->myNum, X_ERROR,
431                 "[drm] drmAgpAlloc failed\n");
432      pXGI->agpSize = 0;
433      drmAgpRelease(pXGI->drmSubFD);
434      break;
435    }
436
437    /* Bind agp-gart table                       */
438    /* fill the phys addr. into gart table       */
439    /*********************************************/
440    if (drmAgpBind(pXGI->drmSubFD, pXGI->agpHandle, 0) < 0) {
441      xf86DrvMsg(pScreen->myNum, X_ERROR,
442                 "[drm] drmAgpBind failed\n");
443      drmAgpFree(pXGI->drmSubFD, pXGI->agpHandle);
444      drmAgpRelease(pXGI->drmSubFD);
445
446      break;
447    }
448
449/*    pXGI->agpSize = AGP_SIZE; */
450    pXGI->agpAddr = drmAgpBase(pXGI->drmSubFD);
451    /* pXGI->agpBase = */ /* Xserver connot access VtxBuf, bc. not mem-map */
452
453    /* any client can access this VtxBuf AGP area */
454    /* by mem-map pXGIDRI->agp.handle             */
455    /**********************************************/
456    pXGIDRI->agp.size = pXGI->agpSize;
457    if (drmAddMap(pXGI->drmSubFD, (drm_handle_t)0,
458                 pXGIDRI->agp.size, DRM_AGP, 0,
459                 &pXGIDRI->agp.handle) < 0) {
460      xf86DrvMsg(pScreen->myNum, X_ERROR,
461                 "[drm] Failed to map public agp area\n");
462      pXGIDRI->agp.size = 0;
463      break;
464    }
465
466#if 1 /* chiawen : remove this to 3d driver */
467    pXGI->agpVtxBufSize = AGP_VTXBUF_SIZE; /* 2MB */
468    pXGI->agpVtxBufAddr = pXGI->agpAddr;
469    pXGI->agpVtxBufBase = pXGI->agpVtxBufAddr - pXGI->agpAddr +
470                          pXGI->agpBase;
471    pXGI->agpVtxBufFree = 0;
472
473    pXGIDRI->AGPVtxBufOffset = pXGI->agpVtxBufAddr - pXGI->agpAddr;
474    pXGIDRI->AGPVtxBufSize = pXGI->agpVtxBufSize;
475
476    /* this AGP area is used for texture */
477    /*               is managed by drm   */
478    /*************************************/
479    {
480      drm_xgi_agp_t agp;
481
482      agp.offset = 0; /* AGP_VTXBUF_SIZE; */
483      agp.size = pXGI->agpSize; /* AGP_SIZE - AGP_VTXBUF_SIZE; */
484#ifdef DRM_IOCTL_XGI_AGP_INIT
485      ioctl(pXGI->drmSubFD, DRM_IOCTL_XGI_AGP_INIT, &agp);
486#endif
487#endif
488    }
489  }
490  while(0);
491
492  /* enable IRQ */
493  pXGI->irq = drmGetInterruptFromBusID(pXGI->drmSubFD,
494#ifdef XSERVER_LIBPCIACCESS
495				       ((pXGI->PciInfo->domain << 8)
496					| pXGI->PciInfo->bus),
497				       pXGI->PciInfo->dev,
498				       pXGI->PciInfo->func
499#else
500	       ((pciConfigPtr)pXGI->PciInfo->thisCard)->busnum,
501	       ((pciConfigPtr)pXGI->PciInfo->thisCard)->devnum,
502	       ((pciConfigPtr)pXGI->PciInfo->thisCard)->funcnum
503#endif
504				       );
505
506  if((drmCtlInstHandler(pXGI->drmSubFD, pXGI->irq)) != 0)
507    {
508      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
509		 "[drm] failure adding irq %d handler, stereo disabled\n",
510		 pXGI->irq);
511      pXGI->irqEnabled = FALSE;
512    }
513  else
514    {
515      pXGI->irqEnabled = TRUE;
516    }
517
518  pXGIDRI->irqEnabled = pXGI->irqEnabled;
519
520  if (!(XGIInitVisualConfigs(pScreen))) {
521    XGIDRICloseScreen(pScreen);
522    return FALSE;
523  }
524  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "visual configs initialized\n" );
525
526  return TRUE;
527#endif /* linux */
528}
529
530void
531XGIDRICloseScreen(ScreenPtr pScreen)
532{
533  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
534  XGIPtr pXGI = XGIPTR(pScrn);
535
536  DRICloseScreen(pScreen);
537
538  if (pXGI->pDRIInfo) {
539    if (pXGI->pDRIInfo->devPrivate) {
540      xfree(pXGI->pDRIInfo->devPrivate);
541      pXGI->pDRIInfo->devPrivate=0;
542    }
543    DRIDestroyInfoRec(pXGI->pDRIInfo);
544    pXGI->pDRIInfo=0;
545  }
546  if (pXGI->pVisualConfigs) xfree(pXGI->pVisualConfigs);
547  if (pXGI->pVisualConfigsPriv) xfree(pXGI->pVisualConfigsPriv);
548
549  if(pXGI->agpSize){
550/* ErrorF("Freeing agp memory\n"); */
551     drmAgpFree(pXGI->drmSubFD, pXGI->agpHandle);
552/* ErrorF("releasing agp module\n"); */
553     drmAgpRelease(pXGI->drmSubFD);
554  }
555}
556
557/* TODO: xserver receives driver's swapping event and do something
558 *       according the data initialized in this function
559 */
560static Bool
561XGICreateContext(ScreenPtr pScreen, VisualPtr visual,
562		  drm_context_t hwContext, void *pVisualConfigPriv,
563		  DRIContextType contextStore)
564{
565  return TRUE;
566}
567
568static void
569XGIDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
570		   DRIContextType contextStore)
571{
572}
573
574Bool
575XGIDRIFinishScreenInit(ScreenPtr pScreen)
576{
577  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
578  XGIPtr pXGI = XGIPTR(pScrn);
579/*  XGIPtr pXGI = XGIPTR(pScrn); */
580  XGIDRIPtr pXGIDRI;
581
582  /*pXGI->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;*/
583  pXGI->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP;
584
585  pXGIDRI=(XGIDRIPtr)pXGI->pDRIInfo->devPrivate;
586  pXGIDRI->deviceID=pXGI->Chipset;
587  pXGIDRI->revisionID=pXGI->ChipRev;
588  pXGIDRI->width=pScrn->virtualX;
589  pXGIDRI->height=pScrn->virtualY;
590  pXGIDRI->mem=pScrn->videoRam*1024;
591  pXGIDRI->bytesPerPixel= (pScrn->bitsPerPixel+7) / 8;
592  /* TODO */
593  pXGIDRI->scrnX=pXGIDRI->width;
594  pXGIDRI->scrnY=pXGIDRI->height;
595
596/*
597  pXGIDRI->textureOffset=pXGI->texOffset;
598  pXGIDRI->textureSize=pXGI->texSize;
599  pXGIDRI->fbOffset=pXGI->fbOffset;
600  pXGIDRI->backOffset=pXGI->backOffset;
601  pXGIDRI->depthOffset=pXGI->depthOffset;
602*/
603
604  /* set SAREA value */
605  {
606    XGISAREAPriv *saPriv;
607
608    saPriv=(XGISAREAPriv*)DRIGetSAREAPrivate(pScreen);
609    assert(saPriv);
610
611    saPriv->CtxOwner = -1;
612    saPriv->QueueLength = 0;
613    pXGI->cmdQueueLenPtr = &(saPriv->QueueLength);
614    saPriv->AGPVtxBufNext = 0;
615
616
617    saPriv->shareWPoffset = pXGI->cmdQueue_shareWP_only2D;
618    pXGI->pCQ_shareWritePort = &(saPriv->shareWPoffset);
619
620
621
622    Volari_Idle(pXGI);
623  }
624
625  return DRIFinishScreenInit(pScreen);
626}
627
628static void
629XGIDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
630		   DRIContextType oldContextType, void *oldContext,
631		   DRIContextType newContextType, void *newContext)
632{
633  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
634  XGIPtr pXGI = XGIPTR(pScrn);
635
636  /* mEndPrimitive */
637  /*
638   * TODO: do this only if X-Server get lock. If kernel supports delayed
639   * signal, needless to do this
640   */
641  /*
642  *(pXGI->IOBase + 0X8B50) = 0xff;
643  *(unsigned int *)(pXGI->IOBase + 0x8B60) = -1;
644  */
645
646  Volari_Idle(pXGI);
647}
648
649static void
650XGIDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
651{
652  ScreenPtr pScreen = pWin->drawable.pScreen;
653  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
654  XGIPtr pXGI = XGIPTR(pScrn);
655
656  Volari_Idle(pXGI);
657}
658
659static void
660XGIDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
661		   RegionPtr prgnSrc, CARD32 index)
662{
663  ScreenPtr pScreen = pParent->drawable.pScreen;
664  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
665  XGIPtr pXGI = XGIPTR(pScrn);
666
667  Volari_Idle(pXGI);
668}
669
670#ifndef XSERVER_LIBPCIACCESS
671/**
672 * Use this function to check AGP slot
673 */
674ULONG CheckAGPSlot(ScreenPtr pScreen, ULONG uNextLink)
675{
676	ULONG uBuffer = 0, uLink = 0, uValue = 0 ;
677	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
678	XGIPtr pXGI = XGIPTR(pScrn);
679
680	uBuffer = pciReadLong(pXGI->PciTag, uNextLink);
681	uLink = (uBuffer & 0xff00) >> 8;
682	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%s]uBuffer=0x%lx uNextLink=0x%lx, uLink=0x%lx\n", __FUNCTION__, uBuffer, uNextLink, uLink);
683
684	if ((uBuffer & 0xff) != 0x02)
685	{
686		if(uLink)
687			uValue = CheckAGPSlot(pScreen, uLink);
688		else
689			uValue = PCI_BUS_TYPE;
690	}
691	else
692		uValue = AGP_BUS_TYPE;
693
694    return uValue;
695}
696#endif
697
698/**
699 * Use this function to check if the current card is AGP or PCI.
700 */
701ULONG IsXGIAGPCard(ScreenPtr pScreen)
702{
703    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
704    XGIPtr pXGI = XGIPTR(pScrn);
705
706
707#ifdef XSERVER_LIBPCIACCESS
708    const struct pci_agp_info *agp_info =
709	pci_device_get_agp_info(pXGI->PciInfo);
710
711    return (agp_info == NULL) ? PCI_BUS_TYPE : AGP_BUS_TYPE;
712#else
713	ULONG u34h = pciReadLong(pXGI->PciTag,0x34);
714	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%s] u34h=0x%lx\n", __FUNCTION__, u34h);
715
716	/* This value is read only and the default value should be 0x40;
717	* I have no idea why I should do this */
718	ULONG uLink = u34h & 0xff;
719
720	if (0 == uLink)
721	{
722		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%s] No Next ID, This is a PCI card\n", __FUNCTION__);
723		return PCI_BUS_TYPE;
724	}
725
726	ULONG uType = 0;
727	uType = CheckAGPSlot(pScreen, uLink);
728
729	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%s] This Card Type is %ld \n", __FUNCTION__, uType);
730
731	if (uType == PCI_BUS_TYPE)
732		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%s] This Card Type is PCI\n", __FUNCTION__);
733	if (uType == AGP_BUS_TYPE)
734		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%s] This Card Type is AGP\n", __FUNCTION__);
735	if (uType == PCIE_BUS_TYPE)
736		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[%s] This Card Type is PCIExpress\n", __FUNCTION__);
737
738	return uType;
739#endif
740}
741