Files
glide/glide2x/cvg/init/sst1init.c
koolsmoky c9e2c802f9 pragma directives for win32
removed detritus
2005-04-25 22:08:48 +00:00

1339 lines
50 KiB
C

/*-*-c++-*-*/
/*
** 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 A
** 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
**
**
** $Revision$
** $Date$
**
*/
/*
** Initialization code for SST-1 board.
**
** NOTE: This code must compiled with optimizations DISABLED!!
**
** The following environment variables can optionally be used to alter
** functionality (A value of X is a "don't care"):
**
** Variable Value Description
** -------- ----- -----------
** SSTV2_ARCADE X Allow special configs for arcade use
** SSTV2_ALLOC_AUX {0,1} Number of aux. buffers to allocate
** SSTV2_ALLOC_COLOR {2,3} Number of color buffers to allocate
** SSTV2_BACKPORCH hex Specify value of backPorch video register
** SSTV2_BOARDS val Specify number of SST-1 boards in system
** SSTV2_CMDFIFO_DIRECT X Enable Direct Execution of CMDFIFO
** SSTV2_CMDFIFO_NOHOLES X Disable hole counting feature in CMDFIFO
** SSTV2_DEBUGDAC X Print out debug information for DAC
** reads and writes
** SSTV2_DEVICEID X Specify the device ID value passed to
** the PCI library
** SSTV2_DIMENSIONS hex Specify value of videoDimensions register
** SSTV2_FASTMEM_RAS_READS X Allow fast ras reads
** SSTV2_FASTPCIRD X Enable fast PCI reads
** SSTV2_FBICFG hex Specify FBI configuration strapping bits
** SSTV2_FBI_MEMSIZE val Specify amount of frame buffer memory
** SSTV2_FT_CLKDEL hex Fbi-to-Trex clock delay value
** SSTV2_GAMMA float Floating point value for gamma correction
** SSTV2_GRXCLK val 16 <= Frequency < 80 (50 is default)
** SSTV2_HSYNC hex Specify value of hSync video register
** SSTV2_IGNORE_CLKDELAYS X Ignore calls to sst1InitSetClkDelays()
** SSTV2_IGNORE_IDLE X Ignore calls to sst1InitIdle*()
** SSTV2_IGNORE_INIT_GAMMA X Bypass sst1InitGamma call and return
** SSTV2_IGNORE_INIT_REGISTERS X Bypass sst1InitRegisters call and return
** SSTV2_IGNORE_INIT_VIDEO X Bypass sst1InitVideo call and return
** SSTV2_INITDEBUG X Enable debug output
** SSTV2_INITDEBUG_FILE file File to direct all debug output
** SSTV2_MEMFIFO 0 Disable FBI Memory FIFO
** SSTV2_MEMFIFO 1 Enable FBI Memory FIFO
** SSTV2_MEMFIFO_ENTRIES hex Set number of entries in memory fifo
** SSTV2_MEMFIFO_HWM hex Set memory fifo high water mark
** SSTV2_MEMFIFO_LFB {0,1} Specify LFB writes through Memory FIFO
** SSTV2_MEMFIFO_LWM hex Set memory fifo low water mark
** SSTV2_MEMFIFO_TEX {0,1} Specify Texture writes through Mem FIFO
** SSTV2_MEMOFFSET hex Specify value of memoffset video register
** SSTV2_NOCHECKHANG X Do not Check for FBI Hangs for texturing
** SSTV2_NODEVICEINFO X Ignore calls to sst1InitFillDeviceInfo()
** SSTV2_NOSHUTDOWN X Do not turn off monitor refresh on call
** to sst1InitShutdown()
** SSTV2_NUM_TMUS {1,2,3} Specify number of TMUs detected
** SSTV2_PCIFIFO_LWM hex Set pci fifo low water mark
** SSTV2_PFT_CLKDEL hex Preliminary Fbi-to-Trex clock delay value
** SSTV2_PTF0_CLKDEL hex Prelim TMU2Fbi clock delay value (TMU #0)
** SSTV2_PTF1_CLKDEL hex Prelim TMU2Fbi clock delay value (TMU #1)
** SSTV2_PTF2_CLKDEL hex Prelim TMU2Fbi clock delay value (TMU #2)
** SSTV2_SIPROCESS_CNTR hex Silicon process monitor PCI counter load
** SSTV2_SLIDETECT {0,1} Specify Scanline Interleaving detection
** SSTV2_SLIM_VIN_CLKDEL hex Specify FBI internal video clock delay
** (SLI Master)
** SSTV2_SLIM_VOUT_CLKDEL hex Specify FBI external video clock delay
** (SLI Master)
** SSTV2_SLIS_VIN_CLKDEL hex Specify FBI internal video clock delay
** (SLI Slave)
** SSTV2_SLIS_VOUT_CLKDEL hex Specify FBI external video clock delay
** (SLI Slave)
** SSTV2_SCREENREFRESH {60,75, Select monitor refresh rate
** 85,120}
** SSTV2_SCREENREZ {512, Select monitor resolution (512x384)
** 512256, (512x256)
** 640400, (640x400)
** 640, (640x480)
** 800, (800x600)
** 856, (856x600)
** 960, (960x720)
** 1024} (1024x768)
** SSTV2_SLOWMEM_RTW X Insert wait state for read-to-write
** transitions
** SSTV2_SLOWMEM_WTR X Insert wait state for write-to-read
** transitions
** SSTV2_SLOWPCIWR X Enable 1 wait-state PCI writes
** SSTV2_SLISWAP 1 Use dac_data[0] for SLI swapping
** SSTV2_SWAPBOARDS X Swap order of mapping boards
** SSTV2_TEXMAP_DISABLE X Disable texture mapping
** SSTV2_TF0_CLKDEL hex Trex-to-Fbi clock delay value (TMU #0)
** SSTV2_TF1_CLKDEL hex Trex-to-Fbi clock delay value (TMU #1)
** SSTV2_TF2_CLKDEL hex Trex-to-Fbi clock delay value (TMU #2)
** SSTV2_TF_FIFO_THRESH hex Set TREX-to-FBI FIFO threshold
** SSTV2_TILESINX hex Specify value of tilesInX video register
** SSTV2_TMUCFG hex Specify TMU configuration strapping bits
** SSTV2_TMUMEM X Enable accurate determination of TMU mem
** SSTV2_TMU_MEMSIZE val Specify amount of texture memory
** SSTV2_TREX0INIT0 hex Set trexInit0 register value - TMU #0
** SSTV2_TREX0INIT1 hex Set trexInit1 register value - TMU #0
** SSTV2_TREX1INIT0 hex Set trexInit0 register value - TMU #1
** SSTV2_TREX1INIT1 hex Set trexInit1 register value - TMU #1
** SSTV2_TREX2INIT0 hex Set trexInit0 register value - TMU #2
** SSTV2_TREX2INIT1 hex Set trexInit1 register value - TMU #2
** SSTV2_VIN_CLKDEL hex Specify FBI internal video clock delay
** SSTV2_VOUT_CLKDEL hex Specify FBI external video clock delay
** SSTV2_VGA_PASS {0,1} Force VGA_PASS output to {0,1}
** SSTV2_VIDCLK2X val Video clock frequency (2x dot clock)
** SSTV2_VIDEO_24BPP 0 Select 16-bit video output
** SSTV2_VIDEO_24BPP 1 Select 24-bit video output
** SSTV2_VIDEO_DISABLE X Turn off Video/Monitor refresh in FBI
** SSTV2_VIDEO_FILTER_DISABLE X Disable video filtering
** SSTV2_VIDEO_FILTER_THRESHOLD hex Set video filtering threshold
** SSTV2_VIDEO_NOCLEAR X Do not clear buffers in sst1InitVideo()
** SSTV2_VIDEO_CLEARCOLOR hex Clear screen color
** SSTV2_VFIFO_THRESH {0-31} Select video fifo threshold
** SSTV2_VSYNC hex Specify value of vSync video register
** SSTV2_NOREMAP 0 Don't try to remap single board sli.
** SSTV2_MISMATCHED_SLI X Allow mismatched SLI
**
** VOODOO2_FILE name Filename used in place of "voodoo2.ini"
** VOODOO2_PATH path Path used to locate "voodoo2.ini" file
**
*/
#ifdef __WIN32__
#pragma optimize ("",off)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef BUILD_FOR_SST1
#include <sst.h>
#else
#include <3dfx.h>
#include <cvgregs.h>
#include <cvgdefs.h>
#endif
#include <fxpci.h>
#define SST1INIT_ALLOCATE // Allocate variables in sst1init.h
#define FX_DLL_DEFINITION
#include <fxdll.h>
#if !macintosh && !__linux__
#include <fxremap.h>
#endif
#include <sst1vid.h>
#include <sst1init.h>
#include "rcver.h"
#ifdef __WIN32__
#include <windows.h>
#endif
// Allow SourceSafe to track Revision
static char codeIdent[] = "@#%" VERSIONSTR ;
/*
** sst1InitMapBoard():
** Find and map SST-1 board into virtual memory
**
** Returns:
** FxU32 pointer to base of SST-1 board if successful mapping occurs
** FXFALSE if cannot map or find SST-1 board
**
*/
FX_EXPORT FxU32 * FX_CSTYLE sst1InitMapBoard(FxU32 BoardNumber)
{
return(sst1InitMapBoardDirect(BoardNumber, FXTRUE));
}
// Use this flag to force a info clear when doing a
// sst1InitMapBoard() for the first time. sst1InitShutdown()
// will also set this flag to TRUE to force a clear
// next time around.
static FxU32 clearBoardInfo = FXTRUE;
FX_EXPORT FxU32 * FX_CSTYLE sst1InitMapBoardDirect(FxU32 BoardNumber,
FxBool resetSLI)
{
static FxU32 firstTime = 1;
FxU32 vendorID = _3DFX_PCI_ID; // 3Dfx Vendor ID
FxU32 deviceID; // 0x0002 - Look for a Voodoo2 board (0xFFFF - Find any 3Dfx board)
FxU32 sizeOfCard = 0x1000000; // 16 MBytes of addr space for SST-1
FxU32 *sstbase;
FxU32 n;
FxU32 j;
FxU32 sstv2_noremap = 0;
if( GETENV( ("SSTV2_DEVICEID") ) )
SSCANF(GETENV(("SSTV2_DEVICEID")), "%ld", &deviceID);
else
deviceID = 0x0002;
#if !DIRECTX
// Open PCI library (necessary for multiple calls to init routines, after
// PCI library is closed by pciClose() call in sst1InitShutdown().
//
// NB: It is safe to do this even if we never called pciClose.
pciOpen();
#endif
/* NB: firstTime does not get cleared until we actually find a
* board and get one mapped (A little weird to begin w/, but
* probably not worth changing at this late date). However,
* sst1InitMapBoard usually gets called up to MAX_PCI_DEVICES
* which means that we'll be re-counting and re-mapping boards
* over and over which is just whacked. Now, if we fail to find
* any suitable boards via sst1InitNumBoardsInSystem we clear the
* firstTime flag, and carry on checking for the non-existant
* board which will (of course) fail to map.
*/
if(firstTime) {
// Make Watcom happy
codeIdent[0] = '@';
headersIdent[0] = '@';
// Find "voodoo2.ini" file if it exists...
sst1InitUseVoodooFile = sst1InitVoodooFile();
if( GETENV( ("SSTV2_NOREMAP") ) ) {
SSCANF(GETENV(("SSTV2_NOREMAP")), "%ld", &sstv2_noremap);
} else {
sstv2_noremap = 0;
}
#if !macintosh && !__linux__
if (!sstv2_noremap) {
fxremap(); /* remap single board SLI */
}
#endif
if(!(boardsInSystem = sst1InitNumBoardsInSystem())) {
firstTime = FXTRUE;
return(NULL);
}
}
if( clearBoardInfo ) {
INIT_PRINTF(("sst1Init Routines"));
#ifdef FX_DLL_ENABLE
INIT_PRINTF(("(DLL)"));
#endif
INIT_PRINTF((": %s\n", VERSIONSTR));
INIT_PRINTF(("sst1InitMapBoard(): BoardsInSystem = %d\n",
boardsInSystem));
// Clear board info structure
sst1InitClearBoardInfo();
clearBoardInfo = FXFALSE;
#if !DIRECTX
/* dpc - 26 feb 1998
* If glide is running on windows the a pciClose will close
* the vxd etc. This is not functionally longer fatal, but w/o
* it we will not be able to do things like set the caching on
* the board's memory etc. This is bad.
*
* The actual cost of doing the re-mapping again is pretty low
* because both the pci library and the init code are caching the
* addresses of the board. However, the call to the pciLibrary
* to map the board has the side affect of causing the vxd to be
* loaded. It is this that is responsible for setting up caching.
*/
firstTime = FXTRUE;
#endif /* !DIRECTX */
}
if(firstTime) {
int boardLoopStart = 0;
int boardLoopStop = SST1INIT_MAX_BOARDS;
int boardLoopInc = 1;
int index = 0;
sst1InitClearBoardInfo();
if(GETENV(("SSTV2_SWAPBOARDS"))) {
boardLoopStart = SST1INIT_MAX_BOARDS-1;
boardLoopStop = -1;
boardLoopInc = -1;
}
for(j=0; j<SST1INIT_MAX_BOARDS; j++) {
sst1BoardInfo[j].virtAddr[0] = (SstRegs *) NULL;
sst1BoardInfo[j].physAddr[0] = (FxU32) NULL;
sst1BoardInfo[j].deviceNumber = 0xdead;
sst1BoardInfo[j].fbiRevision = 0xdead;
sst1BoardInfo[j].deviceID = 0xdead;
sst1BoardInfo[j].vendorID = 0xdead;
}
// Map all boards in the system
// Check that scanline interleaving is not enabled...
for(j = boardLoopStart; j != (FxU32)boardLoopStop; j += boardLoopInc) {
sstbase = pciMapCardMulti(vendorID, deviceID, sizeOfCard,
&sst1InitDeviceNumber, j, 0);
if(sstbase) {
sst1BoardInfo[index].virtAddr[0] = (SstRegs *) sstbase;
PCICFG_RD(PCI_BASE_ADDRESS_0, sst1BoardInfo[index].physAddr[0]);
sst1BoardInfo[index].deviceNumber = sst1InitDeviceNumber;
//sst1BoardInfo[index].singleBrdSLISlave =
// ((sst1InitDeviceNumber >> 13) & 0x7);
{
FxU32 oldFbiRevision, newFbiRevision;
PCICFG_RD(PCI_REVISION_ID, oldFbiRevision);
PCICFG_RD(SST1_PCI_INIT_ENABLE, newFbiRevision);
sst1BoardInfo[index].fbiFab =
(newFbiRevision & SST_CHUCK_MFTG_ID) >>
SST_CHUCK_MFTG_ID_SHIFT;
newFbiRevision = (newFbiRevision & SST_CHUCK_REVISION_ID) >>
SST_CHUCK_REVISION_ID_SHIFT;
if(oldFbiRevision != 0x2 && newFbiRevision < 4)
return(NULL);
sst1BoardInfo[index].fbiRevision = newFbiRevision;
}
PCICFG_RD(PCI_DEVICE_ID, sst1BoardInfo[index].deviceID);
PCICFG_RD(PCI_VENDOR_ID, sst1BoardInfo[index].vendorID);
// Enable Memory accesses to SST-1
// Must be set for PnP BIOS which do not enable memory mapped
// accesses (sst1InitSliDetect reads memory mapped regs)
PCICFG_WR(PCI_COMMAND, SST_PCIMEM_ACCESS_EN);
index++;
} else {
FxU32 code = pciGetErrorCode();
if (code != PCI_ERR_NOERR) {
#ifdef __WIN32__
MessageBox(NULL, pciGetErrorString(), NULL, MB_OK);
INIT_PRINTF(("sst1InitMapBoard(): 0x%X\n", GetLastError()));
#endif // __WIN32__
INIT_PRINTF(("pciError(): %s", pciGetErrorString()));
exit(-1);
}
}
}
}
if(resetSLI) {
// Search through all known boards for SLI enabled...
FxU32 k;
SstRegs *sst;
for(k=0; k<boardsInSystemReally; k++) {
// Disable SLI if detected...
if(!(sstbase = (FxU32 *) sst1BoardInfo[k].virtAddr[0]))
return(NULL);
sst1InitDeviceNumber = sst1BoardInfo[k].deviceNumber;
sst1CurrentBoard = &sst1BoardInfo[k];
sst = (SstRegs *) sstbase;
if(IGET(sst->fbiInit1) & SST_EN_SCANLINE_INTERLEAVE) {
INIT_PRINTF(("sst1InitMapBoard(): Disabling Scanline Interleaving (board #%d)...\n", (k+1)));
// Disable SLI Snooping...
PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
PCICFG_WR(SST1_PCI_INIT_ENABLE, j &
~(SST_SCANLINE_SLV_OWNPCI | SST_SCANLINE_SLI_SLV |
SST_SLI_SNOOP_EN | SST_SLI_SNOOP_MEMBASE));
ISET(sst->fbiInit1, IGET(sst->fbiInit1) &
~SST_EN_SCANLINE_INTERLEAVE);
sst1InitReturnStatus(sstbase);
}
// Tristate video output signals, so two boards connected as SLI
// do not have contention problems when SSTV2_SLIDETECT=0
if(firstTime)
sst1InitVideoShutdown(sstbase, FXFALSE);
}
}
firstTime = 0;
// Max number of supported boards in system
if(BoardNumber > SST1INIT_MAX_BOARDS) return(NULL);
if(!(sstbase = (FxU32 *) sst1BoardInfo[BoardNumber].virtAddr[0]))
return (NULL);
INIT_PRINTF(("sst1InitMapBoard(): vAddr:0x%x pAddr:0x%x Dev:0x%x Board:%d\n",
(FxU32) sst1BoardInfo[BoardNumber].virtAddr[0],
(FxU32) sst1BoardInfo[BoardNumber].physAddr[0],
(FxU32) sst1BoardInfo[BoardNumber].deviceNumber, BoardNumber));
// Default settings
sst1BoardInfo[BoardNumber].vgaPassthruDisable = SST_EN_VGA_PASSTHRU;
sst1BoardInfo[BoardNumber].vgaPassthruEnable = 0x0;
sst1BoardInfo[BoardNumber].fbiVideo16BPP = 0;
if(GETENV(("SSTV2_VGA_PASS"))) {
INIT_PRINTF(("sst1InitMapBoard(): Using SST_VGA_PASS=%d\n",
ATOI(GETENV(("SSTV2_VGA_PASS")))));
if(ATOI(GETENV(("SSTV2_VGA_PASS")))) {
sst1BoardInfo[BoardNumber].vgaPassthruEnable = SST_EN_VGA_PASSTHRU;
sst1BoardInfo[BoardNumber].vgaPassthruDisable = 0x0;
} else {
sst1BoardInfo[BoardNumber].vgaPassthruDisable = SST_EN_VGA_PASSTHRU;
sst1BoardInfo[BoardNumber].vgaPassthruEnable = 0x0;
}
}
return(sstbase);
}
/*
** sst1InitRegisters():
** Initialize registers and memory and return to power-on state
**
** Returns:
** FXTRUE if successfully initializes SST-1
** FXFALSE if cannot initialize SST-1
**
*/
FX_EXPORT FxBool FX_CSTYLE sst1InitRegisters(FxU32 *sstbase)
{
FxU32 n, tf_fifo_thresh;
FxU32 ft_clkdel, tf0_clkdel, tf1_clkdel, tf2_clkdel;
sst1ClkTimingStruct sstGrxClk;
SstRegs *sst = (SstRegs *) sstbase;
if(!sst)
return(FXFALSE);
if(sst1InitCheckBoard(sstbase) == FXFALSE)
return(FXFALSE);
if(GETENV(("SSTV2_IGNORE_INIT_REGISTERS"))) {
INIT_PRINTF(("WARNING: Ignoring sst1InitRegisters()...\n"));
sst1InitIdleFBINoNOP(sstbase);
return(FXTRUE);
}
if(GETENV(("SSTV2_TEXMAP_DISABLE")))
INIT_PRINTF(("sst1InitRegisters() WARNING: Disabling texture mapping\n"));
#if !DIRECTX
// Open PCI library (necessary for multiple calls to init routines, after
// PCI library is closed by pciClose() call in sst1InitShutdown()
pciOpen();
#endif
// Enable writes to the FBIINIT registers
// Do not allow writes into the pci fifo until everything is reset
PCICFG_WR(SST1_PCI_INIT_ENABLE, SST_INITWR_EN);
// Reset Snoop registers to default values
PCICFG_WR(SST1_PCI_BUS_SNOOP0, SST_PCI_BUS_SNOOP_DEFAULT);
PCICFG_WR(SST1_PCI_BUS_SNOOP1, SST_PCI_BUS_SNOOP_DEFAULT);
sst1InitReturnStatus(sstbase); // Stall - can't call IdleFbi because
sst1InitReturnStatus(sstbase); // FBI could be hung at this stage
sst1InitReturnStatus(sstbase);
// Adjust Trex-to-Fbi FIFO
if(GETENV(("SSTV2_TF_FIFO_THRESH")))
SSCANF(GETENV(("SSTV2_TF_FIFO_THRESH")), "%ld", &tf_fifo_thresh);
else
tf_fifo_thresh = 0x8;
INIT_PRINTF(("sst1InitRegisters(): Setting TREX-to-FBI FIFO THRESHOLD to 0x%x...\n",
tf_fifo_thresh));
// Set ft_clkdel for 16 MHz bringup
ft_clkdel = 0x8; // Okay for 16 MHz startup...
if(GETENV(("SSTV2_PFT_CLKDEL")))
SSCANF(GETENV(("SSTV2_PFT_CLKDEL")), "%ld", &ft_clkdel);
INIT_PRINTF(("sst1InitRegisters(): Setting PRELIM FT-CLK delay to 0x%x...\n", ft_clkdel));
// SST_FBIINIT3_DEFAULT is set to disable texture mapping, so if
// TMUs are hung, it will not affect FBI
ISET(sst->fbiInit3,
(SST_FBIINIT3_DEFAULT & ~(SST_FT_CLK_DEL_ADJ | SST_TF_FIFO_THRESH)) |
(ft_clkdel << SST_FT_CLK_DEL_ADJ_SHIFT) |
(tf_fifo_thresh << SST_TF_FIFO_THRESH_SHIFT));
// Wait for Fbi-to-Trex clock delay value to propogate
sst1InitReturnStatus(sstbase); // Stall - can't call IdleFbi because
sst1InitReturnStatus(sstbase); // FBI could be hung at this stage
sst1InitReturnStatus(sstbase);
// Reset graphics and video units
// Must reset video unit before graphics unit, otherwise video unit could
// potentially hang waiting for the graphics unit to respond
ISET(sst->fbiInit1, IGET(sst->fbiInit1) | SST_VIDEO_RESET);
// Don't wait for idle because graphics could be hung...
sst1InitReturnStatus(sstbase);
sst1InitReturnStatus(sstbase);
sst1InitReturnStatus(sstbase);
ISET(sst->fbiInit0,
IGET(sst->fbiInit0) | (SST_GRX_RESET | SST_PCI_FIFO_RESET));
sst1InitIdleFBINoNOP(sstbase);
// Unreset PCI FIFO...
ISET(sst->fbiInit0, IGET(sst->fbiInit0) & ~SST_PCI_FIFO_RESET);
sst1InitIdleFBINoNOP(sstbase);
// Unreset graphics subsystem
// THIS MUST BE PRESENT OTHERWISE THE PCI FIFO WILL NEVER DRAIN!
ISET(sst->fbiInit0, IGET(sst->fbiInit0) & ~SST_GRX_RESET);
sst1InitIdleFBINoNOP(sstbase);
// Reset all FBI and TREX Init registers
ISET(sst->fbiInit0, SST_FBIINIT0_DEFAULT);
ISET(sst->fbiInit1, SST_FBIINIT1_DEFAULT);
ISET(sst->fbiInit2, SST_FBIINIT2_DEFAULT);
ISET(sst->fbiInit3,
(SST_FBIINIT3_DEFAULT & ~(SST_FT_CLK_DEL_ADJ | SST_TF_FIFO_THRESH)) |
(ft_clkdel << SST_FT_CLK_DEL_ADJ_SHIFT) |
(tf_fifo_thresh << SST_TF_FIFO_THRESH_SHIFT));
ISET(sst->fbiInit4, SST_FBIINIT4_DEFAULT);
ISET(sst->fbiInit5, SST_FBIINIT5_DEFAULT);
ISET(sst->fbiInit6, SST_FBIINIT6_DEFAULT);
sst1CurrentBoard->fbiInit6 = SST_FBIINIT6_DEFAULT;
ISET(sst->fbiInit7, SST_FBIINIT7_DEFAULT);
sst1InitIdleFBINoNOP(sstbase); // Wait until init regs are reset
// Enable writes to the FBIINIT registers and allow pushes onto PCI FIFO
PCICFG_WR(SST1_PCI_INIT_ENABLE, (SST_INITWR_EN | SST_PCI_FIFOWR_EN));
// Determine DAC Type
if(sst1InitDacDetect(sstbase) == FXFALSE) {
INIT_PRINTF(("sst1InitRegisters(): Could not detect DAC...\n"));
return(FXFALSE);
}
// set TREX0 init values
if(GETENV(("SSTV2_TREX0INIT0"))) {
INIT_PRINTF(("sst1InitRegisters(): Using SST_TREX0INIT0 environment variable\n"));
SSCANF(GETENV(("SSTV2_TREX0INIT0")), "%ld",
&sst1CurrentBoard->tmuInit0[0]);
} else
sst1CurrentBoard->tmuInit0[0] = SST_TREX0INIT0_DEFAULT;
INIT_PRINTF(("sst1InitRegisters(): Storing TREX0INIT0=0x%x\n",
sst1CurrentBoard->tmuInit0[0]));
if(GETENV(("SSTV2_TREX0INIT1"))) {
INIT_PRINTF(("sst1InitRegisters(): Using SST_TREX0INIT1 environment variable\n"));
SSCANF(GETENV(("SSTV2_TREX0INIT1")), "%ld",
&sst1CurrentBoard->tmuInit1[0]);
} else
sst1CurrentBoard->tmuInit1[0] = SST_TREX0INIT1_DEFAULT;
if(GETENV(("SSTV2_PTF0_CLKDEL"))) {
SSCANF(GETENV(("SSTV2_PTF0_CLKDEL")), "%ld", &tf0_clkdel);
sst1CurrentBoard->tmuInit1[0] = (sst1CurrentBoard->tmuInit1[0] &
~SST_TEX_TF_CLK_DEL_ADJ) |
(tf0_clkdel<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT);
}
INIT_PRINTF(("sst1InitRegisters(): Storing TREX0INIT1=0x%x\n",
sst1CurrentBoard->tmuInit1[0]));
// set TREX1 init values
if(GETENV(("SSTV2_TREX1INIT0"))) {
INIT_PRINTF(("sst1InitRegisters(): Using SST_TREX1INIT0 environment variable\n"));
SSCANF(GETENV(("SSTV2_TREX1INIT0")), "%ld",
&sst1CurrentBoard->tmuInit0[1]);
} else
sst1CurrentBoard->tmuInit0[1] = SST_TREX1INIT0_DEFAULT;
INIT_PRINTF(("sst1InitRegisters(): Storing TREX1INIT0=0x%x\n",
sst1CurrentBoard->tmuInit0[1]));
if(GETENV(("SSTV2_TREX1INIT1"))) {
INIT_PRINTF(("sst1InitRegisters(): Using SST_TREX1INIT1 environment variable\n"));
SSCANF(GETENV(("SSTV2_TREX1INIT1")), "%ld",
&sst1CurrentBoard->tmuInit1[1]);
} else
sst1CurrentBoard->tmuInit1[1] = SST_TREX1INIT1_DEFAULT;
if(GETENV(("SSTV2_PTF1_CLKDEL"))) {
SSCANF(GETENV(("SSTV2_PTF1_CLKDEL")), "%ld", &tf1_clkdel);
sst1CurrentBoard->tmuInit1[1] = (sst1CurrentBoard->tmuInit1[1] &
~SST_TEX_TF_CLK_DEL_ADJ) |
(tf1_clkdel<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT);
}
INIT_PRINTF(("sst1InitRegisters(): Storing TREX1INIT1=0x%x\n",
sst1CurrentBoard->tmuInit1[1]));
// set TREX2 init values
if(GETENV(("SSTV2_TREX2INIT0"))) {
INIT_PRINTF(("sst1InitRegisters(): Using SST_TREX2INIT0 environment variable\n"));
SSCANF(GETENV(("SSTV2_TREX2INIT0")), "%ld",
&sst1CurrentBoard->tmuInit0[2]);
} else
sst1CurrentBoard->tmuInit0[2] = SST_TREX2INIT0_DEFAULT;
INIT_PRINTF(("sst1InitRegisters(): Storing TREX2INIT0=0x%x\n",
sst1CurrentBoard->tmuInit0[2]));
if(GETENV(("SSTV2_TREX2INIT1"))) {
INIT_PRINTF(("sst1InitRegisters(): Using SST_TREX2INIT1 environment variable\n"));
SSCANF(GETENV(("SSTV2_TREX2INIT1")), "%ld",
&sst1CurrentBoard->tmuInit1[2]);
} else
sst1CurrentBoard->tmuInit1[2] = SST_TREX2INIT1_DEFAULT;
if(GETENV(("SSTV2_PTF2_CLKDEL"))) {
SSCANF(GETENV(("SSTV2_PTF2_CLKDEL")), "%ld", &tf2_clkdel);
sst1CurrentBoard->tmuInit1[2] = (sst1CurrentBoard->tmuInit1[2] &
~SST_TEX_TF_CLK_DEL_ADJ) |
(tf2_clkdel<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT);
}
INIT_PRINTF(("sst1InitRegisters(): Storing TREX2INIT1=0x%x\n",
sst1CurrentBoard->tmuInit1[2]));
// Set clock at 16 MHz to properly transmit TREX configuration registers
// Note that setting the clock will automatically reset the TMUs...
// sst1InitResetTmus() also will de-assert TEXMAP_DISABLE in fbiInit3
// unless SSTV2_TEXMAP_DISABLE is set
if(!sst1InitComputeClkParams(16.0f, &sstGrxClk))
return(FXFALSE);
if(!sst1InitSetGrxClk(sstbase, &sstGrxClk))
return(FXFALSE);
sst1CurrentBoard->initGrxClkDone = 0;
// Set PCI wait-states
if(GETENV(("SSTV2_SLOWPCIWR"))) {
INIT_PRINTF(("sst1InitRegisters(): Setting up SLOW PCI Writes...\n"));
ISET(sst->fbiInit1, IGET(sst->fbiInit1) | SST_PCI_WRWS_1);
} else
ISET(sst->fbiInit1, IGET(sst->fbiInit1) & ~SST_PCI_WRWS_1);
if(GETENV(("SSTV2_FASTPCIRD"))) {
INIT_PRINTF(("sst1InitRegisters(): Setting up FAST PCI Reads...\n"));
ISET(sst->fbiInit4, IGET(sst->fbiInit4) & ~SST_PCI_RDWS_2);
}
sst1InitIdleFBINoNOP(sstbase);
// Enable Linear frame buffer reads
ISET(sst->fbiInit1, IGET(sst->fbiInit1) | SST_LFB_READ_EN);
// Swapbuffer algorithm is based on VSync initially
ISET(sst->fbiInit2, (IGET(sst->fbiInit2) & ~SST_SWAP_ALGORITHM) |
SST_SWAP_VSYNC);
// Enable LFB read-aheads
ISET(sst->fbiInit4, IGET(sst->fbiInit4) | SST_EN_LFB_RDAHEAD);
// Enable triangle alternate register mapping
ISET(sst->fbiInit3, IGET(sst->fbiInit3) | SST_ALT_REGMAPPING);
// Enable Endian Byte Swapping
ISET(sst->fbiInit0, IGET(sst->fbiInit0) | SST_EN_ENDIAN_SWAPPING);
// Setup DRAM Refresh
ISET(sst->fbiInit2, (IGET(sst->fbiInit2) & ~SST_DRAM_REFRESH_CNTR) |
SST_DRAM_REFRESH_16MS);
sst1InitIdleFBINoNOP(sstbase);
ISET(sst->fbiInit2, IGET(sst->fbiInit2) | SST_EN_DRAM_REFRESH);
sst1InitIdleFBINoNOP(sstbase);
{
// Setup memory timings...
FxU32 fbiInit1 = IGET(sst->fbiInit1);
FxU32 fbiInit2 = IGET(sst->fbiInit2) |
SST_EN_DRAM_RD_AHEAD_FIFO | SST_EN_FAST_RD_AHEAD_WR;
if(GETENV(("SSTV2_SLOWMEM_WTR"))) {
INIT_PRINTF(("sst1InitRegisters(): Running slow write-to-read memory timing...\n"));
fbiInit1 |= SST_DISEN_RD_AHEAD_WR_RD;
}
if(GETENV(("SSTV2_SLOWMEM_RTW"))) {
INIT_PRINTF(("sst1InitRegisters(): Running slow read-to-write memory timing...\n"));
fbiInit2 &= ~SST_EN_FAST_RD_AHEAD_WR;
}
if(GETENV(("SSTV2_FASTMEM_RAS_READS"))) {
INIT_PRINTF(("sst1InitRegisters(): Enabling fast RAS read memory timing...\n"));
fbiInit2 |= SST_EN_FAST_RAS_READ;
}
ISET(sst->fbiInit1, fbiInit1);
sst1InitReturnStatus(sstbase);
ISET(sst->fbiInit2, fbiInit2);
sst1InitReturnStatus(sstbase);
}
// Return all other registers to their power-on state
sst1InitIdleFBINoNOP(sstbase);
sst1InitSetResolution(sstbase, &SST_VREZ_640X480_60, 0);
sst1InitIdleFBINoNOP(sstbase);
// Get DRAMs up and running (refresh is already enabled)...
ISET(sst->c1, 0x0);
ISET(sst->c0, 0x0);
ISET(sst->zaColor, 0x0);
ISET(sst->clipLeftRight, 100); // draw into 50x50 area
ISET(sst->clipBottomTop, 100);
ISET(sst->fbzMode, SST_RGBWRMASK | SST_ZAWRMASK);
ISET(sst->fastfillCMD, 0x0); // Frontbuffer & Z/A
ISET(sst->nopCMD, 0x1); // Clear fbistat registers after clearing screen
sst1InitIdleFBINoNOP(sstbase);
sst1InitRenderingRegisters(sstbase);
sst1CurrentBoard->tmuRevision = 0xdead; // Force sst1InitFillDeviceInfo()
if(sst1InitFillDeviceInfo(sstbase, sst1CurrentBoard) == FXFALSE) {
INIT_PRINTF(("sst1InitRegisters(): ERROR filling DeviceInfo...\n"));
return(FXFALSE);
}
sst1InitIdleFBINoNOP(sstbase);
sst1InitRenderingRegisters(sstbase);
sst1InitIdleFBINoNOP(sstbase);
// LFB writes stored in memory FIFO?
if(GETENV(("SSTV2_MEMFIFO_LFB")))
n = ATOI(GETENV(("SSTV2_MEMFIFO_LFB")));
else
n = 1;
if(n) {
INIT_PRINTF(("sst1InitRegisters(): LFB Writes go through memory FIFO...\n"));
ISET(sst->fbiInit0, IGET(sst->fbiInit0) | SST_EN_LFB_MEMFIFO);
sst1InitIdleFBINoNOP(sstbase);
}
// Texture memory writes stored in memory FIFO?
if(GETENV(("SSTV2_MEMFIFO_TEX")))
n = ATOI(GETENV(("SSTV2_MEMFIFO_TEX")));
else
n = 1;
if(n) {
INIT_PRINTF(("sst1InitRegisters(): TEXTURE Writes go through memory FIFO...\n"));
ISET(sst->fbiInit0, IGET(sst->fbiInit0) | SST_EN_TEX_MEMFIFO);
sst1InitIdleFBINoNOP(sstbase);
}
ISET(sst->vRetrace, 0x0);
ISET(sst->backPorch, 0x0);
ISET(sst->videoDimensions, 0x0);
ISET(sst->hSync, 0x0);
ISET(sst->vSync, 0x0);
ISET(sst->videoFilterRgbThreshold, 0x0);
sst1InitIdleFBINoNOP(sstbase); // Wait until init regs are reset
// Update info structure for initEnable
PCICFG_RD(SST1_PCI_INIT_ENABLE, sst1CurrentBoard->fbiInitEnable);
INIT_PRINTF(("sst1InitRegisters(): exiting with status %d...\n", FXTRUE));
return(FXTRUE);
}
FX_EXPORT void FX_CSTYLE sst1InitRenderingRegisters(FxU32 *sstbase)
{
FxU32 i;
SstRegs *sst = (SstRegs *) sstbase;
ISET(sst->vA.x, 0x0); ISET(sst->vA.y, 0x0);
ISET(sst->vB.x, 0x0); ISET(sst->vB.y, 0x0);
ISET(sst->vC.x, 0x0); ISET(sst->vC.y, 0x0);
ISET(sst->r, 0x0); ISET(sst->g, 0x0);
ISET(sst->b, 0x0); ISET(sst->z, 0x0);
ISET(sst->a, 0x0); ISET(sst->s, 0x0);
ISET(sst->t, 0x0); ISET(sst->w, 0x0);
ISET(sst->drdx, 0x0); ISET(sst->dgdx, 0x0);
ISET(sst->dbdx, 0x0); ISET(sst->dzdx, 0x0);
ISET(sst->dadx, 0x0); ISET(sst->dsdx, 0x0);
ISET(sst->dtdx, 0x0); ISET(sst->dwdx, 0x0);
ISET(sst->drdy, 0x0); ISET(sst->dgdy, 0x0);
ISET(sst->dbdy, 0x0); ISET(sst->dzdy, 0x0);
ISET(sst->dady, 0x0); ISET(sst->dsdy, 0x0);
ISET(sst->dtdy, 0x0); ISET(sst->dwdy, 0x0);
ISET(sst->fbzColorPath, 0x0);
ISET(sst->fogMode, 0x0);
ISET(sst->alphaMode, 0x0);
ISET(sst->fbzMode, 0x0);
ISET(sst->lfbMode, 0x0);
ISET(sst->clipLeftRight, 0x0);
ISET(sst->clipBottomTop, 0x0);
ISET(sst->fogColor, 0x0);
ISET(sst->zaColor, 0x0);
ISET(sst->chromaKey, 0x0);
ISET(sst->chromaRange, 0x0);
ISET(sst->stipple, 0x0);
ISET(sst->c0, 0x0);
ISET(sst->c1, 0x0);
ISET(sst->sSetupMode, 0x0);
ISET(sst->sVx, 0x0);
ISET(sst->sVy, 0x0);
ISET(sst->sARGB, 0x0);
ISET(sst->sRed, 0x0);
ISET(sst->sGreen, 0x0);
ISET(sst->sBlue, 0x0);
ISET(sst->sAlpha, 0x0);
ISET(sst->sVz, 0x0);
ISET(sst->sOowfbi, 0x0);
ISET(sst->sOow0, 0x0);
ISET(sst->sSow0, 0x0);
ISET(sst->sTow0, 0x0);
ISET(sst->sOow1, 0x0);
ISET(sst->sSow1, 0x0);
ISET(sst->sTow1, 0x0);
ISET(sst->nopCMD, 0x3); // Clear fbistat and trianglesOut registers
for(i=0; i<32; i++)
ISET(sst->fogTable[i], 0x0);
ISET(sst->bltSrcBaseAddr, 0x0);
ISET(sst->bltDstBaseAddr, 0x0);
ISET(sst->bltXYstrides, 0x0);
ISET(sst->bltSrcChromaRange, 0x0);
ISET(sst->bltDstChromaRange, 0x0);
ISET(sst->bltClipX, 0x0);
ISET(sst->bltClipY, 0x0);
ISET(sst->bltSrcXY, 0x0);
ISET(sst->bltDstXY, 0x0);
ISET(sst->bltSize, 0x0);
ISET(sst->bltRop, 0x0);
ISET(sst->bltColor, 0x0);
ISET(sst->bltCommand, 0x0);
// clear TMU registers
ISET(sst->textureMode, 0x0);
ISET(sst->tLOD, 0x0);
ISET(sst->tDetail, 0x0);
ISET(sst->texBaseAddr, 0x0);
ISET(sst->texBaseAddr1, 0x0);
ISET(sst->texBaseAddr2, 0x0);
ISET(sst->texBaseAddr38, 0x0);
for(i=0; i<12; i++)
ISET(sst->nccTable0[i], 0x0);
for(i=0; i<12; i++)
ISET(sst->nccTable1[i], 0x0);
sst1InitIdle(sstbase);
ISET(sst->tchromaKey, 0x0);
ISET(sst->tchromaRange, 0x0);
}
/*
** sst1InitShutdown():
** Shutdown SST-1
** Resets state of VGA_PASS to return monitor control back to the VGA
** Powers-down the DAC
** Resets the graphics clock in FBI to conserve power
**
** Returns:
** FXTRUE if successfully shuts down SST-1
** FXFALSE if cannot shut down the SST-1
**
*/
FX_EXPORT FxBool FX_CSTYLE sst1InitShutdown(FxU32 *sstbase)
{
SstRegs *sstMaster = (SstRegs *) sstbase;
SstRegs *sstSlave;
SstRegs *sstPtr;
FxU32 n;
FxU32 sliEnabled;
sst1ClkTimingStruct sstGrxClk;
if(!sstbase)
return(FXFALSE);
if(sst1InitCheckBoard((FxU32 *) sstbase) == FXFALSE)
return(FXFALSE);
// sst1Initidle() routines must be properly executed...
initIdleEnabled = 1;
sliEnabled = (sst1CurrentBoard->sliSlaveVirtAddr != (FxU32 *) NULL) ? 1 : 0;
sstSlave = (SstRegs *) sst1CurrentBoard->sliSlaveVirtAddr;
#if 0
// If the command fifo is enabled, we can't issue a NOP first, so wait
// until the PCI fifo is empty...
sst1InitPciFifoIdleLoop(sstbase);
if(sst1CurrentBoard->sliSlaveVirtAddr)
sst1InitPciFifoIdleLoop(sst1CurrentBoard->sliSlaveVirtAddr);
#else
sst1InitIdle(sstbase);
#endif
// Disable the command fifo if enabled...
if(sst1CurrentBoard->fbiCmdFifoEn ||
(IGET(sstMaster->fbiInit7) & SST_EN_CMDFIFO))
sst1InitCmdFifo(sstbase, FXFALSE, (void *) NULL, (void *) NULL,
(void *) NULL, NULL);
sst1InitIdle(sstbase);
if(sliEnabled && !GETENV(("SSTV2_NOSHUTDOWN"))) {
if(sst1InitShutdownSli(sstbase) == FXFALSE)
return(FXFALSE);
}
if(GETENV(("SSTV2_NOSHUTDOWN")))
INIT_PRINTF(("sst1InitShutdown(): Bypassing shutdown with SSTV2_NOSHUTDOWN\n"));
n = 0;
while(!GETENV(("SSTV2_NOSHUTDOWN"))) {
if(!n)
sstPtr = sstMaster;
else
sstPtr = sstSlave;
if(sst1InitCheckBoard((FxU32 *) sstPtr) == FXFALSE)
return(FXFALSE);
INIT_PRINTF(("sst1InitShutdown(): Shutting down SST-1 #%d...\n", n));
// Reset video unit to guarantee no contentions on the memory bus
// Blank DAC so VGA Passthru works properly
ISET(sstPtr->fbiInit1,
IGET(sstPtr->fbiInit1) | (SST_VIDEO_RESET | SST_VIDEO_BLANK_EN));
// Turn off dram refresh to guarantee no contentions on the
// memory bus
ISET(sstPtr->fbiInit2, IGET(sstPtr->fbiInit2) & ~SST_EN_DRAM_REFRESH);
// Reset graphics subsystem
ISET(sstPtr->fbiInit0,
IGET(sstPtr->fbiInit0) | (SST_GRX_RESET | SST_PCI_FIFO_RESET));
sst1InitIdleFBINoNOP((FxU32 *) sstPtr);
ISET(sstPtr->fbiInit0, IGET(sstPtr->fbiInit0) & ~SST_PCI_FIFO_RESET);
sst1InitIdleFBINoNOP((FxU32 *) sstPtr);
ISET(sstPtr->fbiInit0, IGET(sstPtr->fbiInit0) & ~SST_GRX_RESET);
sst1InitIdleFBINoNOP((FxU32 *) sstPtr);
// Turnaround VGA_PASS to allow VGA monitor
sst1InitVgaPassCtrl((FxU32 *) sstPtr, 1);
sst1InitIdleFBINoNOP((FxU32 *) sstPtr);
// Set clock at 30 MHz to reduce power consumption...
sst1InitComputeClkParams((float) 30.0, &sstGrxClk);
if(sst1InitSetGrxClk((FxU32 *) sstPtr, &sstGrxClk) == FXFALSE)
INIT_PRINTF(("sst1InitShutdown() WARNING: sst1InitSetGrxClk failed...Continuing...\n"));
sst1CurrentBoard->initGrxClkDone = 0;
#ifndef __linux__
pciUnmapPhysical((FxU32)sst1CurrentBoard->virtAddr[0], 0x1000000UL);
#endif
if((++n > 1) || !sliEnabled)
break;
}
/* sst1InitIdle(sstbase); */
#if !DIRECTX
//
// HACK alert.
//
// There's a pciClose(), but nobody calls it. This is needed by the
// DOS DPMI services to close fxmemmap.vxd.
//
// Note that the call to pciClose must be after the shutdown sequence,
// as the shutdown sequence uses PCI configuration reads/writes...
//
pciClose();
#endif /* !DIRECTX */
INIT_PRINTF(("sst1InitShutdown(): Returning with status %d...\n", FXTRUE));
#ifdef INIT_OUTPUT
if ( sst1InitMsgFile != stdout )
fclose(sst1InitMsgFile);
#endif
// Make sure that the board info structures are
// cleared next time sst1InitMapBoard() is called.
clearBoardInfo = FXTRUE;
return(FXTRUE);
}
/*
** sst1InitCheckBoard():
** Set internal global variables for multiple SST-1 support
**
*/
FX_EXPORT FxBool FX_CSTYLE sst1InitCheckBoard(FxU32 *sstbase)
{
FxU32 n;
FxBool returnVal = FXFALSE;
for(n=0; n<boardsInSystem; n++) {
if((FxU32 *) sst1BoardInfo[n].virtAddr[0] == sstbase) {
sst1InitDeviceNumber = sst1BoardInfo[n].deviceNumber;
sst1CurrentBoard = &sst1BoardInfo[n];
returnVal = FXTRUE;
n = boardsInSystem;
}
}
return(returnVal);
}
/*
** sst1InitGetBaseAddr():
** Return virtual base address to hardware
** Returns NULL if board requested has not been mapped
**
*/
FX_EXPORT FxU32 * FX_CSTYLE sst1InitGetBaseAddr(FxU32 boardNum)
{
SstRegs* sstBaseAddr = sst1BoardInfo[boardNum].virtAddr[0];
sst1DeviceInfoStruct devInfo;
if ((sstBaseAddr != NULL) &&
sst1InitGetDeviceInfo((FxU32*)sstBaseAddr, &devInfo) &&
devInfo.sliDetected &&
!devInfo.monitorDetected) {
SstRegs* tempAddr = NULL;
if (boardNum > 0) {
if (sst1BoardInfo[boardNum - 1].sliSlaveVirtAddr == (FxU32*)sstBaseAddr) {
tempAddr = sst1BoardInfo[boardNum - 1].virtAddr[0];
}
}
if ((tempAddr == NULL) && (boardNum < boardsInSystem)) {
if (sst1BoardInfo[boardNum + 1].sliSlaveVirtAddr == (FxU32*)sstBaseAddr) {
tempAddr = sst1BoardInfo[boardNum + 1].virtAddr[0];
}
}
if (tempAddr != NULL) sstBaseAddr = tempAddr;
}
return (FxU32*)sstBaseAddr;
}
/*
** sst1InitClearBoardInfo():
** Clear board configuration information
**
*/
void sst1InitClearBoardInfo(void)
{
FxU32 n, j;
for(n=0; n<SST1INIT_MAX_BOARDS; n++) {
sst1BoardInfo[n].size = sizeof(sst1DeviceInfoStruct);
//sst1BoardInfo[n].virtAddr[0] = (SstRegs *) NULL;
//sst1BoardInfo[n].physAddr[0] = (FxU32) NULL;
//sst1BoardInfo[n].deviceNumber = 0xdead;
//sst1BoardInfo[n].vendorID = 0xdead;
//sst1BoardInfo[n].deviceID = 0xdead;
//sst1BoardInfo[n].fbiRevision = 0xdead;
//sst1BoardInfo[n].fbiFab = 0xdead;
sst1BoardInfo[n].fbiBoardID = 0xdead;
sst1BoardInfo[n].fbiVideo16BPP = 0xdead;
sst1BoardInfo[n].fbiVideoWidth = 0xdead;
sst1BoardInfo[n].fbiVideoHeight = 0xdead;
sst1BoardInfo[n].fbiVideoRefresh = 0xdead;
sst1BoardInfo[n].fbiVideoColBuffs = 0xdead;
sst1BoardInfo[n].fbiVideoAuxBuffs = 0xdead;
sst1BoardInfo[n].fbiVideoMemOffset = 0xdead;
sst1BoardInfo[n].fbiVideoTilesInX = 0xdead;
sst1BoardInfo[n].fbiVideoStruct = (sst1VideoTimingStruct *) NULL;
sst1BoardInfo[n].fbiVideoDacType = 0xdead;
sst1BoardInfo[n].fbiMemoryFifoEn = 0x0;
sst1BoardInfo[n].fbiCmdFifoEn = 0x0;
sst1BoardInfo[n].fbiLfbLocked = 0x0;
sst1BoardInfo[n].fbiConfig = 0xdead;
sst1BoardInfo[n].fbiGrxClkFreq = 0xdead;
sst1BoardInfo[n].fbiMemSize = 0x0;
sst1BoardInfo[n].fbiInitGammaDone = 0x0;
sst1BoardInfo[n].fbiGammaRed = (double) 0.0;
sst1BoardInfo[n].fbiGammaGreen = (double) 0.0;
sst1BoardInfo[n].fbiGammaBlue = (double) 0.0;
sst1BoardInfo[n].tmuRevision = 0xdead;
sst1BoardInfo[n].numberTmus = 0xdead;
sst1BoardInfo[n].tmuConfig = 0xdead;
sst1BoardInfo[n].tmuGrxClkFreq = 0xdead;
for(j=0; j<MAX_NUM_TMUS; j++) {
sst1BoardInfo[n].tmuFab[j] = 0xdead;
sst1BoardInfo[n].tmuMemSize[j] = 0x0;
sst1BoardInfo[n].tmuInit0[j] = 0xdead;
sst1BoardInfo[n].tmuInit1[j] = 0xdead;
}
sst1BoardInfo[n].fbiInit6 = 0;
sst1BoardInfo[n].fbiInitEnable = 0;
sst1BoardInfo[n].sliDetected = 0;
sst1BoardInfo[n].monitorDetected = 0;
sst1BoardInfo[n].sliSlaveVirtAddr = (FxU32 *) NULL;
sst1BoardInfo[n].initGrxClkDone = 0;
sst1BoardInfo[n].vgaPassthruDisable = 0;
sst1BoardInfo[n].vgaPassthruEnable = 0;
sst1BoardInfo[n].memFifoStatusLwm = 0xdead;
}
}
/*
** sst1InitNumBoardsInSystem():
** Returns the number of SST-1 boards in the system
**
*/
FX_ENTRY FxU32 FX_CSTYLE sst1InitNumBoardsInSystem(void)
{
FxU32 vendorID = _3DFX_PCI_ID; // 3Dfx Vendor ID
FxU32 deviceID; // 0x0002 - Find Voodoo2 boards ( 0xFFFF - Find any 3Dfx board)
FxU32 j, n;
if( GETENV( ("SSTV2_DEVICEID") ) )
deviceID = ATOI( GETENV( "SSTV2_DEVICEID" ) );
else
deviceID = 0x0002;
boardsInSystemReally = 0;
for(j=0; j<SST1INIT_MAX_BOARDS; j++) {
if(pciFindCardMulti(vendorID, deviceID, &n, j))
boardsInSystemReally++;
}
if(GETENV(("SSTV2_BOARDS")))
return(ATOI(GETENV(("SSTV2_BOARDS"))));
else
return(boardsInSystemReally);
}
/*
** sst1InitCaching
**
** Sets up memory caching on P6 class systems and K7 systems for the
** lower 8 MB of the 16 MB virtual address space of the card. These
** hold the command fifo area.
**
*/
FX_ENTRY FxBool FX_CSTYLE
sst1InitCaching(FxU32* sstBase, FxBool enableP)
{
FxBool retVal = sst1InitCheckBoard(sstBase);
if (!retVal) return FXFALSE;
if (enableP && (GETENV("SSTV2_IGNORE_CACHING") == NULL)) {
FxU32 physAddr;
/* Get the board's base. Isn't this the same as what we
* cary around in sst1CurrentBoard->physAddr[0]?
*/
pciGetConfigData(PCI_BASE_ADDRESS_0, sst1CurrentBoard->deviceNumber, &physAddr);
// For some reason, there sometimes is a 008 at the end of the
// physical address, so mask that puppy RTF out
physAddr &= 0xfffff000;
/* dpc - 23 jan 1998 - Warning!!!!!
* We are no longer mapping the entire board range as uswc because
* this causes weird problems on some systems. We are now mapping
* the 3d register area as uncacheable (since no one should be
* writing here anyway, except to bump the swapbufferCMD register)
* and the command fifo range and lfb range as uswc.
*
* NB: It is still unclear why this is happening because the
* memory page containing the registers is never really explicitly
* written to until we are shutting down so changing its caching
* characteristics should have no bearing on anything. */
{
#define kCacheSizeWriteCombine (0x08UL << 20UL)
#define kCacheSizeUncacheable (0x1000UL)
FxBool hasWC = pciFindMTRRMatch(physAddr, kCacheSizeWriteCombine,
PciMemTypeWriteCombining,
&sst1CurrentBoard->mtrrWriteCombine);
FxBool hasUC = pciFindMTRRMatch(physAddr, kCacheSizeUncacheable,
PciMemTypeUncacheable,
&sst1CurrentBoard->mtrrUncacheable);
if (!hasWC) {
if (pciFindFreeMTRR(&sst1CurrentBoard->mtrrWriteCombine)) {
hasWC = pciSetMTRR(sst1CurrentBoard->mtrrWriteCombine,
physAddr, kCacheSizeWriteCombine,
PciMemTypeWriteCombining);
if (!hasWC) INIT_PRINTF(("sst1InitCaching(): Could not set wc mtrr\n"));
} else {
INIT_PRINTF(("sst1InitCaching(): Could not find wc mtrr\n"));
}
} else {
INIT_PRINTF(("sst1InitCaching(): Already have wc\n"));
}
if (!hasUC) {
if (pciFindFreeMTRR(&sst1CurrentBoard->mtrrUncacheable)) {
hasUC = pciSetMTRR(sst1CurrentBoard->mtrrUncacheable,
physAddr, kCacheSizeUncacheable,
PciMemTypeUncacheable);
if (!hasUC) INIT_PRINTF(("sst1InitCaching(): Could not set uc mtrr\n"));
} else {
INIT_PRINTF(("sst1InitCaching(): Could not find uc mtrr\n"));
}
} else {
INIT_PRINTF(("sst1InitCaching(): Already have uc\n"));
}
/* We only succeed if we have them both since having only uswc
* seems to cause problems.
*/
retVal = (hasWC && hasUC);
if (!retVal) goto __errExit;
INIT_PRINTF(("sst1InitCaching(): wc(0x%X) : uc(0x%X)\n",
sst1CurrentBoard->mtrrWriteCombine,
sst1CurrentBoard->mtrrUncacheable));
}
} else {
/* This always succeeds */
retVal = FXTRUE;
__errExit:
if (sst1CurrentBoard->mtrrUncacheable != 0) {
pciSetMTRR(sst1CurrentBoard->mtrrUncacheable, 0, 0, 0);
sst1CurrentBoard->mtrrUncacheable = 0;
}
if (sst1CurrentBoard->mtrrWriteCombine != 0) {
pciSetMTRR(sst1CurrentBoard->mtrrWriteCombine, 0, 0, 0);
sst1CurrentBoard->mtrrWriteCombine = 0;
}
}
return retVal;
} // sst1InitSetCaching
/*
** sst1InitCachingAMD
**
** Sets up memory caching for AMD K6 and AMD K7 systems for the entire
** 16mb virtual address space of the card. For K7, goes through
** sst1InitCaching
**
*/
#define kCacheSizeWriteCombineAMD (0x08UL << 20UL) /* 8 MB */
#define kCacheSizeUncacheableAMD (0x20000UL) /* 128 KB */
FX_ENTRY FxBool FX_CSTYLE
sst1InitCachingAMD(FxU32* sstBase, FxBool enableP, FxBool hasP2MTRR)
{
FxBool retVal = sst1InitCheckBoard(sstBase);
if (!retVal) return FXFALSE;
/* The K7 has MTRRs that are exactly compatible to the P6/PII, so
we just do the work through the existing sst1InitCaching function
*/
if (hasP2MTRR) {
return sst1InitCaching(sstBase, enableP);
}
/* If it's not a K7, we must have a K6 with WC support, i.e. a K6-2 with
CXT core or a Sharptooth, otherwise we wouldn't have gotten here.
*/
if (enableP && (GETENV("SSTV2_IGNORE_CACHING") == NULL)) {
FxU32 physAddr;
/* Get the board's base. Isn't this the same as what we
* carry around in sst1CurrentBoard->physAddr[0]?
*/
pciGetConfigData(PCI_BASE_ADDRESS_0, sst1CurrentBoard->deviceNumber, &physAddr);
/* For some reason, there sometimes is a 008 at the end of the
* physical address, so mask that puppy RTF out
*/
physAddr &= 0xfffff000;
/* dpc - 23 jan 1998 - Warning!!!!!
* We are no longer mapping the entire board range as uswc because
* this causes weird problems on some systems. We are now mapping
* the 3d register area as uncacheable (since no one should be
* writing here anyway, except to bump the swapbufferCMD register)
* and the command fifo range and lfb range as uswc.
*
* NB: It is still unclear why this is happening because the
* memory page containing the registers is never really explicitly
* written to until we are shutting down so changing its caching
* characteristics should have no bearing on anything.
*
* This might no be necessary for K6, as K6 maintains strong write
* ordering in WC regions. We do this here compatible to PII just in
* case. Note: Overlapping WC and UC regions results in UC type on K6,
* just like on PII. Note: the smallest MTRR region size on K6 is 128 KB,
* while on PII it is 4 KB. We make the UC region as small as we can.
*/
/* For K6, we don't do any elaborate allocation, as it only has two
* variable size memory regions, and we need both for Voodoo2. So, we
* just jam the data into the two available MTRRs.
*/
pciSetMTRRAmdK6 (0, physAddr, kCacheSizeWriteCombineAMD, PciMemTypeWriteCombining);
pciSetMTRRAmdK6 (1, physAddr, kCacheSizeUncacheableAMD, PciMemTypeUncacheable);
} else { /* disable MTRRs */
/* This always succeeds */
retVal = FXTRUE;
/* Since AMD recommends a "free for all" policy for allocating MTRRs
on K6, we do nothing for "disable". Any software that wants to grab
the MTRRs can just do so. Leaving the MTRR enabled might actually
beneficial in a situation like the following: We run a D3D app, then
a Glide app, then a D3D app, but the second time around D3D doesn't
re-initialize, since it's still active, so it doesn't reprogram the
MTRRs.
*/
// pciSetMTRRAmdK6 (0, 0, 0, 0); /* size == 0 implies disable */
// pciSetMTRRAmdK6 (1, 0, 0, 0); /* size == 0 implies disable */
}
return retVal;
} // sst1InitSetCachingAMD
#ifdef __WIN32__
#pragma optimize ("",on)
#endif