/* ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. ** ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF ** THE UNITED STATES. ** ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED */ /* We need to provide the following functions: char * hwcGetErrorString(void); hwcInfo * hwcInit(FxU32 vID, FxU32 dID); FxBool hwcMapBoard(hwcBoardInfo *bInfo, FxU32 bAddrMask); FxBool hwcInitRegisters(hwcBoardInfo *bInfo); FxBool hwcAllocBuffers(hwcBoardInfo *bInfo, FxU32 nColBuffers, FxU32 nAuxBuffers); FxBool hwcInitFifo(hwcBoardInfo *bInfo); FxU32 hwcInitAGPFifo(hwcBoardInfo *bInfo); FxBool hwcInitVideo(hwcBoardInfo *bInfo, FxBool tiled, FxVideoTimingInfo *vidTiming, FxBool overlay); FxBool hwcRestoreVideo(hwcBoardInfo *bInfo); FxBool hwcCheckMemSize(hwcBoardInfo *bInfo, FxU32 xres, FxU32 yres, FxU32 nColBuffers, FxU32 nAuxBuffers, FxBool tiled); */ #include #include #include #include #include #include #include #include #include "lindri.h" static FxU32 fenceVar; #if defined(__i386__) #define P6FENCE asm("xchg %%eax, %0" : : "m" (fenceVar) : "eax"); #elif defined(__alpha__) #define P6FENCE asm volatile("mb" ::: "memory") #elif defined(__ia64__) #define P6FENCE asm volatile("mf.a" ::: "memory") #elif Error - need to define P6FENCE #endif #define MAXFIFOSIZE 0x40000 #define FIFOPAD 0x0000 #define AUXPAD 0x1000 #define HWC_LFB_STRIDE 0x2000UL #define HWC_TILED_BUFFER_BYTES 0x1000UL /* 128 Bytes x 32 lines */ #define HWC_TILED_BUFFER_Y_ALIGN 0x20000UL #define HWC_TILED_BUFFER_X_ADJUST 0x80UL static hwcInfo hInfo; static char errorString[1024]; static FxU32 calcBufferStride(hwcBoardInfo *bInfo, FxU32 xres, FxBool tiled); static FxU32 calcBufferSize(hwcBoardInfo *bInfo, FxU32 xres, FxU32 yres, FxBool tiled); static FxU32 calcBufferSizeInTiles(hwcBoardInfo *bInfo, FxU32 xres, FxU32 yres); static FxU32 calcBufferHeightInTiles(hwcBoardInfo *bInfo, FxU32 yres); static FxU32 hwcBufferLfbAddr(const hwcBoardInfo* bInfo, FxU32 physAddress); typedef struct envitem_t { char *env; char *val; struct envitem_t *next; } envitem; static envitem *first=0; static int envinit=0; DRIDef driInfo={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; void grDRIOpen(char *pFB, char *pRegs, 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, volatile int *fifoPtr, volatile int *fifoRead) { driInfo.pFB=pFB; driInfo.pRegs=pRegs; driInfo.deviceID=deviceID; driInfo.screenWidth=width; driInfo.screenHeight=height; driInfo.memory=mem; driInfo.cpp=cpp; driInfo.stride=stride; driInfo.fifoOffset=fifoOffset; driInfo.fifoSize = fifoSize; driInfo.fbOffset=fbOffset; driInfo.backOffset=backOffset; driInfo.depthOffset=depthOffset; driInfo.textureOffset=textureOffset; driInfo.textureSize=textureSize; driInfo.fifoPtr=(volatile int **)fifoPtr; driInfo.fifoRead=(volatile int **)fifoRead; } void grDRIPosition(int x, int y, int w, int h, int numClip, XF86DRIClipRectPtr pClip) { driInfo.x=x; driInfo.y=y; driInfo.w=w; driInfo.h=h; driInfo.numClip=numClip; driInfo.pClip=pClip; } static void loadEnvFile() { FILE *file; char data[128]; char *env, *val; envitem *item; unsigned int sawError=0; envitem *first=(envitem *)0; if (envinit) return; envinit=1; file=fopen("/etc/conf.3dfx/voodoo3", "r"); if (!file) return; while (1) { if (!fgets(data, 128, file)) return; if (*data=='#') continue; if (*data=='\n') continue; val=strchr(data, '='); if (!val) { if (sawError) { fprintf(stderr, "In config file /etc/conf.3dfx/voodoo3:\n"); sawError=1; } fprintf(stderr, "Malformed line: %s\n", data); continue; } *val=0; env=data; val++; item=malloc(sizeof(envitem)); item->env=malloc(strlen(env)+1); strcpy(item->env, env); item->val=malloc(strlen(val)+1); strcpy(item->val, val); item->next=first; first=item; } } static void deleteEnvData() { envitem *ptr, *next; ptr=first; while (ptr) { next=ptr->next; if (ptr->env) free(ptr->env); if (ptr->val) free(ptr->val); free(ptr); ptr=next; } first=0; envinit=0; } char * hwcGetErrorString() { #define FN_NAME "hwcGetErrorString" return errorString; #undef FN_NAME } /* hwcGetErrorString */ hwcInfo * hwcInit(FxU32 vID, FxU32 dID) { hInfo.nBoards = 0; errorString[0] = '\0'; if (!driInfo.pFB) return 0; if (dID!=driInfo.deviceID) return 0; hInfo.boardInfo[0].pciInfo.initialized = FXFALSE; hInfo.nBoards++; hInfo.boardInfo[0].boardNum = 0; hInfo.boardInfo[0].pciInfo.initialized = FXTRUE;; hInfo.boardInfo[0].pciInfo.vendorID = vID; hInfo.boardInfo[0].pciInfo.deviceID = dID; hInfo.boardInfo[0].h3Mem = driInfo.memory>>20; if (driInfo.cpp==3 || driInfo.cpp==4) { /* 24 or 32 bpp modes */ hInfo.boardInfo[0].h3pixelSize=4; } else { hInfo.boardInfo[0].h3pixelSize=2; } hInfo.boardInfo[0].h3nwaySli=1; if (hInfo.nBoards) { return &hInfo; } else { sprintf(errorString, "Can't find or access Banshee/V3 board\n"); return 0; } } extern int getpid(); FxBool hwcMapBoard(hwcBoardInfo *bInfo, FxU32 bAddrMask) { if (bInfo->pciInfo.initialized == FXFALSE) { sprintf(errorString, "hwcMapBoard: Called before hwcInit\n"); return FXFALSE; } bInfo->linearInfo.initialized = FXTRUE; bInfo->osNT = FXFALSE; bInfo->procHandle = getpid(); bInfo->linearInfo.linearAddress[0]=(AnyPtr)driInfo.pRegs; bInfo->linearInfo.linearAddress[1]=(AnyPtr)driInfo.pFB; return FXTRUE; } FxBool hwcUnmapBoard(hwcBoardInfo *bInfo) { return FXTRUE; } FxBool hwcInitRegisters(hwcBoardInfo *bInfo) { int dramInit1; if (bInfo->linearInfo.initialized == FXFALSE) { printf(errorString, "hwcInitRegisters Called before hwcMapBoard\n"); return FXFALSE; } bInfo->regInfo.initialized = FXTRUE; bInfo->regInfo.ioMemBase = bInfo->linearInfo.linearAddress[0] + SST_IO_OFFSET; bInfo->regInfo.cmdAGPBase = bInfo->linearInfo.linearAddress[0] + SST_CMDAGP_OFFSET; bInfo->regInfo.waxBase = bInfo->linearInfo.linearAddress[0] + SST_2D_OFFSET; bInfo->regInfo.sstBase = bInfo->linearInfo.linearAddress[0] + SST_3D_OFFSET; bInfo->regInfo.lfbBase = bInfo->linearInfo.linearAddress[0] + SST_LFB_OFFSET; bInfo->regInfo.rawLfbBase = bInfo->linearInfo.linearAddress[1]; bInfo->regInfo.ioPortBase = (FxU16) bInfo->pciInfo.pciBaseAddr[2] & ~0x1; /* Figure out if it's SDRAM */ HWC_IO_LOAD(bInfo->regInfo, dramInit1, dramInit1); dramInit1 &= SST_MCTL_TYPE_SDRAM; if ( dramInit1 & SST_MCTL_TYPE_SDRAM ) bInfo->sdRAM = FXTRUE; else bInfo->sdRAM = FXFALSE; { FxU32 pciInit0, pciCommandReg = BIT(0) | /* enable i/o decode */ BIT(1); /* enable memory decode */ /* Enable PCI memory and I/O decode */ pciSetConfigData(PCI_COMMAND, bInfo->deviceNum, &pciCommandReg); HWC_IO_LOAD(bInfo->regInfo, pciInit0, pciInit0); pciInit0 |= SST_PCI_READ_WS | SST_PCI_WRITE_WS; HWC_IO_STORE(bInfo->regInfo, pciInit0, pciInit0); } /* Determine the number of chips on the board XXX */ bInfo->pciInfo.numChips=1; return FXTRUE; } /* How the hw treats lfb accesses are dependent on the 'type' of * memory (tiled/linear) that the color/aux buffers are in. We * pre-compute the actual lfb address here while we know about the * memory space and if we adjusted the page alignment above. * * NB: If we are in tiled mode then the fact that we align the color * buffers on page boundaries means that the y offset of the buffers * may not actually be on a boundary for the tile addressing scheme. * The 'rounding' done to HWC_TILED_BUFFER_Y_ALIGN adjust for this. * * NB: The memory optimization of aligning color buffers on even page * boundaries will cause the tiled lfb access to be off by a page so * we add in the width of a page (HWC_TILED_BUFFER_X_ADJUST) here. */ static FxU32 hwcBufferLfbAddr(const hwcBoardInfo *bInfo, FxU32 physAddress) { FxU32 retVal = 0x00UL; FxU32 tileAddress; FxU32 tileNumber; FxU32 tileOffset; FxU32 tileXOffset; FxU32 tileScanline; FxU32 tileRow; FxU32 lfbAddress; /* * This is the tile aperture stride. It should be * a power of two between 1k and 16k. */ FxU32 lfbBufferStride = bInfo->buffInfo.bufLfbStride; FxU32 lfbYOffset; if (bInfo->vidInfo.tiled) { GDBG_INFO(80, "\tphysAddress: 0x%08lx\n",physAddress); /* Compute address in tile space */ tileAddress = physAddress - bInfo->primaryOffset; GDBG_INFO(80, "\ttileAddress: 0x%08lx\n",tileAddress); /* Compute tile number we're in (each tile is 4K bytes) */ tileNumber = tileAddress >> 12; GDBG_INFO(80, "\ttileNumber: 0x%08lx (%d)\n",tileNumber,tileNumber); /* Compute base tile row we're in */ tileRow = tileNumber / bInfo->buffInfo.bufStrideInTiles; GDBG_INFO(80, "\ttileRow: %d (stride = %d)\n",tileNumber,bInfo->buffInfo.bufStrideInTiles); /* Compute offset within the tile */ tileOffset = tileAddress - (tileNumber << 12); GDBG_INFO(80, "\ttileOffset: 0x%08lx\n",tileOffset); /* Compute scanline within the tile */ tileScanline = tileOffset >> 7; GDBG_INFO(80, "\ttileScanline: 0x%08lx\n",tileScanline); /* Compute tile X offset within the row */ tileXOffset = tileNumber - (tileRow * bInfo->buffInfo.bufStrideInTiles); GDBG_INFO(80, "\ttileXOffset: %d\n",tileXOffset); /* Compute Y offset in LFB space */ lfbYOffset = ((tileRow * 32 + tileScanline) << (bInfo->h3nwaySli >> 1)); /* Compute LFB address of tile start */ lfbAddress = bInfo->primaryOffset + lfbYOffset * lfbBufferStride + tileXOffset * 128; GDBG_INFO(80, "\tlfbAddress: %08lx\n", lfbAddress); retVal = lfbAddress; } else { retVal = physAddress; } return retVal; } static FxU32 calculateLfbStride(FxU32 screenWidth) { #if 1 int TileAperturePitch; for (TileAperturePitch = 1024; (TileAperturePitch < (16 << 10)) && (TileAperturePitch < screenWidth); TileAperturePitch <<= 1); return(TileAperturePitch); #else return(0x1000); #endif } FxBool hwcAllocBuffers(hwcBoardInfo *bInfo, FxU32 nColBuffers, FxU32 nAuxBuffers) { #define FN_NAME "hwcAllocBuffers" FxU32 bufStride, bufSize; if (bInfo->vidInfo.initialized == FXFALSE) { sprintf(errorString, "%s: Called before video initialization\n", FN_NAME); return FXFALSE; } GDBG_INFO(80, "%s(0x%x, 0x%x, 0x%x)\n", FN_NAME, bInfo, nColBuffers, nAuxBuffers); /* I've decided on > 2 instead of == 3 because we may support more than 3 buffers in the future, and want 4 to set the triple-buffering bit in dramInit1, also */ bInfo->vidInfo.tripleBuffering = (nColBuffers > 2); bInfo->vidInfo.stride = bufStride = calcBufferStride(bInfo, driInfo.screenWidth, bInfo->vidInfo.tiled); /* We want to place the FIFO after the tram but before the color buffers with some pad */ bufSize = calcBufferSize(bInfo, driInfo.screenWidth, driInfo.screenHeight, bInfo->vidInfo.tiled); bInfo->buffInfo.bufStride = bufStride; bInfo->buffInfo.bufSize = bufSize; bInfo->buffInfo.bufLfbStride = calculateLfbStride(bufStride); if (bInfo->vidInfo.tiled) { bInfo->buffInfo.bufStrideInTiles = (bufStride >> 7); bInfo->buffInfo.bufSizeInTiles = calcBufferSizeInTiles(bInfo, driInfo.screenWidth, driInfo.screenHeight); bInfo->buffInfo.bufHeightInTiles = calcBufferHeightInTiles(bInfo, driInfo.screenHeight); } bInfo->buffInfo.initialized = FXTRUE; bInfo->buffInfo.nColBuffers = nColBuffers; bInfo->buffInfo.nAuxBuffers = nAuxBuffers; bInfo->fbOffset = driInfo.fbOffset; bInfo->fifoInfo.fifoStart = driInfo.fifoOffset; bInfo->fifoInfo.fifoLength = driInfo.fifoSize; bInfo->tramOffset = driInfo.textureOffset; bInfo->tramSize = driInfo.textureSize; /* !!! This needs to be reworked to support second col and aux buffers */ bInfo->primaryOffset = driInfo.backOffset; bInfo->buffInfo.colBuffStart0[0] = driInfo.fbOffset; bInfo->buffInfo.colBuffEnd0[0] = driInfo.fbOffset + driInfo.screenHeight*driInfo.stride; bInfo->buffInfo.colBuffStart0[1] = driInfo.backOffset; bInfo->buffInfo.colBuffEnd0[1] = driInfo.backOffset+bufSize; bInfo->buffInfo.auxBuffStart0 = driInfo.depthOffset; bInfo->buffInfo.auxBuffEnd0 = driInfo.depthOffset+bufSize; bInfo->buffInfo.lfbBuffAddr0[0] = bInfo->buffInfo.colBuffStart0[0]; bInfo->buffInfo.lfbBuffAddr0[1] = bInfo->buffInfo.colBuffStart0[1]; bInfo->buffInfo.lfbBuffAddr0[2] = hwcBufferLfbAddr(bInfo, bInfo->buffInfo.auxBuffStart0); GDBG_INFO(80, "%s: Board Info:\n", FN_NAME); GDBG_INFO(80, "\thdc: 0x%x\n", bInfo->hdc); GDBG_INFO(80, "\textContextID: 0x%x\n", bInfo->extContextID); GDBG_INFO(80, "\tdevRev: 0x%x\n", bInfo->devRev); GDBG_INFO(80, "\tfbOffset: 0x%x\n", bInfo->fbOffset); GDBG_INFO(80, "\th3Rev: 0x%x\n", bInfo->h3Rev); GDBG_INFO(80, "\th3Mem: 0x%x\n", bInfo->h3Mem); GDBG_INFO(80, "\tboardNum: 0x%x\n", bInfo->boardNum); GDBG_INFO(80, "\tdeviceNum: 0x%x\n", bInfo->deviceNum); GDBG_INFO(80, "%s: Buffer Info:\n", FN_NAME); GDBG_INFO(80, "\tbufSize: 0x%x\n", bInfo->buffInfo.bufSize); GDBG_INFO(80, "\tbufSizeInTiles: 0x%x\n", bInfo->buffInfo.bufSizeInTiles); GDBG_INFO(80, "\tbufStride: 0x%x\n", bInfo->buffInfo.bufStride); GDBG_INFO(80, "\tbufStrideInTiles:0x%x\n", bInfo->buffInfo.bufStrideInTiles); GDBG_INFO(80, "\tbufHeightInTiles:0x%x\n", bInfo->buffInfo.bufHeightInTiles); GDBG_INFO(80, "\tbufLfbStride :0x%x\n", bInfo->buffInfo.bufLfbStride); GDBG_INFO(80, "\tnColBuffers: 0x%x\n", bInfo->buffInfo.nColBuffers); GDBG_INFO(80, "\tcolBuffStart0[0]: 0x%x\n", bInfo->buffInfo.colBuffStart0[0]); GDBG_INFO(80, "\tcolBuffEnd0[0]: 0x%x\n", bInfo->buffInfo.colBuffEnd0[0]); GDBG_INFO(80, "\tcolBuffStart0[1]: 0x%x\n", bInfo->buffInfo.colBuffStart0[1]); GDBG_INFO(80, "\tcolBuffEnd0[1]: 0x%x\n", bInfo->buffInfo.colBuffEnd0[1]); GDBG_INFO(80, "\tnAuxBuffers: 0x%x\n", bInfo->buffInfo.nAuxBuffers); GDBG_INFO(80, "\tauxBuffStart0: 0x%x\n", bInfo->buffInfo.auxBuffStart0); GDBG_INFO(80, "\tauxBuffEnd0: 0x%x\n", bInfo->buffInfo.auxBuffEnd0); GDBG_INFO(80, "\ttramOffset: 0x%x\n", bInfo->tramOffset); GDBG_INFO(80, "\ttramSize: 0x%x\n", bInfo->tramSize); GDBG_INFO(80, "\tlfbBuffAddr0[0] 0x%x\n", bInfo->buffInfo.lfbBuffAddr0[0]); GDBG_INFO(80, "\tlfbBuffAddr0[1] 0x%x\n", bInfo->buffInfo.lfbBuffAddr0[1]); GDBG_INFO(80, "\tlfbBuffAddr0[2] 0x%x\n", bInfo->buffInfo.lfbBuffAddr0[2]); GDBG_INFO(80, "%s: FIFO Info:\n", FN_NAME); GDBG_INFO(80, "\tfifoStart: 0x%x\n", bInfo->fifoInfo.fifoStart); GDBG_INFO(80, "\tfifoLength: 0x%x\n", bInfo->fifoInfo.fifoLength); return FXTRUE; #undef FN_NAME } /* hwcAllocBuffers */ FxBool hwcInitFifo(hwcBoardInfo *bInfo, FxBool enableHoleCounting) { #define FN_NAME "hwcInitFifo" if (bInfo->regInfo.initialized == FXFALSE) { sprintf(errorString, "%s: Called before hwcMapBoard\n", FN_NAME); return FXFALSE; } if (bInfo->buffInfo.initialized == FXFALSE) { sprintf(errorString, "%s: Called before hwcInitBuffers\n", FN_NAME); return FXFALSE; } #if 0 driInfo.holeCounting=enableHoleCounting; hwcInitFifoRegs(enableHoleCounting); #endif GDBG_INFO(80 ,"%s: CMD FIFO placed at physical addr 0x%x size 0x%0x\n", FN_NAME, driInfo.fifoOffset, driInfo.fifoSize); return FXTRUE; #undef FN_NAME } /* hwcInitFifo */ FxBool hwcInitVideo(hwcBoardInfo *bInfo, FxBool tiled, FxVideoTimingInfo *vidTiming, FxU32 pixFmt, FxBool overlay) { FxU32 stride, dramInit1, miscInit0; stride= (tiled) ? bInfo->buffInfo.bufStrideInTiles : bInfo->vidInfo.stride; /* Video pixel buffer threshold */ { FxU32 vidPixelBufThold; FxU32 thold = 32; if (getenv("SSTVB_PIXTHOLD")) { thold = atoi(getenv("SSTVB_PIXTHOLD")); } thold &= 0x3f; vidPixelBufThold = (thold | (thold << 6) | (thold << 12)); HWC_IO_STORE(bInfo->regInfo, vidPixelBufThold, vidPixelBufThold); } /* Check to see if the screen and overlay dimensions match. * There are two cases that can happen in reality. * * scrXXX > appXXX: This is a 'real' case, and the overlay dimension * needs to mag scaled so that it fits the requested size. * * (scrXXX == appXXX) && (ovlXXX != scrXXX): This is a somewhat artificial * case where someone left the overlay set to some value, and these did * not get reset in the setVideoMode processing. (For example, if the user is * running an application which bus masters data directly to our video overlay * when launching a glide application). In this case we need to fiddle w/ the * overlay dimension so that it matches the requested resolution. * * (scrXXX < appXXX): If setVideoMode is actually working correctly, this cannot * happen because that code has to know that we can't do min scaling. */ /* Get miscInit0 for y-sub */ HWC_IO_LOAD(bInfo->regInfo, miscInit0, miscInit0); /* Clear out relavent bits */ miscInit0 &= ~SST_YORIGIN_TOP; miscInit0 |= ((driInfo.screenHeight - 1) << SST_YORIGIN_TOP_SHIFT); HWC_IO_STORE(bInfo->regInfo, miscInit0, miscInit0); /* Set up dramInit1 for triple or double buffering */ HWC_IO_LOAD(bInfo->regInfo, dramInit1, dramInit1); if (bInfo->vidInfo.tripleBuffering) dramInit1 |= SST_TRIPLE_BUFFER_EN; else dramInit1 &= ~SST_TRIPLE_BUFFER_EN; HWC_IO_STORE(bInfo->regInfo, dramInit1, dramInit1); HWC_IO_STORE(bInfo->regInfo, vidMaxRGBDelta, 0x100810); return FXTRUE; } FxBool hwcRestoreVideo(hwcBoardInfo *bInfo) { return FXTRUE; } static FxU32 calcBufferStride(hwcBoardInfo *bInfo, FxU32 xres, FxBool tiled) { FxU32 strideInTiles; FxU32 shift = (bInfo->h3pixelSize>>1); if (tiled == FXTRUE) { /* Calculate tile width stuff */ strideInTiles = (xres << shift) >> 7; if ((xres << shift) & (HWC_TILE_WIDTH - 1)) strideInTiles++; return (strideInTiles * HWC_TILE_WIDTH); } else { return (xres << shift); } } /* calcBufferStride */ static FxU32 calcBufferHeightInTiles(hwcBoardInfo *bInfo, FxU32 yres) { FxU32 heightInTiles; /* Height of buffer in tiles */ yres = yres >> (bInfo->h3nwaySli>>1); /* Calculate tile height stuff */ heightInTiles = yres >> 5; if (yres & (HWC_TILE_HEIGHT - 1)) heightInTiles++; return heightInTiles; } /* calcBufferHeightInTiles */ static FxU32 calcBufferSizeInTiles(hwcBoardInfo *bInfo, FxU32 xres, FxU32 yres) { FxU32 bufSizeInTiles; /* Size of buffer in tiles */ bufSizeInTiles = calcBufferHeightInTiles(bInfo, yres) * (calcBufferStride(bInfo, xres, FXTRUE) >> 7); return bufSizeInTiles; } /* calcBufferSizeInTiles */ static FxU32 calcBufferSize(hwcBoardInfo *bInfo, FxU32 xres, FxU32 yres, FxBool tiled) { FxU32 stride, height, bufSize; /* Size of buffer in bytes */ FxU32 shift = (bInfo->h3pixelSize>>1); if (tiled) { stride = calcBufferStride(bInfo, xres, tiled); height = HWC_TILE_HEIGHT * calcBufferHeightInTiles(bInfo, yres); } else { stride = xres << shift; height = yres >> (bInfo->h3nwaySli>>1); } bufSize = stride * height; return bufSize; } /* calcBufferSize */ FxBool hwcCheckMemSize(hwcBoardInfo *bInfo, FxU32 xres, FxU32 yres, FxU32 nColBuffers, FxU32 nAuxBuffers, FxBool tiled) { #define FN_NAME "hwcCheckMemSize" FxU32 bufSize, totSize; bufSize = calcBufferSize(bInfo, xres, yres, tiled); totSize = (nColBuffers + nAuxBuffers) * bufSize; if (totSize < ((bInfo->h3Mem << 20) - 0x200000)) /* Need 2M for texture */ return FXTRUE; else return FXFALSE; #undef FN_NAME } /* hwcCheckMemSize */ FxU32 hwcInitAGPFifo(hwcBoardInfo *bInfo, FxBool enableHoleCounting) { return hwcInitFifo(bInfo, enableHoleCounting); } #define RED_SHIFT 16 #define GREEN_SHIFT 8 #define BLUE_SHIFT 0 FxBool hwcGammaTable(hwcBoardInfo *bInfo, FxU32 nEntries, FxU32 *r, FxU32 *g, FxU32 *b) { /* We don't allow them to store the gamma table, because X controls it */ return FXTRUE; #if 0 #define FN_NAME "hwcGammaTable" FxU32 gRamp[256]; FxU32 i; FxU32 dacBase; /* Load the table into the Display driver as above */ for (i = 0; i < nEntries; i++) { gRamp[i] = ((r[i] & 0xff) << RED_SHIFT) | ((g[i] & 0xff) << GREEN_SHIFT) | ((b[i] & 0xff) << BLUE_SHIFT); } dacBase = 0; for (i = 0; i < nEntries; i++) { HWC_IO_STORE( bInfo->regInfo, dacAddr, dacBase + i); P6FENCE; HWC_IO_STORE( bInfo->regInfo, dacData, gRamp[i]); P6FENCE; } return FXTRUE; #undef FN_NAME #endif } /* hwcGammaTable */ FxBool hwcGetGammaTable(hwcBoardInfo *bInfo, FxU32 nEntries, FxU32 *r, FxU32 *g, FxU32 *b) { #define FN_NAME "hwcGetGammaTable" FxU32 i; FxU32 vidProcCfg; FxU32 dacBase; FxU32 dacAddr ; FxU32 dacData ; /* * AJB- Don't believe the hype. Although we can do this * ourselves on Win9x/DOS, it's actually a piece of cake * to call the GDI Gamma ramp interface. This non-GDIish * implementation is here because it is faster than * calling the GDI function (which thunks to the display * driver). */ HWC_IO_LOAD( bInfo->regInfo, vidProcCfg, vidProcCfg); /* Determine which set of CLUT entries are selected */ if (vidProcCfg & SST_OVERLAY_CLUT_SELECT) dacBase = 256; else dacBase = 0; /* Print out some useful info RE the vidProcCfg register */ GDBG_INFO(80, "%s: vidProcCFG(SST_OVERLAY_CLUT_SELECT) = %d\n", FN_NAME, (vidProcCfg & SST_OVERLAY_CLUT_SELECT) ? 1 : 0); GDBG_INFO(80, "%s: vidProcCFG(SST_OVERLAY_EN) = %d\n", FN_NAME, (vidProcCfg & SST_OVERLAY_EN) ? 1 : 0); GDBG_INFO(80, "%s: vidProcCFG(SST_OVERLAY_CLUT_BYPASS) = %d\n", FN_NAME, (vidProcCfg & SST_OVERLAY_CLUT_BYPASS) ? 1 : 0); for (i = 0; i < nEntries; i++) { int repeat = 100 ; do { HWC_IO_STORE(bInfo->regInfo, dacAddr, dacBase + i); P6FENCE; HWC_IO_LOAD(bInfo->regInfo, dacAddr, dacAddr); P6FENCE; HWC_IO_LOAD(bInfo->regInfo, dacData, dacData); P6FENCE; } while (--repeat && (dacAddr != dacBase + i)) ; if (!repeat) { GDBG_INFO(0, "%s: Error Reading DacData [%d, %x]. DacBase = %d\n", FN_NAME, i, dacData, dacBase); } r[i] = (dacData >> RED_SHIFT) & 0xFF ; g[i] = (dacData >> GREEN_SHIFT) & 0xFF ; b[i] = (dacData >> BLUE_SHIFT) & 0xFF ; } return FXTRUE; #undef FN_NAME } /* hwcGetGammaTable */ FxBool hwcGammaRGB(hwcBoardInfo *bInfo, float gammaR, float gammaG, float gammaB) { /* We don't allow glide to set the gamma as X controls it */ return FXTRUE; #if 0 #define FN_NAME "hwcGammaRGB" FxU32 grRamp[256], ggRamp[256], gbRamp[256]; int i; GDBG_INFO(80, FN_NAME "(0x%x, %1.2f, %1.2f, %1.2f)\n", bInfo, gammaR, gammaG, gammaB); /* ** NB: The system eventually devised by Bob and Ken *may* require ** separate R, G, and B vectors. */ for (i = 0; i < 256; i++) { grRamp[i] = (FxU32)((pow(i/255.0F, 1.0F/gammaR)) * 255.0F + 0.5F); ggRamp[i] = (FxU32)((pow(i/255.0F, 1.0F/gammaG)) * 255.0F + 0.5F); gbRamp[i] = (FxU32)((pow(i/255.0F, 1.0F/gammaB)) * 255.0F + 0.5F); } hwcGammaTable(bInfo, 256, grRamp, ggRamp, gbRamp); /* ** Now that we have a gamma table, we can give it to the driver via ** a call to ExtEscape() when that is defined..... */ return FXFALSE; #undef FN_NAME #endif } /* hwcGammaRGB */ #define M 1 #define K 1 FxBool hwcSetGrxClock(hwcBoardInfo *bInfo, FxU32 speedInMHz) { #define FN_NAME "hwcSetGrxClock" FxU32 pllCtrl1, dramInit0 = 0xc17ae29, dramInit1 = 0x26c031, n, m = 1; n = (FxU32) ((speedInMHz - 4.76f)/2.38f); pllCtrl1 = (K << SST_PLL_K_SHIFT) | (m << SST_PLL_M_SHIFT) | (n << SST_PLL_N_SHIFT); GDBG_INFO(80, "%s: Setting Graphics Clock to %d\n", FN_NAME, speedInMHz); HWC_IO_STORE( bInfo->regInfo, dramInit0, dramInit0); HWC_IO_STORE( bInfo->regInfo, dramInit1, dramInit1); HWC_IO_STORE( bInfo->regInfo, pllCtrl1, pllCtrl1); return FXTRUE; #undef FN_NAME } /* hwcSetGrxClock */ FxBool hwcSetMemClock(hwcBoardInfo *bInfo, FxU32 speedInMHz) { #define FN_NAME "hwcSetMemClock" return FXFALSE; #undef FN_NAME } /* hwcSetMemClock */ char * hwcGetenv(char *a) { envitem *ptr; char *result; result=getenv(a); if (result) return result; if (!envinit) loadEnvFile(); ptr=first; while (ptr) { if (!strcmp(ptr->env, a)) return ptr->val; ptr=ptr->next; } return 0; } FxBool hwcResolutionSupported(hwcBoardInfo *bInfo, GrScreenResolution_t res, GrScreenRefresh_t ref) { #define FN_NAME "hwcResolutionSupported" /* For now we're just going to retur TRUE. We should check with vmode extension to see if the requested size is available */ return FXTRUE; #undef FN_NAME } /* hwcResolutionSupported */ /* This two routines hwcSLIRead{Enable,Disable} are currently NOPs XXX */ void hwcSLIReadEnable(hwcBoardInfo *bInfo) { #if 0 FxU32 cfgSliLfbCtrl; FxU32 cfgAALfbCtrl; FxU32 chipNumber; if(GETENV("FX_GLIDE_A0_READ_ABORT")) { if(bInfo->h3nwaySli > 1) { for(chipNumber = 0; chipNumber < bInfo->pciInfo.numChips; chipNumber++) { /* Turn on SLI Read */ cfgSliLfbCtrl = hwcReadConfigRegister(bInfo, chipNumber, offsetof(SstPCIConfigRegs, cfgSliLfbCtrl)); cfgSliLfbCtrl |= (SST_SLI_LFB_READ_ENABLE); hwcWriteConfigRegister(bInfo, chipNumber, offsetof(SstPCIConfigRegs, cfgSliLfbCtrl), cfgSliLfbCtrl); /* Turn off AA read if it is not supposed to be enabled */ if(bInfo->h3pixelSample < 2) { cfgAALfbCtrl = hwcReadConfigRegister(bInfo, chipNumber, offsetof(SstPCIConfigRegs, cfgAALfbCtrl)); cfgAALfbCtrl &= ~(SST_AA_LFB_READ_ENABLE); hwcWriteConfigRegister(bInfo, chipNumber, offsetof(SstPCIConfigRegs, cfgAALfbCtrl), cfgAALfbCtrl); } } } } #endif } void hwcSLIReadDisable(hwcBoardInfo *bInfo) { #if 0 FxU32 cfgSliLfbCtrl; FxU32 cfgAALfbCtrl; FxU32 chipNumber; if(GETENV("FX_GLIDE_A0_READ_ABORT")) { if(bInfo->h3nwaySli > 1) { for(chipNumber = 0; chipNumber < bInfo->pciInfo.numChips; chipNumber++) { /* Turn off SLI Read */ cfgSliLfbCtrl = hwcReadConfigRegister(bInfo, chipNumber, offsetof(SstPCIConfigRegs, cfgSliLfbCtrl)); cfgSliLfbCtrl &= ~(SST_SLI_LFB_READ_ENABLE); hwcWriteConfigRegister(bInfo, chipNumber, offsetof(SstPCIConfigRegs, cfgSliLfbCtrl), cfgSliLfbCtrl); /* Turn on AA Read */ cfgAALfbCtrl = hwcReadConfigRegister(bInfo, chipNumber, offsetof(SstPCIConfigRegs, cfgAALfbCtrl)); cfgAALfbCtrl |= (SST_AA_LFB_READ_ENABLE); hwcWriteConfigRegister(bInfo, chipNumber, offsetof(SstPCIConfigRegs, cfgAALfbCtrl), cfgAALfbCtrl); } } } #endif } #include /*------------------------------------------------------------------- Function: tlKbHit Date: 2/28 Implementor(s): jdt Library: test library Description: Returns true if there are pending characters in the input queue Arguments: none Return: nonzero if keys in queue -------------------------------------------------------------------*/ int hwcKbHit( void ) { return lin_kbhit(); } char hwcGetCH( void ) { return lin_getch(); } void grDRIImportFifo(FxU32 fifoPtr, FxU32 fifoRead) { _grImportFifo(fifoPtr, fifoRead); } void grDRIInvalidateAll() { _grInvalidateAll(); } void grDRIResetSAREA() { _grExportFifo(driInfo.fifoPtr, driInfo.fifoRead); }