diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:55 +0000 |
commit | c4dd1bf20f2bae6d34db059ae47f053012d8a822 (patch) | |
tree | 99a443cdf17b0b7a89c609ab20359cfc507e0035 |
Initial revisionXORG-STABLE
-rw-r--r-- | man/tdfx.man | 30 | ||||
-rw-r--r-- | src/tdfx.h | 301 | ||||
-rw-r--r-- | src/tdfx_accel.c | 933 | ||||
-rw-r--r-- | src/tdfx_dga.c | 210 | ||||
-rw-r--r-- | src/tdfx_dri.c | 658 | ||||
-rw-r--r-- | src/tdfx_dri.h | 28 | ||||
-rw-r--r-- | src/tdfx_dripriv.h | 24 | ||||
-rw-r--r-- | src/tdfx_driver.c | 2496 | ||||
-rw-r--r-- | src/tdfx_hwcurs.c | 153 | ||||
-rw-r--r-- | src/tdfx_io.c | 120 | ||||
-rw-r--r-- | src/tdfx_priv.c | 358 | ||||
-rw-r--r-- | src/tdfx_priv.h | 423 | ||||
-rw-r--r-- | src/tdfx_sli.c | 769 | ||||
-rw-r--r-- | src/tdfx_video.c | 1474 | ||||
-rw-r--r-- | src/tdfxdefs.h | 386 |
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 |