summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
commitc4dd1bf20f2bae6d34db059ae47f053012d8a822 (patch)
tree99a443cdf17b0b7a89c609ab20359cfc507e0035
Initial revisionXORG-STABLE
-rw-r--r--man/tdfx.man30
-rw-r--r--src/tdfx.h301
-rw-r--r--src/tdfx_accel.c933
-rw-r--r--src/tdfx_dga.c210
-rw-r--r--src/tdfx_dri.c658
-rw-r--r--src/tdfx_dri.h28
-rw-r--r--src/tdfx_dripriv.h24
-rw-r--r--src/tdfx_driver.c2496
-rw-r--r--src/tdfx_hwcurs.c153
-rw-r--r--src/tdfx_io.c120
-rw-r--r--src/tdfx_priv.c358
-rw-r--r--src/tdfx_priv.h423
-rw-r--r--src/tdfx_sli.c769
-rw-r--r--src/tdfx_video.c1474
-rw-r--r--src/tdfxdefs.h386
15 files changed, 8363 insertions, 0 deletions
diff --git a/man/tdfx.man b/man/tdfx.man
new file mode 100644
index 0000000..1dd66a7
--- /dev/null
+++ b/man/tdfx.man
@@ -0,0 +1,30 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx.man,v 1.2 2001/01/27 18:20:55 dawes Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH TDFX __drivermansuffix__ __vendorversion__
+.SH NAME
+tdfx \- 3Dfx video driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI " Identifier \*q" devname \*q
+.B " Driver \*qtdfx\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B tdfx
+is an XFree86 driver for 3Dfx video cards.
+It supports the Voodoo Banshee, Voodoo3, Voodoo4 and Voodoo5 cards.
+.SH SUPPORTED HARDWARE
+The
+.B tdfx
+driver supports...
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(__filemansuffix__) for general configuration
+details. This section only covers configuration details specific to this
+driver.
+.SH "SEE ALSO"
+XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__)
+.SH AUTHORS
+Authors include: ...
diff --git a/src/tdfx.h b/src/tdfx.h
new file mode 100644
index 0000000..b869065
--- /dev/null
+++ b/src/tdfx.h
@@ -0,0 +1,301 @@
+/*
+ Voodoo Banshee driver version 1.0.2
+
+ Author: Daryll Strauss
+
+ Copyright: 1998,1999
+*/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx.h,v 1.27 2002/10/17 01:02:08 dawes Exp $ */
+
+#ifndef _TDFX_H_
+#define _TDFX_H_
+
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "xf86xv.h"
+#include "tdfxdefs.h"
+
+#ifdef XF86DRI
+#include "xf86drm.h"
+#include "sarea.h"
+#define _XF86DRI_SERVER_
+#include "xf86dri.h"
+#include "dri.h"
+#include "GL/glxint.h"
+#include "tdfx_dri.h"
+#include "tdfx_dripriv.h"
+#endif
+
+#define TDFX_VERSION 4000
+#define TDFX_NAME "TDFX"
+#define TDFX_DRIVER_NAME "tdfx"
+#define TDFX_MAJOR_VERSION 1
+#define TDFX_MINOR_VERSION 0
+#define TDFX_PATCHLEVEL 0
+
+struct _TDFXRec;
+typedef struct _TDFXRec *TDFXPtr;
+
+#include "tdfx_priv.h"
+extern void TDFXSwapContextFifo(ScreenPtr pScreen);
+extern void TDFXLostContext(ScreenPtr pScreen);
+extern Bool TDFXSetupSLI(ScrnInfoPtr pScrn, Bool sliEnable, int aaSamples);
+extern Bool TDFXDisableSLI(TDFXPtr pTDFX);
+
+#ifdef XF86DRI
+extern void FillPrivateDRI(TDFXPtr pTDFX, TDFXDRIPtr pTDFXDRI);
+#endif
+
+#if 0
+/* These are not normally turned on. They are only included for debugging. */
+#define TRACE 1
+#define TRACEACCEL 1
+#define TDFX_DEBUG_CMDS
+#define TRACECURS 1
+#define REGDEBUG 1
+#define TRACEREG
+#endif
+
+#ifdef TRACE
+#define TDFXTRACE ErrorF
+#else
+#define TDFXTRACE if(0) ErrorF
+#endif
+
+#ifdef TRACEACCEL
+#define TDFXTRACEACCEL ErrorF
+#else
+#define TDFXTRACEACCEL if(0) ErrorF
+#endif
+
+#ifdef TRACECURS
+#define TDFXTRACECURS ErrorF
+#else
+#define TDFXTRACECURS if(0) ErrorF
+#endif
+
+#ifdef TRACEREG
+#define TDFXTRACEREG ErrorF
+#else
+#define TDFXTRACEREG if(0) ErrorF
+#endif
+
+#include "xaa.h"
+#include "xf86Cursor.h"
+
+typedef void (*TDFXWriteIndexedByteFunc)(TDFXPtr pTDFX, int addr,
+ char index, char value);
+typedef char (*TDFXReadIndexedByteFunc)(TDFXPtr pTDFX, int addr,
+ char index);
+typedef void (*TDFXWriteWordFunc)(TDFXPtr pTDFX, int addr, int value);
+typedef int (*TDFXReadWordFunc)(TDFXPtr pTDFX, int addr);
+typedef void (*TDFXWriteChipIndexedByteFunc)(TDFXPtr pTDFX, int chip,
+ int addr, char index, char value);
+typedef char (*TDFXReadChipIndexedByteFunc)(TDFXPtr pTDFX, int chip,
+ int addr, char index);
+typedef void (*TDFXWriteChipWordFunc)(TDFXPtr pTDFX, int chip,
+ int addr, int value);
+typedef int (*TDFXReadChipWordFunc)(TDFXPtr pTDFX, int chip,
+ int addr);
+typedef void (*TDFXSyncFunc)(ScrnInfoPtr pScrn);
+typedef void (*TDFXBufferFunc)(TDFXPtr pTDFX, int which);
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+typedef void (*TDFXWriteFifoFunc)(TDFXPtr pTDFX, int val);
+#endif
+
+
+typedef struct {
+ unsigned int vidcfg;
+ unsigned int vidpll;
+ unsigned int dacmode;
+ unsigned int vgainit0;
+ unsigned int vgainit1;
+ unsigned int miscinit0;
+ unsigned int miscinit1;
+ unsigned int screensize;
+ unsigned int stride;
+ unsigned int cursloc;
+ unsigned int startaddr;
+ unsigned int clip0min;
+ unsigned int clip0max;
+ unsigned int clip1min;
+ unsigned int clip1max;
+ unsigned int srcbaseaddr;
+ unsigned int dstbaseaddr;
+ unsigned char ExtVga[2];
+ unsigned int dactable[512];
+} TDFXRegRec, *TDFXRegPtr;
+
+typedef struct TextureData_t {
+ int contextid;
+ void *data;
+ struct TextureData_t *next;
+} TextureData;
+
+#define MAXCHIPS 4
+
+typedef struct _TDFXRec {
+ unsigned char *MMIOBase[MAXCHIPS];
+ unsigned char *FbBase;
+ unsigned char *myFbBase;
+ IOADDRESS PIOBase[MAXCHIPS];
+ long FbMapSize;
+ int pixelFormat;
+ int stride;
+ int cpp;
+ int maxClip;
+ int MaxClock;
+ int ChipType;
+ pciVideoPtr PciInfo;
+ unsigned long LinearAddr[MAXCHIPS];
+ unsigned long MMIOAddr[MAXCHIPS];
+ EntityInfoPtr pEnt;
+ int numChips;
+ PCITAG PciTag[MAXCHIPS];
+ Bool Primary;
+ int HasSGRAM;
+ int PciCnt;
+ int PrevDrawState;
+ int DrawState;
+ int Cmd;
+ int DashedLineSize;
+ BoxRec prevBlitDest;
+ TDFXRegRec SavedReg;
+ TDFXRegRec ModeReg;
+ XAAInfoRecPtr AccelInfoRec;
+ xf86CursorInfoPtr CursorInfoRec;
+ CloseScreenProcPtr CloseScreen;
+ Bool usePIO;
+ Bool NoAccel;
+ DGAModePtr DGAModes;
+ Bool DGAactive;
+ Bool initDone;
+ int DGAViewportStatus;
+ int cursorOffset;
+ int fbOffset;
+ int backOffset;
+ int depthOffset;
+ int texOffset;
+ int texSize;
+ TDFXWriteIndexedByteFunc writeControl;
+ TDFXReadIndexedByteFunc readControl;
+ TDFXWriteWordFunc writeLong;
+ TDFXReadWordFunc readLong;
+ TDFXWriteChipWordFunc writeChipLong;
+ TDFXReadChipWordFunc readChipLong;
+ TDFXSyncFunc sync;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ TDFXWriteFifoFunc writeFifo;
+#endif
+ int syncDone;
+ int scanlineWidth;
+ unsigned char *scanlineColorExpandBuffers[2];
+ PROPDATA
+#ifdef XF86DRI
+ Bool directRenderingEnabled;
+ DRIInfoPtr pDRIInfo;
+ int drmSubFD;
+ int numVisualConfigs;
+ __GLXvisualConfig* pVisualConfigs;
+ TDFXConfigPrivPtr pVisualConfigsPriv;
+ TDFXRegRec DRContextRegs;
+#endif
+ /* State for video */
+ FBAreaPtr offscreenYUVBuf;
+ int offscreenYUVBufWidth;
+ int offscreenYUVBufHeight;
+
+ /* This is a small register shadow. I'm only shadowing
+ * sst2dDstFmt
+ * sst2dSrcFmt
+ * If a real register shadow is ever needed we should probably
+ * shadow everything and make it happen automatically for every write. */
+ INT32 sst2DSrcFmtShadow;
+ INT32 sst2DDstFmtShadow;
+ int pixmapCacheLinesMin;
+ int pixmapCacheLinesMax;
+ FBAreaPtr reservedArea;
+ Bool ShowCache;
+ int videoKey;
+ void (*VideoTimerCallback)(ScrnInfoPtr, Time);
+ FBLinearPtr overlayBuffer;
+ FBLinearPtr overlayBuffer2; /* for double-buffering */
+ int whichOverlayBuffer; /* flip-flop */
+ FBAreaPtr textureBuffer;
+ Bool TextureXvideo;
+ XF86VideoAdaptorPtr overlayAdaptor;
+ XF86VideoAdaptorPtr textureAdaptor;
+ ScreenBlockHandlerProcPtr BlockHandler;
+ OptionInfoPtr Options;
+} TDFXRec;
+
+typedef struct {
+ RegionRec clip;
+ CARD32 colorKey;
+ int filterQuality;
+ CARD32 videoStatus;
+ Time offTime;
+ Time freeTime;
+} TDFXPortPrivRec, *TDFXPortPrivPtr;
+
+typedef struct {
+ PROPSAREADATA
+ int fifoOwner;
+ int CtxOwner;
+ int TexOwner;
+} TDFXSAREAPriv;
+
+#define TDFXPTR(p) ((TDFXPtr)((p)->driverPrivate))
+
+#define DRAW_STATE_CLIPPING 0x1
+#define DRAW_STATE_TRANSPARENT 0x2
+#define DRAW_STATE_CLIP1CHANGED 0x4
+
+#define TDFX_FRONT 0
+#define TDFX_BACK 1
+#define TDFX_DEPTH 2
+
+#define TDFX2XCUTOFF 135000
+
+extern Bool TDFXAccelInit(ScreenPtr pScreen);
+extern Bool TDFXCursorInit(ScreenPtr pScreen);
+extern void TDFXSync(ScrnInfoPtr pScrn);
+extern Bool TDFXDRIScreenInit(ScreenPtr pScreen);
+extern void TDFXDRICloseScreen(ScreenPtr pScreen);
+extern Bool TDFXDRIFinishScreenInit(ScreenPtr pScreen);
+extern Bool TDFXDGAInit(ScreenPtr pScreen);
+extern void TDFXCursorGrabMemory(ScreenPtr pScreen);
+extern void TDFXSetLFBConfig(TDFXPtr pTDFX);
+extern void TDFXSendNOPFifo(ScrnInfoPtr pScrn);
+
+extern Bool TDFXSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+extern void TDFXAdjustFrame(int scrnIndex, int x, int y, int flags);
+
+extern void TDFXSetPIOAccess(TDFXPtr pTDFX);
+extern void TDFXSetMMIOAccess(TDFXPtr pTDFX);
+extern void TDFXWriteLongMMIO(TDFXPtr pTDFX, int addr, int val);
+extern int TDFXReadLongMMIO(TDFXPtr pTDFX, int addr);
+extern void TDFXWriteChipLongMMIO(TDFXPtr pTDFX, int chip, int addr, int val);
+
+extern void TDFXNeedSync(ScrnInfoPtr pScrn);
+extern void TDFXCheckSync(ScrnInfoPtr pScrn);
+extern void TDFXFirstSync(ScrnInfoPtr pScrn);
+
+extern void TDFXSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
+ int ydir, int rop,
+ unsigned int planemask,
+ int trans_color);
+extern void TDFXSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX,
+ int srcY, int dstX, int dstY,
+ int w, int h);
+extern void TDFXSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+extern void TDFXSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h);
+
+extern void TDFXSelectBuffer(TDFXPtr pTDFX, int which);
+
+extern void TDFXInitVideo(ScreenPtr pScreen);
+extern void TDFXCloseVideo(ScreenPtr pScreen);
+
+#endif
diff --git a/src/tdfx_accel.c b/src/tdfx_accel.c
new file mode 100644
index 0000000..d7c11b7
--- /dev/null
+++ b/src/tdfx_accel.c
@@ -0,0 +1,933 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_accel.c,v 1.20 2001/10/28 03:33:49 tsi Exp $ */
+
+/* All drivers should typically include these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "compiler.h"
+
+/* Drivers that need to access the PCI config space directly need this */
+#include "xf86Pci.h"
+
+/* Drivers for PCI hardware need this */
+#include "xf86PciInfo.h"
+
+/* Drivers that use XAA need this */
+#include "xaa.h"
+#include "xaalocal.h"
+#include "xf86fbman.h"
+
+#include "miline.h"
+
+#include "tdfx.h"
+
+#ifdef TDFX_DEBUG_CMDS
+static int cmdCnt=0;
+static int lastAddr=0;
+#endif
+
+static int TDFXROPCvt[] = {0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE,
+ 0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF,
+ 0x00, 0xA0, 0x50, 0xF0, 0x0A, 0xAA, 0x5A, 0xFA,
+ 0x05, 0xA5, 0x55, 0xF5, 0x0F, 0xAF, 0x5F, 0xFF};
+#define ROP_PATTERN_OFFSET 16
+
+static void TDFXSetClippingRectangle(ScrnInfoPtr pScrn, int left, int top,
+ int right, int bottom);
+static void TDFXDisableClipping(ScrnInfoPtr pScrn);
+static void TDFXSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx,
+ int paty, int fg, int bg, int rop,
+ unsigned int planemask);
+static void TDFXSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx,
+ int pay, int x, int y,
+ int w, int h);
+static void TDFXSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask);
+static void TDFXSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int srcx,
+ int srcy, int dstx, int dsty,
+ int flags);
+static void TDFXSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y,
+ int len, int dir);
+static void TDFXNonTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int n,
+ NonTEGlyphPtr glyphs, BoxPtr pbox, int fg,
+ int rop, unsigned int planemask);
+static void TDFXSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
+ unsigned int planemask, int length,
+ unsigned char *pattern);
+static void TDFXSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int flags,
+ int phase);
+#ifdef ENABLE_SS_COLOR_EXPAND_FILL
+static void TDFXSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg, int rop,
+ unsigned int planemask);
+static void TDFXSubsequentScreenToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int x, int y, int w,
+ int h, int srcx,
+ int srcy, int offset);
+#endif
+static void TDFXSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int fg, int bg, int rop,
+ unsigned int planemask);
+static void TDFXSubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
+ int x, int y,
+ int w, int h,
+ int skipleft);
+static void TDFXSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
+
+void
+TDFXNeedSync(ScrnInfoPtr pScrn) {
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ pTDFX->syncDone=FALSE;
+ pTDFX->AccelInfoRec->NeedToSync = TRUE;
+}
+
+void
+TDFXFirstSync(ScrnInfoPtr pScrn) {
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ if (!pTDFX->syncDone) {
+#ifdef XF86DRI
+ if (pTDFX->directRenderingEnabled) {
+ DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
+ TDFXSwapContextFifo(screenInfo.screens[pScrn->scrnIndex]);
+ }
+#endif
+ pTDFX->syncDone=TRUE;
+ pTDFX->sync(pScrn);
+ }
+}
+
+void
+TDFXCheckSync(ScrnInfoPtr pScrn) {
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ if (pTDFX->syncDone) {
+ pTDFX->sync(pScrn);
+ pTDFX->syncDone=FALSE;
+#ifdef XF86DRI
+ if (pTDFX->directRenderingEnabled) {
+ DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
+ }
+#endif
+ }
+}
+
+void
+TDFXSelectBuffer(TDFXPtr pTDFX, int which) {
+ int fmt;
+
+ TDFXMakeRoom(pTDFX, 4);
+ DECLARE(SSTCP_SRCBASEADDR|SSTCP_DSTBASEADDR|SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
+ switch (which) {
+ case TDFX_FRONT:
+ if (pTDFX->cpp==1) fmt=pTDFX->stride|(1<<16);
+ else fmt=pTDFX->stride|((pTDFX->cpp+1)<<16);
+ TDFXWriteLong(pTDFX, SST_2D_DSTBASEADDR, pTDFX->fbOffset);
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
+ pTDFX->sst2DDstFmtShadow = fmt;
+ TDFXWriteLong(pTDFX, SST_2D_SRCBASEADDR, pTDFX->fbOffset);
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, fmt);
+ pTDFX->sst2DSrcFmtShadow = fmt;
+ break;
+ case TDFX_BACK:
+ if (pTDFX->cpp==2)
+ fmt=((pTDFX->stride+127)/128)|(3<<16); /* Tiled 16bpp */
+ else
+ fmt=((pTDFX->stride+127)/128)|(5<<16); /* Tiled 32bpp */
+ TDFXWriteLong(pTDFX, SST_2D_DSTBASEADDR, pTDFX->backOffset|BIT(31));
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
+ pTDFX->sst2DDstFmtShadow = fmt;
+ TDFXWriteLong(pTDFX, SST_2D_SRCBASEADDR, pTDFX->backOffset|BIT(31));
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, fmt);
+ pTDFX->sst2DSrcFmtShadow = fmt;
+ break;
+ case TDFX_DEPTH:
+ if (pTDFX->cpp==2)
+ fmt=((pTDFX->stride+127)/128)|(3<<16); /* Tiled 16bpp */
+ else
+ fmt=((pTDFX->stride+127)/128)|(5<<16); /* Tiled 32bpp */
+ TDFXWriteLong(pTDFX, SST_2D_DSTBASEADDR, pTDFX->depthOffset|BIT(31));
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
+ pTDFX->sst2DDstFmtShadow = fmt;
+ TDFXWriteLong(pTDFX, SST_2D_SRCBASEADDR, pTDFX->depthOffset|BIT(31));
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, fmt);
+ pTDFX->sst2DSrcFmtShadow = fmt;
+ break;
+ default:
+ ;
+ }
+}
+
+void
+TDFXSetLFBConfig(TDFXPtr pTDFX) {
+ if (pTDFX->ChipType<=PCI_CHIP_VOODOO3) {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ unsigned int lfbmode;
+ lfbmode=TDFXReadLongMMIO(pTDFX, SST_3D_LFBMODE);
+
+ lfbmode&=~BIT(12); /* 0 bit 12 is byte swizzle */
+ lfbmode|=BIT(11); /* 1 bit 11 is word swizzle */
+ lfbmode&=~BIT(10); /* 0 bit 10 ARGB or ABGR */
+ lfbmode&=~BIT(9); /* 0 bit 9 if bit10 = 0: ARGB else ABGR */
+
+ TDFXWriteLongMMIO(pTDFX, SST_3D_LFBMODE, lfbmode);
+#endif
+ TDFXWriteLongMMIO(pTDFX, LFBMEMORYCONFIG, (pTDFX->backOffset>>12) |
+ SST_RAW_LFB_ADDR_STRIDE_4K |
+ ((pTDFX->stride+127)/128)<<SST_RAW_LFB_TILE_STRIDE_SHIFT);
+ } else {
+ int chip;
+ int stride, bits;
+ int TileAperturePitch, lg2TileAperturePitch;
+ if (pTDFX->cpp==2) stride=pTDFX->stride;
+ else stride=4*pTDFX->stride/pTDFX->cpp;
+ bits=pTDFX->backOffset>>12;
+ for (lg2TileAperturePitch = 0, TileAperturePitch = 1024;
+ (lg2TileAperturePitch < 5) &&
+ TileAperturePitch < stride;
+ lg2TileAperturePitch += 1, TileAperturePitch <<= 1);
+#if 0
+ fprintf(stderr, "Using %d (== lg2(%d)-10) for tile aperture pitch\n",
+ lg2TileAperturePitch, TileAperturePitch);
+ fprintf(stderr, "stride == %d\n", stride);
+#endif
+ for (chip=0; chip<pTDFX->numChips; chip++) {
+ TDFXWriteChipLongMMIO(pTDFX, chip, LFBMEMORYCONFIG, (bits&0x1FFF) |
+ SST_RAW_LFB_ADDR_STRIDE(lg2TileAperturePitch) |
+ ((bits&0x6000)<<10) |
+ ((stride+127)/128)<<SST_RAW_LFB_TILE_STRIDE_SHIFT);
+ }
+ }
+}
+
+Bool
+TDFXAccelInit(ScreenPtr pScreen)
+{
+ XAAInfoRecPtr infoPtr;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ CARD32 commonFlags;
+
+ pTDFX->AccelInfoRec = infoPtr = XAACreateInfoRec();
+ if (!infoPtr) return FALSE;
+
+ infoPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER;
+
+ infoPtr->Sync = pTDFX->sync;
+
+ infoPtr->SetClippingRectangle = TDFXSetClippingRectangle;
+ infoPtr->DisableClipping = TDFXDisableClipping;
+ infoPtr->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND |
+ HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
+ HARDWARE_CLIP_MONO_8x8_FILL |
+ HARDWARE_CLIP_COLOR_8x8_FILL |
+ HARDWARE_CLIP_SOLID_FILL |
+ HARDWARE_CLIP_DASHED_LINE |
+ HARDWARE_CLIP_SOLID_LINE;
+
+ miSetZeroLineBias(pScreen, OCTANT2 | OCTANT5 | OCTANT7 | OCTANT8);
+
+ commonFlags = BIT_ORDER_IN_BYTE_MSBFIRST | NO_PLANEMASK;
+
+ infoPtr->SetupForSolidFill = TDFXSetupForSolidFill;
+ infoPtr->SubsequentSolidFillRect = TDFXSubsequentSolidFillRect;
+ infoPtr->SolidFillFlags = commonFlags;
+
+ infoPtr->SetupForSolidLine = TDFXSetupForSolidLine;
+ infoPtr->SubsequentSolidTwoPointLine = TDFXSubsequentSolidTwoPointLine;
+ infoPtr->SubsequentSolidHorVertLine = TDFXSubsequentSolidHorVertLine;
+ infoPtr->SolidLineFlags = commonFlags;
+
+ infoPtr->SetupForDashedLine = TDFXSetupForDashedLine;
+ infoPtr->SubsequentDashedTwoPointLine = TDFXSubsequentDashedTwoPointLine;
+ infoPtr->DashedLineFlags = commonFlags | LINE_PATTERN_LSBFIRST_LSBJUSTIFIED;
+ infoPtr->DashPatternMaxLength = 32;
+
+ infoPtr->NonTEGlyphRenderer = TDFXNonTEGlyphRenderer;
+ infoPtr->NonTEGlyphRendererFlags = commonFlags;
+
+ infoPtr->SetupForScreenToScreenCopy = TDFXSetupForScreenToScreenCopy;
+ infoPtr->SubsequentScreenToScreenCopy = TDFXSubsequentScreenToScreenCopy;
+ infoPtr->ScreenToScreenCopyFlags = commonFlags;
+
+ /* When we're using the fifo we have to use indirect expansion */
+ pTDFX->scanlineColorExpandBuffers[0] = xalloc((pScrn->virtualX+62)/32*4);
+ pTDFX->scanlineColorExpandBuffers[1] = xalloc((pScrn->virtualX+62)/32*4);
+ infoPtr->NumScanlineColorExpandBuffers=2;
+ infoPtr->ScanlineColorExpandBuffers=pTDFX->scanlineColorExpandBuffers;
+ infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
+ TDFXSetupForCPUToScreenColorExpandFill;
+ infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
+ TDFXSubsequentCPUToScreenColorExpandFill;
+ infoPtr->SubsequentColorExpandScanline =
+ TDFXSubsequentColorExpandScanline;
+ infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK |
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ BIT_ORDER_IN_BYTE_MSBFIRST |
+#endif
+ CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD |
+ LEFT_EDGE_CLIPPING; /* | LEFT_EDGE_CLIPPING_NEGATIVE_X; */
+
+ infoPtr->SetupForMono8x8PatternFill = TDFXSetupForMono8x8PatternFill;
+ infoPtr->SubsequentMono8x8PatternFillRect =
+ TDFXSubsequentMono8x8PatternFillRect;
+ infoPtr->Mono8x8PatternFillFlags = commonFlags |
+ HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
+ HARDWARE_PATTERN_SCREEN_ORIGIN;
+
+#ifdef ENABLE_SS_COLOR_EXPAND_FILL
+ /* This causes us to fail compliance */
+ /* I suspect 1bpp pixmaps are getting written to cache incorrectly */
+ infoPtr->SetupForScreenToScreenColorExpandFill =
+ TDFXSetupForScreenToScreenColorExpandFill;
+ infoPtr->SubsequentScreenToScreenColorExpandFill =
+ TDFXSubsequentScreenToScreenColorExpandFill;
+ infoPtr->ScreenToScreenColorExpandFillFlags = commonFlags;
+#endif
+
+ pTDFX->PciCnt=TDFXReadLongMMIO(pTDFX, 0)&0x1F;
+ pTDFX->PrevDrawState=pTDFX->DrawState=0;
+
+ pTDFX->ModeReg.srcbaseaddr=pTDFX->fbOffset;
+ TDFXWriteLongMMIO(pTDFX, SST_2D_SRCBASEADDR, pTDFX->ModeReg.srcbaseaddr);
+ pTDFX->ModeReg.dstbaseaddr=pTDFX->fbOffset;
+ TDFXWriteLongMMIO(pTDFX, SST_2D_DSTBASEADDR, pTDFX->ModeReg.dstbaseaddr);
+
+ pTDFX->sst2DSrcFmtShadow = TDFXReadLongMMIO(pTDFX, SST_2D_SRCFORMAT);
+ pTDFX->sst2DDstFmtShadow = TDFXReadLongMMIO(pTDFX, SST_2D_DSTFORMAT);
+
+ /* Fill in acceleration functions */
+ return XAAInit(pScreen, infoPtr);
+}
+
+static void TDFXMakeRoomNoProp(TDFXPtr pTDFX, int size) {
+ int stat;
+
+ pTDFX->PciCnt-=size;
+ if (pTDFX->PciCnt<1) {
+ do {
+ stat=TDFXReadLongMMIO(pTDFX, 0);
+ pTDFX->PciCnt=stat&0x1F;
+ } while (pTDFX->PciCnt<size);
+ }
+}
+
+static void TDFXSendNOPNoProp(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+
+ pTDFX=TDFXPTR(pScrn);
+ TDFXMakeRoomNoProp(pTDFX, 1);
+ TDFXWriteLongMMIO(pTDFX, SST_2D_COMMAND, SST_2D_NOP);
+}
+
+void TDFXSync(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+ int i;
+ int stat;
+
+ TDFXTRACEACCEL("TDFXSync\n");
+ pTDFX=TDFXPTR(pScrn);
+
+ TDFXSendNOPNoProp(pScrn);
+ i=0;
+ do {
+ stat=TDFXReadLongMMIO(pTDFX, 0);
+ if (stat&SST_BUSY) i=0; else i++;
+ } while (i<3);
+ pTDFX->PciCnt=stat&0x1F;
+}
+
+static void
+TDFXMatchState(TDFXPtr pTDFX)
+{
+ if (pTDFX->PrevDrawState==pTDFX->DrawState) return;
+
+ /* Do we need to set a clipping rectangle? */
+ if (pTDFX->DrawState&DRAW_STATE_CLIPPING)
+ pTDFX->Cmd |= SST_2D_USECLIP1;
+ else
+ pTDFX->Cmd &= ~SST_2D_USECLIP1;
+
+ /* Do we need to set transparency? */
+ TDFXMakeRoom(pTDFX, 1);
+ DECLARE(SSTCP_COMMANDEXTRA);
+ if (pTDFX->DrawState&DRAW_STATE_TRANSPARENT) {
+ TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, SST_2D_SRC_COLORKEY_EX);
+ } else {
+ TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, 0);
+ }
+
+ /* Has the previous routine left clip1 changed? Reset it. */
+ if (pTDFX->DrawState&DRAW_STATE_CLIP1CHANGED) {
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_CLIP1MIN|SSTCP_CLIP1MAX);
+ TDFXWriteLong(pTDFX, SST_2D_CLIP1MIN, pTDFX->ModeReg.clip1min);
+ TDFXWriteLong(pTDFX, SST_2D_CLIP1MAX, pTDFX->ModeReg.clip1max);
+ pTDFX->DrawState&=~DRAW_STATE_CLIP1CHANGED;
+ }
+
+ pTDFX->PrevDrawState=pTDFX->DrawState;
+}
+
+static void
+TDFXClearState(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+
+ pTDFX=TDFXPTR(pScrn);
+ pTDFX->Cmd=0;
+ pTDFX->DrawState&=~DRAW_STATE_TRANSPARENT;
+ /* Make sure we've done a sync */
+ TDFXFirstSync(pScrn);
+}
+
+static void
+TDFXSetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, int right,
+ int bottom)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("TDFXSetClippingRectangle %d,%d to %d,%d\n", left, top,
+ right, bottom);
+ pTDFX=TDFXPTR(pScrn);
+
+ pTDFX->ModeReg.clip1min=(top&0xFFF)<<16 | (left&0xFFF);
+ pTDFX->ModeReg.clip1max=((bottom+1)&0xFFF)<<16 | ((right+1)&0xFFF);
+
+ pTDFX->DrawState|=DRAW_STATE_CLIPPING|DRAW_STATE_CLIP1CHANGED;
+}
+
+static void
+TDFXDisableClipping(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("TDFXDisableClippingRectangle\n");
+ pTDFX=TDFXPTR(pScrn);
+
+ pTDFX->DrawState&=~DRAW_STATE_CLIPPING;
+}
+
+void
+TDFXSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
+ unsigned int planemask, int trans_color)
+{
+ TDFXPtr pTDFX;
+ int fmt;
+
+ TDFXTRACEACCEL("TDFXSetupForScreenToScreenCopy\n xdir=%d ydir=%d "
+ "rop=%d planemask=%d trans_color=%d\n",
+ xdir, ydir, rop, planemask, trans_color);
+ pTDFX=TDFXPTR(pScrn);
+ TDFXClearState(pScrn);
+
+ if (trans_color!=-1) {
+ TDFXMakeRoom(pTDFX, 3);
+ DECLARE(SSTCP_SRCCOLORKEYMIN|SSTCP_SRCCOLORKEYMAX|SSTCP_ROP);
+ TDFXWriteLong(pTDFX, SST_2D_SRCCOLORKEYMIN, trans_color);
+ TDFXWriteLong(pTDFX, SST_2D_SRCCOLORKEYMAX, trans_color);
+ TDFXWriteLong(pTDFX, SST_2D_ROP, TDFXROPCvt[GXnoop]<<8);
+ pTDFX->DrawState|=DRAW_STATE_TRANSPARENT;
+ }
+ pTDFX->Cmd = (TDFXROPCvt[rop]<<24) | SST_2D_SCRNTOSCRNBLIT;
+ if (xdir==-1) pTDFX->Cmd |= SST_2D_X_RIGHT_TO_LEFT;
+ if (ydir==-1) pTDFX->Cmd |= SST_2D_Y_BOTTOM_TO_TOP;
+ if (pTDFX->cpp==1) fmt=pTDFX->stride|(1<<16);
+ else fmt=pTDFX->stride|((pTDFX->cpp+1)<<16);
+
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
+ pTDFX->sst2DDstFmtShadow = fmt;
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, fmt);
+ pTDFX->sst2DSrcFmtShadow = fmt;
+}
+
+void
+TDFXSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX, int srcY,
+ int dstX, int dstY, int w, int h)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("TDFXSubsequentScreenToScreenCopy\n srcX=%d srcY=%d"
+ " dstX=%d dstY=%d w=%d h=%d\n", srcX, srcY, dstX, dstY, w, h);
+ pTDFX=TDFXPTR(pScrn);
+ TDFXMatchState(pTDFX);
+
+ if (pTDFX->Cmd&SST_2D_Y_BOTTOM_TO_TOP) {
+ srcY += h-1;
+ dstY += h-1;
+ }
+ if (pTDFX->Cmd&SST_2D_X_RIGHT_TO_LEFT) {
+ srcX += w-1;
+ dstX += w-1;
+ }
+ if ((srcY>=dstY-32 && srcY<=dstY)||
+ (srcY>=pTDFX->prevBlitDest.y1-32 && srcY<=pTDFX->prevBlitDest.y1)) {
+ TDFXSendNOP(pScrn);
+ }
+ pTDFX->sync(pScrn);
+
+ TDFXMakeRoom(pTDFX, 4);
+ DECLARE(SSTCP_DSTSIZE|SSTCP_DSTXY|SSTCP_SRCXY|SSTCP_COMMAND);
+ TDFXWriteLong(pTDFX, SST_2D_SRCXY, (srcX&0x1FFF) | ((srcY&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, (w&0x1FFF) | ((h&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX, SST_2D_DSTXY, (dstX&0x1FFF) | ((dstY&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd|SST_2D_GO);
+
+ pTDFX->prevBlitDest.y1=dstY;
+}
+
+void
+TDFXSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+ TDFXPtr pTDFX;
+ int fmt;
+
+ TDFXTRACEACCEL("TDFXSetupForSolidFill color=%d rop=%d planemask=%d\n",
+ color, rop, planemask);
+ pTDFX=TDFXPTR(pScrn);
+ TDFXClearState(pScrn);
+
+ pTDFX->Cmd=TDFXROPCvt[rop]<<24;
+ if (pTDFX->cpp==1) fmt=(1<<16)|pTDFX->stride;
+ else fmt=((pTDFX->cpp+1)<<16)|pTDFX->stride;
+
+ TDFXMakeRoom(pTDFX, 3);
+ DECLARE(SSTCP_DSTFORMAT|SSTCP_COLORFORE|
+ SSTCP_COLORBACK);
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
+ pTDFX->sst2DDstFmtShadow = fmt;
+ TDFXWriteLong(pTDFX, SST_2D_COLORBACK, color);
+ TDFXWriteLong(pTDFX, SST_2D_COLORFORE, color);
+}
+
+void
+TDFXSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
+{
+ /* Also called by TDFXSubsequentMono8x8PatternFillRect */
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("TDFXSubsequentSolidFillRect x=%d y=%d w=%d h=%d\n",
+ x, y, w, h);
+ pTDFX=TDFXPTR(pScrn);
+ TDFXMatchState(pTDFX);
+
+ TDFXMakeRoom(pTDFX, 3);
+ DECLARE(SSTCP_DSTSIZE|SSTCP_DSTXY|SSTCP_COMMAND);
+ TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, ((h&0x1FFF)<<16) | (w&0x1FFF));
+ TDFXWriteLong(pTDFX, SST_2D_DSTXY, ((y&0x1FFF)<<16) | (x&0x1FFF));
+ TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd | SST_2D_RECTANGLEFILL |
+ SST_2D_GO);
+}
+
+static void
+TDFXSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
+ int fg, int bg, int rop, unsigned int planemask)
+{
+ TDFXPtr pTDFX;
+ int fmt;
+
+ TDFXTRACEACCEL("TDFXSetupForMono8x8PatternFill patx=%x paty=%x fg=%d"
+ " bg=%d rop=%d planemask=%d\n", patx, paty, fg, bg, rop,
+ planemask);
+ pTDFX=TDFXPTR(pScrn);
+ TDFXClearState(pScrn);
+
+ pTDFX->Cmd = (TDFXROPCvt[rop+ROP_PATTERN_OFFSET]<<24) |
+ SST_2D_MONOCHROME_PATTERN;
+ if (bg==-1) {
+ pTDFX->Cmd |= SST_2D_TRANSPARENT_MONOCHROME;
+ }
+ if (pTDFX->cpp==1) fmt=(1<<16)|pTDFX->stride;
+ else fmt=((pTDFX->cpp+1)<<16)|pTDFX->stride;
+
+ TDFXMakeRoom(pTDFX, 5);
+ DECLARE(SSTCP_DSTFORMAT|SSTCP_PATTERN0ALIAS
+ |SSTCP_PATTERN1ALIAS|SSTCP_COLORFORE|
+ SSTCP_COLORBACK);
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
+ pTDFX->sst2DDstFmtShadow = fmt;
+ TDFXWriteLong(pTDFX, SST_2D_PATTERN0, patx);
+ TDFXWriteLong(pTDFX, SST_2D_PATTERN1, paty);
+ TDFXWriteLong(pTDFX, SST_2D_COLORBACK, bg);
+ TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
+}
+
+static void
+TDFXSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
+ int x, int y, int w, int h)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("TDFXSubsequentMono8x8PatternFillRect patx=%x paty=%x"
+ " x=%d y=%d w=%d h=%d\n", patx, paty, x, y, w, h);
+ pTDFX=TDFXPTR(pScrn);
+
+ pTDFX->Cmd |= ((patx&0x7)<<SST_2D_X_PATOFFSET_SHIFT) |
+ ((paty&0x7)<<SST_2D_Y_PATOFFSET_SHIFT);
+
+ TDFXSubsequentSolidFillRect(pScrn, x, y, w, h);
+}
+
+static void
+TDFXSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
+ unsigned int planemask)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("TDFXSetupForSolidLine\n");
+ pTDFX=TDFXPTR(pScrn);
+ TDFXClearState(pScrn);
+
+ pTDFX->Cmd = (TDFXROPCvt[rop]<<24);
+
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_COLORFORE|SSTCP_COLORBACK);
+ TDFXWriteLong(pTDFX, SST_2D_COLORBACK, color);
+ TDFXWriteLong(pTDFX, SST_2D_COLORFORE, color);
+}
+
+static void
+TDFXSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int srcx, int srcy,
+ int dstx, int dsty, int flags)
+{
+ /* Also used by TDFXSubsequentDashedTwoPointLine */
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("TDFXSubsequentSolidTwoPointLine "
+ "srcx=%d srcy=%d dstx=%d dsty=%d flags=%d\n",
+ srcx, srcy, dstx, dsty, flags);
+ pTDFX=TDFXPTR(pScrn);
+ TDFXMatchState(pTDFX);
+
+ if (flags&OMIT_LAST) pTDFX->Cmd|=SST_2D_POLYLINE;
+ else pTDFX->Cmd|=SST_2D_LINE;
+
+ TDFXMakeRoom(pTDFX, 3);
+ DECLARE(SSTCP_SRCXY|SSTCP_DSTXY|SSTCP_COMMAND);
+ TDFXWriteLong(pTDFX, SST_2D_SRCXY, (srcy&0x1FFF)<<16 | (srcx&0x1FFF));
+ TDFXWriteLong(pTDFX, SST_2D_DSTXY, (dsty&0x1FFF)<<16 | (dstx&0x1FFF));
+ TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd|SST_2D_GO);
+}
+
+static void
+TDFXSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len,
+ int dir)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("TDFXSubsequentSolidHorVertLine\n");
+ pTDFX=TDFXPTR(pScrn);
+ TDFXMatchState(pTDFX);
+
+ TDFXMakeRoom(pTDFX, 3);
+ DECLARE(SSTCP_SRCXY|SSTCP_DSTXY|SSTCP_COMMAND);
+ TDFXWriteLong(pTDFX, SST_2D_SRCXY, (y&0x1FFF)<<16 | (x&0x1FFF));
+ if (dir == DEGREES_0)
+ TDFXWriteLong(pTDFX, SST_2D_DSTXY, (y&0x1FFF)<<16 | ((x+len)&0x1FFF));
+ else
+ TDFXWriteLong(pTDFX, SST_2D_DSTXY, ((y+len)&0x1FFF)<<16 | (x&0x1FFF));
+ TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd|SST_2D_POLYLINE|SST_2D_GO);
+}
+
+static void
+TDFXNonTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int n,
+ NonTEGlyphPtr glyphs, BoxPtr pbox, int fg, int rop,
+ unsigned int planemask)
+{
+ TDFXPtr pTDFX;
+ int ndwords;
+ int g;
+ NonTEGlyphPtr glyph;
+
+ TDFXTRACEACCEL("TDFXNonTEGlyphRenderer\n");
+ pTDFX=TDFXPTR(pScrn);
+ TDFXClearState(pScrn);
+ /* Don't bother fixing clip1, we're going to change it anyway */
+ pTDFX->DrawState&=~DRAW_STATE_CLIP1CHANGED;
+ TDFXMatchState(pTDFX);
+ /* We're changing clip1 so make sure we use it and flag it */
+ pTDFX->Cmd|=SST_2D_USECLIP1;
+ pTDFX->DrawState|=DRAW_STATE_CLIP1CHANGED;
+
+ pTDFX->Cmd|=(TDFXROPCvt[rop]<<24)|SST_2D_TRANSPARENT_MONOCHROME;
+ pTDFX->Cmd|=SST_2D_HOSTTOSCRNBLIT;
+
+ TDFXMakeRoom(pTDFX, 6);
+ DECLARE(SSTCP_CLIP1MIN|SSTCP_CLIP1MAX|SSTCP_SRCFORMAT|
+ SSTCP_SRCXY|SSTCP_COLORFORE|SSTCP_COMMAND);
+ TDFXWriteLong(pTDFX, SST_2D_CLIP1MIN, ((pbox->y1&0x1FFF)<<16) |
+ (pbox->x1&0x1FFF));
+ TDFXWriteLong(pTDFX, SST_2D_CLIP1MAX, ((pbox->y2&0x1FFF)<<16) |
+ (pbox->x2&0x1FFF));
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, SST_2D_PIXFMT_1BPP |
+ SST_2D_SOURCE_PACKING_DWORD | BIT(20));
+#else
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, SST_2D_PIXFMT_1BPP |
+ SST_2D_SOURCE_PACKING_DWORD);
+#endif
+ pTDFX->sst2DSrcFmtShadow = SST_2D_PIXFMT_1BPP | SST_2D_SOURCE_PACKING_DWORD;
+ TDFXWriteLong(pTDFX, SST_2D_SRCXY, 0);
+ TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
+ TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd);
+
+ for (g=0, glyph=glyphs; g<n; g++, glyph++) {
+ int dx = x+glyph->start;
+ int dy = y-glyph->yoff;
+ int w = glyph->end - glyph->start;
+ int *glyph_data = (int*)glyph->bits;
+
+ if (!glyph->srcwidth) continue;
+ ndwords = (glyph->srcwidth+3)>>2;
+ ndwords *= glyph->height;
+
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_DSTSIZE|SSTCP_DSTXY);
+ TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, ((glyph->height&0x1FFF)<<16) |
+ (w&0x1FFF));
+ TDFXWriteLong(pTDFX, SST_2D_DSTXY, ((dy&0x1FFF)<<16) | (dx&0x1FFF));
+
+ do {
+ int i = ndwords;
+ int j;
+
+ if (i>30) i=30;
+ TDFXMakeRoom(pTDFX, i);
+ DECLARE_LAUNCH(i, 0);
+ for (j=0; j<i; j++) {
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ TDFXWriteLong(pTDFX, SST_2D_LAUNCH, *glyph_data);
+#else
+ TDFXWriteLong(pTDFX, SST_2D_LAUNCH, XAAReverseBitOrder(*glyph_data));
+#endif
+ glyph_data++;
+ }
+ ndwords -= i;
+ } while (ndwords);
+ }
+}
+
+static void
+TDFXSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
+ unsigned int planemask, int length,
+ unsigned char *pattern)
+{
+ TDFXPtr pTDFX;
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ unsigned int pat = *(unsigned int *)pattern;
+#endif
+
+ TDFXTRACEACCEL("TDFXSetupForDashedLine\n");
+ pTDFX=TDFXPTR(pScrn);
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ pat=((pat & 0xAAAAAAAA) >> 1) | ((pat & 0x55555555) << 1);
+ pat=((pat & 0xCCCCCCCC) >> 2) | ((pat & 0x33333333) << 2);
+ pat=((pat & 0xF0F0F0F0) >> 4) | ((pat & 0x0F0F0F0F) << 4);
+ pat=((pat & 0xFF00FF00) >> 8) | ((pat & 0x00FF00FF) << 8);
+ pat=((pat & 0xFFFF0000) >> 16) | ((pat & 0x0000FFFF) << 16);
+#endif
+
+ TDFXClearState(pScrn);
+
+ pTDFX->Cmd = (TDFXROPCvt[rop]<<24) | SST_2D_STIPPLE_LINE;
+ if(bg == -1) {
+ pTDFX->Cmd |= SST_2D_TRANSPARENT_MONOCHROME;
+ }
+ pTDFX->DashedLineSize = ((length-1)&0xFF)+1;
+
+ TDFXMakeRoom(pTDFX, 3);
+ DECLARE(SSTCP_COLORFORE|SSTCP_COLORBACK|SSTCP_LINESTIPPLE);
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ TDFXWriteLong(pTDFX, SST_2D_LINESTIPPLE, pat);
+#else
+ TDFXWriteLong(pTDFX, SST_2D_LINESTIPPLE, *(int *)pattern);
+#endif
+ TDFXWriteLong(pTDFX, SST_2D_COLORBACK, bg);
+ TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
+}
+
+static void
+TDFXSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1,
+ int x2, int y2, int flags, int phase)
+{
+ TDFXPtr pTDFX;
+ int linestyle;
+
+ TDFXTRACEACCEL("TDFXSubsequentDashedTwoPointLine\n");
+ pTDFX=TDFXPTR(pScrn);
+
+ linestyle = ((pTDFX->DashedLineSize-1)<<8) |
+ (((phase%pTDFX->DashedLineSize)&0x1F)<<24);
+
+ TDFXMakeRoom(pTDFX, 1);
+ DECLARE(SSTCP_LINESTYLE);
+ TDFXWriteLong(pTDFX, SST_2D_LINESTYLE, linestyle);
+
+ TDFXSubsequentSolidTwoPointLine(pScrn, x1, y1, x2, y2, flags);
+}
+
+#ifdef ENABLE_SS_COLOR_EXPAND_FILL
+static void
+TDFXSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg,
+ int rop, unsigned int planemask)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("TDFXSetupForScreenToScreenColorExpandFill\n");
+ pTDFX=TDFXPTR(pScrn);
+ TDFXClearState(pScrn);
+
+ TDFXMatchState(pTDFX);
+ pTDFX->Cmd|=SST_2D_SCRNTOSCRNBLIT|(TDFXROPCvt[rop]<<24);
+
+ if (bg==-1) {
+ pTDFX->Cmd |= SST_2D_TRANSPARENT_MONOCHROME;
+ }
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_COLORFORE|SSTCP_COLORBACK);
+ TDFXWriteLong(pTDFX, SST_2D_COLORBACK, bg);
+ TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
+}
+
+static void
+TDFXSubsequentScreenToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h, int srcx, int srcy,
+ int offset)
+{
+ TDFXPtr pTDFX;
+ int fmt;
+
+ TDFXTRACEACCEL("TDFXSubsequentScreenToScreenColorExpandFill "
+ "x=%d y=%d w=%d h=%d srcx=%d srcy=%d offset=%d\n",
+ x, y, w, h, srcx, srcy, offset);
+ pTDFX=TDFXPTR(pScrn);
+ /* Don't bother resetting clip1 since we're changing it anyway */
+ pTDFX->DrawState&=~DRAW_STATE_CLIP1CHANGED;
+ TDFXMatchState(pTDFX);
+ /* We're changing clip1 so make sure we use it and flag it */
+ pTDFX->Cmd|=SST_2D_USECLIP1;
+ pTDFX->DrawState|=DRAW_STATE_CLIP1CHANGED;
+
+ if (srcy>=pTDFX->prevBlitDest.y1-8 && srcy<=pTDFX->prevBlitDest.y1) {
+ TDFXSendNOP(pScrn);
+ }
+
+ if (pTDFX->cpp==1) fmt=(1<<16)|pTDFX->stride;
+ else fmt=(pTDFX->cpp+1)<<16|pTDFX->stride;
+
+ TDFXMakeRoom(pTDFX, 8);
+ DECLARE(SSTCP_SRCFORMAT|SSTCP_SRCXY|SSTCP_DSTFORMAT |
+ SSTCP_DSTSIZE|SSTCP_DSTXY|SSTCP_COMMAND |
+ SSTCP_CLIP1MIN|SSTCP_CLIP1MAX);
+ TDFXWriteLong(pTDFX,SST_2D_DSTFORMAT, fmt);
+ pTDFX->sst2DDstFmtShadow = fmt;
+ TDFXWriteLong(pTDFX,SST_2D_CLIP1MIN, (x&0x1FFF) | ((y&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX,SST_2D_CLIP1MAX, ((x+w)&0x1FFF) | (((y+h)&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX,SST_2D_SRCFORMAT, pTDFX->stride);
+ pTDFX->sst2DSrcFmtShadow = pTDFX->stride;
+ TDFXWriteLong(pTDFX,SST_2D_SRCXY, (srcx&0x1FFF) | ((srcy&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX,SST_2D_DSTSIZE, ((w+offset)&0x1FFF) | ((h&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX,SST_2D_DSTXY, ((x-offset)&0x1FFF) | ((y&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX,SST_2D_COMMAND, pTDFX->Cmd|SST_2D_GO);
+
+ pTDFX->prevBlitDest.y1=y;
+}
+#endif
+
+static void
+TDFXSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg,
+ int rop, unsigned int planemask)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACEACCEL("SetupForCPUToScreenColorExpandFill bg=%x fg=%x rop=%d\n",
+ bg, fg, rop);
+ pTDFX=TDFXPTR(pScrn);
+ TDFXClearState(pScrn);
+
+ pTDFX->Cmd|=SST_2D_HOSTTOSCRNBLIT|(TDFXROPCvt[rop]<<24);
+
+ if (bg == -1) {
+ pTDFX->Cmd |= SST_2D_TRANSPARENT_MONOCHROME;
+ }
+
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_COLORBACK|SSTCP_COLORFORE);
+ TDFXWriteLong(pTDFX, SST_2D_COLORBACK, bg);
+ TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
+}
+
+static void
+TDFXSubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y,
+ int w, int h, int skipleft)
+{
+ TDFXPtr pTDFX;
+ int fmt;
+
+ TDFXTRACEACCEL("SubsequentCPUToScreenColorExpandFill x=%d y=%d w=%d h=%d"
+ " skipleft=%d\n", x, y, w, h, skipleft);
+ pTDFX = TDFXPTR(pScrn);
+
+ /* We're changing clip1 anyway, so don't bother to reset it */
+ pTDFX->DrawState&=~DRAW_STATE_CLIP1CHANGED;
+ TDFXMatchState(pTDFX);
+ /* Make sure we use clip1 and flag it */
+ pTDFX->Cmd|=SST_2D_USECLIP1;
+ pTDFX->DrawState|=DRAW_STATE_CLIP1CHANGED;
+
+ if (pTDFX->cpp==1) fmt=(1<<16)|pTDFX->stride;
+ else fmt=((pTDFX->cpp+1)<<16)|pTDFX->stride;
+ pTDFX->scanlineWidth=w;
+
+ TDFXMakeRoom(pTDFX, 8);
+ DECLARE(SSTCP_CLIP1MIN|SSTCP_CLIP1MAX|SSTCP_SRCFORMAT|
+ SSTCP_DSTFORMAT|SSTCP_DSTSIZE|SSTCP_SRCXY|
+ SSTCP_DSTXY|SSTCP_COMMAND);
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
+ pTDFX->sst2DDstFmtShadow = fmt;
+ TDFXWriteLong(pTDFX, SST_2D_CLIP1MIN, ((y&0x1FFF)<<16)|(x&0x1FFF));
+ TDFXWriteLong(pTDFX, SST_2D_CLIP1MAX, (((y+h)&0x1FFF)<<16)|((x+w)&0x1FFF));
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ /* bit 20 byte swizzle */
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, ((((w+31)/32)*4) & 0x3FFF) | BIT(20));
+#else
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, (((w+31)/32)*4) & 0x3FFF);
+#endif
+ pTDFX->sst2DSrcFmtShadow = (((w+31)/32)*4) & 0x3FFF;
+ TDFXWriteLong(pTDFX, SST_2D_SRCXY, skipleft&0x1F);
+ TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, ((w-skipleft)&0x1FFF)|((h&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX, SST_2D_DSTXY, ((x+skipleft)&0x1FFF) | ((y&0x1FFF)<<16));
+ TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd|SST_2D_GO);
+}
+
+static void TDFXSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
+{
+ TDFXPtr pTDFX;
+ int i, size, cnt;
+ CARD32 *pos;
+
+ TDFXTRACEACCEL("SubsequentColorExpandScanline bufno=%d\n", bufno);
+ pTDFX = TDFXPTR(pScrn);
+
+ cnt=(pTDFX->scanlineWidth+31)/32;
+ pos=(CARD32 *)pTDFX->scanlineColorExpandBuffers[bufno];
+ while (cnt>0) {
+ if (cnt>64) size=64;
+ else size=cnt;
+ TDFXMakeRoom(pTDFX, size);
+ DECLARE_LAUNCH(size, 0);
+ for (i=0; i<size; i++, pos++) {
+ TDFXWriteLong(pTDFX, SST_2D_LAUNCH, *pos);
+ }
+ cnt-=size;
+ }
+}
+
diff --git a/src/tdfx_dga.c b/src/tdfx_dga.c
new file mode 100644
index 0000000..f0a97a3
--- /dev/null
+++ b/src/tdfx_dga.c
@@ -0,0 +1,210 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dga.c,v 1.6 2001/03/21 17:02:26 dawes Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "dgaproc.h"
+
+#include "tdfx.h"
+#include "vgaHW.h"
+
+static Bool TDFX_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
+ int *, int *, int *);
+static Bool TDFX_SetMode(ScrnInfoPtr, DGAModePtr);
+static int TDFX_GetViewport(ScrnInfoPtr);
+static void TDFX_SetViewport(ScrnInfoPtr, int, int, int);
+static void TDFX_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
+static void TDFX_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+static void TDFX_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
+ unsigned long);
+
+
+static
+DGAFunctionRec TDFX_DGAFuncs = {
+ TDFX_OpenFramebuffer,
+ 0,
+ TDFX_SetMode,
+ TDFX_SetViewport,
+ TDFX_GetViewport,
+ TDFXSync,
+ TDFX_FillRect,
+ TDFX_BlitRect,
+ TDFX_BlitTransRect
+};
+
+
+Bool
+TDFXDGAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX;
+ DisplayModePtr pMode, firstMode;
+ DGAModePtr modes=0, newmodes=0, currentMode;
+ int num=0;
+
+ pTDFX = TDFXPTR(pScrn);
+ pMode = firstMode = pScrn->modes;
+
+ while (pMode) {
+ newmodes = xrealloc(modes, (num+1)*sizeof(DGAModeRec));
+
+ if (!newmodes) {
+ xfree(modes);
+ return FALSE;
+ }
+ modes = newmodes;
+
+ currentMode = modes+num;
+ num++;
+ currentMode->mode = pMode;
+ currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
+ if (!pTDFX->NoAccel)
+ currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
+ if (pMode->Flags & V_DBLSCAN)
+ currentMode->flags |= DGA_DOUBLESCAN;
+ if (pMode->Flags & V_INTERLACE)
+ currentMode->flags |= DGA_INTERLACED;
+ currentMode->byteOrder = pScrn->imageByteOrder;
+ currentMode->depth = pScrn->depth;
+ currentMode->bitsPerPixel = pScrn->bitsPerPixel;
+ currentMode->red_mask = pScrn->mask.red;
+ currentMode->green_mask = pScrn->mask.green;
+ currentMode->blue_mask = pScrn->mask.blue;
+ currentMode->visualClass = pScrn->defaultVisual;
+ currentMode->viewportWidth = pMode->HDisplay;
+ currentMode->viewportHeight = pMode->VDisplay;
+ currentMode->xViewportStep = 1;
+ currentMode->yViewportStep = 1;
+ currentMode->viewportFlags = DGA_FLIP_RETRACE;
+ currentMode->offset = 0;
+ currentMode->address = pTDFX->FbBase;
+ currentMode->bytesPerScanline = ((pScrn->displayWidth*pTDFX->cpp)+3) & ~3L;
+ currentMode->imageWidth = pScrn->displayWidth;
+ currentMode->imageHeight = pTDFX->pixmapCacheLinesMax;
+ currentMode->pixmapWidth = currentMode->imageWidth;
+ currentMode->pixmapHeight = currentMode->imageHeight;
+ currentMode->maxViewportX = currentMode->imageWidth -
+ currentMode->viewportWidth;
+ /* this might need to get clamped to some maximum */
+ currentMode->maxViewportY = currentMode->imageHeight -
+ currentMode->viewportHeight;
+
+ pMode = pMode->next;
+ if (pMode == firstMode) break;
+ }
+
+ pTDFX->DGAModes = modes;
+
+ return DGAInit(pScreen, &TDFX_DGAFuncs, modes, num);
+}
+
+static Bool
+TDFX_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
+{
+ static DisplayModePtr OldModes[MAXSCREENS];
+ int index = pScrn->pScreen->myNum;
+
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ if (!pMode) { /* restore the original mode */
+ /* put the ScreenParameters back */
+ if(pTDFX->DGAactive) {
+ TDFXSwitchMode(index, OldModes[index], 0);
+ TDFXAdjustFrame(pScrn->pScreen->myNum, 0, 0, 0);
+ pTDFX->DGAactive = FALSE;
+ }
+ } else {
+ if (!pTDFX->DGAactive) { /* save the old parameters */
+ OldModes[index] = pScrn->currentMode;
+ pTDFX->DGAactive = TRUE;
+ }
+
+ TDFXSwitchMode(index, pMode->mode, 0);
+ }
+
+ return TRUE;
+}
+
+static int
+TDFX_GetViewport(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ return pTDFX->DGAViewportStatus;
+}
+
+static void
+TDFX_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ TDFXAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
+
+ /* fixme */
+ while(hwp->readST01(hwp) & 0x08);
+ while(!(hwp->readST01(hwp) & 0x08));
+
+ pTDFX->DGAViewportStatus = 0;
+}
+
+static void
+TDFX_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h,
+ unsigned long color)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ if (pTDFX->AccelInfoRec) {
+ (*pTDFX->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
+ (*pTDFX->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
+ }
+}
+
+static void
+TDFX_BlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h,
+ int dstx, int dsty)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ if (pTDFX->AccelInfoRec) {
+ int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
+ int ydir = (srcy < dsty) ? -1 : 1;
+
+ (*pTDFX->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, -1);
+ (*pTDFX->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h);
+ }
+}
+
+
+static void
+TDFX_BlitTransRect(
+ ScrnInfoPtr pScrn,
+ int srcx, int srcy,
+ int w, int h,
+ int dstx, int dsty,
+ unsigned long color
+){
+ /* this one should be separate since the XAA function would
+ prohibit usage of ~0 as the key */
+}
+
+
+static Bool
+TDFX_OpenFramebuffer(
+ ScrnInfoPtr pScrn,
+ char **name,
+ unsigned char **mem,
+ int *size,
+ int *offset,
+ int *flags
+){
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ *name = NULL; /* no special device */
+ *mem = (unsigned char*)pTDFX->LinearAddr[0] + pTDFX->fbOffset;
+ *size = pTDFX->FbMapSize;
+ *offset = /* pTDFX->fbOffset */ 0 ; /* DGA is broken */
+ *flags = DGA_NEED_ROOT;
+
+ return TRUE;
+}
diff --git a/src/tdfx_dri.c b/src/tdfx_dri.c
new file mode 100644
index 0000000..0df0b43
--- /dev/null
+++ b/src/tdfx_dri.c
@@ -0,0 +1,658 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.c,v 1.25 2003/02/08 21:26:59 dawes Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Priv.h"
+#include "xf86PciInfo.h"
+#include "xf86Pci.h"
+#include "fb.h"
+#include "miline.h"
+#include "GL/glxtokens.h"
+#include "tdfx.h"
+#include "tdfx_dri.h"
+#include "tdfx_dripriv.h"
+
+static char TDFXKernelDriverName[] = "tdfx";
+static char TDFXClientDriverName[] = "tdfx";
+
+static Bool TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drmContext hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore);
+static void TDFXDestroyContext(ScreenPtr pScreen, drmContext hwContext,
+ DRIContextType contextStore);
+static void TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType readContextType,
+ void *readContextStore,
+ DRIContextType writeContextType,
+ void *writeContextStore);
+static Bool TDFXDRIOpenFullScreen(ScreenPtr pScreen);
+static Bool TDFXDRICloseFullScreen(ScreenPtr pScreen);
+static void TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
+static void TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index);
+static void TDFXDRITransitionTo2d(ScreenPtr pScreen);
+static void TDFXDRITransitionTo3d(ScreenPtr pScreen);
+
+static Bool
+TDFXInitVisualConfigs(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ int numConfigs = 0;
+ __GLXvisualConfig *pConfigs = 0;
+ TDFXConfigPrivPtr pTDFXConfigs = 0;
+ TDFXConfigPrivPtr *pTDFXConfigPtrs = 0;
+ int i, db, stencil, accum, depth;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ case 16:
+ numConfigs = 16;
+
+ if (!(pConfigs = (__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),
+ numConfigs))) {
+ return FALSE;
+ }
+ if (!(pTDFXConfigs = (TDFXConfigPrivPtr)xcalloc(sizeof(TDFXConfigPrivRec),
+ numConfigs))) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+ if (!(pTDFXConfigPtrs = (TDFXConfigPrivPtr*)xcalloc(sizeof(TDFXConfigPrivPtr),
+ numConfigs))) {
+ xfree(pConfigs);
+ xfree(pTDFXConfigs);
+ return FALSE;
+ }
+ for (i=0; i<numConfigs; i++)
+ pTDFXConfigPtrs[i] = &pTDFXConfigs[i];
+
+ i=0;
+ depth=1;
+ for (db = 0; db <=1; db++) {
+ for (depth = 0; depth<=1; depth++) {
+ for (accum = 0; accum <= 1; accum++) {
+ for (stencil = 0; stencil <= 1; stencil++) {
+ pConfigs[i].vid = -1;
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 5;
+ pConfigs[i].greenSize = 6;
+ pConfigs[i].blueSize = 5;
+ pConfigs[i].redMask = 0x0000F800;
+ pConfigs[i].greenMask = 0x000007E0;
+ pConfigs[i].blueMask = 0x0000001F;
+ pConfigs[i].alphaMask = 0;
+ if (accum) {
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ if (db)
+ pConfigs[i].doubleBuffer = TRUE;
+ else
+ pConfigs[i].doubleBuffer = FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 16;
+ if (depth) {
+ if (pTDFX->cpp>2)
+ pConfigs[i].depthSize = 24;
+ else
+ pConfigs[i].depthSize = 16;
+ } else {
+ pConfigs[i].depthSize = 0;
+ }
+ if (stencil)
+ pConfigs[i].stencilSize = 8;
+ else
+ pConfigs[i].stencilSize = 0;
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (stencil || accum)
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ else
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ pConfigs[i].transparentPixel = 0;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ }
+ if (i!=numConfigs) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] TDFXInitVisualConfigs: wrong number of visuals\n");
+ return FALSE;
+ }
+ break; /* 16bpp */
+
+ case 24:
+ case 32:
+ numConfigs = 8;
+
+ pConfigs = (__GLXvisualConfig*) xcalloc(sizeof(__GLXvisualConfig), numConfigs);
+ if (!pConfigs)
+ return FALSE;
+
+ pTDFXConfigs = (TDFXConfigPrivPtr) xcalloc(sizeof(TDFXConfigPrivRec), numConfigs);
+ if (!pTDFXConfigs) {
+ xfree(pConfigs);
+ return FALSE;
+ }
+
+ pTDFXConfigPtrs = (TDFXConfigPrivPtr *) xcalloc(sizeof(TDFXConfigPrivPtr), numConfigs);
+ if (!pTDFXConfigPtrs) {
+ xfree(pConfigs);
+ xfree(pTDFXConfigs);
+ return FALSE;
+ }
+
+ for (i = 0; i < numConfigs; i++)
+ pTDFXConfigPtrs[i] = &pTDFXConfigs[i];
+
+ i=0;
+ for (db = 0; db <=1; db++) {
+ for (depth = 0; depth<=1; depth++) {
+ /*stencil = depth;*/ /* Z and stencil share the same memory */
+ for (accum = 0; accum <= 1; accum++) {
+ /*for (stencil = 0; stencil <=1; stencil++) {*/
+ stencil = depth;
+ pConfigs[i].vid = -1;
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 8;
+ pConfigs[i].greenSize = 8;
+ pConfigs[i].blueSize = 8;
+ pConfigs[i].alphaSize = (pScrn->bitsPerPixel==32) ? 8 : 0;
+ pConfigs[i].redMask = 0x00ff0000;
+ pConfigs[i].greenMask = 0x0000ff00;
+ pConfigs[i].blueMask = 0x000000ff;
+ pConfigs[i].alphaMask = (pScrn->bitsPerPixel==32) ? 0xff000000 : 0;
+ if (accum) {
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = (pScrn->bitsPerPixel==32) ? 16 : 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ if (db)
+ pConfigs[i].doubleBuffer = TRUE;
+ else
+ pConfigs[i].doubleBuffer = FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = (pScrn->bitsPerPixel==32) ? 32 : 24;
+ if (depth) {
+ if (pTDFX->cpp > 2)
+ pConfigs[i].depthSize = 24;
+ else
+ pConfigs[i].depthSize = 16;
+ } else {
+ pConfigs[i].depthSize = 0;
+ }
+ if (stencil)
+ pConfigs[i].stencilSize = 8;
+ else
+ pConfigs[i].stencilSize = 0;
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if (accum)
+ pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
+ else
+ pConfigs[i].visualRating = GLX_NONE_EXT;
+ pConfigs[i].transparentPixel = 0;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ /*}*/
+ }
+ }
+ }
+ if (i!=numConfigs) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] TDFXInitVisualConfigs: wrong number of visuals\n");
+ return FALSE;
+ }
+ break;
+ }
+ pTDFX->numVisualConfigs = numConfigs;
+ pTDFX->pVisualConfigs = pConfigs;
+ pTDFX->pVisualConfigsPriv = pTDFXConfigs;
+ GlxSetVisualConfigs(numConfigs, pConfigs, (void**)pTDFXConfigPtrs);
+ return TRUE;
+}
+
+static void
+TDFXDoWakeupHandler(int screenNum, pointer wakeupData, unsigned long result,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[screenNum];
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ TDFXNeedSync(pScrn);
+}
+
+static void
+TDFXDoBlockHandler(int screenNum, pointer blockData, pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[screenNum];
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+ TDFXCheckSync(pScrn);
+}
+
+Bool TDFXDRIScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ DRIInfoPtr pDRIInfo;
+ TDFXDRIPtr pTDFXDRI;
+ Bool bppOk = FALSE;
+
+ switch (pScrn->bitsPerPixel) {
+ case 16:
+ bppOk = TRUE;
+ break;
+ case 32:
+ if (pTDFX->ChipType > PCI_CHIP_VOODOO3) {
+ bppOk = TRUE;
+ }
+ break;
+ }
+ if (!bppOk) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] tdfx DRI not supported in %d bpp mode, disabling DRI.\n",
+ (pScrn->bitsPerPixel));
+ if (pTDFX->ChipType <= PCI_CHIP_VOODOO3) {
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[dri] To use DRI, invoke the server using 16 bpp\n"
+ "\t(-depth 15 or -depth 16).\n");
+ } else {
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[dri] To use DRI, invoke the server using 16 bpp\n"
+ "\t(-depth 15 or -depth 16) or 32 bpp (-depth 24 -fbbpp 32).\n");
+ }
+ return FALSE;
+ }
+
+ /* Check that the GLX, DRI, and DRM modules have been loaded by testing
+ for canonical symbols in each module. */
+ if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIScreenInit")) return FALSE;
+ if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE;
+ if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "TDFXDRIScreenInit failed (libdri.a too old)\n");
+ return FALSE;
+ }
+
+ /* Check the DRI version */
+ {
+ int major, minor, patch;
+ DRIQueryVersion(&major, &minor, &patch);
+ if (major != 4 || minor < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] TDFXDRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libDRI version is %d.%d.%d but version 4.0.x is needed.\n"
+ "[dri] Disabling the DRI.\n",
+ major, minor, patch);
+ return FALSE;
+ }
+ }
+
+ pDRIInfo = DRICreateInfoRec();
+ if (!pDRIInfo) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRICreateInfoRect() failed, disabling DRI.\n");
+ return FALSE;
+ }
+
+ pTDFX->pDRIInfo = pDRIInfo;
+
+ pDRIInfo->drmDriverName = TDFXKernelDriverName;
+ pDRIInfo->clientDriverName = TDFXClientDriverName;
+ pDRIInfo->busIdString = xalloc(64);
+ sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
+ ((pciConfigPtr)pTDFX->PciInfo->thisCard)->busnum,
+ ((pciConfigPtr)pTDFX->PciInfo->thisCard)->devnum,
+ ((pciConfigPtr)pTDFX->PciInfo->thisCard)->funcnum);
+ pDRIInfo->ddxDriverMajorVersion = TDFX_MAJOR_VERSION;
+ pDRIInfo->ddxDriverMinorVersion = TDFX_MINOR_VERSION;
+ pDRIInfo->ddxDriverPatchVersion = TDFX_PATCHLEVEL;
+ pDRIInfo->frameBufferPhysicalAddress = pTDFX->LinearAddr[0];
+ pDRIInfo->frameBufferSize = pTDFX->FbMapSize;
+ pDRIInfo->frameBufferStride = pTDFX->stride;
+ pDRIInfo->ddxDrawableTableEntry = TDFX_MAX_DRAWABLES;
+
+ pDRIInfo->wrap.ValidateTree = 0;
+ pDRIInfo->wrap.PostValidateTree = 0;
+ pDRIInfo->wrap.BlockHandler = TDFXDoBlockHandler;
+ pDRIInfo->wrap.WakeupHandler = TDFXDoWakeupHandler;
+
+ if (SAREA_MAX_DRAWABLES < TDFX_MAX_DRAWABLES)
+ pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
+ else
+ pDRIInfo->maxDrawableTableEntry = TDFX_MAX_DRAWABLES;
+
+#ifdef NOT_DONE
+ /* FIXME need to extend DRI protocol to pass this size back to client
+ * for SAREA mapping that includes a device private record
+ */
+ pDRIInfo->SAREASize =
+ ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */
+ /* + shared memory device private rec */
+#else
+ /* For now the mapping works by using a fixed size defined
+ * in the SAREA header
+ */
+ if (sizeof(XF86DRISAREARec)+sizeof(TDFXSAREAPriv)>SAREA_MAX) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "Data does not fit in SAREA\n");
+ return FALSE;
+ }
+ pDRIInfo->SAREASize = SAREA_MAX;
+#endif
+
+ if (!(pTDFXDRI = (TDFXDRIPtr)xcalloc(sizeof(TDFXDRIRec),1))) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRI memory allocation failed, disabling DRI.\n");
+ DRIDestroyInfoRec(pTDFX->pDRIInfo);
+ pTDFX->pDRIInfo=0;
+ return FALSE;
+ }
+ pDRIInfo->devPrivate = pTDFXDRI;
+ pDRIInfo->devPrivateSize = sizeof(TDFXDRIRec);
+ pDRIInfo->contextSize = sizeof(TDFXDRIContextRec);
+
+ pDRIInfo->CreateContext = TDFXCreateContext;
+ pDRIInfo->DestroyContext = TDFXDestroyContext;
+ pDRIInfo->SwapContext = TDFXDRISwapContext;
+ pDRIInfo->InitBuffers = TDFXDRIInitBuffers;
+ pDRIInfo->MoveBuffers = TDFXDRIMoveBuffers;
+ pDRIInfo->OpenFullScreen = TDFXDRIOpenFullScreen;
+ pDRIInfo->CloseFullScreen = TDFXDRICloseFullScreen;
+ pDRIInfo->TransitionTo2d = TDFXDRITransitionTo2d;
+ pDRIInfo->TransitionTo3d = TDFXDRITransitionTo3d;
+ pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
+
+ pDRIInfo->createDummyCtx = FALSE;
+ pDRIInfo->createDummyCtxPriv = FALSE;
+
+ if (!DRIScreenInit(pScreen, pDRIInfo, &pTDFX->drmSubFD)) {
+ xfree(pDRIInfo->devPrivate);
+ pDRIInfo->devPrivate=0;
+ DRIDestroyInfoRec(pTDFX->pDRIInfo);
+ pTDFX->pDRIInfo=0;
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit failed, disabling DRI.\n");
+
+ return FALSE;
+ }
+
+ /* Check the TDFX DRM version */
+ {
+ drmVersionPtr version = drmGetVersion(pTDFX->drmSubFD);
+ if (version) {
+ if (version->version_major != 1 ||
+ version->version_minor < 0) {
+ /* incompatible drm version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] TDFXDRIScreenInit failed because of a version mismatch.\n"
+ "[dri] tdfx.o kernel module version is %d.%d.%d but version 1.0.x is needed.\n"
+ "[dri] Disabling the DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel);
+ TDFXDRICloseScreen(pScreen);
+ drmFreeVersion(version);
+ return FALSE;
+ }
+ drmFreeVersion(version);
+ }
+ }
+
+ pTDFXDRI->regsSize=TDFXIOMAPSIZE;
+ if (drmAddMap(pTDFX->drmSubFD, (drmHandle)pTDFX->MMIOAddr[0],
+ pTDFXDRI->regsSize, DRM_REGISTERS, 0, &pTDFXDRI->regs)<0) {
+ TDFXDRICloseScreen(pScreen);
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap failed, disabling DRI.\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08lx\n",
+ pTDFXDRI->regs);
+
+ if (!(TDFXInitVisualConfigs(pScreen))) {
+ TDFXDRICloseScreen(pScreen);
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "TDFXInitVisualConfigs failed, disabling DRI.\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "visual configs initialized\n" );
+
+ return TRUE;
+}
+
+void
+TDFXDRICloseScreen(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ DRICloseScreen(pScreen);
+
+ if (pTDFX->pDRIInfo) {
+ if (pTDFX->pDRIInfo->devPrivate) {
+ xfree(pTDFX->pDRIInfo->devPrivate);
+ pTDFX->pDRIInfo->devPrivate=0;
+ }
+ DRIDestroyInfoRec(pTDFX->pDRIInfo);
+ pTDFX->pDRIInfo=0;
+ }
+ if (pTDFX->pVisualConfigs) xfree(pTDFX->pVisualConfigs);
+ if (pTDFX->pVisualConfigsPriv) xfree(pTDFX->pVisualConfigsPriv);
+}
+
+static Bool
+TDFXCreateContext(ScreenPtr pScreen, VisualPtr visual,
+ drmContext hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore)
+{
+ return TRUE;
+}
+
+static void
+TDFXDestroyContext(ScreenPtr pScreen, drmContext hwContext,
+ DRIContextType contextStore)
+{
+}
+
+Bool
+TDFXDRIFinishScreenInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXDRIPtr pTDFXDRI;
+
+ pTDFX->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
+
+ pTDFXDRI=(TDFXDRIPtr)pTDFX->pDRIInfo->devPrivate;
+ pTDFXDRI->deviceID=pTDFX->PciInfo->chipType;
+ pTDFXDRI->width=pScrn->virtualX;
+ pTDFXDRI->height=pScrn->virtualY;
+ pTDFXDRI->mem=pScrn->videoRam*1024;
+ pTDFXDRI->cpp=pTDFX->cpp;
+ pTDFXDRI->stride=pTDFX->stride;
+ pTDFXDRI->fifoOffset=pTDFX->fifoOffset;
+ pTDFXDRI->fifoSize=pTDFX->fifoSize;
+ pTDFXDRI->textureOffset=pTDFX->texOffset;
+ pTDFXDRI->textureSize=pTDFX->texSize;
+ pTDFXDRI->fbOffset=pTDFX->fbOffset;
+ pTDFXDRI->backOffset=pTDFX->backOffset;
+ pTDFXDRI->depthOffset=pTDFX->depthOffset;
+ pTDFXDRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
+ return DRIFinishScreenInit(pScreen);
+}
+
+static void
+TDFXDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
+ DRIContextType oldContextType, void *oldContext,
+ DRIContextType newContextType, void *newContext)
+{
+}
+
+static void
+TDFXDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ BoxPtr pbox;
+ int nbox;
+
+ /* It looks nicer if these start out black */
+ pbox = REGION_RECTS(prgn);
+ nbox = REGION_NUM_RECTS(prgn);
+
+ TDFXSetupForSolidFill(pScrn, 0, GXcopy, -1);
+ while (nbox--) {
+ TDFXSelectBuffer(pTDFX, TDFX_BACK);
+ TDFXSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
+ pbox->x2-pbox->x1, pbox->y2-pbox->y1);
+ TDFXSelectBuffer(pTDFX, TDFX_DEPTH);
+ TDFXSubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
+ pbox->x2-pbox->x1, pbox->y2-pbox->y1);
+ pbox++;
+ }
+ TDFXSelectBuffer(pTDFX, TDFX_FRONT);
+
+ pTDFX->AccelInfoRec->NeedToSync = TRUE;
+}
+
+static void
+TDFXDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 index)
+{
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ int dx, dy, xdir, ydir, i, x, y, nbox;
+ BoxPtr pbox;
+
+ dx = pParent->drawable.x - ptOldOrg.x;
+ dy = pParent->drawable.y - ptOldOrg.y;
+
+ DRIMoveBuffersHelper(pScreen, dx, dy, &xdir, &ydir, prgnSrc);
+
+ pbox = REGION_RECTS(prgnSrc);
+ nbox = REGION_NUM_RECTS(prgnSrc);
+
+ TDFXSetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, ~0, -1);
+
+ TDFXSelectBuffer(pTDFX, TDFX_BACK);
+ for(i = 0; i < nbox; i++) {
+ x = pbox[i].x1;
+ y = pbox[i].y1;
+ TDFXSubsequentScreenToScreenCopy(pScrn, x, y, x+dx, y+dy,
+ pbox[i].x2 - x, pbox[i].y2 - y);
+ }
+
+ TDFXSelectBuffer(pTDFX, TDFX_DEPTH);
+ for(i = 0; i < nbox; i++) {
+ x = pbox[i].x1;
+ y = pbox[i].y1;
+ TDFXSubsequentScreenToScreenCopy(pScrn, x, y, x+dx, y+dy,
+ pbox[i].x2 - x, pbox[i].y2 - y);
+ }
+
+ TDFXSelectBuffer(pTDFX, TDFX_FRONT);
+
+ pTDFX->AccelInfoRec->NeedToSync = TRUE;
+}
+
+static Bool
+TDFXDRIOpenFullScreen(ScreenPtr pScreen)
+{
+#if 0
+ ScrnInfoPtr pScrn;
+ TDFXPtr pTDFX;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO, "OpenFullScreen\n");
+ pScrn = xf86Screens[pScreen->myNum];
+ pTDFX=TDFXPTR(pScrn);
+ if (pTDFX->numChips>1) {
+ TDFXSetupSLI(pScrn);
+ }
+#endif
+ return TRUE;
+}
+
+static Bool
+TDFXDRICloseFullScreen(ScreenPtr pScreen)
+{
+#if 0
+ ScrnInfoPtr pScrn;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO, "CloseFullScreen\n");
+ pScrn = xf86Screens[pScreen->myNum];
+ TDFXDisableSLI(pScrn);
+#endif
+ return TRUE;
+}
+
+static void
+TDFXDRITransitionTo2d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ xf86FreeOffscreenArea(pTDFX->reservedArea);
+}
+
+static void
+TDFXDRITransitionTo3d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ FBAreaPtr pArea;
+
+ if(pTDFX->overlayBuffer) {
+ xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
+ pTDFX->overlayBuffer = NULL;
+ }
+
+ if(pTDFX->overlayBuffer2) {
+ xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
+ pTDFX->overlayBuffer2 = NULL;
+ }
+
+ if(pTDFX->textureBuffer) {
+ xf86FreeOffscreenArea(pTDFX->textureBuffer);
+ pTDFX->textureBuffer = NULL;
+ }
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+
+ pArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
+ pTDFX->pixmapCacheLinesMin,
+ pScrn->displayWidth, NULL, NULL, NULL);
+ pTDFX->reservedArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
+ pTDFX->pixmapCacheLinesMax - pTDFX->pixmapCacheLinesMin,
+ pScrn->displayWidth, NULL, NULL, NULL);
+ xf86FreeOffscreenArea(pArea);
+}
diff --git a/src/tdfx_dri.h b/src/tdfx_dri.h
new file mode 100644
index 0000000..956b7e7
--- /dev/null
+++ b/src/tdfx_dri.h
@@ -0,0 +1,28 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.h,v 1.5 2001/03/21 17:02:26 dawes Exp $ */
+
+#ifndef _TDFX_DRI_
+#define _TDFX_DRI_
+
+#include "xf86drm.h"
+
+typedef struct {
+ drmHandle regs;
+ drmSize regsSize;
+ drmAddress regsMap;
+ int deviceID;
+ int width;
+ int height;
+ int mem;
+ int cpp;
+ int stride;
+ int fifoOffset;
+ int fifoSize;
+ int fbOffset;
+ int backOffset;
+ int depthOffset;
+ int textureOffset;
+ int textureSize;
+ unsigned int sarea_priv_offset;
+} TDFXDRIRec, *TDFXDRIPtr;
+
+#endif
diff --git a/src/tdfx_dripriv.h b/src/tdfx_dripriv.h
new file mode 100644
index 0000000..69f0d04
--- /dev/null
+++ b/src/tdfx_dripriv.h
@@ -0,0 +1,24 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dripriv.h,v 1.2 1999/12/14 01:33:50 robin Exp $ */
+
+#ifndef _TDFX_DRIPRIV_H_
+#define _TDFX_DRIPRIV_H_
+
+#define TDFX_MAX_DRAWABLES 256
+
+extern void GlxSetVisualConfigs(
+ int nconfigs,
+ __GLXvisualConfig *configs,
+ void **configprivs
+);
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} TDFXConfigPrivRec, *TDFXConfigPrivPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} TDFXDRIContextRec, *TDFXDRIContextPtr;
+
+#endif
diff --git a/src/tdfx_driver.c b/src/tdfx_driver.c
new file mode 100644
index 0000000..0c0ce80
--- /dev/null
+++ b/src/tdfx_driver.c
@@ -0,0 +1,2496 @@
+#define USE_INT10 1
+#define USE_PCIVGAIO 1
+
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_driver.c,v 1.92 2002/11/25 14:05:00 eich Exp $ */
+
+/*
+ * Authors:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+/*
+ * This server does not support these XFree 4.0 features yet
+ * DDC2 (requires I2C)
+ * shadowFb (if requested or acceleration is off)
+ * Overlay planes
+ */
+
+/*
+ * These are X and server generic header files.
+ */
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86RAC.h"
+#include "vbe.h"
+#include "xf86cmap.h"
+
+/* If the driver uses port I/O directly, it needs: */
+
+#include "compiler.h"
+
+/* Drivers using the mi implementation of backing store need: */
+
+#include "mibstore.h"
+
+/* All drivers using the vgahw module need this */
+/* This driver needs to be modified to not use vgaHW for multihead operation */
+#include "vgaHW.h"
+
+/* Drivers using the mi SW cursor need: */
+
+#include "mipointer.h"
+
+/* Drivers using the mi colourmap code need: */
+
+#include "micmap.h"
+
+/* Required for line biases */
+#include "miline.h"
+
+#include "fb.h"
+
+/* !!! These need to be checked !!! */
+#if 0
+#define _XF86DGA_SERVER_
+#include "extensions/xf86dgastr.h"
+#endif
+
+/* The driver's own header file: */
+
+#include "tdfx.h"
+
+#include "miscstruct.h"
+#include "dixstruct.h"
+
+#include "xf86xv.h"
+#include "Xv.h"
+
+#ifdef XF86DRI
+#include "dri.h"
+#endif
+
+/* Required Functions: */
+
+static const OptionInfoRec * TDFXAvailableOptions(int chipid, int busid);
+/* Print a driver identifying message. */
+static void TDFXIdentify(int flags);
+
+/* Identify if there is any hardware present that I know how to drive. */
+static Bool TDFXProbe(DriverPtr drv, int flags);
+
+/* Process the config file and see if we have a valid configuration */
+static Bool TDFXPreInit(ScrnInfoPtr pScrn, int flags);
+
+/* Initialize a screen */
+static Bool TDFXScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
+
+/* Enter from a virtual terminal */
+static Bool TDFXEnterVT(int scrnIndex, int flags);
+
+/* Leave to a virtual terminal */
+static void TDFXLeaveVT(int scrnIndex, int flags);
+
+/* Close down each screen we initialized */
+static Bool TDFXCloseScreen(int scrnIndex, ScreenPtr pScreen);
+
+/* Change screensaver state */
+static Bool TDFXSaveScreen(ScreenPtr pScreen, int mode);
+
+/* Cleanup server private data */
+static void TDFXFreeScreen(int scrnIndex, int flags);
+
+/* Check if a mode is valid on the hardware */
+static int TDFXValidMode(int scrnIndex, DisplayModePtr mode, Bool
+ verbose, int flags);
+
+static void TDFXBlockHandler(int, pointer, pointer, pointer);
+
+/* Switch to various Display Power Management System levels */
+static void TDFXDisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagermentMode, int flags);
+
+DriverRec TDFX = {
+ TDFX_VERSION,
+ TDFX_DRIVER_NAME,
+ TDFXIdentify,
+ TDFXProbe,
+ TDFXAvailableOptions,
+ NULL,
+ 0
+};
+
+/* Chipsets */
+static SymTabRec TDFXChipsets[] = {
+ { PCI_CHIP_BANSHEE, "3dfx Banshee"},
+ { PCI_CHIP_VOODOO3, "3dfx Voodoo3"},
+ { PCI_CHIP_VOODOO5, "3dfx Voodoo5"},
+ { -1, NULL }
+};
+
+static PciChipsets TDFXPciChipsets[] = {
+ { PCI_CHIP_BANSHEE, PCI_CHIP_BANSHEE, RES_SHARED_VGA },
+ { PCI_CHIP_VOODOO3, PCI_CHIP_VOODOO3, RES_SHARED_VGA },
+ { PCI_CHIP_VOODOO5, PCI_CHIP_VOODOO5, RES_SHARED_VGA },
+ { -1, -1, RES_UNDEFINED }
+};
+
+/* !!! Do we want an option for alternate clocking? !!! */
+
+typedef enum {
+ OPTION_NOACCEL,
+ OPTION_SW_CURSOR,
+ OPTION_USE_PIO,
+ OPTION_SHOWCACHE,
+ OPTION_VIDEO_KEY,
+ OPTION_NO_SLI,
+ OPTION_TEXTURED_VIDEO,
+ OPTION_DRI
+} TDFXOpts;
+
+static const OptionInfoRec TDFXOptions[] = {
+ { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_USE_PIO, "UsePIO", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE},
+ { OPTION_NO_SLI, "NoSLI", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_TEXTURED_VIDEO, "TexturedVideo", OPTV_BOOLEAN, {1}, FALSE},
+ { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
+ { -1, NULL, OPTV_NONE, {0}, FALSE}
+};
+
+static const char *vgahwSymbols[] = {
+ "vgaHWEnable",
+ "vgaHWFreeHWRec",
+ "vgaHWGetHWRec",
+ "vgaHWGetIOBase",
+ "vgaHWGetIndex",
+ "vgaHWInit",
+ "vgaHWLock",
+ "vgaHWMapMem",
+ "vgaHWProtect",
+ "vgaHWRestore",
+ "vgaHWSave",
+ "vgaHWSeqReset",
+ "vgaHWUnlock",
+ 0
+};
+
+static const char *ramdacSymbols[] = {
+ "xf86CreateCursorInfoRec",
+ "xf86InitCursor",
+ NULL
+};
+
+static const char *ddcSymbols[] = {
+ "xf86PrintEDID",
+ "xf86SetDDCproperties",
+ NULL
+};
+
+static const char *fbSymbols[] = {
+ "fbPictureInit",
+ "fbScreenInit",
+ NULL
+};
+
+static const char *xaaSymbols[] = {
+ "XAACreateInfoRec",
+ "XAADestroyInfoRec",
+ "XAAInit",
+ "XAAReverseBitOrder",
+ NULL
+};
+
+static const char *vbeSymbols[] = {
+ "VBEInit",
+ "vbeDoEDID",
+ "vbeFree",
+ NULL
+};
+
+static const char *int10Symbols[] = {
+ "xf86FreeInt10",
+ "xf86InitInt10",
+ NULL
+};
+
+#ifdef XF86DRI
+static const char *drmSymbols[] = {
+ "drmAddMap",
+ "drmFreeVersion",
+ "drmGetVersion",
+ NULL
+};
+
+static const char *driSymbols[] = {
+ "DRICloseScreen",
+ "DRICreateInfoRec",
+ "DRIDestroyInfoRec",
+ "DRIFinishScreenInit",
+ "DRIGetSAREAPrivate",
+ "DRILock",
+ "DRIMoveBuffersHelper",
+ "DRIQueryVersion",
+ "DRIScreenInit",
+ "DRIUnlock",
+ "GlxSetVisualConfigs",
+ NULL
+};
+
+#endif
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(tdfxSetup);
+
+static XF86ModuleVersionInfo tdfxVersRec =
+{
+ "tdfx",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ TDFX_MAJOR_VERSION, TDFX_MINOR_VERSION, TDFX_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0,0,0,0}
+};
+
+XF86ModuleData tdfxModuleData = {&tdfxVersRec, tdfxSetup, 0};
+
+static pointer
+tdfxSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ /* This module should be loaded only once, but check to be sure. */
+
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&TDFX, module, 0);
+
+ /*
+ * Modules that this driver always requires may be loaded here
+ * by calling LoadSubModule().
+ */
+
+ /*
+ * Tell the loader about symbols from other modules that this module
+ * might refer to.
+ */
+ LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols,
+ ramdacSymbols, vbeSymbols, int10Symbols,
+#ifdef XF86DRI
+ drmSymbols, driSymbols,
+#endif
+ NULL);
+
+ /*
+ * The return value must be non-NULL on success even though there
+ * is no TearDownProc.
+ */
+ return (pointer)1;
+ } else {
+ if (errmaj) *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+
+#endif
+
+/*
+ * TDFXGetRec and TDFXFreeRec --
+ *
+ * Private data for the driver is stored in the screen structure.
+ * These two functions create and destroy that private data.
+ *
+ */
+static Bool
+TDFXGetRec(ScrnInfoPtr pScrn) {
+ if (pScrn->driverPrivate) return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(TDFXRec), 1);
+ return TRUE;
+}
+
+static void
+TDFXFreeRec(ScrnInfoPtr pScrn) {
+ if (!pScrn) return;
+ if (!pScrn->driverPrivate) return;
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate=0;
+}
+
+/*
+ * TDFXIdentify --
+ *
+ * Returns the string name for the driver based on the chipset. In this
+ * case it will always be an TDFX, so we can return a static string.
+ *
+ */
+static void
+TDFXIdentify(int flags) {
+ xf86PrintChipsets(TDFX_NAME, "Driver for 3dfx Banshee/Voodoo3 chipsets", TDFXChipsets);
+}
+
+static const OptionInfoRec *
+TDFXAvailableOptions(int chipid, int busid)
+{
+ return TDFXOptions;
+}
+
+static void
+TDFXProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+ if (xf86LoadSubModule(pScrn, "vbe"))
+ {
+ pVbe = VBEInit(NULL,index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ }
+}
+
+/*
+ * TDFXProbe --
+ *
+ * Look through the PCI bus to find cards that are TDFX boards.
+ * Setup the dispatch table for the rest of the driver functions.
+ *
+ */
+static Bool
+TDFXProbe(DriverPtr drv, int flags) {
+ int i, numUsed, numDevSections, *usedChips;
+ GDevPtr *devSections;
+ Bool foundScreen = FALSE;
+
+ TDFXTRACE("TDFXProbe start\n");
+ /*
+ Find the config file Device sections that match this
+ driver, and return if there are none.
+ */
+ if ((numDevSections = xf86MatchDevice(TDFX_DRIVER_NAME, &devSections))<=0) {
+ return FALSE;
+ }
+
+ /*
+ Since these Probing is just checking the PCI data the server already
+ collected.
+ */
+ if (!xf86GetPciVideoInfo()) return FALSE;
+
+ numUsed = xf86MatchPciInstances(TDFX_NAME, PCI_VENDOR_3DFX,
+ TDFXChipsets, TDFXPciChipsets,
+ devSections, numDevSections,
+ drv, &usedChips);
+
+ xfree(devSections);
+ if (numUsed<=0) return FALSE;
+
+ if (flags & PROBE_DETECT)
+ foundScreen = TRUE;
+ else for (i=0; i<numUsed; i++) {
+ ScrnInfoPtr pScrn;
+
+ /* Allocate new ScrnInfoRec and claim the slot */
+ pScrn = NULL;
+ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
+ TDFXPciChipsets, NULL, NULL, NULL, NULL, NULL))) {
+
+ pScrn->driverVersion = TDFX_VERSION;
+ pScrn->driverName = TDFX_DRIVER_NAME;
+ pScrn->name = TDFX_NAME;
+ pScrn->Probe = TDFXProbe;
+ pScrn->PreInit = TDFXPreInit;
+ pScrn->ScreenInit = TDFXScreenInit;
+ pScrn->SwitchMode = TDFXSwitchMode;
+ pScrn->AdjustFrame = TDFXAdjustFrame;
+ pScrn->EnterVT = TDFXEnterVT;
+ pScrn->LeaveVT = TDFXLeaveVT;
+ pScrn->FreeScreen = TDFXFreeScreen;
+ pScrn->ValidMode = TDFXValidMode;
+ foundScreen = TRUE;
+ }
+ }
+ xfree(usedChips);
+
+ return foundScreen;
+}
+
+static int
+TDFXCountRam(ScrnInfoPtr pScrn) {
+ TDFXPtr pTDFX;
+ int vmemSize;
+ int vmemType=-1; /* SDRAM or SGRAM */
+
+ pTDFX = TDFXPTR(pScrn);
+ TDFXTRACE("TDFXCountRam start\n");
+ vmemSize=0;
+ if (pTDFX->PIOBase[0]) {
+ CARD32
+ partSize, /* size of SGRAM chips in Mbits */
+ nChips, /* # chips of SDRAM/SGRAM */
+ banks, /* Number of banks of chips */
+ dramInit0_strap,
+ dramInit1_strap,
+ dramInit1,
+ miscInit1;
+
+ /* determine memory type: SDRAM or SGRAM */
+ vmemType = MEM_TYPE_SGRAM;
+ dramInit1_strap = pTDFX->readLong(pTDFX, DRAMINIT1);
+ dramInit1_strap &= SST_MCTL_TYPE_SDRAM;
+ if (dramInit1_strap) vmemType = MEM_TYPE_SDRAM;
+
+ /* set memory interface delay values and enable refresh */
+ /* these apply to all RAM vendors */
+ dramInit1 = 0x0;
+ dramInit1 |= 2<<SST_SGRAM_OFLOP_DEL_ADJ_SHIFT;
+ dramInit1 |= SST_SGRAM_CLK_NODELAY;
+ dramInit1 |= SST_DRAM_REFRESH_EN;
+ dramInit1 |= (0x18 << SST_DRAM_REFRESH_VALUE_SHIFT) & SST_DRAM_REFRESH_VALUE;
+ dramInit1 &= ~SST_MCTL_TYPE_SDRAM;
+ dramInit1 |= dramInit1_strap;
+
+ /* Some information about the timing register (for later debugging) */
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "DRAMINIT1 read 0x%x, programming 0x%x (not Banshee)\n",
+ pTDFX->readLong(pTDFX, DRAMINIT1), dramInit1);
+
+ /*
+ * Here we don't whack the timing register on the Banshee boards as the
+ * BIOS has done a perfectly good job. As Banshee boards were made by
+ * different manufacturers we don't touch this, but carry on whacking it
+ * for Voodoo3 and Voodoo5 boards, as we've never had a problem with them.
+ * I guess this could be removed for all boards as we probably shouldn't
+ * be doing this to the V3/V5 boards too.
+ */
+ if (pTDFX->ChipType != PCI_CHIP_BANSHEE)
+ pTDFX->writeLong(pTDFX, DRAMINIT1, dramInit1);
+
+ /* determine memory size from strapping pins (dramInit0 and dramInit1) */
+ dramInit0_strap = pTDFX->readLong(pTDFX, DRAMINIT0);
+
+ if (pTDFX->ChipType<=PCI_CHIP_VOODOO3) { /* Banshee/V3 */
+ if (vmemType == MEM_TYPE_SDRAM) {
+ vmemSize = 16;
+ } else {
+ nChips = ((dramInit0_strap & SST_SGRAM_NUM_CHIPSETS) == 0) ? 4 : 8;
+
+ if ( (dramInit0_strap & SST_SGRAM_TYPE) == SST_SGRAM_TYPE_8MBIT ) {
+ partSize = 8;
+ } else if ( (dramInit0_strap & SST_SGRAM_TYPE) == SST_SGRAM_TYPE_16MBIT) {
+ partSize = 16;
+ } else {
+ ErrorF("Invalid sgram type = 0x%x",
+ (dramInit0_strap & SST_SGRAM_TYPE) << SST_SGRAM_TYPE_SHIFT );
+ return 0;
+ }
+ vmemSize = (nChips * partSize) / 8; /* in MBytes */
+ }
+ } else { /* V4, V5 */
+ nChips = ((dramInit0_strap & SST_SGRAM_NUM_CHIPSETS)==0) ? 4 : 8;
+ partSize=1<<((dramInit0_strap&0x38000000)>>28);
+ banks=((dramInit0_strap&BIT(30))==0) ? 2 : 4;
+ vmemSize=nChips*partSize*banks;
+ }
+ TDFXTRACEREG("dramInit0 = %x dramInit1 = %x\n", dramInit0_strap, dramInit1_strap);
+ TDFXTRACEREG("MemConfig %d chips %d size %d total\n", nChips, partSize, vmemSize);
+
+ /*
+ disable block writes for SDRAM
+ */
+ miscInit1 = pTDFX->readLong(pTDFX, MISCINIT1);
+ if ( vmemType == MEM_TYPE_SDRAM ) {
+ miscInit1 |= SST_DISABLE_2D_BLOCK_WRITE;
+ }
+ miscInit1|=1;
+ pTDFX->writeLong(pTDFX, MISCINIT1, miscInit1);
+ }
+
+ /* return # of KBytes of board memory */
+ return vmemSize*1024;
+}
+
+#if 0
+static int TDFXCfgToSize(int cfg)
+{
+ if (cfg<4) return 0x8000000<<cfg;
+ return 0x4000000>>(cfg-4);
+}
+#endif
+
+static int TDFXSizeToCfg(int size)
+{
+ switch (size) {
+ case 0x40000000: return 3;
+ case 0x20000000: return 2;
+ case 0x10000000: return 1;
+ case 0x08000000: return 0;
+ case 0x04000000: return 4;
+ case 0x02000000: return 5;
+ case 0x01000000: return 6;
+ case 0x00800000: return 7;
+ case 0x00400000: return 8;
+ default:
+ return -1;
+ }
+}
+
+static void
+TDFXFindChips(ScrnInfoPtr pScrn, pciVideoPtr match)
+{
+ TDFXPtr pTDFX;
+ pciVideoPtr *ppPci;
+
+ pTDFX=TDFXPTR(pScrn);
+ pTDFX->numChips=0;
+ pTDFX->ChipType=match->chipType;
+ for (ppPci = xf86GetPciVideoInfo(); *ppPci != NULL; ppPci++) {
+ if ((*ppPci)->bus == match->bus &&
+ (*ppPci)->device == match->device) {
+ pTDFX->PciTag[pTDFX->numChips] = pciTag((*ppPci)->bus,
+ (*ppPci)->device,
+ (*ppPci)->func);
+ pTDFX->PIOBase[pTDFX->numChips] =
+ pScrn->domainIOBase + ((*ppPci)->ioBase[2] & 0xFFFFFFFCU);
+ pTDFX->numChips++;
+ }
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "TDFXFindChips: found %d chip(s)\n", pTDFX->numChips);
+ /* Disable the secondary chips for now */
+ pTDFX->numChips=1;
+}
+
+static void
+TDFXInitChips(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+ int i, v, cfgbits, initbits;
+ int mem0base, mem1base, mem0size, mem0bits, mem1size, mem1bits;
+
+ pTDFX=TDFXPTR(pScrn);
+ cfgbits=pciReadLong(pTDFX->PciTag[0], CFG_PCI_DECODE);
+ mem0base=pciReadLong(pTDFX->PciTag[0], CFG_MEM0BASE);
+ mem1base=pciReadLong(pTDFX->PciTag[0], CFG_MEM1BASE);
+ initbits=pciReadLong(pTDFX->PciTag[0], CFG_INIT_ENABLE);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "TDFXInitChips: numchips = %d\n", pTDFX->numChips);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "TDFXInitChips: cfgbits = 0x%08lx, initbits = 0x%08lx\n",
+ cfgbits, initbits);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "TDFXInitChips: mem0base = 0x%08lx, mem1base = 0x%08lx\n",
+ mem0base, mem1base);
+ mem0size=32*1024*1024; /* Registers are always 32MB */
+ mem1size=pScrn->videoRam*1024*2; /* Linear mapping is 2x memory */
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "TDFXInitChips: mem0size = 0x%08lx, mem1size = 0x%08lx\n",
+ mem0size, mem1size);
+ mem0bits=TDFXSizeToCfg(mem0size);
+ mem1bits=TDFXSizeToCfg(mem1size)<<4;
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "TDFXInitChips: mem0bits = 0x%08lx, mem1bits = 0x%08lx\n",
+ mem0bits, mem1bits);
+ cfgbits=(cfgbits&~(0xFF))|mem0bits|mem1bits;
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "TDFXInitChips: cfgbits = 0x%08lx\n", cfgbits);
+ for (i=0; i<pTDFX->numChips; i++) {
+ initbits|=BIT(10);
+ pciWriteLong(pTDFX->PciTag[i], CFG_INIT_ENABLE, initbits);
+ v=pciReadWord(pTDFX->PciTag[i], CFG_PCI_COMMAND);
+#if 0
+ if (!i)
+ pciWriteWord(pTDFX->PciTag[i], CFG_PCI_COMMAND, v|0x3);
+ else
+ pciWriteWord(pTDFX->PciTag[i], CFG_PCI_COMMAND, v|0x2);
+#endif
+ pTDFX->MMIOAddr[i]=mem0base+i*mem0size;
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "TDFXInitChips: MMIOAddr[%d] = 0x%08lx\n",
+ i, pTDFX->MMIOAddr[i]);
+ pciWriteLong(pTDFX->PciTag[i], CFG_MEM0BASE, pTDFX->MMIOAddr[i]);
+ pTDFX->MMIOAddr[i]&=0xFFFFFF00;
+ pTDFX->LinearAddr[i]=mem1base+i*mem1size;
+ pciWriteLong(pTDFX->PciTag[i], CFG_MEM1BASE, pTDFX->LinearAddr[i]);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+ "TDFXInitChips: LinearAddr[%d] = 0x%08lx\n",
+ i, pTDFX->LinearAddr[i]);
+ pTDFX->LinearAddr[i]&=0xFFFFFF00;
+ pciWriteLong(pTDFX->PciTag[i], CFG_PCI_DECODE, cfgbits);
+ initbits&=~BIT(10);
+ pciWriteLong(pTDFX->PciTag[i], CFG_INIT_ENABLE, initbits);
+ }
+}
+
+/*
+ * TDFXPreInit --
+ *
+ * Do initial setup of the board before we know what resolution we will
+ * be running at.
+ *
+ */
+static Bool
+TDFXPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ TDFXPtr pTDFX;
+ ClockRangePtr clockRanges;
+ int i;
+ MessageType from;
+ int flags24;
+ rgb defaultWeight = {0, 0, 0};
+ pciVideoPtr match;
+ int availableMem;
+
+ TDFXTRACE("TDFXPreInit start\n");
+ if (pScrn->numEntities != 1) return FALSE;
+
+ /* Allocate driverPrivate */
+ if (!TDFXGetRec(pScrn)) {
+ return FALSE;
+ }
+
+ pTDFX = TDFXPTR(pScrn);
+
+ pTDFX->initDone=FALSE;
+ pTDFX->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+
+ if (flags & PROBE_DETECT) {
+#if !defined(__powerpc__)
+ TDFXProbeDDC(pScrn, pTDFX->pEnt->index);
+ return TRUE;
+#else
+ return FALSE;
+#endif
+ }
+
+ if (pTDFX->pEnt->location.type != BUS_PCI) return FALSE;
+
+ /* The vgahw module should be loaded here when needed */
+ if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE;
+
+ xf86LoaderReqSymLists(vgahwSymbols, NULL);
+
+ /* Allocate a vgaHWRec */
+ if (!vgaHWGetHWRec(pScrn)) return FALSE;
+
+#if USE_INT10
+#if !defined(__powerpc__)
+ if (xf86LoadSubModule(pScrn, "int10")) {
+ xf86Int10InfoPtr pInt;
+
+ xf86LoaderReqSymLists(int10Symbols, NULL);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Softbooting the board (through the int10 interface).\n");
+ pInt = xf86InitInt10(pTDFX->pEnt->index);
+ if (!pInt)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Softbooting the board failed.\n");
+ }
+ else
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Softbooting the board succeeded.\n");
+ xf86FreeInt10(pInt);
+ }
+ }
+#endif
+#endif
+
+ match=pTDFX->PciInfo=xf86GetPciInfoForEntity(pTDFX->pEnt->index);
+ TDFXFindChips(pScrn, match);
+ pTDFX->Primary = xf86IsPrimaryPci(pTDFX->PciInfo);
+
+ if (xf86RegisterResources(pTDFX->pEnt->index, NULL, ResExclusive)) {
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+ /*
+ * We don't need VGA resources during OPERATING state. However I'm
+ * not sure if they are disabled.
+ */
+ xf86SetOperatingState(resVgaIo, pTDFX->pEnt->index, ResDisableOpr);
+#if 0
+ pScrn->racIoFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
+ pScrn->racMemFlags = RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
+#endif
+#if 0
+#if 1
+
+ /* Is VGA memory disabled during OPERATING state? */
+
+ xf86SetOperatingState(resVgaMem, pTDFX->pEnt->index, ResDisableOpr);
+#else
+ pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
+#endif
+#endif
+
+#if 1
+ /*
+ * I'm sure we don't need to set these. All resources
+ * for these operations are exclusive.
+ */
+ if (pTDFX->usePIO) {
+ pScrn->racMemFlags = RAC_FB;
+ pScrn->racIoFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
+ } else
+ pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
+#endif
+
+ /* Set pScrn->monitor */
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ flags24=Support24bppFb | Support32bppFb | SupportConvert32to24;
+ if (!xf86SetDepthBpp(pScrn, 8, 8, 8, flags24)) {
+ return FALSE;
+ } else {
+ switch (pScrn->depth) {
+ case 8:
+ case 16:
+ case 24:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by tdfx driver\n",
+ pScrn->depth);
+ return FALSE;
+ }
+ }
+ xf86PrintDepthBpp(pScrn);
+
+ pScrn->rgbBits=8;
+ if (pScrn->depth>8) {
+ if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
+ return FALSE;
+ }
+
+ if (!xf86SetDefaultVisual(pScrn, -1)) {
+ return FALSE;
+ } else {
+ /* We don't currently support DirectColor at > 8bpp */
+ if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
+ " (%s) is not supported at depth %d\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+ return FALSE;
+ }
+ }
+
+ /* We use a programmable clock */
+ pScrn->progClock = TRUE;
+
+ pTDFX->cpp = pScrn->bitsPerPixel/8;
+
+ /* Process the options */
+ xf86CollectOptions(pScrn, NULL);
+ if (!(pTDFX->Options = xalloc(sizeof(TDFXOptions))))
+ return FALSE;
+ memcpy(pTDFX->Options, TDFXOptions, sizeof(TDFXOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTDFX->Options);
+
+ /*
+ * Set the Chipset and ChipRev, allowing config file entries to
+ * override.
+ */
+ if (pTDFX->pEnt->device->chipset && *pTDFX->pEnt->device->chipset) {
+ pScrn->chipset = pTDFX->pEnt->device->chipset;
+ from = X_CONFIG;
+ } else if (pTDFX->pEnt->device->chipID >= 0) {
+ pScrn->chipset = (char *)xf86TokenToString(TDFXChipsets, pTDFX->pEnt->device->chipID);
+ from = X_CONFIG;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
+ pTDFX->pEnt->device->chipID);
+ } else {
+ from = X_PROBED;
+ pScrn->chipset = (char *)xf86TokenToString(TDFXChipsets, match->chipType);
+ }
+ if (pTDFX->pEnt->device->chipRev >= 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
+ pTDFX->pEnt->device->chipRev);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
+
+ if (pTDFX->pEnt->device->MemBase != 0) {
+ pTDFX->LinearAddr[0] = pTDFX->pEnt->device->MemBase;
+ from = X_CONFIG;
+ } else {
+ if (match->memBase[1] != 0) {
+ pTDFX->LinearAddr[0] = match->memBase[1];
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid FB address in PCI config space\n");
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
+ (unsigned long)pTDFX->LinearAddr[0]);
+
+ if (pTDFX->pEnt->device->IOBase != 0) {
+ pTDFX->MMIOAddr[0] = pTDFX->pEnt->device->IOBase;
+ from = X_CONFIG;
+ } else {
+ if (match->memBase[0]) {
+ pTDFX->MMIOAddr[0] = match->memBase[0];
+ from = X_PROBED;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid MMIO address in PCI config space\n");
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at addr 0x%lX\n",
+ (unsigned long)pTDFX->MMIOAddr[0]);
+
+ if (!match->ioBase[2]) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No valid PIO address in PCI config space\n");
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PIO registers at addr 0x%lX\n",
+ (unsigned long)pTDFX->PIOBase[0]);
+
+ /* We have to use PIO to probe, because we haven't mappend yet */
+ TDFXSetPIOAccess(pTDFX);
+
+ /* Calculate memory */
+ pScrn->videoRam = TDFXCountRam(pScrn);
+ from = X_PROBED;
+ if (pTDFX->pEnt->device->videoRam) {
+ pScrn->videoRam = pTDFX->pEnt->device->videoRam;
+ from = X_CONFIG;
+ }
+
+ TDFXInitChips(pScrn);
+
+ /* Multiple by two because tiled access requires more address space */
+ pTDFX->FbMapSize = pScrn->videoRam*1024*2;
+ xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte Mapping %d kByte\n",
+ pScrn->videoRam, pTDFX->FbMapSize/1024);
+
+ /* Since we can do gamma correction, we call xf86SetGamma */
+ {
+ Gamma zeros = {0.0, 0.0, 0.0};
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ return FALSE;
+ }
+ }
+
+ pTDFX->MaxClock = 0;
+ if (pTDFX->pEnt->device->dacSpeeds[0]) {
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP8];
+ break;
+ case 16:
+ pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP16];
+ break;
+ case 24:
+ pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP24];
+ break;
+ case 32:
+ pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[DAC_BPP32];
+ break;
+ }
+ if (!pTDFX->MaxClock)
+ pTDFX->MaxClock = pTDFX->pEnt->device->dacSpeeds[0];
+ from = X_CONFIG;
+ } else {
+ switch (pTDFX->ChipType) {
+ case PCI_CHIP_BANSHEE:
+ pTDFX->MaxClock = 270000;
+ break;
+ case PCI_CHIP_VOODOO3:
+ switch(match->subsysCard) {
+ case PCI_CARD_VOODOO3_2000:
+ pTDFX->MaxClock = 300000;
+ break;
+ case PCI_CARD_VOODOO3_3000:
+ pTDFX->MaxClock = 350000;
+ break;
+ default:
+ pTDFX->MaxClock = 300000;
+ break;
+ }
+ break;
+ case PCI_CHIP_VOODOO5:
+ pTDFX->MaxClock = 350000;
+ break;
+ }
+ }
+ clockRanges = xnfcalloc(sizeof(ClockRange), 1);
+ clockRanges->next=NULL;
+ clockRanges->minClock= 12000; /* !!! What's the min clock? !!! */
+ clockRanges->maxClock=pTDFX->MaxClock;
+ clockRanges->clockIndex = -1;
+ clockRanges->interlaceAllowed = FALSE;
+ clockRanges->doubleScanAllowed = TRUE;
+
+ /*
+ * Max memory available for the framebuffer is the total less the
+ * HW cursor space and FIFO space.
+ */
+ availableMem = pScrn->videoRam - 4096 -
+ (((255 <= CMDFIFO_PAGES) ? 255 : CMDFIFO_PAGES) << 12);
+
+ i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
+ pScrn->display->modes, clockRanges,
+ 0, 320, 2048, 16*pScrn->bitsPerPixel,
+ 200, 2047,
+ pScrn->display->virtualX, pScrn->display->virtualY,
+ availableMem, LOOKUP_BEST_REFRESH);
+
+ if (i==-1) {
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86PruneDriverModes(pScrn);
+
+ if (!i || !pScrn->modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+
+ pScrn->currentMode = pScrn->modes;
+
+ xf86PrintModes(pScrn);
+
+ xf86SetDpi(pScrn, 0, 0);
+
+ if (!xf86LoadSubModule(pScrn, "fb")) {
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+
+ if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_NOACCEL, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "xaa")) {
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(xaaSymbols, NULL);
+ }
+
+ if (!xf86GetOptValBool(pTDFX->Options, OPTION_SHOWCACHE, &(pTDFX->ShowCache))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache %s\n", pTDFX->ShowCache ? "Enabled" : "Disabled");
+ } else {
+ pTDFX->ShowCache = FALSE;
+ }
+
+ if (xf86GetOptValBool(pTDFX->Options, OPTION_TEXTURED_VIDEO, &(pTDFX->TextureXvideo))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Texture Xvideo Adaptor %s\n", pTDFX->TextureXvideo ? "Enabled" : "Disabled");
+ } else {
+ pTDFX->TextureXvideo = FALSE;
+ }
+
+ if (xf86GetOptValInteger(pTDFX->Options, OPTION_VIDEO_KEY, &(pTDFX->videoKey))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", pTDFX->videoKey);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key default 0x%x\n", pTDFX->videoKey = 0x1E);
+ }
+
+ if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) {
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+
+#if USE_INT10
+#if !defined(__powerpc__)
+ /* Load DDC if needed */
+ /* This gives us DDC1 - we should be able to get DDC2B using i2c */
+ if (!xf86LoadSubModule(pScrn, "ddc")) {
+ TDFXFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(ddcSymbols, NULL);
+
+ /* Initialize DDC1 if possible */
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ xf86MonPtr pMon;
+ vbeInfoPtr pVbe = VBEInit(NULL,pTDFX->pEnt->index);
+
+ xf86LoaderReqSymLists(vbeSymbols, NULL);
+ pMon = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ xf86SetDDCproperties(pScrn,xf86PrintEDID(pMon));
+ }
+#endif
+#endif
+
+ if (xf86ReturnOptValBool(pTDFX->Options, OPTION_USE_PIO, FALSE)) {
+ pTDFX->usePIO=TRUE;
+ }
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ pTDFX->ModeReg.miscinit0 = pTDFX->readLong(pTDFX, MISCINIT0);
+ pTDFX->SavedReg.miscinit0 = pTDFX->ModeReg.miscinit0;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pTDFX->writeFifo = TDFXWriteFifo_8;
+ pTDFX->ModeReg.miscinit0 &= ~BIT(30); /* LFB byte swizzle */
+ pTDFX->ModeReg.miscinit0 &= ~BIT(31); /* LFB word swizzle */
+ break;
+ case 15:
+ case 16:
+ pTDFX->writeFifo = TDFXWriteFifo_16;
+ pTDFX->ModeReg.miscinit0 |= BIT(30); /* LFB byte swizzle */
+ pTDFX->ModeReg.miscinit0 |= BIT(31); /* LFB word swizzle */
+ break;
+ case 24:
+ case 32:
+ pTDFX->writeFifo = TDFXWriteFifo_24;
+ pTDFX->ModeReg.miscinit0 |= BIT(30); /* LFB byte swizzle */
+ pTDFX->ModeReg.miscinit0 &= ~BIT(31); /* LFB word swizzle */
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+ pTDFX->writeLong(pTDFX, MISCINIT0, pTDFX->ModeReg.miscinit0);
+#endif
+
+
+ return TRUE;
+}
+
+static Bool
+TDFXMapMem(ScrnInfoPtr pScrn)
+{
+ int mmioFlags, i;
+ TDFXPtr pTDFX;
+
+ TDFXTRACE("TDFXMapMem start\n");
+ pTDFX = TDFXPTR(pScrn);
+
+ mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
+
+ for (i=0; i<pTDFX->numChips; i++) {
+ pTDFX->MMIOBase[i] = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
+ pTDFX->PciTag[i],
+ pTDFX->MMIOAddr[i],
+ TDFXIOMAPSIZE);
+
+ if (!pTDFX->MMIOBase[i]) return FALSE;
+ }
+
+ pTDFX->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pTDFX->PciTag[0],
+ pTDFX->LinearAddr[0],
+ pTDFX->FbMapSize);
+ if (!pTDFX->FbBase) return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+TDFXUnmapMem(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+ int i;
+
+ TDFXTRACE("TDFXUnmapMem start\n");
+ pTDFX = TDFXPTR(pScrn);
+
+ for (i=0; i<pTDFX->numChips; i++) {
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTDFX->MMIOBase[i],
+ TDFXIOMAPSIZE);
+ pTDFX->MMIOBase[i]=0;
+ }
+
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTDFX->FbBase, pTDFX->FbMapSize);
+ pTDFX->FbBase = 0;
+ return TRUE;
+}
+
+static void
+PrintRegisters(ScrnInfoPtr pScrn, TDFXRegPtr regs)
+{
+#ifdef TRACE
+ int i;
+ TDFXPtr pTDFX;
+ vgaHWPtr pHW = VGAHWPTR(pScrn);
+ vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
+
+
+ pTDFX = TDFXPTR(pScrn);
+#if 1
+ ErrorF("VGA Registers\n");
+ ErrorF("MiscOutReg = %x versus %x\n", pHW->readMiscOut(pHW), pVga->MiscOutReg);
+ ErrorF("EnableReg = %x\n", pHW->readEnable(pHW));
+ for (i=0; i<25; i++) {
+ int x;
+ x = pHW->readCrtc(pHW, i);
+ ErrorF("CRTC[%d]=%d versus %d\n", i, x, pVga->CRTC[i]);
+ }
+ for (i=0; i<21; i++) {
+ ErrorF("Attribute[%d]=%d versus %d\n", i, pHW->readAttr(pHW, i), pVga->Attribute[i]);
+ }
+ for (i=0; i<9; i++) {
+ ErrorF("Graphics[%d]=%d versus %d\n", i, pHW->readGr(pHW, i), pVga->Graphics[i]);
+ }
+ for (i=0; i<5; i++) {
+ ErrorF("Sequencer[%d]=%d versus %d\n", i, pHW->readSeq(pHW, i), pVga->Sequencer[i]);
+ }
+#endif
+#if 1
+ ErrorF("Banshee Registers\n");
+ ErrorF("VidCfg = %x versus %x\n", pTDFX->readLong(pTDFX, VIDPROCCFG), regs->vidcfg);
+ ErrorF("DACmode = %x versus %x\n", pTDFX->readLong(pTDFX, DACMODE), regs->dacmode);
+ ErrorF("Vgainit0 = %x versus %x\n", pTDFX->readLong(pTDFX, VGAINIT0), regs->vgainit0);
+ ErrorF("Vgainit1 = %x versus %x\n", pTDFX->readLong(pTDFX, VGAINIT1), regs->vgainit1);
+ ErrorF("Miscinit0 = %x versus %x\n", pTDFX->readLong(pTDFX, MISCINIT0), regs->miscinit0);
+ ErrorF("Miscinit1 = %x versus %x\n", pTDFX->readLong(pTDFX, MISCINIT1), regs->miscinit1);
+ ErrorF("DramInit0 = %x\n", pTDFX->readLong(pTDFX, DRAMINIT0));
+ ErrorF("DramInit1 = %x\n", pTDFX->readLong(pTDFX, DRAMINIT1));
+ ErrorF("VidPLL = %x versus %x\n", pTDFX->readLong(pTDFX, PLLCTRL0), regs->vidpll);
+ ErrorF("screensize = %x versus %x\n", pTDFX->readLong(pTDFX, VIDSCREENSIZE), regs->screensize);
+ ErrorF("stride = %x versus %x\n", pTDFX->readLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE), regs->stride);
+ ErrorF("startaddr = %x versus %x\n", pTDFX->readLong(pTDFX, VIDDESKTOPSTARTADDR), regs->startaddr);
+ ErrorF("Input Status 0 = %x\n", pTDFX->readLong(pTDFX, 0xc2));
+ ErrorF("Input Status 1 = %x\n", pTDFX->readLong(pTDFX, 0xda));
+ ErrorF("2D Status = %x\n", pTDFX->readLong(pTDFX, SST_2D_OFFSET));
+ ErrorF("3D Status = %x\n", pTDFX->readLong(pTDFX, SST_3D_OFFSET));
+#endif
+#endif
+}
+
+/*
+ * TDFXSave --
+ *
+ * This function saves the video state. It reads all of the SVGA registers
+ * into the vgaTDFXRec data structure. There is in general no need to
+ * mask out bits here - just read the registers.
+ */
+static void
+DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, TDFXRegPtr tdfxReg, Bool saveFonts)
+{
+ TDFXPtr pTDFX;
+ vgaHWPtr hwp;
+ int i, dummy, count;
+
+ TDFXTRACE("TDFXDoSave start\n");
+ pTDFX = TDFXPTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ /*
+ * This function will handle creating the data structure and filling
+ * in the generic VGA portion.
+ */
+ if (saveFonts && pTDFX->Primary) {
+ /* Enable legacy VGA to access font memory. */
+ dummy = pTDFX->readLong(pTDFX, VGAINIT0);
+ pTDFX->writeLong(pTDFX, VGAINIT0, dummy & ~SST_VGA0_LEGACY_DECODE);
+ vgaHWSave(pScrn, vgaReg, VGA_SR_MODE|VGA_SR_FONTS);
+ pTDFX->writeLong(pTDFX, VGAINIT0, dummy);
+ } else
+ vgaHWSave(pScrn, vgaReg, VGA_SR_MODE);
+
+ tdfxReg->ExtVga[0] = hwp->readCrtc(hwp, 0x1a);
+ tdfxReg->ExtVga[1] = hwp->readCrtc(hwp, 0x1b);
+ tdfxReg->miscinit1=pTDFX->readLong(pTDFX, MISCINIT1);
+ tdfxReg->vidcfg=pTDFX->readLong(pTDFX, VIDPROCCFG);
+ tdfxReg->vidpll=pTDFX->readLong(pTDFX, PLLCTRL0);
+ tdfxReg->dacmode=pTDFX->readLong(pTDFX, DACMODE);
+ tdfxReg->screensize=pTDFX->readLong(pTDFX, VIDSCREENSIZE);
+ tdfxReg->stride=pTDFX->readLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE);
+ tdfxReg->cursloc=pTDFX->readLong(pTDFX, HWCURPATADDR);
+ tdfxReg->startaddr=pTDFX->readLong(pTDFX, VIDDESKTOPSTARTADDR);
+ tdfxReg->clip0min=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP0MIN);
+ tdfxReg->clip0max=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP0MAX);
+ tdfxReg->clip1min=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP1MIN);
+ tdfxReg->clip1max=TDFXReadLongMMIO(pTDFX, SST_2D_CLIP1MAX);
+ tdfxReg->srcbaseaddr=TDFXReadLongMMIO(pTDFX, SST_2D_SRCBASEADDR);
+ tdfxReg->dstbaseaddr=TDFXReadLongMMIO(pTDFX, SST_2D_DSTBASEADDR);
+ for (i=0; i<512; i++) {
+ count=0;
+ do {
+ TDFXWriteLongMMIO(pTDFX, DACADDR, i);
+ dummy=TDFXReadLongMMIO(pTDFX, DACADDR);
+ } while (count++<100 && dummy!=i);
+ tdfxReg->dactable[i]=TDFXReadLongMMIO(pTDFX, DACDATA);
+ }
+ PrintRegisters(pScrn, tdfxReg);
+}
+
+static void
+TDFXSave(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp;
+ TDFXPtr pTDFX;
+
+ TDFXTRACE("TDFXSave start\n");
+ hwp = VGAHWPTR(pScrn);
+ pTDFX = TDFXPTR(pScrn);
+ /* Make sure VGA functionality is enabled */
+ pTDFX->SavedReg.vgainit0=pTDFX->readLong(pTDFX, VGAINIT0);
+#if 0
+ pTDFX->SavedReg.vgainit1=pTDFX->readLong(pTDFX, VGAINIT1);
+#endif
+ pTDFX->writeLong(pTDFX, VGAINIT0, pTDFX->ModeReg.vgainit0);
+#if 0
+ pTDFX->writeLong(pTDFX, VGAINIT1, pTDFX->ModeReg.vgainit1);
+#endif
+ vgaHWEnable(hwp);
+
+ DoSave(pScrn, &hwp->SavedReg, &pTDFX->SavedReg, TRUE);
+}
+
+static void
+DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, TDFXRegPtr tdfxReg,
+ Bool restoreFonts) {
+ TDFXPtr pTDFX;
+ vgaHWPtr hwp;
+ int i, dummy, count;
+
+ TDFXTRACE("TDFXDoRestore start\n");
+ pTDFX = TDFXPTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ pTDFX->sync(pScrn);
+
+ vgaHWProtect(pScrn, TRUE);
+
+ if (restoreFonts && pTDFX->Primary) {
+ /* Enable legacy VGA to access font memory. */
+ dummy = pTDFX->readLong(pTDFX, VGAINIT0);
+ pTDFX->writeLong(pTDFX, VGAINIT0, dummy & ~SST_VGA0_LEGACY_DECODE);
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE);
+ pTDFX->writeLong(pTDFX, VGAINIT0, dummy);
+ } else
+ vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
+
+ hwp->writeCrtc(hwp, 0x1a, tdfxReg->ExtVga[0]);
+ hwp->writeCrtc(hwp, 0x1b, tdfxReg->ExtVga[1]);
+ pTDFX->writeLong(pTDFX, PLLCTRL0, tdfxReg->vidpll);
+ pTDFX->writeLong(pTDFX, DACMODE, tdfxReg->dacmode);
+ pTDFX->writeLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE, tdfxReg->stride);
+ pTDFX->writeLong(pTDFX, HWCURPATADDR, tdfxReg->cursloc);
+ pTDFX->writeLong(pTDFX, VIDSCREENSIZE, tdfxReg->screensize);
+ pTDFX->writeLong(pTDFX, VIDDESKTOPSTARTADDR, tdfxReg->startaddr);
+ TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP0MIN, tdfxReg->clip0min);
+ TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP0MAX, tdfxReg->clip0max);
+ TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP1MIN, tdfxReg->clip1min);
+ TDFXWriteLongMMIO(pTDFX, SST_2D_CLIP1MAX, tdfxReg->clip1max);
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ pTDFX->writeLong(pTDFX, MISCINIT0, tdfxReg->miscinit0);
+#endif
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, tdfxReg->vidcfg);
+ TDFXWriteLongMMIO(pTDFX, SST_2D_SRCBASEADDR, tdfxReg->srcbaseaddr);
+ TDFXWriteLongMMIO(pTDFX, SST_2D_DSTBASEADDR, tdfxReg->dstbaseaddr);
+ for (i=0; i<512; i++) {
+ count=0;
+ do {
+ TDFXWriteLongMMIO(pTDFX, DACADDR, i);
+ dummy=TDFXReadLongMMIO(pTDFX, DACADDR);
+ } while (count++<100 && dummy!=i);
+ count=0;
+ do {
+ TDFXWriteLongMMIO(pTDFX, DACDATA, tdfxReg->dactable[i]);
+ dummy=TDFXReadLongMMIO(pTDFX, DACDATA);
+ } while (count++<100 && dummy!=tdfxReg->dactable[i]);
+ }
+ pTDFX->writeLong(pTDFX, VGAINIT0, tdfxReg->vgainit0);
+#if 0
+ pTDFX->writeLong(pTDFX, VGAINIT1, tdfxReg->vgainit1);
+ pTDFX->writeLong(pTDFX, MISCINIT1, tdfxReg->miscinit1);
+#endif
+ vgaHWProtect(pScrn, FALSE);
+
+ pTDFX->sync(pScrn);
+ PrintRegisters(pScrn, tdfxReg);
+}
+
+static void
+TDFXRestore(ScrnInfoPtr pScrn) {
+ vgaHWPtr hwp;
+ TDFXPtr pTDFX;
+
+ TDFXTRACE("TDFXRestore start\n");
+ hwp = VGAHWPTR(pScrn);
+ pTDFX = TDFXPTR(pScrn);
+
+ DoRestore(pScrn, &hwp->SavedReg, &pTDFX->SavedReg, TRUE);
+}
+
+#define REFFREQ 14318.18
+
+static int
+CalcPLL(int freq, int *f_out, int isBanshee) {
+ int m, n, k, best_m, best_n, best_k, f_cur, best_error;
+ int minm, maxm;
+
+ TDFXTRACE("CalcPLL start\n");
+ best_error=freq;
+ best_n=best_m=best_k=0;
+ if (isBanshee) {
+ minm=24;
+ maxm=24;
+ } else {
+ minm=1;
+ maxm=57; /* This used to be 64, alas it seems the last 8 (funny that ?)
+ * values cause jittering at lower resolutions. I've not done
+ * any calculations to what the adjustment affects clock ranges,
+ * but I can still run at 1600x1200@75Hz */
+ }
+ for (n=1; n<256; n++) {
+ f_cur=REFFREQ*(n+2);
+ if (f_cur<freq) {
+ f_cur=f_cur/3;
+ if (freq-f_cur<best_error) {
+ best_error=freq-f_cur;
+ best_n=n;
+ best_m=1;
+ best_k=0;
+ continue;
+ }
+ }
+ for (m=minm; m<maxm; m++) {
+ for (k=0; k<4; k++) {
+ f_cur=REFFREQ*(n+2)/(m+2)/(1<<k);
+ if (abs(f_cur-freq)<best_error) {
+ best_error=abs(f_cur-freq);
+ best_n=n;
+ best_m=m;
+ best_k=k;
+ }
+ }
+ }
+ }
+ n=best_n;
+ m=best_m;
+ k=best_k;
+ *f_out=REFFREQ*(n+2)/(m+2)/(1<<k);
+ return (n<<8)|(m<<2)|k;
+}
+
+static Bool
+SetupVidPLL(ScrnInfoPtr pScrn, DisplayModePtr mode) {
+ TDFXPtr pTDFX;
+ TDFXRegPtr tdfxReg;
+ int freq, f_out;
+
+ TDFXTRACE("SetupVidPLL start\n");
+ pTDFX = TDFXPTR(pScrn);
+ tdfxReg = &pTDFX->ModeReg;
+ freq=mode->Clock;
+ tdfxReg->dacmode&=~SST_DAC_MODE_2X;
+ tdfxReg->vidcfg&=~SST_VIDEO_2X_MODE_EN;
+ if (freq>TDFX2XCUTOFF) {
+ if (freq>pTDFX->MaxClock) {
+ ErrorF("Overclocked PLLs\n");
+ freq=pTDFX->MaxClock;
+ }
+ tdfxReg->dacmode|=SST_DAC_MODE_2X;
+ tdfxReg->vidcfg|=SST_VIDEO_2X_MODE_EN;
+ }
+ tdfxReg->vidpll=CalcPLL(freq, &f_out, 0);
+ TDFXTRACEREG("Vid PLL freq=%d f_out=%d reg=%x\n", freq, f_out,
+ tdfxReg->vidpll);
+ return TRUE;
+}
+
+#if 0
+static Bool
+SetupMemPLL(int freq) {
+ TDFXPtr pTDFX;
+ vgaTDFXPtr tdfxReg;
+ int f_out;
+
+ TDFXTRACE("SetupMemPLL start\n");
+ pTDFX=TDFXPTR();
+ tdfxReg=(vgaTDFXPtr)vgaNewVideoState;
+ tdfxReg->mempll=CalcPLL(freq, &f_out);
+ pTDFX->writeLong(pTDFX, PLLCTRL1, tdfxReg->mempll);
+ TDFXTRACEREG("Mem PLL freq=%d f_out=%d reg=%x\n", freq, f_out,
+ tdfxReg->mempll);
+ return TRUE;
+}
+
+static Bool
+SetupGfxPLL(int freq) {
+ TDFXPtr pTDFX;
+ vgaTDFXPtr tdfxReg;
+ int f_out;
+
+ TDFXTRACE("SetupGfxPLL start\n");
+ pTDFX=TDFXPTR();
+ tdfxReg=(vgaTDFXPtr)vgaNewVideoState;
+ if (pTDFX->chipType==PCI_CHIP_BANSHEE)
+ tdfxReg->gfxpll=CalcPLL(freq, &f_out, 1);
+ else
+ tdfxReg->gfxpll=CalcPLL(freq, &f_out, 0);
+ pTDFX->writeLong(pTDFX, PLLCTRL2, tdfxReg->gfxpll);
+ TDFXTRACEREG("Gfx PLL freq=%d f_out=%d reg=%x\n", freq, f_out,
+ tdfxReg->gfxpll);
+ return TRUE;
+}
+#endif
+
+#if 0
+static Bool
+TDFXInitWithBIOSData(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+ unsigned char *bios = NULL;
+ int offset1, offset2;
+ int i;
+ CARD32 uint[9];
+
+ pTDFX=TDFXPTR(pScrn);
+
+ if (pTDFX->initDone)
+ return TRUE;
+
+ if (pTDFX->Primary) {
+ uint[0] = pTDFX->readLong(pTDFX, PCIINIT0);
+ uint[1] = pTDFX->readLong(pTDFX, MISCINIT0);
+ uint[2] = pTDFX->readLong(pTDFX, MISCINIT1);
+ uint[3] = pTDFX->readLong(pTDFX, DRAMINIT0);
+ uint[4] = pTDFX->readLong(pTDFX, DRAMINIT1);
+ uint[5] = pTDFX->readLong(pTDFX, AGPINIT);
+ uint[6] = pTDFX->readLong(pTDFX, PLLCTRL1);
+ uint[7] = pTDFX->readLong(pTDFX, PLLCTRL2);
+ for (i = 0; i < 8; i++) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Primary UINT32[%d] is 0x%08lx\n", i, uint[i]);
+ }
+ return TRUE;
+ }
+
+#define T_B_SIZE (64 * 1024)
+ bios = xcalloc(T_B_SIZE, 1);
+ if (!bios)
+ return FALSE;
+
+ if (!xf86ReadPciBIOS(0, pTDFX->PciTag[0], 1, bios, T_B_SIZE)) {
+#if 0
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Bad BIOS read.\n");
+ xfree(bios);
+ return FALSE;
+#endif
+ }
+
+ if (bios[0] != 0x55 || bios[1] != 0xAA) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Bad BIOS signature.\n");
+ xfree(bios);
+ return FALSE;
+ }
+
+ offset1 = bios[0x50] | (bios[0x51] << 8);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Offset 1 is (0x%04x)\n", offset1);
+ offset2 = bios[offset1] | (bios[offset1 + 1] << 8);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Offset 2 is (0x%04x)\n", offset2);
+
+ for (i = 0; i < 9; i++) {
+ int o;
+
+ o = offset2 + i * 4;
+ uint[i] = bios[o] | (bios[o+1] << 8) | (bios[o+2] << 16) | (bios[o+3] << 24);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UINT32[%d] is 0x%08lx\n", i, uint[i]);
+ }
+
+#if 1
+ uint[0] = 0x0584fb04;
+ uint[1] = 0x00000000;
+ uint[2] = 0x03000001;
+ uint[3] = 0x0c17a9e9;
+ uint[4] = 0x00202031;
+ uint[5] = 0x8000049e;
+ uint[6] = 0x00003a05;
+ uint[7] = 0x00000c00;
+#endif
+
+ pTDFX->writeLong(pTDFX, PCIINIT0, uint[0]);
+ pTDFX->writeLong(pTDFX, MISCINIT0, uint[1]);
+ pTDFX->writeLong(pTDFX, MISCINIT1, uint[2]);
+ pTDFX->writeLong(pTDFX, DRAMINIT0, uint[3]);
+ pTDFX->writeLong(pTDFX, DRAMINIT1, uint[4]);
+ pTDFX->writeLong(pTDFX, AGPINIT, uint[5]);
+ pTDFX->writeLong(pTDFX, PLLCTRL1, uint[6]);
+ pTDFX->writeLong(pTDFX, PLLCTRL2, uint[7]);
+#if 0
+ pTDFX->writeLong(pTDFX, DRAMCOMMAND, uint[8]);
+#endif
+
+ /* reset */
+ pTDFX->writeLong(pTDFX, MISCINIT0, 0xF3);
+ pTDFX->writeLong(pTDFX, MISCINIT0, uint[1]);
+
+ xfree(bios);
+ return TRUE;
+}
+#endif
+
+
+static Bool
+TDFXInitVGA(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+ TDFXRegPtr tdfxReg;
+
+ TDFXTRACE("TDFXInitVGA start\n");
+ pTDFX=TDFXPTR(pScrn);
+ if (pTDFX->initDone) return TRUE;
+ pTDFX->initDone=TRUE;
+
+ tdfxReg = &pTDFX->ModeReg;
+ tdfxReg->vgainit0 = 0;
+ tdfxReg->vgainit0 |= SST_VGA0_EXTENSIONS;
+ tdfxReg->vgainit0 |= SST_WAKEUP_3C3 << SST_VGA0_WAKEUP_SELECT_SHIFT;
+#if USE_PCIVGAIO
+ tdfxReg->vgainit0 |= SST_VGA0_LEGACY_DECODE;
+#endif
+ tdfxReg->vgainit0 |= SST_ENABLE_ALT_READBACK << SST_VGA0_CONFIG_READBACK_SHIFT;
+ tdfxReg->vgainit0 |= SST_CLUT_SELECT_8BIT << SST_VGA0_CLUT_SELECT_SHIFT;
+
+ tdfxReg->vgainit0 |= BIT(12);
+#if 0
+ tdfxReg->vgainit1 |= 0;
+ tdfxReg->miscinit1 = 0;
+#endif
+
+ tdfxReg->vidcfg = SST_VIDEO_PROCESSOR_EN | SST_CURSOR_X11 | SST_DESKTOP_EN |
+ (pTDFX->cpp-1)<<SST_DESKTOP_PIXEL_FORMAT_SHIFT;
+
+ /* tdfxReg->vidcfg |= SST_DESKTOP_CLUT_BYPASS; */
+
+ tdfxReg->stride = pTDFX->stride;
+
+ tdfxReg->clip0min = tdfxReg->clip1min = 0;
+ tdfxReg->clip0max = tdfxReg->clip1max = pTDFX->maxClip;
+
+ return TRUE;
+}
+
+static Bool
+TDFXSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) {
+ TDFXPtr pTDFX;
+ TDFXRegPtr tdfxReg;
+ vgaRegPtr pVga;
+ int hbs, hbe, vbs, vbe, hse, wd;
+ int hd, hss, ht, vss, vt, vd, vse;
+
+ TDFXTRACE("TDFXSetMode start\n");
+
+ pTDFX = TDFXPTR(pScrn);
+ tdfxReg = &pTDFX->ModeReg;
+ pVga = &VGAHWPTR(pScrn)->ModeReg;
+
+ if (pTDFX->cpp==4)
+ wd = pScrn->displayWidth>>1;
+ else
+ wd = pScrn->displayWidth>>(4-pTDFX->cpp);
+
+ /* Tell the board we're using a programmable clock */
+ pVga->MiscOutReg |= 0xC;
+
+ /* Calculate the CRTC values */
+ hd = (mode->CrtcHDisplay>>3)-1;
+ hss = (mode->CrtcHSyncStart>>3);
+ hse = (mode->CrtcHSyncEnd>>3);
+ ht = (mode->CrtcHTotal>>3)-5;
+ hbs = (mode->CrtcHBlankStart>>3)-1;
+ hbe = (mode->CrtcHBlankEnd>>3)-1;
+
+ vd = mode->CrtcVDisplay-1;
+ vss = mode->CrtcVSyncStart;
+ vse = mode->CrtcVSyncEnd;
+ vt = mode->CrtcVTotal-2;
+ vbs = mode->CrtcVBlankStart-1;
+ vbe = mode->CrtcVBlankEnd-1;
+
+ /* Undo the "KGA fixes" */
+ pVga->CRTC[3] = (hbe&0x1F)|0x80;
+ pVga->CRTC[5] = (((hbe)&0x20)<<2) | (hse&0x1F);
+ pVga->CRTC[22] =vbe&0xFF;
+
+ /* Handle the higher resolution modes */
+ tdfxReg->ExtVga[0] = (ht&0x100)>>8 | (hd&0x100)>>6 | (hbs&0x100)>>4 |
+ (hbe&0x40)>>1 | (hss&0x100)>>2 | (hse&0x20)<<2;
+
+ tdfxReg->ExtVga[1] = (vt&0x400)>>10 | (vd&0x400)>>8 | (vbs&0x400)>>6 |
+ (vbe&0x400)>>4;
+
+ if (!SetupVidPLL(pScrn, mode)) return FALSE;
+
+ /* Set the screen size */
+ if (mode->Flags&V_DBLSCAN) {
+ pVga->CRTC[9] |= 0x80;
+ tdfxReg->screensize=mode->HDisplay|(mode->VDisplay<<13);
+ tdfxReg->vidcfg |= SST_HALF_MODE;
+ } else {
+ tdfxReg->screensize=mode->HDisplay|(mode->VDisplay<<12);
+ tdfxReg->vidcfg &= ~SST_HALF_MODE;
+ }
+
+ TDFXTRACEREG("cpp=%d Hdisplay=%d Vdisplay=%d stride=%d screensize=%x\n",
+ pTDFX->cpp, mode->HDisplay, mode->VDisplay, tdfxReg->stride,
+ tdfxReg->screensize);
+
+ return TRUE;
+}
+
+static Bool
+TDFXModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp;
+ TDFXPtr pTDFX;
+ int hd, hbs, hss, hse, hbe, ht, hskew;
+ Bool dbl;
+
+ hd = hbs = hss = hse = hbe = ht = hskew = 0;
+ hwp = VGAHWPTR(pScrn);
+ pTDFX = TDFXPTR(pScrn);
+
+ TDFXTRACE("TDFXModeInit start\n");
+ dbl=FALSE;
+ /* Check for 2x mode and halve all the timing values */
+ if (mode->Clock>TDFX2XCUTOFF) {
+ hd=mode->CrtcHDisplay;
+ hbs=mode->CrtcHBlankStart;
+ hss=mode->CrtcHSyncStart;
+ hse=mode->CrtcHSyncEnd;
+ hbe=mode->CrtcHBlankEnd;
+ ht=mode->CrtcHTotal;
+ hskew=mode->CrtcHSkew;
+ mode->CrtcHDisplay=hd>>1;
+ mode->CrtcHBlankStart=hbs>>1;
+ mode->CrtcHSyncStart=hss>>1;
+ mode->CrtcHSyncEnd=hse>>1;
+ mode->CrtcHBlankEnd=hbe>>1;
+ mode->CrtcHTotal=ht>>1;
+ mode->CrtcHSkew=hskew>>1;
+ dbl=TRUE;
+ }
+
+ vgaHWUnlock(hwp);
+
+ if (!vgaHWInit(pScrn, mode)) return FALSE;
+
+ pScrn->vtSema = TRUE;
+
+ if (!TDFXSetMode(pScrn, mode)) return FALSE;
+
+ if (dbl) {
+ mode->CrtcHDisplay=hd;
+ mode->CrtcHBlankStart=hbs;
+ mode->CrtcHSyncStart=hss;
+ mode->CrtcHSyncEnd=hse;
+ mode->CrtcHBlankEnd=hbe;
+ mode->CrtcHTotal=ht;
+ mode->CrtcHSkew=hskew;
+ }
+
+#ifdef XF86DRI
+ if (pTDFX->directRenderingEnabled) {
+ DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
+ TDFXSwapContextFifo(screenInfo.screens[pScrn->scrnIndex]);
+ }
+#endif
+ DoRestore(pScrn, &hwp->ModeReg, &pTDFX->ModeReg, FALSE);
+#ifdef XF86DRI
+ if (pTDFX->directRenderingEnabled) {
+ DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
+ }
+#endif
+
+ return TRUE;
+}
+
+static void
+TDFXLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
+ VisualPtr pVisual) {
+ TDFXPtr pTDFX;
+ int i, j, index, v, repeat, max;
+
+ TDFXTRACE("TDFXLoadPalette16 start\n");
+ pTDFX = TDFXPTR(pScrn);
+
+ for (i=0; i<numColors; i++) {
+ index=indices[i];
+ v=(colors[index/2].red<<16)|(colors[index].green<<8)|colors[index/2].blue;
+ max=min((index+1)<<2, 256);
+ for (j = index<<2; j < max; j++)
+ {
+ repeat=100;
+ do {
+ TDFXWriteLongMMIO(pTDFX, DACADDR, j);
+ } while (--repeat && TDFXReadLongMMIO(pTDFX, DACADDR)!=j);
+ if (!repeat) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac index, bypassing CLUT\n");
+ pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
+ return;
+ }
+
+ repeat=100;
+ do {
+ TDFXWriteLongMMIO(pTDFX, DACDATA, v);
+ } while (--repeat && TDFXReadLongMMIO(pTDFX, DACDATA)!=v);
+ if (!repeat) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac value, bypassing CLUT\n");
+ pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
+ return;
+ }
+ }
+ }
+}
+
+static void
+TDFXLoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
+ VisualPtr pVisual) {
+ TDFXPtr pTDFX;
+ int i, index, v, repeat;
+
+ TDFXTRACE("TDFXLoadPalette24 start\n");
+ pTDFX = TDFXPTR(pScrn);
+ for (i=0; i<numColors; i++) {
+ index=indices[i];
+ v=(colors[index].red<<16)|(colors[index].green<<8)|colors[index].blue;
+ repeat=100;
+ do {
+ TDFXWriteLongMMIO(pTDFX, DACADDR, index);
+ } while (--repeat && TDFXReadLongMMIO(pTDFX, DACADDR)!=index);
+ if (!repeat) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac index, "
+ "bypassing CLUT\n");
+ pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
+ return;
+ }
+ repeat=100;
+ do {
+ TDFXWriteLongMMIO(pTDFX, DACDATA, v);
+ } while (--repeat && TDFXReadLongMMIO(pTDFX, DACDATA)!=v);
+ if (!repeat) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to set dac value, "
+ "bypassing CLUT\n");
+ pTDFX->ModeReg.vidcfg |= SST_DESKTOP_CLUT_BYPASS;
+ return;
+ }
+ }
+}
+
+#define TILE_WIDTH 128
+#define TILE_HEIGHT 32
+
+static int
+calcBufferStride(int xres, Bool tiled, int cpp)
+{
+ int strideInTiles;
+
+ if (tiled == TRUE) {
+ /* Calculate tile width stuff */
+ strideInTiles = (xres+TILE_WIDTH-1)/TILE_WIDTH;
+
+ return strideInTiles*cpp*TILE_WIDTH;
+ } else {
+ return xres*cpp;
+ }
+} /* calcBufferStride */
+
+static int
+calcBufferHeightInTiles(int yres)
+{
+ int heightInTiles; /* Height of buffer in tiles */
+
+
+ /* Calculate tile height stuff */
+ heightInTiles = yres >> 5;
+
+ if (yres & (TILE_HEIGHT - 1))
+ heightInTiles++;
+
+ return heightInTiles;
+
+} /* calcBufferHeightInTiles */
+
+#if 0
+static int
+calcBufferSizeInTiles(int xres, int yres, int cpp) {
+ int bufSizeInTiles; /* Size of buffer in tiles */
+
+ bufSizeInTiles =
+ calcBufferHeightInTiles(yres) * (calcBufferStride(xres, TRUE, cpp) >> 7);
+
+ return bufSizeInTiles;
+
+} /* calcBufferSizeInTiles */
+#endif
+
+static int
+calcBufferSize(int xres, int yres, Bool tiled, int cpp)
+{
+ int stride, height, bufSize;
+
+ if (tiled) {
+ stride = calcBufferStride(xres, tiled, cpp);
+ height = TILE_HEIGHT * calcBufferHeightInTiles(yres);
+ } else {
+ stride = xres*cpp;
+ height = yres;
+ }
+
+ bufSize = stride * height;
+
+ return bufSize;
+
+} /* calcBufferSize */
+
+static void allocateMemory(ScrnInfoPtr pScrn) {
+ TDFXPtr pTDFX;
+ int memRemaining, fifoSize, screenSizeInTiles, cursorSize;
+ int fbSize;
+ int verb;
+ char *str;
+
+ pTDFX = TDFXPTR(pScrn);
+
+ if (pTDFX->cpp!=3) {
+ screenSizeInTiles=calcBufferSize(pScrn->virtualX, pScrn->virtualY,
+ TRUE, pTDFX->cpp);
+ }
+ else {
+ /* cpp==3 needs to bump up to 4 */
+ screenSizeInTiles=calcBufferSize(pScrn->virtualX, pScrn->virtualY,
+ TRUE, 4);
+ }
+
+ /*
+ * Layout is:
+ * cursor, fifo, fb, tex, bb, db
+ */
+
+ fbSize = (pScrn->virtualY + pTDFX->pixmapCacheLinesMin) * pTDFX->stride;
+
+ memRemaining=((pScrn->videoRam<<10) - 1) &~ 0xFFF;
+ /* Note that a page is 4096 bytes, and a */
+ /* tile is 32 x 128 = 4096 bytes. So, */
+ /* page and tile boundaries are the same */
+ /* Place the depth offset first, forcing */
+ /* it to be on an *odd* page boundary. */
+ pTDFX->depthOffset = (memRemaining - screenSizeInTiles) &~ 0xFFF;
+ if ((pTDFX->depthOffset & (0x1 << 12)) == 0) {
+#if 1
+ if (pTDFX->depthOffset > 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Changing depth offset from 0x%08x to 0x%08x\n",
+ pTDFX->depthOffset,
+ pTDFX->depthOffset - (0x1 << 12));
+ }
+#endif
+ pTDFX->depthOffset -= (0x1 << 12);
+ }
+ /* Now, place the back buffer, forcing it */
+ /* to be on an *even* page boundary. */
+ pTDFX->backOffset = (pTDFX->depthOffset - screenSizeInTiles) &~ 0xFFF;
+ if (pTDFX->backOffset & (0x1 << 12)) {
+#if 1
+ if (pTDFX->backOffset > 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Changing back offset from 0x%08x to 0x%08x\n",
+ pTDFX->backOffset,
+ pTDFX->backOffset - (0x1 << 12));
+ }
+#endif
+ pTDFX->backOffset -= (0x1 << 12);
+ }
+ /* Give the cmd fifo at least */
+ /* CMDFIFO_PAGES pages, but no more than */
+ /* 64. NOTE: Don't go higher than 64, as */
+ /* there is suspect code in Glide3 ! */
+ fifoSize = ((64 <= CMDFIFO_PAGES) ? 64 : CMDFIFO_PAGES) << 12;
+
+ /* We give 4096 bytes to the cursor */
+ cursorSize = 4096;
+ pTDFX->cursorOffset = 0;
+
+ pTDFX->fifoOffset = pTDFX->cursorOffset + cursorSize;
+ pTDFX->fifoSize = fifoSize;
+ /* Now, place the front buffer, forcing */
+ /* it to be on a page boundary too, just */
+ /* for giggles. */
+ pTDFX->fbOffset = pTDFX->fifoOffset + pTDFX->fifoSize;
+ pTDFX->texOffset = pTDFX->fbOffset + fbSize;
+ if (pTDFX->depthOffset <= pTDFX->texOffset ||
+ pTDFX->backOffset <= pTDFX->texOffset) {
+ /*
+ * pTDFX->texSize < 0 means that the DRI is disabled. pTDFX->backOffset
+ * is used to calculate the maximum amount of memory available for
+ * 2D offscreen use. With DRI disabled, set this to the top of memory.
+ */
+
+ pTDFX->texSize = -1;
+ pTDFX->backOffset = pScrn->videoRam * 1024;
+ pTDFX->depthOffset = -1;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Not enough video memory available for textures and depth buffer\n"
+ "\tand/or back buffer. Disabling DRI. To use DRI try lower\n"
+ "\tresolution modes and/or a smaller virtual screen size\n");
+ } else {
+ pTDFX->texSize = pTDFX->backOffset - pTDFX->texOffset;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Textures Memory %0.02f MB\n",
+ (float)pTDFX->texSize/1024.0/1024.0);
+ }
+
+/* This could be set to 2 or 3 */
+#define OFFSET_VERB 1
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, OFFSET_VERB,
+ "Cursor Offset: [0x%08X,0x%08X)\n",
+ pTDFX->cursorOffset,
+ pTDFX->cursorOffset + cursorSize);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, OFFSET_VERB,
+ "Fifo Offset: [0x%08X, 0x%08X)\n",
+ pTDFX->fifoOffset,
+ pTDFX->fifoOffset + pTDFX->fifoSize);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, OFFSET_VERB,
+ "Front Buffer Offset: [0x%08X, 0x%08X)\n",
+ pTDFX->fbOffset,
+ pTDFX->fbOffset +
+ (pScrn->virtualY+pTDFX->pixmapCacheLinesMin)*pTDFX->stride);
+ if (pTDFX->texSize > 0) {
+ verb = OFFSET_VERB;
+ str = "";
+ } else {
+ verb = 3;
+ str = "(NOT USED) ";
+ }
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verb,
+ "%sTexture Offset: [0x%08X, 0x%08X)\n", str,
+ pTDFX->texOffset,
+ pTDFX->texOffset + pTDFX->texSize);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verb,
+ "%sBackOffset: [0x%08X, 0x%08X)\n", str,
+ pTDFX->backOffset,
+ pTDFX->backOffset + screenSizeInTiles);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verb,
+ "%sDepthOffset: [0x%08X, 0x%08X)\n", str,
+ pTDFX->depthOffset,
+ pTDFX->depthOffset + screenSizeInTiles);
+}
+
+static Bool
+TDFXScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) {
+ ScrnInfoPtr pScrn;
+ vgaHWPtr hwp;
+ TDFXPtr pTDFX;
+ VisualPtr visual;
+ BoxRec MemBox;
+#ifdef XF86DRI
+ MessageType driFrom = X_DEFAULT;
+#endif
+ int scanlines;
+
+ TDFXTRACE("TDFXScreenInit start\n");
+ pScrn = xf86Screens[pScreen->myNum];
+ pTDFX = TDFXPTR(pScrn);
+ hwp = VGAHWPTR(pScrn);
+
+ if (!TDFXMapMem(pScrn)) return FALSE;
+ pScrn->memPhysBase = (int)pTDFX->LinearAddr[0];
+
+ if (!pTDFX->usePIO) TDFXSetMMIOAccess(pTDFX);
+
+#if USE_PCIVGAIO
+ hwp->PIOOffset = pTDFX->PIOBase[0] - 0x300;
+#endif
+ vgaHWGetIOBase(hwp);
+ /* Map VGA memory only for primary cards (to save/restore textmode data). */
+ if (pTDFX->Primary) {
+ if (!vgaHWMapMem(pScrn))
+ return FALSE;
+ }
+
+ pTDFX->stride = pScrn->displayWidth*pTDFX->cpp;
+
+ /* enough to do DVD */
+ pTDFX->pixmapCacheLinesMin = ((720*480*pTDFX->cpp) +
+ pTDFX->stride - 1)/pTDFX->stride;
+
+ if (pTDFX->ChipType > PCI_CHIP_VOODOO3) {
+ if ((pTDFX->pixmapCacheLinesMin + pScrn->virtualY) > 4095)
+ pTDFX->pixmapCacheLinesMin = 4095 - pScrn->virtualY;
+ } else {
+ if ((pTDFX->pixmapCacheLinesMin + pScrn->virtualY) > 2047)
+ pTDFX->pixmapCacheLinesMin = 2047 - pScrn->virtualY;
+ }
+
+ allocateMemory(pScrn);
+
+ pScrn->fbOffset = pTDFX->fbOffset;
+
+#if 0
+ if (pTDFX->numChips>1) {
+ if (xf86ReturnOptValBool(pTDFX->Options, OPTION_NO_SLI, FALSE)) {
+ TDFXSetupSLI(pScrn, FALSE, 0);
+ } else {
+ TDFXSetupSLI(pScrn, TRUE, 0);
+ }
+ }
+#endif
+
+ TDFXSetLFBConfig(pTDFX);
+
+ /* We initialize in the state that our FIFO is up to date */
+ pTDFX->syncDone=TRUE;
+ if (!TDFXInitFifo(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to initialize private\n");
+ return FALSE;
+ }
+
+ scanlines = (pTDFX->backOffset - pTDFX->fbOffset) / pTDFX->stride;
+ if(pTDFX->ChipType < PCI_CHIP_VOODOO5) {
+ if (scanlines > 2047)
+ scanlines = 2047;
+ } else {
+ /* MaxClip seems to have only 12 bits => 0->4095 */
+ if (scanlines > 4095)
+ scanlines = 4095;
+ }
+
+ pTDFX->pixmapCacheLinesMax = scanlines - pScrn->virtualY;
+
+ /*
+ * Note, pTDFX->pixmapCacheLinesMax may be smaller than
+ * pTDFX->pixmapCacheLinesMin when pTDFX->texSize < 0. DRI is disabled
+ * in that case, so pTDFX->pixmapCacheLinesMin isn't used when that's true.
+ */
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Minimum %d, Maximum %d lines of offscreen memory available\n",
+ pTDFX->pixmapCacheLinesMin, pTDFX->pixmapCacheLinesMax);
+
+ MemBox.y1 = 0;
+ MemBox.x1 = 0;
+ MemBox.x2 = pScrn->displayWidth;
+ MemBox.y2 = scanlines;
+
+ pTDFX->maxClip = MemBox.x2 | (MemBox.y2 << 16);
+
+#if 0
+ TDFXInitWithBIOSData(pScrn);
+#endif
+ TDFXInitVGA(pScrn);
+ TDFXSave(pScrn);
+ if (!TDFXModeInit(pScrn, pScrn->currentMode)) return FALSE;
+
+ TDFXSetLFBConfig(pTDFX);
+
+ miClearVisualTypes();
+
+ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+
+ miSetPixmapDepths ();
+
+ pTDFX->NoAccel=xf86ReturnOptValBool(pTDFX->Options, OPTION_NOACCEL, FALSE);
+#ifdef XF86DRI
+ /*
+ * Setup DRI after visuals have been established, but before fbScreenInit
+ * is called. fbScreenInit will eventually call into the drivers
+ * InitGLXVisuals call back.
+ */
+ if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_DRI, TRUE) || pTDFX->NoAccel) {
+ pTDFX->directRenderingEnabled = FALSE;
+ driFrom = X_CONFIG;
+ } else if (pTDFX->texSize < 0) {
+ pTDFX->directRenderingEnabled = FALSE;
+ driFrom = X_PROBED;
+ } else {
+ pTDFX->directRenderingEnabled = TDFXDRIScreenInit(pScreen);
+ }
+#endif
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ if (!fbScreenInit(pScreen, pTDFX->FbBase+pTDFX->fbOffset,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ pScrn->displayWidth, pScrn->bitsPerPixel))
+ return FALSE;
+ break;
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Internal error: invalid bpp (%d) in TDFXScrnInit\n",
+ pScrn->bitsPerPixel);
+ return FALSE;
+ }
+
+ if (pScrn->bitsPerPixel>8) {
+ visual = pScreen->visuals + pScreen->numVisuals;
+ while (--visual >= pScreen->visuals) {
+ if ((visual->class | DynamicClass) == DirectColor) {
+ visual->offsetRed = pScrn->offset.red;
+ visual->offsetGreen = pScrn->offset.green;
+ visual->offsetBlue = pScrn->offset.blue;
+ visual->redMask = pScrn->mask.red;
+ visual->greenMask = pScrn->mask.green;
+ visual->blueMask = pScrn->mask.blue;
+ }
+ }
+ }
+
+ /* must be after RGB ordering fixed */
+ fbPictureInit (pScreen, 0, 0);
+
+ xf86SetBlackWhitePixels(pScreen);
+
+ TDFXDGAInit(pScreen);
+
+ xf86InitFBManager(pScreen, &MemBox);
+
+ if (!pTDFX->NoAccel) {
+ if (!TDFXAccelInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware acceleration initialization failed\n");
+ }
+ }
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ xf86SetSilkenMouse(pScreen);
+
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ if (!xf86ReturnOptValBool(pTDFX->Options, OPTION_SW_CURSOR, FALSE)) {
+ if (!TDFXCursorInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ }
+ }
+
+ if (!miCreateDefColormap(pScreen)) return FALSE;
+
+ if (pScrn->bitsPerPixel==16) {
+ if (!xf86HandleColormaps(pScreen, 256, 8, TDFXLoadPalette16, 0,
+ CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ } else {
+ if (!xf86HandleColormaps(pScreen, 256, 8, TDFXLoadPalette24, 0,
+ CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
+ return FALSE;
+ }
+
+ TDFXAdjustFrame(scrnIndex, 0, 0, 0);
+
+ xf86DPMSInit(pScreen, TDFXDisplayPowerManagementSet, 0);
+
+#ifdef XF86DRI
+ if (pTDFX->directRenderingEnabled) {
+ /* Now that mi, fb, drm and others have done their thing,
+ * complete the DRI setup.
+ */
+ pTDFX->directRenderingEnabled = TDFXDRIFinishScreenInit(pScreen);
+ }
+ if (pTDFX->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, driFrom, "Direct rendering enabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, driFrom, "Direct rendering disabled\n");
+ }
+#endif
+
+
+#ifdef XvExtension
+ /* Initialize Xv support */
+ TDFXInitVideo (pScreen);
+#endif
+
+ pScreen->SaveScreen = TDFXSaveScreen;
+ pTDFX->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = TDFXCloseScreen;
+
+ pTDFX->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = TDFXBlockHandler;
+
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+ return TRUE;
+}
+
+Bool
+TDFXSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) {
+ ScrnInfoPtr pScrn;
+
+ TDFXTRACE("TDFXSwitchMode start\n");
+ pScrn=xf86Screens[scrnIndex];
+ return TDFXModeInit(pScrn, mode);
+}
+
+void
+TDFXAdjustFrame(int scrnIndex, int x, int y, int flags) {
+ ScrnInfoPtr pScrn;
+ TDFXPtr pTDFX;
+ TDFXRegPtr tdfxReg;
+
+ TDFXTRACE("TDFXAdjustFrame start\n");
+ pScrn = xf86Screens[scrnIndex];
+ pTDFX = TDFXPTR(pScrn);
+
+ if (pTDFX->ShowCache && y && pScrn->vtSema)
+ y += pScrn->virtualY - 1;
+
+ tdfxReg = &pTDFX->ModeReg;
+ if(pTDFX->ShowCache && y && pScrn->vtSema)
+ y += pScrn->virtualY - 1;
+ tdfxReg->startaddr = pTDFX->fbOffset+y*pTDFX->stride+(x*pTDFX->cpp);
+ TDFXTRACE("TDFXAdjustFrame to x=%d y=%d offset=%d\n", x, y, tdfxReg->startaddr);
+ pTDFX->writeLong(pTDFX, VIDDESKTOPSTARTADDR, tdfxReg->startaddr);
+}
+
+static Bool
+TDFXEnterVT(int scrnIndex, int flags) {
+ ScrnInfoPtr pScrn;
+ ScreenPtr pScreen;
+#ifdef XF86DRI
+ TDFXPtr pTDFX;
+#endif
+
+ TDFXTRACE("TDFXEnterVT start\n");
+ pScrn = xf86Screens[scrnIndex];
+ pScreen = screenInfo.screens[scrnIndex];
+ TDFXInitFifo(pScreen);
+#ifdef XF86DRI
+ pTDFX = TDFXPTR(pScrn);
+ if (pTDFX->directRenderingEnabled) {
+ DRIUnlock(pScreen);
+ }
+#endif
+ if (!TDFXModeInit(pScrn, pScrn->currentMode)) return FALSE;
+ TDFXAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+ return TRUE;
+}
+
+static void
+TDFXLeaveVT(int scrnIndex, int flags) {
+ ScrnInfoPtr pScrn;
+ vgaHWPtr hwp;
+ ScreenPtr pScreen;
+ TDFXPtr pTDFX;
+
+ TDFXTRACE("TDFXLeaveVT start\n");
+ pScrn = xf86Screens[scrnIndex];
+ hwp=VGAHWPTR(pScrn);
+ TDFXRestore(pScrn);
+ vgaHWLock(hwp);
+ pScreen = screenInfo.screens[scrnIndex];
+ pTDFX = TDFXPTR(pScrn);
+ pTDFX->sync(pScrn);
+ TDFXShutdownFifo(pScreen);
+#ifdef XF86DRI
+ if (pTDFX->directRenderingEnabled) {
+ DRILock(pScreen, 0);
+ }
+#endif
+}
+
+static Bool
+TDFXCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ vgaHWPtr hwp;
+ TDFXPtr pTDFX;
+
+ TDFXTRACE("TDFXCloseScreen start\n");
+ pScrn = xf86Screens[scrnIndex];
+ hwp = VGAHWPTR(pScrn);
+ pTDFX = TDFXPTR(pScrn);
+
+#ifdef XF86DRI
+ if (pTDFX->directRenderingEnabled) {
+ TDFXDRICloseScreen(pScreen);
+ pTDFX->directRenderingEnabled=FALSE;
+ }
+#endif
+
+ TDFXShutdownFifo(pScreen);
+
+ if (pScrn->vtSema) {
+ TDFXRestore(pScrn);
+ vgaHWLock(hwp);
+ TDFXUnmapMem(pScrn);
+ vgaHWUnmapMem(pScrn);
+ }
+
+ if (pTDFX->AccelInfoRec) XAADestroyInfoRec(pTDFX->AccelInfoRec);
+ pTDFX->AccelInfoRec=0;
+ if (pTDFX->DGAModes) xfree(pTDFX->DGAModes);
+ pTDFX->DGAModes=0;
+ if (pTDFX->scanlineColorExpandBuffers[0])
+ xfree(pTDFX->scanlineColorExpandBuffers[0]);
+ pTDFX->scanlineColorExpandBuffers[0]=0;
+ if (pTDFX->scanlineColorExpandBuffers[1])
+ xfree(pTDFX->scanlineColorExpandBuffers[1]);
+ pTDFX->scanlineColorExpandBuffers[1]=0;
+ if (pTDFX->overlayAdaptor)
+ xfree(pTDFX->overlayAdaptor);
+ pTDFX->overlayAdaptor=0;
+ if (pTDFX->textureAdaptor)
+ xfree(pTDFX->textureAdaptor);
+ pTDFX->textureAdaptor=0;
+
+ pScrn->vtSema=FALSE;
+
+ pScreen->BlockHandler = pTDFX->BlockHandler;
+ pScreen->CloseScreen = pTDFX->CloseScreen;
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+static void
+TDFXFreeScreen(int scrnIndex, int flags) {
+ TDFXTRACE("TDFXFreeScreen start\n");
+ TDFXFreeRec(xf86Screens[scrnIndex]);
+ if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
+ vgaHWFreeHWRec(xf86Screens[scrnIndex]);
+}
+
+static int
+TDFXValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) {
+ TDFXTRACE("TDFXValidMode start\n");
+ if ((mode->HDisplay>2048) || (mode->VDisplay>1536))
+ return MODE_BAD;
+ /* Banshee doesn't support interlace. Does V3? */
+ if (mode->Flags&V_INTERLACE)
+ return MODE_BAD;
+ /* In clock doubled mode widths must be divisible by 16 instead of 8 */
+ if ((mode->Clock>TDFX2XCUTOFF) && (mode->HDisplay%16))
+ return MODE_BAD;
+ return MODE_OK;
+}
+
+/* replacement of vgaHWBlankScreen(pScrn, unblank) which doesn't unblank
+ * the screen if it is already unblanked. */
+static void
+TDFXBlankScreen(ScrnInfoPtr pScrn, Bool unblank)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ unsigned char scrn;
+
+ TDFXTRACE("TDFXBlankScreen start\n");
+
+ scrn = hwp->readSeq(hwp, 0x01);
+
+ if (unblank) {
+ if((scrn & 0x20) == 0) return;
+ scrn &= ~0x20; /* enable screen */
+ } else {
+ scrn |= 0x20; /* blank screen */
+ }
+
+ vgaHWSeqReset(hwp, TRUE);
+ hwp->writeSeq(hwp, 0x01, scrn); /* change mode */
+ vgaHWSeqReset(hwp, FALSE);
+}
+
+static Bool
+TDFXSaveScreen(ScreenPtr pScreen, int mode)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ Bool unblank;
+
+ TDFXTRACE("TDFXSaveScreen start\n");
+
+ unblank = xf86IsUnblank(mode);
+
+ if (unblank)
+ SetTimeSinceLastInputEvent();
+
+ if (pScrn->vtSema) {
+ TDFXBlankScreen(pScrn, unblank);
+ }
+ return TRUE;
+}
+
+static void
+TDFXBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ pScreen->BlockHandler = pTDFX->BlockHandler;
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+ pScreen->BlockHandler = TDFXBlockHandler;
+
+ if(pTDFX->VideoTimerCallback) {
+ (*pTDFX->VideoTimerCallback)(pScrn, currentTime.milliseconds);
+ }
+}
+
+static void
+TDFXDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags) {
+ TDFXPtr pTDFX;
+ int dacmode, state=0;
+
+ TDFXTRACE("TDFXDPMS start\n");
+ pTDFX = TDFXPTR(pScrn);
+ dacmode=pTDFX->readLong(pTDFX, DACMODE);
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ /* Screen: On; HSync: On, VSync: On */
+ state=0;
+ break;
+ case DPMSModeStandby:
+ /* Screen: Off; HSync: Off, VSync: On */
+ state=BIT(3);
+ break;
+ case DPMSModeSuspend:
+ /* Screen: Off; HSync: On, VSync: Off */
+ state=BIT(1);
+ break;
+ case DPMSModeOff:
+ /* Screen: Off; HSync: Off, VSync: Off */
+ state=BIT(1)|BIT(3);
+ break;
+ }
+ dacmode&=~(BIT(1)|BIT(3));
+ dacmode|=state;
+ pTDFX->writeLong(pTDFX, DACMODE, dacmode);
+}
diff --git a/src/tdfx_hwcurs.c b/src/tdfx_hwcurs.c
new file mode 100644
index 0000000..637ece4
--- /dev/null
+++ b/src/tdfx_hwcurs.c
@@ -0,0 +1,153 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_hwcurs.c,v 1.5 2001/10/28 03:33:50 tsi Exp $ */
+/*
+ Voodoo Banshee driver version 1.0.2
+
+ Author: Daryll Strauss
+
+ Copyright: 1998,1999
+*/
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86fbman.h"
+
+#include "tdfx.h"
+
+static void TDFXLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
+static void TDFXShowCursor(ScrnInfoPtr pScrn);
+static void TDFXHideCursor(ScrnInfoPtr pScrn);
+static void TDFXSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
+static void TDFXSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
+static Bool TDFXUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
+
+Bool
+TDFXCursorInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ TDFXPtr pTDFX;
+ xf86CursorInfoPtr infoPtr;
+
+ TDFXTRACECURS("TDFXCursorInit start\n");
+ pScrn = xf86Screens[pScreen->myNum];
+ pTDFX = TDFXPTR(pScrn);
+ pTDFX->CursorInfoRec = infoPtr = xf86CreateCursorInfoRec();
+ if (!infoPtr) return FALSE;
+
+ infoPtr->MaxWidth = 64;
+ infoPtr->MaxHeight = 64;
+
+ infoPtr->Flags =
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
+#endif
+ HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK|
+ HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
+ HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
+ infoPtr->SetCursorColors = TDFXSetCursorColors;
+ infoPtr->SetCursorPosition = TDFXSetCursorPosition;
+ infoPtr->LoadCursorImage = TDFXLoadCursorImage;
+ infoPtr->HideCursor = TDFXHideCursor;
+ infoPtr->ShowCursor = TDFXShowCursor;
+ infoPtr->UseHWCursor = TDFXUseHWCursor;
+
+ pTDFX->ModeReg.cursloc = pTDFX->cursorOffset;
+ pTDFX->writeLong(pTDFX, HWCURPATADDR, pTDFX->cursorOffset);
+
+ return xf86InitCursor(pScreen, infoPtr);
+}
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+static unsigned int TDFXSwap(TDFXPtr pTDFX, unsigned int val) {
+ switch (pTDFX->cpp) {
+ default:
+ return val;
+ case 2:
+ return ((val & 0x00ff00ff) << 8) |
+ ((val & 0xff00ff00) >> 8);
+ case 3:
+ case 4:
+ return BE_BSWAP32(val);
+ }
+}
+#endif
+
+static void
+TDFXLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACECURS("TDFXLoadCursorImage start\n");
+ pTDFX = TDFXPTR(pScrn);
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ {
+ int i;
+ unsigned int *ptr=(unsigned int *)(pTDFX->FbBase+pTDFX->cursorOffset);
+
+ for (i=0; i<256; i++) {
+ unsigned int val = ((unsigned int *)src)[i];
+ *ptr++ = TDFXSwap(pTDFX, val);
+ }
+ }
+#else
+ memcpy(pTDFX->FbBase+pTDFX->cursorOffset, src, 1024);
+#endif
+}
+
+static void
+TDFXShowCursor(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACECURS("TDFXShowCursor start\n");
+ pTDFX = TDFXPTR(pScrn);
+ pTDFX->ModeReg.vidcfg|=BIT(27);
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+}
+
+void
+TDFXHideCursor(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACECURS("TDFXHideCursor start\n");
+ pTDFX = TDFXPTR(pScrn);
+ pTDFX->ModeReg.vidcfg&=~BIT(27);
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+}
+
+static void
+TDFXSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ TDFXPtr pTDFX;
+
+ /* TDFXTRACECURS("TDFXSetCursorPosition start\n"); */
+ pTDFX = TDFXPTR(pScrn);
+ pTDFX->writeLong(pTDFX, HWCURLOC, ((y+64)<<16)|(x+64));
+}
+
+static void
+TDFXSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ TDFXPtr pTDFX;
+
+ TDFXTRACECURS("TDFXSetCursorColors start\n");
+ pTDFX = TDFXPTR(pScrn);
+ pTDFX->writeLong(pTDFX, HWCURC0, bg);
+ pTDFX->writeLong(pTDFX, HWCURC1, fg);
+}
+
+static Bool
+TDFXUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ ScrnInfoPtr pScrn;
+ TDFXPtr pTDFX;
+
+ TDFXTRACECURS("TDFXUseHWCursor start\n");
+ pScrn = xf86Screens[pScreen->myNum];
+ pTDFX = TDFXPTR(pScrn);
+ if (pScrn->currentMode->Flags&V_DBLSCAN)
+ return FALSE;
+ if (!pTDFX->CursorInfoRec) return FALSE;
+ return TRUE;
+}
diff --git a/src/tdfx_io.c b/src/tdfx_io.c
new file mode 100644
index 0000000..5de08d7
--- /dev/null
+++ b/src/tdfx_io.c
@@ -0,0 +1,120 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_io.c,v 1.7 2001/04/05 21:29:17 dawes Exp $ */
+
+/*
+ * Authors:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ *
+ */
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+
+#include "tdfx.h"
+
+#define minb(b, p) MMIO_IN8((b), (p))
+#define moutb(b, p,v) MMIO_OUT8((b), (p),(v))
+#define minl(b, p) MMIO_IN32((b), (p))
+#define moutl(b, p,v) MMIO_OUT32((b), (p),(v))
+
+static void TDFXWriteControlPIO(TDFXPtr pTDFX, int addr, char index, char val) {
+ outb(pTDFX->PIOBase[0]+addr, index);
+ outb(pTDFX->PIOBase[0]+addr+1, val);
+}
+
+static char TDFXReadControlPIO(TDFXPtr pTDFX, int addr, char index) {
+ outb(pTDFX->PIOBase[0]+addr, index);
+ return inb(pTDFX->PIOBase[0]+addr+1);
+}
+
+static void TDFXWriteChipLongPIO(TDFXPtr pTDFX, int chip, int addr, int val) {
+ outl(pTDFX->PIOBase[chip]+addr, val);
+}
+
+static int TDFXReadChipLongPIO(TDFXPtr pTDFX, int chip, int addr) {
+ return inl(pTDFX->PIOBase[chip]+addr);
+}
+
+static void TDFXWriteLongPIO(TDFXPtr pTDFX, int addr, int val) {
+ TDFXWriteChipLongPIO(pTDFX, 0, addr, val);
+}
+
+static int TDFXReadLongPIO(TDFXPtr pTDFX, int addr) {
+ return TDFXReadChipLongPIO(pTDFX, 0, addr);
+}
+
+void TDFXSetPIOAccess(TDFXPtr pTDFX) {
+ if (!pTDFX->PIOBase[0])
+ ErrorF("Can not set PIO Access before PIOBase[0]\n");
+ pTDFX->writeControl=TDFXWriteControlPIO;
+ pTDFX->readControl=TDFXReadControlPIO;
+ pTDFX->writeLong=TDFXWriteLongPIO;
+ pTDFX->readLong=TDFXReadLongPIO;
+ pTDFX->readChipLong=TDFXReadChipLongPIO;
+ pTDFX->writeChipLong=TDFXWriteChipLongPIO;
+}
+
+static void TDFXWriteControlMMIO(TDFXPtr pTDFX, int addr, char index, char val) {
+ moutb(pTDFX->MMIOBase[0], addr, index);
+ moutb(pTDFX->MMIOBase[0], addr+1, val);
+}
+
+static char TDFXReadControlMMIO(TDFXPtr pTDFX, int addr, char index) {
+ moutb(pTDFX->MMIOBase[0], addr, index);
+ return minb(pTDFX->MMIOBase[0], addr+1);
+}
+
+void TDFXWriteChipLongMMIO(TDFXPtr pTDFX, int chip, int addr, int val) {
+ moutl(pTDFX->MMIOBase[chip], addr, val);
+}
+
+static int TDFXReadChipLongMMIO(TDFXPtr pTDFX, int chip, int addr) {
+ return minl(pTDFX->MMIOBase[chip], addr);
+}
+
+void TDFXWriteLongMMIO(TDFXPtr pTDFX, int addr, int val) {
+ TDFXWriteChipLongMMIO(pTDFX, 0, addr, val);
+}
+
+int TDFXReadLongMMIO(TDFXPtr pTDFX, int addr) {
+ return TDFXReadChipLongMMIO(pTDFX, 0, addr);
+}
+
+void TDFXSetMMIOAccess(TDFXPtr pTDFX) {
+ if (!pTDFX->MMIOBase[0])
+ ErrorF("Can not set MMIO access before MMIOBase[0]\n");
+ pTDFX->writeControl=TDFXWriteControlMMIO;
+ pTDFX->readControl=TDFXReadControlMMIO;
+ pTDFX->writeLong=TDFXWriteLongMMIO;
+ pTDFX->readLong=TDFXReadLongMMIO;
+ pTDFX->writeChipLong=TDFXWriteChipLongMMIO;
+ pTDFX->readChipLong=TDFXReadChipLongMMIO;
+}
+
diff --git a/src/tdfx_priv.c b/src/tdfx_priv.c
new file mode 100644
index 0000000..c4de4ce
--- /dev/null
+++ b/src/tdfx_priv.c
@@ -0,0 +1,358 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_priv.c,v 1.16 2001/05/21 21:43:55 dawes Exp $ */
+
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86fbman.h"
+#include "compiler.h"
+#include "tdfx.h"
+
+/*
+ Memory layout of card is as follows:
+
+ 000000-00ffff: VGA memory
+ 010000-013fff: Cursor
+ 011000-xxxxxx: Fifo (Min of CMDFIFO pages)
+ xxxxxx- A-1 : Front Buffer (framebuffer)
+ A - B-1 : Pixmap Cache (framebuffer)
+ B - C-1 : Texture Memory
+ C - D-1 : Back Buffer
+ D - E-1 : Depth Buffer
+
+ NB: pixmap cache usually butts right up against texture memory. when
+ 3d is disabled (via Transition2D) then the pixmap cache is increased
+ to overlap the texture memory. maximum pixmap cache of 4095 lines on
+ voodoo5 and 2048 on voodoo3/4 applies.
+*/
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+void TDFXWriteFifo_24(TDFXPtr pTDFX, int val) {
+ *pTDFX->fifoPtr++ = val;
+}
+
+void TDFXWriteFifo_16(TDFXPtr pTDFX, int val) {
+ *pTDFX->fifoPtr++ = BE_WSWAP32(val);
+}
+
+void TDFXWriteFifo_8(TDFXPtr pTDFX, int val) {
+ *pTDFX->fifoPtr++ = BE_BSWAP32(val);
+}
+#endif
+
+
+static void TDFXSendNOPFifo3D(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+
+ pTDFX=TDFXPTR(pScrn);
+ TDFXAllocateSlots(pTDFX, 2);
+ SET_3DPK4_HEADER(1, 0x48<<3);
+ WRITE_FIFO(pTDFX, 0, 0);
+}
+
+void TDFXSendNOPFifo2D(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+
+ pTDFX=TDFXPTR(pScrn);
+ if (!pTDFX->syncDone) {
+ TDFXFirstSync(pScrn);
+ return;
+ }
+ TDFXAllocateSlots(pTDFX, 2);
+ SET_PKT2_HEADER(SSTCP_COMMAND);
+ WRITE_FIFO(pTDFX, SST_2D_COMMAND, SST_2D_NOP|SST_2D_GO);
+}
+
+void TDFXSendNOPFifo(ScrnInfoPtr pScrn)
+{
+ TDFXSendNOPFifo2D(pScrn);
+ TDFXSendNOPFifo3D(pScrn);
+}
+
+static void InstallFifo(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+
+ pTDFX=TDFXPTR(pScrn);
+ /* Install the fifo */
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASEADDR0, pTDFX->fifoOffset>>12);
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_BUMP0, 0);
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_RDPTRL0, pTDFX->fifoOffset);
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_RDPTRH0, 0);
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_AMIN0, pTDFX->fifoOffset-4);
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_AMAX0, pTDFX->fifoOffset-4);
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_DEPTH0, 0);
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_HOLECNT0, 0);
+ if (pTDFX->ChipType == PCI_CHIP_BANSHEE)
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_FIFOTHRESH, (0x9<<5) | 0x2);
+ else
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_FIFOTHRESH, (0xf<<5) | 0x8);
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, ((pTDFX->fifoSize>>12)-1) |
+ SST_EN_CMDFIFO);
+ /* Set the internal state */
+ pTDFX->fifoRead = pTDFX->fifoBase;
+ pTDFX->fifoPtr = pTDFX->fifoBase;
+ pTDFX->fifoSlots = (pTDFX->fifoSize>>2) - 1;
+ pTDFX->fifoEnd = pTDFX->fifoBase+pTDFX->fifoSlots;
+ TDFXSendNOPFifo(pScrn);
+}
+
+static void TDFXResetFifo(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+ int oldValue;
+ long start_sec, end_sec, dummy;
+
+ pTDFX=TDFXPTR(pScrn);
+ ErrorF("Resetting FIFO\n");
+ /* Shut down the fifo */
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, 0);
+ /* Toggle the reset bits */
+ oldValue=TDFXReadLongMMIO(pTDFX, MISCINIT0);
+ TDFXWriteLongMMIO(pTDFX, MISCINIT0, oldValue|0x23);
+ getsecs(&start_sec, &dummy);
+ do {
+ getsecs(&end_sec, &dummy);
+ } while (end_sec-start_sec<2);
+ TDFXWriteLongMMIO(pTDFX, MISCINIT0, oldValue);
+ oldValue=TDFXReadLongMMIO(pTDFX, MISCINIT1);
+ TDFXWriteLongMMIO(pTDFX, MISCINIT1, oldValue|BIT(19));
+ getsecs(&start_sec, &dummy);
+ do {
+ getsecs(&end_sec, &dummy);
+ } while (end_sec-start_sec<2);
+ TDFXWriteLongMMIO(pTDFX, MISCINIT1, oldValue);
+ InstallFifo(pScrn);
+}
+
+/*
+ There are two steps to fully syncing the board:
+
+ 1) Send a NOP, which waits for any commands in progress
+ 2) Read the status register for 3 consecutive non-busy
+
+ !!! We should use expedential backoff in our reads !!!
+*/
+static void TDFXSyncFifo(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX;
+ int i, cnt, resets=0;
+ int stat;
+ long start_sec, end_sec, dummy, readptr;
+
+ TDFXTRACEACCEL("TDFXSyncFifo start\n");
+ pTDFX=TDFXPTR(pScrn);
+ TDFXSendNOPFifo(pScrn);
+ i=0;
+ cnt=0;
+ start_sec=0;
+ readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
+ do {
+ readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
+ stat=TDFXReadLongMMIO(pTDFX, 0);
+ if (stat&SST_BUSY) i=0; else i++;
+ cnt++;
+ if (cnt==1000) {
+ if (!start_sec) {
+ getsecs(&start_sec, &dummy);
+ } else {
+ getsecs(&end_sec, &dummy);
+ if (end_sec-start_sec>3) {
+ dummy=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
+ if (dummy==readptr) {
+ TDFXResetFifo(pScrn);
+ readptr=dummy;
+ resets++;
+ if (resets==3) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Board is not responding.\n");
+ return;
+ }
+ }
+ start_sec=0;
+ }
+ }
+ cnt=0;
+ }
+ } while (i<3);
+ pTDFX->PciCnt=stat&0x1F;
+ pTDFX->prevBlitDest.x1=pTDFX->prevBlitDest.y1=0;
+ pTDFX->prevBlitDest.x2=pTDFX->prevBlitDest.y2=0;
+}
+
+Bool TDFXInitFifo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ TDFXPtr pTDFX;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pTDFX=TDFXPTR(pScrn);
+#ifdef DEBUG_FIFO
+ pTDFX->fifoMirrorBase=0;
+#endif
+ pTDFX->fifoBase = (uint32*)(pTDFX->FbBase+pTDFX->fifoOffset);
+#ifdef DEBUG_FIFO
+ pTDFX->fifoMirrorBase = xalloc(pTDFX->fifoSize);
+ pTDFX->fifoMirrorPtr = pTDFX->fifoMirrorBase;
+#endif
+ pTDFX->sync=TDFXSyncFifo;
+ InstallFifo(pScrn);
+ return TRUE;
+}
+
+void TDFXShutdownFifo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ TDFXPtr pTDFX;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pTDFX=TDFXPTR(pScrn);
+ TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, 0);
+ pTDFX->sync=TDFXSync;
+#ifdef DEBUG_FIFO
+ if (pTDFX->fifoMirrorBase) xfree(pTDFX->fifoMirrorBase);
+ pTDFX->fifoMirrorBase=0;
+#endif
+}
+
+static uint32
+GetReadPtr(TDFXPtr pTDFX)
+{
+ uint32 read_ptr, dummy;
+
+ do {
+ dummy = TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
+ read_ptr = TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
+ } while (read_ptr != dummy);
+ return read_ptr;
+}
+
+#ifdef XF86DRI
+void TDFXSwapContextFifo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ TDFXPtr pTDFX;
+ int dummy, readPos;
+ TDFXSAREAPriv *sPriv;
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pTDFX=TDFXPTR(pScrn);
+ sPriv=(TDFXSAREAPriv*)DRIGetSAREAPrivate(pScreen);
+ /* if (sPriv)
+ ErrorF("In FifoPtr=%d FifoRead=%d\n", sPriv->fifoPtr, sPriv->fifoRead); */
+#if 1
+ do {
+ dummy=TDFXReadLongMMIO(pTDFX, SST_FIFO_DEPTH0);
+ readPos=TDFXReadLongMMIO(pTDFX, SST_FIFO_DEPTH0);
+ } while (dummy || readPos);
+ readPos=(GetReadPtr(pTDFX)-pTDFX->fifoOffset)>>2;
+ pTDFX->fifoPtr = pTDFX->fifoBase+readPos;
+ pTDFX->fifoRead = pTDFX->fifoPtr;
+#else
+ sPriv=(TDFXSAREAPriv*)DRIGetSAREAPrivate(pScreen);
+ if (!sPriv) return;
+ if ((sPriv->fifoPtr<pTDFX->fifoOffset) ||
+ (sPriv->fifoPtr>(int)pTDFX->fifoOffset+pTDFX->fifoSize) ||
+ (sPriv->fifoRead<pTDFX->fifoOffset) ||
+ (sPriv->fifoRead>(int)pTDFX->fifoOffset+pTDFX->fifoSize)) {
+ ErrorF("Invalid offsets passed between client and X server\n");
+ ResetFifo(pScrn);
+ } else {
+ pTDFX->fifoPtr = (unsigned int *)(pTDFX->FbBase+sPriv->fifoPtr);
+ pTDFX->fifoRead = (unsigned int *)(pTDFX->FbBase+sPriv->fifoRead);
+ }
+#endif
+ if (pTDFX->fifoRead>pTDFX->fifoPtr)
+ pTDFX->fifoSlots = pTDFX->fifoRead-pTDFX->fifoPtr-1-8;
+ else
+ pTDFX->fifoSlots = pTDFX->fifoEnd-pTDFX->fifoPtr-8;
+}
+
+#endif
+
+static void
+TDFXMakeSpace(TDFXPtr pTDFX, uint32 slots)
+{
+ uint32 slots_available;
+
+ /*
+ ** Check to see if we have to wrap to get enough space.
+ */
+ if (slots > pTDFX->fifoEnd-pTDFX->fifoPtr) {
+ /*
+ ** Make sure that the read pointer is not ahead of us in the
+ ** the command fifo before wrapping.
+ ** This insures two things:
+ ** 1) There is room at fifo_ptr for the JMP packet.
+ ** 2) There are slots available at the beginning of the fifo up to the read_ptr.
+ **
+ ** Since we are wrapping, insure that the read pointer is not at the
+ ** beginning of the fifo to prevent the ambiguous situation described
+ ** below.
+ */
+ do {
+ pTDFX->fifoRead = (uint32*)(pTDFX->FbBase + GetReadPtr(pTDFX));
+ }
+ while (pTDFX->fifoRead>pTDFX->fifoPtr ||
+ pTDFX->fifoRead == pTDFX->fifoBase);
+ /*
+ ** Put a jump command in command fifo to wrap to the beginning.
+ */
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ WRITE_FIFO(pTDFX, 0, (pTDFX->fifoOffset >> 2) << SSTCP_PKT0_ADDR_SHIFT |
+ SSTCP_PKT0_JMP_LOCAL);
+#else
+ *pTDFX->fifoPtr = (pTDFX->fifoOffset >> 2) << SSTCP_PKT0_ADDR_SHIFT |
+ SSTCP_PKT0_JMP_LOCAL;
+#endif
+ FLUSH_WCB();
+
+ /*
+ ** Reset the fifo_ptr to the beginning of the command fifo.
+ */
+ pTDFX->fifoPtr = pTDFX->fifoBase;
+#ifdef DEBUG_FIFO
+ pTDFX->fifoMirrorPtr = pTDFX->fifoMirrorBase;
+#endif
+ }
+
+ /*
+ ** Wait for enough slots to satisfy the request.
+ */
+ do {
+ pTDFX->fifoRead = (uint32*)(pTDFX->FbBase + GetReadPtr(pTDFX));
+
+ /*
+ ** If the HW read_ptr is ahead the SW fifo_ptr, we don't allocate the
+ ** fifo slot immediately behind the HW read_ptr. This is to prevent
+ ** the following ambiguous situation...
+ **
+ ** If (HW read_ptr == SW fifo_ptr) is it because the HW read_ptr has
+ ** caught up to the SW fifo_ptr and the fifo is completely empty
+ ** OR is it because the SW fifo_ptr has caught up to the HW read_ptr
+ ** and the fifo is completely full?
+ */
+ if ((uint32*)pTDFX->fifoRead > pTDFX->fifoPtr)
+ slots_available = pTDFX->fifoRead - pTDFX->fifoPtr - 1;
+ else
+ slots_available = pTDFX->fifoEnd - pTDFX->fifoPtr;
+ } while (slots > slots_available);
+
+ pTDFX->fifoSlots = slots_available-slots;
+}
+
+void
+TDFXAllocateSlots(TDFXPtr pTDFX, int slots)
+{
+#ifdef TDFX_DEBUG_FIFO
+ if (pTDFX->fifoEnd-pTDFX->fifoPtr<pTDFX->fifoSlots)
+ ErrorF("FIFO overrun\n");
+ if (!pTDFX->syncDone) {
+ ErrorF("Writing to FIFO without sync\n");
+ }
+#endif
+ pTDFX->fifoSlots-=slots;
+ if (pTDFX->fifoSlots<0) TDFXMakeSpace(pTDFX, slots);
+}
diff --git a/src/tdfx_priv.h b/src/tdfx_priv.h
new file mode 100644
index 0000000..28f72f3
--- /dev/null
+++ b/src/tdfx_priv.h
@@ -0,0 +1,423 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_priv.h,v 1.11 2001/06/05 15:54:15 alanh Exp $ */
+
+
+#ifndef _TDFX_FIFO_H_
+#define _TDFX_FIFO_H_
+
+typedef unsigned int uint32;
+typedef unsigned short uint16;
+typedef unsigned char uint8;
+typedef int int32;
+typedef short int16;
+typedef char int8;
+
+#define CMDFIFO_PAGES 64
+
+#define PROPSAREADATA \
+ volatile int fifoPtr; \
+ volatile int fifoRead;
+
+#define PROPDATASTD \
+ volatile unsigned int *fifoPtr; \
+ volatile unsigned int *fifoRead; \
+ int fifoSlots; \
+ unsigned int *fifoBase; \
+ unsigned int *fifoEnd; \
+ int fifoOffset; \
+ int fifoSize
+
+#define PROPDATADBG \
+ unsigned int *fifoMirrorBase; \
+ unsigned int *fifoMirrorPtr;
+
+#ifdef FIFO_DEBUG
+#define PROPDATA PROPDATASTD; \
+ PROPDATADBG
+#else
+#define PROPDATA PROPDATASTD;
+#endif
+
+#ifdef TDFX_DEBUG_CMDS
+#define TDFXMakeRoom(p, n) \
+ do { \
+ if (fifoCnt) \
+ ErrorF("Previous TDFXMakeRoom passed incorrect size\n"); \
+ cmdCnt=n; \
+ TDFXAllocateSlots(p, (n)+1); \
+ while (0)
+#define TDFXWriteLong(p, a, v)
+ do { \
+ if (lastAddr & a<lastAddr) \
+ ErrorF("TDFXWriteLong not ordered\n"); \
+ cmdCnt--; \
+ WRITE_FIFO(p, a, v); \
+ while (0)
+#else
+#define TDFXMakeRoom(p, n) TDFXAllocateSlots(p, (n)+1)
+#define TDFXWriteLong(p, a, v) WRITE_FIFO(p, a, v)
+#endif
+#define DECLARE SET_PKT2_HEADER
+#define DECLARE_LAUNCH SET_PK1_HEADER_LAUNCH
+#define TDFXSendNOP TDFXSendNOPFifo
+
+/*
+** Structures for Banshee AGP/CMD Transfer/MISC registers.
+*/
+typedef volatile struct _H3CmdFifo
+{
+ uint32 baseAddrL;
+ uint32 baseSize;
+ uint32 bump;
+ uint32 readPtrL;
+ uint32 readPtrH;
+ uint32 aMin;
+ uint32 unusedA;
+ uint32 aMax;
+ uint32 unusedB;
+ uint32 depth;
+ uint32 holeCount;
+ uint32 reserved;
+} H3CmdFifo;
+
+Bool TDFXInitFifo(ScreenPtr pScreen);
+void TDFXShutdownFifo(ScreenPtr pScreen);
+void TDFXAllocateSlots(TDFXPtr pTDFX, int slots);
+void TDFXSendNOPFifo2D(ScrnInfoPtr pScreen);
+
+#define CHECK_FOR_ROOM(_n) \
+ if ((pTDFX->fifoSlots -= (_n)) < 0) \
+ cmdfifo_make_room(adapter, fifo_ptr, _n); \
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+#define BE_BSWAP32(val) ((((val) & 0x000000ff) << 24) | \
+ (((val) & 0x0000ff00) << 8) | \
+ (((val) & 0x00ff0000) >> 8) | \
+ (((val) & 0xff000000) >> 24))
+
+#define BE_WSWAP32(val) ((((val) & 0x0000ffff) << 16) | \
+ (((val) & 0xffff0000) >> 16))
+ void TDFXWriteFifo_24(TDFXPtr pTDFX, int val);
+ void TDFXWriteFifo_16(TDFXPtr pTDFX, int val);
+ void TDFXWriteFifo_8(TDFXPtr pTDFX, int val);
+#else
+/* Don't swap on little-endian platforms */
+#define BE_BSWAP32(val) val
+#define BE_WSWAP32(val) val
+#endif
+
+
+#ifdef DEBUG_FIFO
+#define WRITE_FIFO(ptr, loc, _val) \
+ do { \
+ *pTDFX->fifoMirrorPtr++ = _val; \
+ *pTDFX->fifoPtr++ = _val; \
+ } while(0)
+#else
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+#define WRITE_FIFO(ptr, loc, _val) \
+ do { \
+ pTDFX->writeFifo(ptr, _val); \
+ } while (0)
+#else
+#define WRITE_FIFO(ptr, loc, _val) \
+ do { \
+ *pTDFX->fifoPtr++ = _val; \
+ } while(0)
+#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
+#endif /* DEBUG_FIFO */
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+#define FLUSH_WCB()
+#else
+#define FLUSH_WCB() inb(0x80)
+#endif
+
+/*
+** Send a packet header type 1 (2D) to the cmdfifo
+*/
+#define SET_2DPK1_HEADER(_ndwords, _inc, _reg) \
+ WRITE_FIFO ( pTDFX, 0, (_ndwords) << SSTCP_PKT1_NWORDS_SHIFT | \
+ ((_inc) ? SSTCP_PKT1_INC : SSTCP_PKT1_NOINC) | \
+ SSTCP_PKT1_2D | \
+ FIELD_OFFSET(H3_2D_REGISTERS, _reg)/4 << SSTCP_REGBASE_SHIFT | \
+ SSTCP_PKT1 \
+ )
+
+/*
+** Send a packet header type 1 to begin at launchArea[0] to the cmdfifo
+*/
+#define SET_PK1_HEADER_LAUNCH(_ndwords, _inc) \
+ WRITE_FIFO ( pTDFX, 0, (_ndwords) << SSTCP_PKT1_NWORDS_SHIFT | \
+ ((_inc) ? SSTCP_PKT1_INC : SSTCP_PKT1_NOINC) | \
+ SSTCP_PKT1_LAUNCH | SSTCP_PKT1 \
+ )
+
+/*
+** Send a packet header type 1 to begin at colorPattern[0] to the cmdfifo
+*/
+#define SET_PK1_HEADER_COLORPATTERN(_ndwords, _inc) \
+ WRITE_FIFO ( pTDFX, 0, (_ndwords) << SSTCP_PKT1_NWORDS_SHIFT | \
+ ((_inc) ? SSTCP_PKT1_INC : SSTCP_PKT1_NOINC) | \
+ SSTCP_PKT1_COLORPATTERN | SSTCP_PKT1 \
+ )
+
+/*
+** Send a packet header type 2 to the cmdfifo
+*/
+#define SET_PKT2_HEADER(_mask) \
+ WRITE_FIFO (pTDFX, 0, ((_mask) << SSTCP_PKT2_MASK_SHIFT) | SSTCP_PKT2)
+
+/*
+** These are used to select a register mask for use with
+** command fifo packet type 4. The defines represent an
+** offset register from the base register.
+** e.g. R5 = baseReg + 5, R0 = baseReg etc..
+*/
+#define R0 (1 << 0)
+#define R1 (1 << 1)
+#define R2 (1 << 2)
+#define R3 (1 << 3)
+#define R4 (1 << 4)
+#define R5 (1 << 5)
+#define R6 (1 << 6)
+#define R7 (1 << 7)
+#define R8 (1 << 8)
+#define R9 (1 << 9)
+#define R10 (1 << 10)
+#define R11 (1 << 11)
+#define R12 (1 << 12)
+#define R13 (1 << 13)
+
+#define SET_2DPK4_HEADER(_mask, _reg0) \
+ WRITE_FIFO ( pTDFX, 0, ((_mask) << SSTCP_PKT4_MASK_SHIFT) | \
+ SSTCP_PKT4_2D | \
+ (_reg0) | \
+ SSTCP_PKT4 \
+ )
+
+#define SET_3DPK4_HEADER(_mask, _reg0) \
+ WRITE_FIFO ( pTDFX, 0, ((_mask) << SSTCP_PKT4_MASK_SHIFT) | \
+ (_reg0) | \
+ SSTCP_PKT4 \
+ )
+
+/*----------------- SST cmdFifo*.baseSize bits --------------------------- */
+#define SST_CMDFIFO_SIZE 0xFF
+#define SST_EN_CMDFIFO BIT(8)
+#define SST_CMDFIFO_AGP BIT(9)
+#define SST_CMDFIFO_DISABLE_HOLES BIT(10)
+
+/* SST COMMAND PACKET defines */
+#define SSTCP_PKT_SIZE 3
+#define SSTCP_PKT SST_MASK(SSTCP_PKT_SIZE)
+#define SSTCP_PKT0 0
+#define SSTCP_PKT1 1
+#define SSTCP_PKT2 2
+#define SSTCP_PKT3 3
+#define SSTCP_PKT4 4
+#define SSTCP_PKT5 5
+#define SSTCP_PKT6 6
+#define SSTCP_PKT7 7
+
+#define SSTCP_BOGUS_WORDS_SHIFT 29
+#define SSTCP_BOGUS_WORDS (7 << SSTCP_BOGUS_WORDS_SHIFT)
+
+/* packet 0 defines */
+#define SSTCP_PKT0_FUNC_SHIFT 3
+#define SSTCP_PKT0_FUNC (7 << SSTCP_PKT0_FUNC_SHIFT)
+#define SSTCP_PKT0_NOP ((0<<SSTCP_PKT0_FUNC_SHIFT) | SSTCP_PKT0)
+#define SSTCP_PKT0_JSR ((1<<SSTCP_PKT0_FUNC_SHIFT) | SSTCP_PKT0)
+#define SSTCP_PKT0_RET ((2<<SSTCP_PKT0_FUNC_SHIFT) | SSTCP_PKT0)
+#define SSTCP_PKT0_JMP_LOCAL ((3<<SSTCP_PKT0_FUNC_SHIFT) | SSTCP_PKT0)
+#define SSTCP_PKT0_JMP_AGP ((4<<SSTCP_PKT0_FUNC_SHIFT) | SSTCP_PKT0)
+#define SSTCP_PKT0_ADDR_SHIFT 6
+#define SSTCP_PKT0_ADDR (0x7FFFFF<<SSTCP_PKT0_ADDR_SHIFT)
+
+/* packet 1 defines */
+#define SSTCP_REGBASE_SHIFT SSTCP_PKT_SIZE
+#ifdef H4
+#define SSTCP_REGBASE (0x7FF<<SSTCP_REGBASE_SHIFT)
+#define SSTCP_REGBASE_FROM_ADDR(x) ( (((x)>>2) & 0x7FF) << SSTCP_REGBASE_SHIFT )
+#else
+#define SSTCP_REGBASE ((0x3FF)<<SSTCP_REGBASE_SHIFT)
+#define SSTCP_REGBASE_FROM_ADDR(x) ( (((x)>>2) & 0x3FF) << SSTCP_REGBASE_SHIFT )
+#endif
+#define SSTCP_PKT1_2D BIT(14)
+#define SSTCP_INC BIT(15)
+#define SSTCP_PKT1_NWORDS_SHIFT 16
+#define SSTCP_PKT1_NWORDS (0xFFFFUL<<SSTCP_PKT1_NWORDS_SHIFT)
+
+#define SSTCP_PKT1_NOINC 0
+#define SSTCP_PKT1_INC SSTCP_INC
+#define SSTCP_PKT1_CLIP0MIN (SSTCP_PKT1_2D | (0x02 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_CLIP0MAX (SSTCP_PKT1_2D | (0x03 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_DSTBASEADDR (SSTCP_PKT1_2D | (0x04 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_DSTFORMAT (SSTCP_PKT1_2D | (0x05 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_SRCCOLORKEYMIN (SSTCP_PKT1_2D | (0x06 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_SRCCOLORKEYMAX (SSTCP_PKT1_2D | (0x07 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_DSTCOLORKEYMIN (SSTCP_PKT1_2D | (0x08 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_DSTCOLORKEYMAX (SSTCP_PKT1_2D | (0x09 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_BRESERROR0 (SSTCP_PKT1_2D | (0x0a << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_BRESERROR1 (SSTCP_PKT1_2D | (0x0b << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_ROP (SSTCP_PKT1_2D | (0x0c << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_SRCBASEADDR (SSTCP_PKT1_2D | (0x0d << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_COMMANDEXTRA (SSTCP_PKT1_2D | (0x0e << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_LINESTIPPLE (SSTCP_PKT1_2D | (0x0f << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_LINESTYLE (SSTCP_PKT1_2D | (0x10 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_PATTERN0ALIAS (SSTCP_PKT1_2D | (0x11 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_PATTERN1ALIAS (SSTCP_PKT1_2D | (0x12 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_CLIP1MIN (SSTCP_PKT1_2D | (0x13 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_CLIP1MAX (SSTCP_PKT1_2D | (0x14 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_SRCFORMAT (SSTCP_PKT1_2D | (0x15 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_SRCSIZE (SSTCP_PKT1_2D | (0x16 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_SRCXY (SSTCP_PKT1_2D | (0x17 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_COLORBACK (SSTCP_PKT1_2D | (0x18 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_COLORFORE (SSTCP_PKT1_2D | (0x19 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_DSTSIZE (SSTCP_PKT1_2D | (0x1a << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_DSTXY (SSTCP_PKT1_2D | (0x1b << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_COMMAND (SSTCP_PKT1_2D | (0x1c << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_LAUNCH (SSTCP_PKT1_2D | (0x20 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT1_COLORPATTERN (SSTCP_PKT1_2D | (0x40 << SSTCP_REGBASE_SHIFT))
+
+/* packet 2 defines */
+#define SSTCP_PKT2_MASK_SHIFT SSTCP_PKT_SIZE
+#define SSTCP_PKT2_MASK (0x1FFFFFFFUL<<SSTCP_PKT2_MASK_SHIFT)
+
+#define SSTCP_CLIP0MIN 0x00000001L
+#define SSTCP_CLIP0MAX 0x00000002L
+#define SSTCP_DSTBASEADDR 0x00000004L
+#define SSTCP_DSTFORMAT 0x00000008L
+#define SSTCP_SRCCOLORKEYMIN 0x00000010L
+#define SSTCP_SRCCOLORKEYMAX 0x00000020L
+#define SSTCP_DSTCOLORKEYMIN 0x00000040L
+#define SSTCP_DSTCOLORKEYMAX 0x00000080L
+#define SSTCP_BRESERROR0 0x00000100L
+#define SSTCP_BRESERROR1 0x00000200L
+#define SSTCP_ROP 0x00000400L
+#define SSTCP_SRCBASEADDR 0x00000800L
+#define SSTCP_COMMANDEXTRA 0x00001000L
+#define SSTCP_LINESTIPPLE 0x00002000L
+#define SSTCP_LINESTYLE 0x00004000L
+#define SSTCP_PATTERN0ALIAS 0x00008000L
+#define SSTCP_PATTERN1ALIAS 0x00010000L
+#define SSTCP_CLIP1MIN 0x00020000L
+#define SSTCP_CLIP1MAX 0x00040000L
+#define SSTCP_SRCFORMAT 0x00080000L
+#define SSTCP_SRCSIZE 0x00100000L
+#define SSTCP_SRCXY 0x00200000L
+#define SSTCP_COLORBACK 0x00400000L
+#define SSTCP_COLORFORE 0x00800000L
+#define SSTCP_DSTSIZE 0x01000000L
+#define SSTCP_DSTXY 0x02000000L
+#define SSTCP_COMMAND 0x04000000L
+
+/* packet 3 defines */
+#define SSTCP_PKT3_CMD_SHIFT SSTCP_PKT_SIZE
+#define SSTCP_PKT3_CMD (0x7<<SSTCP_PKT3_CMD_SHIFT)
+# define SSTCP_PKT3_BDDBDD (0<<SSTCP_PKT3_CMD_SHIFT)
+# define SSTCP_PKT3_BDDDDD (1<<SSTCP_PKT3_CMD_SHIFT)
+# define SSTCP_PKT3_DDDDDD (2<<SSTCP_PKT3_CMD_SHIFT)
+#define SSTCP_PKT3_NUMVERTEX_SHIFT (SSTCP_PKT_SIZE+3)
+#define SSTCP_PKT3_NUMVERTEX (0xF << SSTCP_PKT3_NUMVERTEX_SHIFT)
+#define SSTCP_PKT3_PMASK_SHIFT (SSTCP_PKT_SIZE+3+4)
+#define SSTCP_PKT3_PMASK (0xFFFUL<<SSTCP_PKT3_PMASK_SHIFT)
+#define SSTCP_PKT3_SMODE_SHIFT (SSTCP_PKT3_PMASK_SHIFT+12)
+#define SSTCP_PKT3_SMODE (0x3FUL<<SSTCP_PKT3_SMODE_SHIFT)
+#define SSTCP_PKT3_PACKEDCOLOR BIT(28)
+
+/* packet 4 defines */
+#define SSTCP_REGBASE_SHIFT SSTCP_PKT_SIZE
+#ifdef H4
+#define SSTCP_REGBASE ((0x7FF)<<SSTCP_REGBASE_SHIFT)
+#else
+#define SSTCP_REGBASE ((0x3FF)<<SSTCP_REGBASE_SHIFT)
+#endif
+#define SSTCP_PKT4_2D BIT(14)
+#define SSTCP_PKT4_MASK_SHIFT 15
+#define SSTCP_PKT4_MASK (0x3FFFUL<<SSTCP_PKT4_MASK_SHIFT)
+
+#define SSTCP_PKT4_CLIP0MIN (SSTCP_PKT4_2D | (0x02 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_CLIP0MAX (SSTCP_PKT4_2D | (0x03 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_DSTBASEADDR (SSTCP_PKT4_2D | (0x04 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_DSTFORMAT (SSTCP_PKT4_2D | (0x05 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_SRCCOLORKEYMIN (SSTCP_PKT4_2D | (0x06 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_SRCCOLORKEYMAX (SSTCP_PKT4_2D | (0x07 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_DSTCOLORKEYMIN (SSTCP_PKT4_2D | (0x08 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_DSTCOLORKEYMAX (SSTCP_PKT4_2D | (0x09 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_BRESERROR0 (SSTCP_PKT4_2D | (0x0a << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_BRESERROR1 (SSTCP_PKT4_2D | (0x0b << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_ROP (SSTCP_PKT4_2D | (0x0c << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_SRCBASEADDR (SSTCP_PKT4_2D | (0x0d << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_COMMANDEXTRA (SSTCP_PKT4_2D | (0x0e << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_LINESTIPPLE (SSTCP_PKT4_2D | (0x0f << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_LINESTYLE (SSTCP_PKT4_2D | (0x10 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_PATTERN0ALIAS (SSTCP_PKT4_2D | (0x11 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_PATTERN1ALIAS (SSTCP_PKT4_2D | (0x12 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_CLIP1MIN (SSTCP_PKT4_2D | (0x13 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_CLIP1MAX (SSTCP_PKT4_2D | (0x14 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_SRCFORMAT (SSTCP_PKT4_2D | (0x15 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_SRCSIZE (SSTCP_PKT4_2D | (0x16 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_SRCXY (SSTCP_PKT4_2D | (0x17 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_COLORBACK (SSTCP_PKT4_2D | (0x18 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_COLORFORE (SSTCP_PKT4_2D | (0x19 << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_DSTSIZE (SSTCP_PKT4_2D | (0x1a << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_DSTXY (SSTCP_PKT4_2D | (0x1b << SSTCP_REGBASE_SHIFT))
+#define SSTCP_PKT4_COMMAND (SSTCP_PKT4_2D | (0x1c << SSTCP_REGBASE_SHIFT))
+
+/* packet 5 defines */
+#define SSTCP_PKT5_NWORDS_SHIFT 3
+#define SSTCP_PKT5_NWORDS (0x7FFFFUL<<SSTCP_PKT5_NWORDS_SHIFT)
+#define SSTCP_PKT5_BYTEN_WN_SHIFT 22
+#define SSTCP_PKT5_BYTEN_WN (0xFUL<<SSTCP_PKT5_BYTEN_WN_SHIFT)
+#define SSTCP_PKT5_BYTEN_W2_SHIFT 26
+#define SSTCP_PKT5_BYTEN_W2 (0xFUL<<SSTCP_PKT5_BYTEN_W2_SHIFT)
+#define SSTCP_PKT5_SPACE_SHIFT 30
+#define SSTCP_PKT5_SPACE (0x3UL<<SSTCP_PKT5_SPACE_SHIFT)
+#define SSTCP_PKT5_LFB (0x0UL<<SSTCP_PKT5_SPACE_SHIFT)
+#define SSTCP_PKT5_YUV (0x1UL<<SSTCP_PKT5_SPACE_SHIFT)
+#define SSTCP_PKT5_3DLFB (0x2UL<<SSTCP_PKT5_SPACE_SHIFT)
+#define SSTCP_PKT5_TEXPORT (0x3UL<<SSTCP_PKT5_SPACE_SHIFT)
+#define SSTCP_PKT5_BASEADDR 0x1FFFFFFUL
+
+/* packet 6 defines */
+#define SSTCP_PKT6_SPACE_SHIFT 3
+#define SSTCP_PKT6_SPACE (0x3UL<<SSTCP_PKT6_SPACE_SHIFT)
+#define SSTCP_PKT6_LFB (0x0UL<<SSTCP_PKT6_SPACE_SHIFT)
+#define SSTCP_PKT6_YUV (0x1UL<<SSTCP_PKT6_SPACE_SHIFT)
+#define SSTCP_PKT6_3DLFB (0x2UL<<SSTCP_PKT6_SPACE_SHIFT)
+#define SSTCP_PKT6_TEXPORT (0x3UL<<SSTCP_PKT6_SPACE_SHIFT)
+#define SSTCP_PKT6_NBYTES_SHIFT 5
+#define SSTCP_PKT6_NBYTES (SST_MASK(20) << SSTCP_PKT6_NBYTES_SHIFT)
+#define SSTCP_PKT6_SRC_BASELOW SST_MASK(32)
+#define SSTCP_PKT6_SRC_WIDTH SST_MASK(14)
+#define SSTCP_PKT6_SRC_STRIDE_SHIFT 14
+#define SSTCP_PKT6_SRC_STRIDE (SST_MASK(14) <<SSTCP_PKT6_SRC_STRIDE_SHIFT)
+#define SSTCP_PKT6_SRC_BASEHIGH_SHIFT 28
+#define SSTCP_PKT6_SRC_BASEHIGH (SST_MASK(4) <<SSTCP_PKT6_SRC_BASEHIGH_SHIFT)
+#define SSTCP_PKT6_FRAME_BUFFER_OFFSET SST_MASK(26)
+#define SSTCP_PKT6_DST_STRIDE SST_MASK(15)
+
+#define SST_FIFO_OFFSET 0x0080000
+#define SST_FIFO_BASEADDR0 SST_FIFO_OFFSET+0x20
+#define SST_FIFO_BASESIZE0 SST_FIFO_OFFSET+0x24
+#define SST_FIFO_BUMP0 SST_FIFO_OFFSET+0x28
+#define SST_FIFO_RDPTRL0 SST_FIFO_OFFSET+0x2c
+#define SST_FIFO_RDPTRH0 SST_FIFO_OFFSET+0x30
+#define SST_FIFO_AMIN0 SST_FIFO_OFFSET+0x34
+#define SST_FIFO_AMAX0 SST_FIFO_OFFSET+0x3c
+#define SST_FIFO_DEPTH0 SST_FIFO_OFFSET+0x44
+#define SST_FIFO_HOLECNT0 SST_FIFO_OFFSET+0x48
+
+#define SST_FIFO_BASEADDR1 SST_FIFO_OFFSET+0x50
+#define SST_FIFO_BASESIZE1 SST_FIFO_OFFSET+0x54
+#define SST_FIFO_BUMP1 SST_FIFO_OFFSET+0x58
+#define SST_FIFO_RDPTRL1 SST_FIFO_OFFSET+0x5c
+#define SST_FIFO_RDPTRH1 SST_FIFO_OFFSET+0x60
+#define SST_FIFO_AMIN1 SST_FIFO_OFFSET+0x64
+#define SST_FIFO_AMAX1 SST_FIFO_OFFSET+0x6c
+#define SST_FIFO_DEPTH1 SST_FIFO_OFFSET+0x74
+#define SST_FIFO_HOLECNT1 SST_FIFO_OFFSET+0x78
+
+#define SST_FIFO_FIFOTHRESH SST_FIFO_OFFSET+0x80
+
+#endif
diff --git a/src/tdfx_sli.c b/src/tdfx_sli.c
new file mode 100644
index 0000000..803a0db
--- /dev/null
+++ b/src/tdfx_sli.c
@@ -0,0 +1,769 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_sli.c,v 1.7 2001/03/21 17:02:26 dawes Exp $ */
+
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xf86_OSproc.h"
+#include "xf86Pci.h"
+#include "tdfx.h"
+
+#define AACLKOUTDEL 0x2
+#define CFGSWAPALGORITHM 0x1
+
+/* #define RD_ABORT_ERROR */
+#define H3VDD
+
+Bool TDFXDisableSLI(TDFXPtr pTDFX)
+{
+ int i;
+ int v;
+
+ for (i=0; i<pTDFX->numChips; i++) {
+ v=pciReadLong(pTDFX->PciTag[i], CFG_INIT_ENABLE);
+ pciWriteLong(pTDFX->PciTag[i], CFG_INIT_ENABLE,
+ v&~(CFG_SNOOP_MEMBASE0 | CFG_SNOOP_EN | CFG_SNOOP_MEMBASE0_EN |
+ CFG_SNOOP_MEMBASE1_EN | CFG_SNOOP_SLAVE |
+ CFG_SNOOP_FBIINIT_WR_EN | CFG_SWAP_ALGORITHM |
+ CFG_SWAP_QUICK));
+ v=pciReadLong(pTDFX->PciTag[i], CFG_SLI_LFB_CTRL);
+ pciWriteLong(pTDFX->PciTag[i], CFG_SLI_LFB_CTRL,
+ v&~(CFG_SLI_LFB_CPU_WR_EN | CFG_SLI_LFB_DPTCH_WR_EN |
+ CFG_SLI_RD_EN));
+#ifdef H3VDD
+ pTDFX->writeChipLong(pTDFX, i, SST_3D_SLICTRL, 0);
+ pTDFX->writeChipLong(pTDFX, i, SST_3D_AACTRL, 0);
+#endif
+ v=pciReadLong(pTDFX->PciTag[i], CFG_AA_LFB_CTRL);
+ pciWriteLong(pTDFX->PciTag[i], CFG_AA_LFB_CTRL,
+ v&~(CFG_AA_LFB_CPU_WR_EN | CFG_AA_LFB_DPTCH_WR_EN |
+ CFG_AA_LFB_RD_EN));
+ v=pciReadLong(pTDFX->PciTag[i], CFG_SLI_AA_MISC);
+ pciWriteLong(pTDFX->PciTag[i], CFG_SLI_AA_MISC,
+ (v&~CFG_VGA_VSYNC_OFFSET) |
+ (0 << CFG_VGA_VSYNC_OFFSET_PIXELS_SHIFT) |
+ (0 << CFG_VGA_VSYNC_OFFSET_CHARS_SHIFT) |
+ (0 << CFG_VGA_VSYNC_OFFSET_HXTRA_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0, 0);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1, 0);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2, 0);
+
+ if (pTDFX->numChips>1) {
+ v=pTDFX->readChipLong(pTDFX, i, PCIINIT0);
+ pTDFX->writeChipLong(pTDFX, i, PCIINIT0,
+ (v&~(SST_PCI_DISABLE_IO|SST_PCI_DISABLE_MEM|
+ SST_PCI_RETRY_INTERVAL)) |
+ (0<<SST_PCI_RETRY_INTERVAL_SHIFT) |
+ SST_PCI_FORCE_FB_HIGH);
+ } else {
+ v=pTDFX->readChipLong(pTDFX, i, PCIINIT0);
+ pTDFX->writeChipLong(pTDFX, i, PCIINIT0,
+ (v&~(SST_PCI_DISABLE_IO|SST_PCI_DISABLE_MEM|
+ SST_PCI_RETRY_INTERVAL)) |
+ (0<<SST_PCI_RETRY_INTERVAL_SHIFT));
+ }
+
+#if 0
+ if (i>0) {
+ pTDFX->writeChipLong(pTDFX, i, DACMODE,
+ SST_DAC_DPMS_ON_VSYNC | SST_DAC_DPMS_ON_HSYNC);
+ v=pTDFX->readChipLong(pTDFX, i, VIDPROCCFG);
+ pTDFX->writeChipLong(pTDFX, i, VIDPROCCFG, v&~SST_VIDEO_PROCESSOR_EN);
+ }
+#endif
+ }
+ return TRUE;
+}
+
+Bool TDFXSetupSLI(ScrnInfoPtr pScrn, Bool sliEnable, int aaSamples)
+{
+ TDFXPtr pTDFX;
+ int i, sliLines, sliLinesLog2, nChipsLog2, v;
+ int sli_renderMask, sli_compareMask, sli_scanMask;
+ int sliAnalog, dwFormat;
+
+ pTDFX=TDFXPTR(pScrn);
+ if (pScrn->depth == 24 || pScrn->depth==32) {
+ if ((aaSamples == 4) && (pTDFX->numChips>1)) {
+ pTDFX->pixelFormat=GR_PIXFMT_AA_4_ARGB_8888;
+ } else if (aaSamples >= 2) {
+ pTDFX->pixelFormat=GR_PIXFMT_AA_2_ARGB_8888;
+ } else {
+ pTDFX->pixelFormat=GR_PIXFMT_ARGB_8888;
+ }
+ } else if (pScrn->depth == 16) {
+ if ((aaSamples == 4) && (pTDFX->numChips>1)) {
+ pTDFX->pixelFormat=GR_PIXFMT_AA_4_RGB_565;
+ } else if (aaSamples >= 2) {
+ pTDFX->pixelFormat=GR_PIXFMT_AA_2_RGB_565;
+ } else {
+ pTDFX->pixelFormat=GR_PIXFMT_RGB_565;
+ }
+ } else if (pScrn->depth == 8) {
+ pTDFX->pixelFormat=GR_PIXFMT_I_8;
+ }
+ if (!sliEnable && !aaSamples) { /* Turn off */
+ return TDFXDisableSLI(pTDFX);
+ }
+
+ if (pScrn->virtualY>768) sliLinesLog2=5;
+ else sliLinesLog2=4;
+ sliLines=1<<sliLinesLog2;
+ if (pScrn->virtualY*pScrn->virtualX>1600*1024) sliAnalog=1;
+ else sliAnalog=0;
+ /* XXX We need to avoid SLI in double scan modes somehow */
+
+ switch (pTDFX->numChips) {
+ case 1:
+ nChipsLog2=0;
+ break;
+ case 2:
+ nChipsLog2=1;
+ break;
+ case 4:
+ nChipsLog2=2;
+ break;
+ default:
+ return FALSE;
+ /* XXX Huh? Unsupported configuration */
+ }
+
+ for (i=0; i<pTDFX->numChips; i++) {
+ /* Do we want to set these differently for a VIA board? */
+ v=pTDFX->readChipLong(pTDFX, i, PCIINIT0);
+ v=(v&~(SST_PCI_RETRY_INTERVAL|SST_PCI_FORCE_FB_HIGH)) |
+ SST_PCI_READ_WS | SST_PCI_WRITE_WS |
+ SST_PCI_DISABLE_IO | SST_PCI_DISABLE_MEM |
+ (5<<SST_PCI_RETRY_INTERVAL_SHIFT);
+ pTDFX->writeChipLong(pTDFX, i, PCIINIT0,
+ (v&~(SST_PCI_RETRY_INTERVAL|SST_PCI_FORCE_FB_HIGH)) |
+ SST_PCI_READ_WS | SST_PCI_WRITE_WS |
+ SST_PCI_DISABLE_IO | SST_PCI_DISABLE_MEM |
+ (5<<SST_PCI_RETRY_INTERVAL_SHIFT));
+ v=pTDFX->readChipLong(pTDFX, i, TMUGBEINIT);
+ pTDFX->writeChipLong(pTDFX, i, TMUGBEINIT,
+ (v&~(SST_AA_CLK_DELAY | SST_AA_CLK_INVERT)) |
+ (AACLKOUTDEL<<SST_AA_CLK_DELAY_SHIFT) |
+ SST_AA_CLK_INVERT);
+
+ if (pTDFX->numChips>1) {
+ v=pciReadLong(pTDFX->PciTag[i], CFG_INIT_ENABLE);
+ pciWriteLong(pTDFX->PciTag[i], CFG_INIT_ENABLE, v |
+ (CFGSWAPALGORITHM << CFG_SWAPBUFFER_ALGORITHM_SHIFT) |
+ CFG_SWAP_ALGORITHM | ((!i)? CFG_SWAP_MASTER : 0));
+ if (!i) {
+ v=pciReadLong(pTDFX->PciTag[i], CFG_INIT_ENABLE);
+ pciWriteLong(pTDFX->PciTag[i], CFG_INIT_ENABLE,
+ v | CFG_SNOOP_EN);
+ v=pciReadLong(pTDFX->PciTag[i], CFG_PCI_DECODE);
+ } else {
+ v=pciReadLong(pTDFX->PciTag[i], CFG_INIT_ENABLE);
+ v=(v & ~CFG_SNOOP_MEMBASE0) | CFG_SNOOP_EN |
+ CFG_SNOOP_MEMBASE0_EN | CFG_SNOOP_MEMBASE1_EN |
+ CFG_SNOOP_SLAVE | CFG_SNOOP_FBIINIT_WR_EN |
+ (((pTDFX->MMIOAddr[0]>>22)&0x3ff)<<CFG_SNOOP_MEMBASE0_SHIFT) |
+ ((pTDFX->numChips>2)? CFG_SWAP_QUICK : 0);
+ pciWriteLong(pTDFX->PciTag[i], CFG_INIT_ENABLE, v);
+ v=pciReadLong(pTDFX->PciTag[i], CFG_PCI_DECODE);
+ v=(v & ~CFG_SNOOP_MEMBASE1) |
+ ((pTDFX->LinearAddr[0]>>22)&0x3ff)<<CFG_SNOOP_MEMBASE1_SHIFT;
+ pciWriteLong(pTDFX->PciTag[i], CFG_PCI_DECODE, v);
+ }
+ }
+
+ if (sliEnable && aaSamples<4) {
+ /* SLI is on and we're using less than 4 AA samples */
+ sli_renderMask = (pTDFX->numChips-1) << sliLinesLog2;
+ sli_compareMask = i << sliLinesLog2;
+ sli_scanMask = sliLines - 1;
+ v = (sli_renderMask << CFG_SLI_LFB_RENDERMASK_SHIFT) |
+ (sli_compareMask << CFG_SLI_LFB_COMPAREMASK_SHIFT) |
+ (sli_scanMask << CFG_SLI_LFB_SCANMASK_SHIFT) |
+ (nChipsLog2 << CFG_SLI_LFB_NUMCHIPS_LOG2_SHIFT) |
+ CFG_SLI_LFB_CPU_WR_EN | CFG_SLI_LFB_DPTCH_WR_EN;
+#ifndef RD_ABORT_ERROR
+ v|=CFG_SLI_RD_EN;
+#endif
+ pciWriteLong(pTDFX->PciTag[i], CFG_SLI_LFB_CTRL, v);
+
+#ifdef H3VDD
+ pTDFX->writeChipLong(pTDFX, i, SST_3D_SLICTRL,
+ (sli_renderMask << SLICTL_3D_RENDERMASK_SHIFT) |
+ (sli_compareMask << SLICTL_3D_COMPAREMASK_SHIFT) |
+ (sli_scanMask << SLICTL_3D_SCANMASK_SHIFT) |
+ (nChipsLog2 << SLICTL_3D_NUMCHIPS_LOG2_SHIFT) |
+ SLICTL_3D_EN);
+#endif
+ } else if (!sliEnable && aaSamples) {
+ /* SLI is off and AA is on */
+ sli_renderMask = 0;
+ sli_compareMask = 0;
+ sli_scanMask = 0;
+ pciWriteLong(pTDFX->PciTag[i], CFG_SLI_LFB_CTRL,
+ (sli_renderMask << CFG_SLI_LFB_RENDERMASK_SHIFT) |
+ (sli_compareMask << CFG_SLI_LFB_COMPAREMASK_SHIFT) |
+ (sli_scanMask << CFG_SLI_LFB_SCANMASK_SHIFT) |
+ (0x0 << CFG_SLI_LFB_NUMCHIPS_LOG2_SHIFT));
+#ifdef H3VDD
+ pTDFX->writeChipLong(pTDFX, i, SST_3D_SLICTRL,
+ (sli_renderMask << SLICTL_3D_RENDERMASK_SHIFT) |
+ (sli_compareMask << SLICTL_3D_COMPAREMASK_SHIFT) |
+ (sli_scanMask << SLICTL_3D_SCANMASK_SHIFT) |
+ (0 << SLICTL_3D_NUMCHIPS_LOG2_SHIFT));
+#endif
+ } else {
+ /* SLI is on && aaSamples=4 */
+ sli_renderMask = ((pTDFX->numChips>>1)-1) << sliLinesLog2;
+ sli_compareMask = (i>>1) << sliLinesLog2;
+ sli_scanMask = sliLines - 1;
+ v = (sli_renderMask << CFG_SLI_LFB_RENDERMASK_SHIFT) |
+ (sli_compareMask << CFG_SLI_LFB_COMPAREMASK_SHIFT) |
+ (sli_scanMask << CFG_SLI_LFB_SCANMASK_SHIFT) |
+ ((nChipsLog2-1) << CFG_SLI_LFB_NUMCHIPS_LOG2_SHIFT) |
+ CFG_SLI_LFB_CPU_WR_EN | CFG_SLI_LFB_DPTCH_WR_EN;
+#ifndef RD_ABORT_ERROR
+ v|=CFG_SLI_RD_EN;
+#endif
+ pciWriteLong(pTDFX->PciTag[i], CFG_SLI_LFB_CTRL, v);
+#ifdef H3VDD
+ pTDFX->writeChipLong(pTDFX, i, SST_3D_SLICTRL,
+ (sli_renderMask << SLICTL_3D_RENDERMASK_SHIFT) |
+ (sli_compareMask << SLICTL_3D_COMPAREMASK_SHIFT) |
+ (sli_scanMask << SLICTL_3D_SCANMASK_SHIFT) |
+ ((nChipsLog2-1) << SLICTL_3D_NUMCHIPS_LOG2_SHIFT) |
+ SLICTL_3D_EN);
+#endif
+ }
+
+ TDFXSetLFBConfig(pTDFX);
+ if (pTDFX->cpp==2) dwFormat = CFG_AA_LFB_RD_FORMAT_16BPP;
+ else dwFormat = CFG_AA_LFB_RD_FORMAT_32BPP;
+ if (pTDFX->numChips==2 && !sliEnable && aaSamples==2)
+ dwFormat|=CFG_AA_LFB_RD_DIVIDE_BY_4;
+ /* Thess are wrong, because we don't know where the secondary buffers
+ are located */
+ pTDFX->writeChipLong(pTDFX, i, CFG_AA_LFB_CTRL,
+ (pScrn->videoRam<<10 /* 2nd buf */ << CFG_AA_BASEADDR_SHIFT) |
+ CFG_AA_LFB_CPU_WR_EN | CFG_AA_LFB_DPTCH_WR_EN |
+ CFG_AA_LFB_RD_EN | dwFormat |
+ ((aaSamples==4)?CFG_AA_LFB_RD_DIVIDE_BY_4:0));
+ pTDFX->writeChipLong(pTDFX, i, CFG_AA_ZBUFF_APERTURE,
+ ((pTDFX->depthOffset>>12)<<CFG_AA_DEPTH_BUFFER_BEG_SHIFT) |
+ ((pScrn->videoRam>>2)<<CFG_AA_DEPTH_BUFFER_END_SHIFT));
+
+ if (pTDFX->numChips>1 && i && (aaSamples || sliEnable)) {
+ int vsyncOffsetPixels, vsyncOffsetChars, vsyncOffsetHXtra;
+
+ if (aaSamples || (pTDFX->numChips==4 && sliEnable && aaSamples==4 &&
+ sliAnalog && i==3)) {
+ vsyncOffsetPixels=7;
+ vsyncOffsetChars=4;
+ vsyncOffsetHXtra=0;
+ } else {
+ vsyncOffsetPixels=7;
+ vsyncOffsetChars=5;
+ vsyncOffsetHXtra=0;
+ }
+ v=pciReadLong(pTDFX->PciTag[i], CFG_SLI_AA_MISC);
+ pciWriteLong(pTDFX->PciTag[i], CFG_SLI_AA_MISC,
+ (v&~CFG_VGA_VSYNC_OFFSET) |
+ (vsyncOffsetPixels << CFG_VGA_VSYNC_OFFSET_PIXELS_SHIFT) |
+ (vsyncOffsetChars << CFG_VGA_VSYNC_OFFSET_CHARS_SHIFT) |
+ (vsyncOffsetHXtra <<
+ CFG_VGA_VSYNC_OFFSET_HXTRA_SHIFT));
+ }
+ if (pTDFX->numChips==1 && aaSamples) {
+ /* 1 chip 2 AA */
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ CFG_VIDEO_OTHERMUX_SEL_PIPE<<CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT |
+ CFG_DIVIDE_VIDEO_BY_2);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ 0x0 << CFG_SLI_RENDERMASK_FETCH_SHIFT |
+ 0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT |
+ 0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT |
+ 0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ 0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT |
+ 0xff << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT);
+ } else if (pTDFX->numChips==2 && !sliEnable && aaSamples==4 &&
+ !sliAnalog) {
+ /* 2 chips 4 digital AA */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE_PLUS_AAFIFO <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_4);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (0x0 << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ (CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (0x0 << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips==2 && !sliEnable && aaSamples==4 && sliAnalog) {
+ /* 2 chips 4 analog AA */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ (CFG_ENHANCED_VIDEO_EN |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_4));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_DAC_HSYNC_TRISTATE |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_4);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (0x0 << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips==2 && sliEnable && !aaSamples && !sliAnalog) {
+ /* 2 chips 2 digital SLI */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ (CFG_ENHANCED_VIDEO_EN |
+ (CFG_VIDEO_OTHERMUX_SEL_AAFIFO <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ ((0x0<<sliLinesLog2) << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((i<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ ((i<<sliLinesLog2) <<
+ CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips>=2 && sliEnable && !aaSamples && sliAnalog) {
+ /* 2 or 4 chips 2/4 analog SLI */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((i<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ ((i<<sliLinesLog2) <<
+ CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips==2 && sliEnable && aaSamples==2 && !sliAnalog) {
+ /* 2 chips 2 AA 2 digital SLI */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_AAFIFO <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_2);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ ((0x1<<sliLinesLog2) <<
+ CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((i<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ ((i<<sliLinesLog2) <<
+ CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips==2 && !sliEnable && aaSamples==2 && !sliAnalog) {
+ /* 2 chips 2 digital AA */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE_PLUS_AAFIFO <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_2);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (0x0 << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (0x0 << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips==2 && !sliEnable && aaSamples==2 && sliAnalog) {
+ /* 2 chips 2 analog AA */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_2);
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_DAC_HSYNC_TRISTATE |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_2);
+ }
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (0x0 << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else if (pTDFX->numChips>=2 && sliEnable && aaSamples==2 && sliAnalog) {
+ /* 2 or 4 chips 2 AA 2 or 4 analog SLI */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_2);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_2);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((i<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ ((i<<sliLinesLog2) << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips==4 && sliEnable && !aaSamples && !sliAnalog) {
+ /* 4 chips 4 digital SLI */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ (CFG_VIDEO_OTHERMUX_SEL_AAFIFO <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_SLI_AAFIFO_COMPARE_INV |
+ CFG_DIVIDE_VIDEO_BY_1);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ ((0x0<<sliLinesLog2) <<
+ CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((i<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ ((i<<sliLinesLog2) << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips==4 && sliEnable && aaSamples==2 && !sliAnalog) {
+ /* 4 chips 2 AA 4 digital SLI */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_AAFIFO <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_SLI_AAFIFO_COMPARE_INV |
+ CFG_DIVIDE_VIDEO_BY_2);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ ((0x0<<sliLinesLog2) << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((i<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ (0x0 << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (((pTDFX->numChips-1)<<sliLinesLog2) <<
+ CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ ((i<<sliLinesLog2) << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips==4 && sliEnable && aaSamples==4 && !sliAnalog) {
+ /* 4 chips 4 AA 2 digital SLI */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE_PLUS_AAFIFO <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_4);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((0x0<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ ((0x0<<sliLinesLog2) << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else if (i==1 || i==3) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_DAC_HSYNC_TRISTATE |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_1);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((((i+1)>>2)<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ ((0x0<<sliLinesLog2) << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ ((0xff<<sliLinesLog2) << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE_PLUS_AAFIFO <<
+ CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_4);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0xff << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ } else if (pTDFX->numChips==4 && sliEnable && aaSamples==4 && sliAnalog) {
+ /* 4 chips 4 AA 2 analog SLI */
+ if (!i) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_4);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((0x0<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ ((0x0<<sliLinesLog2) << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else if (i==1 || i==3) {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_DAC_HSYNC_TRISTATE |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_4);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((((i+1)>>2)<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ ((((i+1)>>2)<<sliLinesLog2) << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ } else {
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ CFG_ENHANCED_VIDEO_EN |
+ CFG_ENHANCED_VIDEO_SLV |
+ CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY |
+ (CFG_VIDEO_OTHERMUX_SEL_PIPE <<
+ CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT) |
+ CFG_DIVIDE_VIDEO_BY_4);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL1,
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_FETCH_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_COMPAREMASK_FETCH_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_RENDERMASK_CRT_SHIFT) |
+ ((0x1<<sliLinesLog2) << CFG_SLI_COMPAREMASK_CRT_SHIFT));
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL2,
+ (0x0 << CFG_SLI_RENDERMASK_AAFIFO_SHIFT) |
+ (0x0 << CFG_SLI_COMPAREMASK_AAFIFO_SHIFT));
+ }
+ }
+ if (pTDFX->numChips==4 && sliEnable && aaSamples==4 && i==3) {
+ v=pciReadLong(pTDFX->PciTag[i], CFG_SLI_AA_MISC);
+ pciWriteLong(pTDFX->PciTag[i], CFG_SLI_AA_MISC,
+ v | CFG_AA_LFB_RD_SLV_WAIT);
+ }
+ if (i) {
+ v=pciReadLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0);
+ pciWriteLong(pTDFX->PciTag[i], CFG_VIDEO_CTRL0,
+ v|CFG_VIDPLL_SEL);
+ v=pTDFX->readChipLong(pTDFX, i, MISCINIT1);
+ pTDFX->writeChipLong(pTDFX, i, MISCINIT1, v|SST_POWERDOWN_DAC);
+ }
+ }
+ return TRUE;
+}
diff --git a/src/tdfx_video.c b/src/tdfx_video.c
new file mode 100644
index 0000000..8d90c1f
--- /dev/null
+++ b/src/tdfx_video.c
@@ -0,0 +1,1474 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_video.c,v 1.16 2002/10/17 01:02:08 dawes Exp $ */
+
+#include "xf86.h"
+#include "tdfx.h"
+#include "dixstruct.h"
+
+#include "Xv.h"
+#include "fourcc.h"
+
+static Atom xvColorKey, xvFilterQuality;
+
+/* These should move into tdfxdefs.h with better names */
+#define YUV_Y_BASE 0xC00000
+#define YUV_U_BASE 0xD00000
+#define YUV_V_BASE 0xE00000
+
+#define SST_2D_FORMAT_YUYV 0x8
+#define SST_2D_FORMAT_UYVY 0x9
+
+#define YUVBASEADDR 0x80100
+#define YUVSTRIDE 0x80104
+#define VIDPROCCFGMASK 0xa2e3eb6c
+
+#define OFF_DELAY 250 /* milliseconds */
+#define FREE_DELAY 15000
+
+#define OFF_TIMER 0x01
+#define FREE_TIMER 0x02
+#define CLIENT_VIDEO_ON 0x04
+#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
+
+#define TDFX_MAX_OVERLAY_PORTS 1
+#define TDFX_MAX_TEXTURE_PORTS 32
+
+#define GET_PORT_PRIVATE(pScrn) \
+ (TDFXPortPrivPtr)((TDFXPTR(pScrn))->overlayAdaptor->pPortPrivates[0].ptr)
+
+/* Doesn't matter what screen we use */
+#define DummyScreen screenInfo.screens[0]
+
+/* Needed for attribute atoms */
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+/*
+ * PROTOTYPES
+ */
+
+static FBAreaPtr TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height);
+static FBLinearPtr TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size);
+static void TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time);
+
+static XF86VideoAdaptorPtr TDFXSetupImageVideoTexture(ScreenPtr);
+static int TDFXSetPortAttributeTexture(ScrnInfoPtr, Atom, INT32, pointer);
+static int TDFXGetPortAttributeTexture(ScrnInfoPtr, Atom ,INT32 *, pointer);
+static int TDFXPutImageTexture(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer);
+static void TDFXStopVideoTexture(ScrnInfoPtr, pointer, Bool);
+
+static XF86VideoAdaptorPtr TDFXSetupImageVideoOverlay(ScreenPtr);
+static int TDFXSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer);
+static int TDFXGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer);
+static int TDFXPutImageOverlay(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer);
+static void TDFXStopVideoOverlay(ScrnInfoPtr, pointer, Bool);
+static void TDFXResetVideoOverlay(ScrnInfoPtr);
+
+static void TDFXQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);
+static int TDFXQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *);
+
+static void TDFXInitOffscreenImages(ScreenPtr);
+
+/*
+ * ADAPTOR INFORMATION
+ */
+
+static XF86VideoEncodingRec OverlayEncoding[] =
+{
+ { 0, "XV_IMAGE", 2048, 2048, {1, 1} }
+};
+
+static XF86VideoEncodingRec TextureEncoding[] =
+{
+ { 0, "XV_IMAGE", 1024, 1024, {1, 1} }
+};
+
+static XF86VideoFormatRec OverlayFormats[] =
+{
+ {8, TrueColor}, {8, DirectColor}, {8, PseudoColor},
+ {8, GrayScale}, {8, StaticGray}, {8, StaticColor},
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor},
+ {15, DirectColor}, {16, DirectColor}, {24, DirectColor}
+};
+
+static XF86VideoFormatRec TextureFormats[] =
+{
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+static XF86AttributeRec OverlayAttributes[] =
+{
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
+};
+
+static XF86AttributeRec TextureAttributes[] =
+{
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
+};
+
+static XF86ImageRec OverlayImages[] =
+{
+ XVIMAGE_YUY2, XVIMAGE_UYVY, XVIMAGE_YV12, XVIMAGE_I420
+};
+
+static XF86ImageRec TextureImages[] =
+{
+ XVIMAGE_YV12, XVIMAGE_I420
+};
+
+/*
+ * COMMON SETUP FUNCTIONS
+ */
+
+void TDFXInitVideo(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+ XF86VideoAdaptorPtr newAdaptor = NULL;
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ int num_adaptors;
+
+ /* The hardware can't convert YUV->8 bit color */
+ if(pTDFX->cpp == 1)
+ return;
+
+ if(!pTDFX->AccelInfoRec || !pTDFX->AccelInfoRec->FillSolidRects)
+ return;
+
+ if (!pTDFX->TextureXvideo) {
+ /* Offscreen support for Overlay only */
+ TDFXInitOffscreenImages(pScreen);
+
+ /* Overlay adaptor */
+ newAdaptor = TDFXSetupImageVideoOverlay(pScreen);
+ } else {
+ /* Texture adaptor */
+ newAdaptor = TDFXSetupImageVideoTexture(pScreen);
+ }
+
+ num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
+
+ if(newAdaptor) {
+ if (!num_adaptors) {
+ num_adaptors = 1;
+ adaptors = &newAdaptor;
+ } else {
+ newAdaptors =
+ xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
+ if(newAdaptors) {
+ memcpy(newAdaptors, adaptors, num_adaptors *
+ sizeof(XF86VideoAdaptorPtr));
+ newAdaptors[num_adaptors] = newAdaptor;
+ adaptors = newAdaptors;
+ num_adaptors++;
+ }
+ }
+ }
+
+ if(num_adaptors)
+ xf86XVScreenInit(pScreen, adaptors, num_adaptors);
+
+ if(newAdaptors)
+ xfree(newAdaptors);
+}
+
+
+void TDFXCloseVideo (ScreenPtr pScreen)
+{
+}
+
+
+static XF86VideoAdaptorPtr
+TDFXAllocAdaptor(ScrnInfoPtr pScrn, int numberPorts)
+{
+ XF86VideoAdaptorPtr adapt;
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv;
+
+ if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
+ return NULL;
+
+ if(!(pPriv = xcalloc(1, sizeof(TDFXPortPrivRec) + (numberPorts * sizeof(DevUnion)))))
+ {
+ xfree(adapt);
+ return NULL;
+ }
+
+ adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
+ adapt->pPortPrivates[0].ptr = (pointer)pPriv;
+
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+ xvFilterQuality = MAKE_ATOM("XV_FILTER_QUALITY");
+
+ pPriv->colorKey = pTDFX->videoKey;
+ pPriv->videoStatus = 0;
+ pPriv->filterQuality = 1;
+
+ return adapt;
+}
+
+
+static XF86VideoAdaptorPtr
+TDFXSetupImageVideoOverlay(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv;
+ XF86VideoAdaptorPtr adapt;
+
+ if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_OVERLAY_PORTS)))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "3dfx Video Overlay";
+ adapt->nPorts = TDFX_MAX_OVERLAY_PORTS;
+ adapt->nEncodings = sizeof(OverlayEncoding) / sizeof(XF86VideoEncodingRec);
+ adapt->pEncodings = OverlayEncoding;
+ adapt->nFormats = sizeof(OverlayFormats) / sizeof(XF86VideoFormatRec);
+ adapt->pFormats = OverlayFormats;
+ adapt->nAttributes = sizeof(OverlayAttributes) / sizeof(XF86AttributeRec);
+ adapt->pAttributes = OverlayAttributes;
+ adapt->nImages = sizeof(OverlayImages) / sizeof(XF86ImageRec);
+ adapt->pImages = OverlayImages;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = TDFXStopVideoOverlay;
+ adapt->SetPortAttribute = TDFXSetPortAttributeOverlay;
+ adapt->GetPortAttribute = TDFXGetPortAttributeOverlay;
+ adapt->QueryBestSize = TDFXQueryBestSize;
+ adapt->PutImage = TDFXPutImageOverlay;
+ adapt->QueryImageAttributes = TDFXQueryImageAttributes;
+
+ pTDFX->overlayAdaptor = adapt;
+
+ pPriv = (TDFXPortPrivPtr)(adapt->pPortPrivates[0].ptr);
+ REGION_INIT(pScreen, &(pPriv->clip), NullBox, 0);
+
+ TDFXResetVideoOverlay(pScrn);
+
+ return adapt;
+}
+
+static XF86VideoAdaptorPtr
+TDFXSetupImageVideoTexture(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ XF86VideoAdaptorPtr adapt;
+ int i;
+
+ if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_TEXTURE_PORTS)))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = 0;
+ adapt->name = "3dfx Video Texture";
+ adapt->nPorts = TDFX_MAX_TEXTURE_PORTS;
+ adapt->nEncodings = sizeof(TextureEncoding) / sizeof(XF86VideoEncodingRec);
+ adapt->pEncodings = TextureEncoding;
+ adapt->nFormats = sizeof(TextureFormats) / sizeof(XF86VideoFormatRec);
+ adapt->pFormats = TextureFormats;
+ adapt->nAttributes = sizeof(TextureAttributes) / sizeof(XF86AttributeRec);
+ adapt->pAttributes = TextureAttributes;
+ adapt->nImages = sizeof(TextureImages) / sizeof(XF86ImageRec);
+ adapt->pImages = TextureImages;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = TDFXStopVideoTexture;
+ adapt->SetPortAttribute = TDFXSetPortAttributeTexture;
+ adapt->GetPortAttribute = TDFXGetPortAttributeTexture;
+ adapt->QueryBestSize = TDFXQueryBestSize;
+ adapt->PutImage = TDFXPutImageTexture;
+ adapt->QueryImageAttributes = TDFXQueryImageAttributes;
+
+ for(i = 0; i < TDFX_MAX_TEXTURE_PORTS; i++)
+ adapt->pPortPrivates[i].val = i;
+
+ pTDFX->textureAdaptor = adapt;
+
+ return adapt;
+}
+
+
+/*
+ * MISCELLANEOUS ROUTINES
+ */
+
+static Bool
+TDFXClipVideo(
+ BoxPtr dst,
+ INT32 *xa,
+ INT32 *xb,
+ INT32 *ya,
+ INT32 *yb,
+ RegionPtr reg,
+ INT32 width,
+ INT32 height
+){
+ INT32 vscale, hscale, delta;
+ BoxPtr extents = REGION_EXTENTS(DummyScreen, reg);
+ int diff;
+
+ hscale = ((*xb - *xa) << 16) / (dst->x2 - dst->x1);
+ vscale = ((*yb - *ya) << 16) / (dst->y2 - dst->y1);
+
+ *xa <<= 16; *xb <<= 16;
+ *ya <<= 16; *yb <<= 16;
+
+ diff = extents->x1 - dst->x1;
+ if(diff > 0) {
+ dst->x1 = extents->x1;
+ *xa += diff * hscale;
+ }
+ diff = dst->x2 - extents->x2;
+ if(diff > 0) {
+ dst->x2 = extents->x2;
+ *xb -= diff * hscale;
+ }
+ diff = extents->y1 - dst->y1;
+ if(diff > 0) {
+ dst->y1 = extents->y1;
+ *ya += diff * vscale;
+ }
+ diff = dst->y2 - extents->y2;
+ if(diff > 0) {
+ dst->y2 = extents->y2;
+ *yb -= diff * vscale;
+ }
+
+ if(*xa < 0) {
+ diff = (- *xa + hscale - 1)/ hscale;
+ dst->x1 += diff;
+ *xa += diff * hscale;
+ }
+ delta = *xb - (width << 16);
+ if(delta > 0) {
+ diff = (delta + hscale - 1)/ hscale;
+ dst->x2 -= diff;
+ *xb -= diff * hscale;
+ }
+ if(*xa >= *xb) return FALSE;
+
+ if(*ya < 0) {
+ diff = (- *ya + vscale - 1)/ vscale;
+ dst->y1 += diff;
+ *ya += diff * vscale;
+ }
+ delta = *yb - (height << 16);
+ if(delta > 0) {
+ diff = (delta + vscale - 1)/ vscale;
+ dst->y2 -= diff;
+ *yb -= diff * vscale;
+ }
+ if(*ya >= *yb) return FALSE;
+
+ if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) ||
+ (dst->y1 != extents->y1) || (dst->y2 != extents->y2))
+ {
+ RegionRec clipReg;
+ REGION_INIT(DummyScreen, &clipReg, dst, 1);
+ REGION_INTERSECT(DummyScreen, reg, reg, &clipReg);
+ REGION_UNINIT(DummyScreen, &clipReg);
+ }
+ return TRUE;
+}
+
+static int
+TDFXQueryImageAttributes(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short *w, unsigned short *h,
+ int *pitches, int *offsets
+){
+ int size, tmp;
+
+ if(*w > 1024) *w = 1024;
+ if(*h > 1024) *h = 1024;
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *h = (*h + 1) & ~1;
+ size = (*w + 3) & ~3;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ if(offsets) offsets[1] = size;
+ tmp = ((*w >> 1) + 3) & ~3;
+ if(pitches) pitches[1] = pitches[2] = tmp;
+ tmp *= (*h >> 1);
+ size += tmp;
+ if(offsets) offsets[2] = size;
+ size += tmp;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if(pitches) pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+
+
+static int
+TDFXSetPortAttributeOverlay(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data
+){
+
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+
+ if(attribute == xvColorKey) {
+ pPriv->colorKey = value;
+ pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey);
+ pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey);
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+ } else if(attribute == xvFilterQuality) {
+ if((value < 0) || (value > 1))
+ return BadValue;
+ pPriv->filterQuality = value;
+ } else return BadMatch;
+
+ return Success;
+}
+
+static int
+TDFXGetPortAttributeOverlay(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+){
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
+
+ if(attribute == xvColorKey) {
+ *value = pPriv->colorKey;
+ } else if(attribute == xvFilterQuality) {
+ *value = pPriv->filterQuality;
+ } else return BadMatch;
+
+ return Success;
+}
+
+
+static int
+TDFXSetPortAttributeTexture(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value,
+ pointer data
+) {
+ return Success;
+}
+
+
+static int
+TDFXGetPortAttributeTexture(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value,
+ pointer data
+){
+ return Success;
+}
+
+
+static void
+TDFXQueryBestSize(
+ ScrnInfoPtr pScrn,
+ Bool motion,
+ short vid_w, short vid_h,
+ short drw_w, short drw_h,
+ unsigned int *p_w, unsigned int *p_h,
+ pointer data
+){
+ if(vid_w > drw_w) drw_w = vid_w;
+ if(vid_h > drw_h) drw_h = vid_h;
+
+ *p_w = drw_w;
+ *p_h = drw_h;
+}
+
+
+static void
+TDFXCopyData(
+ unsigned char *src,
+ unsigned char *dst,
+ int srcPitch,
+ int dstPitch,
+ int h,
+ int w
+){
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ w >>= 1;
+ while(h--) {
+ int i;
+ for (i=0; i<w; i++)
+ ((unsigned long *)dst)[i]=BE_WSWAP32(((unsigned long *)src)[i]);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+#else
+ w <<= 1;
+ while(h--) {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+#endif
+}
+
+static void
+TDFXCopyMungedData(
+ unsigned char *src1,
+ unsigned char *src2,
+ unsigned char *src3,
+ unsigned char *dst1,
+ int srcPitch,
+ int srcPitch2,
+ int dstPitch,
+ int h,
+ int w
+){
+ CARD32 *dst;
+ CARD8 *s1, *s2, *s3;
+ int i, j;
+
+ w >>= 1;
+
+ for(j = 0; j < h; j++) {
+ dst = (CARD32*)dst1;
+ s1 = src1; s2 = src2; s3 = src3;
+ i = w;
+ while(i > 4) {
+ dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) |
+ (s2[0] << 24));
+ dst[1] = BE_WSWAP32(s1[2] | (s1[3] << 16) | (s3[1] << 8) |
+ (s2[1] << 24));
+ dst[2] = BE_WSWAP32(s1[4] | (s1[5] << 16) | (s3[2] << 8) |
+ (s2[2] << 24));
+ dst[3] = BE_WSWAP32(s1[6] | (s1[7] << 16) | (s3[3] << 8) |
+ (s2[3] << 24));
+ dst += 4; s2 += 4; s3 += 4; s1 += 8;
+ i -= 4;
+ }
+ while(i--) {
+ dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) |
+ (s2[0] << 24));
+ dst++; s2++; s3++;
+ s1 += 2;
+ }
+
+ dst1 += dstPitch;
+ src1 += srcPitch;
+ if(j & 1) {
+ src2 += srcPitch2;
+ src3 += srcPitch2;
+ }
+ }
+}
+
+
+/*
+ * TEXTURE DRAWING FUNCTIONS
+ */
+
+
+static void
+TDFXStopVideoTexture(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ if (cleanup) {
+ if(pTDFX->textureBuffer) {
+ xf86FreeOffscreenArea(pTDFX->textureBuffer);
+ pTDFX->textureBuffer = NULL;
+ }
+ }
+}
+
+
+static void
+TDFXScreenToScreenYUVStretchBlit (ScrnInfoPtr pScrn,
+ short src_x1, short src_y1,
+ short src_x2, short src_y2,
+ short dst_x1, short dst_y1,
+ short dst_x2, short dst_y2)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ /* reformulate the paramaters the way the hardware wants them */
+ INT32 src_x = src_x1 & 0x1FFF;
+ INT32 src_y = src_y1 & 0x1FFF;
+ INT32 dst_x = dst_x1 & 0x1FFF;
+ INT32 dst_y = dst_y1 & 0x1FFF;
+ INT32 src_w = (src_x2 - src_x1) & 0x1FFF;
+ INT32 src_h = (src_y2 - src_y1) & 0x1FFF;
+ INT32 dst_w = (dst_x2 - dst_x1) & 0x1FFF;
+ INT32 dst_h = (dst_y2 - dst_y1) & 0x1FFF;
+ /* Setup for blit src and dest */
+ TDFXMakeRoom(pTDFX, 4);
+ DECLARE(SSTCP_DSTSIZE|SSTCP_SRCSIZE|SSTCP_DSTXY|SSTCP_COMMAND/*|SSTCP_COMMANDEXTRA*/);
+ /* TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, SST_COMMANDEXTRA_VSYNC);*/
+ TDFXWriteLong(pTDFX, SST_2D_SRCSIZE, src_w | (src_h<<16));
+ TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, dst_w | (dst_h<<16));
+ TDFXWriteLong(pTDFX, SST_2D_DSTXY, dst_x | (dst_y<<16));
+ TDFXWriteLong(pTDFX, SST_2D_COMMAND, SST_2D_SCRNTOSCRNSTRETCH | 0xCC000000);
+ /* Write to the launch area to start the blit */
+ TDFXMakeRoom(pTDFX, 1);
+ DECLARE_LAUNCH(1, 0);
+ TDFXWriteLong(pTDFX, SST_2D_LAUNCH, (src_x<<1) | (src_y<<16));
+ /* Wait for it to happen */
+ TDFXSendNOPFifo2D(pScrn);
+}
+
+
+static void
+YUVPlanarToPacked (ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short src_h, short src_w,
+ int id, unsigned char *buf,
+ short width, short height,
+ FBAreaPtr fbarea)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ unsigned char *psrc, *pdst;
+ int count;
+ int baseaddr;
+ INT32 yuvBaseAddr, yuvStride;
+
+ /* Save these registers so I can restore them when we are done. */
+ yuvBaseAddr = TDFXReadLongMMIO(pTDFX, YUVBASEADDR);
+ yuvStride = TDFXReadLongMMIO(pTDFX, YUVSTRIDE);
+
+ /* Set yuvBaseAddress and yuvStride. */
+ baseaddr = pTDFX->fbOffset + pTDFX->cpp * fbarea->box.x1 + pTDFX->stride * fbarea->box.y1;
+ TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, pTDFX->stride);
+ TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, baseaddr);
+
+ /* Copy Y plane (twice as much Y as U or V) */
+ psrc = buf;
+ psrc += (src_x & ~0x1) + src_y * width;
+ pdst = pTDFX->MMIOBase[0] + YUV_Y_BASE;
+ TDFXCopyData(psrc, pdst, width, 1024, src_h, src_w + (src_x & 0x1));
+
+ /* Copy V plane */
+ psrc = buf + width * height;
+ psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
+ pdst = pTDFX->MMIOBase[0] + YUV_V_BASE;
+ TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1);
+
+ /* Copy U plane */
+ psrc = buf + width * height + (width >> 1) * (height >> 1);
+ psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
+ pdst = pTDFX->MMIOBase[0] + YUV_U_BASE;
+ TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1);
+
+ /* IDLE until the copy finished, timeout for safety */
+ for (count = 0; count < 1000; count++)
+ if (!((TDFXReadLongMMIO(pTDFX, STATUS) & SST_BUSY)))
+ break;
+
+ /* Restore trashed registers */
+ TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, yuvBaseAddr);
+ TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, yuvStride);
+
+ /* Wait for it to happen */
+ TDFXSendNOPFifo2D(pScrn);
+}
+
+
+static int
+TDFXPutImageTexture(
+ ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char* buf,
+ short width, short height,
+ Bool sync,
+ RegionPtr clipBoxes, pointer data
+ )
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ BoxPtr pbox;
+ int nbox;
+ int format;
+
+ TDFXTRACE("TDFXPutImageTexture(src_x=%d, src_y=%d, drw_x=%d, drw_y=%d, .. sync=%d\n",
+ src_x, src_y, drw_x, drw_y, sync);
+
+ /* Check the source format */
+ if (id == FOURCC_YV12) format = SST_2D_FORMAT_YUYV;
+ else if (id == FOURCC_UYVY) format = SST_2D_FORMAT_UYVY;
+ else return BadAlloc;
+
+ /* Get a buffer to store the packed YUV data */
+ if (!(pTDFX->textureBuffer = TDFXAllocateMemoryArea(pScrn, pTDFX->textureBuffer, src_w, src_h)))
+ return BadAlloc;
+
+ /* Pack the YUV data in offscreen memory using YUV framebuffer (0x[CDE]0000) */
+ YUVPlanarToPacked (pScrn, src_x, src_y, src_h, src_w,
+ id, buf, width, height,
+ pTDFX->textureBuffer);
+
+ /* Setup source and destination pixel formats (yuv -> rgb) */
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->stride|((pTDFX->cpp+1)<<16));
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->stride|((format)<<16));
+
+ /* Blit packed YUV data from offscreen memory, respecting clips */
+#define SRC_X1 (pTDFX->textureBuffer->box.x1)
+#define SRC_Y1 (pTDFX->textureBuffer->box.y1)
+#define SCALEX(dx) ((int)(((dx) * src_w) / drw_w))
+#define SCALEY(dy) ((int)(((dy) * src_h) / drw_h))
+ for (nbox = REGION_NUM_RECTS(clipBoxes),
+ pbox = REGION_RECTS(clipBoxes); nbox > 0; nbox--, pbox++)
+ {
+ TDFXScreenToScreenYUVStretchBlit (pScrn,
+ SRC_X1 + SCALEX(pbox->x1 - drw_x),
+ SRC_Y1 + SCALEY(pbox->y1 - drw_y),
+ SRC_X1 + SCALEX(pbox->x2 - drw_x),
+ SRC_Y1 + SCALEY(pbox->y2 - drw_y),
+ pbox->x1, pbox->y1,
+ pbox->x2, pbox->y2);
+ }
+
+ /* Restore the WAX registers we trashed */
+ TDFXMakeRoom(pTDFX, 2);
+ DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
+ TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->sst2DDstFmtShadow);
+ TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->sst2DSrcFmtShadow);
+
+ /* Wait for it to happen */
+ TDFXSendNOPFifo2D(pScrn);
+
+ return Success;
+}
+
+
+/*
+ * COMMON DRAWING FUNCTIONS
+ */
+
+static Bool
+RegionsEqual(RegionPtr A, RegionPtr B)
+{
+ int *dataA, *dataB;
+ int num;
+
+ num = REGION_NUM_RECTS(A);
+ if(num != REGION_NUM_RECTS(B))
+ return FALSE;
+
+ if((A->extents.x1 != B->extents.x1) ||
+ (A->extents.x2 != B->extents.x2) ||
+ (A->extents.y1 != B->extents.y1) ||
+ (A->extents.y2 != B->extents.y2))
+ return FALSE;
+
+ dataA = (int*)REGION_RECTS(A);
+ dataB = (int*)REGION_RECTS(B);
+
+ while(num--) {
+ if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+ return FALSE;
+ dataA += 2;
+ dataB += 2;
+ }
+
+ return TRUE;
+}
+
+/*
+ * OVERLAY DRAWING FUNCTIONS
+ */
+
+
+static void
+TDFXResetVideoOverlay(ScrnInfoPtr pScrn)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
+
+ /* reset the video */
+ pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+ pTDFX->writeLong(pTDFX, RGBMAXDELTA, 0x0080808);
+ pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey);
+ pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey);
+}
+
+
+static void
+TDFXStopVideoOverlay(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
+
+ REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+ if(cleanup) {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+ }
+ if(pTDFX->overlayBuffer) {
+ xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
+ pTDFX->overlayBuffer = NULL;
+ }
+ if(pTDFX->overlayBuffer2) {
+ xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
+ pTDFX->overlayBuffer2 = NULL;
+ }
+ pPriv->videoStatus = 0;
+ } else {
+ if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
+ pPriv->videoStatus |= OFF_TIMER;
+ pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+ }
+ }
+}
+
+
+/* * * * * *
+
+Decoder...
+
+VIDPROCCFG: 0x5c: Video Processor Configuration register
+
+#define VIDPROCCFGMASK 0xa2e3eb6c
+ 3 2 1 0
+ 10987654321098765432109876543210
+ 10100010111000111110101101101100
+
+The "1" bits are the bits cleared to 0 in pTDFX->ModeReg.vidcfg
+
+
+Then we or in 0x320:
+
+ 11
+ 109876543210
+320 = 001100100000
+
+bit 11=0: Do not bypass clut (colour lookup) for overlay
+bit 10=0: Do not bypass clut for desktop
+bit 9=1: use video-in buffer address as overlay start
+ address (auto-flipping)
+bit 8=1: fetch overlay surface
+bit 7=0: do not fetch the desktop surface (?)
+bit 6=0: chromakey not inverted
+bit 5=1: chromakey enabled
+bit 4=0: half-mode disabled
+bit 3=0: not interlaced (interlace doesn't work on Avenger)
+bit 2=0: overlay stereo disabled
+bit 1=0: Windows cursor mode
+bit 0=0: Video processor off, VGA mode on
+
+SST_VIDEO_2X_MODE_EN: bit26: means 2 pixels per screen clock mode is on
+
+VIDOVERLAYSTARTCOORDS: x&y coords of overlay on the screen
+VIDOVERLAYENDSCREENCOORDS: x&y coorder of bot-right of overlay on the screen
+VIDOVERLAYDUDX: step size in source per hoz step in screen space (x-mag)
+VIDOVERLAYDUDXOFFSETSRCWIDTH:
+VIDOVERLAYDVDY: step size in sourcxe per vertical step in screen (y-mag)
+VIDOVERLAYDVDYOFFSET: initial offset of DVDY
+VIDDESKTOPOVERLAYSTRIDE: desktop surface stride
+
+SST_3D_LEFTOVERLAYBUF: starting physical address of the overlay surface buffer
+VIDINADDR0: starting address of video-in buffer-0
+ [this is set, but this is for video _input_ as I understand docs...?]
+
+* * * * * */
+
+static void
+TDFXDisplayVideoOverlay(
+ ScrnInfoPtr pScrn,
+ int id,
+ int offset,
+ short width, short height,
+ int pitch,
+ int left, int right, int top,
+ BoxPtr dstBox,
+ short src_w, short src_h,
+ short drw_w, short drw_h
+){
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
+ int dudx, dvdy;
+
+ dudx = (src_w << 20) / drw_w;
+ dvdy = (src_h << 20) / drw_h;
+
+ offset += ((left >> 16) & ~1) << 1;
+ left = (left & 0x0001ffff) << 3;
+
+ pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
+ pTDFX->ModeReg.vidcfg |= 0x00000320;
+
+ if(drw_w != src_w) pTDFX->ModeReg.vidcfg |= (1 << 14);
+ if(drw_h != src_h) pTDFX->ModeReg.vidcfg |= (1 << 15);
+ if(id == FOURCC_UYVY) pTDFX->ModeReg.vidcfg |= (6 << 21);
+ else pTDFX->ModeReg.vidcfg |= (5 << 21);
+ if(pScrn->depth == 8) pTDFX->ModeReg.vidcfg |= (1 << 11);
+ /* can't do bilinear filtering when in 2X mode */
+ if(pPriv->filterQuality && !(pTDFX->ModeReg.vidcfg & SST_VIDEO_2X_MODE_EN))
+ pTDFX->ModeReg.vidcfg |= (3 << 16);
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+
+ pTDFX->writeLong(pTDFX, VIDOVERLAYSTARTCOORDS, dstBox->x1 | (dstBox->y1 << 12));
+ pTDFX->writeLong(pTDFX, VIDOVERLAYENDSCREENCOORDS, (dstBox->x2 - 1) | ((dstBox->y2 - 1) << 12));
+ pTDFX->writeLong(pTDFX, VIDOVERLAYDUDX, dudx);
+ pTDFX->writeLong(pTDFX, VIDOVERLAYDUDXOFFSETSRCWIDTH, left | (src_w << 20));
+ pTDFX->writeLong(pTDFX, VIDOVERLAYDVDY, dvdy);
+ pTDFX->writeLong(pTDFX, VIDOVERLAYDVDYOFFSET, (top & 0x0000ffff) << 3);
+
+ pTDFX->ModeReg.stride &= 0x0000ffff;
+ pTDFX->ModeReg.stride |= pitch << 16;
+ pTDFX->writeLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE, pTDFX->ModeReg.stride);
+ pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3);
+ pTDFX->writeLong(pTDFX, VIDINADDR0, offset & ~3);
+ TDFXTRACE("TDFXDisplayVideoOverlay: done, offset=0x%x\n");
+}
+
+
+#if 0
+
+/* * * * *
+
+TDFXSwapVideoOverlayBuffer tries to use the Avenger SWAPBUFFER
+capability to change frames without tearing.
+
+Use this in preference to TDFXDisplayVideoOverlay where all image
+parameters are the same as the previous frame - ie where only the
+SST_3D_LEFTOVERLAYBUF register would have been changed.
+
+NOTE: Work in progress - doesn't seem to sync to VSYNC, and only every
+other frame gets displayed...
+
+Seeing that the buffer swap initiated by DisplayVideoOverlay gets
+synced to VSYNC anyway, just adding double-buffering to PutImageOverlay
+appears to do the job. Still - I leave this code in in case we can
+get it working later
+
+ -- Steve Davies 2002-10-04
+ -- <steve@daviesfam.org>
+
+* * * * * */
+
+static void
+TDFXSwapVideoOverlayBuffer(
+ ScrnInfoPtr pScrn,
+ int offset,
+ int left
+){
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ offset += ((left >> 16) & ~1) << 1;
+ /* Write mew buffer address */
+ pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3);
+ /* Incremement the swap-pending counter */
+ pTDFX->writeLong(pTDFX, SST_3D_SWAPPENDING, 0);
+ /* write the swapbuffer command - triggered by (next) VSYNC */
+ pTDFX->writeLong(pTDFX, SST_3D_SWAPBUFFERCMD, 1);
+}
+
+#endif
+
+static int
+TDFXPutImageOverlay(
+ ScrnInfoPtr pScrn,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ int id, unsigned char* buf,
+ short width, short height,
+ Bool Sync,
+ RegionPtr clipBoxes, pointer data
+){
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
+ INT32 xa, xb, ya, yb;
+ unsigned char *dst_start;
+ int pitch, new_size, offset;
+ int s2offset = 0, s3offset = 0;
+ int srcPitch = 0, srcPitch2 = 0;
+ int dstPitch;
+ int top, left, npixels, nlines, bpp;
+ BoxRec dstBox;
+ CARD32 tmp;
+
+ TDFXTRACE("TDFXPutImageOverlay: src_x=%d, src_y=%d, drw_x=%d, drw_y=%d, src_w=%d, src_h=%d, drw_w=%d, drw_h=%d, id=%d, width=%d, height=%d, sync=%d\n",
+ src_x, src_y, drw_x, drw_y, src_w, src_h, drw_w, drw_h, id, width, height, Sync);
+
+ /*
+ * s2offset, s3offset - byte offsets into U and V plane of the
+ * source where copying starts. Y plane is
+ * done by editing "buf".
+ *
+ * offset - byte offset to the first line of the destination.
+ *
+ * dst_start - byte address to the first displayed pel.
+ *
+ */
+
+ if(src_w > drw_w) drw_w = src_w;
+ if(src_h > drw_h) drw_h = src_h;
+
+ /* Clip */
+ xa = src_x;
+ xb = src_x + src_w;
+ ya = src_y;
+ yb = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if(!TDFXClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height))
+ return Success;
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+ bpp = pScrn->bitsPerPixel >> 3;
+ pitch = bpp * pScrn->displayWidth;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ dstPitch = ((width << 1) + 3) & ~3;
+ new_size = ((dstPitch * height) + bpp - 1) / bpp;
+ srcPitch = (width + 3) & ~3;
+ s2offset = srcPitch * height;
+ srcPitch2 = ((width >> 1) + 3) & ~3;
+ s3offset = (srcPitch2 * (height >> 1)) + s2offset;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ dstPitch = ((width << 1) + 3) & ~3;
+ new_size = ((dstPitch * height) + bpp - 1) / bpp;
+ srcPitch = (width << 1);
+ break;
+ }
+
+ if(!(pTDFX->overlayBuffer = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer, new_size)))
+ return BadAlloc;
+ /* Second buffer for double-buffering (If we can't get the memory then we just don't double-buffer) */
+ if (!(pTDFX->overlayBuffer2 = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer2, new_size)))
+ pTDFX->whichOverlayBuffer = 0;
+ TDFXTRACE("TDFXPutImageOverlay: %s have a second overlay buffer for double-buffering\n",
+ pTDFX->overlayBuffer2 ? "Do" : "Do not");
+
+ /* copy data */
+ top = ya >> 16;
+ left = (xa >> 16) & ~1;
+ npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left;
+
+ /* Get buffer offset */
+ if (pTDFX->whichOverlayBuffer == 0)
+ offset = (pTDFX->overlayBuffer->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset;
+ else
+ offset = (pTDFX->overlayBuffer2->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset;
+
+ /* Flip to other buffer for next time */
+ pTDFX->whichOverlayBuffer ^= 1;
+
+ dst_start = pTDFX->FbBase + offset;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ top &= ~1;
+ dst_start += left << 1;
+ tmp = ((top >> 1) * srcPitch2) + (left >> 1);
+ s2offset += tmp;
+ s3offset += tmp;
+ if(id == FOURCC_I420) {
+ tmp = s2offset;
+ s2offset = s3offset;
+ s3offset = tmp;
+ }
+ nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top;
+ TDFXTRACE("TDFXPutImageOverlay: using copymungeddata\n");
+ TDFXCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset,
+ buf + s3offset, dst_start, srcPitch, srcPitch2,
+ dstPitch, nlines, npixels);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ left <<= 1;
+ buf += (top * srcPitch) + left;
+ nlines = ((yb + 0xffff) >> 16) - top;
+ dst_start += left;
+ TDFXTRACE("TDFXPutImageOverlay: using copydata\n");
+ TDFXCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
+ break;
+ }
+
+ if(!RegionsEqual(&pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+ (*pTDFX->AccelInfoRec->FillSolidRects)(pScrn, pPriv->colorKey,
+ GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+ }
+
+ TDFXDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPriv->videoStatus = CLIENT_VIDEO_ON;
+
+ pTDFX->VideoTimerCallback = TDFXVideoTimerCallback;
+
+ /* Display some swap-buffer related info...: vidCurrOverlayStartAddr, fbiSwapHistory */
+ /* To give us some insight into workings or otherwise of swapbuffer stuff */
+ TDFXTRACE("TDFXPutImageOverlay: vidCurrOverlayStrtAdr=%x, fbiSwpHist=%x, whchBuf=%d, 3Dstus=%x\n",
+ pTDFX->readLong(pTDFX, VIDCUROVERLAYSTARTADDR),
+ pTDFX->readLong(pTDFX, SST_3D_FBISWAPHISTORY),
+ pTDFX->whichOverlayBuffer,
+ pTDFX->readLong(pTDFX, SST_3D_STATUS)
+ );
+
+ return Success;
+}
+
+
+static void
+TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
+
+ if(pPriv->videoStatus & TIMER_MASK) {
+ if(pPriv->videoStatus & OFF_TIMER) {
+ if(pPriv->offTime < time) {
+ pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+ pPriv->videoStatus = FREE_TIMER;
+ pPriv->freeTime = time + FREE_DELAY;
+ }
+ } else
+ if(pPriv->videoStatus & FREE_TIMER) {
+ if(pPriv->freeTime < time) {
+ if(pTDFX->overlayBuffer) {
+ xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
+ pTDFX->overlayBuffer = NULL;
+ }
+ if(pTDFX->overlayBuffer2) {
+ xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
+ pTDFX->overlayBuffer2 = NULL;
+ }
+ pPriv->videoStatus = 0;
+ pTDFX->VideoTimerCallback = NULL;
+ }
+ }
+ } else /* shouldn't get here */
+ pTDFX->VideoTimerCallback = NULL;
+}
+
+
+/*
+ * MEMORY MANAGEMENT
+ */
+
+
+static FBAreaPtr
+TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height)
+{
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ ScreenPtr pScreen;
+ FBAreaPtr new_area;
+
+ if (area) {
+ if ((area->box.x2 - area->box.x1 >= width) &&
+ (area->box.y2 - area->box.y1 >= height))
+ return area;
+
+ if (xf86ResizeOffscreenArea(area, width, height))
+ return area;
+
+ xf86FreeOffscreenArea(area);
+ }
+
+ pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
+
+ if (!new_area) {
+ int max_width, max_height;
+
+ xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pTDFX->cpp, 0, PRIORITY_EXTREME);
+
+ if (max_width < width || max_height < height)
+ return NULL;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
+ }
+
+ return new_area;
+}
+
+
+static FBLinearPtr
+TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
+{
+ ScreenPtr pScreen;
+ FBLinearPtr new_linear;
+
+ if(linear) {
+ if(linear->size >= size)
+ return linear;
+
+ if(xf86ResizeOffscreenLinear(linear, size))
+ return linear;
+
+ xf86FreeOffscreenLinear(linear);
+ }
+
+ pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
+
+ if(!new_linear) {
+ int max_size;
+
+ xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME);
+
+ if(max_size < size)
+ return NULL;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
+ }
+
+ return new_linear;
+}
+
+/****************** Offscreen stuff ***************/
+
+typedef struct {
+ FBLinearPtr linear;
+ Bool isOn;
+} OffscreenPrivRec, * OffscreenPrivPtr;
+
+static int
+TDFXAllocateSurface(
+ ScrnInfoPtr pScrn,
+ int id,
+ unsigned short w,
+ unsigned short h,
+ XF86SurfacePtr surface
+){
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ FBLinearPtr linear;
+ int pitch, fbpitch, size, bpp;
+ OffscreenPrivPtr pPriv;
+
+ if((w > 2048) || (h > 2048))
+ return BadAlloc;
+
+ w = (w + 1) & ~1;
+ pitch = ((w << 1) + 15) & ~15;
+ bpp = pScrn->bitsPerPixel >> 3;
+ fbpitch = bpp * pScrn->displayWidth;
+ size = ((pitch * h) + bpp - 1) / bpp;
+
+ if(!(linear = TDFXAllocateMemoryLinear(pScrn, NULL, size)))
+ return BadAlloc;
+
+ surface->width = w;
+ surface->height = h;
+
+ if(!(surface->pitches = xalloc(sizeof(int)))) {
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(surface->offsets = xalloc(sizeof(int)))) {
+ xfree(surface->pitches);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+ if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xf86FreeOffscreenLinear(linear);
+ return BadAlloc;
+ }
+
+ pPriv->linear = linear;
+ pPriv->isOn = FALSE;
+
+ surface->pScrn = pScrn;
+ surface->id = id;
+ surface->pitches[0] = pitch;
+ surface->offsets[0] = pTDFX->fbOffset + (linear->offset * bpp);
+ surface->devPrivate.ptr = (pointer)pPriv;
+
+ return Success;
+}
+
+static int
+TDFXStopSurface(
+ XF86SurfacePtr surface
+){
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+
+ if(pPriv->isOn) {
+ TDFXPtr pTDFX = TDFXPTR(surface->pScrn);
+ pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
+ pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
+ pPriv->isOn = FALSE;
+ }
+
+ return Success;
+}
+
+
+static int
+TDFXFreeSurface(
+ XF86SurfacePtr surface
+){
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+
+ if(pPriv->isOn)
+ TDFXStopSurface(surface);
+ xf86FreeOffscreenLinear(pPriv->linear);
+ xfree(surface->pitches);
+ xfree(surface->offsets);
+ xfree(surface->devPrivate.ptr);
+
+ return Success;
+}
+
+static int
+TDFXGetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 *value
+){
+ return TDFXGetPortAttributeOverlay(pScrn, attribute, value,
+ (pointer)(GET_PORT_PRIVATE(pScrn)));
+}
+
+static int
+TDFXSetSurfaceAttribute(
+ ScrnInfoPtr pScrn,
+ Atom attribute,
+ INT32 value
+){
+ return TDFXSetPortAttributeOverlay(pScrn, attribute, value,
+ (pointer)(GET_PORT_PRIVATE(pScrn)));
+}
+
+static int
+TDFXDisplaySurface(
+ XF86SurfacePtr surface,
+ short src_x, short src_y,
+ short drw_x, short drw_y,
+ short src_w, short src_h,
+ short drw_w, short drw_h,
+ RegionPtr clipBoxes
+){
+ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
+ ScrnInfoPtr pScrn = surface->pScrn;
+ TDFXPtr pTDFX = TDFXPTR(pScrn);
+ TDFXPortPrivPtr portPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
+ INT32 x1, y1, x2, y2;
+ BoxRec dstBox;
+
+ x1 = src_x;
+ x2 = src_x + src_w;
+ y1 = src_y;
+ y2 = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ if(!TDFXClipVideo(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
+ surface->width, surface->height))
+ {
+ return Success;
+ }
+
+ dstBox.x1 -= pScrn->frameX0;
+ dstBox.x2 -= pScrn->frameX0;
+ dstBox.y1 -= pScrn->frameY0;
+ dstBox.y2 -= pScrn->frameY0;
+
+#if 0
+ TDFXResetVideoOverlay(pScrn);
+#endif
+
+ TDFXDisplayVideoOverlay(pScrn, surface->id, surface->offsets[0],
+ surface->width, surface->height, surface->pitches[0],
+ x1, y1, x2, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ (*pTDFX->AccelInfoRec->FillSolidRects)(pScrn, portPriv->colorKey,
+ GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+
+ pPriv->isOn = TRUE;
+ /* we've prempted the XvImage stream so set its free timer */
+ if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
+ REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
+ UpdateCurrentTime();
+ portPriv->videoStatus = FREE_TIMER;
+ portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+ pTDFX->VideoTimerCallback = TDFXVideoTimerCallback;
+ }
+
+ return Success;
+}
+
+static void
+TDFXInitOffscreenImages(ScreenPtr pScreen)
+{
+ XF86OffscreenImagePtr offscreenImages;
+
+ /* need to free this someplace */
+ if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
+ return;
+
+ offscreenImages[0].image = &OverlayImages[0];
+ offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
+ VIDEO_CLIP_TO_VIEWPORT;
+ offscreenImages[0].alloc_surface = TDFXAllocateSurface;
+ offscreenImages[0].free_surface = TDFXFreeSurface;
+ offscreenImages[0].display = TDFXDisplaySurface;
+ offscreenImages[0].stop = TDFXStopSurface;
+ offscreenImages[0].setAttribute = TDFXSetSurfaceAttribute;
+ offscreenImages[0].getAttribute = TDFXGetSurfaceAttribute;
+ offscreenImages[0].max_width = 2048;
+ offscreenImages[0].max_height = 2048;
+ offscreenImages[0].num_attributes = 2;
+ offscreenImages[0].attributes = OverlayAttributes;
+
+ xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
+}
diff --git a/src/tdfxdefs.h b/src/tdfxdefs.h
new file mode 100644
index 0000000..a9ef1df
--- /dev/null
+++ b/src/tdfxdefs.h
@@ -0,0 +1,386 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfxdefs.h,v 1.13 2002/10/17 01:02:08 dawes Exp $ */
+/*
+ Voodoo Banshee driver version 1.0.1
+
+ Author: Daryll Strauss
+
+ Copyright: 1998,1999
+*/
+
+#ifndef _TDFXDEFS_H_
+#define _TDFXDEFS_H_
+
+#define TDFXIOMAPSIZE 0x2000000
+
+/* Flags */
+#define BIT(n) (1UL<<(n))
+#define SST_SGRAM_OFLOP_DEL_ADJ_SHIFT 20
+#define SST_SGRAM_CLK_NODELAY BIT(13)
+#define SST_DRAM_REFRESH_EN BIT(0)
+#define SST_DRAM_REFRESH_VALUE_SHIFT 1
+#define SST_DRAM_REFRESH_VALUE (0x1FF<<SST_DRAM_REFRESH_VALUE_SHIFT)
+#define SST_SGRAM_TYPE_SHIFT 27
+#define SST_SGRAM_TYPE (0x1L<<SST_SGRAM_TYPE_SHIFT)
+#define SST_SGRAM_NUM_CHIPSETS BIT(26)
+#define SST_SGRAM_TYPE_8MBIT (0x0L<<SST_SGRAM_TYPE_SHIFT)
+#define SST_SGRAM_TYPE_16MBIT (0x1L<<SST_SGRAM_TYPE_SHIFT)
+#define SST_DISABLE_2D_BLOCK_WRITE BIT(15)
+#define SST_MCTL_TYPE_SDRAM BIT(30)
+#define SST_DAC_MODE_2X BIT(0)
+#define SST_VIDEO_2X_MODE_EN BIT(26)
+#define SST_VGA0_EXTENSIONS BIT(6)
+#define SST_WAKEUP_3C3 1
+#define SST_VGA0_WAKEUP_SELECT_SHIFT 8
+#define SST_VGA0_LEGACY_DECODE_SHIFT 9
+#define SST_VGA0_LEGACY_DECODE (1 << SST_VGA0_LEGACY_DECODE_SHIFT)
+#define SST_VGA0_ENABLE_DECODE 0
+#define SST_ENABLE_ALT_READBACK 0
+#define SST_VGA0_CLUT_SELECT_SHIFT 2
+#define SST_CLUT_SELECT_6BIT 0
+#define SST_CLUT_SELECT_8BIT 1
+#define SST_VGA0_CONFIG_READBACK_SHIFT 10
+#define SST_VIDEO_PROCESSOR_EN BIT(0)
+#define SST_CURSOR_MODE_SHIFT 1
+#define SST_CURSOR_X11 (1<<SST_CURSOR_MODE_SHIFT)
+#define SST_DESKTOP_EN BIT(7)
+#define SST_DESKTOP_PIXEL_FORMAT_SHIFT 18
+#define SST_DESKTOP_CLUT_BYPASS BIT(10)
+#define SST_HALF_MODE BIT(4)
+#define SST_CURSOR_EN BIT(27)
+#define SST_FBI_BUSY BIT(7)
+#define SST_BUSY BIT(9)
+#define SST_RETRACE BIT(6)
+#define SST_COMMANDEXTRA_VSYNC BIT(2)
+
+#define MEM_TYPE_SGRAM 0
+#define MEM_TYPE_SDRAM 1
+/*
+ * SST_RAW_LFB_ADDR_STRIDE(Lg2SizeInK) takes the
+ * lfbMemoryConfig value for SGRAMStrideInTiles. This
+ * is given by this table:
+ * SGRAMStrideInBytes lfbMemoryConfig Value
+ * ================== =====================
+ * 1k 0
+ * 2k 1
+ * 4k 2
+ * 8k 3
+ * 16k 4
+ *
+ * FWIW, the right hand column is log2(left hand column)-10
+ */
+#define SST_RAW_LFB_ADDR_STRIDE_SHIFT 13
+#define SST_RAW_LFB_ADDR_STRIDE(Lg2SizeInK) \
+ ((Lg2SizeInK)<<SST_RAW_LFB_ADDR_STRIDE_SHIFT)
+#define SST_RAW_LFB_ADDR_STRIDE_4K SST_RAW_LFB_ADDR_STRIDE(2)
+#define SST_RAW_LFB_ADDR_STRIDE_8K SST_RAW_LFB_ADDR_STRIDE(3)
+#define SST_RAW_LFB_ADDR_STRIDE_16K SST_RAW_LFB_ADDR_STRIDE(4)
+#define SST_RAW_LFB_TILE_STRIDE_SHIFT 16
+
+#define BLIT_LEFT 1
+#define BLIT_UP 2
+
+/* Base Registers */
+#define STATUS 0x0
+#define PCIINIT0 0x4
+#define SIPMONITOR 0x8
+#define LFBMEMORYCONFIG 0xC
+#define MISCINIT0 0x10
+#define MISCINIT1 0x14
+#define DRAMINIT0 0x18
+#define DRAMINIT1 0x1C
+#define AGPINIT 0x20
+#define TMUGBEINIT 0x24
+#define VGAINIT0 0x28
+#define VGAINIT1 0x2c
+#define DRAMCOMMAND 0x30
+#define DRAMDATA 0x34
+#define PLLCTRL0 0x40
+#define PLLCTRL1 0x44
+#define PLLCTRL2 0x48
+#define DACMODE 0x4c
+#define DACADDR 0x50
+#define DACDATA 0x54
+#define RGBMAXDELTA 0x58
+#define VIDPROCCFG 0x5c
+#define HWCURPATADDR 0x60
+#define HWCURLOC 0x64
+#define HWCURC0 0x68
+#define HWCURC1 0x6c
+#define VIDINFORMAT 0x70
+#define VIDINSTATUS 0x74
+#define VIDSERIALPARALLELPORT 0x78
+#define VIDINXDECIMDELTAS 0x7c
+#define VIDINDECIMINITERRS 0x80
+#define VIDYDECIMDELTA 0x84
+#define VIDPXELBUGTHOLD 0x88
+#define VIDCHROMAMIN 0x8c
+#define VIDCHROMAMAX 0x90
+#define VIDCURRENTLINE 0x94
+#define VIDSCREENSIZE 0x98
+#define VIDOVERLAYSTARTCOORDS 0x9c
+#define VIDOVERLAYENDSCREENCOORDS 0xa0
+#define VIDOVERLAYDUDX 0xa4
+#define VIDOVERLAYDUDXOFFSETSRCWIDTH 0xa8
+#define VIDOVERLAYDVDY 0xac
+#define VIDOVERLAYDVDYOFFSET 0xe0
+#define VIDDESKTOPSTARTADDR 0xe4
+#define VIDDESKTOPOVERLAYSTRIDE 0xe8
+#define VIDINADDR0 0xec
+#define VIDINADDR1 0xf0
+#define VIDINADDR2 0xf4
+#define VIDINSTRIDE 0xf8
+#define VIDCUROVERLAYSTARTADDR 0xfc
+
+/* 2D Commands */
+#define SST_2D_NOP 0
+#define SST_2D_SCRNTOSCRNBLIT 1
+#define SST_2D_SCRNTOSCRNSTRETCH 2
+#define SST_2D_HOSTTOSCRNBLIT 3
+#define SST_2D_HOSTTOSCRNSTRECH 4
+#define SST_2D_RECTANGLEFILL 5
+#define SST_2D_LINE (6 | SST_2D_REVERSIBLE)
+#define SST_2D_POLYLINE (7 | SST_2D_REVERSIBLE)
+#define SST_2D_POLYGONFILL (8 | SST_2D_REVERSIBLE)
+
+/* Flags */
+#define SST_2D_REVERSIBLE BIT(9)
+#define SST_2D_STIPPLE_LINE BIT(12)
+#define SST_2D_MONOCHROME_PATTERN BIT(13)
+#define SST_2D_X_RIGHT_TO_LEFT BIT(14)
+#define SST_2D_Y_BOTTOM_TO_TOP BIT(15)
+#define SST_2D_TRANSPARENT_MONOCHROME BIT(16)
+#define SST_2D_SOURCE_PACKING_SHIFT 22
+#define SST_2D_SOURCE_PACKING_BYTE (1<<SST_2D_SOURCE_PACKING_SHIFT)
+#define SST_2D_SOURCE_PACKING_WORD (2<<SST_2D_SOURCE_PACKING_SHIFT)
+#define SST_2D_SOURCE_PACKING_DWORD (3<<SST_2D_SOURCE_PACKING_SHIFT)
+#define SST_2D_X_PATOFFSET_SHIFT 17
+#define SST_2D_Y_PATOFFSET_SHIFT 20
+#define SST_2D_SRC_FORMAT_SHIFT 16
+#define SST_2D_PIXFMT_1BPP (0<<SST_2D_SRC_FORMAT_SHIFT)
+#define SST_2D_SRC_COLORKEY_EX BIT(0)
+#define SST_2D_GO BIT(8)
+#define SST_2D_USECLIP1 BIT(23)
+
+/* 2D Registers */
+#define SST_2D_OFFSET 0x100000
+#define SST_2D_CLIP0MIN SST_2D_OFFSET+0x8
+#define SST_2D_CLIP0MAX SST_2D_OFFSET+0xC
+#define SST_2D_DSTBASEADDR SST_2D_OFFSET+0x10
+#define SST_2D_DSTFORMAT SST_2D_OFFSET+0x14
+#define SST_2D_SRCCOLORKEYMIN SST_2D_OFFSET+0x18
+#define SST_2D_SRCCOLORKEYMAX SST_2D_OFFSET+0x1c
+#define SST_2D_DSTCOLORKEYMIN SST_2D_OFFSET+0x20
+#define SST_2D_DSTCOLORKEYMAX SST_2D_OFFSET+0x24
+#define SST_2D_BRESERROR0 SST_2D_OFFSET+0x28
+#define SST_2D_BRESERROR1 SST_2D_OFFSET+0x2c
+#define SST_2D_ROP SST_2D_OFFSET+0x30
+#define SST_2D_SRCBASEADDR SST_2D_OFFSET+0x34
+#define SST_2D_COMMANDEXTRA SST_2D_OFFSET+0x38
+#define SST_2D_LINESTIPPLE SST_2D_OFFSET+0x3c
+#define SST_2D_LINESTYLE SST_2D_OFFSET+0x40
+#define SST_2D_CLIP1MIN SST_2D_OFFSET+0x4C
+#define SST_2D_CLIP1MAX SST_2D_OFFSET+0x50
+#define SST_2D_SRCFORMAT SST_2D_OFFSET+0x54
+#define SST_2D_SRCSIZE SST_2D_OFFSET+0x58
+#define SST_2D_SRCXY SST_2D_OFFSET+0x5C
+#define SST_2D_COLORBACK SST_2D_OFFSET+0x60
+#define SST_2D_COLORFORE SST_2D_OFFSET+0x64
+#define SST_2D_DSTSIZE SST_2D_OFFSET+0x68
+#define SST_2D_DSTXY SST_2D_OFFSET+0x6C
+#define SST_2D_COMMAND SST_2D_OFFSET+0x70
+#define SST_2D_LAUNCH SST_2D_OFFSET+0x80
+#define SST_2D_PATTERN0 SST_2D_OFFSET+0x100
+#define SST_2D_PATTERN1 SST_2D_OFFSET+0x104
+
+/* 3D Commands */
+#define SST_3D_NOP 0
+
+/* 3D Registers */
+#define SST_3D_OFFSET 0x200000
+#define SST_3D_STATUS SST_3D_OFFSET+0
+#define SST_3D_LFBMODE SST_3D_OFFSET+0x114
+#define SST_3D_COMMAND SST_3D_OFFSET+0x120
+#define SST_3D_SWAPBUFFERCMD SST_3D_OFFSET+0x128
+#define SST_3D_SLICTRL SST_3D_OFFSET+0x20C
+#define SST_3D_AACTRL SST_3D_OFFSET+0x210
+#define SST_3D_SWAPPENDING SST_3D_OFFSET+0x24C
+#define SST_3D_LEFTOVERLAYBUF SST_3D_OFFSET+0x250
+#define SST_3D_RIGHTOVERLAYBUF SST_3D_OFFSET+0x254
+#define SST_3D_FBISWAPHISTORY SST_3D_OFFSET+0x258
+
+/* NAPALM REGISTERS */
+#define CFG_PCI_COMMAND 4
+#define CFG_MEM0BASE 16
+#define CFG_MEM1BASE 20
+#define CFG_INIT_ENABLE 64
+#define CFG_PCI_DECODE 72
+#define CFG_VIDEO_CTRL0 128
+#define CFG_VIDEO_CTRL1 132
+#define CFG_VIDEO_CTRL2 136
+#define CFG_SLI_LFB_CTRL 140
+#define CFG_AA_ZBUFF_APERTURE 144
+#define CFG_AA_LFB_CTRL 148
+#define CFG_SLI_AA_MISC 172
+
+/* Pixel Formats */
+#define GR_PIXFMT_I_8 0x0001
+#define GR_PIXFMT_AI_88 0x0002
+#define GR_PIXFMT_RGB_565 0x0003
+#define GR_PIXFMT_ARGB_1555 0x0004
+#define GR_PIXFMT_ARGB_8888 0x0005
+#define GR_PIXFMT_AA_2_RGB_565 0x0006
+#define GR_PIXFMT_AA_2_ARGB_1555 0x0007
+#define GR_PIXFMT_AA_2_ARGB_8888 0x0008
+#define GR_PIXFMT_AA_4_RGB_565 0x0009
+#define GR_PIXFMT_AA_4_ARGB_1555 0x000a
+#define GR_PIXFMT_AA_4_ARGB_8888 0x000b
+
+/* pciInit0 */
+#define SST_PCI_STALL_ENABLE BIT(0)
+#define SST_PCI_LOWTHRESH_SHIFT 2
+#define SST_PCI_LOWTHRESH (0xF << SST_PCI_LOWTHRESH_SHIFT)
+#define SST_PCI_HARDCODE_BASE BIT(7)
+#define SST_PCI_READ_WS BIT(8)
+#define SST_PCI_WRITE_WS BIT(9)
+#define SST_PCI_DISABLE_IO BIT(11)
+#define SST_PCI_DISABLE_MEM BIT(12)
+#define SST_PCI_RETRY_INTERVAL_SHIFT 13
+#define SST_PCI_RETRY_INTERVAL (0x1F << SST_PCI_RETRY_INTERVAL_SHIFT)
+#define SST_PCI_INTERRUPT_ENABLE BIT(18)
+#define SST_PCI_TIMEOUT_ENABLE BIT(19)
+#define SST_PCI_FORCE_FB_HIGH BIT(26)
+
+#define SST_AA_CLK_INVERT BIT(20)
+#define SST_AA_CLK_DELAY_SHIFT 21
+#define SST_AA_CLK_DELAY (0xF<<SST_AA_CLK_DELAY_SHIFT)
+
+#define CFG_SWAP_ALGORITHM_VSYNC (0x00)
+#define CFG_SWAP_ALGORITHM_SYNCIN (0x01)
+#define CFG_SWAPBUFFER_ALGORITHM_SHIFT (25)
+
+/* CFG_INIT_ENABLE */
+#define CFG_UPDATE_MEMBASE_LSBS BIT(10)
+#define CFG_SNOOP_EN BIT(11)
+#define CFG_SNOOP_MEMBASE0_EN BIT(12)
+#define CFG_SNOOP_MEMBASE1_EN BIT(13)
+#define CFG_SNOOP_SLAVE BIT(14)
+#define CFG_SNOOP_MEMBASE0_SHIFT 15
+#define CFG_SNOOP_MEMBASE0 (0x3FF<<CFG_SNOOP_MEMBASE0_SHIFT)
+#define CFG_SWAP_ALGORITHM BIT(25)
+#define CFG_SWAP_MASTER BIT(26)
+#define CFG_SWAP_QUICK BIT(27)
+#define CFG_MULTI_FUNCTION_DEV BIT(28)
+#define CFG_LFB_RD_CACHE_DISABLE BIT(29)
+#define CFG_SNOOP_FBIINIT_WR_EN BIT(30)
+#define CFG_SNOOP_MEMBASE0_DECODE_SHIFT 10
+#define CFG_SNOOP_MEMBASE0_DECODE (0xF<<CFG_SNOOP_MEMBASE0_DECODE_SHIFT)
+#define CFG_SNOOP_MEMBASE1_DECODE_SHIFT 14
+#define CFG_SNOOP_MEMBASE1_DECODE (0xF<<CFG_SNOOP_MEMBASE1_DECODE_SHIFT)
+#define CFG_SNOOP_MEMBASE1_SHIFT 18
+#define CFG_SNOOP_MEMBASE1 (0x3FF<<CFG_SNOOP_MEMBASE1_SHIFT)
+
+/* CFG_VIDEO_CTRL0 */
+#define CFG_ENHANCED_VIDEO_EN BIT(0)
+#define CFG_ENHANCED_VIDEO_SLV BIT(1)
+#define CFG_VIDEO_TV_OUTPUT_EN BIT(2)
+#define CFG_VIDEO_LOCALMUX_SEL BIT(3)
+#define CFG_VIDEO_LOCALMUX_DESKTOP_PLUS_OVERLAY BIT(3)
+#define CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT 4
+#define CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT 6
+#define CFG_VIDEO_OTHERMUX_SEL_TRUE (0x3<<CFG_VIDEO_OTHERMUX_SEL_TRUE_SHIFT)
+#define CFG_VIDEO_OTHERMUX_SEL_FALSE (0x3<<CFG_VIDEO_OTHERMUX_SEL_FALSE_SHIFT)
+#define CFG_VIDEO_OTHERMUX_SEL_PIPE 0
+#define CFG_VIDEO_OTHERMUX_SEL_PIPE_PLUS_AAFIFO 1
+#define CFG_VIDEO_OTHERMUX_SEL_AAFIFO 2
+#define CFG_SLI_FETCH_COMPARE_INV BIT(8)
+#define CFG_SLI_CRT_COMPARE_INV BIT(9)
+#define CFG_SLI_AAFIFO_COMPARE_INV BIT(10)
+#define CFG_VIDPLL_SEL BIT(11)
+#define CFG_DIVIDE_VIDEO_SHIFT 12
+#define CFG_DIVIDE_VIDEO (0x7<<CFG_DIVIDE_VIDEO_SHIFT)
+#define CFG_DIVIDE_VIDEO_BY_1 (0x0<<CFG_DIVIDE_VIDEO_SHIFT)
+#define CFG_DIVIDE_VIDEO_BY_2 (0x1<<CFG_DIVIDE_VIDEO_SHIFT)
+#define CFG_DIVIDE_VIDEO_BY_4 (0x2<<CFG_DIVIDE_VIDEO_SHIFT)
+#define CFG_DIVIDE_VIDEO_BY_8 (0x3<<CFG_DIVIDE_VIDEO_SHIFT)
+#define CFG_DIVIDE_VIDEO_BY_16 (0x4<<CFG_DIVIDE_VIDEO_SHIFT)
+#define CFG_DIVIDE_VIDEO_BY_32 (0x5<<CFG_DIVIDE_VIDEO_SHIFT)
+#define CFG_ALWAYS_DRIVE_AA_BUS BIT(15)
+#define CFG_VSYNC_IN_DEL_SHIFT 16
+#define CFG_VSYNC_IN_DEL (0xF<<CFG_VSYNC_IN_DEL_SHIFT)
+#define CFG_DAC_VSYNC_TRISTATE BIT(24)
+#define CFG_DAC_HSYNC_TRISTATE BIT(25)
+
+/* CFG_VIDEO_CTRL1 */
+#define CFG_SLI_RENDERMASK_FETCH_SHIFT 0
+#define CFG_SLI_RENDERMASK_FETCH (0xFF<<CFG_SLI_RENDERMASK_FETCH_SHIFT)
+#define CFG_SLI_COMPAREMASK_FETCH_SHIFT 8
+#define CFG_SLI_COMPAREMASK_FETCH (0xFF<<CFG_SLI_COMPAREMASK_FETCH_SHIFT)
+#define CFG_SLI_RENDERMASK_CRT_SHIFT 16
+#define CFG_SLI_RENDERMASK_CRT (0xFF<<CFG_SLI_RENDERMASK_CRT_SHIFT)
+#define CFG_SLI_COMPAREMASK_CRT_SHIFT 24
+#define CFG_SLI_COMPAREMASK_CRT (0xFF<<CFG_SLI_COMPAREMASK_CRT_SHIFT)
+
+/* CFG_VIDEO_CTRL2 */
+#define CFG_SLI_RENDERMASK_AAFIFO_SHIFT 0
+#define CFG_SLI_RENDERMASK_AAFIFO (0xFF<<CFG_SLI_RENDERMASK_AAFIFO_SHIFT)
+#define CFG_SLI_COMPAREMASK_AAFIFO_SHIFT 8
+#define CFG_SLI_COMPAREMASK_AAFIFO (0xFF<<CFG_SLI_COMPAREMASK_AAFIFO_SHIFT)
+
+/* CFG_SLI_LFB_CTRL */
+#define CFG_SLI_LFB_RENDERMASK_SHIFT 0
+#define CFG_SLI_LFB_RENDERMASK (0xFF<<CFG_SLI_LFB_RENDERMASK_SHIFT)
+#define CFG_SLI_LFB_COMPAREMASK_SHIFT 8
+#define CFG_SLI_LFB_COMPAREMASK (0xFF<<CFG_SLI_LFB_COMPAREMASK_SHIFT)
+#define CFG_SLI_LFB_SCANMASK_SHIFT 16
+#define CFG_SLI_LFB_SCANMASK (0xFF<<CFG_SLI_LFB_SCANMASK_SHIFT)
+#define CFG_SLI_LFB_NUMCHIPS_LOG2_SHIFT 24
+#define CFG_SLI_LFB_NUMCHIPS_LOG2 (0x3<<CFG_SLI_LFB_NUMCHIPS_LOG2_SHIFT)
+#define CFG_SLI_LFB_CPU_WR_EN BIT(26)
+#define CFG_SLI_LFB_DPTCH_WR_EN BIT(27)
+#define CFG_SLI_RD_EN BIT(28)
+
+/* CFG_AA_ZBUFF_APERTURE */
+#define CFG_AA_DEPTH_BUFFER_BEG_SHIFT 0
+#define CFG_AA_DEPTH_BUFFER_BEG (0x7FFF<<CFG_AA_DEPTH_BUFFER_BEG_SHIFT)
+#define CFG_AA_DEPTH_BUFFER_END_SHIFT 16
+#define CFG_AA_DEPTH_BUFFER_END (0xFFFF<<CFG_AA_DEPTH_BUFFER_END_SHIFT)
+
+/* CFG_AA_LFB_CTRL */
+#define CFG_AA_BASEADDR_SHIFT 0
+#define CFG_AA_BASEADDR (0x3FFFFFF<<CFG_AA_BASEADDR_SHIFT)
+#define CFG_AA_LFB_CPU_WR_EN BIT(26)
+#define CFG_AA_LFB_DPTCH_WR_EN BIT(27)
+#define CFG_AA_LFB_RD_EN BIT(28)
+#define CFG_AA_LFB_RD_FORMAT_SHIFT 29
+#define CFG_AA_LFB_RD_FORMAT (0x3<<CFG_AA_LFB_RD_FORMAT_SHIFT)
+#define CFG_AA_LFB_RD_FORMAT_16BPP (0x0<<CFG_AA_LFB_RD_FORMAT_SHIFT)
+#define CFG_AA_LFB_RD_FORMAT_15BPP (0x1<<CFG_AA_LFB_RD_FORMAT_SHIFT)
+#define CFG_AA_LFB_RD_FORMAT_32BPP (0x2<<CFG_AA_LFB_RD_FORMAT_SHIFT)
+#define CFG_AA_LFB_RD_DIVIDE_BY_4 BIT(31)
+
+/* CFG_SLI_AA_MISC */
+#define CFG_VGA_VSYNC_OFFSET_SHIFT 0
+#define CFG_VGA_VSYNC_OFFSET (0x1ff<<CFG_VGA_VSYNC_OFFSET_SHIFT)
+#define CFG_VGA_VSYNC_OFFSET_PIXELS_SHIFT 0
+#define CFG_VGA_VSYNC_OFFSET_CHARS_SHIFT 3
+#define CFG_VGA_VSYNC_OFFSET_HXTRA_SHIFT 6
+#define CFG_HOTPLUG_SHIFT 9
+#define CFG_HOTPLUG_TRISTATE (0x0<<CFG_HOTPLUG_SHIFT)
+#define CFG_HOTPLUG_DRIVE0 (0x2<<CFG_HOTPLUG_SHIFT)
+#define CFG_HOTPLUG_DRIVE1 (0x3<<CFG_HOTPLUG_SHIFT)
+#define CFG_AA_LFB_RD_SLV_WAIT BIT(12)
+
+/* SLICTL_3D_CTRL */
+#define SLICTL_3D_RENDERMASK_SHIFT 0
+#define SLICTL_3D_RENDERMASK (0xFF<<SLICTL_3D_RENDERMASK_SHIFT)
+#define SLICTL_3D_COMPAREMASK_SHIFT 8
+#define SLICTL_3D_COMPAREMASK (0xFF<<SLICTL_3D_COMPAREMASK_SHIFT)
+#define SLICTL_3D_SCANMASK_SHIFT 16
+#define SLICTL_3D_SCANMASK (0xFF<<SLICTL_3D_SCANMASK_SHIFT)
+#define SLICTL_3D_NUMCHIPS_LOG2_SHIFT 24
+#define SLICTL_3D_NUMCHIPS_LOG2 (0x3<<SLICTL_3D_NUMCHIPS_LOG2_SHIFT)
+#define SLICTL_3D_EN BIT(26)
+
+#define SST_POWERDOWN_DAC BIT(8)
+
+#endif